1Copy the scriptPress Copy script above, or the copy button on the code below.
2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
3Paste over the templateCreate a new strategy, select all of the template text and paste. Press Save and give it a name.
4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.
Source Code
153 lines of Pine Script v5 from pine/trend_join_long.pine, published under MIT. Keep the author's credit and licence lines when you reuse it.
trend_join_long.pine
//@version=5
// =============================================================================
// Quality-gated trend-join-long (gap-and-go) — TradingView-native version
// -----------------------------------------------------------------------------
// Mirrors the Python system, per symbol/chart:
// Stage 1 3-yr avg ROCE >= 12% AND market cap > $1B (fundamentals)
// Stage 2 daily uptrend: close>EMA200, EMA50>EMA200, EMA50 rising
// Stage 3 gap-and-go: gap>3% + premarket vol>20k + first-hour vol>1M
// + price crosses above session VWAP
// Risk 1% risk sizing, ATR stop, ATR chandelier trail, trend-break exit
//
// HOW TO USE
// * Add to an INTRADAY chart (e.g. 5m) of a US stock.
// * Enable "Extended hours" on the chart, or the premarket-volume gate can't pass.
// * ROCE needs enough loaded history to have seen 3 annual reports.
// * This runs on a TradingView paper chart and can drive alerts/webhooks; it is a
// research tool — validate before any real use. Not financial advice.
// =============================================================================
strategy("Quality Trend-Join-Long (gap-and-go)", overlay=true,
default_qty_type=strategy.fixed, pyramiding=0, calc_on_every_tick=false,
initial_capital=100000, currency=currency.USD)
// ----------------------------- Inputs ----------------------------------------
grpF = "Stage 1 — fundamentals"
roceMin = input.float(0.12, "Min 3-yr avg ROCE", step=0.01, group=grpF)
mktCapMin = input.float(1e9, "Min market cap ($)", group=grpF)
grpT = "Stage 2 — daily trend"
emaFastLen = input.int(50, "EMA fast", group=grpT)
emaSlowLen = input.int(200, "EMA slow", group=grpT)
slopeLkbk = input.int(5, "EMA-fast slope lookback", group=grpT)
grpE = "Stage 3 — gap-and-go entry"
gapMin = input.float(0.03, "Min overnight gap", step=0.01, group=grpE)
preVolMin = input.float(20000, "Min premarket volume", group=grpE)
hourVolMin = input.float(1000000,"Min first-hour volume", group=grpE)
windowMin = input.int(60, "First-hour window (min)", group=grpE)
grpR = "Risk"
riskPct = input.float(0.01, "Risk per trade", step=0.005, group=grpR)
atrLen = input.int(14, "ATR length", group=grpR)
atrMult = input.float(2.0, "ATR stop multiple", step=0.5, group=grpR)
exitAtVwap = input.bool(true, "Exit when price hits VWAP (else within % above)", group=grpR)
vwapExitPct= input.float(0.05, " ...% above VWAP (proximity mode only)", step=0.01, group=grpR)
// ------------------------ Stage 1: fundamentals ------------------------------
// Collect the last 3 fiscal-year ROCE readings as the annual reports arrive.
ebitFY = request.financial(syminfo.tickerid, "EBIT", "FY")
taFY = request.financial(syminfo.tickerid, "TOTAL_ASSETS", "FY")
clFY = request.financial(syminfo.tickerid, "TOTAL_CURRENT_LIABILITIES", "FY")
var float[] roceHist = array.new_float()
newAnnual = not na(taFY) and taFY != taFY[1]
if newAnnual
ce = taFY - clFY
if ce > 0 and not na(ebitFY)
array.push(roceHist, ebitFY / ce)
if array.size(roceHist) > 3
array.shift(roceHist)
avgRoce = array.size(roceHist) > 0 ? array.avg(roceHist) : na
roceOK = array.size(roceHist) >= 3 and avgRoce >= roceMin
// Market cap = shares outstanding * price. (Swap the id if your data uses another.)
sharesOut = request.financial(syminfo.tickerid, "TOTAL_SHARES_OUTSTANDING", "FQ")
mktCap = na(sharesOut) ? na : sharesOut * close
mcapOK = not na(mktCap) and mktCap > mktCapMin
// ------------------------ Stage 2: daily trend -------------------------------
dailyUptrend = request.security(syminfo.tickerid, "D",
close > ta.ema(close, emaSlowLen)
and ta.ema(close, emaFastLen) > ta.ema(close, emaSlowLen)
and ta.ema(close, emaFastLen) > ta.ema(close, emaFastLen)[slopeLkbk],
lookahead=barmerge.lookahead_off)
dailyBelowFast = request.security(syminfo.tickerid, "D",
close < ta.ema(close, emaFastLen), lookahead=barmerge.lookahead_off)
// ------------------------ Stage 3: gap-and-go --------------------------------
// Overnight gap from daily open vs prior daily close.
dOpen = request.security(syminfo.tickerid, "D", open, lookahead=barmerge.lookahead_off)
dPrevClse = request.security(syminfo.tickerid, "D", close[1], lookahead=barmerge.lookahead_off)
gap = (dOpen - dPrevClse) / dPrevClse
gapOK = not na(gap) and gap > gapMin
// Per-day volume accumulators (premarket + first hour of regular session).
newDay = ta.change(time("D")) != 0
var float preVol = 0.0
var float hourVol = 0.0
var int regOpenTime = na
if newDay
preVol := 0.0
hourVol := 0.0
regOpenTime := na
if session.ispremarket
preVol += volume
if session.ismarket
if na(regOpenTime)
regOpenTime := time
if time <= regOpenTime + windowMin * 60 * 1000
hourVol += volume
preVolOK = preVol > preVolMin
hourVolOK = hourVol > hourVolMin
// VWAP reclaim (the join trigger).
crossUpVWAP = ta.crossover(close, ta.vwap)
allGates = roceOK and mcapOK and dailyUptrend and gapOK and preVolOK and hourVolOK and crossUpVWAP
// ------------------------------ Risk / orders --------------------------------
atrVal = ta.atr(atrLen)
riskPerShare = atrMult * atrVal
qty = riskPerShare > 0 ? math.floor((strategy.equity * riskPct) / riskPerShare) : 0
enterLong = allGates and strategy.position_size == 0 and session.ismarket and qty > 0
if enterLong
strategy.entry("Long", strategy.long, qty=qty)
// Chandelier trailing stop (ratchets up) + trend-break exit.
var float trailStop = na
if strategy.position_size > 0
chand = high - atrMult * atrVal
trailStop := na(trailStop) ? close - atrMult * atrVal : math.max(trailStop, chand)
strategy.exit("Exit", "Long", stop=trailStop)
vwapExitLevel = exitAtVwap ? ta.vwap : ta.vwap * (1 + vwapExitPct)
if close <= vwapExitLevel
strategy.close("Long", comment="at/near VWAP")
if dailyBelowFast
strategy.close("Long", comment="trend break")
else
trailStop := na
// ------------------------------- Plots ---------------------------------------
plot(ta.vwap, "VWAP", color=color.new(color.orange, 0))
plot(ta.ema(close, emaFastLen), "EMA fast", color=color.new(color.blue, 0))
plot(ta.ema(close, emaSlowLen), "EMA slow", color=color.new(color.gray, 0))
plot(strategy.position_size > 0 ? trailStop : na, "Trail stop", color=color.new(color.red, 0), style=plot.style_linebr)
plotshape(enterLong, "Entry", shape.triangleup, location.belowbar, color.new(color.green, 0), size=size.small)
// Gate status table (top-right).
var table t = table.new(position.top_right, 1, 7, border_width=1)
if barstate.islast
f_row(i, txt, ok) =>
table.cell(t, 0, i, txt, text_color=ok ? color.green : color.red,
text_size=size.small, text_halign=text.align_left)
table.cell(t, 0, 0, "Quality trend-join-long", text_color=color.white, text_size=size.small)
f_row(1, "ROCE 3y " + (na(avgRoce) ? "n/a" : str.tostring(avgRoce*100, "#.0") + "%"), roceOK)
f_row(2, "MktCap " + (na(mktCap) ? "n/a" : "$" + str.tostring(mktCap/1e9, "#.0") + "B"), mcapOK)
f_row(3, "Daily uptrend", dailyUptrend)
f_row(4, "Gap " + str.tostring(gap*100, "#.0") + "%", gapOK)
f_row(5, "PreVol " + str.tostring(preVol/1000, "#") + "k", preVolOK)
f_row(6, "HourVol " + str.tostring(hourVol/1e6, "#.00") + "M", hourVolOK)
Overview
Quality Trend-Join-Long (gap-and-go) filters equities across three sequential stages: verifying fundamental criteria (minimum three-year average ROCE and market capitalization via financial data requests), confirming a daily uptrend using fast and slow EMAs, and validating intraday momentum through overnight gaps, premarket volume, first-hour volume, and session VWAP crossovers. Positions are sized by risk percentage and protected by an ATR-based stop loss, with additional exit options tied to VWAP breaches.
Fundamental filtering using ROCE and market capitalization
Daily EMA trend and slope verification
Premarket and first-hour volume gating
Intraday session VWAP breakout entry and exit logic
The inputs you can change from the gear icon on the chart. Defaults are the author's.
Setting
Type
Default
Variable
Min 3-yr avg ROCE
float
0.12
roceMin
Min market cap ($)
float
1e9
mktCapMin
EMA fast
int
50
emaFastLen
EMA slow
int
200
emaSlowLen
EMA-fast slope lookback
int
5
slopeLkbk
Min overnight gap
float
0.03
gapMin
Min premarket volume
float
20000
preVolMin
Min first-hour volume
float
1000000
hourVolMin
First-hour window (min)
int
60
windowMin
Risk per trade
float
0.01
riskPct
ATR length
int
14
atrLen
ATR stop multiple
float
2.0
atrMult
Show all 14 settings
Setting
Type
Default
Variable
Exit when price hits VWAP (else within % above)
bool
true
exitAtVwap
...% above VWAP (proximity mode only)
float
0.05
vwapExitPct
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 Pine v4 strategy draws on the price chart and filters breakouts with a fixed Supertrend, ATR length, volume moving-average markup, and moving-average alignment, plus short and long high-low periods. Trade direction defaults to long and can include shorts.
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
This strategy combines the ATR-banded Q-Trend indicator with the Klinger Volume Oscillator (KVO) to execute confluence trades. It enters long when a Q-Trend buy trigger aligns with a positive KVO value and a bullish candle confirmation, taking short trades und
This strategy plots a comparative relative strength line against a benchmark symbol in a separate pane. It calculates price and volume simple moving averages alongside a multi-period highest high. Long trades enter using full equity when price exceeds its movi
This trend-following strategy executes a classic Donchian channel breakout system designed to cross-validate backtest results against external framework benchmarks. It triggers a long entry when the closing price breaks above the highest high of the prior entr
This strategy plots running pivot highs as red R circles and pivot lows as blue S circles directly on the price chart. It computes an EMA 3 and a Cto trend line from close prices, then generates long signals on upward EMA-Cto crossovers combined with price pos