SDK Reference: Options
Options
The venue-agnostic options surface: the reader seam, chain and contract records,
quotes, snapshots, and symbol and expected-move helpers. The data model lives in
SabrTrader.Pipeline.Contracts, namespace SabrTrader.Pipeline.Options, and
comes with the SDK meta-package. Narrative:
Options data & trading.
On this page
The reader seam
| Type | Members |
|---|---|
IOptionChainReader |
The read-only, venue-agnostic entry point, obtained from a context: bool IsAvailable;
event Action? AvailabilityChanged (any thread; always unsubscribe on dispose);
Task<IReadOnlyList<OptionUnderlying>> SearchUnderlyingsAsync(string query, CancellationToken ct = default);
Task<IOptionChainView?> OpenChainAsync(string underlyingSymbol, CancellationToken ct = default),
null when no connected venue serves the symbol. |
IOptionChainView |
: IDisposable. An open chain bound to the (hidden) venue that resolved it; provider ids
are meaningful only within the same view. string UnderlyingSymbol;
OptionChain Chain (full expiry list plus the venue's default nearest expiries);
Task<OptionChain> GetContractsAsync(IReadOnlyList<DateOnly> expiries, CancellationToken ct = default);
Task<OptionChainSnapshot> GetSnapshotAsync(OptionChainSnapshotRequest? request = null, CancellationToken ct = default);
IDisposable SubscribeQuotes(IReadOnlyList<string> providerInstrumentIds, Action<OptionQuote> onQuote).
Disposing tears down the view's quote subscriptions; the view lives only as long as its venue. |
OptionChainSnapshotRequest |
record; bounds for one snapshot capture, every field optional (null = host default; values are
clamped bounds, not guarantees): IReadOnlyList<DateOnly>? Expiries,
int? MaxExpiries, int? MaxContracts (centered on the money; a near-the-money
floor of about 30 contracts per expiry is kept regardless), double? MinGreekCoverage
(0 to 1), TimeSpan? GreekWaitTimeout, bool TradedContractsOnly (hint: only
contracts that traded today are needed). |
Chain & contract data
| Type | Members |
|---|---|
OptionChain |
record, required init: string UnderlyingSymbol,
string UnderlyingProviderInstrumentId (empty when the venue does not report one),
IReadOnlyList<DateOnly> Expiries (always complete, ascending),
IReadOnlyList<OptionContract> Contracts (only the fetched expiries);
void Validate(). |
OptionContract |
record, required init: string ProviderInstrumentId,
string UnderlyingSymbol, DateOnly Expiry, decimal Strike,
OptionRight Right; init: OptionExerciseStyle ExerciseStyle,
decimal Multiplier (default 100), string? Currency (premium currency),
string? OptionClass (OCC root / trading class, null when the venue does not
distinguish classes), string NativeInstrumentType (empty when the source did not
classify); computed string DisplaySymbol ("AAPL 18DEC26 150 C");
void Validate(). |
OptionRight |
enum: Call, Put. |
OptionExerciseStyle |
enum: Unknown, American, European. |
OptionUnderlying |
record (string UnderlyingId, string Symbol, string Description): one
underlying-search hit. UnderlyingId is the serving venue's id; pass
Symbol to OpenChainAsync. |
Quotes & snapshots
| Type | Members |
|---|---|
OptionQuote |
record; one PARTIAL quote update, where a null field means "unchanged". Required init:
string ProviderInstrumentId; init (all decimal?):
Bid, Ask, Mid, Last, Delta,
Gamma, Theta, Vega, ImpliedVol (a fraction:
0.25 = 25%), Volume, OpenInterest, NetChange,
PercentChange; bool? AccessDenied (true only when the venue explicitly
refused market data for the instrument).
OptionQuote MergedWith(OptionQuote? previous) folds this update onto the last known
quote, keeping every field the update does not carry; static
(decimal? Bid, decimal? Ask) Uncross(decimal? bid, decimal? ask, bool bidIsFresh, bool askIsFresh)
clears the stale side of a crossed pair. |
OptionChainSnapshot |
record, required init: IReadOnlyList<OptionChainSnapshotEntry> Entries,
IReadOnlyList<DateOnly> Expiries, string UnderlyingProviderInstrumentId,
string UnderlyingSymbol; init decimal? UnderlyingPrice (spot at capture
time, when reported). |
OptionChainSnapshotEntry |
record (OptionContract Contract, OptionQuote Quote): a complete point-in-time
reading of one contract. |
OptionUnderlyingAnalytics
The per-underlying analytics record behind the host's options screener and Market Analyzer options
columns: required UnderlyingSymbol, CapturedUtc; optional
UnderlyingPrice, Iv30, IvRankPct, IvPercentilePct,
IvHistorySessions, ExpectedMove30d / ExpectedMove30dPct,
FrontExpiry, ThirtyDayExpiry, TermSlope, Skew25Delta,
AtmSpreadPct, OpenInterest, OptionVolume,
PutCallVolumeRatio, PutCallOpenInterestRatio, VolumeToOpenInterest.
A null field means "not computable from what the venue served". No SDK member returns this record;
compute your own values from a snapshot and
ImpliedMoveMath.
Symbols
| Type | Members |
|---|---|
OccOptionSymbol |
readonly record struct (string Root, DateOnly Expiry, bool IsCall, decimal Strike):
the OCC/OSI concatenated form {root}{yyMMdd}{C|P}{strike×1000, 8 digits}
(e.g. AAPL240119C00190000). string ToSymbol() (also
ToString()); static OccOptionSymbol Parse(string symbol),
bool TryParse(string? symbol, out OccOptionSymbol result) (strict full match, so a plain
equity ticker is never accepted), string? RootOf(string? symbol) (the class from either
the concatenated or the space-padded OSI form; null when neither). |
IndexFutureProxies |
static bool TryCashIndex(string futuresRoot, out string cashIndex): the cash index
whose options are an index future's options (ES/MES → SPX,
NQ/MNQ → NDX, RTY/M2K →
RUT, YM/MYM → DJX). Use it to map a futures chart
to an option board. |
OptionUnderlyingSymbols |
static, namespace SabrTrader.Pipeline.Venues.OptionStrategies:
Root(string?), BareRoot(string?), SameUnderlying(a, b),
MatchesTypedRoot(typedQuery, hitSymbol), PreferTypedRoot(typedQuery, hits).
The underlying-identity rule, so a search for "SPX" resolves to SPX and not to a look-alike. |
Expected move & implied spot
Two pure helpers in SabrTrader.Pipeline.Options, the same arithmetic the platform's
chain window and gamma indicators use. Usage: Expected
move & implied spot.
ImpliedMoveMathpublic static class ImpliedMoveMath
{
public const double DaysPerYear = 365.0; // IV is quoted on CALENDAR days
public const double MeanAbsoluteDeviationRatio = 0.7978845608028654; // sqrt(2/pi)
public const double StraddleShare = 0.85; // expected move / ATM straddle
public static readonly TimeOnly SettlementTimeNewYork; // 16:00
public static DateTime SettlementUtc(DateOnly expiry); // 16:00 New York on that date, in UTC
public static double OneSigma(double spot, double impliedVolatility, double years); // S * sigma * sqrt(T)
public static double OneSigmaFromDays(double spot, double impliedVolatility, double days);
public static double ExpectedMoveFromSigma(double oneSigma);
public static double ExpectedMoveFromStraddle(double atmStraddlePrice);
public static (double High, double Low) Band(double spot, double magnitude); // Low floored at 0
public static double YearsTo(DateOnly expiry, DateOnly today); // whole days
public static double YearsUntil(DateTime expiryUtc, DateTime nowUtc);
public static double YearsUntilExpiry(DateOnly expiry, DateTime nowUtc); // to SettlementUtc(expiry)
}
impliedVolatility is a fraction (0.15 = 15%). Functions return NaN for a
missing or impossible input, so a board with no IV yields no band. The expected move is narrower than a
1σ band because it is the average size of a move (sqrt(2/pi) of the standard deviation),
not its root-mean-square.
ChainImpliedSpotpublic static class ChainImpliedSpot
{
public readonly record struct ParityPoint(DateOnly Expiry, decimal Strike, decimal CallMid, decimal PutMid);
public static decimal? Compute(IReadOnlyList<ParityPoint> points);
}
The underlying price implied by the board, for when no underlying quote is available. Put/call
parity (S ≈ K + C − P) at the nearest expiry and the strike where |C − P| is
smallest; the result is the forward. Returns null without at least one two-sided strike, or when the
best pair's gap is too wide to be a price.
Context access
| Member | Where |
|---|---|
IIndicatorContext.OptionChains |
IOptionChainReader?, null when the host serves no options data. Namespace
SabrTrader.Pipeline.Indicators. |
IStrategyContext.OptionChains / Strategy.OptionChains
|
The same reader from strategy code, plus the strategy-side trading methods
PlaceMultiLegOrderAsync (two overloads), PrecheckMultiLegOrderAsync and
ExerciseOptionAsync. All are default-implemented; unsupported hosts answer through the
result. |
OptionChainReaderAmbient |
static (namespace SabrTrader.Pipeline.Indicators): Reader,
SetReader(reader), IDisposable Use(reader). The host installs the reader
here and the context defaults read it. Plugins use the context member; tests use Use
to scope a fake reader. |
Trading types
The multi-leg order model (MultiLegOrderRequest, OptionLeg,
PositionEffect, NetPriceDirection, MultiLegPlacement,
MultiLegPrecheckResult) and the MultiLegOrders /
ExerciseOptions capability flags live in SabrTrader.Pipeline.Venues.Trading
and are listed in the Trading reference. Usage:
Multi-leg orders & exercise.
Venue SPI
A venue plugin serves option chains by implementing IOptionChainSource (and optionally
IOptionChainSnapshotSource) from SabrTrader.Pipeline.Venues.Options, returning
the records on this page, and declaring its live-quote budget with OptionQuoteCapacity.
That namespace is listed in the
Venue seam reference.