Strategies
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.
On this page
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). |
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. |