Skip to content
← All examples

Example 40

Carry scanner

the carry scanner: reads funding and basis (mark against index) for every symbol the terminal offers, ranks them, and opens a

Category
Host: needs the terminal's data and engine
Permissions
market.readworkspace.readworkspace.write
Before you run it
a terminal connected to a backend that captures funding for the symbols it offers
What it does
OPENS up to three charts (1h) of the symbols it ranks first, unless already open.
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
derivs >=0.1.0, <0.2.0workspace >=0.1.0, <0.2.0event >=0.1.0, <0.2.0

Source

// Purpose: the carry scanner: reads funding and basis (mark against index) for every symbol the terminal offers, ranks them, and opens a
// chart for the three with the most extreme funding. **A symbol the capture has no reading for is left out and counted, never ranked on a
// guess**; a symbol whose funding the venue did not publish is ranked on nothing.
// Category: host
// Permissions: market.read, workspace.read, workspace.write
// Preconditions: a terminal connected to a backend that captures funding for the symbols it offers
// Side effects: OPENS up to three charts (1h) of the symbols it ranks first, unless already open.
// 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 "workspace" ">=0.1.0, <0.2.0";
requires "event" ">=0.1.0, <0.2.0";
import std.fin;
import std.list;

struct Row {
    symbol: String,
    funding: Float,
    basis: Float,
}

fn main() -> Result<Unit, Error> {
    let now = event.current().time;
    let mut rows: List<Row> = [];
    let mut unknown = 0;
    for symbol in workspace.symbols() {
        let reading = derivs.at(symbol, now)?;
        match reading.funding_rate {
            Some(rate) => {
                match reading.mark {
                    Some(mark) => {
                        match reading.index {
                            Some(index) => {
                                rows.push(Row { symbol: symbol, funding: to_float(rate.value()), basis: to_float(fin.pct_change(index, mark).value()) });
                            }
                            None => {
                                unknown = unknown + 1;
                            }
                        }
                    }
                    None => {
                        unknown = unknown + 1;
                    }
                }
            }
            None => {
                unknown = unknown + 1;
            }
        }
    }
    print(to_string(rows.len()) + " symbols read, " + to_string(unknown) + " with no usable reading (left out)");
    if rows.is_empty() {
        return Ok(());
    }

    // The three with the largest funding in either direction, by selection: a list the language sorts only by its own order.
    let mut taken: List<String> = [];
    let mut rank = 0;
    while rank < 3 && rank < rows.len() {
        let mut best: Option<Row> = None;
        let mut best_size: Float = -1.0;
        for row in rows {
            let size = if row.funding < 0.0 { 0.0 - row.funding } else { row.funding };
            if size > best_size && !list.contains(taken, row.symbol) {
                best_size = size;
                best = Some(row);
            }
        }
        let pick = best.expect("one is left");
        taken.push(pick.symbol);
        print(to_string(rank + 1) + ". " + pick.symbol + ": funding " + to_string(pick.funding * 100.0) + " %, basis " + to_string(pick.basis * 100.0) + " %");
        let mut open = false;
        for chart in workspace.charts() {
            if chart.symbol == pick.symbol {
                open = true;
            }
        }
        if !open {
            match workspace.open_chart(pick.symbol, "1h") {
                Ok(_) => print("   opened a chart"),
                Err(e) => print("   not opened: " + e.code),
            }
        }
        rank = rank + 1;
    }
    return Ok(());
}