Strategies

Reference

Strategies

The automated-trading surface: the Strategy base class and its context, the parameter and indicator declaration system, the managed-order and ATM controllers, data feeds, the catalog, and the backtest result and performance analytics.

Strategy & context — SabrTrader.Pipeline.Strategies

Derive from Strategy, declare parameters and indicators in OnInitialize, and act in OnBar using the protected bar/position/order helpers. The same surface is exposed abstractly as IStrategyContext for the host runtime.

Type Members
Strategy (abstract) State: Calculate, Instrument, Account, StrategyName, TickSize, PointValue, State, BarCount, CurrentBar, GetBar(barsAgo), TryGetBar(barsAgo, out bar), IsBarClosed, IsFirstTickOfBar, TradingHours, Session, IsFirstBarOfSession, InSession, Position, IsFlat/IsLong/IsShort, AccountSnapshot, WorkingOrders, RiskStateRegistry, WireUnitsPerQuantity, QuantityStep, MinQuantity, TryGetOrderFlowBar(barsAgo, out orderFlow), TryGetOrderBook(out book), RecordedDepth, ToWireQuantity(qty).
Actions: PlaceOrder/CancelOrder/ModifyOrder/Flatten, EnterLong/EnterShort/ExitLong/ExitShort(qty), HasPendingManagedOrder, Log(msg), NotifyEntryBlocked(reason), ClaimPositionManagement().
Options: OptionChains (IOptionChainReader? — null when the host serves no options data), Task<MultiLegPlacement> PlaceMultiLegOrderAsync(MultiLegOrderRequest, ct), Task<MultiLegPrecheckResult> PrecheckMultiLegOrderAsync(MultiLegOrderRequest, ct), Task<bool> ExerciseOptionAsync(instrument, quantity, ct) — failure lands in the result, never a faulted task; see Multi-leg orders & exercise.
ATM: UseAtm(AtmStrategy, tickSize?, pointValue?), HasAtmBracket, SetAtmBracketGeometry(stop, target), SetNextStopPrice(price?).
Declare: IntParameter / DoubleParameter / BoolParameter / StringParameter / FilePathParameter(...), DeclareIndicator<T>(factory).
Overrides: OnInitialize / OnStart / OnBar / OnOrderUpdate / OnFill / OnPositionUpdate / OnStop, and on a recorded-book run OnMarketByOrder / OnMarketDepth / OnOrderBookLifecycle (below).
IStrategyContext Runtime seam mirroring the above: bar accessors, CreateSessionIterator(template?), order verbs, Position, AccountSnapshot, RiskStateRegistry, WorkingOrders, WireUnitsPerQuantity, QuantityStep, MinQuantity, TryGetOrderFlowBar(barsAgo, out orderFlow), IManagedOrderController CreateManagedOrderController(), IAtmService CreateAtmService(AtmStrategy, double tickSize, double pointValue), ClaimPositionManagement(), plus the options members (OptionChains, PlaceMultiLegOrderAsync, PrecheckMultiLegOrderAsync, ExerciseOptionAsync — default-implemented so backtest/fake contexts inherit safe "unsupported" behaviour).
StrategyState enum: Created, Initialized, Running, Stopped, Faulted.
StrategyRunConfig record (string instrument, AccountId account, string? strategyName = null, IReadOnlyDictionary<string,object>? parameterOverrides = null, double? tickSize = null, double? pointValue = null, string? instrumentKey = null, string? instrumentVenue = null, string? tradingHoursTemplateName = null, double? quantityStep = null, QuantityUnit quantityUnit = QuantityUnit.Contract, double? minQuantity = null).
RenderingStrategy abstract Strategy, IChartCustomRender, IRepaintNotifier: event Action? RepaintRequested, OnCustomRender(IIndicatorRenderContext), RenderLayer, RequestChartRepaint().

Order-flow-aware strategies

Strategies that need pre-aggregated order-flow bars implement IOrderFlowAwareStrategy so the host can attach an IOrderFlowStrategyDataFeed. Inside the strategy, prefer TryGetOrderFlowBar / ToWireQuantity over assuming 1 lot = 1 wire unit.

public interface IOrderFlowAwareStrategy
{
    bool RequiresOrderFlow(IReadOnlyDictionary<string, object>? parameterValues);
}

public interface IOrderFlowStrategyDataFeed : IStrategyDataFeed
{
    IReadOnlyList<OrderFlowBar>? HistoryOrderFlow { get; }
    bool TryGetOrderFlowFor(in Bar closedBar, out OrderFlowBar orderFlow);
}

Recorded order book in backtests

An EveryTickReal run with a recorded MBO or L2 tape for the instrument attaches a private IOrderBook to the strategy and streams the tape into it in timestamp order with the ticks. Read it through TryGetOrderBook(out book); book.DepthMode is PerOrder for an MBO tape and Aggregated for an L2 tape. Nothing here touches the live hub.

Three hooks fire, all after the book has been updated and never during warmup bars:

Hook Fires
OnMarketByOrder(in MboEvent evt) Per recorded MBO event. A tape replay is complete: every recorded event fires, in order.
OnMarketDepth(in DepthUpdate update) Per recorded L2 event when the tape is L2 (no MBO).
OnOrderBookLifecycle(OrderBookLifecycleEvent evt) Per control marker on the tape, in stream order: Reset, CaptureGap (a hole the recorder wrote; the book was cleared and is incomplete until the next re-image), RebuildStarted / RebuildCompleted around a venue image. See OrderBookLifecycleEvent.

Outside a run, RecordedDepth (IRecordedDepthCatalog?, null when the host records nothing) opens the same tapes directly: see IRecordedDepthCatalog.

Parameters & indicators

Parameters are typed, optionally optimizable, and convert implicitly to their value. Declared indicators return a handle whose Instance updates each bar.

Type Members
StrategyParameter (abstract) string Name, OptimizationRange? OptimizationRange, bool IsOptimizable, ParameterEditorKind EditorKind, string? FileFilter, object BoxedValue, Type ValueType.
StrategyParameter<T> T DefaultValue, T Value; implicit operator T(StrategyParameter<T>).
ParameterSet IReadOnlyList<StrategyParameter> All, int Count, StrategyParameter? Find(string name), bool TrySetValue(string name, object? value).
OptimizationRange record (decimal Min, decimal Max, decimal Step); Validated(string parameterName).
StrategyIndicator<T> T Instance, bool IsReady (where T : IndicatorBase).

Managed orders & ATM

Two layers of order management. IManagedOrderController turns position-aware enter/exit intents into orders; IAtmService runs an AtmStrategy bracket and advances its stop/target each bar. Create both via IStrategyContext.

Type Members
IManagedOrderController bool HasPendingOrder, void EnterLong(decimal quantity), void EnterShort(decimal quantity), void ExitLong(), void ExitShort(), void HandleOrderUpdate(Order order).
IAtmService bool HasBracket, void UpdateBracketGeometry(decimal stopOffset, decimal targetOffset), void SetNextBracketStopPrice(decimal? stopPrice), void OnBar(), void OnOrderUpdate(Order order), void OnPositionUpdate(Position position).
See also. AtmStrategy and the bracket model live in the trading contracts — see Trading → ATM.

Data feeds

Type Members
IStrategyDataFeed IReadOnlyList<Bar> History, event Action<Bar>? BarClosed.
IIntrabarStrategyDataFeed : IStrategyDataFeed adds event Action<IntrabarUpdate>? BarUpdated.
IntrabarUpdate readonly record struct: Bar DevelopingBar, bool IsFirstTickOfBar.
ILiveStrategyDataFeed : IStrategyDataFeed, IDisposable Task StartAsync(ct), Task StopAsync(), event Action<Exception>? Faulted.
IStrategyLogger void Log(string strategyName, string message); NullStrategyLogger.Instance.

Catalog — SabrTrader.Pipeline.Strategies.Catalog

Discovery and registration. Decorate a strategy with [StrategyMetadata] for a friendly name; the catalog reflects assemblies into launchable StrategyDescriptors.

Type Members
StrategyMetadataAttribute [AttributeUsage(Class)]: string? DisplayName, string? Description.
StrategyDescriptor string Id, Type StrategyType, string DisplayName, string Description, IReadOnlyList<StrategyParameter> Parameters, Strategy CreateInstance().
StrategyCatalog event Action? Changed, IReadOnlyList<StrategyDescriptor> Strategies, RegisterDynamic(...), ClearDynamic(), static BuildDefault() / BuildFrom(IEnumerable<Assembly>), StrategyDescriptor? Find(string name).

Backtest result & analytics

A backtest returns a BacktestResult with the final account/position, fills, equity curve and a rich PerformanceReport (namespace SabrTrader.Pipeline.Analytics and …Analytics.Metrics).

Type Members
BacktestResult StartingCash, FinalAccount, FinalPosition, Fills, Orders, EquityCurve, BarsReplayed, FinalState, FaultException, Performance, RealizedPnL, NetProfit, FillCount, WasCancelled.
PerformanceReport record: Pnl, Trades, Drawdown, RiskAdjusted, Excursion, Exposure, TradeList, EquityCurve, HasTrades; static Empty(startingCash).
Trade record: Number, Direction, EntryTimeUtc/ExitTimeUtc, EntryPrice/ExitPrice, Quantity, GrossPnL, Commission, NetPnL, IsWinner/IsLoser/IsOpen, Duration, BarsInTrade, Mae/Mfe(Currency/Price), EndTradeDrawdown.
TradeDirection enum: Long, Short.
EquityPoint readonly record struct (DateTime TimeUtc, decimal Equity).
PnLSummary StartingCash, NetProfit, GrossProfit/GrossLoss, TotalCommission, ProfitFactor, ReturnPct, EndingEquity.
TradeStatistics TotalTrades, Winning/Losing/BreakEven, Long/Short splits, AverageTrade/Winner/Loser, LargestWinner/Loser, MaxConsecutiveWinners/Losers, WinLossRatio, Sqn, WinRatePct.
DrawdownMetrics MaxDrawdown, MaxDrawdownPct, AverageDrawdown, LongestDrawdownDuration, MaxRunup, UlcerIndex, RecoveryFactor.
RiskAdjustedMetrics SharpeRatio, SortinoRatio, CalmarRatio, AnnualReturnPct, DailyReturnStdDevPct.
ExcursionMetrics AverageMae/AverageMfe, WorstMae/BestMfe, AverageEndTradeDrawdown, AverageTradeEfficiencyPct.
ExposureMetrics TimeInMarketPct, TotalContractsTraded, AveragePositionSize.

Replay options — SabrTrader.Pipeline.Strategies.Replay

Type Values
BacktestResolution enum: BarOpenOnly, BarClose, BarOHLC, BarMagnifier, EveryTickGenerated, EveryTickReal.
IntrabarTieBreak enum: UseBarDirection, LowBeforeHigh, HighBeforeLow.