← All examples
Example 50
Sweep fade managed
a managed order-flow trade, written to use what a complex strategy needs: an entry that carries its own stop and target, a part of the
- Category
- Host: needs the terminal's data and engine
- Permissions
- orders.submit
- Before you run it
- a chart in hand on the live market or a replay, whose instrument the live feed serves (aggregated prints and closed bars)
- What it does
- asks the terminal to run the strategy on that market; once running it places orders on the account the person chose.
- How to run it
- Add script on the Market Replay window or the title bar's script icon (replay or real time); Insert strategy in the Datasets window (backtest).
- Language
>=0.1.2, <0.2.0- Host
>=0.1.9, <0.2.0- Needs
- features >=0.1.4, <0.2.0trade >=0.1.0, <0.2.0
Source
// Purpose: a managed order-flow trade, written to use what a complex strategy needs: an entry that carries its own stop and target, a part of the // position taken off on the way, the stop brought to break-even once it has, a time limit, and a rest between trades. // // SETUP the bar that just closed went THROUGH the edge of the last `lookback` bars' range and closed back inside it, with the aggressors // pushing into the edge (buying into a high that did not hold, selling into a low that did not): a failed break. // ENTRY against the break, at the market. The stop rests `pad` dollars beyond the bar's extreme; the distance from the price to it is the // trade's risk, R, remembered from the entry (`at_entry`). // MANAGE at `first_r` R in favour, half of the position is closed and the stop is moved to the entry price; // the rest runs to the target, `final_r` R, or is closed after `max_minutes`. // REST no new trade for `rest_minutes` after one closes. // // HONEST NOTE ON ITS EDGE: IT HAS NONE THAT WAS FOUND. This setup was studied on the twenty days of BTCUSDT prints recorded on this machine. // As written here (the 8-hour range, the stop 5 dollars past the bar), over those twenty days it would have taken 251 trades and made +0.5 basis // points a trade before fees and LOST 10 a trade after them (taker 5 bp and 1 bp of slippage, maker 2 bp): its risk is a few dollars, and a // round trip costs more than the move it catches. A variant with a wide stop made +13 bp a trade net on the first twelve days and lost 23 on the // eight kept aside. It is here to show how a managed trade is written, and to be studied and changed -- not to be trusted with money. // Category: host // Permissions: orders.submit // Preconditions: a chart in hand on the live market or a replay, whose instrument the live feed serves (aggregated prints and closed bars) // Side effects: asks the terminal to run the strategy on that market; once running it places orders on the account the person chose. // Run: Add script on the Market Replay window or the title bar's script icon (replay or real time); Insert strategy in the Datasets window (backtest). lang ">=0.1.2, <0.2.0"; host "ttt" ">=0.1.9, <0.2.0"; requires "features" ">=0.1.4, <0.2.0"; requires "trade" ">=0.1.0, <0.2.0"; strategy sweep_fade(lookback: Int, pad: Decimal, first_r: Decimal, final_r: Decimal, max_minutes: Decimal, rest_minutes: Decimal, size: Quantity) version "1.0.0" { // The last closed bar, and the range of the `lookback` bars before it. let px = features.price(features.Source.AggTrades); let close = features.bar_close(); let high = features.bar_high(); let low = features.bar_low(); let range_high = features.highest_high(lookback, 1); let range_low = features.lowest_low(lookback, 1); let delta = features.bar_delta(features.Source.AggTrades); // True on the one step where a new bar has closed -- a bar is looked at once. let new_bar = close != prev(close); let failed_up = high > range_high && close < range_high && delta > 0; let failed_down = low < range_low && close > range_low && delta < 0; let rested = features.flat_minutes() >= rest_minutes; // Where the stop goes, and the risk that makes. let short_stop = high + pad; let long_stop = low - pad; // The open trade: its side, its price, and the risk it was taken with -- held from the entry, so that it is still the same after the stop // that defined it has been moved. let held = features.position_sign(); let entry = features.entry_price(); let short_risk = at_entry(short_stop - px); let long_risk = at_entry(px - long_stop); let whole = features.position_fraction() > 0.75; let aged = features.position_minutes() >= max_minutes; // Out of time. rule long_timed_out when exposure_is(Exposure.Open) && held > 0 && aged => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size)); rule short_timed_out when exposure_is(Exposure.Open) && held < 0 && aged => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size)); // The first target: half off, once. rule long_first when exposure_is(Exposure.Open) && held > 0 && whole && px >= entry + first_r * long_risk => order(Side.Sell, Intent.Reduce, OrderType.Market, Sizing.PercentOfPosition(percent(50))); rule short_first when exposure_is(Exposure.Open) && held < 0 && whole && px <= entry - first_r * short_risk => order(Side.Buy, Intent.Reduce, OrderType.Market, Sizing.PercentOfPosition(percent(50))); // What is left cannot lose: the stop to the entry price, once. rule long_safe when exposure_is(Exposure.Open) && held > 0 && !whole && features.stop_price() < entry => protect(Protect.StopLoss(entry)); rule short_safe when exposure_is(Exposure.Open) && held < 0 && !whole && features.stop_price() > entry => protect(Protect.StopLoss(entry)); // The entries, each with its stop beyond the bar's extreme and its target `final_r` risks away. rule fade_high when exposure_is(Exposure.Flat) && new_bar && failed_up && rested => order(Side.Sell, Intent.Open, OrderType.Market, Sizing.Fixed(size), Protect.Bracket(px - final_r * (short_stop - px), short_stop)); rule fade_low when exposure_is(Exposure.Flat) && new_bar && failed_down && rested => order(Side.Buy, Intent.Open, OrderType.Market, Sizing.Fixed(size), Protect.Bracket(px + final_r * (px - long_stop), long_stop)); flatten_on_stop; } fn main() -> Result<Unit, Error> { // The 8-hour range; the stop 5 dollars past the bar; half off at 1 R; the rest to 3 R or four hours; half an hour between trades. let run = trade.run(sweep_fade(480, 5.0, 1.0, 3.0, 240.0, 30.0, qty(0.02)))?; print(run.name + " on " + run.target + ": " + run.state); return Ok(()); }