Live GEX vs Settled GEX: Why Intraday Dealer Positioning Differs From the Morning Print | FlashAlpha

Live GEX vs Settled GEX: Why Intraday Dealer Positioning Differs From the Morning Print

Why FlashAlpha returns two GEX numbers for the same symbol. Settled GEX is computed from the morning-broadcast OPRA OI and is stable all session. Live GEX adds an intraday flow simulator estimate at 0.43 confidence. The two surfaces are independent: /v1/exposure/* is never modified by /v1/flow/*. Full explainer of effective OI, the simulator state table, and the flow_direction enum.

T
Tomasz Dobrowolski Quant Engineer
May 15, 2026
31 min read
GammaExposure DealerPositioning API OptionsFlow IntradayData DeveloperGuide

If you are searching for "does GEX update during the day", "settled OI vs live OI", "why does the FlashAlpha API return two different gamma numbers", or wondering whether the morning gamma print is stale by lunchtime, this is the canonical explainer. The short answer: both numbers are correct, they answer different questions, and they come from two surfaces that never modify each other.


Two Different Questions, Two Different Numbers

Dealer positioning analytics rests on one input: how many contracts are open at each strike, and who holds them. The instant you pick which open interest (OI) figure to feed the gamma math, you have implicitly chosen which question you are answering.

  1. "What is dealer positioning right now according to the books?" Answered by /v1/exposure/*. These endpoints compute against the settled OI broadcast every morning - the same value the OPRA tape reports. It does not move during the session.
  2. "What would dealer positioning look like if today's flow really did add or remove the positions the model thinks it did?" Answered by /v1/flow/*. These endpoints compute against effective OI: the settled value plus an intraday simulator estimate of position change driven by today's option flow.

Both are legitimate. A backtest that needs to match what was knowable at the open uses settled. A live dashboard that wants to react to today's order flow before tomorrow's OI print uses effective. The mistake is assuming there should only be one number.

Settled OI: The Morning Print That Does Not Move

Settled OI is the official open interest figure computed overnight by the clearing process and broadcast in the morning. It is the same number the OPRA tape reports for each contract. FlashAlpha's /v1/exposure/* endpoints compute gamma, delta, vanna, and charm exposure against this settled value, so the settled GEX you read at 9:45 AM is the same settled GEX you read at 3:30 PM. It is stable through the entire session by construction.

This stability is a feature, not staleness. End-of-day reconciliation, backtest parity, and any analysis that must agree with the official tape all depend on the OI not drifting intraday. When a developer says "the morning gamma print looks stale by noon", what they usually mean is "I expected it to react to today's flow." It does not - that is what the flow surface is for.

Effective OI: Settled Plus an Intraday Flow Estimate

The flow surface starts from the exact same settled OI, then adds an intraday simulator estimate of how many contracts today's flow has opened or closed. The simulator side-classifies trade volume into buys and sells, then applies a confidence weight (currently 0.43) to estimate how many contracts were actually opened versus merely traded between existing holders.

Per contract, the simulator tracks the following state. This is the chain you should internalize:

FieldMeaningStability
official_oiLast OPRA settled OI. The morning-broadcast value, identical to what /v1/exposure/* uses.Stable all session
intraday_oi_deltaSigned estimate of contracts opened (positive) or closed (negative) today, derived from side-classified flow.Updates intraday
oi_delta_confidence0.43 - the fraction of side-classified volume assumed to open new positions rather than reshuffle existing ones.Model constant
simulated_oiofficial_oi + intraday_oi_delta. Unclamped: it may go negative if the model overshoots on a heavy-close contract. Diagnostic only.Updates intraday
effective_oimax(0, simulated_oi). The analytics-safe input actually fed into GEX, DEX, and wall computation on the flow surface.Updates intraday

Read it top to bottom: start from the settled value, apply a confidence-weighted estimate of today's opening flow to get an unclamped simulated value, then floor it at zero so the analytics never see a negative position count. The simulated_oi field is exposed for diagnostics precisely so you can see when the model overshot; effective_oi is what the gamma math consumes.

The Two Surfaces Are Independent

This is the single most important reassurance in this article: nothing under /v1/flow/* changes anything under /v1/exposure/*. FlashAlpha does not modify, overwrite, or "correct" the OPRA OI number. The settled surface is computed from official_oi and is mathematically untouched by the simulator. You can call the flow endpoints all day long and your exposure numbers will not move because of it.

The field names are deliberately disambiguated so you can never accidentally mix them in code:

Settled surface (/v1/exposure/*)Flow surface (/v1/flow/*)
gexlive_gex
net_gexlive_net_gex
Computed from official_oiComputed from effective_oi

If you see live_gex in a payload, you are looking at the flow surface. If you see gex or net_gex, you are looking at the settled surface. There is no shared mutable state between them.

One nuance: the exact flow-side field name is endpoint-specific, not interchangeable. The aggregate /v1/flow/summary/{symbol} returns live_gex (net dealer gamma on effective OI), whereas /v1/flow/gex/{symbol} returns live_net_gex (alongside live_net_gex_label and live_gamma_flip, plus per-strike call_oi/put_oi on effective OI). The settled mirrors are gex and net_gex respectively. So read for the field the endpoint you called actually returns: live_gex from /v1/flow/summary, live_net_gex from /v1/flow/gex.

Settled GEX and live flow GEX, side by side, for 6,000+ symbols

Settled GEX and levels start on Free; the flow surface is Growth and above.

Get API Access

Calling Both and Diffing Them

The clearest way to internalize the distinction is to call both surfaces for the same symbol and look at the gap. Here is a minimal example that pulls settled GEX from /v1/exposure/gex/SPY and the live flow picture from /v1/flow/summary/SPY, then prints the difference.

import requests

BASE = "https://lab.flashalpha.com"
HEADERS = {"X-Api-Key": "YOUR_KEY"}

# Settled surface - computed from morning-broadcast OPRA OI
settled = requests.get(f"{BASE}/v1/exposure/gex/SPY", headers=HEADERS).json()
settled_net_gex = settled["net_gex"]

# Flow surface - computed from effective OI (settled + simulator delta)
flow = requests.get(f"{BASE}/v1/flow/summary/SPY", headers=HEADERS).json()
live_gex = flow["live_gex"]

print(f"Settled net GEX:        {settled_net_gex:,}")
print(f"Live (flow) net GEX:    {live_gex:,}")
print(f"Flow direction:         {flow['flow_direction']}")
print(f"Intraday OI delta:      {flow['intraday_oi_delta']:+,} contracts")
print(f"GEX pct shift:          {flow['flow_gex_pct_shift']}")

# The settled number did not move because we called the flow endpoint.
# These two surfaces are independent by design.
const BASE = 'https://lab.flashalpha.com';
const headers = { 'X-Api-Key': 'YOUR_KEY' };

// Settled surface - morning-broadcast OPRA OI
const settled = await (await fetch(`${BASE}/v1/exposure/gex/SPY`, { headers })).json();

// Flow surface - effective OI (settled + simulator delta)
const flow = await (await fetch(`${BASE}/v1/flow/summary/SPY`, { headers })).json();

console.log(`Settled net GEX:     ${settled.net_gex}`);
console.log(`Live (flow) net GEX: ${flow.live_gex}`);
console.log(`Flow direction:      ${flow.flow_direction}`);
console.log(`Intraday OI delta:   ${flow.intraday_oi_delta}`);
console.log(`GEX pct shift:       ${flow.flow_gex_pct_shift}`);
using System.Net.Http;
using System.Net.Http.Headers;

var http = new HttpClient { BaseAddress = new Uri("https://lab.flashalpha.com") };
http.DefaultRequestHeaders.Add("X-Api-Key", "YOUR_KEY");

// Settled surface - morning-broadcast OPRA OI
var settled = await http.GetStringAsync("/v1/exposure/gex/SPY");

// Flow surface - effective OI (settled + simulator delta)
var flow = await http.GetStringAsync("/v1/flow/summary/SPY");

Console.WriteLine($"Settled GEX payload: {settled}");
Console.WriteLine($"Flow summary payload: {flow}");
// Parse with System.Text.Json: settled.net_gex vs flow.live_gex
package main

import (
    "encoding/json"
    "fmt"
    "net/http"
)

func get(path string) map[string]any {
    req, _ := http.NewRequest("GET", "https://lab.flashalpha.com"+path, nil)
    req.Header.Set("X-Api-Key", "YOUR_KEY")
    resp, _ := http.DefaultClient.Do(req)
    defer resp.Body.Close()
    var out map[string]any
    json.NewDecoder(resp.Body).Decode(&out)
    return out
}

func main() {
    settled := get("/v1/exposure/gex/SPY") // morning-broadcast OPRA OI
    flow := get("/v1/flow/summary/SPY")    // effective OI

    fmt.Printf("Settled net GEX:     %v\n", settled["net_gex"])
    fmt.Printf("Live (flow) net GEX: %v\n", flow["live_gex"])
    fmt.Printf("Flow direction:      %v\n", flow["flow_direction"])
}
# Settled surface - stable all session
curl -H "X-Api-Key: YOUR_KEY" \
  "https://lab.flashalpha.com/v1/exposure/gex/SPY"

# Flow surface - effective OI, updates intraday
curl -H "X-Api-Key: YOUR_KEY" \
  "https://lab.flashalpha.com/v1/flow/summary/SPY"
$ Settled never moves because you called flow. Field names (net_gex vs live_gex) keep them separate.

A representative /v1/flow/summary/SPY response looks like this. The values below are an illustrative API-shape sample, not live market data:

{
  "symbol": "SPY",
  "as_of": "2026-05-15T16:30:45Z",
  "underlying_price": 597.50,
  "expiry": "2026-05-15",
  "flow_direction": "amplifying",
  "intraday_oi_delta": 12450,
  "contracts_with_flow": 1842,
  "contracts_total": 4586,
  "live_gex": 12500000000,
  "flow_gex_pct_shift": 0.067
}

Note the field is live_gex, not gex. The settled /v1/exposure/gex/SPY response for the same instant carries net_gex and is computed entirely from official_oi - it would be unchanged whether or not you ever called the flow endpoint.

The flow_direction Enum

The /v1/flow/summary and /v1/flow/dealer-risk endpoints return a flow_direction classification that summarizes what today's flow is doing to the dealer gamma regime. The five values:

ValueMeaning
no_flowZero per-contract movement on every contract (contracts_with_flow is 0). Distinct from neutral - there is literally nothing to simulate.
neutralFlow exists, but the resulting net GEX shift is under the 5% threshold. Movement is present but immaterial.
amplifyingNet GEX kept the same sign and its magnitude grew. Today's flow is making dealers more exposed in the existing regime.
dampeningNet GEX kept the same sign but its magnitude shrank. Positions are resolving and the regime is weakening.
regime_flipNet GEX changed sign (positive to negative gamma or the reverse), or a regime was created from a zero baseline.

The distinction between no_flow and neutral matters in code: no_flow means the simulator had no input at all, while neutral means it ran but the effect was below the materiality threshold. Treat them differently in alerting logic.

When flow_gex_pct_shift Is null

The flow_gex_pct_shift field expresses the live GEX move as a fraction of the settled GEX. Because it is a ratio against the settled value, there is an edge case where it is mathematically undefined:

  • null - settled GEX is zero but live GEX is nonzero. The flow simulator has created a gamma regime from no baseline, so "percent shift relative to settled" has no denominator. This pairs with flow_direction: "regime_flip" (regime created from zero).
  • 0 - both settled GEX and live GEX are zero. There is no regime and no shift, so the shift is exactly zero rather than undefined.
  • A finite number (for example 0.067 in the sample above) - both values are nonzero and the ratio is well defined.

Handle null explicitly. Treating it as zero will mask exactly the scenario you most want to detect: a fresh regime forming from flow with no prior settled baseline.

Filtering by Expiry

The simulation-aware Flow Analytics endpoints - /v1/flow/{levels,pin-risk,summary,gex,dex,dealer-risk,oi,live} - accept an optional ?expiry=YYYY-MM-DD query parameter. When supplied, the chain is filtered to that single expiry before the simulator and gamma math run, so the returned live_gex reflects only that expiry. Omit it to aggregate across all expirations. An invalid date format returns 400 {"error":"invalid_expiry"}; a syntactically valid date with no contracts returns 404. The Raw Flow Data tape endpoints (/v1/flow/options|stocks/* and the cross-symbol leaderboard/outliers routes) do not accept ?expiry; they filter with limit, minSize, minutes, and window parameters instead.

Which Tier Each Surface Needs

The settled exposure surface is tiered three ways: /v1/exposure/{gex,levels} on Free and above, /v1/exposure/{dex,vex,chex} on Basic and above, and /v1/exposure/{summary,narrative} on Growth and above. The flow surface is gated separately:

Endpoint groupTier
/v1/flow/{levels,pin-risk,summary,gex,dex,dealer-risk}Growth and above
/v1/flow/{oi,live} and raw /v1/flow/options|stocks/*Alpha and above

Pricing for reference: Free $0 (5 req/day), Basic from $63/mo (100/day), Growth from $239/mo (2,500/day), Alpha from $1,199/mo (unlimited).

Frequently Asked Questions

Effective OI is max(0, official_oi + intraday_oi_delta). It starts from the morning-broadcast settled OI, adds the intraday simulator's signed estimate of contracts opened or closed today, then floors the result at zero so the analytics never see a negative position count. It is the input the /v1/flow/* endpoints feed into their GEX, DEX, and wall computations. The settled /v1/exposure/* endpoints do not use it.
Settled GEX is computed from the morning-broadcast OPRA open interest, which is stable all session. Live GEX is computed from effective OI: the same settled value plus an intraday simulator estimate of position change driven by today's flow. They differ by exactly the gamma impact of the simulator's estimated intraday OI change. Neither is wrong; they answer different questions.
No. The settled OPRA open interest is never modified. It is stored as official_oi and the /v1/exposure/* surface computes against it untouched. The flow simulator produces a separate intraday_oi_delta and effective_oi used only by /v1/flow/*. The two surfaces share no mutable state.
It is oi_delta_confidence, the fraction of side-classified buy/sell volume the simulator assumes opens new positions rather than reshuffling contracts between existing holders. Not every traded contract changes open interest, so the raw volume is scaled by 0.43 before becoming intraday_oi_delta. It is a model constant, not a per-symbol value.
No. The /v1/exposure/* output is computed entirely from settled official_oi and is never modified by anything under /v1/flow/*. Calling the flow endpoints, in any order or frequency, has zero effect on your exposure numbers. The field names (net_gex vs live_net_gex) keep the two surfaces unambiguous in client code.
It is null when settled GEX is zero but live GEX is nonzero - the flow simulator created a regime from no baseline, so a percent shift relative to settled has no denominator. It is 0 when both settled and live GEX are zero. It is a finite number when both are nonzero. Handle null explicitly rather than coercing it to zero.
Both describe same-sign net GEX. amplifying means the magnitude grew - today's flow is making dealers more exposed in the existing gamma regime. dampening means the magnitude shrank - positions are resolving and the regime is weakening. A sign change instead returns regime_flip, and a sub-threshold move returns neutral.

Live Market Pulse

Get tick-by-tick visibility into market shifts with full-chain analytics streaming in real time.

Intelligent Screening

Screen millions of option pairs per second using your custom EV rules, filters, and setups.

Execution-Ready

Instantly send structured orders to Interactive Brokers right from your scan results.

Join the Community

Discord

Engage in real time conversations with us!

Twitter / X

Follow us for real-time updates and insights!

GitHub

Explore our open-source SDK, examples, and analytics resources!