ProRealCode - Trading & Coding with ProRealTime™
Hi ProRealTime team,
I’m building a single ProBacktest/ProOrder strategy that automatically selects among 8 sub-strategies (Trend-Confirmation, Divergence Reversal, Breakout, Pullback, ORB, Mean-Reversion to VWAP, Squeeze→Expansion, and News/Volume-Impulses). It computes a Quality Score gating (0–6, must be ≥4), and then ranks the eligible strategies each bar to decide whether to go long/short. Risk management uses ATR-based stops/targets with an optional trailing stop, and the system trades only 08:00–16:30 London.
To maximize compatibility, I:
Use fractions (e.g., 5/4 instead of 1.25) to avoid decimal-locale issues.
Avoid underscores in the key sizing variables.
Avoid multiple statements per line.
Compute MACD step-by-step (no inline subtraction) and a manual intraday VWAP that resets daily.
Keep indicators to standard names: ExponentialAverage, RSI, AverageTrueRange, Average, Lowest.
Issue we’re hitting:
Even with the simplifications, the editor frequently flags “Unknown command line 1”, and when we isolate, we get hard errors on lines like:
Assignment to macdLine = emaMacdFast - emaMacdSlow (fixed by expanding into two assignments), then
The ATR line atr = AverageTrueRange[atrLen] (or with (close)), and earlier we also saw failures when using comma decimals (hence the switch to fractions).
Could you please confirm, for the IG/ProOrder build we are using:
The exact function signatures expected for:
ExponentialAverage[period](priceSeries)
RSI[period](priceSeries)
AverageTrueRange[period] (with or without (close))
Whether assignments like a = b - c are valid on our build (or if we must use an intermediate variable).
Whether the code below violates any reserved words, naming rules, or requires any additional declarations.
Whether manual daily reset logic (using Day <> Day[1]) is acceptable inside strategies.
If you can pinpoint which single line is rejected by the current parser (and why), I can adjust it immediately. Thank you!
—End of message—
DEFPARAM CumulateOrders = False
DEFPARAM PreLoadBars = 2000
// -------- Session (London) --------
sessionStart = 080000
sessionEnd = 163000
// -------- Risk & sizing (fractions, no decimals) --------
fixedSize = 1
riskATRmult = 5/4 // 1.25
targetRmultiple= 3/2 // 1.50
useTrailingStop= 1
trailATRmult = 1 // 1.00
// -------- Indicator lengths --------
rsiLen = 14
emaFast = 20
emaSlow = 50
macdF = 12
macdS = 26
macdSig = 9
atrLen = 14
rvolLen = 60
// -------- Opening Range window --------
ORStart = 080000
OREnd = 083000
// -------- Quality score threshold --------
minQualityScore = 4
// -------- Divergence swing settings --------
swingLookback = 20
swingDepth = 2
// -------- Cooldown --------
cooldownBarsAfterExit = 1
ONCE lastOrderBar = -100000
// ================== CORE INDICATORS ==================
ema20 = ExponentialAverage[emaFast](close)
ema50 = ExponentialAverage[emaSlow](close)
// --- MACD (stepwise to avoid inline subtraction parser issues) ---
emaMacdFast = ExponentialAverage[macdF](close)
emaMacdSlow = ExponentialAverage[macdS](close)
macdDiff = emaMacdFast
macdDiff = macdDiff - emaMacdSlow
macdLine = macdDiff
macdSignal = ExponentialAverage[macdSig](macdLine)
macdHist = macdLine - macdSignal
rsi = RSI[rsiLen](close)
// --- ATR (confirm signature on your build) ---
atr = AverageTrueRange[atrLen]
// -------- Manual intraday VWAP (resets daily) --------
ONCE vCumPV = 0.0
ONCE vCumV = 0.0
IF Day <> Day[1] THEN
vCumPV = 0.0
vCumV = 0.0
ENDIF
tp = (High + Low + Close) / 3
vCumPV = vCumPV + tp * Volume
vCumV = vCumV + Volume
vwap = 0.0
IF vCumV > 0 THEN
vwap = vCumPV / vCumV
ENDIF
// -------- Relative volume (RVOL) --------
avgVol = Average[rvolLen](Volume)
rvol = 0.0
IF avgVol > 0 THEN
rvol = Volume / avgVol
ENDIF
// -------- Candle anatomy --------
barRange = High - Low
body = Abs(Close - Open)
bodyPct = 0.0
posInBar = 0.0
IF barRange > 0 THEN
bodyPct = 100 * body / barRange
posInBar = 100 * (Close - Low) / barRange
ENDIF
// -------- ATR baseline (for quality test) --------
atrBase = Average[100](atr)
// -------- Opening Range (first 30m) --------
ONCE ORH = 0.0
ONCE ORL = 0.0
IF Day <> Day[1] THEN
ORH = 0.0
ORL = 0.0
ENDIF
IF Time = ORStart THEN
ORH = High
ORL = Low
ENDIF
IF Time > ORStart AND Time <= OREnd THEN
IF High > ORH THEN
ORH = High
ENDIF
IF Low < ORL THEN
ORL = Low
ENDIF
ENDIF
IF ORH = 0.0 AND BarIndex > 0 THEN
ORH = ORH[1]
ORL = ORL[1]
ENDIF
// -------- Helpers --------
inSession = (Time >= sessionStart AND Time <= sessionEnd)
canTradeBar= (BarIndex > lastOrderBar + cooldownBarsAfterExit)
// ================== QUALITY SCORE 0..6 ==================
q_rvol = 0
IF rvol >= 13/10 THEN
q_rvol = 1
ENDIF
q_vwapL = 0
IF Close > vwap THEN
q_vwapL = 1
ENDIF
q_rsi50L = 0
IF rsi > 50 THEN
q_rsi50L = 1
ENDIF
q_macd0L = 0
IF macdLine > 0 THEN
q_macd0L = 1
ENDIF
q_candleL = 0
IF bodyPct >= 60 AND posInBar >= 75 THEN
q_candleL = 1
ENDIF
q_atr = 0
IF atr >= atrBase THEN
q_atr = 1
ENDIF
qualityLong = q_rvol + q_vwapL + q_rsi50L + q_macd0L + q_candleL + q_atr
q_vwapS = 0
IF Close < vwap THEN
q_vwapS = 1
ENDIF
q_rsi50S = 0
IF rsi < 50 THEN
q_rsi50S = 1
ENDIF
q_macd0S = 0
IF macdLine < 0 THEN
q_macd0S = 1
ENDIF
q_candleS = 0
IF bodyPct >= 60 AND posInBar <= 25 THEN
q_candleS = 1
ENDIF
qualityShort = q_rvol + q_vwapS + q_rsi50S + q_macd0S + q_candleS + q_atr
// ================== DIVERGENCE TOOLS ==================
isSwingLow = (Low[2] > Low[1] AND Low > Low[1] AND Low[1] < Low[3] AND Low[1] < Low[2])
isSwingHigh = (High[2] < High[1] AND High < High[1] AND High[1] > High[3] AND High[1] > High[2])
ONCE low1Idx = -1
ONCE low2Idx = -1
ONCE low1 = 0.0
ONCE low2 = 0.0
ONCE macdLow1= 0.0
ONCE macdLow2= 0.0
ONCE high1Idx = -1
ONCE high2Idx = -1
ONCE high1 = 0.0
ONCE high2 = 0.0
ONCE macdHigh1= 0.0
ONCE macdHigh2= 0.0
IF isSwingLow THEN
low2Idx = low1Idx
low2 = low1
macdLow2 = macdLow1
low1Idx = BarIndex - 1
low1 = Low[1]
macdLow1 = macdLine[1]
ENDIF
IF isSwingHigh THEN
high2Idx = high1Idx
high2 = high1
macdHigh2 = macdHigh1
high1Idx = BarIndex - 1
high1 = High[1]
macdHigh1 = macdLine[1]
ENDIF
validLowSwings = (low1Idx > 0 AND low2Idx > 0 AND (low1Idx - low2Idx) >= swingDepth AND (BarIndex - low1Idx) <= swingLookback)
validHighSwings = (high1Idx > 0 AND high2Idx > 0 AND (high1Idx - high2Idx) >= swingDepth AND (BarIndex - high1Idx) <= swingLookback)
bullDiv = 0
IF validLowSwings AND low1 < low2 AND macdLow1 > macdLow2 THEN
bullDiv = 1
ENDIF
bearDiv = 0
IF validHighSwings AND high1 > high2 AND macdHigh1 < macdHigh2 THEN
bearDiv = 1
ENDIF
// ================== STRATEGY SIGNALS (8) ==================
macdBullX = (macdLine crosses over macdSignal)
macdBearX = (macdLine crosses under macdSignal)
rsiUpFrom30 = (rsi crosses over 30)
rsiDnFrom70 = (rsi crosses under 70)
emaTrendUp = (ema50 >= ema50[1])
emaTrendDown = (ema50 <= ema50[1])
// 1) MACD–RSI Trend-Confirmation
TrendConf_Long = rsiUpFrom30 AND macdBullX AND emaTrendUp
TrendConf_Short = rsiDnFrom70 AND macdBearX AND emaTrendDown
// 2) RSI+MACD Divergence Reversal
reversalBullCandle = (Close > Open AND posInBar >= 65 AND bodyPct >= 50)
reversalBearCandle = (Close < Open AND posInBar <= 35 AND bodyPct >= 50)
DivRev_Long = (bullDiv = 1 AND rsi < 30 AND reversalBullCandle)
DivRev_Short = (bearDiv = 1 AND rsi > 70 AND reversalBearCandle)
// 3) RSI Trend Filter + MACD Breakout
breakAboveOR = (Time > OREnd AND Close > ORH AND High[1] <= ORH)
breakBelowOR = (Time > OREnd AND Close < ORL AND Low[1] >= ORL)
RSItrendLong = (rsi > 50)
RSItrendShort = (rsi < 50)
Breakout_Long = RSItrendLong AND macdBullX AND macdHist > macdHist[1] AND (breakAboveOR OR Close > ema20) AND rvol >= 13/10
Breakout_Short = RSItrendShort AND macdBearX AND macdHist < macdHist[1] AND (breakBelowOR OR Close < ema20) AND rvol >= 13/10
// 4) RSI Pullback + MACD Trend Bias
rsiTurnUp = (rsi > rsi[1] AND rsi[1] <= rsi[2])
rsiTurnDown = (rsi < rsi[1] AND rsi[1] >= rsi[2])
Pullback_Long = (macdHist > 0) AND (rsi >= 40 AND rsi <= 50) AND rsiTurnUp AND (Close >= ema20 OR Close >= vwap) AND rvol >= 12/10
Pullback_Short = (macdHist < 0) AND (rsi <= 60 AND rsi >= 50) AND rsiTurnDown AND (Close <= ema20 OR Close <= vwap) AND rvol >= 12/10
// 5) Opening-Range Breakout (ORB) + Trend Filter
ORB_Long = (Time > OREnd) AND (Close > ORH) AND emaTrendUp AND rsi > 50 AND macdHist > macdHist[1] AND rvol >= 13/10
ORB_Short = (Time > OREnd) AND (Close < ORL) AND emaTrendDown AND rsi < 50 AND macdHist < macdHist[1] AND rvol >= 13/10
// 6) Mean Reversion to VWAP (fade)
farFromVWAP_Long = (Close < vwap AND (vwap - Close) >= (3 * Average[5](atr)) / 2)
farFromVWAP_Short = (Close > vwap AND (Close - vwap) >= (3 * Average[5](atr)) / 2)
MR_Long = farFromVWAP_Long AND rsi < 30 AND (macdHist > macdHist[1]) AND reversalBullCandle
MR_Short = farFromVWAP_Short AND rsi > 70 AND (macdHist < macdHist[1]) AND reversalBearCandle
// 7) Volatility Squeeze -> Expansion (ATR squeeze proxy)
lowATRNow = (atr <= Lowest[150](atr) * 11/10)
Squeeze_Long = lowATRNow AND Close > ema20 AND rsi > 50 AND rvol >= 13/10 AND Close > High[1]
Squeeze_Short = lowATRNow AND Close < ema20 AND rsi < 50 AND rvol >= 13/10 AND Close < Low[1]
// 8) News / Volume-Spike Reaction (First Pullback)
impulseUp = (rvol >= 2 AND bodyPct >= 70 AND Close > vwap AND macdLine > 0)
impulseDown = (rvol >= 2 AND bodyPct >= 70 AND Close < vwap AND macdLine < 0)
pullbackOK_L = impulseUp AND Close >= ema20 AND rsi > 50 AND macdLine >= 0
pullbackOK_S = impulseDown AND Close <= ema20 AND rsi < 50 AND macdLine <= 0
NewsPB_Long = pullbackOK_L AND (Close > High[1])
NewsPB_Short = pullbackOK_S AND (Close < Low[1])
// ============== ELIGIBILITY + RANKING ==============
Elig_TrendConf_L = TrendConf_Long AND (qualityLong >= minQualityScore)
Elig_DivRev_L = DivRev_Long AND (qualityLong >= minQualityScore)
Elig_Breakout_L = Breakout_Long AND (qualityLong >= minQualityScore)
Elig_Pullback_L = Pullback_Long AND (qualityLong >= minQualityScore)
Elig_ORB_L = ORB_Long AND (qualityLong >= minQualityScore)
Elig_MR_L = MR_Long AND (qualityLong >= minQualityScore)
Elig_Squeeze_L = Squeeze_Long AND (qualityLong >= minQualityScore)
Elig_NewsPB_L = NewsPB_Long AND (qualityLong >= minQualityScore)
Elig_TrendConf_S = TrendConf_Short AND (qualityShort >= minQualityScore)
Elig_DivRev_S = DivRev_Short AND (qualityShort >= minQualityScore)
Elig_Breakout_S = Breakout_Short AND (qualityShort >= minQualityScore)
Elig_Pullback_S = Pullback_Short AND (qualityShort >= minQualityScore)
Elig_ORB_S = ORB_Short AND (qualityShort >= minQualityScore)
Elig_MR_S = MR_Short AND (qualityShort >= minQualityScore)
Elig_Squeeze_S = Squeeze_Short AND (qualityShort >= minQualityScore)
Elig_NewsPB_S = NewsPB_Short AND (qualityShort >= minQualityScore)
bestLong = -1
bestShort = -1
score = 0
IF Elig_NewsPB_L THEN
score = qualityLong + 80
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_ORB_L THEN
score = qualityLong + 70
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_Breakout_L THEN
score = qualityLong + 60
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_Squeeze_L THEN
score = qualityLong + 50
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_Pullback_L THEN
score = qualityLong + 40
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_TrendConf_L THEN
score = qualityLong + 30
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_MR_L THEN
score = qualityLong + 20
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_DivRev_L THEN
score = qualityLong + 10
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF Elig_NewsPB_S THEN
score = qualityShort + 80
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_ORB_S THEN
score = qualityShort + 70
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_Breakout_S THEN
score = qualityShort + 60
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_Squeeze_S THEN
score = qualityShort + 50
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_Pullback_S THEN
score = qualityShort + 40
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_TrendConf_S THEN
score = qualityShort + 30
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_MR_S THEN
score = qualityShort + 20
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF Elig_DivRev_S THEN
score = qualityShort + 10
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
goLong = (bestLong > bestShort)
goShort = (bestShort > bestLong)
// ================== ORDERS & RISK ==================
sizeToUse = fixedSize
riskPoints = atr * riskATRmult
IF riskPoints <= 0 THEN
riskPoints = 1
ENDIF
IF inSession AND canTradeBar THEN
IF NOT LongOnMarket AND NOT ShortOnMarket AND goLong THEN
lastOrderBar = BarIndex
BUY sizeToUse CONTRACTS AT MARKET
SET STOP pLOSS riskPoints
SET TARGET pPROFIT (targetRmultiple * riskPoints)
ENDIF
IF NOT LongOnMarket AND NOT ShortOnMarket AND goShort THEN
lastOrderBar = BarIndex
SELLSHORT sizeToUse CONTRACTS AT MARKET
SET STOP pLOSS riskPoints
SET TARGET pPROFIT (targetRmultiple * riskPoints)
ENDIF
ENDIF
IF useTrailingStop = 1 THEN
IF LongOnMarket AND Close >= TradePrice + riskPoints THEN
SET STOP TRAILING (trailATRmult * atr)
ENDIF
IF ShortOnMarket AND Close <= TradePrice - riskPoints THEN
SET STOP TRAILING (trailATRmult * atr)
ENDIF
ENDIF
// -------- Safety exits --------
IF LongOnMarket AND (macdBearX OR (rsi < 50 AND Close < vwap)) THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND (macdBullX OR (rsi > 50 AND Close > vwap)) THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND Close >= vwap AND macdHist < macdHist[1] THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND Close <= vwap AND macdHist > macdHist[1] THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND Time > OREnd AND (Close < ORH AND Close < ema20) THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND Time > OREnd AND (Close > ORL AND Close > ema20) THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND (macdHist <= 0 OR Close < vwap) THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND (macdHist >= 0 OR Close > vwap) THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND Close >= vwap THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND Close <= vwap THEN
EXITSHORT AT MARKET
ENDIF/*
Trading Strategy:
for long and buy set ups: • MACD line crosses above Signal, trade at maximum 1% if the cross happens below the MACD zero line Price prints a lower lows, otherwise make buy at 0.5% of total trading fund as signal is not as strong. • RSI also has already or does cross so it it shows higher lows. The buy should turnup from the 0-35 zone to buy at the maximum 1% amount (dependent on MACD rule), or else it buys at 0.5%. • then the next criteria needs to see a green bullish candle that needs to show bullish momentum: bullish reversal candle, Hammer, Engulfing, Morning Star with volume rising also. •The last criteria needs to assess the VWAP (Volume-Weighted Average Price) bar and to buy only if bullish momentum is shown which needs to be when price is above VWAP.
For Short sell Setups: • MACD line crosses below Signal, trade at maximum 1% if the cross happens above the MACD zero line (momentum fading at overbought levels). Price prints a lower lows, otherwise make sell at 0.5% amount of total trading fund as signal is not as strong. • RSI also has already or does cross so it it shows lower highs. The sell should roll over from the 65-100 zone to sell at the maximum 1% amount (dependent on MACD rule), or else it sells at 0.5%. • then the last criteria needs to see a red bearish candle that needs to show bullish momentum: bearish reversal candle (Shooting Star, Bearish Engulfing, Evening Star/ Inverted hammer) on increasing sell volume. The last criteria needs to short and sell is to assess the VWAP and to sell only if bearish momentum is shown which is when the price is below the VWAP.
*/
DEFPARAM CumulateOrders = False
DEFPARAM PreLoadBars = 2000
// -------- Session (London) --------
sessionStart = 080000
sessionEnd = 163000
// -------- Risk & sizing (fractions, no decimals) --------
fixedSize = 1
riskATRmult = 5/4 // 1.25
targetRmultiple= 3/2 // 1.50
useTrailingStop= 1
trailATRmult = 1 // 1.00
// -------- Indicator lengths --------
rsiLen = 14
emaFast = 20
emaSlow = 50
macdF = 12
macdS = 26
macdSig = 9
atrLen = 14
rvolLen = 60
// -------- Opening Range window --------
ORStart = 080000
OREnd = 083000
// -------- Quality score threshold --------
minQualityScore = 4
// -------- Divergence swing settings --------
swingLookback = 20
swingDepth = 2
// -------- Cooldown --------
cooldownBarsAfterExit = 1
ONCE lastOrderBar = -100000
// ================== CORE INDICATORS ==================
ema20 = ExponentialAverage[emaFast](close)
ema50 = ExponentialAverage[emaSlow](close)
// --- MACD (stepwise to avoid inline subtraction parser issues) ---
emaMacdFast = ExponentialAverage[macdF](close)
emaMacdSlow = ExponentialAverage[macdS](close)
macdDiff = emaMacdFast
macdDiff = macdDiff - emaMacdSlow
myMacdLine = macdDiff
myMacdSignal = ExponentialAverage[macdSig](myMacdLine)
macdHist = myMacdLine - myMacdSignal
myRSI = RSI[rsiLen](close)
// --- ATR (confirm signature on your build) ---
atr = AverageTrueRange[atrLen]
// -------- Manual intraday VWAP (resets daily) --------
ONCE vCumPV = 0.0
ONCE vCumV = 0.0
IF Day <> Day[1] THEN
vCumPV = 0.0
vCumV = 0.0
ENDIF
tp = (High + Low + Close) / 3
vCumPV = vCumPV + tp * Volume
vCumV = vCumV + Volume
vwap = 0.0
IF vCumV > 0 THEN
vwap = vCumPV / vCumV
ENDIF
// -------- Relative volume (RVOL) --------
avgVol = Average[rvolLen](Volume)
rvol = 0.0
IF avgVol > 0 THEN
rvol = Volume / avgVol
ENDIF
// -------- Candle anatomy --------
barRange = High - Low
body = Abs(Close - Open)
bodyPct = 0.0
posInBar = 0.0
IF barRange > 0 THEN
bodyPct = 100 * body / barRange
posInBar = 100 * (Close - Low) / barRange
ENDIF
// -------- ATR baseline (for quality test) --------
atrBase = Average[100](atr)
// -------- Opening Range (first 30m) --------
ONCE ORH = 0.0
ONCE ORL = 0.0
IF Day <> Day[1] THEN
ORH = 0.0
ORL = 0.0
ENDIF
IF Time = ORStart THEN
ORH = High
ORL = Low
ENDIF
IF Time > ORStart AND Time <= OREnd THEN
IF High > ORH THEN
ORH = High
ENDIF
IF Low < ORL THEN
ORL = Low
ENDIF
ENDIF
IF ORH = 0.0 AND BarIndex > 0 THEN
ORH = ORH[1]
ORL = ORL[1]
ENDIF
// -------- Helpers --------
inSession = (Time >= sessionStart AND Time <= sessionEnd)
canTradeBar= (BarIndex > lastOrderBar + cooldownBarsAfterExit)
// ================== QUALITY SCORE 0..6 ==================
qXrvol = 0
IF rvol >= 13/10 THEN
qXrvol = 1
ENDIF
qXvwapL = 0
IF Close > vwap THEN
qXvwapL = 1
ENDIF
qXrsi50L = 0
IF myRSI > 50 THEN
qXrsi50L = 1
ENDIF
qXmacd0L = 0
IF myMacdLine > 0 THEN
qXmacd0L = 1
ENDIF
qXcandleL = 0
IF bodyPct >= 60 AND posInBar >= 75 THEN
qXcandleL = 1
ENDIF
qXatr = 0
IF atr >= atrBase THEN
qXatr = 1
ENDIF
qualityLong = qXrvol + qXvwapL + qXrsi50L + qXmacd0L + qXcandleL + qXatr
qXvwapS = 0
IF Close < vwap THEN
qXvwapS = 1
ENDIF
qXrsi50S = 0
IF myRSI < 50 THEN
qXrsi50S = 1
ENDIF
qXmacd0S = 0
IF myMacdLine < 0 THEN
qXmacd0S = 1
ENDIF
qXcandleS = 0
IF bodyPct >= 60 AND posInBar <= 25 THEN
qXcandleS = 1
ENDIF
qualityShort = qXrvol + qXvwapS + qXrsi50S + qXmacd0S + qXcandleS + qXatr
// ================== DIVERGENCE TOOLS ==================
isSwingLow = (Low[2] > Low[1] AND Low > Low[1] AND Low[1] < Low[3] AND Low[1] < Low[2])
isSwingHigh = (High[2] < High[1] AND High < High[1] AND High[1] > High[3] AND High[1] > High[2])
ONCE low1Idx = -1
ONCE low2Idx = -1
ONCE low1 = 0.0
ONCE low2 = 0.0
ONCE macdLow1= 0.0
ONCE macdLow2= 0.0
ONCE high1Idx = -1
ONCE high2Idx = -1
ONCE high1 = 0.0
ONCE high2 = 0.0
ONCE macdHigh1= 0.0
ONCE macdHigh2= 0.0
IF isSwingLow THEN
low2Idx = low1Idx
low2 = low1
macdLow2 = macdLow1
low1Idx = BarIndex - 1
low1 = Low[1]
macdLow1 = myMacdLine[1]
ENDIF
IF isSwingHigh THEN
high2Idx = high1Idx
high2 = high1
macdHigh2 = macdHigh1
high1Idx = BarIndex - 1
high1 = High[1]
macdHigh1 = myMacdLine[1]
ENDIF
validLowSwings = (low1Idx > 0 AND low2Idx > 0 AND (low1Idx - low2Idx) >= swingDepth AND (BarIndex - low1Idx) <= swingLookback)
validHighSwings = (high1Idx > 0 AND high2Idx > 0 AND (high1Idx - high2Idx) >= swingDepth AND (BarIndex - high1Idx) <= swingLookback)
bullDiv = 0
IF validLowSwings AND low1 < low2 AND macdLow1 > macdLow2 THEN
bullDiv = 1
ENDIF
bearDiv = 0
IF validHighSwings AND high1 > high2 AND macdHigh1 < macdHigh2 THEN
bearDiv = 1
ENDIF
// ================== STRATEGY SIGNALS (8) ==================
macdBullX = (myMacdLine crosses over myMacdSignal)
macdBearX = (myMacdLine crosses under myMacdSignal)
rsiUpFrom30 = (myRSI crosses over 30)
rsiDnFrom70 = (myRSI crosses under 70)
emaTrendUp = (ema50 >= ema50[1])
emaTrendDown = (ema50 <= ema50[1])
// 1) MACD-RSI Trend-Confirmation
TrendConfXLong = rsiUpFrom30 AND macdBullX AND emaTrendUp
TrendConfXShort = rsiDnFrom70 AND macdBearX AND emaTrendDown
// 2) RSI+MACD Divergence Reversal
reversalBullCandle = (Close > Open AND posInBar >= 65 AND bodyPct >= 50)
reversalBearCandle = (Close < Open AND posInBar <= 35 AND bodyPct >= 50)
DivRevXLong = (bullDiv = 1 AND myRSI < 30 AND reversalBullCandle)
DivRevXShort = (bearDiv = 1 AND myRSI > 70 AND reversalBearCandle)
// 3) RSI Trend Filter + MACD Breakout
breakAboveOR = (Time > OREnd AND Close > ORH AND High[1] <= ORH)
breakBelowOR = (Time > OREnd AND Close < ORL AND Low[1] >= ORL)
RSItrendLong = (myRSI > 50)
RSItrendShort = (myRSI < 50)
BreakoutXLong = RSItrendLong AND macdBullX AND macdHist > macdHist[1] AND (breakAboveOR OR Close > ema20) AND rvol >= 13/10
BreakoutXShort = RSItrendShort AND macdBearX AND macdHist < macdHist[1] AND (breakBelowOR OR Close < ema20) AND rvol >= 13/10
// 4) RSI Pullback + MACD Trend Bias
rsiTurnUp = (myRSI > myRSI[1] AND myRSI[1] <= myRSI[2])
rsiTurnDown = (myRSI < myRSI[1] AND myRSI[1] >= myRSI[2])
PullbackXLong = (macdHist > 0) AND (myRSI >= 40 AND myRSI <= 50) AND rsiTurnUp AND (Close >= ema20 OR Close >= vwap) AND rvol >= 12/10
PullbackXShort = (macdHist < 0) AND (myRSI <= 60 AND myRSI >= 50) AND rsiTurnDown AND (Close <= ema20 OR Close <= vwap) AND rvol >= 12/10
// 5) Opening-Range Breakout (ORB) + Trend Filter
ORBXLong = (Time > OREnd) AND (Close > ORH) AND emaTrendUp AND myRSI > 50 AND macdHist > macdHist[1] AND rvol >= 13/10
ORBXShort = (Time > OREnd) AND (Close < ORL) AND emaTrendDown AND myRSI < 50 AND macdHist < macdHist[1] AND rvol >= 13/10
// 6) Mean Reversion to VWAP (fade)
farFromVWAPXLong = (Close < vwap AND (vwap - Close) >= (3 * Average[5](atr)) / 2)
farFromVWAPXShort = (Close > vwap AND (Close - vwap) >= (3 * Average[5](atr)) / 2)
MRXLong = farFromVWAPXLong AND myRSI < 30 AND (macdHist > macdHist[1]) AND reversalBullCandle
MRXShort = farFromVWAPXShort AND myRSI > 70 AND (macdHist < macdHist[1]) AND reversalBearCandle
// 7) Volatility Squeeze -> Expansion (ATR squeeze proxy)
lowATRNow = (atr <= Lowest[150](atr) * 11/10)
SqueezeXLong = lowATRNow AND Close > ema20 AND myRSI > 50 AND rvol >= 13/10 AND Close > High[1]
SqueezeXShort = lowATRNow AND Close < ema20 AND myRSI < 50 AND rvol >= 13/10 AND Close < Low[1]
// 8) News / Volume-Spike Reaction (First Pullback)
impulseUp = (rvol >= 2 AND bodyPct >= 70 AND Close > vwap AND myMacdLine > 0)
impulseDown = (rvol >= 2 AND bodyPct >= 70 AND Close < vwap AND myMacdLine < 0)
pullbackOKXL = impulseUp AND Close >= ema20 AND myRSI > 50 AND myMacdLine >= 0
pullbackOKXS = impulseDown AND Close <= ema20 AND myRSI < 50 AND myMacdLine <= 0
NewsPBXLong = pullbackOKXL AND (Close > High[1])
NewsPBXShort = pullbackOKXS AND (Close < Low[1])
// ============== ELIGIBILITY + RANKING ==============
EligXTrendConfXL = TrendConfXLong AND (qualityLong >= minQualityScore)
EligXDivRevXL = DivRevXLong AND (qualityLong >= minQualityScore)
EligXBreakoutXL = BreakoutXLong AND (qualityLong >= minQualityScore)
EligXPullbackXL = PullbackXLong AND (qualityLong >= minQualityScore)
EligXORBXL = ORBXLong AND (qualityLong >= minQualityScore)
EligXMRXL = MRXLong AND (qualityLong >= minQualityScore)
EligXSqueezeXL = SqueezeXLong AND (qualityLong >= minQualityScore)
EligXNewsPBXL = NewsPBXLong AND (qualityLong >= minQualityScore)
EligXTrendConfXS = TrendConfXShort AND (qualityShort >= minQualityScore)
EligXDivRevXS = DivRevXShort AND (qualityShort >= minQualityScore)
EligXBreakoutXS = BreakoutXShort AND (qualityShort >= minQualityScore)
EligXPullbackXS = PullbackXShort AND (qualityShort >= minQualityScore)
EligXORBXS = ORBXShort AND (qualityShort >= minQualityScore)
EligXMRXS = MRXShort AND (qualityShort >= minQualityScore)
EligXSqueezeXS = SqueezeXShort AND (qualityShort >= minQualityScore)
EligXNewsPBXS = NewsPBXShort AND (qualityShort >= minQualityScore)
bestLong = -1
bestShort = -1
score = 0
IF EligXNewsPBXL THEN
score = qualityLong + 80
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXORBXL THEN
score = qualityLong + 70
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXBreakoutXL THEN
score = qualityLong + 60
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXSqueezeXL THEN
score = qualityLong + 50
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXPullbackXL THEN
score = qualityLong + 40
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXTrendConfXL THEN
score = qualityLong + 30
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXMRXL THEN
score = qualityLong + 20
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXDivRevXL THEN
score = qualityLong + 10
IF score > bestLong THEN
bestLong = score
ENDIF
ENDIF
IF EligXNewsPBXS THEN
score = qualityShort + 80
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXORBXS THEN
score = qualityShort + 70
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXBreakoutXS THEN
score = qualityShort + 60
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXSqueezeXS THEN
score = qualityShort + 50
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXPullbackXS THEN
score = qualityShort + 40
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXTrendConfXS THEN
score = qualityShort + 30
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXMRXS THEN
score = qualityShort + 20
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
IF EligXDivRevXS THEN
score = qualityShort + 10
IF score > bestShort THEN
bestShort = score
ENDIF
ENDIF
goLong = (bestLong > bestShort)
goShort = (bestShort > bestLong)
// ================== ORDERS & RISK ==================
sizeToUse = fixedSize
riskPoints = atr * riskATRmult
IF riskPoints <= 0 THEN
riskPoints = 1
ENDIF
IF inSession AND canTradeBar THEN
IF NOT LongOnMarket AND NOT ShortOnMarket AND goLong THEN
lastOrderBar = BarIndex
BUY sizeToUse CONTRACTS AT MARKET
SET STOP pLOSS riskPoints
SET TARGET pPROFIT (targetRmultiple * riskPoints)
ENDIF
IF NOT LongOnMarket AND NOT ShortOnMarket AND goShort THEN
lastOrderBar = BarIndex
SELLSHORT sizeToUse CONTRACTS AT MARKET
SET STOP pLOSS riskPoints
SET TARGET pPROFIT (targetRmultiple * riskPoints)
ENDIF
ENDIF
IF useTrailingStop = 1 THEN
IF LongOnMarket AND Close >= TradePrice + riskPoints THEN
SET STOP TRAILING (trailATRmult * atr)
ENDIF
IF ShortOnMarket AND Close <= TradePrice - riskPoints THEN
SET STOP TRAILING (trailATRmult * atr)
ENDIF
ENDIF
// -------- Safety exits --------
IF LongOnMarket AND (macdBearX OR (myRSI < 50 AND Close < vwap)) THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND (macdBullX OR (rsi > 50 AND Close > vwap)) THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND Close >= vwap AND macdHist < macdHist[1] THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND Close <= vwap AND macdHist > macdHist[1] THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND Time > OREnd AND (Close < ORH AND Close < ema20) THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND Time > OREnd AND (Close > ORL AND Close > ema20) THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND (macdHist <= 0 OR Close < vwap) THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND (macdHist >= 0 OR Close > vwap) THEN
EXITSHORT AT MARKET
ENDIF
IF LongOnMarket AND Close >= vwap THEN
SELL AT MARKET
ENDIF
IF ShortOnMarket AND Close <= vwap THEN
EXITSHORT AT MARKET
ENDIF
Many thanks for looks ng into this.Tbh I had to use and various AI coding platforms to put this together, clearly it is not working! Is it possible to build in multiple strategies and a scoring criterias to have the appropriate strategy assigned at any given time, to multiple instruments, for automatic trading? I would very much like to build a fully automated trading platform that reacts in real time to price changes. I tried to implement eight basic main strategies and rules to give a underlying base to have 8 strategies be deployed to react to market changes live. But if even two strategies can be built and then switched depending on the state of the share price etc, I would be very interested how to build this and what code has been used please! Thanks
strategy assigned at any given time, to multiple instrumentsA single coded Strategy can only be assigned to a single Instrument. You could run the same coded Strategy duplicated multiple times across multiple Instruments.
Please correct Code to allow this to work to backtest and in automatic trading
This topic contains 4 replies,
has 3 voices, and was last updated by GraHal
4 months, 3 weeks ago.
| Forum: | ProBuilder: Indicators & Custom Tools |
| Language: | English |
| Started: | 10/11/2025 |
| Status: | Active |
| Attachments: | 1 files |
The information collected on this form is stored in a computer file by ProRealCode to create and access your ProRealCode profile. This data is kept in a secure database for the duration of the member's membership. They will be kept as long as you use our services and will be automatically deleted after 3 years of inactivity. Your personal data is used to create your private profile on ProRealCode. This data is maintained by SAS ProRealCode, 407 rue Freycinet, 59151 Arleux, France. If you subscribe to our newsletters, your email address is provided to our service provider "MailChimp" located in the United States, with whom we have signed a confidentiality agreement. This company is also compliant with the EU/Swiss Privacy Shield, and the GDPR. For any request for correction or deletion concerning your data, you can directly contact the ProRealCode team by email at privacy@prorealcode.com If you would like to lodge a complaint regarding the use of your personal data, you can contact your data protection supervisory authority.