Skip to content
← All examples

Example 48

Forming bar momentum

a strategy that decides INSIDE the bar, from the bar still forming -- not from the last one that closed. It buys when, in the minute in

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)
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.9, <0.2.0
Needs
features >=0.1.4, <0.2.0trade >=0.1.0, <0.2.0

Source

// Purpose: a strategy that decides INSIDE the bar, from the bar still forming -- not from the last one that closed. It buys when, in the minute in
// progress, buyers have taken at least `min_delta` more than sellers, the price is at that bar's high and has come `min_move` up from its open;
// it sells on the mirror of that. It is out at a target of two moves, at a stop of one, or as soon as the bar's buying and selling turn against it.
//
// The bar still forming (`features.forming_open`, `forming_high`, `forming_low`, `forming_volume`, `forming_delta`) is made of the prints the
// strategy is given, so it is the same bar in a backtest, in a replay and live, and it changes at every print. It is unknown in a minute the
// strategy did not see from its start (a part of a bar is another bar) and from a bar's close until the next print, and a rule that reads an
// unknown value does not fire. Its close is `features.price`. Volume and delta are in units of the instrument, like an order's size.
// 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)
// 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.9, <0.2.0";
requires "features" ">=0.1.4, <0.2.0";
requires "trade" ">=0.1.0, <0.2.0";

strategy forming_bar_momentum(min_delta: Decimal, min_move: Decimal, size: Quantity) version "1.0.0" {
    // The bar still forming, as the prints so far make it.
    let px = features.price(features.Source.AggTrades);
    let open = features.forming_open(features.Source.AggTrades);
    let high = features.forming_high(features.Source.AggTrades);
    let low = features.forming_low(features.Source.AggTrades);
    let delta = features.forming_delta(features.Source.AggTrades);

    // The open trade: which side, and at what price.
    let held = features.position_sign();
    let entry = features.entry_price();

    rule long_target when exposure_is(Exposure.Open) && held > 0 && px >= entry + 2.0 * min_move
        => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule long_stop when exposure_is(Exposure.Open) && held > 0 && px <= entry - min_move
        => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule long_turned when exposure_is(Exposure.Open) && held > 0 && delta < 0
        => order(Side.Sell, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule short_target when exposure_is(Exposure.Open) && held < 0 && px <= entry - 2.0 * min_move
        => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule short_stop when exposure_is(Exposure.Open) && held < 0 && px >= entry + min_move
        => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size));
    rule short_turned when exposure_is(Exposure.Open) && held < 0 && delta > 0
        => order(Side.Buy, Intent.Close, OrderType.Market, Sizing.Fixed(size));

    rule enter_long when exposure_is(Exposure.Flat) && delta >= min_delta && px >= high && px - open >= min_move
        => order(Side.Buy, Intent.Open, OrderType.Market, Sizing.Fixed(size));
    rule enter_short when exposure_is(Exposure.Flat) && delta + min_delta <= 0 && px <= low && open - px >= min_move
        => order(Side.Sell, Intent.Open, OrderType.Market, Sizing.Fixed(size));
    flatten_on_stop;
}

fn main() -> Result<Unit, Error> {
    // Five units of the instrument more bought than sold in the minute, and ten dollars up from its open.
    let run = trade.run(forming_bar_momentum(5.0, 10.0, qty(0.01)))?;
    print(run.name + " on " + run.target + ": " + run.state);
    return Ok(());
}