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

예제 41

Cvd divergence

spot against perpetual during a liquidation: over the last hour of five-minute bars, finds the bars in which long liquidations ran

분류
Workspace: 차트와 패널을 읽거나 변경
권한
market.readworkspace.readworkspace.write
실행하기 전에
a terminal connected to a backend that records liquidations, the perpetual's tape and the spot tape
하는 일
DRAWS marks named "cvd_divergence" on the active chart (run again: replaced).
실행 방법
grant market.read, workspace.read and workspace.write, Run.
언어
>=0.1.1, <0.2.0
호스트
>=0.1.7, <0.2.0
필요한 것
derivs >=0.1.0, <0.2.0flow >=0.1.0, <0.2.0workspace >=0.1.0, <0.2.0plot >=0.1.0, <0.2.0event >=0.1.0, <0.2.0

소스

// Purpose: spot against perpetual during a liquidation: over the last hour of five-minute bars, finds the bars in which long liquidations ran
// at three times the average, the perpetual's order flow was negative (sellers) and the spot's was positive (buyers) -- the spot absorbing what
// the perpetual dumped. Marks them on the chart. **Spot is only there if the deployment records it** (the daemon with CAPTURE_SPOT=1): without
// it the program says so and stops, it does not report a divergence from a market it has no data of. A bar missing any of the three
// readings is skipped and counted.
// Category: workspace
// Permissions: market.read, workspace.read, workspace.write
// Preconditions: a terminal connected to a backend that records liquidations, the perpetual's tape and the spot tape
// Side effects: DRAWS marks named "cvd_divergence" on the active chart (run again: replaced).
// Run: grant market.read, workspace.read and workspace.write, Run.

lang ">=0.1.1, <0.2.0";
host "ttt" ">=0.1.7, <0.2.0";
requires "derivs" ">=0.1.0, <0.2.0";
requires "flow" ">=0.1.0, <0.2.0";
requires "workspace" ">=0.1.0, <0.2.0";
requires "plot" ">=0.1.0, <0.2.0";
requires "event" ">=0.1.0, <0.2.0";

const OWNER: String = "cvd_divergence";

fn main() -> Result<Unit, Error> {
    let chart = workspace.active_chart().expect("no chart is open");
    let now = event.current().time;
    let from = now - 65min;
    plot.clear(chart.chart, OWNER)?;

    let attempt = flow.spot(chart.symbol, "5m", from, now);
    match attempt {
        Ok(_) => {}
        Err(e) => {
            print("no verdict: " + e.code + ": " + e.message);
            return Ok(());
        }
    }
    let spot = attempt?;
    let perp = flow.footprint(chart.symbol, "5m", from, now, price(50.0, USDT))?;
    let liq = derivs.liquidations(chart.symbol, from, now, 5min, price(50.0, USDT))?;

    // The average of the known long liquidations of the hour.
    let mut sum: Float = 0.0;
    let mut known = 0;
    for b in liq.buckets {
        match b.longs {
            Some(longs) => {
                sum = sum + to_float(longs.value());
                known = known + 1;
            }
            None => {}
        }
    }
    if known == 0 {
        print("no verdict: none of the hour's liquidations were recorded");
        return Ok(());
    }
    let average = sum / to_float(known);

    let mut skipped = 0;
    let mut found = 0;
    let mut i = 0;
    while i < liq.buckets.len() {
        let bucket = liq.buckets.get(i).expect("a bucket");
        let bar = perp.bars.get(i).expect("a bar");
        let spot_bar = spot.bars.get(i).expect("a spot bar");
        if bucket.known && bar.known && spot_bar.known {
            let longs = to_float(bucket.longs.expect("known").value());
            let mut perp_delta: Float = 0.0;
            for cell in bar.cells {
                perp_delta = perp_delta + to_float(cell.buy.value()) - to_float(cell.sell.value());
            }
            let spot_delta = to_float(spot_bar.buy.expect("known").value()) - to_float(spot_bar.sell.expect("known").value());
            if average > 0.0 && longs >= average * 3.0 && perp_delta < 0.0 && spot_delta > 0.0 {
                match bucket.levels.first() {
                    Some(level) => {
                        plot.marker(chart.chart, OWNER, bucket.time, level.price, "spot bid vs perp dump: spot " + to_string(spot_delta) + ", perp " + to_string(perp_delta), "cyan")?;
                    }
                    None => {}
                }
                found = found + 1;
            }
        } else {
            skipped = skipped + 1;
        }
        i = i + 1;
    }
    print(chart.symbol + ": " + to_string(found) + " divergence(s) in the last hour; " + to_string(skipped) + " of " + to_string(liq.buckets.len()) + " bars skipped for lack of a recording");
    return Ok(());
}