Cómo está construido
ADR-0011: T0 Lang 0.2 — strict mode, named books, market signals, and the handler model
Estas páginas están en inglés. Una especificación en un solo idioma dice una sola cosa.
Status: decisions 1–4 accepted and implemented (2026-10-18); decision 5 (handlers) accepted as a design, not implemented.
Context#
Strategies had grown past what 0.1 could say: partial closes and pyramiding, several positions on one symbol, state a rule remembers, what to do when an order is turned away, and signals from the footprint, the funding, the open interest, the liquidations and the book. The user asked for a language able to write very complex order-flow strategies, ready for production, without breaking any 0.1 program and without letting a strategy see the future.
Decision#
- Versions side by side. 0.2.0 sits next to 0.1.2. A program is compiled as the newest supported version its
langrange allows; a 0.1 program is unchanged and a 0.2 construct in it isE-VER-FEATURE. The artifact records the effective version. Hosts accept<0.3.0. - Errors are mandatory only in strict mode.
mode "strict";turnsW-UNUSED-RESULTintoE-UNUSED-RESULT(also forOption);let _ = expr;discards on purpose; and a strategy that sends orders must say what happens when one is turned away (halt_on_error;, or a rule readingrefused(rule),rejected(rule)orlast_error():E-STRAT-UNHANDLED-REJECTION). Without the header nothing becomes an error: 0.1 habits keep working. - Named books.
position name;declares an independent position;rule … for namesays which one a rule belongs to. The runtime tags every order and lot with its book (side maps in the runtime state, so no struct literal across the workspace changed), allows one order per book per step, and acts on every position of a book forReduce,CloseandProtect.Intent.Addadds an entry to an open book. Strategies that declare no book have one,main, and behave as before: the identity hash of an old strategy does not change (new fields are skipped when empty). - Market signals are features, with a rule for unknown. Footprint figures (the chart's own definitions, tested against
aggregation), facts (funding, open interest, liquidations, book), levels of the UTC day and large prints of the tape are signals of the strategy graph. Each is unknown — never zero, never carried — when it was not watched in full, when a hole reaches into it, or when the environment does not carry it. The capability catalogue says where each is served; a backtest refuses, in words and before it runs, a dataset that lacks a stream, and a deployment to live refuses what the live feed does not deliver yet. - Handlers (as built; the design below was simplified). Imperative strategies —
on bar(5min),on fill,on order,on timer— keep their state by value and call out only through actxthat gives what the engine already knows at that instant (closed bars, the footprint, positions per book, the account, declared features) and nothing after it. The compiler lowers each handler to a function(state, ctx) -> Step; the runtime gains anInstanceAPI (load the artifact once, call functions with a budget per call), and TTT implementsstrategy_core::Strategyon top of it so a backtest, a replay and a demo run the same code. Open questions the implementer must settle:ValueisRc-based, so an instance cannot cross threads — build it on the backtest thread; budget per call versus per run; the cost ofon trade, which warns (W-HOT-HANDLER).
Consequences#
- Existing programs and strategies are untouched; the new surface is additive in the host contract (
features0.1.8, API 0.1.13). - Everything in 1–4 is covered by conformance fixtures, unit tests and end-to-end backtests that run twice and compare journals.
- What is not validated: the GUI with these strategies, derivatives and book on the live feed, and anything against a real venue (strategies stay demo, replay and backtest).
See
LAUNCH_TODO.md§0 andt0-lang/STATUS.md.
Addendum (2026-10-18): what was built differently, and what was decided since#
- Handlers are functions the strategy names, not an
on …block language:handler bar(5) = on_bar(ctx, px, avg);withstate = init();. The market reaches a handler only through the strategy's signals (so there is nothing to clip to the instant); what the strategy holds reaches it throughctx, ahandlers.Context(positions of every book, working orders, equity). Noon trade: the cost question is moot. Measured: a handler on a one-minute bar over 30 days costs about 8 % more than the same strategy as rules. - Modules (
import "lib/x.tz" as x;) are one text to the compiler (the program, then its modules, deps first): no IR change, diagnostics remapped to the import line, the language services follow a name into the module that declares it. Orders gainedStop/StopLimit(entries and exits), exits that rest at a price (Limit,Stop,StopLimitonCloseandReduce),OrderOption.PostOnly/ImmediateOrCancel/Expire, and a stop entry carries its own bracket. - The IR moved by a patch, 0.1.3 (compatibility policy): an older runtime refuses an artifact that uses
Map. - Data: funding rate, open interest (and its change) reach a live strategy from the terminal's poll, as the same events a dataset holds; the resting book reaches it from the capture's heat columns, as book frames stamped with their arrival. Neither is offered to a replay or a backtest where it would not repeat or does not exist. The catalogue said a replay served the book while nothing produced the event; it was corrected.
- Not built: a venue parameter and gamma/spot/other exchanges in strategies (the datasets have no such streams); liquidations and settled funding live (the backend gives aggregated buckets); the book in a replay (the replay would have to hold its clock for the column).