//@version=5
strategy("15-Min ORB Strategy for NQ - TP3 Runner", overlay=true, default_qty_type=strategy.fixed, default_qty_value=1, pyramiding=0, margin_long=100, margin_short=100)
// ────────────────────────────────────────
// Inputs
// ────────────────────────────────────────
qty = input.int(3, "Total Contracts Qty", minval=1, group="Position Sizing", tooltip="Total contracts to split between TP1, TP2, and TP3.")
tp1Percent = input.int(33, "TP1 %", minval=0, maxval=100, group="Exits")
tp2Percent = input.int(33, "TP2 %", minval=0, maxval=100, group="Exits")
tp3Percent = input.int(34, "TP3 %", minval=0, maxval=100, group="Exits")
rr1 = input.float(1.0, "TP1 (RR)", minval=0.1, step=0.1, group="Exits")
rr2 = input.float(2.0, "TP2 (RR)", minval=0.1, step=0.1, group="Exits")
rr3 = input.float(4.0, "TP3 (RR)", minval=0.1, step=0.1, group="Exits")
slBuffer = input.float(0.0, "SL Buffer (Points)", step=0.25, group="Exits")
// Breakeven Settings
useBE = input.bool(true, "Move SL to Breakeven after TP1?", group="Exits")
beOffset = input.float(0.0, "BE Offset (Points)", minval=0, group="Exits")
// Trailing Settings
useTrail = input.bool(false, "Activate Trailing SL after TP1?", group="Trailing Stop (Post-TP1)")
trailPts = input.float(10.0, "Trailing Distance (Points)", minval=0.25, group="Trailing Stop (Post-TP1)")
showTrailLine = input.bool(true, "Show Red Trailing Line?", group="Trailing Stop (Post-TP1)")
// ────────────────────────────────────────
// State Tracking
// ────────────────────────────────────────
var float orHigh = na
var float orLow = na
var bool entryTaken = false
var bool tp1Hit = false
var float trailPrice = na
// Reset at start of day
if ta.change(time("D", "America/New_York")) != 0
entryTaken := false
tp1Hit := false
orHigh := na
orLow := na
// Detect TP1 Fill (if current position is less than original qty)
if strategy.position_size != 0 and math.abs(strategy.position_size) < qty
tp1Hit := true
// ────────────────────────────────────────
// Time & Session
// ────────────────────────────────────────
inORB = not na(time(timeframe.period, "0930-0945:1234567", "America/New_York"))
isEOD = session.islastbar_regular or (hour(time, "America/New_York") == 15 and minute(time, "America/New_York") >= 55)
if inORB
orHigh := na(orHigh) ? high : math.max(orHigh, high)
orLow := na(orLow) ? low : math.min(orLow, low)
// Breakout Logic
breakoutUp = not inORB and not entryTaken and not na(orHigh) and close > orHigh
breakoutDown = not inORB and not entryTaken and not na(orLow) and close < orLow
// ────────────────────────────────────────
// Entries
// ────────────────────────────────────────
if breakoutUp
strategy.entry("Long", strategy.long, qty=qty)
entryTaken := true
tp1Hit := false
trailPrice := na
if breakoutDown
strategy.entry("Short", strategy.short, qty=qty)
entryTaken := true
tp1Hit := false
trailPrice := na
// ────────────────────────────────────────
// Exit Calculations
// ────────────────────────────────────────
// LONG EXIT LOGIC
if strategy.position_size > 0
riskLong = strategy.position_avg_price - (orLow - slBuffer)
tp1Price = strategy.position_avg_price + (riskLong * rr1)
tp2Price = strategy.position_avg_price + (riskLong * rr2)
tp3Price = strategy.position_avg_price + (riskLong * rr3)
float slLevel = orLow - slBuffer
if useBE and tp1Hit
slLevel := strategy.position_avg_price + beOffset
if useTrail and tp1Hit
trailPrice := na(trailPrice) ? high - trailPts : math.max(trailPrice, high - trailPts)
slLevel := math.max(slLevel, trailPrice)
strategy.exit("L-TP1", "Long", qty_percent=tp1Percent, limit=tp1Price, stop=slLevel, comment_profit="TP1", comment_loss="SL")
strategy.exit("L-TP2", "Long", qty_percent=tp2Percent, limit=tp2Price, stop=slLevel, comment_profit="TP2", comment_loss="SL")
strategy.exit("L-TP3", "Long", qty_percent=tp3Percent, limit=tp3Price, stop=slLevel, comment_profit="TP3", comment_loss=tp1Hit ? "Trail/BE" : "SL")
if isEOD
strategy.close("Long", comment="EOD Close")
// SHORT EXIT LOGIC
if strategy.position_size < 0
riskShort = (orHigh + slBuffer) - strategy.position_avg_price
tp1PriceS = strategy.position_avg_price - (riskShort * rr1)
tp2PriceS = strategy.position_avg_price - (riskShort * rr2)
tp3PriceS = strategy.position_avg_price - (riskShort * rr3)
float slLevelS = orHigh + slBuffer
if useBE and tp1Hit
slLevelS := strategy.position_avg_price - beOffset
if useTrail and tp1Hit
trailPrice := na(trailPrice) ? low + trailPts : math.min(trailPrice, low + trailPts)
slLevelS := math.min(slLevelS, trailPrice)
strategy.exit("S-TP1", "Short", qty_percent=tp1Percent, limit=tp1PriceS, stop=slLevelS, comment_profit="TP1", comment_loss="SL")
strategy.exit("S-TP2", "Short", qty_percent=tp2Percent, limit=tp2PriceS, stop=slLevelS, comment_profit="TP2", comment_loss="SL")
strategy.exit("S-TP3", "Short", qty_percent=tp3Percent, limit=tp3PriceS, stop=slLevelS, comment_profit="TP3", comment_loss=tp1Hit ? "Trail/BE" : "SL")
if isEOD
strategy.close("Short", comment="EOD Close")
if strategy.position_size == 0
trailPrice := na
// ────────────────────────────────────────
// Plots
// ────────────────────────────────────────
plot(orHigh, title="OR High", color=color.new(color.red, 30), linewidth=2, style=plot.style_linebr)
plot(orLow, title="OR Low", color=color.new(color.green, 30), linewidth=2, style=plot.style_linebr)
bgcolor(inORB ? color.new(color.yellow, 92) : na, title="ORB Period")
plot(showTrailLine and strategy.position_size != 0 and tp1Hit and useTrail ? trailPrice : na, "Trail SL Level", color=color.red, style=plot.style_linebr, linewidth=2)
// Dashboard (Expanded for TP3)
if barstate.islast
var table dashboard = table.new(position.top_right, columns=2, rows=8, bgcolor=color.new(color.black, 60), border_width=1, border_color=color.new(color.gray, 50), frame_width=1, frame_color=color.new(color.gray, 30))
table.cell(dashboard, 0, 0, "ORB TP3 Runner", text_color=color.white, bgcolor=#0d47a1)
table.cell(dashboard, 1, 0, "", bgcolor=#0d47a1)
table.cell(dashboard, 0, 1, "OR High", text_color=color.white, bgcolor=color.new(color.red, 70))
table.cell(dashboard, 1, 1, str.tostring(orHigh, "#.##"), text_color=color.red)
table.cell(dashboard, 0, 2, "OR Low", text_color=color.white, bgcolor=color.new(color.green, 70))
table.cell(dashboard, 1, 2, str.tostring(orLow, "#.##"), text_color=color.green)
table.cell(dashboard, 0, 3, "Contracts", text_color=color.white, bgcolor=color.new(color.blue, 70))
table.cell(dashboard, 1, 3, str.tostring(qty), text_color=color.blue)
table.cell(dashboard, 0, 4, "TP1 RR", text_color=color.white, bgcolor=color.new(color.orange, 70))
table.cell(dashboard, 1, 4, str.tostring(rr1), text_color=color.orange)
table.cell(dashboard, 0, 5, "TP2 RR", text_color=color.white, bgcolor=color.new(color.purple, 70))
table.cell(dashboard, 1, 5, str.tostring(rr2), text_color=color.purple)
table.cell(dashboard, 0, 6, "TP3 RR", text_color=color.white, bgcolor=color.new(color.teal, 70))
table.cell(dashboard, 1, 6, str.tostring(rr3), text_color=color.teal)
table.cell(dashboard, 0, 7, "Entry Taken", text_color=color.white, bgcolor=color.new(color.gray, 70))
table.cell(dashboard, 1, 7, entryTaken ? "Yes" : "No", text_color=entryTaken ? color.red : color.lime)
Overview
The position is split across three take profit targets set as risk multiples, with adjustable percentages. The stop sits at the opposite side of the range plus an optional buffer, can move to breakeven after the first target, and can switch to a trailing stop. Open trades close near the end of the session.
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Total Contracts Qty
int
3
qty
TP1 %
int
33
tp1Percent
TP2 %
int
33
tp2Percent
TP3 %
int
34
tp3Percent
TP1 (RR)
float
1.0
rr1
TP2 (RR)
float
2.0
rr2
TP3 (RR)
float
4.0
rr3
SL Buffer (Points)
float
0.0
slBuffer
Move SL to Breakeven after TP1?
bool
true
useBE
BE Offset (Points)
float
0.0
beOffset
Activate Trailing SL after TP1?
bool
false
useTrail
Trailing Distance (Points)
float
10.0
trailPts
Show all 13 settings
Setting
Type
Default
Variable
Show Red Trailing Line?
bool
true
showTrailLine
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.
This script monitors opening gap conditions and breakout behavior relative to the first candle's range across up to twenty configurable stock tickers. It detects whether following bars remain inside the opening range before breaking out, displaying the status
This strategy enters long or short on the price chart when price is on the correct side of a 200-period EMA, MACD agrees, RSI is not at the opposing extreme, ADX exceeds a threshold, volume beats a 20-bar average, and close breaks the recent high or low. A tim
This strategy enters long when price closes above the prior Donchian high and short when it closes below the prior Donchian low, only while flat and inside a Taipei-hour window. It exits on a MACD histogram reversal or through an ATR stop and a percentage take
This intraday strategy implements Mark Fisher's Opening Range Breakout (ORB) methodology tailored for index futures like ES and NQ. It calculates session opening ranges, volume z-scores, and VWAP bands to plot support, resistance, and confirmation levels on th
This strategy tracks an opening session time range to establish directional bias and triggers pullback trades using Stochastic RSI. Once price breaks out of the initial range, it establishes a directional bias and enters when the Stochastic RSI crosses over in
This strategy evaluates breakout and trend opportunities on the price chart using a weighted composite score of volume, trend, and candlestick structure. It tracks volume spikes, fast and slow EMAs, higher-timeframe EMA trend alignment, opening ranges, and ses