Strategies
Overview & lifecycle
Automated trading logic — managed orders, parameters, indicators, full ATM bracket management, backtest and live — all from the same class, driven by a small set of lifecycle hooks.
The strategy model
Everything in this chapter starts from one base class. A strategy subclasses
Strategy in the TradeStrike.Pipeline.Strategies namespace, overrides a few
lifecycle hooks, and calls the protected helpers (bars, position, orders, logging) to do its
work. None of the host plumbing — data feed, trading service, runner — is ever visible: every
helper delegates to an IStrategyContext the runner injects before the first callback. That is
what lets the same class run unchanged against a live broker or a backtest engine.
Three invariants the runtime guarantees shape how you store state and reason about concurrency:
- One instance = one run. Every backtest or live launch creates a fresh instance; fields hold per-run state. The runner never resets a strategy's fields — to run again, construct a new instance.
-
Single-threaded. Every
On…hook runs on the run's single serialised strategy thread. No locks, novolatile— the one exception is custom chart rendering (see custom rendering andRenderingStrategy). -
Same code, both modes. The strategy depends only on the
IStrategyContextseam, so the identical class runs deterministically in a backtest and live against a real broker.
Order operations are fire-and-forget. PlaceOrder, CancelOrder,
ModifyOrder and Flatten never block on a broker round-trip; the outcome arrives
later through OnOrderUpdate / OnFill / OnPositionUpdate.
Lifecycle hooks
A strategy is defined entirely by the hooks it overrides. The runner calls them in a fixed order: declare once, start once, a callback per bar, with order/fill/position events interleaved as the market responds, and finally a clean-shutdown hook. Every override is optional — a hook you do not override is a no-op.
| Hook | When | Use it for |
|---|---|---|
OnInitialize() |
Once, first, before any bar | Declare parameters & indicators, set Calculate. |
OnStart() |
Once, after overrides applied, before bars | Read final param values, warm-up, call UseAtm. |
OnBar() |
Per bar (per Calculate mode) |
Your entry/exit logic. |
OnOrderUpdate(Order) |
Order state changed | React to working/filled/rejected. |
OnFill(Fill) |
One execution | Track raw executions / commission. |
OnPositionUpdate(Position) |
Net position changed | Track PnL, reconcile state. |
OnStop() |
Clean shutdown | Release external resources. (Not called on a fault.) |
OnInitialize,
but read their final values from OnStart onward — the host applies parameter overrides
between those two hooks, so a value read in OnInitialize is still the default.
Declarations added later than OnInitialize are ignored: the indicator host is built once,
between OnInitialize and OnStart.How a run flows
The runner drives the lifecycle and isolates faults: an exception thrown in any hook transitions the run
to Faulted and releases its subscriptions — it never escapes to crash the host. The
state machine is one-way and linear, with Faulted as an off-ramp.
graph LR; C[Created] --> I[Initialized]; I --> R[Running]; R --> S[Stopped]; R -. throws .-> F[Faulted]; I -. throws .-> F;
Stopped and Faulted are terminal. OnStop runs on a clean stop, but
not on a fault — the strategy is in an unknown state and running its teardown could
compound the failure. You read the current state any time via the State property
(StrategyState).
The rest of this chapter
Strategies are a big surface, so the topics are split across focused pages. Start with your first strategy and walk down the list; each page builds on the model and lifecycle above.
| Page | What it covers |
|---|---|
| Your first strategy | A complete SMA-crossover strategy, end to end. |
| Discovery & metadata | How the catalog finds your class and what [StrategyMetadata] controls. |
| Parameters | Optimizable and fixed inputs, and the override flow. |
| Using indicators | Declaring SDK and built-in indicators inside a strategy. |
| Bars & position state | Reading history, the current bar, position, account and session. |
| Managed orders | Position-aware intent: enter/exit with reversal handling. |
| Raw orders & brackets | Direct order requests, modifies, cancels and the enum reference. |
| Advanced trade management (ATM) | Multi-target brackets, auto-breakeven and trailing. |
| Calculation cadence | On-bar-close, on-price-change and on-each-tick evaluation. |
| Backtest & live | Running the same class in the harness and in production. |