Add option chain selection helpers - #9783
Open
jhonabreul wants to merge 6 commits into
Open
Conversation
jhonabreul
force-pushed
the
feature-option-chain-pickers
branch
3 times, most recently
from
September 9, 2026 20:24
0abb215 to
79bb448
Compare
Single contract pickers and views on OptionChain, null-safe instead of raising: - select() and its synonym pick(): best match by right, target/min/max days to expiration and one of moneyness, strike_from_atm or target_delta - closest_expiry(), at(expiry), at_the_money(), calls, puts, expiries and strike_prices (StrikeList with closest_to, first_above, first_below) - days_to_expiry on contracts, counted to the last trading date for options Expirations and days to expiration follow the last trading date, so Saturday expiring equity options before February 2015 match their Friday.
…exer set Calls, Puts, StrikePrices and Expiries are computed once per contract count and returned as read-only views, since slice chains are filled in as data arrives. DataDictionary's indexer setter now clears its cached keys and values like Add() does, otherwise Values kept returning the list from before the set.
StrikeTarget carries the one strike criterion of OptionChain.Select and Pick, at the money, moneyness, distance from ATM or delta, so the criteria can no longer conflict and the selection math is testable on its own. Shorter doc comments on the selection helpers, StrikeList and days to expiry.
One method per strike criterion instead of a target type: Select and Pick take the moneyness, SelectByStrikeDistance the distance from the underlying price and SelectByDelta the target delta, all sharing the right and expiration narrowing.
StrikeList is a read only collection whose closest, first above and first below lookups binary search the sorted strikes. ClosestExpiry reads the cached expiry view and Select the distinct expiries of its candidates, both searched by days to expiration for the window bounds and the target.
The chain pickers, at() and days_to_expiry use the contract's listed date, matching the shared filters. Counting Saturday and holiday expiries on their last trading day moves to its own change.
jhonabreul
force-pushed
the
feature-option-chain-pickers
branch
from
September 9, 2026 21:25
79bb448 to
3007d54
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Builds on the chain filters from #9779, now merged, for
OptionChainFilterUniverse.Single contract pickers and views on
OptionChain, so the usual sorted-comprehension selection becomes one call and returnsNoneinstead of raising when nothing matches:select/pick(synonym): by right, days to expiration window and moneyness;select_by_strike_distanceandselect_by_deltatake the strike criterion the universe strategy filters and delta targeting use.closest_expiry,at(expiry),at_the_money(right): expiry pickers that compose with the Share the option universe filters with OptionChain #9779 filters, e.g.chain.at(expiry).puts_only().strikes(-2, 0).calls,puts,expiries,strike_prices: cached, read-only views.StrikePricesis aStrikeListwithclosest_to,first_aboveandfirst_below, binary searched over the sorted strikes.days_to_expiryon contracts.Design notes
selecttakes a target and picks the closest expiry inside an optional[min_dte, max_dte]window. Both semantics are documented side by side.IReadOnlyList, so repeated reads cannot be mutated.ScaledStrikewith the underlying price, so index options with a strike multiplier work.OptionChain.Selection.cs; the core class and the filters file from Share the option universe filters with OptionChain #9779 are untouched.Bug found and fixed along the way
DataDictionary's indexer setter cleared its cached sorted items but not its cachedKeysandValueslists, so afterchain.Contracts[symbol] = contracttheValuescollection was stale.Add()cleared all three. The setter now does the same;DataDictionaryTestscovers it.Related Issue
N/A
Motivation and Context
Option algorithms keep re-deriving the same picks from a chain: the expiry nearest a target, the same-expiry subset, the strike nearest the spot or a delta. Hand-rolled versions crash on empty
min()and pick 0-DTE contracts by accident. One null-safe call each removes that.Requires Documentation Change
Yes: the new
OptionChainmembers,StrikeListanddays_to_expiry.How Has This Been Tested?
OptionChainSelectionTests(30 test methods): each helper against a synthetic chain built with the universe serializer: expiry windows and ties, moneyness, strike distance and delta targeting, sign-insensitive delta, contracts without greeks, null-safety on empty chains and missing underlying price, view caching and invalidation, read-only strike list, and Python access through pythonnet.DataDictionaryTests: the indexer setter refreshes the cached keys and values.OptionChainSelectionHelpersRegressionAlgorithm(C# and Python): every helper against the hand-rolled equivalent on real GOOG data, then trades the pick from the slice chain.LiveTradingDataFeedTests.HandlesAllTypescase that passes alone; the later commits reran the option fixtures.Types of changes
Checklist:
bug-<issue#>-<description>orfeature-<issue#>-<description>