← 모든 예제
예제 45
Orderflow strategy
an order-flow strategy, described in T0 and run by TTT's engine. It buys when sellers were absorbed -- heavy one-sided selling that did not
- 분류
- Host: 터미널의 데이터와 엔진 필요
- 권한
- market.readbacktest.run
- 실행하기 전에
- at least one published BTCUSDT dataset on this machine (Datasets window)
- 하는 일
- starts two backtest jobs (they appear in the Jobs panel); writes their runs under the terminal's runs folder.
- 실행 방법
- grant market.read and backtest.run in the T0 Lang window, Run. "Stop job" stops only the backtest; "Stop program" stops both.
- 언어
>=0.1.1, <0.2.0- 호스트
>=0.1.1, <0.2.0- 필요한 것
- market >=0.1.1, <0.2.0features >=0.1.0, <0.2.0backtest >=0.1.1, <0.2.0
소스
// Purpose: an order-flow strategy, described in T0 and run by TTT's engine. It buys when sellers were absorbed -- heavy one-sided selling that did not // move price (`inferred_absorption_sell_side`: INFERRED from the tape, never observed) -- while price is under the session VWAP, and sells when price // crosses back up through the VWAP. It is run twice on the newest published BTCUSDT dataset, with a loose and a strict notion of "heavy", and the two // reports are printed side by side: the point of a backtest is the comparison, and a rule that only works at one threshold is a curve fit. // `min_volume` is in units of the instrument, like an order's size: 1.0 and 5.0 below are one and five bitcoin sold into the bar. // Category: host // Permissions: market.read, backtest.run // Preconditions: at least one published BTCUSDT dataset on this machine (Datasets window) // Side effects: starts two backtest jobs (they appear in the Jobs panel); writes their runs under the terminal's runs folder. // Run: grant market.read and backtest.run in the T0 Lang window, Run. "Stop job" stops only the backtest; "Stop program" stops both. lang ">=0.1.1, <0.2.0"; host "ttt" ">=0.1.1, <0.2.0"; requires "market" ">=0.1.1, <0.2.0"; requires "features" ">=0.1.0, <0.2.0"; requires "backtest" ">=0.1.1, <0.2.0"; strategy vwap_absorption(min_volume: Decimal, imbalance_bps: Decimal, size: Quantity) version "1.0.0" { let px = features.price(features.Source.AggTrades); let vw = features.vwap(features.Source.AggTrades); let absorbed = features.inferred_absorption_sell_side(features.Source.AggTrades, min_volume, imbalance_bps); rule enter when absorbed && px < vw && exposure_is(Exposure.Flat) => order(Side.Buy, Intent.Open, OrderType.Market, Sizing.Fixed(size)); rule exit when cross_above(px, vw) && exposure_is(Exposure.Open) => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size)); flatten_on_stop; } fn run(ds: market.Dataset, min_volume: Decimal, imbalance_bps: Decimal) -> Result<Unit, Error> { let job = backtest.submit(backtest.Spec { strategy: vwap_absorption(min_volume, imbalance_bps, qty(0.01)), dataset: ds, start: None, end: None, starting_balance: money(10000, 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, }, })?; let report = backtest.wait(job)?; print("heavy from " + to_string(min_volume) + " at " + to_string(imbalance_bps) + " bps: " + to_string(report.status) + ", " + to_string(report.trades) + " trades, realized " + to_string(report.realized_pnl) + ", fees " + to_string(report.fees_paid)); return Ok(()); } fn main() -> Result<Unit, Error> { let ds = market.datasets("BTCUSDT")?.first().expect("no published BTCUSDT dataset on this machine"); run(ds, 1.0, 6000.0)?; run(ds, 5.0, 8000.0)?; return Ok(()); }