Ir al contenido
← Todos los ejemplos

Ejemplo 57

Handler follower

a strategy decided by a function of the program (a handler) instead of by rules. The strategy keeps its signals -- the last price

Categoría
Host: necesita los datos y el motor de la terminal
Permisos
market.readbacktest.run
Antes de ejecutarlo
at least one published BTCUSDT dataset on this machine (Datasets window)
Qué hace
starts a backtest job (it appears in the Jobs panel); writes its run under the terminal's runs folder.
Cómo ejecutarlo
grant market.read and backtest.run in the T0 Lang window, Run. Put on a replay or the live market, the same handlers run there.
Lenguaje
>=0.2.0, <0.3.0
Host
>=0.1.14, <0.2.0
Necesita
market >=0.1.1, <0.2.0features >=0.1.0, <0.2.0handlers >=0.1.0, <0.2.0backtest >=0.1.1, <0.2.0

Código

// Purpose: a strategy decided by a function of the program (a handler) instead of by rules. The strategy keeps its signals -- the last price
// and a three-bar average -- and on every closed five-minute bar the host calls `on_bar` with the state it keeps and those two values. The function
// counts the bars it has seen, remembers whether it is holding, and asks for a buy when the price is over the average and a sell when it falls under.
// What a handler cannot do is look ahead: it sees the signals as of the event that closed the bar, and only when they are all known.
// Category: host
// Permissions: market.read, backtest.run
// Preconditions: at least one published BTCUSDT dataset on this machine (Datasets window)
// Side effects: starts a backtest job (it appears in the Jobs panel); writes its run under the terminal's runs folder.
// Run: grant market.read and backtest.run in the T0 Lang window, Run. Put on a replay or the live market, the same handlers run there.

lang ">=0.2.0, <0.3.0";
host "ttt" ">=0.1.14, <0.2.0";
requires "market" ">=0.1.1, <0.2.0";
requires "features" ">=0.1.0, <0.2.0";
requires "handlers" ">=0.1.0, <0.2.0";
requires "backtest" ">=0.1.1, <0.2.0";

struct Memory {
    bars: Int,
    holding: Bool,
}

struct Step {
    state: Memory,
    actions: List<handlers.Act>,
}

fn begin() -> Memory {
    return Memory { bars: 0, holding: false };
}

fn order(side: handlers.Side, intent: handlers.Intent, size: Quantity) -> handlers.Act {
    return handlers.Act.Submit(handlers.Order { book: "main", side: side, intent: intent, qty: size, limit: None, stop: None, take_profit: None, stop_loss: None, tag: 0, post_only: false, immediate: false, expire_minutes: 0 });
}

fn on_bar(memory: Memory, px: Float, average: Float) -> Step {
    let bars = memory.bars + 1;
    if !memory.holding && px > average {
        return Step { state: Memory { bars: bars, holding: true }, actions: [order(handlers.Side.Buy, handlers.Intent.Open, qty(0.1))] };
    }
    if memory.holding && px < average {
        return Step { state: Memory { bars: bars, holding: false }, actions: [order(handlers.Side.Sell, handlers.Intent.Close, qty(0.1))] };
    }
    return Step { state: Memory { bars: bars, holding: memory.holding }, actions: [] };
}

strategy follower(period: Int) version "1.0.0" {
    let px = features.price(features.Source.AggTrades);
    let average = features.sma(period);
    state = begin();
    handler bar(5) = on_bar(px, average);
}

fn main() -> Result<Unit, Error> {
    let ds = market.datasets("BTCUSDT")?.first().expect("no published BTCUSDT dataset on this machine");
    let report = backtest.run(backtest.Spec {
        strategy: follower(3),
        dataset: ds,
        start: None,
        end: None,
        starting_balance: money(100000, USDT),
        execution: backtest.Execution {
            maker_fee: bps(2),
            taker_fee: bps(5),
            slippage: backtest.Slippage.None,
            latency: 0ms,
            market_fill: backtest.MarketFill.NextPrint,
            limit_fill: backtest.LimitFill.TradeThrough,
        },
    })?;
    print(report.status);
    print(report.trades);
    print(report.final_equity);
    return Ok(());
}