, we need to upgrade it from a simple signal generator into a complete, robust algorithmic trading system.
Instead of buying a flat percentage of equity, it now calculates precise position sizing based on risking a fixed percentage of your account (e.g., 1%) per trade.
It dynamically calculates your Stop Loss and Take Profit based on market volatility (Average True Range) and a Risk-to-Reward ratio, rather than holding trades indefinitely.
A dynamic UI table in the corner of the chart that shows you exactly what each of the three timeframes is currently doing in real-time.
Backtesting inputs that allow you to constrain the strategy to specific dates so you can measure forward-testing vs. historical performance.
Code: Select all
//@version=5
strategy("Triple Timeframe Pro [Algo]", overlay=true, initial_capital=10000, default_qty_type=strategy.cash, commission_value=0.03, margin_long=100, margin_short=100)
// =========================================================================
// 1. INPUTS & PARAMETERS
// =========================================================================
grp_tf = "--- Timeframe Setup ---"
htf = input.timeframe("240", "Higher Timeframe (Bias)", group=grp_tf)
mtf = input.timeframe("15", "Medium Timeframe (Setup)", group=grp_tf)
grp_strat = "--- Technical Parameters ---"
ma_fast_len = input.int(50, "HTF Fast EMA", group=grp_strat)
ma_slow_len = input.int(200, "HTF Slow EMA", group=grp_strat)
rsi_len = input.int(14, "MTF RSI Length", group=grp_strat)
rsi_ob = input.float(70, "MTF Overbought Level", group=grp_strat)
rsi_os = input.float(30, "MTF Oversold Level", group=grp_strat)
ltf_ema_len = input.int(10, "LTF Trigger EMA", group=grp_strat)
grp_risk = "--- Risk & Trade Management ---"
risk_perc = input.float(1.0, "Risk Per Trade (%)", step=0.1, group=grp_risk)
atr_len = input.int(14, "ATR Length (For Stop Loss)", group=grp_risk)
sl_mult = input.float(1.5, "Stop Loss (ATR Multiplier)", step=0.1, group=grp_risk)
rr_ratio = input.float(2.0, "Take Profit (Risk:Reward Ratio)", step=0.1, group=grp_risk)
grp_time = "--- Backtest Window ---"
start_date = input.time(timestamp("2024-01-01 00:00"), "Start Date", group=grp_time)
end_date = input.time(timestamp("2030-01-01 00:00"), "End Date", group=grp_time)
in_window = true
// =========================================================================
// 2. NON-REPAINTING SECURITY FUNCTION
// =========================================================================
// Pulls the last closed bar of the higher timeframe to prevent backtest bias
f_secure_htf(_tf, _src) =>
request.security(syminfo.tickerid, _tf, _src[1], lookahead = barmerge.lookahead_on)
// =========================================================================
// 3. TIMEFRAME CALCULATIONS
// =========================================================================
// -- HTF Bias --
htf_fast_ema = f_secure_htf(htf, ta.ema(close, ma_fast_len))
htf_slow_ema = f_secure_htf(htf, ta.ema(close, ma_slow_len))
htf_bullish = (htf_fast_ema > htf_slow_ema)
htf_bearish = (htf_fast_ema < htf_slow_ema)
// -- MTF Setup Zone --
mtf_rsi = f_secure_htf(mtf, ta.rsi(close, rsi_len))
mtf_oversold = (mtf_rsi < rsi_os)
mtf_overbought = (mtf_rsi > rsi_ob)
// -- LTF Trigger --
ltf_ema = ta.ema(close, ltf_ema_len)
ltf_buy_trigger = (open < ltf_ema and close > ltf_ema)
ltf_sell_trigger = (open > ltf_ema and close < ltf_ema)
// =========================================================================
// 4. RISK MANAGEMENT & SIZING
// =========================================================================
ltf_atr = ta.atr(atr_len)
sl_dist = ltf_atr * sl_mult
tp_dist = sl_dist * rr_ratio
// Calculate how many units we can buy without risking more than X% of account
risk_in_dollars = (strategy.equity * (risk_perc / 100))
pos_size = risk_in_dollars / sl_dist
// =========================================================================
// 5. EXECUTION LOGIC
// =========================================================================
// Only trigger if we are flat (not already in a position)
is_flat = strategy.position_size == 0
long_cond = htf_bullish and mtf_oversold and ltf_buy_trigger and in_window and is_flat
short_cond = htf_bearish and mtf_overbought and ltf_sell_trigger and in_window and is_flat
// Entry & Automated Bracket Orders (SL/TP)
if (long_cond)
strategy.entry("Long", strategy.long, qty=pos_size)
strategy.exit("Exit Long", "Long", stop=close - sl_dist, limit=close + tp_dist)
if (short_cond)
strategy.entry("Short", strategy.short, qty=pos_size)
strategy.exit("Exit Short", "Short", stop=close + sl_dist, limit=close - tp_dist)
// =========================================================================
// 6. VISUALIZATION & UI DASHBOARD
// =========================================================================
// Plot LTF Trigger EMA
plot(ltf_ema, color=color.new(color.yellow, 0), title="LTF Trigger EMA")
// Draw visual markers on the chart where trades are taken
plotshape(long_cond, title="Buy Signal", style=shape.triangleup, location=location.belowbar, color=color.green, size=size.small)
plotshape(short_cond, title="Sell Signal", style=shape.triangledown, location=location.abovebar, color=color.red, size=size.small)
// UI Dashboard configuration
var table dash = table.new(position.top_right, 2, 4, border_width=1, border_color=color.new(color.gray, 50))
if barstate.islast
// Headers
table.cell(dash, 0, 0, "Timeframe", text_color=color.white, bgcolor=color.new(color.black, 20))
table.cell(dash, 1, 0, "Current Status", text_color=color.white, bgcolor=color.new(color.black, 20))
// HTF Row
table.cell(dash, 0, 1, "HTF Bias", text_color=color.white, bgcolor=color.new(color.black, 50))
table.cell(dash, 1, 1, htf_bullish ? "BULLISH" : (htf_bearish ? "BEARISH" : "FLAT"), text_color=color.white, bgcolor=htf_bullish ? color.new(color.teal, 30) : (htf_bearish ? color.new(color.maroon, 30) : color.new(color.gray, 50)))
// MTF Row
table.cell(dash, 0, 2, "MTF Zone", text_color=color.white, bgcolor=color.new(color.black, 50))
table.cell(dash, 1, 2, mtf_oversold ? "OVERSOLD" : (mtf_overbought ? "OVERBOUGHT" : "WAITING"), text_color=color.white, bgcolor=mtf_oversold ? color.new(color.teal, 30) : (mtf_overbought ? color.new(color.maroon, 30) : color.new(color.gray, 50)))
// LTF Row
table.cell(dash, 0, 3, "LTF Trigger", text_color=color.white, bgcolor=color.new(color.black, 50))
table.cell(dash, 1, 3, ltf_buy_trigger ? "BUY FIRED" : (ltf_sell_trigger ? "SELL FIRED" : "WAITING"), text_color=color.white, bgcolor=ltf_buy_trigger ? color.new(color.teal, 30) : (ltf_sell_trigger ? color.new(color.maroon, 30) : color.new(color.gray, 50)))