← すべてのサンプル
サンプル 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
- カテゴリ
- Host:ターミナルのデータとエンジンが必要
- 権限
- market.readbacktest.run
- 実行する前に
- at least one published BTCUSDT dataset on this machine (Datasets window)
- 何をするか
- starts a backtest job (it appears in the Jobs panel); writes its run under the terminal's runs folder.
- 実行方法
- 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.
- 言語
>=0.2.0, <0.3.0- ホスト
>=0.1.14, <0.2.0- 必要なもの
- 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
ソース
// 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(()); }