Skip to content
← All examples

Example 47

Live vwap reversion

the VWAP third-deviation reversion of `46_vwap_3sd_reversion.tzs` (a bar closes beyond the third deviation of the session VWAP; the target

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.1, <0.2.0
Host
>=0.1.8, <0.2.0
Needs
features >=0.1.3, <0.2.0trade >=0.1.0, <0.2.0

Source

// Purpose: the VWAP third-deviation reversion of `46_vwap_3sd_reversion.tzs` (a bar closes beyond the third deviation of the session VWAP; the target
// is the second deviation, the stop is 1:1), **handed to the terminal to run where this script is started**: on a replay, on the live market in
// real time, or -- inserted in the Datasets window -- as a backtest over the datasets chosen. One script, one line, the same strategy and rules.
//
// `trade.run` returns at once. The terminal then tells the person what the script reads (the session's VWAP and its spread need the session's
// prints) and asks whether to load them -- computed on this machine, on demand -- before it starts; and which account it trades is the person's
// choice where they started the script (a replay's practice account, the demo account, or the real one if they switched it on), never the script's.
// 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.1, <0.2.0";
host "ttt" ">=0.1.8, <0.2.0";
requires "features" ">=0.1.3, <0.2.0";
requires "trade" ">=0.1.0, <0.2.0";

strategy vwap_3sd_reversion(entry_k: Decimal, target_k: Decimal, size: Quantity) version "1.0.0" {
    // What the market is doing: the last print, the last closed bar, the VWAP and its spread.
    let px = features.price(features.Source.AggTrades);
    let bar = features.bar_close();
    let vw = features.vwap(features.Source.AggTrades);
    let sd = features.vwap_spread(features.Source.AggTrades);
    let lower = vw - entry_k * sd;
    let upper = vw + entry_k * sd;

    // True on the one step where a new bar has closed -- so a bar is looked at once, not at every print until the next one.
    let new_bar = bar != prev(bar);

    // The open trade, as it was decided: which side, at what price, and where the VWAP and its spread were then.
    let held = features.position_sign();
    let entry = features.entry_price();
    let entry_vw = features.entry_vwap(features.Source.AggTrades);
    let entry_sd = features.entry_spread(features.Source.AggTrades);
    let long_target = entry_vw + target_k * entry_sd;
    let long_stop = entry - (long_target - entry);
    let short_target = entry_vw - target_k * entry_sd;
    let short_stop = entry + (entry - short_target);

    rule long_target_hit when exposure_is(Exposure.Open) && held > 0 && px >= long_target
        => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule long_stop_hit when exposure_is(Exposure.Open) && held > 0 && px <= long_stop
        => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule short_target_hit when exposure_is(Exposure.Open) && held < 0 && px <= short_target
        => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule short_stop_hit when exposure_is(Exposure.Open) && held < 0 && px >= short_stop
        => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size));

    rule enter_long when exposure_is(Exposure.Flat) && new_bar && bar < lower
        => order(Side.Buy, Intent.Open, OrderType.Market, Sizing.Fixed(size));
    rule enter_short when exposure_is(Exposure.Flat) && new_bar && bar > upper
        => order(Side.Sell, Intent.Open, OrderType.Market, Sizing.Fixed(size));
    flatten_on_stop;
}

fn main() -> Result<Unit, Error> {
    // The target on the second deviation FARTHEST from the entry (2.0); -2.0 puts it on the nearest.
    let run = trade.run(vwap_3sd_reversion(3.0, 2.0, qty(0.01)))?;
    print(run.name + " on " + run.target + ": " + run.state);
    return Ok(());
}