An options chain with full Greeks tells you what the market is paying for convexity, time decay, and volatility — right now, by strike, by expiry. Technical indicators take the same price series and ask a different question: has the recent path changed. Both are noisy. Both are useful when the user knows what they're being told.
Notes from Surendra Singh.
get_options_chain(ticker, expiry) returns the full chain — calls and puts, all strikes — with mid-price, bid/ask, open interest, volume, implied vol, and Greeks. Greeks are sourced from the Massive provider where available; the math is Black-Scholes with dividend yield, and yes, you can argue with that choice (American exercise, early-exercise premium for puts, dividend timing). For a quick read on positioning, BS is fine. For a market-making book, you build your own pricer.
get_options_chain( ticker: str, expiry: str = "", # YYYY-MM-DD; default: nearest weekly option_type: str = "both", # "calls" | "puts" | "both" moneyness: str = "all", # "itm" | "atm" | "otm" | "all" ) -> str
Price sensitivity to a $1 move in the underlying. Calls 0 to 1, puts -1 to 0. ATM ≈ 0.5. The hedge ratio.
Rate of change of Δ. Highest at the money, near expiry. Long gamma is the desk that profits from volatility, period.
Time decay per day. Always negative for a long option. The cost you pay for being right slowly.
Sensitivity to a 1-vol-point move in implied volatility. Long vega benefits when IV expands — earnings, macro, stress.
Sensitivity to interest rates. Mostly ignored on short-dated equity options. Matters on LEAPS and rates products.
Not a Greek, but the input to all of them. The vol the market is pricing in — backed out of the option premium itself.
"Δ tells you the hedge. Γ tells you how fast the hedge breaks. Θ tells you what you're paying to wait. ν tells you what happens when the world panics."
get_technical_indicator(ticker, indicator, ...) dispatches into one of four computations. They share a common preprocessing step: fetch adjusted close, drop NaNs, run the formula, return the series with a written interpretation. Indicators are cheap to compute. The expensive part is interpretation, and that's the part most retail tools hand-wave.
RSI = 100 - (100 / (1 + (avg_gain / avg_loss))) # 14-period default MACD = EMA(12) - EMA(26); signal = EMA9(MACD) # crossovers, histogram SMA = price.rolling(window).mean() # 20 / 50 / 200 BB = SMA ± 2 * price.rolling(window).std() # Bollinger bands
RSI > 70 is "overbought" only relative to its own recent history. In a strong uptrend, RSI lives above 70 for weeks. The indicator did not become wrong — the user's interpretation rule was wrong. The library returns the number; the persona ( /finance-analyst ) writes the interpretation in context. Numbers without context are just numbers.
Three failure modes worth naming, because every indicator-driven workflow runs into them:
The library does not flag these for you. The library returns numbers. The persona writes the interpretation, the analyst owns the call. That's the right division of labor.