← すべてのサンプル
サンプル 69
Risk sweep
how much of the account to risk on each trade, found by running instead of guessing. The same strategy and the same dataset are backtested once for each value of the
- カテゴリ
- Host:ターミナルのデータとエンジンが必要
- 権限
- market.readbacktest.run
- 実行する前に
- a BTCUSDT dataset, and the terminal's risk bindings binding example 64's policy (`risk-per-trade`) to the `backtest` or `demo` account.
- 何をするか
- runs one backtest for each value (a few seconds each on a day of data); nothing else.
- 実行方法
- Run in the T0 Lang window, granting market.read and backtest.run.
- 言語
>=0.2.0, <0.3.0- ホスト
>=0.1.22, <0.2.0- 必要なもの
- market >=0.1.0, <0.2.0features >=0.1.0, <0.2.0backtest >=0.1.5, <0.2.0
ソース
// Purpose: how much of the account to risk on each trade, found by running instead of guessing. The same strategy and the same dataset are backtested once for each value of the // policy's `risk_per_trade` (example 64's policy, bound to the `backtest` or `demo` account in the terminal's risk bindings), and the table says what each value made, how deep it fell // and what it ended with. `backtest.run_with_risk` gives the policy these numbers for the run: the script is the same one, pinned by the same hash, and the bindings file is not changed. // HONEST NOTE: a table of results over one stretch of one market says what happened there, not what will; compare the Sharpe and the deepest fall, not only the profit, and look at // how many trades stand behind each line (the Performance window shows how sure the figures are). // Category: host // Permissions: market.read, backtest.run // Preconditions: a BTCUSDT dataset, and the terminal's risk bindings binding example 64's policy (`risk-per-trade`) to the `backtest` or `demo` account. // Side effects: runs one backtest for each value (a few seconds each on a day of data); nothing else. // Run: Run in the T0 Lang window, granting market.read and backtest.run. lang ">=0.2.0, <0.3.0"; host "ttt" ">=0.1.22, <0.2.0"; requires "market" ">=0.1.0, <0.2.0"; requires "features" ">=0.1.0, <0.2.0"; requires "backtest" ">=0.1.5, <0.2.0"; strategy trend_sized_by_risk(window: Int, stop_pct: Decimal) version "1.0.0" { let px = features.price(features.Source.AggTrades); let average = features.sma(window); let stop = px * (1 - stop_pct / 100); rule enter when cross_above(px, average) && exposure_is(Exposure.Flat) => order(Side.Buy, Intent.Open, OrderType.Market, Sizing.ByRisk, Protect.StopLoss(stop)); rule exit when cross_below(px, average) && exposure_is(Exposure.Open) => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(qty(1))); flatten_on_stop; } fn configuration(share: String) -> String { return "{\"risk_per_trade\": \"" + share + "\", \"max_gross\": \"500000 USDT\", \"max_age\": \"5s\", \"step\": \"0.001\"}"; } fn main() -> Result<Unit, Error> { let datasets = market.datasets("BTCUSDT")?; let ds = datasets.first().expect("no published BTCUSDT dataset on this machine"); let spec = backtest.Spec { strategy: trend_sized_by_risk(20, 1.0), 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.Fraction(bps(1)), latency: 50ms, market_fill: backtest.MarketFill.NextPrint, limit_fill: backtest.LimitFill.TradeThrough, }, }; print("risk per trade | trades | realized | deepest fall | final equity"); for share in ["0.0025", "0.005", "0.01", "0.02"] { match backtest.run_with_risk(spec, configuration(share)) { Ok(report) => { print(share + " | " + to_string(report.trades) + " | " + to_string(report.realized_pnl) + " | " + to_string(report.max_drawdown) + " | " + to_string(report.final_equity)); } Err(e) => { print(share + " | not run: " + e.code + " " + e.message); } } } return Ok(()); }