FD FlowDesk

Tape Transformer — research

A real multi-layer, multi-head transformer, trained on the actual tape values over time (not the bucketed calibration on /calibrate) to forecast the expected forward move. This is an experiment, kept fully separate from live Top Pick ranking — nothing here ever affects a real trading decision.

Model status

Trained steps
10,730
Train loss
0.002071
Validation loss
0.001910
never trained on — the real generalization check
Checkpoint
Restored from DB
Best validation loss
0.001751 (step 8,241)
forecasts and rankings use THIS snapshot, not necessarily the live training weights above — see /api/tape_transformer_export.php's docblock
Training examples
292
Validation examples
38
Examples seen (cumulative)
10,730

Architecture: d_model=16, heads=4, layers=2, feedforward=64, sequence length=6 points, forecast horizon=2 days. Features per point (30 total, each roughly scaled to a similar band): composite, money-flow skew, log return from the previous point, confidence, quality, stable_composite, a log-scaled call+put volume magnitude, cross-sectional composite z-score vs the tracked universe that day, that day's real VIX, days-to-next-earnings, a mask for confidence/quality/stable_composite being real vs. defaulted, a sector-relative composite z-score vs. the symbol's own real peers, an options-chain wall skew (where the chain's heaviest real open interest sits relative to spot), a sector-peer composite LAGGED 2 days back — a lower-risk stand-in for full cross-symbol lead-lag attention (see SD_TT_NUM_FEATURES's own docblock for why), that day's real market-wide breadth (advancers ÷ advancers+decliners, centered so an even split reads as neutral) — a different signal than VIX: VIX says how much fear exists, breadth says how BROAD a move is — and this symbol's own real institutional-interest history (a blend of real SEC Form-4 insider buy/sell activity and real analyst street consensus, centered the same way breadth is), read from a day-collapsed history table kept specifically to avoid leaking today's value onto past training examples — a different signal than money-flow skew above: skew is same-day options-tape positioning, this is real-world insider/analyst conviction — and this symbol's own realized volatility (the stdev of its real per-point returns within the same window, capped at a 5%+ stdev reading as maximally volatile), the one feature here that needs no external table or query at all since it's derived purely from spot values already in the window, directly answering how CHOPPY this specific name's own recent price action has actually been — this symbol's own real beta and log-scaled market cap (real Finnhub metrics, read from the same kind of day-collapsed history table as institutional-interest, for the same look-ahead-bias reason), a systematic-risk multiplier and a direct size signal nothing else here carries — momentum (cumulative log return from the window's own first point to each point, distinct from the single-step return above, and needing no new data at all) — and return skew (the third moment of the same real returns realized volatility already accumulates, saying whether this name's real moves lean toward sharp drops or sharp rallies, not just how big they are). Beyond the per-point features above, the model also runs real cross-symbol attention: up to 1 real same-sector peer, resolved and windowed the same point-in-time-correct way as every other context feature, is encoded through the SAME weight-shared self-attention stack as the symbol itself, then a single cross-attention block lets the symbol's own pooled representation attend to that real peer before the forecast head — replacing a guess at what a related name is doing with the peer's own real, contemporaneous tape data, deliberately bounded to one peer and one head to keep the added parameters small relative to this model's still-modest real training set. confidence/quality/stable_composite are real tape_history columns already populated by the regular cron — not new data collection, just not previously read by this pipeline; a row from before those columns existed defaults to 0 rather than a guessed value. 15% of examples are held out for validation (never trained on), chosen deterministically per symbol+timestamp so the same example never switches sides between chunks. Training now scans the FULL 180-day window across every tracked symbol before capping — earlier versions of this pipeline stopped early and were biased toward whichever symbols sorted first alphabetically. Trained with plain SGD (learning rate 0.01) plus a small L2 weight decay (0.0001) on every step — a standard defense against overfitting on a real dataset still this small; see the train/validation loss gap above for whether it's actually holding.

Sign in as an admin to train this model further.

Training loss curve

trainvalidation
step 556 — loss 0.01597step 10730 — loss 0.00207

Headline language model

A separate, real, character-level model trained on real stock headline text (see api/lib/language_model_lib.php) — its own scalar read on a headline feeds the transformer above as one point-in-time-safe feature, but it is never called live during scoring and never affects a trading decision on its own. Unlike the transformer above, this model has no manual "train more" button — it trains automatically once a day via cron.php's own gate as real headline text accumulates, so this panel is its only status view. A different, genuinely generative proof-of-concept model (real text OUT, not just a score) lives at Language Playground — fully separate, manually trained, built for a future chatbot project.

Trained steps
27
Train loss
0.004811
Validation loss
0.000633
never trained on — the real generalization check
Checkpoint
Restored from DB
Best validation loss
0.000633 (step 27)
lm_read_history is scored from THIS snapshot, not necessarily the live training weights above
Real headlines in window
881
stock_news, last 180 days — the model's only real source of training text
Headlines scored so far
100
lm_read_history rows — what the transformer above can actually read
Last cron training attempt
2026-08-29 14:08
gated to at most once/day, whether or not real examples were found that day

Check back after a couple of training chunks — the loss curve needs at least two points to plot.

Transformer-only basket — forward-tracked, vs. Top Pick

The real test of "should this model's own judgment replace the existing gate/bucket system": once per day (not every cron tick — a real portfolio doesn't rebalance every few minutes), the model ranks the WHOLE tracked universe purely by its own forecast — no VerdictLib usable+bullish gate, no confidence/quality threshold — and the top 10 POSITIVE forecasts become this basket. On a day where the model's own top picks come back net negative, this can hold fewer than 10 (or none) — it sits out rather than forcing a fixed count of "long" entries into names it itself expects to fall. Real entries at real prices, measured going forward from the moment each position opens — never a fabricated backtest, same discipline as Top Pick's own ledger.

Transformer basket avg return
+1.09%
29 positions tracked
Transformer win rate
31%
Top Pick avg return (for comparison)
-0.12%
Top Pick win rate (for comparison)
28%

Tracked since 2026-08-27. Not an apples-to-apples backtest yet on a short sample — different rebalance cadence (daily vs. Top Pick's continuous), different universe (unfiltered vs. gated), and both numbers need real sample size before either is trustworthy. This is the evidence being built, not a conclusion yet.

Win/loss asymmetry

A low win rate can still mean a profitable basket if winners run bigger than losers — this splits the one net avg return above into what each side actually averaged.

Avg win
+6.34%
9 winning positions
Avg loss
-2.54%
10 losing positions
Win/loss ratio
2.50x
avg win ÷ avg loss magnitude

Sector concentration — currently held

This basket has no sector/theme gate either — the model ranks each symbol on its own forecast, so two names that move on the same underlying driver (two bitcoin miners, two regional banks) can both rank highly and land in the basket as if they were independent bets. Report only: this never reorders or caps the basket, it just shows what's actually concentrated right now.

SectorHeldSymbols
Technology concentrated2MSFT, QNT
Automobiles concentrated2GGR, NIU
Health Care concentrated2MYO, SKYA
Electrical Equipment concentrated2NPWR, NEOV
Media1DIS
Real Estate1RMAX
SymbolEnteredForecast at entryReturnStatus
MSFT2026-08-29+0.73%+0.00%open
QNT2026-08-29+0.74%+0.00%open
DIS2026-08-29+1.01%+0.00%open
GGR2026-08-29+1.14%+0.00%open
NIU2026-08-29+2.14%+0.00%open
MYO2026-08-29+2.21%+0.00%open
RMAX2026-08-29+2.45%+0.00%open
NPWR2026-08-29+2.75%+0.00%open
NEOV2026-08-29+2.77%+0.00%open
SKYA2026-08-29+4.74%+0.00%open
COP2026-08-28+3.73%+0.64%closed
CAT2026-08-28+3.00%-2.05%closed
LIN2026-08-28+2.39%+0.86%closed
CCL2026-08-28+2.15%-0.76%closed
MDT2026-08-28+1.35%+1.40%closed
IWM2026-08-28+1.29%-1.35%closed
STRL2026-08-28+1.25%-7.08%closed
GE2026-08-28+1.23%-0.04%closed
FCEL2026-08-28+1.47%-8.07%closed
HPQ2026-08-27+7.24%-2.92%closed

Current model vs. held basket

The basket above only resyncs once a day, on purpose — training can keep improving the model in between without the held basket changing at all. This runs the CURRENT best snapshot's ranking right now, live, and compares it against what's actually held — a read-only preview, it does not change the real basket. Basket last actually resynced 2026-08-29 08:02.

Preview current ranking

The model's own calibration

Bins every CLOSED transformer-basket position by its own forecast_return_pct at entry and reports what actually happened — the same evidence-based discipline as the conviction bands on /auto-trade, applied to this model's own predictions instead of the composite/confidence/quality inputs. A well-calibrated forecaster's avg return should roughly track each band's own midpoint (a "predicted +2%" band actually returning near +2%); a flat or inverted band is honest evidence the model isn't there yet, not something to hide.

Forecast at entryClosed positionsWin rateReal avg returnSample
+1% to +2%520.0%-3.03%too few
+2% to +3%333.3%-0.65%too few
+3% to +4%1100.0%+0.64%too few
+4% to +5%366.7%+0.28%too few
+5% to +6%333.3%-0.26%too few
+6% to +7%3100.0%+16.98%too few
+7% to +8%10.0%-2.92%too few

Calibration by liquidity

This basket deliberately has no confidence/quality/liquidity gate — it ranks purely by forecast, and a thin, low-volume name can rank just as high as a liquid mega-cap. This checks whether that's actually costing anything: does the model's real calibration hold up as well on illiquid names as it does on liquid ones, or does forecast accuracy fall apart on thin tape? Same tiers and same evidence-based discipline as the liquidity calibration on /auto-trade — report only, this never adds a threshold to the basket itself.

No closed transformer-basket positions with a recorded volume snapshot yet — this fills in as the daily-tracked basket closes positions.

Forecast vs. reality

Same evidence as the bands above, as a picture instead of a table: one point per closed position, forecast on the X axis, what actually happened on the Y axis. A point ON the dashed diagonal means that forecast came true exactly; points scattered off it — especially systematically above (underforecasting) or below (overforecasting) — are the real calibration gap, at a glance rather than five separate band numbers.

Forecast → outcome correlation
0.49
19 closed positions — 0 = no relationship, 1.0 = forecast perfectly tracked the real outcome, negative = forecast and outcome moved opposite ways

Forecast a symbol

Runs the current model's forward pass on a symbol's most recent 6 real tape_history points. Withheld (not guessed) if the model has never been trained, or there isn't enough real history yet.