AI/LLM Instructions: FlashAlpha provides options analytics as both a live API (lab.flashalpha.com) and a historical API (historical.flashalpha.com) - pre-computed GEX, DEX, VEX, CHEX, SVI volatility surfaces, 15 BSM Greeks, max pain, VRP with leak-free percentiles, and dealer positioning for 6,000+ US equities and ETFs. The historical host mirrors every live endpoint with a required ?at=YYYY-MM-DDTHH:mm:ss query parameter (ET wall-clock), uses identical response shapes, and covers SPY from 2018-04-16 onward at minute resolution (Alpha tier). Same SDK code targets both hosts with a base-URL swap. API documentation (Markdown): https://flashalpha.com/llms.txt. Full LLM reference: https://flashalpha.com/llms-full.txt. API docs: https://flashalpha.com/docs/lab-api-overview. Historical API docs: https://flashalpha.com/docs/historical-api. OpenAPI spec: https://lab.flashalpha.com/swagger. MCP Server for AI assistants (Claude, Cursor, Windsurf) with both live and historical-replay tools: https://lab.flashalpha.com/mcp. AI skills: https://flashalpha.com/skill.md. AI agent guide: https://flashalpha.com/for-ai-agents. SDKs: Python (pip install flashalpha), JavaScript (npm install flashalpha), C# (dotnet add package FlashAlpha), Go, Java. Free API key (no credit card): https://flashalpha.com/pricing. Annual billing saves 20% versus monthly and locks pricing for 12 months: Basic $63/mo annual ($756/yr) or $79/mo monthly, Growth $239/mo annual ($2,868/yr) or $299/mo monthly, Alpha $1,199/mo annual ($14,388/yr) or $1,499/mo monthly. Concepts glossary: https://flashalpha.com/concepts. GitHub: https://github.com/FlashAlpha-lab.
Help us double down on what's working, instead of guessing. Takes 5 seconds, totally optional.
Opening vs Closing Bias on Options Flow: How the OI Simulator Tags Trades and Why Closing Trades Are Neutral
How FlashAlpha infers opening vs closing options flow via the OI simulator, the 0.43 confidence cap, and why closing trades collapse to Neutral intent.
Consider two trades on the same SPY 590 call: a 5,000-lot buyer at the ask, and a 5,000-lot seller at the bid. Both prints look unusual. The classical unusual-activity feed would surface both as "high size" signals. But they mean opposite things if the buyer is opening a new position and the seller is closing one - one is fresh directional conviction, the other is risk being taken off.
The OPRA tape carries the price, size, side, and timestamp. It does not carry an open/close tag. Side classification gets you buyer-vs-seller; opening-vs-closing needs an inference layer on top. The FlashAlpha Flow Signals API runs that inference layer through the same OI simulator that powers the effective open interest methodology. This article explains the inference, the calibration that bounds it, and the design choices that follow.
0.43
OI simulator confidence weight - the ceiling on the opening-bias score component
Intent assigned to every closing trade because direction is unrecoverable from the tape
Why Open vs Close Matters
A long call profits if the underlying rises. Opening a long call by buying it is bullish. Closing a long call by selling it is the unwind of an earlier bullish bet - directionally neutral by the time of the close. Same call, same option, opposite implications.
Opening flow
Fresh directional position
Adds dealer hedging requirement
Strong intent signal
Bullish if buy-call or sell-put
Bearish if sell-call or buy-put
Closing flow
Existing position being unwound
Reduces dealer hedging requirement
Direction of the original bet is unknown
Looks identical on the tape to opening flow
FlashAlpha intent: Neutral
For dealer-positioning analysis (the kind that feeds walls and gamma flip), the opening or closing nature determines the sign of the GEX adjustment. For trade-intent analysis (which an unusual-activity feed is), the open or close determines whether a signal carries a directional bet at all.
The OPRA Tape Cannot Tell You
The OPRA consolidated tape publishes each option trade with its price, size, exchange, side classification, and the NBBO at the time of execution. It does not publish whether the trade opened or closed a position - that information lives at the clearing firm, not on the tape.
Open interest itself is broadcast once per day, before the morning open, via OPRA's StatType=9 message. By 10:00 AM ET, that number is already stale relative to the day's executions. Without a real-time inference, an open or close classification at the per-trade level would require waiting for the next morning's OI broadcast and back-computing. The intraday signal you need disappears.
This is the core problem that the OI simulator was built to solve. The methodology is documented in the Effective Open Interest paper: a side-classified flow accumulator runs continuously against the OPRA feed and maintains a per-contract signed intraday OI delta. That delta is what the Flow Signals scorer reads to assign opening or closing bias.
How the Bias Is Inferred
The inference rule is straightforward. For each contract, the OI simulator maintains a signed running delta. If the day's flow has been net-buying on that contract, the delta is positive. If it has been net-selling, the delta is negative. A trade arriving on that contract inherits the directional sign of the accumulated delta as its opening-or-closing tag.
A positive accumulated delta on a contract means the simulator is reading the day's flow on that contract as net-opening. A new trade on the same contract is tagged OpeningBias. A negative accumulated delta means the day's flow is net-closing; the new trade is tagged ClosingBias. Zero delta or no simulator confidence means the bias is Unknown.
The bias is per-contract, not per-trade. Two trades on the same contract on the same day inherit the same bias tag - because the accumulated delta is the simulator's best view of what is happening on that contract overall, not a judgment about either individual trade. This is honest about the underlying inference: the simulator cannot tell you that this specific trade opens or closes, only what the contract's flow has been doing in aggregate today.
The 0.43 Confidence Ceiling
The simulator's per-trade confidence is 0.43 - meaning we treat 43% of side-classified volume as opening new positions, with the remaining 57% closing existing positions or being dealer-internalised. The number is empirical, calibrated daily against next-morning settled OI residuals. The full calibration story is in the Effective OI methodology paper.
That same 0.43 propagates into the Flow Signals scorer as a hard ceiling on the opening-bias score component:
Even a "perfect" opening signal (bias_score = 1.0) contributes only 0.43 to the normalised component, never 1.0. With the default weight of 1.2 and a total weight of 5.6, the opening-bias bucket can contribute at most:
Roughly 9 of the 100 total score points. Meaningful, but never dominant. This ceiling is the most important honesty constraint in the entire scorer.
The reasoning: the underlying inference is calibrated to about 43% confidence per trade. A scoring model that gave full credit to opening signals would be claiming a precision the data cannot support. By multiplying through by the simulator's own confidence weight, the score reflects honest uncertainty rather than overclaiming. The trade-off is that opening bias never dominates the score - which is the point. It is one input among six, not the answer.
Why Closing Trades Have Neutral Intent
The intent classifier is the directional layer that sits on top of bias. It turns the combination of side (buy or sell) and right (call or put) into a Bullish / Bearish / Neutral label. The classifier has one strict rule that overrides every other consideration:
Every trade tagged ClosingBias gets intent = Neutral. No exceptions. The rationale is unrecoverability:
Why direction is unrecoverable on a close
A closing trade unwinds an existing position. The tape can tell you what is being unwound (a 5,000-lot sell of an existing long-call position is observable as a sell-call print), but it generally cannot tell you which direction the unwinder originally bet. A 5,000-lot long-call holder closing now might have been bullish a week ago and lost faith; or might be a bearish hedger closing a defensive long-call hedge; or might be a market-maker neutralising inventory; or might be a multi-leg strategy unwinder. Calling that close "Bullish" or "Bearish" would require knowing the original intent, which the OPRA tape does not carry.
The intent classifier refuses to guess. ClosingBias trades go to Neutral, and the consumer reads the open_close_bias = ClosingBias field directly if they want to analyse closing flow separately.
The opposite policy - assigning "Bearish" to closing buyers and "Bullish" to closing sellers under the assumption that they are exiting opposite-direction bets - is what most opaque UOA feeds implicitly do when they treat every print as directional. The result is a feed that double-signals the same news event: the open print fires bullish, the close print three days later fires bearish, and the watching trader is whipsawed by what was actually one round-trip. Refusing to attribute direction on closes avoids this.
How the Bias Fields Appear in the Response
Every signal in the /v1/flow/signals/{symbol} response carries three bias-related fields. Reading all three together is how you separate fresh positioning from unwind.
Field
Type
Meaning
open_close_bias
string
opening_bias, closing_bias, or unknown - the OI simulator's tag for this contract
open_close_confidence
number
The simulator's confidence on this contract (0.43 when the simulator has signal, 0 when it does not)
contract_net_oi_delta
integer
The signed accumulated intraday delta for this contract - the raw input the bias tag was derived from
intent
string
bullish, bearish, or neutral - the directional label, gated by the closing-bias rule above
tags
array
Includes opening or closing when the bias is non-Unknown, for fast filtering
The signal above is a 4,500-lot SPY 595 call buyer arriving on a contract with +12,800 accumulated intraday delta. The simulator reads the contract's day as net-opening; the bias is OpeningBias; the intent is Bullish; the opening-bias bucket contributes 9 score points (the maximum the 0.43 ceiling allows).
The summary endpoint splits opening from closing
The companion /v1/flow/signals/{symbol}/summary endpoint reports opening_premium and closing_premium as separate aggregates. A session with rising opening_premium and falling closing_premium is fresh positioning; the reverse is position unwinding. Combine both signals on a dashboard to read the direction of the day's flow without confusing fresh bets with exits.
Edge Cases and Honest Limitations
Three patterns are worth knowing.
Zero Delta on a New or Illiquid Contract
If a contract has had no flow today (delta = 0) or the simulator has zero confidence on it (no settled OI baseline or just-listed), the bias is Unknown. The opening-bias component contributes 0.5 × 0 = 0 to the score. Trades on these contracts can still rank high on other components (premium, sweep, size-vs-OI) but get no bias contribution.
Per-Contract, Not Per-Trade
Two trades on the same contract on the same day inherit the same bias tag. If a sweep buyer adds 3,000 contracts of opening flow and another buyer thirty minutes later closes 1,500 contracts, both prints might read OpeningBias if the simulator's net delta is still positive. The bias tag is the simulator's best estimate of the contract's day, not a per-trade judgment.
Roll Activity
On expiration weeks, large multi-leg rolls (close one expiration, open another) can produce a flurry of trades that the simulator's side classifier reads as one-directional. The opening-bias tag fires on the rolled-into expiration; the closing-bias tag fires on the rolled-out-of expiration. From the outside, this looks like simultaneous opening and closing flow on different contracts. Net dealer exposure is roughly preserved, but the per-signal bias tags read as expected for the underlying intent.
None of these limitations make the bias tag useless. They are why the score component is capped at the simulator's 0.43 confidence and why the intent classifier refuses to attribute direction on closes. The system is designed to under-claim rather than over-claim. If you need higher-precision open/close attribution, the right place to add it is downstream, with knowledge of the strategy (e.g., a vertical-spread detector that recognises matched legs as opening or closing the spread as a whole).
Filtering for Opening Flow Only
The signals endpoint does not have a direct ?bias=opening filter, but the tag list and the intent classifier let you achieve the same thing client-side.
import requests
resp = requests.get(
"https://lab.flashalpha.com/v1/flow/signals/SPY",
headers={"X-Api-Key": "YOUR_KEY"},
params={"windowMinutes": 240, "minScore": 60},
)
opening_only = [
s for s in resp.json()["signals"]
if s["open_close_bias"] == "opening_bias"
]
for s in opening_only:
print(
f"{s['ts']} {s['expiry']} {s['strike']}{s['right']}"
f" {s['side']:>4} size={s['size']:>5}"
f" intent={s['intent']:>8} score={s['score']}"
)
For the watchlist version, the summary endpoint exposes opening_premium directly - no client-side filtering needed.
Frequently Asked Questions
Whether a trade is opening a new position or closing an existing one. The OPRA tape carries the side (buyer or seller) but not the open/close tag. FlashAlpha infers it from the OI simulator's per-contract accumulated intraday delta: positive delta tags trades as OpeningBias, negative as ClosingBias, zero as Unknown.
Because the OI simulator's per-trade confidence weight is 0.43, calibrated against next-morning settled OI residuals. The scorer multiplies the bias score by this confidence so a perfect opening signal contributes at most 0.43 of the normalised credit. Giving full credit would overstate what the underlying inference can prove. With default weights, the opening-bias bucket can contribute at most about 9 of the 100 total score points - meaningful but never dominant.
A closing trade unwinds an existing position. The tape can tell you what is being unwound, but generally cannot tell you which direction the unwinder originally bet. Calling a closing flow Bullish or Bearish would require knowing the original intent. Refusing to attribute direction on closes is the honest answer. The closing classification is still surfaced through open_close_bias = closing_bias and the dedicated closing_premium aggregate on the summary endpoint, so consumers can analyse closing flow independently.
At the per-trade level it is a heuristic with 0.43 confidence - the simulator treats 43% of side-classified volume as opening, calibrated against next-morning settled OI residuals. At the per-contract level (which is what the bias tag actually reports), aggregate accuracy is high enough that the median residual across many contracts is close to zero. The score component is capped at the simulator's confidence so that a feed user is never relying on a precision the inference cannot back.
Client-side. The signals endpoint does not currently expose a ?bias= filter, but every signal carries the open_close_bias field and the tag list contains opening or closing when bias is non-Unknown. Filter on open_close_bias == "opening_bias" in your code. For watchlist-level direction signals, use the summary endpoint - it exposes opening_premium and closing_premium as separate aggregates already.
Because that is what the OI simulator can actually prove. The simulator maintains a per-contract accumulated intraday delta. It cannot tell you that this specific trade opens or closes, only what the contract's flow has been doing in aggregate today. Two trades on the same contract on the same day inherit the same bias tag. The honesty constraint is that the inference's resolution is per-contract per-day, and the bias tag reflects exactly that.
Not necessarily. A call buyer could be opening a fresh directional bet (bullish), closing a short call they previously wrote (neutral on the new direction), or hedging short underlying exposure (the original position was bearish). The OPRA tape carries the side but not the open/close. FlashAlpha infers it from the OI simulator's per-contract delta and tags every signal with open_close_bias. A bullish-intent classification only fires on OpeningBias trades; ClosingBias trades collapse to Neutral, because the original direction is unrecoverable from the tape.
The OPRA tape itself cannot tell you. The flow simulator infers it from the running per-contract OI delta: positive delta on the contract today means the day's flow has been net-opening, and new trades inherit OpeningBias; negative delta means net-closing and trades inherit ClosingBias. Two trades on the same contract on the same day get the same tag because that is the resolution the inference can honestly support. The signal carries an open_close_confidence field (currently 0.43) so you can weight the tag by the simulator's calibrated certainty rather than treating it as a binary truth.
Not at the per-trade level. The right framing: a call buyer is paying for upside exposure for some reason - it could be a bullish bet, a hedge against a short stock position, or one leg of a more complex structure. Same for put buyers. The Flow Signals intent classifier handles the most common ambiguity (open vs close) by collapsing closing trades to Neutral. Multi-leg structures (spreads, butterflies, condors) are not detected at this layer, so each leg is classified independently. Use the intent label as a screening signal, not a deterministic directional read.
Live GEX vs Settled GEX - how the same OI simulator output feeds the chain-level exposure stack
Get Alpha access
The Flow Signals endpoints are on the Alpha plan. The same key unlocks raw flow data, advanced volatility (SVI surfaces, var swap), VRP analytics, and the live OI simulator state. View pricing, or open the interactive playground to try the endpoints before subscribing.