← すべてのサンプル
サンプル 37
Stop sweep
the stop sweep: the last closed bar broke under the lows of the twenty bars before it, a spike of long liquidations went off in
- カテゴリ
- Workspace:チャートやパネルを読む・変更する
- 権限
- market.readworkspace.readworkspace.write
- 実行する前に
- a terminal connected to a backend that captures trades and liquidations, with a chart on a timeframe of a few minutes
- 何をするか
- DRAWS a mark named "stop_sweep" on the active chart (run again: replaced); sounds the alert chime on a sweep.
- 実行方法
- grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (60 s) to keep watch.
- 言語
>=0.1.1, <0.2.0- ホスト
>=0.1.7, <0.2.0- 必要なもの
- market >=0.1.3, <0.2.0derivs >=0.1.0, <0.2.0flow >=0.1.0, <0.2.0workspace >=0.1.0, <0.2.0plot >=0.1.0, <0.2.0alert >=0.1.0, <0.2.0
ソース
// Purpose: the stop sweep: the last closed bar broke under the lows of the twenty bars before it, a spike of long liquidations went off in // it, and it closed back above them with buyers in control -- a mark on the chart where the sweep was. **It judges only what was recorded**: // if the capture has no liquidations or no order flow for the bar, it says which and gives no verdict, because a bar with the liquidations // missing looks exactly like a bar without a sweep. // Category: workspace // Permissions: market.read, workspace.read, workspace.write // Preconditions: a terminal connected to a backend that captures trades and liquidations, with a chart on a timeframe of a few minutes // Side effects: DRAWS a mark named "stop_sweep" on the active chart (run again: replaced); sounds the alert chime on a sweep. // Run: grant market.read, workspace.read and workspace.write, Run. Attach it to "Every N seconds" (60 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 "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 "alert" ">=0.1.0, <0.2.0"; const OWNER: String = "stop_sweep"; const LOOKBACK: Int = 20; fn main() -> Result<Unit, Error> { let chart = workspace.active_chart().expect("no chart is open"); let candles = market.chart_candles(chart.symbol, chart.timeframe, LOOKBACK + 1)?; plot.clear(chart.chart, OWNER)?; if candles.len() < LOOKBACK + 1 { print("no verdict: only " + to_string(candles.len()) + " closed bars to compare with"); return Ok(()); } let bar = candles.last().expect("a bar"); let width = bar.close_time - bar.open_time; // 1. Price: under the lows of the bars before it, and back above them at the close. let mut floor = candles.first().expect("a bar").low; let mut i = 0; while i < LOOKBACK { let earlier = candles.get(i).expect("a bar"); if earlier.low < floor { floor = earlier.low; } i = i + 1; } if !(bar.low < floor && bar.close > floor) { print(chart.symbol + ": no sweep -- the bar did not take out the " + to_string(LOOKBACK) + "-bar low and close back above it"); return Ok(()); } // 2. Liquidations: the bar's bucket against the hour before. Unknown stays unknown. let hour = derivs.liquidations(chart.symbol, bar.open_time - width * 12, bar.close_time, width, price(50.0, USDT))?; let bucket = hour.buckets.last().expect("a bucket"); if !bucket.known { print("no verdict: the bar took out the low, but the capture did not record its liquidations (" + to_string(hour.holes.len()) + " hole(s) in the range)"); return Ok(()); } let mut earlier_sum: Float = 0.0; let mut earlier_known = 0; for b in hour.buckets { if b.time != bucket.time { match b.longs { Some(longs) => { earlier_sum = earlier_sum + to_float(longs.value()); earlier_known = earlier_known + 1; } None => {} } } } if earlier_known == 0 { print("no verdict: none of the bars before it had recorded liquidations to compare with"); return Ok(()); } let average = earlier_sum / to_float(earlier_known); let longs = to_float(bucket.longs.expect("known").value()); if longs < average * 3.0 || longs <= 0.0 { print(chart.symbol + ": took out the low, but the long liquidations (" + to_string(longs) + ") were not 3x the average of " + to_string(average)); return Ok(()); } // 3. Order flow: buyers won the bar. let fp = flow.footprint(chart.symbol, chart.timeframe, bar.open_time, bar.close_time, price(50.0, USDT))?; let traded = fp.bars.last().expect("the bar"); if !traded.known { print("no verdict: swept and liquidated, but the tape did not record the bar's order flow"); return Ok(()); } let mut delta: Float = 0.0; for cell in traded.cells { delta = delta + to_float(cell.buy.value()) - to_float(cell.sell.value()); } if delta <= 0.0 { print(chart.symbol + ": swept the low with " + to_string(longs) + " longs liquidated, but sellers still won the bar (delta " + to_string(delta) + ")"); return Ok(()); } plot.marker(chart.chart, OWNER, bar.open_time, bar.low, "stop sweep: " + to_string(longs) + " longs, delta +" + to_string(delta), "green")?; alert.notify("Stop sweep", chart.symbol + ": low taken out, " + to_string(longs) + " longs liquidated, buyers took the bar")?; print(chart.symbol + ": STOP SWEEP -- " + to_string(longs) + " longs liquidated (" + to_string(longs / average) + " x the average), delta +" + to_string(delta)); return Ok(()); }