mql5/Shared Projects/ERMT-ML/QQEX_Cross_v6_Strategy.pine

238 lines
14 KiB
Text

//@version=6
strategy("QQE Cross v6 Modernized", shorttitle="QQEX v6", overlay=true, max_bars_back=2000,
pyramiding=0,
default_qty_type=strategy.cash,
default_qty_value=1000,
commission_type=strategy.commission.percent,
commission_value=0.1,
initial_capital=10000,
process_orders_on_close=true)
anchor = input.int(4, minval=0, maxval=100, title="Relative TimeFrame Multiplier for Second MA Ribbon (0=none, max=100)")
showAvgs = input.bool(true, title="Show Moving Average Lines")
type1 = input.string("EMA", title="Fast MA Type", options=["SMA", "EMA", "WMA", "VWMA", "SMMA", "DEMA", "TEMA", "HullMA", "ZEMA", "TMA", "SSMA"])
len1 = input.int(16, title="Fast Length", minval=1)
gamma1 = 0.33
type2 = input.string("EMA", title="Medium MA Type", options=["SMA", "EMA", "WMA", "VWMA", "SMMA", "DEMA", "TEMA", "HullMA", "ZEMA", "TMA", "SSMA"])
len2 = input.int(21, title="Medium Length", minval=1)
gamma2 = 0.55
type3 = input.string("EMA", title="Slow MA Type", options=["SMA", "EMA", "WMA", "VWMA", "SMMA", "DEMA", "TEMA", "HullMA", "ZEMA", "TMA", "SSMA"])
len3 = input.int(26, title="Slow Length", minval=1)
gamma3 = 0.77
RSILen = input.int(14, title="RSI Length", minval=1)
SF = input.int(8, title="RSI Smoothing Factor", minval=1)
QQEfactor = input.float(5.0, title="Fast QQE Factor", minval=0.1)
threshhold = input.int(10, title="RSI Threshold", minval=1)
sQQEx = input.bool(true, title="Show QQE Signal Crosses")
sQQEz = input.bool(false, title="Show QQE Zero Crosses")
sQQEc = input.bool(true, title="Show QQE Threshold Channel Exits")
tradeSignal = input.string("XC", title="Select which QQE signal to Buy/Sell", options=["XC", "XQ", "XZ"])
closeSignal = input.string("XQ", title="Select which QQE signal to Close Order", options=["XC", "XQ", "XZ"])
xfilter = input.bool(true, title="Filter XQ Buy/Sell Orders by Threshold")
filter = input.bool(false, title="Use Moving Average Filter")
dfilter = input.bool(true, title="Use Trend Directional Filter")
ufirst = input.bool(false, title="Only Alert First Buy/Sell in a New Trend")
RSIsrc = input.source(close, title="Source")
enableLongs = input.bool(true, title="Enable Long Entries")
enableShorts = input.bool(true, title="Enable Short Entries")
useDateFilter = input.bool(false, title="Use Backtest Date Filter")
startTime = input.time(timestamp(2018, 6, 12, 0, 0), title="Backtest Start")
endTime = input.time(timestamp(2099, 12, 31, 23, 59), title="Backtest End")
src = RSIsrc
srcclose = RSIsrc
mult = anchor > 0 ? anchor : 1
inTradeWindow = not useDateFilter or (time >= startTime and time <= endTime)
variant_supersmoother(_src, _len) =>
float a1 = math.exp(-1.414 * math.pi / _len)
float b1 = 2.0 * a1 * math.cos(1.414 * math.pi / _len)
float c2 = b1
float c3 = -a1 * a1
float c1 = 1.0 - c2 - c3
float ss = 0.0
ss := c1 * (_src + nz(_src[1])) / 2.0 + c2 * nz(ss[1]) + c3 * nz(ss[2])
ss
variant_smoothed(_src, _len) =>
float smma = na
smma := na(smma[1]) ? ta.sma(_src, _len) : (smma[1] * (_len - 1) + _src) / _len
smma
variant_zerolagema(_src, _len) =>
ema1 = ta.ema(_src, _len)
ema2 = ta.ema(ema1, _len)
ema1 + (ema1 - ema2)
variant_doubleema(_src, _len) =>
ema1 = ta.ema(_src, _len)
2.0 * ema1 - ta.ema(ema1, _len)
variant_tripleema(_src, _len) =>
ema1 = ta.ema(_src, _len)
3.0 * (ema1 - ta.ema(ema1, _len)) + ta.ema(ta.ema(ema1, _len), _len)
variant(_type, _src, _len, _g) =>
switch _type
"EMA" => ta.ema(_src, _len)
"WMA" => ta.wma(_src, _len)
"VWMA" => ta.vwma(_src, _len)
"SMMA" => variant_smoothed(_src, _len)
"DEMA" => variant_doubleema(_src, _len)
"TEMA" => variant_tripleema(_src, _len)
"HullMA" => ta.wma(2.0 * ta.wma(_src, int(math.max(1, _len / 2))) - ta.wma(_src, _len), int(math.max(1, math.round(math.sqrt(_len)))))
"SSMA" => variant_supersmoother(_src, _len)
"ZEMA" => variant_zerolagema(_src, _len)
"TMA" => ta.sma(ta.sma(_src, _len), _len)
=> ta.sma(_src, _len)
Wilders_Period = RSILen * 2 - 1
Rsi = ta.rsi(RSIsrc, RSILen)
RSIndex = ta.ema(Rsi, SF)
AtrRsi = math.abs(RSIndex[1] - RSIndex)
MaAtrRsi = ta.ema(AtrRsi, Wilders_Period)
DeltaFastAtrRsi = ta.ema(MaAtrRsi, Wilders_Period) * QQEfactor
newshortband = RSIndex + DeltaFastAtrRsi
newlongband = RSIndex - DeltaFastAtrRsi
var float longband = na
var float shortband = na
var int trend = 1
longband := RSIndex[1] > nz(longband[1], newlongband) and RSIndex > nz(longband[1], newlongband) ? math.max(nz(longband[1], newlongband), newlongband) : newlongband
shortband := RSIndex[1] < nz(shortband[1], newshortband) and RSIndex < nz(shortband[1], newshortband) ? math.min(nz(shortband[1], newshortband), newshortband) : newshortband
trend := ta.cross(RSIndex, nz(shortband[1], newshortband)) ? 1 : ta.cross(nz(longband[1], newlongband), RSIndex) ? -1 : nz(trend[1], 1)
FastAtrRsiTL = trend == 1 ? longband : shortband
ma_fast = variant(type1, srcclose, len1, gamma1)
ma_medium = variant(type2, srcclose, len2, gamma2)
ma_slow = variant(type3, srcclose, len3, gamma3)
ma_fast_alt = variant(type1, srcclose, len1 * mult, gamma1)
ma_medium_alt = variant(type2, srcclose, len2 * mult, gamma2)
ma_slow_alt = variant(type3, srcclose, len3 * mult, gamma3)
direction = ta.rising(ma_medium, 3) ? 1 : ta.falling(ma_medium, 3) ? -1 : 0
altDirection = ta.rising(ma_medium_alt, 3) ? 1 : ta.falling(ma_medium_alt, 3) ? -1 : 0
var int QQExlong = 0
var int QQExshort = 0
QQExlong := FastAtrRsiTL < RSIndex ? nz(QQExlong[1]) + 1 : 0
QQExshort := FastAtrRsiTL > RSIndex ? nz(QQExshort[1]) + 1 : 0
var int QQEzlong = 0
var int QQEzshort = 0
QQEzlong := RSIndex >= 50 ? nz(QQEzlong[1]) + 1 : 0
QQEzshort := RSIndex < 50 ? nz(QQEzshort[1]) + 1 : 0
var int QQEclong = 0
var int QQEcshort = 0
QQEclong := RSIndex > (50 + threshhold) ? nz(QQEclong[1]) + 1 : 0
QQEcshort := RSIndex < (50 - threshhold) ? nz(QQEcshort[1]) + 1 : 0
QQEflong = mult == 1 ?
(not filter or (srcclose > ma_medium and ma_medium > ma_slow and ma_fast > ma_medium)) and (not dfilter or direction > 0) :
(not filter or (ma_medium > ma_medium_alt and srcclose > ma_fast and ma_fast > ma_medium)) and (not dfilter or (direction > 0 and altDirection > 0 and srcclose > ma_medium))
QQEfshort = mult == 1 ?
(not filter or (srcclose < ma_medium and ma_medium < ma_slow and ma_fast < ma_medium)) and (not dfilter or direction < 0) :
(not filter or (ma_medium < ma_medium_alt and srcclose < ma_fast and ma_fast < ma_medium)) and (not dfilter or (direction < 0 and altDirection < 0 and srcclose < ma_medium))
QQExfilter = not xfilter or RSIndex > (50 + threshhold) or RSIndex < (50 - threshhold)
var int buy_ = 0
var int sell_ = 0
buy_ := tradeSignal == "XC" ? (QQEclong[1] == 1 and QQEflong[1] ? nz(buy_[1]) + 1 : 0) :
tradeSignal == "XQ" ? (QQExlong[1] == 1 and QQEflong[1] and QQExfilter[1] ? nz(buy_[1]) + 1 : 0) :
tradeSignal == "XZ" ? (QQEzlong[1] == 1 and QQEflong[1] ? nz(buy_[1]) + 1 : 0) : 0
sell_ := tradeSignal == "XC" ? (QQEcshort[1] == 1 and QQEfshort[1] ? nz(sell_[1]) + 1 : 0) :
tradeSignal == "XQ" ? (QQExshort[1] == 1 and QQEfshort[1] and QQExfilter[1] ? nz(sell_[1]) + 1 : 0) :
tradeSignal == "XZ" ? (QQEzshort[1] == 1 and QQEfshort[1] ? nz(sell_[1]) + 1 : 0) : 0
var int Buy = 0
var int Sell = 0
Buy := sell_ > 0 ? 0 : ((buy_ == 1 or nz(Buy[1]) > 0) ? nz(Buy[1]) + 1 : nz(Buy[1]))
Sell := buy_ > 0 ? 0 : ((sell_ == 1 or nz(Sell[1]) > 0) ? nz(Sell[1]) + 1 : nz(Sell[1]))
buy = ufirst ? Buy : buy_
sell = ufirst ? Sell : sell_
var int closeLong = 0
var int closeShort = 0
closeLong := closeSignal == "XC" ? (QQEcshort == 1 ? nz(closeLong[1]) + 1 : 0) :
closeSignal == "XQ" ? (tradeSignal == "XQ" ? (QQExshort == 1 ? nz(closeLong[1]) + 1 : 0) : ((QQExshort == 1 or QQEzshort > 0 or QQEcshort > 0) ? nz(closeLong[1]) + 1 : 0)) :
closeSignal == "XZ" ? (QQEzshort == 1 ? nz(closeLong[1]) + 1 : 0) : 0
closeShort := closeSignal == "XC" ? (QQEclong == 1 ? nz(closeShort[1]) + 1 : 0) :
closeSignal == "XQ" ? (tradeSignal == "XQ" ? (QQExlong == 1 ? nz(closeShort[1]) + 1 : 0) : ((QQExlong == 1 or QQEzlong > 0 or QQEclong == 1) ? nz(closeShort[1]) + 1 : 0)) :
closeSignal == "XZ" ? (QQEzlong == 1 ? nz(closeShort[1]) + 1 : 0) : 0
var int tradestate = 0
tradestate := tradestate == 0 ? (buy == 1 ? 1 : sell == 1 ? 2 : 0) : ((tradestate == 1 and closeLong == 1) or (tradestate == 2 and closeShort == 1) ? 0 : tradestate)
isLong = tradestate != nz(tradestate[1]) and tradestate == 1
isShort = tradestate != nz(tradestate[1]) and tradestate == 2
isCloseLong = tradestate != nz(tradestate[1]) and tradestate == 0 and nz(tradestate[1]) == 1
isCloseShort = tradestate != nz(tradestate[1]) and tradestate == 0 and nz(tradestate[1]) == 2
tcolor = direction < 0 ? color.red : color.green
altTcolor = altDirection < 0 ? color.red : color.green
plot(showAvgs ? ma_medium : na, title="MA Medium", color=tcolor, linewidth=2)
plot(showAvgs and mult > 1 ? ma_fast_alt : na, title="MA Fast Alt", color=altTcolor, linewidth=1)
plot(showAvgs and mult > 1 ? ma_medium_alt : na, title="MA Medium Alt", color=altTcolor, linewidth=2)
plot(showAvgs and mult > 1 ? ma_slow_alt : na, title="MA Slow Alt", color=altTcolor, linewidth=1)
barcolor(mult > 1 ? altTcolor : na)
turned_aqua = altTcolor[1] == color.red and altTcolor == color.green
turned_blue = altTcolor[1] == color.green and altTcolor == color.red
take_profit_long = ma_slow > ma_fast_alt and ma_slow > ma_slow_alt and tcolor[1] == color.green and tcolor == color.red
take_profit_short = ma_slow < ma_fast_alt and ma_slow < ma_slow_alt and tcolor[1] == color.red and tcolor == color.green
plotshape(turned_aqua, title="MA Green Buy", style=shape.triangleup, location=location.belowbar, text="Long", color=color.new(color.green, 20), size=size.normal)
plotshape(turned_blue, title="MA Red Sell", style=shape.triangledown, location=location.abovebar, text="Short", color=color.new(color.red, 20), size=size.normal)
plotshape(take_profit_long, title="Take Profit Long", style=shape.triangledown, location=location.abovebar, text="TP Long", color=color.new(color.purple, 20), size=size.tiny)
plotshape(take_profit_short, title="Take Profit Short", style=shape.triangleup, location=location.belowbar, text="TP Short", color=color.new(color.purple, 20), size=size.tiny)
plotshape(sQQEc and QQEclong == 1 and not isLong, title="QQE X Over Channel", style=shape.triangleup, location=location.belowbar, text="XC", color=color.new(color.olive, 20), size=size.tiny)
plotshape(sQQEc and QQEcshort == 1 and not isShort, title="QQE X Under Channel", style=shape.triangledown, location=location.abovebar, text="XC", color=color.new(color.red, 20), size=size.tiny)
plotshape(sQQEx and QQExlong == 1 and QQEclong != 1 and not isLong, title="QQE Cross Over", style=shape.triangleup, location=location.belowbar, text="XQ", color=color.new(color.blue, 20), size=size.tiny)
plotshape(sQQEx and QQExshort == 1 and QQEcshort != 1 and not isShort, title="QQE Cross Under", style=shape.triangledown, location=location.abovebar, text="XQ", color=color.new(color.black, 20), size=size.tiny)
plotshape(sQQEz and QQEzlong == 1 and QQEclong != 1 and not isLong and QQExlong != 1, title="QQE Zero Cross Over", style=shape.triangleup, location=location.belowbar, text="XZ", color=color.new(color.aqua, 20), size=size.tiny)
plotshape(sQQEz and QQEzshort == 1 and QQEcshort != 1 and not isShort and QQExshort != 1, title="QQE Zero Cross Under", style=shape.triangledown, location=location.abovebar, text="XZ", color=color.new(color.fuchsia, 20), size=size.tiny)
plotshape(isLong, title="QQEX Long", style=shape.arrowup, location=location.belowbar, text="Open\nLONG", color=color.lime, textcolor=color.green, size=size.tiny)
plotshape(isShort, title="QQEX Short", style=shape.arrowdown, location=location.abovebar, text="Open\nSHORT", color=color.red, textcolor=color.maroon, size=size.tiny)
plotshape(isCloseLong, title="QQEX Close Long", style=shape.arrowdown, location=location.abovebar, text="Close\nLONG", color=color.gray, textcolor=color.gray, size=size.tiny)
plotshape(isCloseShort, title="QQEX Close Short", style=shape.arrowup, location=location.belowbar, text="Close\nSHORT", color=color.gray, textcolor=color.gray, size=size.tiny)
alertcondition(turned_aqua, title="Long", message="MA's Turned Green")
alertcondition(turned_blue, title="Short", message="MA's Turned Red")
alertcondition(take_profit_long, title="Take Profit Long", message="Take Profit Long")
alertcondition(take_profit_short, title="Take Profit Short", message="Take Profit Short")
alertcondition(isLong, title="QQEX Long", message="QQEX LONG")
alertcondition(isShort, title="QQEX Short", message="QQEX SHORT")
alertcondition(isCloseLong, title="QQEX Close Long", message="QQEX CLOSE LONG")
alertcondition(isCloseShort, title="QQEX Close Short", message="QQEX CLOSE SHORT")
plotshape(isLong or isShort, title="Cross Alert Completed", location=location.bottom, color=isShort ? color.red : color.green, style=shape.circle, size=size.auto)
plotshape(isCloseShort[1] or isCloseLong[1], title="Close Order", location=location.top, color=isCloseShort[1] ? color.red : color.green, style=shape.square, size=size.auto, offset=-1)
if inTradeWindow and barstate.isconfirmed
if isCloseLong
strategy.close("Long", comment="QQEX Close Long")
if isCloseShort
strategy.close("Short", comment="QQEX Close Short")
if isLong and enableLongs
strategy.close("Short", comment="Reverse to Long")
strategy.entry("Long", strategy.long, comment="QQEX Long")
if isShort and enableShorts
strategy.close("Long", comment="Reverse to Short")
strategy.entry("Short", strategy.short, comment="QQEX Short")