The order-routing surface: the trading provider and service, the order/position/account
model, all order enums, trading events, risk validation, commission models, bracket presets, and the ATM
advanced-trade-management types.
Provider & service — SabrTrader.Pipeline.Venues.Trading
An ITradingProvider is one connected brokerage; the host aggregates providers behind an
ITradingService and fans out a single TradingEvent stream. Both expose the same
place / cancel / modify / flatten verbs.
| Type |
Members |
ITradingProvider : IDisposable
|
ProviderKey, Capabilities, bool ReportsCommission, IsRunning, Exception? LastStartError, Accounts, OpenOrders, Positions; event Action<TradingEvent>? EventEmitted; Task<bool> StartAsync(ct), Task StopAsync(ct), Task<OrderId> PlaceAsync(OrderRequest, AccountId, ct), Task<bool> CancelAsync(OrderId, ct), Task<bool> ModifyAsync(OrderId, OrderModification, ct), Task<bool> FlattenAsync(AccountId, string? instrument = null, ct), Task<bool> ExerciseOptionAsync(AccountId, string instrument, decimal quantity, ct), Task<MultiLegPlacement> PlaceMultiLegAsync(MultiLegOrderRequest, AccountId, ct), Task<OcoPlacement> PlaceOcoAsync(OcoRequest, AccountId, ct), Task<MultiLegPrecheckResult> PrecheckMultiLegAsync(MultiLegOrderRequest, AccountId, ct), IReadOnlyList<AccountBalance> GetBalances(AccountId). |
ITradingService : IDisposable
|
Accounts, OpenOrders, Positions, Providers; Account? GetAccount(AccountId), Order? GetOrder(OrderId), TradingProviderCapabilities GetCapabilities(AccountId), IReadOnlyList<AccountBalance> GetBalances(AccountId); event Action<TradingEvent>? EventEmitted; void AddProvider(ITradingProvider), bool RemoveProvider(string providerKey); same PlaceAsync / CancelAsync / ModifyAsync / FlattenAsync verbs (service also has FlattenAsync(account, instrument, instrumentKey, instrumentVenue, ct)) plus ExerciseOptionAsync, PlaceMultiLegAsync, PlaceOcoAsync, PrecheckMultiLegAsync. |
TradingProviderCapabilities |
[Flags] enum: None, PlaceOrders, CancelOrders, ModifyOrders, FlattenPositions, AccountDiscovery, PositionStream, FillsStream, Brackets, AssetBalances, NativeOco, ShortSelling, MultiLegOrders, ExerciseOptions, Leverage, Full. |
TradingProviderKeys |
static: const char VenueQualifierSeparator, string VenueOf(string providerKey), string Compose(string venue, string qualifier), bool BelongsToVenue(string providerKey, string venue). |
IBracketLegSplitController |
bool CanSplit(OrderId), bool SplitLeg(OrderId, decimal quantity, int widenTicks = 0). |
IProtectionVerifier |
bool IsProtected(AccountId account, string instrument). |
Orders & enums
Build an OrderRequest (optionally with a BracketSpec) and submit it; the resulting
Order carries its state and fills. OrderRequest.Validate() throws on malformed
requests — call it before placing.
| Type |
Members |
OrderRequest |
record (string Instrument, OrderSide Side, OrderType Type, decimal Quantity, decimal? LimitPrice = null, decimal? StopPrice = null, TimeInForce TimeInForce = Day, BracketSpec? Bracket = null, string? OcoGroupId = null, string? ClientTag = null, ...); init InstrumentKey, InstrumentVenue, OriginId, NativeInstrumentId, NativeInstrumentType, PositionEffect? PositionEffect, bool? PostOnly, bool? ReduceOnly; void Validate(). |
BracketSpec |
record (decimal? StopLossPrice, decimal? TakeProfitPrice); void Validate(OrderSide entrySide). |
OrderModification |
record (decimal? NewQuantity = null, decimal? NewLimitPrice = null, decimal? NewStopPrice = null, TimeInForce? NewTimeInForce = null). |
Order |
record (OrderId Id, AccountId AccountId, OrderRequest Request, OrderRequest OriginalRequest, OrderState State, decimal FilledQuantity, decimal AverageFillPrice, string? BrokerOrderId, string? RejectReason, DateTime CreatedUtc, DateTime UpdatedUtc); IsTerminal, RemainingQuantity; static Pending(id, accountId, request). |
Fill |
record (OrderId OrderId, decimal Quantity, decimal Price, decimal Commission, DateTime TimestampUtc, string? FeeCurrency = null). |
OrderId |
readonly record struct: Guid Value; static New(), bool TryParse(string?, out OrderId). |
OrderSide |
enum: Buy, Sell. |
OrderType |
enum: Market, Limit, Stop, StopLimit. |
TimeInForce |
enum: Day, Gtc, Ioc, Fok. |
OrderState |
enum: Pending, Working, PartiallyFilled, Filled, Cancelled, Rejected, Expired, Stale. |
PositionEffect |
enum: Open, Close. |
Multi-leg & OCO orders
Two placement families beyond the single OrderRequest: an atomic net-priced multi-leg
(options) order and an one-cancels-other pair. Gate each on the matching capability flag
(MultiLegOrders, NativeOco) and call the corresponding
PlaceMultiLegAsync / PlaceOcoAsync verb.
| Type |
Members |
MultiLegOrderRequest |
record (IReadOnlyList<OptionLeg> Legs, decimal NetLimitPrice, decimal Quantity, string? ClientTag = null); const int MinLegs = 2, const int MaxLegs = 4; init NetPriceDirection? Direction; OrderRequest ToRiskOrderRequest(OptionLeg leg), void Validate(). |
OptionLeg |
record (string Instrument, string NativeInstrumentId, string NativeInstrumentType, OrderSide Side, int Ratio, PositionEffect PositionEffect); init decimal? ReferencePrice. |
MultiLegPlacement |
record (bool Success, IReadOnlyList<OrderId> OrderIds, string? GroupId, string? RejectReason); static Ok(orderIds, groupId), Failed(reason). |
MultiLegPrecheckResult |
record (bool Ok, decimal? EstimatedCashRequired, string? Currency, string? Reason); static Unsupported(reason). |
OcoRequest |
record (string Instrument, IReadOnlyList<OcoLeg> Legs, string? InstrumentKey = null, string? InstrumentVenue = null, string? OriginId = null); OrderRequest ToOrderRequest(OcoLeg leg), void Validate(). |
OcoLeg |
record (OrderSide Side, OrderType Type, decimal Quantity, decimal? LimitPrice = null, decimal? StopPrice = null, TimeInForce TimeInForce = Day, string? ClientTag = null). |
OcoPlacement |
record (bool Success, IReadOnlyList<OrderId> LegOrderIds, string? FailureReason); static Ok(legOrderIds), Failed(reason). |
NetPriceDirection |
enum: Debit, Credit. |
Accounts & positions
| Type |
Members |
Account |
record (AccountId Id, string DisplayName, string Currency, decimal CashValue, decimal? RealizedPnL, decimal UnrealizedPnL, decimal MarginUsed, decimal BuyingPower, DateTime UpdatedUtc); init IsSnapshot, AccountMetrics? Metrics, PrefersDisplayNameInSelector, UnrealizedExcludedCount; computed Mode, Equity, SelectorLabel, IsUnrealizedPartial; static NewSim(...). |
AccountId |
readonly record struct: string ProviderKey, string ProviderAccountId, AccountMode Mode; static None; IsEmpty, bool TryParse(string?, out AccountId). |
AccountMode |
enum: Live, Paper, Sim. |
AccountBalance |
record: string Asset, decimal Total, decimal Available, decimal Reserved; static Create(asset, total, available). |
AccountMetrics |
record of nullable broker metrics: TotalCashBalance, GrossRealizedPnL, TotalCommissions, MaintenanceMargin, ExcessBuyMargin/ExcessSellMargin, UsedBuyingPower, DailyLossLimit, DrawdownPercentUsed, TrailingDrawdownFloor, NetQuantity, OpenPositions, FilledBuys/FilledSells, WorkingBuys/WorkingSells, … |
Position |
record (AccountId AccountId, string Instrument, decimal Quantity, decimal AverageEntryPrice, decimal LastPrice, decimal UnrealizedPnL, decimal RealizedPnLSession, DateTime OpenedUtc, DateTime UpdatedUtc, decimal Multiplier = 1m); IsLong/IsShort/IsFlat; init IsSnapshot, PositionMetrics? Metrics, string? PnlCurrency; ApplyFill(side, qty, price, time), MarkToMarket(price, time); static Empty(...). |
PositionMetrics |
record of nullable per-position metrics: decimal? Financing, DerivativeMetrics? Derivative; option fields OptionIsCall, OptionStrike, OptionExpiry, OptionUnderlyingSymbol, OptionCanExerciseEarly. |
DerivativeMetrics |
record of nullable derivative metrics: MarkPrice, LiquidationPrice, Leverage, MarginMode? MarginMode, PositionMarginUsed, FundingRate, NextFundingTime, UnrealizedFunding, PaidFunding. |
MarginMode |
enum: Cross, Isolated. |
Trading events
The provider/service stream a single abstract TradingEvent hierarchy. TimestampUtc
and a monotonic Sequence are on the base; switch on the concrete type to react.
| Type |
Carries |
TradingEvent (abstract) |
DateTime TimestampUtc, long Sequence. |
AccountSnapshotEvent |
Account Account. |
AccountRemovedEvent |
AccountId AccountId. |
OrderCancelRejectedEvent |
AccountId AccountId, OrderId OrderId, string Reason. |
OrderUpdateEvent |
Order Order. |
FillEvent |
AccountId AccountId, Fill Fill. |
PositionUpdateEvent |
Position Position. |
BalanceSnapshotEvent |
AccountId AccountId, IReadOnlyList<AccountBalance> Balances. |
ConnectionStateEvent |
string ProviderKey, bool Connected, string? Reason. |
ATM — SabrTrader.Pipeline.Venues.Trading.Atm
An AtmStrategy describes a multi-bracket exit plan (per-bracket stop/target, auto-breakeven,
auto-trail, optional time exit). The host's ATM engine consumes it; plugins build and validate strategies
and place/cancel/modify through an IAtmOrderGateway.
| Type |
Members |
AtmStrategy |
record (string Name, AtmParameterUnit Unit, IReadOnlyList<AtmBracket> Brackets, AtmStopStrategy StopStrategy, AtmTimeExit? TimeExit = null); decimal TotalQuantity, int AtrPeriod, bool RequiresPipSize, bool UsesAdaptiveBrackets, void Validate(). |
AtmBracket |
record (decimal Quantity, decimal StopLoss, decimal ProfitTarget); bool IsRunner, init decimal FallbackStopTicks, AtmParameterUnit? StopLossUnit, AtmParameterUnit? ProfitTargetUnit; AtmParameterUnit EffectiveStopLossUnit(AtmParameterUnit strategyUnit), AtmParameterUnit EffectiveProfitTargetUnit(AtmParameterUnit strategyUnit), Validate(int index). |
AtmStopStrategy |
record (AtmStopOrderType StopOrderType, decimal StopLimitOffsetTicks, AtmAutoBreakeven? AutoBreakeven, AtmAutoTrail? AutoTrail); static StaticMarket, Validate(). |
AtmAutoBreakeven |
record (decimal ProfitTrigger, decimal Plus); Validate(). |
AtmAutoTrail |
record (IReadOnlyList<AtmAutoTrailStep> Steps); const int MaxSteps = 3, Validate(). |
AtmAutoTrailStep |
record (decimal ProfitTrigger, decimal StopLoss, decimal Frequency); Validate(int index). |
AtmTimeExit |
record (TimeSpan CloseAt, string TimeZoneId); Validate(). |
AtmParameterUnit |
enum: Ticks, Currency, Percent, Price, Atr, RiskReward, Pips. |
AtmStopOrderType |
enum: StopMarket, StopLimit, Simulated. |
AtmEntryQuantity |
static: decimal Resolve(AtmStrategy?, decimal requestedQuantity). |
IAtmOrderGateway |
void Place(OrderRequest), void PlaceOco(OcoRequest), void Cancel(OrderId), void Modify(OrderId, OrderModification). |
IAtmStrategyStore |
IReadOnlyList<AtmStrategy> Load(), void Save(...), event EventHandler? Changed. |
IAtmDefaultsStore |
Load(), Save(...), string? GetDefault(string instrument), void SetDefault(string instrument, string? strategyName). |
IPositionManagementRegistry |
IDisposable Claim(...), IDisposable? TryClaim(...), bool IsClaimed(...), event Action? Changed. |
ManagedInstrument |
readonly record struct (string? CanonicalKey, string NativeSymbol). |
IDynamicStopLevelSource |
decimal? CurrentLevel, string Description — feed a trailing stop from an indicator. |
Bracket presets — SabrTrader.Pipeline.Venues.Trading.Brackets
A reusable stop/target offset preset (in price or ticks) plus the math to turn it into absolute bracket
prices for a given entry and side.
| Type |
Members |
BracketPreset |
record (string name, BracketOffsetUnit unit, decimal? stopLossOffset, decimal? takeProfitOffset); init Name, Unit, StopLossOffset, TakeProfitOffset. |
BracketOffsetUnit |
enum: Price, Ticks, Pips. |
BracketPriceResult |
readonly record struct (decimal? StopLossPrice, decimal? TakeProfitPrice). |
BracketPresetMath |
static: BracketPriceResult ComputeBracketPrices(decimal entryPrice, OrderSide side, BracketPreset preset, decimal tickSize, decimal pipSize = 0m). |
IBracketPresetStore |
IReadOnlyList<BracketPreset> Load(), void Save(IReadOnlyList<BracketPreset> presets). |
Risk validation — SabrTrader.Pipeline.Venues.Trading.Risk
An IRiskValidator inspects an order against RiskLimits and a RiskSnapshot
and returns a RiskRejection (one of the typed subtypes) or null to allow it.
| Type |
Members |
IRiskValidator |
RiskRejection? Validate(OrderRequest, AccountId, RiskSnapshot), RiskRejection? ValidateModification(OrderRequest currentOrder, decimal newQuantity, AccountId, RiskSnapshot). |
RiskLimits |
record: decimal? MaxPositionSize, MaxDailyRealizedLoss, int? MaxOpenOrders, MaxOrderQuantity, MaxTotalLoss, DailyProfitLock, int? MaxConsecutiveLosers. |
RiskSnapshot |
record (Account Account, Position? CurrentPosition, int OpenOrderCount, AccountRiskState? RiskState = null). |
AccountRiskState |
record (int ConsecutiveLosers, DateOnly TradingDate); static ForDate(DateOnly). |
RiskRejection (abstract) |
string Reason; subtypes PositionSizeExceeded, DailyLossLimitHit, OpenOrderCountExceeded, OrderQuantityExceeded, TotalLossLimitHit, DailyProfitTargetReached, ConsecutiveLossLimitHit, VenueNotConnected. |
IRiskLimitsRegistry |
RiskLimits? GetLimits(AccountId), event Action<AccountId>? LimitsChanged. |
IRiskLimitsStore |
IReadOnlyDictionary<AccountId,RiskLimits> Load(), void Save(...). |
IAccountRiskStateRegistry |
AccountRiskState GetState(AccountId), event Action<AccountId>? StateChanged. |
IRiskTradeOutcomeSink |
void OnTradeClosed(AccountId, decimal realizedPnLDelta, DateTime timestampUtc). |
Commissions — SabrTrader.Pipeline.Venues.Trading.Commissions
An ICommissionModel turns a CommissionContext (symbol, qty, price, side,
liquidity) into a CommissionResult. RateCommissionModel covers the common
rate-based cases.
| Type |
Members |
ICommissionModel |
CommissionResult Compute(in CommissionContext ctx). |
RateCommissionModel |
RateCommissionModel(CommissionRate rate); CommissionRate Rate, Compute(in ctx). |
CommissionModels |
static: readonly ICommissionModel Zero, ICommissionModel Flat(decimal perUnit). |
CommissionRate |
record (CommissionBasis basis, decimal value, decimal minFee = 0m, decimal maxFee = 0m, decimal? makerValue = null, decimal? takerValue = null, CommissionAccrual accrual = PerSide); static Zero. |
CommissionContext |
readonly record struct (string Symbol, decimal Quantity, decimal Price, decimal Multiplier, OrderSide Side, Liquidity Liquidity, string Venue, decimal PriorOrderRawCommission = 0m, string? InstrumentKey = null). |
CommissionResult |
readonly record struct (decimal Amount, decimal CumulativeRawCommission); static Zero. |
CommissionBasis |
enum: PerUnit, PerOrder, PercentNotional, BasisPoints. |
CommissionAccrual |
enum: PerSide, PerRound. |
Liquidity |
enum: Unknown, Maker, Taker. |
Client-side OCO — SabrTrader.Pipeline.Venues.Trading.Oco
For venues without NativeOco, ClientSideOcoCoordinator emulates one-cancels-other:
it places the legs through an IOcoLegGateway, and when one fills it cancels (or resizes) the
others, with retry and optional durable intent (IOcoIntentStore) so a group survives a restart.
| Type |
Members |
ClientSideOcoCoordinator |
ClientSideOcoCoordinator(IOcoLegGateway gateway, int retryAttempts = 3, Action<string>? log = null, IOcoIntentStore? store = null); Task<OcoPlacement> PlaceAsync(OcoRequest, AccountId, ct), Task OnOrderUpdate(Order), void Register(string? groupId, OrderId), void Forget(OrderId), void Rearm(IReadOnlyList<Order> reconciledOpenOrders), void Reset(). |
IOcoLegGateway |
Task<OrderId> PlaceLegAsync(OrderRequest leg, AccountId, ct), Task<bool> CancelLegAsync(OrderId, ct), Task<bool> ResizeLegAsync(OrderId, decimal newQuantity, ct), bool TryGetOrder(OrderId, out Order). |
IOcoIntentStore |
IReadOnlyDictionary<string, IReadOnlyList<string>> LoadGroups(string accountId), void SaveMember(string accountId, string groupId, string brokerOrderId), void RemoveMember(string accountId, string brokerOrderId). |
NullOcoIntentStore |
no-op IOcoIntentStore; static Instance. |
Price feed — SabrTrader.Pipeline.Venues.Trading.Sim
The price source the simulated/paper trading engine subscribes to. Plugins rarely implement this; it is
documented here because TickQuote appears in sim and ATM flows.
| Type |
Members |
IPriceFeed |
IDisposable Subscribe(string instrument, Action<TickQuote> handler), TickQuote? GetLastTick(string instrument). |
TickQuote |
readonly record struct (DateTime TimestampUtc, decimal Bid, decimal Ask, decimal Last); HasSpread, Mid; init ContinuousFromPrior, BidSize, AskSize, LastSize; static AtPrice(...). |
Day clock & position helpers
| Type |
Members |
TradingDayClock |
TradingDayClock(TimeOnly settlement, TimeZoneInfo exchangeTimeZone); CmeDefault; DateOnly TradingDay(DateTime utcInstant); DateTime NextBoundaryUtc(DateTime utcInstant). |
IPositionPnlConverter |
decimal? ToAccountCurrency(Position position) — convert a position's PnL into the account currency when venues report a foreign PnlCurrency. |
IPositionPropagationDelay |
TimeSpan PositionPropagationDelay { get; } — how long after a fill the venue's position stream is expected to catch up. |
DuplicateSubmission / RealizedPnLUnavailable / UnrealizedPnLPartial
|
Additional RiskRejection subtypes (ns SabrTrader.Pipeline.Venues.Trading.Risk). UnrealizedPnLPartial carries int ExcludedPositions. |