// Where BTC option dealers flip from damping moves to chasing them, on the chart: the
// gamma flip, blue while dealers are long gamma at BTC's price (they sell rises and buy dips) and
// red while they are short (they buy rises and sell dips), and as levels the strikes within 5% of
// the price where their long and short gamma is largest now. From the Dealer exposure panel's
// model, every 5 minutes, the last 7 days. The nearest expiry dominates gamma near the price, so it
// is the default, as in the panel; with every expiry dealers often stay long gamma all the way out,
// and there is no flip.
indicator('Dealer gamma', { overlay: true, shortName: 'Dealer gamma' });
const model = input.choice('Dealer positions from', 'block', ['block', 'all'], { labels: { block: 'Block flow', all: 'All trades' } });
const expiries = input.choice('Expiries', 'next', ['next', 'all'], { labels: { next: 'Next', all: 'All' } });
const chart = bars();
const dealers = dealerExposure({ model, expiries });
const flip = plot.line('Gamma flip', { width: 2 });
const LONG = color.rgb(77, 148, 240);
const SHORT = color.rgb(239, 79, 90);
chart.onBar(() => {
if (!dealers.available) return;
flip.set(dealers.flip, dealers.gamma >= 0 ? LONG : SHORT);
if (!chart.isLast) return;
// Now: the strikes that add the most gamma each way at the snapshot's price, as levels across the chart.
let most = 0;
let least = 0;
let mostAt = na;
let leastAt = na;
for (const k of dealers.strikes()) {
if (Math.abs(k.strike / dealers.spot - 1) > 0.05) continue;
if (k.gamma > most) { most = k.gamma; mostAt = k.strike; }
if (k.gamma < least) { least = k.gamma; leastAt = k.strike; }
}
for (const [at, ink, words] of [[mostAt, LONG, 'Long gamma'], [leastAt, SHORT, 'Short gamma']] as const) {
if (isNa(at)) continue;
draw.line({ from: { bar: chart.index - 1, price: at }, to: { bar: chart.index, price: at }, extend: 'left', color: color.withAlpha(ink, 0.7), style: 'dashed' });
draw.label({ at: { bar: chart.index, price: at }, text: `${words} ${fmt.price(at)}`, style: 'lowerRight', color: color.withAlpha(color.panel, 0.85), textColor: ink, size: 'small' });
}
});