Python SDK for the FlashAlpha Historical API — point-in-time replay of GEX, gamma flip, VRP, narrative, max pain, and the full stock summary at any minute back to 2018-04-16. Backtest options strategies against 6.7B+ option rows.
Project description
flashalpha-historical
Python SDK for the FlashAlpha Historical API — point-in-time replay of every live analytics endpoint. Ask what GEX, gamma flip, VRP, narrative, max pain, or the full stock summary looked like at any minute back to 2018-04-16, in the same response shape as the live API.
Coverage: SPY 2018-04-16 → today, with daily extensions; more symbols added on demand.
pip install flashalpha-historical
Requires Python 3.10+. Same X-Api-Key you use for api.flashalpha.com.
Alpha plan or higher on every endpoint.
Quickstart
from flashalpha_historical import FlashAlphaHistorical
hx = FlashAlphaHistorical("YOUR_API_KEY")
# One snapshot — what dealer positioning looked like during the COVID crash
snap = hx.exposure_summary("SPY", at="2020-03-16T15:30:00")
print(snap["regime"], snap["exposures"]["net_gex"])
# → 'negative_gamma' -2633970601
The at= parameter accepts strings ("2026-03-05T15:30:00" or
"2026-03-05" → defaults to 16:00 ET), datetime objects, or date objects.
Backtesting
The SDK ships with replay utilities that turn any endpoint into an iterator over a date / minute range. Holiday calendar is built in (NYSE 2018-2026); gap days are skipped silently by default.
Daily replay
from flashalpha_historical import FlashAlphaHistorical, Backtester, iter_days
hx = FlashAlphaHistorical("YOUR_API_KEY")
def strategy(at, snap):
"""Short vol when VRP rich AND dealers long gamma."""
vrp = snap["volatility"]["vrp"]
regime = snap["exposure"]["regime"]
return {
"signal": "short_strangle" if vrp > 5 and regime == "positive_gamma" else None,
"vrp": vrp,
"regime": regime,
}
bt = Backtester(hx, method="stock_summary", symbol="SPY")
results = bt.run(iter_days("2024-01-02", "2024-03-29"), strategy)
# Convert to DataFrame
import pandas as pd
df = pd.DataFrame(bt.to_records(results))
Minute-level replay
from flashalpha_historical import iter_minutes, replay
# Walk every 15 minutes through one trading day
for at, snap in replay(hx, "exposure_summary", "SPY",
iter_minutes("2025-01-15", "2025-01-15", step_minutes=15)):
print(at, snap["regime"], snap["gamma_flip"], snap["exposures"]["net_gex"])
Quota note: every call counts against your daily plan quota (shared with the live API). 1-minute replay = 390 calls per analytic per day — coarsen with
step_minutes=15orstep_minutes=30for development loops.
API
Every analytics method takes a required at keyword argument.
Coverage
| Method | Endpoint |
|---|---|
tickers() |
GET /v1/tickers |
tickers(symbol="SPY") |
GET /v1/tickers?symbol=SPY |
Market data
| Method | Endpoint |
|---|---|
stock_quote(ticker, at=...) |
/v1/stockquote/{ticker} |
option_quote(ticker, at=..., expiry=, strike=, type=) |
/v1/optionquote/{ticker} |
surface(symbol, at=...) |
/v1/surface/{symbol} |
Exposure analytics
| Method | Endpoint |
|---|---|
gex(symbol, at=..., expiration=, min_oi=) |
/v1/exposure/gex/{symbol} |
dex(symbol, at=..., expiration=) |
/v1/exposure/dex/{symbol} |
vex(symbol, at=..., expiration=) |
/v1/exposure/vex/{symbol} |
chex(symbol, at=..., expiration=) |
/v1/exposure/chex/{symbol} |
exposure_summary(symbol, at=...) |
/v1/exposure/summary/{symbol} |
exposure_levels(symbol, at=...) |
/v1/exposure/levels/{symbol} |
narrative(symbol, at=...) |
/v1/exposure/narrative/{symbol} |
zero_dte(symbol, at=..., strike_range=) |
/v1/exposure/zero-dte/{symbol} |
Composite & vol
| Method | Endpoint |
|---|---|
stock_summary(symbol, at=...) |
/v1/stock/{symbol}/summary |
volatility(symbol, at=...) |
/v1/volatility/{symbol} |
adv_volatility(symbol, at=...) |
/v1/adv_volatility/{symbol} |
vrp(symbol, at=...) |
/v1/vrp/{symbol} |
max_pain(symbol, at=..., expiration=) |
/v1/maxpain/{symbol} |
Errors
from flashalpha_historical import (
FlashAlphaHistoricalError, # base
AuthenticationError, # 401
TierRestrictedError, # 403 — needs Alpha plan
InvalidAtError, # 400 — bad `at` format
NoDataError, # 404 — outside coverage / inside gap
SymbolNotFoundError, # 404 — symbol not at this `at`
NoCoverageError, # 404 — symbol not in historical dataset
InsufficientDataError, # 404 — surface grid too sparse
RateLimitError, # 429
ServerError, # 5xx
)
try:
hx.exposure_summary("SPY", at="2017-01-01") # before coverage starts
except NoDataError as e:
print("gap:", e)
Known gaps from live (intentional, documented)
optionquote.bidSize/askSize— always0(minute table has no sizes)optionquote.volume/gex.call_volume/put_volume— always0optionquote.svi_vol—nullwithsvi_vol_gated: "backtest_mode"narrative.data.top_oi_changes— empty array (no prior-day OI diff yet)gex.call_oi_change/put_oi_change— alwaysnullstock_summary.macro.vix_futures/fear_and_greed—nullvrp.macro.hy_spread— hard-coded3.5- 0DTE intraday greeks (delta/gamma/theta/iv) often
0/null— chain still listed for OI analysis
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file flashalpha_historical-0.4.0rc8.tar.gz.
File metadata
- Download URL: flashalpha_historical-0.4.0rc8.tar.gz
- Upload date:
- Size: 25.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e874f0f3ce32e23d7b5065a473fef28c54d44b3c2b714d31eacb8763b1bc798a
|
|
| MD5 |
1d3b4d938a2f2203d6c02690268e5216
|
|
| BLAKE2b-256 |
f0a4c92305c4b68973720fcb8db29aeb4172e6191c743d321220644a37991546
|
File details
Details for the file flashalpha_historical-0.4.0rc8-py3-none-any.whl.
File metadata
- Download URL: flashalpha_historical-0.4.0rc8-py3-none-any.whl
- Upload date:
- Size: 26.5 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.13.13
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
59ac30bd92fc8fd8cad191107f13b73052fdaceabab41568fc9d023aefd9654a
|
|
| MD5 |
955998a99d31cd849e1f0203d8fb6f62
|
|
| BLAKE2b-256 |
30013cbf54f11eb0c1ccac88d29d8549970e0804604585c7f4b04eee16a58c1b
|