MMTMMT Docs

Strategy runner template

Build a reusable long-and-short paper strategy with deterministic backtesting, live marking, fees, leverage, liquidation, a trade ledger, and a fixed HUD.

The strategy runner template is a complete single-position paper execution engine. It replays the loaded chart as a backtest and then continues from the same confirmed state when realtime data arrives. Strategy signals use the chart context timeframe; protective execution uses confirmed one-minute candles.

Use the template to keep the execution and reporting rules consistent while changing the entry and exit algorithm.

The customization boundary

Four functions are the strategy interface:

fn wantsLong(fast: float?, slow: float?) -> bool {
  return allowLongs && ta.crossover(fast, slow)
}

fn wantsShort(fast: float?, slow: float?) -> bool {
  return allowShorts && ta.crossunder(fast, slow)
}

fn wantsLongExit(fast: float?, slow: float?) -> bool {
  return ta.crossunder(fast, slow)
}

fn wantsShortExit(fast: float?, slow: float?) -> bool {
  return ta.crossover(fast, slow)
}

Replace these helpers and their arguments with the algorithm's close-confirmed inputs. Keep fills, accounting, tables, plots, and HUD code unchanged.

One state machine for history and realtime

Entries and signal exits are simulated in on chart.close. Historical replay calls that handler once for every confirmed strategy candle, and a running chart calls it once when each live strategy candle confirms. This avoids counting several fills while the realtime candle is still changing.

Liquidation checks run in on minute.close from a dedicated tf("1m") subscription. The minute clock is declared before the strategy clock, so a protective fill wins when both timeframes confirm at the same boundary. A new position ignores the already-completed signal minute and becomes eligible on the following minute.

on chart.update marks to market from minute.forming.close, falling back to chart.forming.close and then the last confirmed close. It updates the entry and liquidation plots, active row, and anchored HUD, but does not commit a fill.

Account model

The template exposes initial capital, leverage, margin allocation, fee per fill, slippage per fill in basis points, and maintenance margin as inputs. It models one isolated linear position at a time:

let margin = equity * allocationPct / 100.0
let notional = margin * leverage
let quantity = price > 0.0 ? notional / price : 0.0
let fee = notional * feePct / 100.0

Entry and exit fees are both included in net PnL. Buys fill above the reference price and sells fill below it by the configured slippage. If a one-minute candle opens beyond a liquidation threshold, the open becomes the reference before slippage instead of granting a fill at the crossed level. Equity stays marked at realized value, while the HUD adds active unrealized PnL. The liquidation line is an approximation based on entry price, leverage, and the configured maintenance rate; an exchange's tiered margin, funding, and insurance rules can produce a different liquidation price.

Visual and tabular outputs

The chart shows long entries, short entries, exits, active entry, and active liquidation. A table window retains the active position plus up to 999 closed trades. The anchor.topRight entity pools form a fixed HUD with mode, side, marked equity, open PnL, win rate, profit factor, maximum drawdown, leverage, and fees.

Paper execution boundary

Scripting v3 does not expose a broker order API. REALTIME means the simulator and visuals are consuming live chart publications; it does not place an exchange order. Confirmed one-minute execution has up to one minute of trigger latency. A raw-trade subscription can provide finer trigger ordering, but requires a trade-level fill policy and substantially more history. Use the close-confirmed entry and exit markers as the integration signals for an external execution service.

On this page