Why write this?
The DailyTickers scanner publishes 10 A+ setups every trading night. Behind those setups sits a fully deterministic pipeline — every step is reproducible, every number is derived from the same primary JSON sources, and every trade is tracked until it hits TP1, TP2, its stop, or expires. This article opens that box so you can audit, replicate, or fork it.
We are keeping the pipeline honest by exposing it here publicly — and by re-running a battery of agents after every maintenance session to catch drift. This write-up doubles as a regression test: if any step below breaks, the article will stop matching the live endpoints and the drift will be obvious.
The pipeline, end-to-end
Six deterministic steps run each trading evening. The orchestrator is tools/publish-daily-card.sh.
1 · Scan generation
Claude produces the scanner HTML at scanner/YYYYMMDD/index.html — 10 A+ setups
ranked by a composite score (technical, fundamental, sentiment, R/R) with a mandatory
id="synthese" summary table. Strategies are limited to Momentum / Breakout /
Pullback / Pre-Squeeze. Anti-dilution and anti-doublon filters are bloquant.
2 · Live price tracking — tools/update-tracking.js
Parses the last 35 days of scan HTMLs using the shared library
tools/lib/scanner-parser.js, pulls current Yahoo Finance prices,
and writes data/scanner-positions.json (open positions) and
data/scanner-metrics.json (aggregate stats). A position is
classified as open, tp1, tp2, sl, or expired in a single pass.
3 · Backtest grid search — tools/sweep.js
A walk-forward backtest iterates ~98k parameter combinations (portfolio size,
top-N, minScore, horizon, rotation, strategy filter, TP/trailing) against the
full scan history. It writes the frozen equity curve per mode into
data/backtest-results.json and the per-trade ledger into
data/backtest-trades.json.
4 · Mode allocation — tools/gen-status-page.js
Builds the snapshot per mode. Applies signalsFor(cfg) (strategy filter +
minScore + topN) and posFor(cfg, trades) (pending backtest trades capped
at portfolioSize). Each mode is an independent alternative strategy —
the same ticker legitimately showing up across modes is treated as a confirmation
signal, not a duplicate.
5 · Public endpoints — tools/gen-api.js
Reads the latest snapshot and writes 33 JSON endpoints under
portfolio/v1/ — signals, positions,
trades, equity, orders,
actions, all, winning-streaks per mode,
plus root aliases pointing to balanced for backward compat.
6 · Publish + notify
Commit, push, and fire a Telegram notification via
tools/telegram-publish-notify.js. Topic 72 for scanner, topic 73 for
the daily briefing, topic 75 for stock analyses.
The five modes, side by side
Every signal produced by the scanner is routed through five parallel mode configurations. Each mode has a different risk profile, slot count, and strategy filter — optimized by the sweep grid search (13M+ combinations) to hit a specific objective.
| Mode | Slots | Alloc | Horizon | Filter | Return | Max DD | Win Rate | PF |
|---|---|---|---|---|---|---|---|---|
| ● Turbo | 1 | 100% | 2d | all | +59.18% | −2.59% | 52.2% | 13.56x |
| ● Dynamic | 1 | 100% | 2d | all | +52.69% | −3% | 53.8% | 8x |
| ● Balanced | 3 | 33% | 2d | mom_bo | +33.33% | −6.27% | 44.4% | 1.99x |
| ● Secured | 2 | 50% | 2d | breakout_only | +20.67% | −4.26% | 56.3% | 2.93x |
| ● Fortress | 4 | 13% | 8d | mom_bo | +11.85% | −1.32% | 57.5% | 2.78x |
How the 5 modes differ (updated 2026-04-25, config v3)
Turbo uses all filter, partial TP at TP1 (sell 50%, trail the rest),
and aggressive breakeven lock at +0.5% — producing 52.2% WR with a PF of 13.56x.
Balanced uses mom_bo (momentum + breakout), Secured uses breakout_only.
Fortress uses the same filter as Balanced but with positionSizePct = 0.5 — half-sized
positions that mechanically halve the drawdown.
A position's lifecycle
Each open position transitions through a deterministic state machine. The update runs once per trading day after the close. No manual intervention required.
Entry
Parsed from the synthese row: ticker, strategy, entry midpoint, stop, TP1, TP2, horizon (default 20 biz days). Written to scanner-positions.json.
Live classification
Each night update-tracking.js fetches the Yahoo regular market price and compares it against stop / TP1 / TP2 / expire. State: open, tp1, tp2, sl, expired.
Exit
The first triggered level wins (stop → TP2 → TP1 → expired). Exit price, exit date, and pnl_pct are frozen on that pass and the position drops out of open_positions.
Live display
On the scanner page, assets/live-tracker.js injects a live badge onto each setup card (Entry zone, Trending, Near stop, Stopped, TP1 Hit, TP2 Hit) with a classification refreshed every 30 seconds.
What this unlocks
- Every trade in the live ledger has a traceable origin (scan date + rank).
- The same parser drives the backtest and the live tracker — no divergence between sim and prod.
- The five modes are alternative strategies: a ticker in all five is a confirmation signal, not a hidden risk.
Public endpoints — consume the pipeline yourself
Every signal, position, trade and equity value is exposed under
https://articles.dailytickers.com/portfolio/v1/. No auth, CORS open,
JSON. The same layout under each mode prefix:
# Fetch the live balanced signals curl -s https://articles.dailytickers.com/portfolio/v1/balanced/signals.json | jq . # Winning-streaks snapshot per mode (new — April 11, 2026) curl -s https://articles.dailytickers.com/portfolio/v1/secured/winning-streaks.json # { # "currentStreak": 0, "bestStreak": 9, # "totalWins": 43, "totalLosses": 34, "winRate": 55.8 # } # Full state in a single request (orders, positions, trades, equity curve) curl -s https://articles.dailytickers.com/portfolio/v1/balanced/all.json \ | jq '{stats, positions: (.positions|length), signals: (.signals|length)}'
You can also explore the full schema interactively at
/portfolio/v1/docs/ (new Swagger UI —
April 2026). Drop into the Try it out panel to hit live endpoints without
leaving the browser. The OpenAPI 3.0 spec is also downloadable at
openapi.yaml.
Quality controls
After every pipeline change, we re-run a validation suite that checks:
- Parser sanity — the shared
scanner-parser.jslib is tested against the last 35 scan HTMLs. Any structural drift in the synthese table is caught immediately. - Mode cap invariants — no mode can show more positions than
cfg.portfolioSize(Secured was previously leaking 17 positions when the limit is 10 — fixed 2026-04-11). - Endpoint availability — each of the 33 public endpoints is JSON-valid and contains at minimum the expected top-level keys.
- Mode independence — each mode (Dynamic, Balanced, Secured) is evaluated as a standalone strategy. A ticker showing up in multiple modes is a confirmation signal, not duplication.
- Signal parity —
signals.jsoncannot be empty unless the scanner actually has no A+ pick that matches the mode filter (a known-empty state is documented, a surprise-empty state is a bug).
Three fixes landed in this session
- Shared parser library (
tools/lib/scanner-parser.js) replaces three divergent copies of the synthese regex. - Secured mode can no longer display more positions than its 10-slot allocation.
- Signals surface correctly even when the scan dir is an empty placeholder — the pipeline now picks the most recent non-empty scanner HTML.
Disclaimer
This is not financial advice. The metrics and setups shown here come from an internal backtest + live tracker. Past performance does not guarantee future results. The API is provided as-is, without warranty. Always do your own due diligence.