DEV Community

0xGollum
0xGollum

Posted on

I cloned my equity options scanner for crypto — the same 3 rules, a completely different data source

A while back I built a scanner that flags "unusual options activity" on US equities — the kind of signal where a contract suddenly trades on way more volume than its standing open interest, backed by real dollar premium, not just noise. Three gates: liquidity, freshness (volume vs open interest ratio), and money behind the trade.

Someone asked me: could the same idea work for crypto options? My first instinct was "sure, just swap the data source." That instinct was mostly right, but not entirely — here's what actually changed.

The data source is a different shape

Equities options data (I was pulling from a public CDN) comes back per-ticker: one call, one full chain for that symbol. Crypto options don't work that way — there's really one dominant venue for BTC/ETH options, and its public API returns every strike and expiry for a whole currency in a single call. So the "loop over tickers" became a "loop over currencies" — structurally similar, but the unit of iteration changed.

No fixed contract multiplier

US equity options are always 1 contract = 100 shares. That "x100" was hardcoded in my premium calculation. Crypto options are 1 contract = 1 unit of the underlying (1 BTC, 1 ETH) — no multiplier. I ended up parameterizing the premium function instead of hardcoding the multiplier, which also made the pure signal-logic module reusable as-is between both versions. Same detection math, same tests, different constant.

Prices aren't in USD

Crypto options are quoted in the base currency (a BTC option's price is itself a fraction of a BTC), not in dollars. So every price has to be converted using the current index price before any of the USD-premium thresholds make sense. Easy to get right, easy to silently get wrong if you forget it in one code path.

The bug that actually mattered

While writing tests for the instrument-name parser (something like BTC-28AUG26-59000-P), I'd assumed the date chunk was always a fixed length. It's not — a 1-digit day ("7AUG26") is shorter than a 2-digit day ("28AUG26"). My first length check silently rejected every single-digit-day contract as unparseable. That's roughly 10% of live instruments gone, quietly, with no error — and they skew toward near-dated (often the most actively traded) expiries.

Nothing caught it until I wrote a dedicated test for the parser itself, separate from the end-to-end "does it produce output" test. The lesson isn't really about crypto or options — it's that a parsing function deserves its own unit tests with real edge-case inputs, not just a smoke test that happens to pass because your sample data avoided the edge case.

Same three rules, same pure detection logic, ported across a genuinely different market — most of the actual work was in the boring conversion layer, not the "signal" part.


The crypto version is live on Apify if you want to poke at it: https://apify.com/0xgollum/unusual-crypto-options-activity

Top comments (0)