Pull Crypto Options Open Interest and Max Pain in Python
Deribit's public options API returns hundreds of individual instrument rows per expiry — every strike, every call and put, as separate line items. This playbook pulls one endpoint that has already aggregated it into open interest by strike, put/call ratio, and max pain, so you don't have to write that aggregation code yourself.
The problem: raw options data is hundreds of rows
If you've ever hit Deribit's public/get_book_summary_by_currency endpoint directly, you know the shape you get back: one row per instrument, named things like BTC-27MAR26-80000-C. For a single currency on a single day there can be 300-800 of these rows across a dozen expiries. To get anything useful out of it — open interest by strike, a put/call ratio, where max pain sits for the nearest expiry — you have to parse each instrument name into expiry/strike/type, bucket by strike, sum open interest on each side, and then run a max-pain calculation across every candidate strike for every expiry.
That parsing and aggregation is exactly what GET /v1/options/chain pre-computes. One request returns the underlying price, total call/put open interest, put/call ratios by OI and by volume, open interest bucketed by strike (filtered to a sane range around spot), a per-expiry summary, and max pain per expiry — already computed from the same Deribit book-summary data.
Prerequisites
This specific endpoint is public — no API key needed to call it. You'll need:
- Python 3.8+ and the
requestslibrary (pip install requests) - Nothing else — no signup, no key, no auth header for this call
The endpoint
GET https://api.smartmoneyapi.com/v1/options/chain?currency=BTC
Query parameter currency accepts BTC or ETH (defaults to BTC if omitted). The underlying data source is Deribit's public options API — this endpoint doesn't add any proprietary options data, it just parses Deribit's instrument-name strings (BTC-27MAR26-80000-C → expiry 27MAR26, strike 80000, type call) and aggregates the result so you don't have to.
| Field | Meaning |
|---|---|
| underlying_price | Current BTC/ETH index price from Deribit |
| total_call_oi / total_put_oi | Sum of open interest across all calls / puts, all expiries |
| pcr_oi | Put/call ratio by open interest — total_put_oi ÷ total_call_oi |
| pcr_volume | Put/call ratio by 24h traded volume |
| oi_by_strike | Array of {strike, call_oi, put_oi}, filtered to strikes between 0.5x and 2.0x the underlying price |
| expiry_summary | Per-expiry object keyed by Deribit date code (e.g. "27MAR26") with call_oi, put_oi, pcr, max_pain, total_contracts |
| max_pain | Per-expiry object with the max-pain strike and total_pain_quote (USD notional) |
A companion endpoint, GET /v1/options/history?currency=BTC&metric=pcr_oi&hours=24, is also public and returns a time series for pcr_oi, total_oi, or max_pain — useful once you want to chart how positioning is shifting rather than just look at a snapshot.
Python script
This fetches the BTC chain, prints the top-level summary, the nearest expiry's max pain strike, and the top 5 strikes by combined open interest:
JavaScript / fetch variant
Same call from Node or a browser console, using the built-in fetch:
This same key unlocks funding heatmaps, whale positioning across 8 chains, and liquidation data — one API instead of a dozen exchange integrations.
Get your free API key →Expected output
A trimmed real response for currency=BTC looks like this (fields shortened for readability — oi_by_strike and expiry_summary normally contain many more entries):
Running the Python script above against a response shaped like this prints something like:
What max pain actually is (and isn't)
Max pain is a purely mechanical open-interest calculation: for a given expiry, the code walks every candidate strike price and sums the dollar value of contracts that would finish in-the-money on each side (calls below the candidate, puts above it, distance × OI). The candidate strike where that total payout is lowest — where the largest total dollar amount of open contracts would expire worthless — is the max pain strike.
That's it. It is a snapshot of where existing open interest happens to sit, computed the same way every time from the same book-summary data. It is not a prediction that price will move to that strike, and it is not evidence of market maker manipulation or any other directional claim. Treat it the same way you'd treat any other open-interest statistic: descriptive of current positioning, not predictive of where price goes next.
What to build next
- Chart PCR over time using
/v1/options/history?currency=BTC&metric=pcr_oi&hours=168to see whether put/call positioning is trending, rather than relying on a single snapshot. - Compare BTC vs ETH side by side — call the endpoint twice with
currency=BTCandcurrency=ETHand diff the put/call ratios. - Track max pain drift into expiry by polling daily and logging how the nearest-expiry max_pain strike shifts as more contracts get opened, closed, or expire.
- Add derivatives context from
/v1/derivatives/funding-heatmap(also public) to see options positioning alongside perpetual funding rates for the same symbol.
All of this lives behind one API key across 66+ endpoints covering derivatives, on-chain, and whale data — instead of separately integrating Deribit, half a dozen chain explorers, and multiple exchange APIs.