Options levels

Build something

Options levels

Consume vendor gamma / options-levels snapshots from SabrTrader.Pipeline.Levels — named walls, HVL, expected-move bands and optional per-strike exposure profiles. Feeds publish immutable snapshots by reference swap; reads are lock-free on any thread, including the chart render thread.

Resolving a feed

The host installs an ILevelsRegistry via LevelsAmbient.SetRegistry. Plugin code resolves the feed that owns an instrument, then tracks the vendor symbol:

ConsumeLevels.csusing SabrTrader.Pipeline.Levels;

var registry = LevelsAmbient.Registry
    ?? throw new InvalidOperationException("No levels registry installed.");

var feed = registry.ResolveFeed(instrumentId);
if (feed is null) return;

var vendorSymbol = feed.MapInstrument(instrumentId) ?? instrumentId;
feed.Track(vendorSymbol);

feed.SnapshotChanged += symbol =>
{
    var snap = feed.GetSnapshot(symbol);
    if (snap is null) return;
    // Re-read and schedule your own repaint / recompute — keep this handler cheap.
};

Reading a snapshot

GammaLevelSnapshot.cspublic sealed class GammaLevelSnapshot
{
    public required string Symbol { get; init; }
    public required string ProviderKey { get; init; }
    public required DateOnly SessionDate { get; init; }
    public required DateTimeOffset AsOfUtc { get; init; }
    public required IReadOnlyList<GammaLevel> Levels { get; init; }
    public GammaScalars? Scalars { get; init; }
    public double? UnderlyingPrice { get; init; }
}

public readonly record struct GammaLevel(
    GammaLevelType Type, double Price, int Rank, string? Label, string? VendorTag);

GammaLevelType covers call/put walls, HVL, 0DTE walls, GEX, expected-move high/low, blind spots, swing / gamma-scalp levels, and VendorSpecific. GammaScalars carries optional regime / IV / net GEX / DEX / put-call ratio.

Capabilities

[Flags]
public enum LevelsCapabilities
{
    None = 0,
    NamedLevels = 1,
    FuturesNative = 2,
    Intraday = 4,
    History = 8,
    StrikeProfile = 16,
    ExpirySelection = 32,
}

Gate optional behaviour on these flags. History uses GetSnapshot(symbol, sessionDate) within HistoryDays. Strike profiles are exposed via the optional ILevelsStrikeProfile interface on the same feed instance.

Choosing expirations

A gamma level is a whole options board collapsed to one price, and WHICH boards go into that collapse changes the answer completely: a full-chain call wall is dominated by monthly open interest, while a same-day one sits close to spot. Implement ILevelsExpirySelection and advertise ExpirySelection when your vendor can compute its levels from a chosen subset of expirations.

// Consumer side: declare what you want, hold it, read it lock-free.
using var hold = feed.Track("NDX", ExpirySelection.ZeroDte);
var snapshot = feed.GetSnapshot("NDX", ExpirySelection.ZeroDte);

// Label from what came BACK, never from what you asked for.
string prefix = snapshot.Expiry.Kind == ExpirySelectionKind.WithinDays && snapshot.Expiry.Days == 0
    ? "0DTE " : "";

Three rules make this safe. Call ExpirySelection.Resolve rather than deciding for yourself what "0 DTE" means, so every vendor answers identically. Stamp GammaLevelSnapshot.Expiry with what you ACTUALLY produced, because a vendor that cannot slice reports VendorDefault and its full-chain wall must never appear under a "0DTE" label. And do the work inside Track, keeping it warm until the handle is disposed, so both GetSnapshot overloads stay lock-free for the chart render thread.

A selection you cannot satisfy publishes an EMPTY level set that still states itself. Never substitute a neighbouring board. Full signatures on the reference page.

Full type reference

Every public type in SabrTrader.Pipeline.Levels is listed on the Options levels reference page — feeds, registry, ambient, settings schema for custom sources, and strike-profile snapshots.