The venue SDK surface a plugin implements: plugin, descriptor and manifest; session, context and notices; the instrument catalog and symbol grammar; backfill composition; the depth/MBO ingest plane; the venue-neutral trading components; the chain SPI; and the trade-history and cash-activity contracts. Narrative: Venue plugins and Broker venues.
Plugin & descriptor — SabrTrader.Pipeline.Venues
One plugin DLL exports IVenuePlugin; each venue it provides is one
IVenueDescriptor. Narrative:
The plugin & manifest.
| Type |
Members |
IVenuePlugin |
IReadOnlyList<IVenueDescriptor> Venues { get; } — called once at discovery; must be
fast, pure and must never touch the network. |
IVenueDescriptor |
VenueManifest Manifest; IVenueSession CreateSession(VenueSessionContext);
bool TryValidateSettings(IReadOnlyDictionary<string,string>, out string? error)
(default true); Task<IReadOnlyList<VenueChoice>> GetDynamicChoicesAsync(string
fieldKey, IReadOnlyDictionary<string,string> currentValues, CancellationToken)
(default: the static choices); IVenueSymbolParser? CreateSymbolParser(ISharedSymbolParsers)
(default null). |
VenueChoice |
record (string Label, string Value); static
IReadOnlyList<VenueChoice> StaticChoicesFor(VenueManifest, string fieldKey). |
Manifest & capabilities
| Type |
Members |
VenueManifest |
record (string TypeId, string DisplayName, VenueCategory Category,
IReadOnlyList<VenueAssetClass> AssetClasses, VenueCapabilities Capabilities,
IReadOnlyList<ProviderCredentialField> SettingsSchema, bool SupportsPaper = false,
int MaxConcurrentSessions = 1, int FallbackPriority = VenuePriorityBands.Default,
string? StateStorageFolder = null, string? AttributionBadge = null);
void Validate() throws ArgumentException naming the venue. |
VenueCategory |
enum: MarketData, Levels. |
VenueAssetClass |
enum: Unknown, Future, Option, Stock,
Forex, Crypto, Index, Commodity,
Metal, Bond, CryptoPerp. |
VenueCapabilities |
[Flags] enum (long). Data: LiveTrades, LiveQuotes,
MarketDepth, MarketByOrder, OpenInterest,
MarketSummary, Fundamentals. Historical:
HistoricalBars, HistoricalTicks, HistoricalOrderFlow,
NativeBars. Instruments: InstrumentCatalog,
SymbolSearch. Trading: Trading, CashActivity,
TradeHistoryBackfill. Extras: OptionChains, Levels,
Replay. |
VenuePriorityBands |
static const: Primary = 100, Default = 500, Fallback = 900.
Lower wins. |
ProviderCredentialField |
record (string Key, string DisplayName, ProviderCredentialKind Kind, string? Placeholder,
bool Required = true, IReadOnlyList<string>? Choices, string? DefaultValue, string? HelpText,
string? WarningText, bool Multiline = false, bool DynamicChoices = false, bool ReadOnly = false,
string? StorageName = null). Namespace SabrTrader.Pipeline.Providers. |
Two-layer rule. The manifest declares INTENT; the port bitmasks
(ProviderCapabilities, TradingProviderCapabilities) are the runtime FACT
and may be narrower per session, never wider.
Session & context
| Type |
Members |
IVenueSession : IAsyncDisposable
|
ProviderConnectionStatus Status; event Action<ProviderConnectionStatus>?
StatusChanged; VenueFailure? LastFailure; IDataProvider? Data;
ITradingProvider? Trading; event Action<VenueStreams>? StreamsRestored;
Task ConnectAsync(CancellationToken); Task DisconnectAsync();
T? GetPort<T>() where T : class (default this as T). |
VenueStreams |
[Flags] enum: None, MarketData, Trading,
Account. |
VenueFailure |
record (string Message, bool Permanent, string? Code = null).
Permanent stops the host supervisor retrying. |
IVenueSessionDecorator |
IVenueSession Inner { get; } — marker for wrapping sessions. |
VenueSessionPorts |
static: T? AsPort<T>(this IVenueSession?) — walks decorators, asking each level's
GetPort<T>. |
VenueSessionContext |
Profile, Settings (decrypted, keyed by schema field key),
Notices, Stores, Storage, Credentials,
Depth, BackfillComposer, IvHistory, Clock,
ExecutionGate. |
VenueProfileInfo |
record (Guid ProfileId, string ProfileName, bool Paper = false). |
IVenueStores |
ITimeBarStore? TimeBars, ITickStore? Ticks,
INativeBarStore? NativeBars, IOrderFlowBarStore? OrderFlowBars,
IBackfillActivityTracker? BackfillActivity. All optional — tolerate nulls. |
IVenueExecutionGate |
bool ExecutionPermitted, string? BlockedReason. Host-implemented; null =
unrestricted. |
Notices, failure & storage
| Type |
Members |
IVenueNoticeSink |
void Post(VenueNotice), void Log(string). Non-blocking, never throws,
available from construction. |
VenueNotice |
record (VenueNoticeSeverity Severity, string Message, string? Symbol = null,
string? Code = null). |
VenueNoticeSeverity |
enum: Info, Warning, Error. |
VenueNoticeCodes |
const: EntitlementDenied = "entitlement-denied", DelayedData =
"delayed-data". |
IVenueStateStorage |
string? ReadText(string), void WriteText(string, string),
string? ReadLocalText(string), void WriteLocalText(string, string).
The Local lane is guaranteed machine-local. |
IVenueCredentialWriter |
void Persist(IReadOnlyDictionary<string,string> updatedValues) — plaintext keyed by
schema field key; the host encrypts and saves. |
VenueNotConnectedException |
The one offline condition for both planes. |
IVenueIvHistorySink |
void Publish(string underlyingSymbol, IReadOnlyList<VenueIvHistoryPoint> points) —
venue-served native IV history, seeds IV Rank. Idempotent per session host-side; never throws. |
VenueIvHistoryPoint |
readonly record struct (DateOnly Session, double Iv30). Iv30 is a
FRACTION (0.256 = 25.6%), the platform's IV unit. |
LevelsVenueSession |
Shipped IVenueSession for options-levels vendors: ctor
(string displayName, Func<ILevelsFeed> feedFactory, IVenueNoticeSink? notices = null).
Builds the feed inside ConnectAsync, resolves it through
GetPort<ILevelsFeed>() only while Connected, reports failures NON-permanent.
Data and Trading are always null. |
Instruments & symbols
| Type |
Members |
IVenueInstrumentCatalog |
IReadOnlyList<VenueCatalogEntry> ListEntries(); event Action?
EntriesChanged. Probed with Data.AsCapability<T>(). THE catalog surface —
serves both the persistent sync and live exchange browse. |
VenueCatalogEntry |
readonly record struct (string InstrumentId, VenueAssetClass AssetClass, string? Exchange,
string? Description, string? ProductCode, string? InstrumentType, string? Expiration). |
IVenueInstrumentClassifier |
VenueInstrumentClassification? Classify(string instrumentId) — the asset class and symbol
a venue means by one raw id, paired with IInstrumentDirectory's flat id list. |
VenueInstrumentClassification |
readonly record struct (VenueAssetClass AssetClass, string Symbol). |
IVenueSymbolParser |
VenueSymbolParse Parse(string rawSymbol). Pure, fast, never throws. |
VenueSymbol |
readonly record struct (VenueAssetClass AssetClass, string Root, int? ExpiryYear,
int? ExpiryMonth); factories Future(root[, year, month]),
Stock, Index, Forex, Crypto. |
VenueSymbolParse |
record (VenueSymbol? Best, VenueSymbolConfidence Confidence,
IReadOnlyList<VenueSymbol>? Alternatives); static Unrecognized. |
VenueSymbolConfidence |
enum: Unrecognized, Low, Medium, High. |
ISharedSymbolParsers |
Futures, Equities, Forex, Crypto? — the
platform's grammars, handed into CreateSymbolParser. Host-implemented. |
Backfill composition
| Type |
Members |
IVenueBackfillComposer |
ComposedVenueBackfill Compose(VenueBackfillParts parts). Host-implemented; arrives as
context.BackfillComposer. |
VenueBackfillParts |
record (string ProviderKey, string VenueDisplayName, IHistoricalTimeBarSource TimeBars,
IHistoricalTickSource Ticks, IInstrumentMetadata Instruments, IBackfillProvider DirectBackfill,
ITimeBarPeriodSupport? PeriodSupport, TimeSpan DefaultLookback, Action<string>? Log = null,
IHistoricalOrderFlowBarSource? OrderFlowBars = null, INativeBarSource? NativeBars = null). |
ComposedVenueBackfill |
record (IBackfillProvider Backfill, bool SupportsTickDerived). |
DirectVenueBackfillComposer |
static Instance — the no-host fallback: the venue's uncached direct backfill verbatim,
SupportsTickDerived = false. |
ISeamPriorityHistoricalTickSource |
Opt-in on your tick source: serve the history→live seam's uncached fetch on a dedicated replay lane,
so it is not starved behind bulk day backfills. Same tick contract as LoadTicks. |
IOpenInterestAwareTimeBarSource |
Opt-in on your time-bar source: report per-bar open interest alongside native bars. The OI-aware load
bypasses the on-disk bar cache (fixed-width OHLCV cannot hold OI). |
IFormingBarFreshnessSource |
Opt-in on your backfill provider: report how far the FORMING bar you appended is actually complete, so
the session's history→live overlap cutoff does not under-count. |
LadderTimeBarPeriodSupport |
Shipped ITimeBarPeriodSupport for the common venue shape — a FIXED ladder of native
grains (OANDA granularities, Saxo horizons, TWS bar sizes, cTrader trendbar periods). Must be the
venue's REAL native set. |
IInstrumentAdjustmentResolver |
Optional async companion to IInstrumentMetadata: resolves + caches an instrument's
corporate-action adjustment version BEFORE it is read into a cache key (the synchronous
TryGetAdjustmentVersion cannot do an async per-symbol lookup). Namespace
SabrTrader.Pipeline.Storage. |
Depth & MBO ingest — SabrTrader.Pipeline.MarketDepth
The host's ingest plane, reached through context.Depth. Narrative:
Live ticks & depth.
| Type |
Members |
IMarketDepthHost |
IHostedDepthFeed CreateDepthFeed(IDepthUpstream),
IHostedMboFeed CreateMboFeed(IMboUpstream). |
IHostedDepthFeed : IMarketDepthFeed
|
void Inject(in DepthUpdate), void Reset() (scoped to this feed). |
IHostedMboFeed : IMarketByOrderFeed
|
void Inject(in MboEvent), void BeginReimage(string),
void CompleteReimage(string), void FailImage(string, string reason),
void Reset(). |
IDepthUpstream |
void OnSubscribe(string), void OnUnsubscribe(string). No defaults, on
purpose. |
IMboUpstream |
void OnSubscribe(string), void OnUnsubscribe(string),
void Reimage(string), void FailClosed(string, string reason). |
MboFlowMonitor |
Venue-facing diagnostic: tracks live MBO flow per layer and per UI consumer, logging
consumer-stall when a consumer that was receiving data goes quiet. Namespace
SabrTrader.Pipeline.MarketDepth.Hub. |
MboConnectionDiagnosticLog |
Venue-facing diagnostic sink for the end-to-end MBO connection lifecycle (venue subscribe →
sequencer → hub → feed → consumers), wired by the host into the activity log. |
Inject perf contract. Synchronous, void, by in, allocation-free, never
blocks, safe from any venue thread. Upstream calls arrive on host threads and must return quickly —
queue venue I/O, never perform it inline.
Venue-neutral trading components — SabrTrader.Pipeline.Venues.Trading
Shared machinery any venue composes. Narrative:
The trading port.
| Type |
Members |
OrderRevisionTracker |
static string Stamp(OrderId, int revision), bool TryParse(string?,
out OrderId, out int); instance int Claim(OrderId),
void Rollback(OrderId, int), void Forget(OrderId),
void Reset(), bool IsSupersededRevisionCancel(…). |
StreamGenerationGuard<TKey> : notnull
|
void Touch(TKey), Dictionary<TKey,long> Snapshot(),
bool WasTouchedSince(TKey, IReadOnlyDictionary<TKey,long>),
void Reset(). |
AmbiguousPlacementResolver |
static DefaultProbeDelay (2s); Task ResolveAsync<TUpdate>(probeDelay, delay,
abandoned, fetchOpenOrders, isPendingOrdersTwin, adoptVenueTruth, isStillPending,
rejectAsNeverLanded, diagnostic) — venue specifics arrive as delegates. |
WorkingOrderProbe<TOrder,TUpdate> |
ctor (snapshotCandidates, lookup, fold, abandoned, diagnostic);
DefaultInterval (60s); void Start(TimeSpan?),
Task RunOnceAsync(), void Dispose(). Single-flight. |
PositionSnapshotReconciler |
static List<Position> SelectRetirees<TKey>(tracked, venueKeyOf, reportedKeys, guard,
generationsBeforeRoundTrip, keptDiagnostic), Position AsRetired(Position,
DateTime). Only licensed by a COMPLETE snapshot. |
OrderUpdateFold + VenueOrderReport
|
static FoldResult Apply(Order before, in VenueOrderReport, bool wasLocallyCancelled);
FoldResult = (bool Dropped, Order After, Fill? IncrementalFill). |
OrderQuantitySnapper + OrderSizingRules
|
static bool TrySnap(OrderRequest, OrderSizingRules, out OrderRequest?, out string?);
rules record (decimal? PriceStep, QuantityStep, MinQuantity, MaxQuantity, MinNotional)
+ None. |
QuantityStepMath |
Pure quantity-grid math for INTERACTIVE editing (a quantity stepper): round to the NEAREST step and
clamp into [min, max], and move by whole increments. Deliberately distinct from
OrderQuantitySnapper, which floors DOWN and REJECTS out-of-bounds — the right behaviour
for PLACEMENT, the wrong one while typing. |
ITradingProviderDecorator |
ITradingProvider Inner { get; }. |
TradingProviderCapabilityProbes |
static T? AsCapability<T>(this ITradingProvider?) — walks decorators. |
IPositionPropagationDelay |
TimeSpan PositionPropagationDelay { get; } — how long the venue's position row may lag a
fill. |
IOcoLegGateway |
Task<OrderId> PlaceLegAsync(OrderRequest, AccountId, ct),
Task<bool> CancelLegAsync(OrderId, ct),
Task<bool> ResizeLegAsync(OrderId, decimal, ct),
bool TryGetOrder(OrderId, out Order). Namespace
SabrTrader.Pipeline.Venues.Trading.Oco. |
The full order / account / position / event surface is on the
Trading reference.
Option chain SPI — SabrTrader.Pipeline.Venues.Options
The venue-side SPI, exposed as a session port and probed with
AsPort<IOptionChainSource>(). The data records it serves live in
SabrTrader.Pipeline.Options (package Pipeline.Contracts) and are listed in
the Options reference.
| Type |
Members |
IOptionChainSource |
Task<IReadOnlyList<OptionUnderlying>> SearchUnderlyingsAsync(string query, ct);
Task<OptionChain> GetChainAsync(string underlyingId, IReadOnlyList<DateOnly>? expiries,
ct) (+ a strikesPerExpiry overload);
IDisposable SubscribeQuotes(IReadOnlyList<string> providerInstrumentIds,
Action<OptionQuote> handler);
string? TryGetPositionSymbol(string providerInstrumentId). |
IOptionChainSnapshotSource |
Bounded chain snapshots for the screener / analytics path. |
IOptionChainSourceRegistry |
Host-side registry the port registrar publishes connected sources into. |
OptionChainSourceRegistration |
One registered source: the composed provider key ("saxo:live") + the live
IOptionChainSource. |
Trade history & cash activity — SabrTrader.Pipeline.Venues.TradeHistory
| Type |
Members |
IVenueTradeHistorySource |
bool Supports(AccountId account) — true only for accounts behind THIS login;
Task<VenueTradeHistoryPage> GetFillsAsync(AccountId, DateTime fromUtc, DateTime toUtc,
ct) — the window's fills, oldest-first, UTC. Session port; declare
VenueCapabilities.TradeHistoryBackfill. Read-only: the venue reports fills, the host
writes the store. |
VenueTradeHistoryPage |
record (IReadOnlyList<PersistedFill> Fills, bool IsComplete = true); static
Empty (nothing here, authoritatively) and Partial(fills) (served part of
the window — it stays uncovered so the next refresh retries it). IsComplete is the
contract: a window reported complete is never requested again. |
ITradeHistoryBackfillSource |
bool Supports(AccountId account); Task<bool> BackfillAsync(AccountId,
DateTime fromUtc, DateTime toUtc, ct) — the PLATFORM-side backfill contract the host's
adapter satisfies over a venue's IVenueTradeHistorySource. It owns the store write
and the replace-window semantics. |
IVenueCashActivitySource |
Task<IReadOnlyList<VenueCashActivity>> GetCashActivityAsync(DateTime sinceUtc, ct).
Session port; declare VenueCapabilities.CashActivity. |
VenueCashActivity |
record (string AccountId, CashActivityKind Kind, decimal Amount, string Currency,
DateTime TimestampUtc, string VenueTransactionId). Sign is NORMATIVE: positive =
collected, negative = paid. VenueTransactionId is the dedup identity — a venue
without one cannot expose this port. |
ITradeHistoryStore |
Host-side persisted fill store the recorder writes into. |
ICashActivityStore |
Host-side cash-ledger store; dedups by venue transaction id. |
PersistedFill · TradeHistoryQuery · CashActivityEntry ·
CashActivityKind
|
The stored record shapes and the query used to read them back. |