Table of Contents

Class OptionRequestGuard

Namespace
ATAS.DataFeedsCore
Assembly
ATAS.DataFeedsCore.dll

Connector-level limit on option requests that come past the budgeted options API.

The options API (OptionsSubscriptionService behind IOptionsDataProvider and the Options Board, PLAT-5011) budgets its own subscriptions and lookups per connector and marks its connector calls with EnterBudgetedScope(). Everything else that reaches a connector for options - a chart or DOM opened on an option, or a third-party indicator that took the connector itself instead of the provider - is a direct caller. Direct callers get a small allowance meant for a person opening option charts, not for a program walking a whole option chain: at most MaxDirectOptions options held at once (an option shared with the options API counts too), a token bucket for the subscribe requests they send to the broker (a subscription restored after a reconnect costs a token too) and one for series/chain lookups. A request over the allowance is refused locally and never reaches the broker. The unattended server hosts (ReconnectOnFirstConnect) are our own infrastructure; the base connector does not consult the guard for them.

The holdings are counted per origin and per subscription type, mirroring the connector's subscription counter: the budgeted and the direct holders of one option are tracked apart, so a direct caller cannot ride on a subscription of the options API and keep it after the API released it. The connector serialises the guard with its own counter (see BaseConnector); the guard's own lock only protects its state.

Background: on 2026-09-28 Rithmic blocked clients of 8.0.15.271 that ran an indicator subscribing ~4 000 option strikes straight through the connector, around the budget of the options API, and re-subscribing all of them after every reconnect.

The scope is a guard against bugs, not a security boundary: indicators run in-process with full trust.

Added in ATAS 8.0.15.

public sealed class OptionRequestGuard
Inheritance
object
OptionRequestGuard
Extension Methods

Constructors

OptionRequestGuard(ILoggerSource, SubscriptionStatistics, TimeProvider)

Creates the guard of one connector.

public OptionRequestGuard(ILoggerSource logger, SubscriptionStatistics statistics, TimeProvider timeProvider)

Parameters

logger ILoggerSource

Log source for refusal reports.

statistics SubscriptionStatistics

Statistics that count refused subscriptions and lookups.

timeProvider TimeProvider

Time source of the rate limits and the report period.

Exceptions

ArgumentNullException

An argument is null.

Fields

DirectLookupBurst

Largest burst of direct option series/chain lookups per connector.

public const int DirectLookupBurst = 10

Field Value

int

DirectLookupRefillPerSecond

Sustained direct option series/chain lookups per second per connector (two per minute).

public const double DirectLookupRefillPerSecond = 0.03333333333333333

Field Value

double

DirectSubscribeBurst

Largest burst of direct option subscribe requests per connector.

public const int DirectSubscribeBurst = 200

Field Value

int

DirectSubscribeRefillPerSecond

Sustained direct option subscribe requests per second per connector (30 per minute).

public const double DirectSubscribeRefillPerSecond = 0.5

Field Value

double

MaxDirectOptions

Options a direct caller may hold subscribed at once per connector.

public const int MaxDirectOptions = 200

Field Value

int

Properties

DirectOptions

Options held by direct callers at the moment.

public int DirectOptions { get; }

Property Value

int

IsBudgeted

The calls of the current thread are budgeted by their caller and pass unlimited.

public static bool IsBudgeted { get; }

Property Value

bool

Methods

EnterBudgetedScope()

Marks the option connector calls of the current thread as already budgeted by the caller until the returned scope is disposed. Only for code that keeps its own per-connector budget (the options API) or whose volume is bounded by the account (position subscriptions). The scope must be entered and disposed on the same thread around the synchronous part of the call, for subscribes and unsubscribes alike.

public static OptionRequestGuard.BudgetedScope EnterBudgetedScope()

Returns

OptionRequestGuard.BudgetedScope

Release(Security)

The option has no active subscription left at the connector: every holding of it is forgotten and a direct place is given back.

public void Release(Security option)

Parameters

option Security

Remove(Security, SubscriptionType)

The current caller unsubscribed the option from the types. The holding is taken from the caller's origin; types the origin does not hold are taken from the other one (a caller that subscribed and unsubscribes under different scopes).

public void Remove(Security option, SubscriptionType subscriptionTypes)

Parameters

option Security
subscriptionTypes SubscriptionType

RemoveRejected(Security, SubscriptionType)

The broker rejected the registration of the types, reported on whatever thread: the holding is taken from the budgeted side first. When the options API and a direct caller share the option, the rejected request is the options API's more often than not, and a direct place is never given back on a guess.

public void RemoveRejected(Security option, SubscriptionType subscriptionTypes)

Parameters

option Security
subscriptionTypes SubscriptionType

TryAdmitLookup(string, out Exception?)

Decides whether an option series or chain lookup may reach the broker.

public bool TryAdmitLookup(string request, out Exception? error)

Parameters

request string
error Exception

Returns

bool

TryAdmitResubscribe(Security, SubscriptionType, out Exception?)

Decides whether an option still counted as subscribed after a reconnect may be searched and subscribed at the broker again. An option held only inside budgeted scopes passes; an option a direct caller holds costs a direct token. A refused option is forgotten: the connector drops its subscription.

public bool TryAdmitResubscribe(Security option, SubscriptionType countedTypes, out Exception? error)

Parameters

option Security

The option.

countedTypes SubscriptionType

The types the connector counts for the option; recorded as a direct holding when the guard does not know the option.

error Exception

The reason of a refusal.

Returns

bool

TryAdmitSubscribe(Security, SubscriptionType, bool, out Exception?)

Decides whether the current caller may subscribe the option to the types and, when it may, records the holding under the caller's origin.

public bool TryAdmitSubscribe(Security option, SubscriptionType subscriptionTypes, bool sendsRequest, out Exception? error)

Parameters

option Security

The option.

subscriptionTypes SubscriptionType

The types the caller subscribes to.

sendsRequest bool

The subscription sends a request to the broker (it adds a type nobody holds yet and the connector is connected); only such a subscription costs a token.

error Exception

The reason of a refusal.

Returns

bool