본문으로 건너뛰기
← 모든 예제

예제 39

Gamma flip cross

the gamma flip: the strike where the options market's net gamma changes sign. Above it dealers damp moves, below it they feed

분류
Host: 터미널의 데이터와 엔진 필요
권한
market.readworkspace.readworkspace.write
실행하기 전에
a terminal connected to a backend that reads the options chain; a BTC or ETH chart
하는 일
sounds the alert chime when the flip was crossed. Reads only.
실행 방법
grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (300 s) to keep watch.
언어
>=0.1.1, <0.2.0
호스트
>=0.1.7, <0.2.0
필요한 것
market >=0.1.3, <0.2.0options >=0.1.0, <0.2.0workspace >=0.1.0, <0.2.0alert >=0.1.0, <0.2.0event >=0.1.0, <0.2.0

소스

// Purpose: the gamma flip: the strike where the options market's net gamma changes sign. Above it dealers damp moves, below it they feed
// them. Reports which side of the flip the last close is on, how far, how much the market moved in the last hour -- and raises an alert when
// the close crossed it in the last fifteen minutes. **Needs the flip at both ends of the window**: when the options chain was not read at
// either (or has no flip), it says so and reports no crossing, because a flip carried over from an old chain is a level that is not there.
// Category: host
// Permissions: market.read, workspace.read, workspace.write
// Preconditions: a terminal connected to a backend that reads the options chain; a BTC or ETH chart
// Side effects: sounds the alert chime when the flip was crossed. Reads only.
// Run: grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (300 s) to keep watch.

lang ">=0.1.1, <0.2.0";
host "ttt" ">=0.1.7, <0.2.0";
requires "market" ">=0.1.3, <0.2.0";
requires "options" ">=0.1.0, <0.2.0";
requires "workspace" ">=0.1.0, <0.2.0";
requires "alert" ">=0.1.0, <0.2.0";
requires "event" ">=0.1.0, <0.2.0";
import std.text;
import std.ind;
import std.stats;

fn main() -> Result<Unit, Error> {
    let chart = workspace.active_chart().expect("no chart is open");
    let asset = if text.starts_with(chart.symbol, "ETH") { "ETH" } else { "BTC" };
    let now = event.current().time;
    let candles = market.chart_candles(chart.symbol, "5m", 13)?;
    if candles.len() < 4 {
        print("no reading: fewer than four closed five-minute bars");
        return Ok(());
    }
    let last = candles.last().expect("a bar");
    let before = candles.get(candles.len() - 4).expect("a bar");

    let gamma_now = options.gamma_at(asset, now)?;
    match gamma_now.unknown {
        Some(why) => {
            print("no reading: " + why);
            return Ok(());
        }
        None => {}
    }
    if gamma_now.flip.is_none() {
        print(asset + ": the chain has no flip -- net gamma does not change sign within the listed strikes");
        return Ok(());
    }
    let flip = gamma_now.flip.expect("checked above");
    // The flip is in USD (the options' strikes) and the candles in USDT: the language never converts between them, so the comparison is of
    // the numbers, which takes USDT as worth one USD. Said here because it is an assumption, and a depeg is when it fails.
    let level = flip.amount();
    let above = last.close.amount() > level;
    let distance = to_float(last.close.amount() / level - 1.0) * 100.0;
    print(chart.symbol + " closed at " + to_string(last.close) + ", " + to_string(distance) + " % " + (if above { "above" } else { "below" }) + " the flip at " + to_string(flip) + (if above { " (dealers damp moves)" } else { " (dealers feed moves)" }));

    // Realized volatility of the last twelve bars (or the bars there are), per bar.
    let mut closes: List<Float> = [];
    for c in candles {
        closes.push(to_float(c.close.amount()));
    }
    match stats.stdev(ind.known(ind.log_returns(closes))) {
        Some(vol) => print("realized volatility of the last " + to_string(candles.len()) + " bars: " + to_string(vol * 100.0) + " % per bar"),
        None => print("realized volatility: too few bars"),
    }

    // The flip fifteen minutes ago, from the chain the capture read then: unknown stays unknown.
    let gamma_then = options.gamma_at(asset, now - 15min)?;
    match gamma_then.unknown {
        Some(why) => {
            print("no crossing verdict: no chain fifteen minutes ago (" + why + ")");
            return Ok(());
        }
        None => {}
    }
    if gamma_then.flip.is_none() {
        print("no crossing verdict: the chain fifteen minutes ago had no flip");
        return Ok(());
    }
    let flip_then = gamma_then.flip.expect("checked above");
    let above_then = before.close.amount() > flip_then.amount();
    if above != above_then {
        alert.notify("Gamma flip crossed", chart.symbol + " went " + (if above { "above" } else { "below" }) + " the gamma flip (" + to_string(flip) + ")")?;
        print("CROSSED the flip in the last fifteen minutes: " + (if above_then { "above" } else { "below" }) + " -> " + (if above { "above" } else { "below" }));
    } else {
        print("no crossing in the last fifteen minutes");
    }
    return Ok(());
}