Ir al contenido
← Todos los ejemplos

Ejemplo 34

Liquidation cascade

a liquidation thermometer: how the last five minutes of forced closes compare with the hour before, and a mark on the chart

Categoría
Espacio de trabajo: lee o cambia gráficos y paneles
Permisos
market.readworkspace.readworkspace.write
Antes de ejecutarlo
a terminal connected to a backend that captures liquidations, with a chart open
Qué hace
DRAWS marks named "liq_heat" on the active chart (run again: replaced).
Cómo ejecutarlo
grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (300 s) to keep it current.
Lenguaje
>=0.1.1, <0.2.0
Host
>=0.1.7, <0.2.0
Necesita
derivs >=0.1.0, <0.2.0workspace >=0.1.0, <0.2.0plot >=0.1.0, <0.2.0event >=0.1.0, <0.2.0

Código

// Purpose: a liquidation thermometer: how the last five minutes of forced closes compare with the hour before, and a mark on the chart
// at every five minutes that ran hot. **A stretch nobody recorded is not a quiet one**: buckets the capture missed are left out of the
// average and counted aloud, and if the last five minutes are among them there is no reading.
// Category: workspace
// Permissions: market.read, workspace.read, workspace.write
// Preconditions: a terminal connected to a backend that captures liquidations, with a chart open
// Side effects: DRAWS marks named "liq_heat" on the active chart (run again: replaced).
// Run: grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (300 s) to keep it current.

lang ">=0.1.1, <0.2.0";
host "ttt" ">=0.1.7, <0.2.0";
requires "derivs" ">=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 = "liq_heat";

// What was closed by force in a bucket, both sides, or None when the capture did not record it.
fn total(b: derivs.Bucket) -> Option<Float> {
    let found = match b.longs {
        Some(longs) => match b.shorts {
            Some(shorts) => Some(to_float(longs.value()) + to_float(shorts.value())),
            None => None,
        },
        None => None,
    };
    return found;
}

fn main() -> Result<Unit, Error> {
    let chart = workspace.active_chart().expect("no chart is open");
    let now = event.current().time;
    let series = derivs.liquidations(chart.symbol, now - 65min, now, 5min, price(50.0, USDT))?;
    plot.clear(chart.chart, OWNER)?;
    if series.buckets.is_empty() {
        print("no five-minute bucket has closed in the range");
        return Ok(());
    }

    // The average of what is known, the newest bucket aside.
    let last = series.buckets.last().expect("a bucket");
    let mut sum: Float = 0.0;
    let mut known = 0;
    let mut unknown = 0;
    for b in series.buckets {
        if b.time != last.time {
            match total(b) {
                Some(amount) => {
                    sum = sum + amount;
                    known = known + 1;
                }
                None => {
                    unknown = unknown + 1;
                }
            }
        }
    }
    if unknown > 0 {
        print(to_string(unknown) + " of the earlier buckets were not recorded and are left out of the average");
    }
    if known == 0 {
        print("no reading: none of the hour before was recorded");
        return Ok(());
    }
    let average = sum / to_float(known);

    // Every known bucket that ran three times hotter than the average gets a mark where its liquidations were.
    let mut marked = 0;
    for b in series.buckets {
        match total(b) {
            Some(amount) => {
                if average > 0.0 && amount >= average * 3.0 {
                    match b.levels.first() {
                        Some(level) => {
                            plot.marker(chart.chart, OWNER, b.time, level.price, "liq x" + to_string(amount / average), "orange")?;
                            marked = marked + 1;
                        }
                        None => {}
                    }
                }
            }
            None => {}
        }
    }

    match total(last) {
        Some(amount) => {
            let mut heat: Float = 0.0;
            if average > 0.0 {
                heat = amount / average;
            }
            print(chart.symbol + ": last five minutes " + to_string(amount) + " liquidated, " + to_string(heat) + " x the hour's average of " + to_string(average) + " (" + to_string(known) + " buckets); " + to_string(marked) + " marked");
        }
        None => print(chart.symbol + ": no reading -- the last five minutes were not recorded by the capture"),
    }
    return Ok(());
}