Compose powerful analytics with Lychee using a no-code SQL builder: filter rows, compute metrics, group for charts, and join datasets for deep research.
SQL is the lingua franca of research and quantitative finance.
When you’re investigating market structure, validating signals, or stress-testing a strategy, you don’t just need charts—you need repeatable logic you can trust. SQL gives you that logic: filtering, transforming, aggregating, and combining datasets with the same rigor you’d expect from a trading model.
Lychee makes the same kinds of queries accessible as a no-code workflow. Instead of writing SQL, you select the columns, add filters, choose aggregations, and (where supported) apply join recipes—then run your query and load the result straight into your workspace.
SELECT, WHERE, DISTINCT, LIMIT, ORDER BY)Lychee can build row-level queries on your dataset by letting you:
WHERE filters that narrow the rows,ORDER BY,For DISTINCT, Lychee supports two related (but different) experiences:
COUNT(DISTINCT ...)): available in the Columns compose flow as the count distinct summarize option, and also in the Meta Table flow via the UNIQUE operator.SELECT DISTINCT ...): available in the grid toolbar as Remove duplicates (it deduplicates rows in your current sheet).SELECT "ticker", "volume"
FROM "trades"
WHERE "volume" > 100
ORDER BY "volume" DESC
LIMIT 1000
ticker and volume.volume>100IN / NOT IN to match categorical values from a list
(strings like "yes", "no"; numbers like 1, 2, 3)volume and direction descending.COUNT(), SUM(), and more)Lychee’s Columns/compose flow supports the most common aggregation primitives:
COUNT(...) (row counts per selected group)SUM(...) (sums per selected group)GROUP BY when you include aggregationsLychee’s compose flow also exposes:
AVG() (average)MIN() / MAX() (extremes)MEDIAN() (approx)STDDEV() / VARIANCE()COUNT(DISTINCT ...) via the count_distinct optionSELECT
"ticker",
COUNT("ticker") AS trades_count
FROM "trades"
WHERE "volume" > 100
GROUP BY "ticker"
ticker) and leave its summarize as “no total” / none.volume).Count (non-empty) / Sum numbers, orAverage, Min, Max, Median (approx), Stddev, Variance, Count distinctGROUP BY and HAVING)Lychee expresses grouping automatically:
SUM/COUNT, Lychee sets up the needed GROUP BY under the hood.HAVING (filtering aggregated results) is exposed as Having (filter aggregated results) in the Columns compose flow (when you have aggregates selected).
SELECT
"price_bucket",
COUNT(*)
FROM "trades"
WHERE "volume" > 100
GROUP BY "price_bucket"
HAVING COUNT(*) > 1000
>, <, =, !=)Lychee supports dataset joins via join recipes (not yet a free-form join editor). It also supports a sheet-level join across already-loaded sheets:
Supported join style today:
Free-form SQL join types are still limited in the compose builder; use Combine Sheets for cross-sheet joins.
SELECT
r."price_bucket",
SUM(CAST(t."count" AS DOUBLE)) AS contracts
FROM (
SELECT * FROM "trades"
-- join with resolved markets (preset logic)
) t
JOIN "resolved_markets" r
ON t."ticker" = r."ticker"
GROUP BY r."price_bucket"
Lychee supports calculated columns primarily through spreadsheet-style operations:
+, -, *, /) via the Σ (Sigma) Mathematics Operations tool in the grid toolbarGeneral conditional expression building (e.g. CASE WHEN ... THEN ... ELSE ... END) and boolean logic expressions are not yet exposed as a first-class expression builder in the current compose UI.
Workaround flow today:
SELECT
"count" * "price" / 100 AS "notional"
FROM "trades"
Multiply or Add etc.Lychee supports:
bucket by day/week/month/quarter/year)Engine-level binning functions like FLOOR(), ROUND(), and WIDTH_BUCKET() are used in internal presets (including Kalshi join recipes), but are not yet exposed as generic UI controls for arbitrary columns.
SELECT
DATE_TRUNC('quarter', "timestamp") AS "quarter",
COUNT(*) AS trades
FROM "trades"
GROUP BY 1
quarter / month / week / etc.Window functions (e.g. ROW_NUMBER(), RANK(), DENSE_RANK(), LAG() / LEAD(), SUM() OVER(), AVG() OVER(), NTILE()) are not exposed in the current compose UI.
If you tell us which window pattern you want first, we can add it in the same composable style as the rest of the SQL builder.
SELECT
"ticker",
"price",
LAG("price") OVER (PARTITION BY "ticker" ORDER BY "time") AS prev_price
FROM "trades"
Window functions are not yet exposed in the current compose UI.
What to do today:
CTEs / pipeline subqueries are not exposed yet as a first-class UI construct.
Lychee focuses on producing a single compose statement you can run and then refine through selection, aggregation, and post-processing.
WITH volumes AS (
SELECT "ticker", SUM("size") AS v
FROM "trades"
GROUP BY "ticker"
)
SELECT *
FROM volumes
WHERE v > 1000
CTEs/subqueries are not yet exposed as a first-class compose option.
What to do today:
UNION, INTERSECT, and EXCEPT are not exposed yet in the current UI builder.
SELECT "ticker" FROM "trades_2023"
UNION ALL
SELECT "ticker" FROM "trades_2024"
Set operations are not yet exposed as a UI builder.
What to do today:
Lychee supports date/time conversion and bucketing using the Date / time shape controls, so you can group and visualize time-series easily.
Common SQL date functions like EXTRACT(), CAST(), and INTERVAL are not yet exposed as separate UI controls. In practice, you’ll get most of what you need via the bucketing/text-shape options plus normal filtering and aggregation.
SELECT
DATE_TRUNC('day', "timestamp") AS day,
COUNT(*) AS trades
FROM "trades"
GROUP BY 1
ORDER BY day DESC
Lychee detects null/NaN-ish values during loading and shows a dialog letting you choose to:
A direct expression-builder experience for SQL null functions like COALESCE(), NULLIF(), IS NULL, and IS NOT NULL is not yet exposed as a compose option.
SELECT COALESCE("volume", 0) AS safe_volume
FROM "trades"
WHERE "volume" IS NOT NULL
Distinct counting is supported in two ways:
Count distinct (produces COUNT(DISTINCT ...) aggregated results)UNIQUE operator to dedupe values before countingSELECT COUNT(DISTINCT "ticker") AS unique_markets
FROM "trades"
Count distinctWhere (filter) predicatescount.Filter.ticker).Lychee is designed so we can extend the compose system incrementally—each new SQL capability fits into the same “select → filter → compose → run” workflow without turning it into a scripting experience.
If you want, tell me which two SQL constructs you want next (window functions vs CTEs vs UNIONs), and I’ll help map them into Lychee’s existing UI flow.
Learn how to stream real-time Polymarket market data using the WebSocket market channel and build live prediction market charts — no code required.
guidesLearn how to connect to Polymarket’s Events List endpoint, filter and analyze structured event data, and export datasets, from anywhere in the world — no code required.
guidesExplore our docs or reach out to our team.