← すべてのサンプル
サンプル 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
- カテゴリ
- Workspace:チャートやパネルを読む・変更する
- 権限
- market.readworkspace.readworkspace.write
- 実行する前に
- a terminal connected to a backend that captures liquidations, with a chart open
- 何をするか
- DRAWS marks named "liq_heat" on the active chart (run again: replaced).
- 実行方法
- grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (300 s) to keep it current.
- 言語
>=0.1.1, <0.2.0- ホスト
>=0.1.7, <0.2.0- 必要なもの
- 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
ソース
// 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(()); }