Skip to content

Complete alpha-101 demo — 10 alphas, catalog stream, consolidated dashboards#29

Merged
gangtao merged 5 commits into
mainfrom
feature/27-alpha-101-more-alphas
May 21, 2026
Merged

Complete alpha-101 demo — 10 alphas, catalog stream, consolidated dashboards#29
gangtao merged 5 commits into
mainfrom
feature/27-alpha-101-more-alphas

Conversation

@gangtao
Copy link
Copy Markdown
Contributor

@gangtao gangtao commented May 21, 2026

Closes #27.

Summary

Completes the alpha-101 demo with 10 WorldQuant 101 alphas, a catalog mutable stream describing each one, and two consolidated dashboards (Live + Backtest) with an Alpha dropdown that switches between all 10 signals.

What ships

1. Ten alphas — one per streaming-SQL pattern

# Streaming-SQL pattern showcased
1 lags window + signed_power + array_first_index for ts_argmax + cross-sectional rank via group_array + array_sort + ARRAY JOIN array_enumerate
2 Cross-sectional rank of two derived features per bucket → per-stock 6-bucket Pearson correlation
3 Same pattern as #2 but with raw OHLC inputs and a 10-bucket window
4 Time-series rank within a rolling windowarray_count(x -> x <= current, lags(_, 0, 8))
6 Raw-value rolling Pearson correlation (no rank step)
9 Rolling min/max via array_min/array_max over lags(_, 0, 4) + multi_if nested conditionals
12 Minimal alpha — single-step deltas via lags(_, 1, 1), sign, multiplication; tiny SQL footprint
22 Chained derived series: rolling correlation → delta of correlation × cross-sectional rank of rolling stddev
41 VWAP derivation in v_bars (sum(price*volume) / sum(volume)) + intra-bar nonlinear
54 Pure intra-bar nonlinear OHLC — no lags, no aggregation, all instantaneous

2. Shared pipeline

random_market_data  →  mv_market_data  →  market_data  →  v_bars
                                                    (time, stock_id,
                                                     open, close, high, low,
                                                     volume, vwap)

Each alpha branch:

v_bars
  →  v_features_alpha_N    (per-stock features + close-to-close returns)
  →  [v_ranks_alpha_N]     (optional: cross-sectional ranks per bucket)
  →  v_alpha_N             (the signal itself)
  →  v_backtest_alpha_N    (pairs lag(alpha) × returns, branched on `strategy`)

Simpler alphas (#12, #41, #54) skip the features and ranks layers.

3. alpha_catalog mutable stream

CREATE MUTABLE STREAM alpha_catalog (
  alpha_name  string,    -- PK
  description string,
  equation    string
) PRIMARY KEY alpha_name

Install-time seed via a single INSERT INTO ... VALUES (…) (registered as type: system in the manifest). After install, SELECT * FROM alpha_101.alpha_catalog returns one row per alpha with its name, short description, and original WorldQuant formula. Mutable-stream semantics mean re-inserting on the same alpha_name upserts in place — the catalog is editable without rebuilding.

4. Consolidated dashboards

Two dashboards, each with an Alpha dropdown (1, 2, 3, 4, 6, 9, 12, 22, 41, 54) that templates the suffix into panel queries — FROM alpha_101.v_alpha_{{filter_alpha}} resolves at render time:

Realtime Alpha 101 (6 panels)

  • Stock + Alpha dropdowns
  • Selected Alpha — markdown panel reading from alpha_catalog, shows the description and equation of the chosen alpha
  • Live Prices + Live Volume (side-by-side, filtered by Stock dropdown)
  • Alpha Leaderboard (latest, all stocks)
  • Alpha Over Time (multi-stock line)

Alpha 101 Backtest (6 panels)

  • Alpha dropdown
  • t-stat tile + summary table
  • PnL by Stock + Portfolio PnL per 30s
  • Per-Stock PnL Over Time

Adding Alpha #N from here: a new DDL chain (v_features_alpha_N → … → v_backtest_alpha_N), append ,N to each dropdown's inlineValues, and INSERT a row into the catalog. No new dashboard files.

5. Naming convention

shared (unsuffixed):        per-alpha (suffixed):
random_market_data          v_features_alpha_N
market_data                 v_ts_argmax_5_alpha_1   (alpha-1 only)
mv_market_data              v_ranks_alpha_N         (where used)
v_bars                      v_alpha_N
                            v_backtest_alpha_N
alpha_catalog               (alpha-name keyed)

6. Synthetic-data caveat (documented in README)

Alphas operating on raw price levels (#3 rank(open), #4 rank(low), #6 correlation(open, …)) are degenerate on this synthetic feed because per-stock price bands never overlap — STOCK_0's low is always lowest, STOCK_2's is always highest, so cross-sectional ranks of price levels are constants. The math is correct, the alphas are honest about having no information to extract. Alphas operating on returns, deltas, or intra-bar quantities (#1, #2, #9, #12, #22, #41, #54) produce meaningful varying signals.

7. Bundled skill / docs improvements

skill/SKILL.md Common Errors gained four entries during this PR:

  1. Multi-series line/area charts need color set
  2. Dashboard WHERE filters must use time (not _tp_time) on tumble-derived views
  3. YAML # truncates unquoted strings in manifest values
  4. nullif is rejected; use null_if
  5. Sprig templates in dashboard JSON get flattened to literals when re-saved via the UI

Verified end-to-end

Check Result
.tpapp install ✓ 37 DDL resources + 2 dashboards register
All 10 alphas emit ✓ verified live
All 10 backtests emit pnl ✓ verified live
alpha_catalog populated on install ✓ 10 rows queryable via SELECT * FROM alpha_catalog
Markdown panel renders catalog row for selected alpha ✓ Alpha dropdown drives WHERE alpha_name = 'alpha_{{filter_alpha}}'
Sprig stock-selector template auto-scales ✓ install with config[num_stocks]=5STOCK_0..STOCK_4
Dashboard Alpha dropdown switches all panels ✓ leaderboard + over-time + t-stat + summary + PnL all update

Test plan

  • make build && make install with default config
  • make install with config[num_stocks]=5 config[bucket]=5s config[strategy]=sign
  • SELECT alpha_name, description, equation FROM alpha_101.alpha_catalog returns all 10 rows
  • Reviewer: on the Realtime Alpha 101 dashboard, cycle through all 10 Alpha values — the markdown banner updates with each alpha's description + formula; the leaderboard and over-time panels update accordingly
  • Reviewer: switch Stock dropdown — Live Prices + Live Volume update
  • Reviewer: on the Alpha 101 Backtest dashboard, cycle through alphas — t-stat tile, summary, per-stock PnL, portfolio PnL all update

🤖 Generated with Claude Code

Closes #27.

Extends the existing alpha-101 app to also implement WorldQuant
Alpha #2:

    -1 * correlation(rank(delta(log(volume), 2)),
                     rank((close - open) / open),
                     6)

Shared pipeline changes (affecting Alpha #1 too, verified non-breaking):

- random_market_data gains a `volume` field (uniform [1, 100] per tick).
- market_data + mv_market_data plumb volume through.
- v_bars now exposes `open` (earliest price in bucket), `close`
  (latest price), and `volume` (sum of tick volumes). Alpha #1's
  downstream chain works unchanged.

New views for Alpha #2:

- v_features_2: per-stock per-bucket intraday_ret = (close - open) / open,
  log_vol_delta_2 = log(volume_t) - log(volume_{t-2}), and bucket-to-bucket
  returns (plumbed for the backtest).
- v_ranks_2: per-bucket cross-sectional rank of BOTH features (using the
  same mean-zero rank pattern as Alpha #1, computed once per bucket via
  group_array + array_sort + array_first_index for each feature).
- v_alpha_2: per-stock 6-bucket rolling Pearson correlation between the
  two rank series, negated. Manual covariance / variance computation via
  array_reduce('avg', array_map(...)) over lags(_, 0, 5).
- v_backtest_2: same shape as v_backtest, branched on `strategy` config
  (linear | sign).

Two new dashboards:

- "Alpha #2 Live" (volume per bucket, leaderboard, alpha over time)
- "Alpha #2 Backtest" (t-stat tile, summary, per-stock, portfolio PnL)

End-to-end live-verified: install of the rebuilt .tpapp produces both
alphas; v_alpha_2 values bounded in [-1, 1]; v_backtest_2 emits
sensible pnl on each (time, stock) row.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@gangtao gangtao linked an issue May 21, 2026 that may be closed by this pull request
gangtao and others added 4 commits May 20, 2026 18:53
…ources

Rename so alpha-specific views are clearly tagged and shared
pipeline pieces stay unsuffixed:

  v_features        →  v_features_alpha_1
  v_ts_argmax_5     →  v_ts_argmax_5_alpha_1
  v_backtest        →  v_backtest_alpha_1
  v_features_2      →  v_features_alpha_2
  v_ranks_2         →  v_ranks_alpha_2
  v_backtest_2      →  v_backtest_alpha_2

Unchanged (shared or already-suffixed):

  random_market_data, market_data, mv_market_data, v_bars,
  v_alpha_1, v_alpha_2

DDL filenames updated to match the view names. All cross-references
(FROM clauses, manifest resource list, dashboard viz_content) updated
to the new names. Verified end-to-end with a fresh .tpapp install:
9 views provisioned with the expected names, both alphas emit valid
values, both backtest layers emit pnl.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
With consistent _alpha_N naming, the dashboard SQL can template the
alpha suffix at runtime. Each dashboard now has a single "Alpha"
dropdown (values: 1, 2) writing to `filter_alpha`, and the panel
queries reference views as `alpha_101.v_alpha_{{filter_alpha}}` and
`alpha_101.v_backtest_alpha_{{filter_alpha}}`.

Before: 4 dashboards (Realtime Alpha 101, Alpha #1 Backtest, Alpha #2
Live, Alpha #2 Backtest).
After: 2 dashboards (Realtime Alpha 101, Alpha 101 Backtest), each
serving both alphas via the dropdown.

The Realtime dashboard also shows price AND volume side-by-side
(both filtered by the stock dropdown), since those are shared
market-data views that don't change between alphas.

Adding Alpha #N now requires only:
- a new DDL chain (v_features_alpha_N, ..., v_backtest_alpha_N)
- appending "N" to the Alpha dropdown's inlineValues

No new dashboard files. Verified end-to-end: 2 dashboards register
with 6 panels each; switching the Alpha dropdown updates the
leaderboard / alpha-over-time / all backtest panels in place.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The Timeplus dashboard UI persisted the rendered value of the
inlineValues template (literal "STOCK_0,STOCK_1,STOCK_2") instead
of the template itself, which broke auto-scaling to non-default
num_stocks. Restore the original:

  "[[ range $i, $_ := until (int .Config.num_stocks) ]]
       [[ if $i ]],[[ end ]]STOCK_[[ $i ]][[ end ]]"

Verified by installing with config[num_stocks]=5 — the rendered
inlineValues correctly resolves to STOCK_0,STOCK_1,STOCK_2,STOCK_3,STOCK_4.

UI-side improvements kept as-is (these are real fixes, not noise):
- Live Volume + Portfolio PnL column charts: updateMode/Key changed
  from "time" to "all" (cleaner streaming render for column charts).
- Alpha selector in backtest dashboard: position shifted from x=0
  to x=2 (layout polish).

Also save the broader gotcha to the skill: dashboard UI edits can
silently render-and-persist template expressions, replacing the
authored template with its evaluated string.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When a Timeplus user opens a dashboard installed from a .tpapp via
the UI and re-saves a layout tweak, any [[ ]] Sprig expressions in
the JSON (e.g. an inlineValues template referencing .Config.*) get
replaced by their rendered string. Auto-scaling behavior breaks
silently on next install with a different config. Hit this on the
alpha-101 stock selector after the user moved a panel.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@gangtao gangtao changed the title Add Alpha #2 (volume-return correlation reversal) to alpha-101 Alpha #2 + naming refactor + merged dashboards May 21, 2026
@gangtao gangtao merged commit 1ab50b7 into main May 21, 2026
@gangtao gangtao changed the title Alpha #2 + naming refactor + merged dashboards Complete alpha-101 demo with 10 WorldQuant alphas May 21, 2026
@gangtao gangtao changed the title Complete alpha-101 demo with 10 WorldQuant alphas Complete alpha-101 demo — 10 alphas, catalog stream, consolidated dashboards May 21, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

alpha-101 : more alphas

1 participant