Breakout Trend Trading Strategy - V1.pine
Copy
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © HeWhoMustNotBeNamed
//@version=4
strategy("Breakout Trend Trading - V1", overlay=true, initial_capital = 2000, default_qty_type = strategy.percent_of_equity, default_qty_value = 100, commission_type = strategy.commission.cash_per_order, pyramiding = 1, commission_value = 2)
///////////////////////////////////////// Input ////////////////////////////////////////////////////////////////////
//supertrendMult = input(6, minval=1, maxval=10, step=0.5)
//supertrendLength = input(22, minval=1)
//volumelength = input(title="Volume MA Length", defval=20, minval=10, step=10)
//volumeMaType = input(title="Volume MA Type", defval="sma", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
//trendVolumeMarkup = input(15, minval=0, maxval=100, step=5)
//reverseVolumeMarkup = input(15, minval=0, maxval=100, step=5)
//highVolumeMultiplyer = input(5, minval=2, maxval=10, step=1)
//atrlength = input(22, minval=1)
//trendTargetMult = input(1, minval=1, maxval=10, step=0.5)
//reverseTargetMult = input(1, minval=1, maxval=10, step=0.5)
//highBreakoutMult = input(2, minval=2, maxval=10, step=1)
//trendValueMarkup = input(15, minval=0, maxval=100, step=5)
//reverseValueMarkup = input(30, minval=0, maxval=100, step=5)
//stopMultFactor = input(1, minval=0.5, maxval=10, step=0.5)
//considerNewLongTermHighLows = input(true,"Filter Highs/Lows for entry")
//shortHighLowPeriod = input(120, step=10)
//longHighLowPeriod = input(180, step=10)
//considerMaAlignment = input(true,"Check recent moving average alignment")
//MAType = input(title="Moving Average Type", defval="sma", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
//LookbackPeriod = input(200, step=10)
//alignmentIndexThreshold = input(0, step=10)
//includePartiallyAligned = input(true)
//considerMaSupertrend = input(true)
//source = input(ohlc4)
//MaTypeMa = input(title="Volume MA Type", defval="sma", options=["ema", "sma", "hma", "rma", "vwma", "wma"])
//MaLengthMa = input(10, step=10)
//supertrendLengthMa = input(10, step=10)
//supertrendMultMa = input(1, step=1)
supertrendMult = 6
supertrendLength = 22
volumelength = 20
volumeMaType = "sma"
trendVolumeMarkup = 15
reverseVolumeMarkup = 25
highVolumeMultiplyer = 5
atrlength = 22
trendTargetMult = 1
reverseTargetMult = 1
highBreakoutMult = 2
trendValueMarkup = 15
reverseValueMarkup = 30
stopMultFactor = 1
considerYearlyHighLow = true
ignoreReverseBreakout = true
//allowImmediateCompound = true
considerOpenCloseBreakout = false
allowReduceCompound = true
considerNewLongTermHighLows = true
shortHighLowPeriod = 120
longHighLowPeriod = 180
considerMaAlignment = true
MAType = "sma"
LookbackPeriod = 280
alignmentIndexThreshold = 0
includePartiallyAligned = true
considerMaSupertrend = true
source = ohlc4
MaTypeMa = "sma"
MaLengthMa = 10
supertrendLengthMa = 10
supertrendMultMa = 1
exitOnSignal = input(false)
tradeDirection = input(title="Trade Direction", defval=strategy.direction.long, options=[strategy.direction.all, strategy.direction.long, strategy.direction.short])
allowImmediateCompound = input(false)
displayMode = input(title="Display Mode", defval="Targets", options=["Targets", "Target Channel", "Target with Stops", "Up Channel", "Down Channel"])
showTrailingStop = input(true)
showTargetLevels = input(true)
showPreviousLevels = input(false)
stopMultiplyer = input(6, minval=1, maxval=10, step=0.5)
compoundMultiplyer = input(1, minval=1, maxval=10, step=0.5)
backtestYears = input(10, minval=1, step=1)
///////////////////////////// Display mode calculation ////////////////////////////////////////////////
f_getDisplayModeVeriables(displayMode)=>
bool showTargets = false
bool showChannel = false
bool showTargetStops = false
bool showUpChannel = false
bool showDownChannel = false
if(displayMode == "Targets")
showTargets := true
if(displayMode == "Target Channel")
showChannel := true
if(displayMode == "Target with Stops")
showTargetStops := true
if(displayMode == "Up Channel")
showUpChannel := true
if(displayMode == "Down Channel")
showDownChannel := true
[showTargets,showChannel,showTargetStops,showUpChannel,showDownChannel]
///////////////////////////// Get Price breakout values ////////////////////////////////////////////////
f_getPriceBreakout(atr, trendTargetMult, reverseTargetMult, considerOpenCloseBreakout, highBreakoutMult)=>
trendBreakout = false
if(abs(close[1] - close) > atr * trendTargetMult) or (high-low > 2 * atr * trendTargetMult and considerOpenCloseBreakout)
trendBreakout := true
reverseBreakout = false
if(abs(close[1] - close) > atr * reverseTargetMult) or (high-low > 2 * atr * reverseTargetMult and considerOpenCloseBreakout)
reverseBreakout := true
highBreakout = false
if(abs(close[1] - close) > atr * highBreakoutMult) or (high-low > 2 * atr * highBreakoutMult and considerOpenCloseBreakout)
highBreakout:=true
[trendBreakout, reverseBreakout, highBreakout]
///////////////////////////// Get Volume breakout values ////////////////////////////////////////////////
f_getVolumeBreakout(vma, trendVolumeMarkup, reverseVolumeMarkup, highVolumeMarkup)=>
vmaMarkup = vma * (1+(trendVolumeMarkup/100))
vmaReverseMarkup = vma * (1+(reverseVolumeMarkup/100))
vmaHighVolumeMarkup = vma * highVolumeMarkup
trendVolumeBreakout = vmaMarkup < volume or na(volume)
stopVolumeBreakout = vmaReverseMarkup < volume or na(volume)
highVolumeBreakout = vmaHighVolumeMarkup < volume and not na(volume)
[trendVolumeBreakout, stopVolumeBreakout, highVolumeBreakout]
//////////////////////////////////// Get Candle color //////////////////////////////////////////////////
f_getBarState(dir,trendBreakout, reverseBreakout, highBreakout, trendVolumeBreakout, reverseVolumeBreakout, highVolumeBreakout)=>
barState = 0
if(close > close[1] and ( (dir == -1 and trendBreakout and trendVolumeBreakout) or (dir == 1 and reverseBreakout and reverseVolumeBreakout) or highVolumeBreakout or highBreakout))
barState := 1
if(close < close[1] and ( (dir == 1 and trendBreakout and trendVolumeBreakout) or (dir == -1 and reverseBreakout and reverseVolumeBreakout) or highVolumeBreakout or highBreakout))
barState := -1
barState
//////////////////////////////////// Calculate target values //////////////////////////////////////////////////
f_getTargets(barState, trendValueMarkup, reverseValueMarkup, stopMultFactor, dir, atr)=>
diff = max(high-low, max(abs(high-close[1]), abs(low-close[1])))
upTarget = (barState == 1) ? high + ((dir==-1?trendValueMarkup:reverseValueMarkup)/100)*diff : na
downTarget = (barState == -1) ? low - ((dir==1?trendValueMarkup:reverseValueMarkup)/100)*diff : na
stopUpTarget = (barState == 1) ? low - atr * stopMultFactor : na
stopDownTarget = (barState == -1) ? high + atr * stopMultFactor : na
lastBreakout = barState
lastBreakout:= lastBreakout == 0? nz(lastBreakout[1], 0): lastBreakout
[upTarget,stopUpTarget,downTarget,stopDownTarget,lastBreakout]
//////////////////////////////////// Calculate target values //////////////////////////////////////////////////
f_getChannels(upTarget, stopUpTarget, downTarget, stopDownTarget)=>
upLine = upTarget
downLine = downTarget
stopUpLine = stopUpTarget
stopDownLine = stopDownTarget
upLine := na(upLine) ? nz(upLine[1],na) : upLine
downLine := na(downLine) ? nz(downLine[1],na) : downLine
stopUpLine := na(stopUpLine) ? nz(stopUpLine[1],na) : stopUpLine
stopDownLine := na(stopDownLine) ? nz(stopDownLine[1],na) : stopDownLine
[upLine,stopUpLine,downLine,stopDownLine]
//////////////////////////////////// Calculate Yearly High Low //////////////////////////////////////////////////
f_getYearlyHighLowCondition(considerYearlyHighLow)=>
yhigh = security(syminfo.tickerid, '12M', high[1])
ylow = security(syminfo.tickerid, '12M', low[1])
yhighlast = yhigh[365]
ylowlast = ylow[365]
yhighllast = yhigh[2 * 365]
ylowllast = ylow[2 * 365]
yearlyTrendUp = na(yhigh)? true : na(yhighlast)? close > yhigh : na(yhighllast)? close > max(yhigh,yhighlast) : close > max(yhigh, min(yhighlast, yhighllast))
yearlyHighCondition = ( (na(yhigh) or na(yhighlast) ? true : (yhigh > yhighlast) ) and ( na(yhigh) or na(yhighllast) ? true : (yhigh > yhighllast))) or yearlyTrendUp or not considerYearlyHighLow
yearlyTrendDown = na(ylow)? true : na(ylowlast)? close < ylow : na(ylowllast)? close < min(ylow,ylowlast) : close < min(ylow, max(ylowlast, ylowllast))
yearlyLowCondition = ( (na(ylow) or na(ylowlast) ? true : (ylow < ylowlast) ) and ( na(ylow) or na(ylowllast) ? true : (ylow < ylowllast))) or yearlyTrendDown or not considerYearlyHighLow
[yearlyHighCondition,yearlyLowCondition]
//////////////////////////////////// Calculate Trade Flags /////////////////////////////////////////////////////
f_calculateTradeFlags(dir, barState, buySignal, stopBuySignal, sellSignal, stopSellSignal, yearlyHighCondition, yearlyLowCondition, inDateRange)=>
buyPrerequisites = inDateRange and yearlyHighCondition
sellPrerequisites = inDateRange and yearlyLowCondition
buyEntry = buySignal and yearlyHighCondition and barState != -1 and inDateRange
sellEntry = sellSignal and yearlyLowCondition and barState != 1 and inDateRange
stopBuyEntry = stopBuySignal and barState != 1 and inDateRange
stopSellEntry = stopSellSignal and barState != -1 and inDateRange
[buyEntry, sellEntry, stopBuyEntry, stopSellEntry]
//////////////////////////////////// Get Moving average ///////////////////////////////////
f_getMovingAverage(source, MAType, length)=>
ma = sma(source, length)
if(MAType == "ema")
ma := ema(source,length)
if(MAType == "hma")
ma := hma(source,length)
if(MAType == "rma")
ma := rma(source,length)
if(MAType == "vwma")
ma := vwma(source,length)
if(MAType == "wma")
ma := wma(source,length)
ma
f_supertrendOnMa(source, MaType, MaLength, supertrendLength, supertrendMult)=>
supertrendDistance = supertrendMult * atr(supertrendLength)
ma = f_getMovingAverage(source,MaType, MaLength)
longStop = ma - supertrendDistance
longStopPrev = nz(longStop[1], longStop)
longStop := ma > longStopPrev ? max(longStop, longStopPrev) : longStop
shortStop = ma + supertrendDistance
shortStopPrev = nz(shortStop[1], shortStop)
shortStop := ma < shortStopPrev ? min(shortStop, shortStopPrev) : shortStop
dir = 1
dir := nz(dir[1], dir)
dir := dir == -1 and ma > shortStopPrev ? 1 : dir == 1 and ma < longStopPrev ? -1 : dir
supertrend = dir==1 ? longStop: shortStop
[supertrend, ma, dir]
f_getMaAlignment(MAType, includePartiallyAligned)=>
ma5 = f_getMovingAverage(close,MAType,5)
ma10 = f_getMovingAverage(close,MAType,10)
ma20 = f_getMovingAverage(close,MAType,20)
ma30 = f_getMovingAverage(close,MAType,30)
ma50 = f_getMovingAverage(close,MAType,50)
ma100 = f_getMovingAverage(close,MAType,100)
ma200 = f_getMovingAverage(close,MAType,200)
upwardScore = 0
upwardScore := close > ma5? upwardScore+1:upwardScore
upwardScore := ma5 > ma10? upwardScore+1:upwardScore
upwardScore := ma10 > ma20? upwardScore+1:upwardScore
upwardScore := ma20 > ma30? upwardScore+1:upwardScore
upwardScore := ma30 > ma50? upwardScore+1:upwardScore
upwardScore := ma50 > ma100? upwardScore+1:upwardScore
upwardScore := ma100 > ma200? upwardScore+1:upwardScore
upwards = close > ma5 and ma5 > ma10 and ma10 > ma20 and ma20 > ma30 and ma30 > ma50 and ma50 > ma100 and ma100 > ma200
downwards = close < ma5 and ma5 < ma10 and ma10 < ma20 and ma20 < ma30 and ma30 < ma50 and ma50 < ma100 and ma100 < ma200
upwards?1:downwards?-1:includePartiallyAligned ? (upwardScore > 5? 0.5: upwardScore < 2?-0.5:upwardScore>3?0.25:-0.25) : 0
//////////////////////////////////// Calculate Buy Sell signals //////////////////////////////////////////////////
f_calculateBuySellFlags(dir,lastBreakout,ignoreReverseBreakout, barState, upLine, stopUpLine, downLine, stopDownLine)=>
greenBreakout = (lastBreakout > 0) or ignoreReverseBreakout
redBreakout = (lastBreakout < 0) or ignoreReverseBreakout
buySignal = ((crossover(dir==-1?high:low, upLine[1]) and greenBreakout and close > downLine[1]) or (crossover(dir==-1?high:low, stopDownLine[1]) and redBreakout) or ((barState == 1) and (dir==-1?high:low) > upLine[1]))
stopBuySignal = (crossunder(dir==-1?close:low, downLine[1]) or crossunder(dir==-1?close:low, stopUpLine[1]))
sellSignal = ((crossunder(dir==1?low:high, downLine[1]) and redBreakout and close < upLine[1]) or (crossunder(dir==1?low:high, stopUpLine[1]) and greenBreakout) or (barState == -1) and (dir==1?low:high) < downLine[1])
stopSellSignal = (crossover(dir==1?close:high, upLine[1]) or crossover(dir==1?close:high, stopDownLine[1]))
[buySignal,stopBuySignal,sellSignal,stopSellSignal]
//////////////////////////////////// Calculate new high low condition //////////////////////////////////////////////////
f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)=>
newHigh = highest(shortHighLowPeriod) == highest(longHighLowPeriod) or not considerNewLongTermHighLows
newLow = lowest(shortHighLowPeriod) == lowest(longHighLowPeriod) or not considerNewLongTermHighLows
[newHigh,newLow]
//////////////////////////////////// Calculate trailing stop //////////////////////////////////////////////////
f_calculateTrailingStop(stop)=>
strategy.position_size > 0? (stop > stop[1]? stop : stop[1]) : strategy.position_size < 0 ? (stop < stop[1]? stop : stop[1]) : stop
//////////////////////////////////// Calculate stop and compound //////////////////////////////////////////////////
f_calculateStopAndCompound(target, atr, stopMultiplyer, compoundMultiplyer, barState)=>
buyStop = target - (stopMultiplyer * atr)
sellStop = target + (stopMultiplyer * atr)
if(barState > 0 or strategy.position_size > 0)
buyStop := target - (stopMultiplyer * atr)
sellStop := target + (compoundMultiplyer * atr)
buyStop := (buyStop < buyStop[1] or close < sellStop[1])? buyStop[1] : buyStop
sellStop := (sellStop < sellStop[1] or close < sellStop[1]) ? sellStop[1] : sellStop
else if(barState < 0 or strategy.position_size < 0)
buyStop := target - (compoundMultiplyer * atr)
sellStop := target + (stopMultiplyer * atr)
sellStop := (sellStop > sellStop[1] or close > buyStop[1])? sellStop[1] : sellStop
buyStop := (buyStop > buyStop[1] or close > buyStop[1]) ? buyStop[1] : buyStop
[buyStop, sellStop]
//////////////////////////////////// Draw Lines with labels //////////////////////////////////////////////////
f_drawLinesWithLabels(target, lbl, linecolor)=>
line_x1 = time+(60*60*24*1000*1)
line_x2 = time+(60*60*24*1000*7)
label_x = time+(60*60*24*1000*4)
targetLine = line.new(x1=line_x1, y1=target, x2=line_x2, y2=target, color=linecolor, xloc=xloc.bar_time)
targetLabel = label.new(x=label_x, y=target, text=lbl + " : "+tostring(target), xloc=xloc.bar_time, style=label.style_none, textcolor=color.black, size=size.normal)
[targetLine,targetLabel]
//////////////////////////////////// Delete Lines with labels //////////////////////////////////////////////////
f_deleteLinesWithLabels(targetLine, targetLabel, last)=>
line.delete(id=last?targetLine[1]:targetLine)
label.delete(id=last?targetLabel[1]:targetLabel)
/////////////////////////////////////////////////// Calculate Trend //////////////////////////////////////////////////////
inDateRange = time >= timestamp(syminfo.timezone, year(timenow) - backtestYears, 01, 01, 0, 0)
[showTargets,showChannel,showTargetStops,showUpChannel,showDownChannel] = f_getDisplayModeVeriables(displayMode)
vma = f_getMovingAverage(volume, volumeMaType, volumelength)
[superTrend, dir] = supertrend(supertrendMult, supertrendLength)
atr = atr(atrlength)
[trendBreakout, reverseBreakout, highBreakout] = f_getPriceBreakout(atr, trendTargetMult, reverseTargetMult, considerOpenCloseBreakout, highBreakoutMult)
[trendVolumeBreakout, reverseVolumeBreakout, highVolumeBreakout] = f_getVolumeBreakout(vma, trendVolumeMarkup, reverseVolumeMarkup, highVolumeMultiplyer)
barState = f_getBarState(dir,trendBreakout, reverseBreakout, highBreakout, trendVolumeBreakout, reverseVolumeBreakout, highVolumeBreakout)
[upTarget,stopUpTarget,downTarget,stopDownTarget, lastBreakout] = f_getTargets(barState, trendValueMarkup, reverseValueMarkup, stopMultFactor, dir, atr)
[upLine,stopUpLine,downLine,stopDownLine] = f_getChannels(upTarget, stopUpTarget, downTarget, stopDownTarget)
[yearlyHighCondition,yearlyLowCondition] = f_getYearlyHighLowCondition(considerYearlyHighLow)
[supertrendMa, ma, dirMa] = f_supertrendOnMa(source, MaTypeMa, MaLengthMa, supertrendLengthMa, supertrendMultMa)
//////////////////////////////////////// Calculate Trade //////////////////////////////////////////////////////
percentRank = percentrank(source, LookbackPeriod)
[buySignal,stopBuySignal,sellSignal,stopSellSignal] = f_calculateBuySellFlags(dir,lastBreakout,ignoreReverseBreakout, barState, upLine, stopUpLine, downLine, stopDownLine)
[newHigh, newLow] = f_calculateNewHighLows(shortHighLowPeriod, longHighLowPeriod, considerNewLongTermHighLows)
[buyEntry, sellEntry, stopBuyEntry, stopSellEntry] = f_calculateTradeFlags(dir, barState, buySignal, stopBuySignal, sellSignal, stopSellSignal, yearlyHighCondition, yearlyLowCondition, inDateRange)
[buyStop, sellStop] = f_calculateStopAndCompound(close, atr, stopMultiplyer, compoundMultiplyer, barState)
crossedCompound = (strategy.position_size > 0 ? close > sellStop : strategy.position_size < 0 ? close < buyStop : true) or allowImmediateCompound
maAlignment = f_getMaAlignment(MAType,includePartiallyAligned)
alignedMaIndex = sum(maAlignment,LookbackPeriod)
maHigh = alignedMaIndex > alignmentIndexThreshold or not considerMaAlignment
maLow = alignedMaIndex < -alignmentIndexThreshold or not considerMaAlignment
//buyEntry := buyEntry and ((newHigh and maHigh and percentRank > 50) or strategy.netprofit >= 0)
//sellEntry := sellEntry and ((newLow and maLow and percentRank < 50) or strategy.netprofit >= 0)
buyEntry := buyEntry and ((newHigh and maHigh and (dirMa == 1 or not considerMaSupertrend) and percentRank > 70) or strategy.netprofit >= 0)
sellEntry := sellEntry and ((newLow and maLow and (dirMa == -1 or not considerMaSupertrend) and percentRank < 30) or strategy.netprofit >= 0)
//////////////////////////////////////// Plot //////////////////////////////////////////////////////
plot(showChannel?upLine:na, title="UpChannel", color=color.green, linewidth=2, style=plot.style_line)
plot(showChannel?downLine:na, title="downChannel", color=color.red, linewidth=2, style=plot.style_line)
plotshape(showTargets or showTargetStops?upTarget:na, title="UpTarget", color=color.green, style=shape.triangleup, location = location.absolute)
plotshape(showTargets or showTargetStops?downTarget:na, title="DownTarget", color=color.red, style=shape.triangledown, location = location.absolute)
plotshape(showTargetStops?stopUpTarget:na, title="UpStop", color=color.green, style=shape.triangleup, location = location.absolute)
plotshape(showTargetStops?stopDownTarget:na, title="DownStop", color=color.red, style=shape.triangledown, location = location.absolute)
plot(showUpChannel?upLine:na, title="UpChannel", color=color.green, linewidth=2, style=plot.style_line)
plot(showUpChannel?stopUpLine:na, title="StopUpChannel", color=color.red, linewidth=2, style=plot.style_line)
plot(showDownChannel?stopDownLine:na, title="StopDownChannel", color=color.green, linewidth=2, style=plot.style_line)
plot(showDownChannel?downLine:na, title="DownChannel", color=color.red, linewidth=2, style=plot.style_line)
channelview = showChannel or showUpChannel or showDownChannel
plot(showTrailingStop and strategy.position_size != 0 and not channelview? buyStop : na, title="DownStop", color=(strategy.position_size > 0?color.green:strategy.position_size < 0 ?color.red:color.blue), linewidth=2, style=plot.style_stepline)
plot(showTrailingStop and strategy.position_size != 0 and not channelview? sellStop : na, title="UpStop", color=(strategy.position_size > 0?color.green:strategy.position_size < 0 ?color.red:color.blue), linewidth=2, style=plot.style_stepline)
//plot(percentValue, title="percentRank", color=color.blue, linewidth=2, style=plot.style_stepline)
barcolor(barState == 1? color.lime : barState == -1? color.orange : color.silver)
//////////////////////////////////////// Plot Trade //////////////////////////////////////////////////////
if(buyEntry or sellEntry) and (showTargetLevels)
[targetLine, targetLabel] = f_drawLinesWithLabels(close,buyEntry?"Long":"Short",color.blue)
if(not showPreviousLevels)
f_deleteLinesWithLabels(targetLine, targetLabel, true)
if(buyEntry or sellEntry or strategy.position_size != 0)
[stopLine, stopLabel] = f_drawLinesWithLabels(buyEntry?buyStop:sellStop,"Stop",color.red)
[compoundLine, compoundLabel] = f_drawLinesWithLabels(buyEntry?sellStop:buyStop,"Compound",color.green)
f_deleteLinesWithLabels(stopLine, stopLabel, true)
f_deleteLinesWithLabels(compoundLine, compoundLabel, true)
//////////////////////////////////////// Trade //////////////////////////////////////////////////////
strategy.risk.allow_entry_in(tradeDirection)
strategy.entry("Buy", strategy.long, when=buyEntry and crossedCompound)
strategy.close("Buy", when=stopBuyEntry and exitOnSignal)
strategy.exit("ExitBuy", "Buy", stop = buyStop)
strategy.entry("Sell", strategy.short, when=sellEntry and crossedCompound)
strategy.close("Sell", when=stopSellEntry and exitOnSignal)
strategy.exit("ExitSell", "Sell", stop = sellStop)
Expand (395 lines)
Show all 332 lines