You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This file records how the vision in strategy-vision.md maps onto the live GitHub board after the 2026-07-05 program restructure (epic #37), and what changed on 2026-07-06. The vision doc itself is unchanged; treat this as its tracking companion.
Status since the vision doc was written
Live foundation VALIDATED during market hours (2026-07-06): quotes, trades, 1m bars flowing and persisted with real timestamps (#23 market-hours pass; fixes #75, #77, #79).
Recorder professionalization program filed AND half-executed the same day (epic #80): internal bars merged (#64, closes #49), per-symbol quote/Greeks sampling + candle upsert + TimescaleDB compression merged (#88). Remaining lanes: policy doc #81, sampling cutovers, dynamic scanner universe #83, live Greeks #86.
DAG engine foundation merged: schema + canonical definition_hash (E-01), static validator (E-02 groundwork), op registry + indicator allowlist (E-03), versioned storage with migration 0007 (E-04). The interpreter MVP is #52.
Vision -> board map
Vision section
Board home
Two-layer split (builder vs deterministic engine)
Epic #37 north star; docs/nautilus/program-north-star.md
Runtime graph as one nautilus Strategy
#52 interpreter MVP (Phase E, epic #41)
Node library: TA indicators
#50 native indicators (Phase D)
Node library: candlestick/chart patterns
existing code (indicators/patterns.py, patterns/detector.py); wrapped during #52/#50
Node library: sentiment (index/sector/peer)
#96 (new, 2026-07-06): derived from recorded proxy-symbol bars, no external feed in v1
Node library: news buzzword scoring
#97 (new, 2026-07-06): offline AI scorer writes plain rows; runtime gate node is deterministic
performance gate added to #52 acceptance (comment, 2026-07-06)
skyway = builder only, never runtime
boundary restated in #98; unchanged
One policy interaction to know about
The replay promise ("a session traded live can be replayed bar-for-bar") holds for bar- and trade-driven nodes: those streams are recorded complete. Since 2026-07-06 (#88), QUOTES and GREEKS are sampled per symbol (default 1000ms) for volume control. A future DAG node consuming raw quote ticks requires flipping quote_sample_interval_ms for the affected symbols before its data is recorded, or accepting approximate replay. The recording-policy doc (#81) carries this as a revisit trigger.
Corrected tracking (the footer in strategy-vision.md predates the restructure)
#18 (strategy-DAG spike): CLOSED, absorbed into epic #37 / Phase E (#41: #51 #52 #53).
#21 (native indicators backlog): CLOSED, re-scoped into Phase D (#40: #49 shipped via PR #64, #50 open); portfolio_stats MCP tool shipped.
#19 (warm-up): CLOSED, shipped.
#15 (brackets/trailing via OrderEmulator): CLOSED, shipped.
OptionsChainLoader + live Greeks capture landing via #86; historical options via DoltHub (#73)
later phase, after #86
later
Gate order (from epic #37): #52 interpreter MVP with its performance gate is the choke point; every node category above waits on it, by design. The op registry and allowlist (E-03) plus the versioned spec store with definition_hash (E-04) are already merged, so adding a node category is registry + pure function + tests, not engine work.
Vision — A dynamic, AI-composed trading strategy engine
Status: the live trading node (NautilusTrader + Tastytrade + dxFeed) now connects, reconciles, and runs in sandbox. This doc is the forward architecture for how strategies themselves should work. Feedback very welcome — see the linked GitHub issues at the end.
TL;DR
A strategy becomes DATA — a declarative graph spec, not hardcoded Python.
An AI "builder" composes & evolves strategies at design/research time (creative, allowed to be non-deterministic).
A deterministic engine runs them on live realtime data and in backtest — identically, with no AI in the decision path.
The graph is assembled from a reusable library of nodes (indicators, candlestick/chart patterns, sentiment, news, sizing, entry/exit).
The whole point: instead of hand-coding N strategies, we build a node library once and let the builder compose a wide space of strategies — each a fixed, testable, reproducible artifact.
1. The two layers (the core idea)
The apparent contradiction — "as dynamic as possible" and "no AI in the strategy" and "must backtest identically" — dissolves once you split build time from run time.
flowchart LR
subgraph BUILD["BUILD TIME -- AI builder (creative, non-deterministic, offline)"]
direction TB
perf["Past performance / regime / market structure"] --> builder
lib["Node library"] --> builder
builder["AI builder<br/>(skyway .sky nightly workflow)<br/>'understands how to build a strategy'"]
builder --> spec[["Strategy graph spec<br/>(DATA, not code)"]]
end
subgraph RUN["RUN TIME -- Deterministic engine (NO AI)"]
direction TB
spec --> engine["Compute-DAG runtime<br/>(a nautilus Strategy)"]
engine --> intents["Order intents"]
end
intents --> results["Fills / PnL"]
results -. "fitness signal" .-> builder
Loading
Build time is where creativity lives: an AI reads the node library + recent performance and authors or edits a strategy graph. Non-determinism is fine here — it produces an artifact, then stops.
Run time is pure and deterministic: the engine loads the graph (data) and executes it. No LLM, no wall-clock, no un-seeded randomness — so the same event stream always yields the same decisions.
Key enabler — strategy-as-data: because a strategy is a graph definition, an AI can author/evolve it and an engine can run it deterministically. That single choice unlocks everything else.
2. The runtime strategy graph (streaming dataflow)
At run time the strategy is a stateful streaming operator graph: realtime data arrives on the message bus, propagates incrementally through nodes, and the terminal nodes emit order intents. It is reactive, not batch — a node fires when its inputs tick.
flowchart LR
subgraph DATA["Realtime data on the bus (multi-rate)"]
ticks["Quote / Trade ticks (fast)"]
bars["1m / 5m bars"]
greeks["Option greeks"]
sent["Sentiment: index / sector / peer (slow)"]
news["News buzzwords (slow)"]
end
ticks --> ind["Indicator nodes<br/>vwap, rsi, macd, atr, delta, rel-strength"]
bars --> ind
bars --> pat["Pattern nodes<br/>candlestick + chart patterns"]
greeks --> ind
ind --> sig["Signal node<br/>multi-timeframe alignment + score"]
pat --> sig
sig --> filt["Filter / gate nodes"]
sent --> filt
news --> filt
filt --> size["Sizing / risk node"]
size --> entry["Entry subgraph -> entry intent"]
size --> exitn["Exit / position-mgmt subgraph -> exit intent"]
entry --> out(["Order intents"])
exitn --> out
A nautilus Strategy runs unchanged in both the live TradingNode and the BacktestEngine — both drive it through the sameon_bar / on_tick handlers. The strategy is agnostic to where data comes from.
flowchart TB
subgraph LIVE["Live"]
feed["DxFeed / Tastytrade feed"] --> nodeL["nautilus TradingNode"]
end
subgraph BACKTEST["Backtest"]
cat["Parquet catalog replay (history)"] --> nodeB["nautilus BacktestEngine"]
end
nodeL --> strat
nodeB --> strat
strat["THE SAME strategy graph<br/>(same handlers, deterministic nodes)"]
strat --> same["Identical outputs for an identical event sequence"]
Loading
Because live ticks/bars are also persisted to the catalog, a session traded live can be replayed bar-for-bar through the very same graph — same-day validation and full reproducibility.
5. What does a strategy output?
An order intent — not a percentage. Three things kept distinct:
Thing
What it is
Who consumes it
Runtime output (per event)
enter/exit/size/stop intent, or no-op
nautilus exec engine
Win-rate / Sharpe / valid-invalid
evaluation metrics, computed after trades resolve
the AI builder (fitness signal)
Order placement / closing
submit/cancel/OCO/trailing/reconcile
nautilus (deterministic)
You do not need a separate DAG for placing/closing orders. Order execution is already nautilus's deterministic job (ExecEngine, RiskEngine pre-trade caps, OrderEmulator for brackets/trailing, reconciliation). The strategy graph's leaf nodes are the entry/exit intent nodes; nautilus executes those intents.
Nightly (skyway .sky workflow): pull yesterday's fills → analyze regime/PnL → propose a new/edited graph → backtest it → if it beats the incumbent, open a PR to promote it. The candidate then runs deterministically on live data, and its results feed back to the builder.
7. Why not just run strategies on skyway directly?
skyway's .sky DAG is an LLM-agent orchestration graph — each node shells out to an AI model (seconds-to-minutes, non-deterministic, costs money, not reproducible). That's perfect for the builder (offline, creative) and a category error for a per-bar decision on a real-money account.
So we borrow skyway's grammar idea (nodes + dependencies + guards) for the runtime graph, and use skyway's actual runtime one layer up — to evolve strategies, not to run them.
Build-time builder (skyway)
Run-time engine (this)
Driver
AI / LLM
deterministic code
Latency
minutes
sub-millisecond
Reproducible
no (creative)
yes (required)
In the order path
never
yes
8. Where we are today
The live foundation works (sandbox, dry-run): the node connects DxFeed + Tastytrade, reconciles the account, starts the strategy, and subscribes quotes/trades/1m-bars/greeks. The current momentum/swing strategies are already nautilus Strategy subclasses (they run in both engines) — the spike just makes the implicit pipeline an explicit, declarative graph while keeping that property.
First step of the spike (not a big-bang migration): define the node interface + graph-spec format, then a 2-3 node prototype wired declaratively that runs in both a backtest and a synthetic live feed with identical outputs.