equity-options
Skill268 starsChanged 48 days agoApache-2.0View on GitHub
Use when an algorithm trades options on a SINGLE named underlying Equity — subscribing (`AddOption` vs `AddOptionContract`), reading the chain (the slice's `OptionChains` vs the `OptionChain()` method), greeks/IV data freshness, strike/expiry filters, price seeding, and warm-up. Triggers — code calling any of those four APIs; questions like "why are my deltas/IV stale", "why can't I trade the contract I just added", "why is the chain empty", "which API gives decision-time greeks". Skip when — options on a DYNAMIC equity universe (see chained-universes-options), historical/backfilled option data for past dates (see historical-data-equity-options), or multi-leg order placement and assignment/exercise handling (see option-strategies).
In this repository39 other files it gives its agents.
- CLAUDE.mdCLAUDE.md
- docs-styleSkill
- calendarSkill
- code-qualitySkill
- cryptoSkill
- data-exportSkill
- data-issuesSkill
- debug-algorithmSkill
- debug-performanceSkill
- equity-fundamental-dataSkill
- futuresSkill
- historical-data-equity-optionsSkill
- historySkill
- indicatorsSkill
- loggingSkill
- option-strategiesSkill
- ordersSkill
- pricingSkill
- scheduled-eventsSkill
- universesSkill
- calendarSkill
- code-qualitySkill
- cryptoSkill
- data-exportSkill
- data-issuesSkill
- debug-algorithmSkill
- debug-performanceSkill
- equity-fundamental-dataSkill
- equity-optionsSkill
- futuresSkill
- historical-data-equity-optionsSkill
- historySkill
- indicatorsSkill
- loggingSkill
- option-strategiesSkill
- ordersSkill
- pricingSkill
- scheduled-eventsSkill
- universesSkill
The file
We split this skill into the rules it gives an agent
4 rules. About 0 are common, 0 are distinctive, and 4 are very specific to this project.
≈0
Common · estimate
Many files like this have a rule of this kind.
≈0
Distinctive · estimate
This author's own choices. Worth a look.
4
Very specific
Tied to their project's names, files or tools. Probably skip.
- Common
- Distinctive
- Very specific
- Very specific: line 34
Prefer a strategy-shaped filter when one matches the structure — u.IronCondor(30, 5, 10), u.Straddle(30), u.CallSpread(30, 5), and friends …
- Very specific: line 51
Default filter: if you never call SetFilter: standards + weeklys, within 1 strike of the underlying price, expiring within 35 days — almost …
- Very specific: line 103
Forgetting
IncludeWeeklys(): when a spec's DTE window (e.g. - Very specific: line 107
Only American-style US equity options are supported.
≈ “Common” is an estimate: at least 1 in 5 of the 350,495 skill files we read have a rule of the same kind, not the same words. “Very specific” is our guess from the words: it names a file, a command, a setting or the project itself.
Files
Equity Options: subscriptions and chain data — QuantConnect / LEAN
Two decisions shape every equity-options algorithm, and each has two answers that look interchangeable but carry different data: how you subscribe (AddOption vs AddOptionContract) and how you read the chain (the slice's OptionChains vs the OptionChain() method). Picking the wrong member of either pair produces algorithms that trade on day-old numbers without any error.
Greeks/IV freshness — the core rule
There are two different option datasets behind the APIs (doc: "There is a daily, pre-calculated dataset based on the end of the previous trading day. There is also a stream of values that are calculated on-the-fly as your algorithm runs."):
| Access path | Data you get |
option.SetFilter(...) filter function (incl. .Delta()/.IV() filters) | "daily, pre-calculated values based on the end of the previous trading day" — not customizable |
OptionChain(symbol) method | same prior-day EOD pre-calculated values; returns all tradable contracts, not just your filter's picks |
History<OptionUniverse>(...) | same prior-day EOD values, one full chain per trading day |
the slice: data.OptionChains (or CurrentSlice.OptionChains) | current values from the Option price model, computed on request against live data — customizable via option.PriceModel |
The operating rule that follows: any intraday decision — entry sizing, delta hedging, IV-threshold checks, strike selection at a decision time — should read the slice's chain. The OptionChain() method is for daily contract discovery (find which contracts exist, filter by prior-day delta/OI, then subscribe); using it for intraday sizing or greeks means every number is one day stale, and nothing errors to tell you. Greeks on slice contracts are computed lazily — accessing Greeks costs nothing; accessing Greeks.Delta triggers the calculation — so only read the greeks you need.
Pick ONE route — and subscribe only what the strategy can trade
Decide the route once, in Initialize. Mixing them is usually a smell:
- Universe route (
AddOption+ filter): a universe's purpose is its slice chain. If all selection, pricing, and sizing happen throughOptionChain()anyway, the minute-resolution subscriptions are pure cost — either read the slice for the decisions that need live data, or drop the universe and subscribe the picks directly. - Discovery route (
OptionChain()+AddOptionContract): the daily chain picks the contracts; subscribe each pick. Match the data to the decision: theOptionChain()rows are previous-close values — fine when daily-granularity data suits the strategy (screening, ranking, a daily-cadence rule that tolerates day-old marks), but when the strategy calls for decision-time values (intraday sizing, hedging, entry marks), read the subscribed picks' live quotes from the slice. Whichever you use, know which one you are using. - A subscription earns its cost by being read or being held: a contract you own needs its subscription (position pricing, fills, expiry processing) even if you never read a chain. What doesn't earn its cost is breadth — a wide
AddOptionuniverse where the algorithm neither reads the slice chain nor holds more than its few picks. OptionChain()needs no option subscription — the underlying's equity subscription is sufficient. Never addAddOption, a filter, orAddUniverseOptionsjust to make a chain available; an empty chain has some other cause.
Size the subscription to the trade, not to the chain:
- Prefer a strategy-shaped filter when one matches the structure —
u.IronCondor(30, 5, 10),u.Straddle(30),u.CallSpread(30, 5), and friends subscribe only the legs the strategy needs. - Otherwise derive the strike span and DTE window from the structure's own numbers (target deltas, wing widths, expiry rules), adding a delta-band filter (
u.Delta(0.05m, 0.30m)) where the structure is delta-targeted. The span should be the tightest one that always contains the tradable candidates — not a safety blanket. Strikes(-100, 100), or an unfilteredExpiration(0, 500)window, subscribes thousands of minute-resolution contracts — a cost bug even when the algorithm is otherwise correct.
Subscription route 1: AddOption — a filtered basket (universe)
For strategies that pick contracts from a chain at decision time (spreads, condors, straddles, rolling structures), subscribe once in Initialize:
UniverseSettings.Asynchronous = true;
var option = AddOption("SPY"); // underlying auto-subscribed RAW
option.SetFilter(u => u.IncludeWeeklys().Strikes(-3, 3).Expiration(15, 60));
_symbol = option.Symbol; // canonical Symbol — save it- The canonical
option.Symbolis not tradable — it is the key intodata.OptionChainsand the first argument of everyOptionStrategiesfactory. - Filter timing: selection "usually runs at the first bar of every day"; a newly selected contract's data arrives "in the next
Slice". So the chain can be absent on any given event — always guard:if (!data.OptionChains.TryGetValue(_symbol, out var chain)) return;. - Default filter if you never call
SetFilter: standards + weeklys, within 1 strike of the underlying price, expiring within 35 days — almost never what a spec wants; set the filter explicitly. - Filter building blocks:
Strikes(min, max)(relative strike counts around the money, not dollars),Expiration(minDays, maxDays),CallsOnly()/PutsOnly(),WeeklysOnly()/StandardsOnly()/IncludeWeeklys(),FrontMonth()/BackMonth(), greek/OI filtersDelta(min, max),IV(min, max),OpenInterest(min, max)(these compare prior-day EOD values — use them for coarse pre-selection, then pick precisely from live slice greeks), and strategy-shaped helpers (u.Straddle(30),u.IronCondor(30, 5, 10)) that narrow the universe to exactly the legs a named strategy needs. - Resolution rule: the option resolution must be ≥ the underlying Equity's resolution (minute equity → minute/hour/daily options). Contract subscriptions support minute, hour, and daily; minute is the default.
Reading the chain at a decision time:
public override void OnData(Slice data)
{
if (!data.OptionChains.TryGetValue(_symbol, out var chain)) return;
var spot = chain.Underlying.Price;
var atmCall = chain.Where(c => c.Right == OptionRight.Call)
.OrderBy(c => Math.Abs(c.Strike - spot)).First();
var delta = atmCall.Greeks.Delta; // live price-model value, computed on request
var mid = (atmCall.BidPrice + atmCall.AskPrice) / 2;
}In a Scheduled Event there is no slice parameter — read the same object through CurrentSlice.OptionChains.
Subscription route 2: AddOptionContract — individual known contracts
For strategies that hold a few specific contracts found by daily screening, discover with the OptionChain() method, then subscribe each pick:
// In a scheduled event — OptionChain() carries PRIOR-DAY EOD greeks: fine for
// discovering contracts, wrong for intraday sizing or hedging.
var chain = OptionChain(_underlying);
var expiry = chain.Min(c => c.Expiry);
var symbol = chain
.Where(c => c.Expiry == expiry && c.Right == OptionRight.Call && c.Greeks.Delta > 0.3m)
.OrderBy(c => c.OpenInterest).Last().Symbol;
AddOptionContract(symbol);The three idioms that must accompany this route:
- Seed prices — a contract subscribed this time step has no data until the next slice ("you'll need to wait until the next
Sliceto receive data and trade the contract"). SetSettings.SeedInitialPrices = true;inInitializeto trade it immediately. - RAW underlying — subscribe the underlying with
AddEquity("SPY", dataNormalizationMode: DataNormalizationMode.Raw)so strike-vs-price comparisons share a scale. If you skip this, LEAN auto-subscribes (or force-switches an existing subscription) to RAW anyway — see the history caveat below. - Volatility warm-up —
SetWarmUpinInitializecannot anticipate contracts added later; warm the underlying's volatility model in a security initializer (feed ~30 daily bars throughsecurity.VolatilityModel.Update(...)) so slice-chain IV/greeks are sane from the first read. On theAddOptionroute the simpleSetWarmUp(31, Resolution.Daily)suffices (default volatility model needs 30+1 daily bars).
To read a subscribed contract from the slice, index the chain with the canonical: data.OptionChains.TryGetValue(_contractSymbol.Canonical, out var chain). RemoveOptionContract(symbol) cancels its open orders and liquidates the position.
The RAW-underlying history caveat
Because any option subscription forces the underlying Equity to RAW normalization, a History() call on that underlying now returns raw closes — dividend gaps included. Any realized-volatility, daily-return, or overnight-gap calculation on an option underlying must request adjusted data explicitly: History(_underlying, 22, Resolution.Daily, dataNormalizationMode: DataNormalizationMode.Adjusted). Do not "fix" this by subscribing the underlying ADJUSTED — LEAN silently switches it back to RAW.
Common mistakes
- Sizing or hedging from
OptionChain()intraday. Its marks and greeks are the previous close; position sizes computed from them are provably off versus decision-time quotes. Decision-time numbers come from the slice's chain. - Trading the canonical symbol, or passing a contract symbol where the canonical is required (chain lookup,
OptionStrategiesfactories). - No
TryGetValueguard — the chain is legitimately absent before the first daily selection and whenever the filter turns over. - Forgetting
IncludeWeeklys()when a spec's DTE window (e.g. 21–45 days, closest to 30) needs weekly expiries to hit its target. - Carrying a wide universe you never read — subscribing a broad chain while doing all selection, pricing, and sizing through
OptionChain(): every subscription beyond the contracts actually held is pure cost. Read the universe's slice chain for the decisions that need live data, or drop the universe and useAddOptionContracton the picks. - Subscribing a huge chain as a tradability crutch (±100 strikes, unbounded expiries) so any discovered contract can be ordered directly — subscribe the picks with
AddOptionContractinstead, and let a strategy-shaped or structure-derived filter keep the universe minimal. - Computing RV/returns on the force-RAW underlying without an explicit adjusted-normalization history request.
- Only American-style US equity options are supported; strikes in the filter API are relative counts, not dollar offsets —
Strikes(-1, 1)means one strike either side of the money.
Does it work?
Reviews from people and from AI agents that ran it: what they used it for, and whether it worked.
Reviews can't be read right now.
Your trail
Files you open will collect here, so you can find them again.
Open two or more, and you can remix the rules you like from each into one list. Kept in this browser only.
Now do this for your own.
Bring your CLAUDE.md, AGENTS.md or skills. agentleFS shows which of your rules are common, which are yours and which only fit one project, and keeps one version your agents read everywhere.

