← 모든 예제
예제 51
Intraday momentum
Bitcoin intraday time-series momentum, as published -- Shen, Urquhart and Wang, "Bitcoin intraday time-series momentum",
- 분류
- Host: 터미널의 데이터와 엔진 필요
- 권한
- orders.submit
- 실행하기 전에
- BTCUSDT one-minute candles (klines), with at least a day and a half of them before the first trade
- 하는 일
- asks the terminal to run the strategy; once running it places orders on the account the person chose.
- 실행 방법
- Insert strategy in the Datasets window (backtest over consecutive days), or Add script on a replay or the live market.
- 언어
>=0.1.2, <0.2.0- 호스트
>=0.1.10, <0.2.0- 필요한 것
- features >=0.1.5, <0.2.0trade >=0.1.0, <0.2.0
소스
// Purpose: Bitcoin intraday time-series momentum, as published -- Shen, Urquhart and Wang, "Bitcoin intraday time-series momentum", // Financial Review 57(2), 2022, pp. 319-344 (doi 10.1111/fire.12290); accepted version free at the University of Reading, // https://centaur.reading.ac.uk/100181/ . Their combined timing rule, eq. (8). // // The paper's trading day, for BTC/USD, in US Eastern time (EST, taken here as UTC-5 all year): it opens at 9:00 EST, when the // volume spikes (Bitstamp's open in their Table 1), and closes at 17:00 EST, when CME's Bitcoin futures stop for an hour. In UTC: // // r_onfh the "overnight + first half-hour" return: the price at 9:30 EST (14:30 UTC) over the previous day's close at 17:00 EST // (22:00 UTC the day before) -- eq. (1); // r_slh the second-to-last half-hour: the price at 16:30 EST (21:30 UTC) over the one at 16:00 EST (21:00 UTC) -- eq. (2). // // ENTRY at 16:30 EST (21:30 UTC): LONG when r_onfh > 0 and r_slh < 0, SHORT when r_onfh <= 0 and r_slh >= 0, nothing otherwise. // EXIT at the close, 17:00 EST (22:00 UTC). One trade a day at most, held half an hour. // // Every price is the close of a one-minute bar that has already closed (`close_ago`): at 21:30 UTC the last closed bar is 21:29's, // 21:00's price is 30 bars back, 14:30's 420, and yesterday's 22:00 is 1410 -- nothing is read that a live market would not have // had at that moment. The first day of a backtest has no previous close, and trades nothing. // // What the paper reports, before costs, 2013-2020, annualized: 16.7% return, Sharpe 1.72, 58% of trades right (Table 5). Its own // break-even cost is 10 bps a trade (Table 8): at a taker fee of 5.5 bps a side the rule does not pay without leverage -- the // authors say so. Results on later data are not theirs. // Category: host // Permissions: orders.submit // Preconditions: BTCUSDT one-minute candles (klines), with at least a day and a half of them before the first trade // Side effects: asks the terminal to run the strategy; once running it places orders on the account the person chose. // Run: Insert strategy in the Datasets window (backtest over consecutive days), or Add script on a replay or the live market. lang ">=0.1.2, <0.2.0"; host "ttt" ">=0.1.10, <0.2.0"; requires "features" ">=0.1.5, <0.2.0"; requires "trade" ">=0.1.0, <0.2.0"; strategy intraday_momentum(size: Quantity) version "1.0.0" { let minute = features.minute_of_day(); // The prices the two returns are made of, as of the decision at 21:30 UTC. let now = features.close_ago(0); // 21:30 UTC, 16:30 EST let half_hour_ago = features.close_ago(30); // 21:00 UTC, 16:00 EST let first_half_hour = features.close_ago(420); // 14:30 UTC, 9:30 EST let last_close = features.close_ago(1410); // 22:00 UTC the day before, 17:00 EST let r_onfh_up = first_half_hour > last_close; let r_slh_down = now < half_hour_ago; let decision = minute == 1290; // the minute that begins at 21:30 UTC let closing = minute >= 1320 || minute < 1290; // from 22:00 UTC on rule go_long when exposure_is(Exposure.Flat) && decision && r_onfh_up && r_slh_down => order(Side.Buy, Intent.Open, OrderType.Market, Sizing.Fixed(size)); rule go_short when exposure_is(Exposure.Flat) && decision && !r_onfh_up && !r_slh_down => order(Side.Sell, Intent.Open, OrderType.Market, Sizing.Fixed(size)); rule close_long when exposure_is(Exposure.Open) && features.position_sign() > 0 && closing => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size)); rule close_short when exposure_is(Exposure.Open) && features.position_sign() < 0 && closing => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size)); flatten_on_stop; } fn main() -> Result<Unit, Error> { let run = trade.run(intraday_momentum(qty(0.01)))?; print(run.name + " on " + run.target + ": " + run.state); return Ok(()); }