Venue seam

Reference

Venue seam

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.