← All examples
Example 38
Iceberg
the iceberg: a band of the book that is hit and fills back up again and again. Follows the largest resting bid and the largest
- Category
- Workspace: reads or changes charts and panels
- Permissions
- market.readworkspace.readworkspace.write
- Before you run it
- a terminal connected to a data engine that builds the book of the chart's symbol
- What it does
- DRAWS a level named "iceberg" on the active chart for a band refilled three times or more (run again: replaced).
- How to run it
- grant market.read, workspace.read and workspace.write, Run.
- Language
>=0.1.1, <0.2.0- Host
>=0.1.7, <0.2.0- Needs
- book >=0.1.0, <0.2.0workspace >=0.1.0, <0.2.0plot >=0.1.0, <0.2.0event >=0.1.0, <0.2.0
Source
// Purpose: the iceberg: a band of the book that is hit and fills back up again and again. Follows the largest resting bid and the largest // resting ask over the last five minutes, reading by reading, and counts how many times each was cut to under a third and came back to over // four fifths. **A refill is counted only between two readings that both exist**: a stretch the book was not recorded through is not a // band being hit, and the count starts again after it. // Category: workspace // Permissions: market.read, workspace.read, workspace.write // Preconditions: a terminal connected to a data engine that builds the book of the chart's symbol // Side effects: DRAWS a level named "iceberg" on the active chart for a band refilled three times or more (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 "book" ">=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 = "iceberg"; // The size resting in the band at `at`, or None when the reading is unknown. fn resting(side: List<book.Level>, known: Bool, at: Price) -> Option<Float> { if !known { return None; } let mut size: Float = 0.0; for level in side { if level.price == at { size = to_float(level.size.value()); } } return Some(size); } // How many times the band at `at` was cut and came back, over the readings. fn refills(columns: List<book.Snapshot>, bids: Bool, at: Price, full: Float) -> Int { let mut count = 0; let mut cut = false; let mut before: Option<Float> = None; for snapshot in columns { let side = if bids { snapshot.bids } else { snapshot.asks }; let here = resting(side, snapshot.known, at); match here { Some(size) => { if size <= full * 0.33 { cut = true; } if cut && size >= full * 0.8 { match before { Some(_) => { count = count + 1; } None => {} } cut = false; } before = Some(size); } None => { // A reading is missing: what was happening across it is not known, so the sequence starts again. before = None; cut = false; } } } return count; } // The largest band of one side over the readings, with its size. fn largest(columns: List<book.Snapshot>, bids: Bool) -> Option<book.Level> { let mut best: Option<book.Level> = None; let mut best_size: Float = 0.0; for snapshot in columns { if snapshot.known { let side = if bids { snapshot.bids } else { snapshot.asks }; for level in side { let size = to_float(level.size.value()); if size > best_size { best_size = size; best = Some(level); } } } } return best; } fn main() -> Result<Unit, Error> { let chart = workspace.active_chart().expect("no chart is open"); let now = event.current().time; let history = book.history(chart.symbol, now - 5min, now, 5s, 30)?; plot.clear(chart.chart, OWNER)?; if history.missing > 0 { print(to_string(history.missing) + " of " + to_string(history.columns.len()) + " readings of the book were not recorded; a refill is never counted across them"); } let mut found = 0; for bids in [true, false] { match largest(history.columns, bids) { Some(level) => { let full = to_float(level.size.value()); let times = refills(history.columns, bids, level.price, full); let side = if bids { "bid" } else { "ask" }; print(side + " band " + to_string(level.price) + " (" + to_string(full) + " at most): refilled " + to_string(times) + " time(s)"); if times >= 3 { plot.level(chart.chart, OWNER, level.price, "iceberg " + side + " x" + to_string(times), "purple")?; found = found + 1; } } None => print("no verdict on the " + (if bids { "bid" } else { "ask" }) + " side: the book was not recorded in the last five minutes"), } } if found == 0 { print(chart.symbol + ": no iceberg"); } return Ok(()); }