//@version = 3 //THIS STRATEGY UTILISES PRICE REENTRY TO UPPER AND LOWER BOLLINGER BANDS TO TRIGGER SHORT AND LONG TRADES ON 1 MIN CHART. TRADE ENTRY IS QUALIFIED BY ONLY TRADING IN THE DIRECTION OF A LONGER-TERM MOVING AVERAGE, AND ONLY WHEN THE SLOPE OF THAT LONGER MA EXCEEDS A CERTAIN VALUE // 4 SIMULTANEOUS TRADES ARE PLACED TO ALLOW DOLLAR-COST AVERAGE EXIT BASED ON DIFFERENT PARAMETERS (OF PERCENTAGE PROFIT AND DISTANCE OUTSIDE OF OPPOSING BOLLINGER BAND) // Opening Parameters set: // default_qty_type - orders are placed based on a percentage of available equity // pyramiding - the strategy may be repeated in a stacked fashion, up to 12 total orders (in fact as we place 4 at a time, this means 3 batches of orders in total) // default_qty_value - 8.33% of available equity will be used for each order - as we use 4 simultaneous order placements this means that a third of available equity is used per batch of 4 orders // commission_value - commission is applied at the rate of 0.01 percent strategy("GBPUSD 1 min MA SLOPE DCA Exit", overlay=true, default_qty_type = strategy.percent_of_equity, pyramiding = 12, default_qty_value = 8.33, commission_type=strategy.commission.percent, commission_value=0.01) //INPUT PARAMETERS //These are the parameters which are subject to optimisation source = close // source price for calculations is close price length = input(87, minval=1) // length for the sma calculation used for centreline of Bollinger Bands mult = input(1.4, minval=0.001, maxval=50) // multiplier applied to the standard deviation away from BB centreline, to define upper and lower bands stop_loss_percentage = input(1.0) // stop loss for all trade batches ProfitTarget1 = input(0.6) // profit target percentage for first quarter of trade (DCA exit strategy) ProfitTarget2 = input(1.0) // profit target percentage for second quarter of trade (DCA exit strategy) MASlopeLength = input(246) // length of the longer-term moving average used for trade qualification MASlopeThreshold = input(50.0) // threshold minimum slope of the longer-term MA ExitOutsideBand = input(1.5) // additional multiple used to define an extreme outside the bands at which trades should be exited (DCA Exit Strategy) TrailingStopLimit = input(1.4) // percentage at which a trailing stop should be activated for a portion of the trade (DCA Exit Strategy) TrailingStopOffset = input(50) // offset for the trailing stop in pips WaitBeforeReentry = input(4) // how many bars to wait after a trade before permitting another set of trade entries //calculate stop loss in quantity terms for use in exit management stop_loss = close*stop_loss_percentage*1000 //calculate BB SMA centre line and spread basis = sma(source, length) dev = mult * stdev(source, length) //calculate spread for outer extreme BB bounds for use in trade exits devexit = (mult+ExitOutsideBand)*stdev(source,length) //calculate upper and lower BB lines. uppersl & lowersl provide for possible adjusted stop loss zones outside of the bands upper = basis + dev lower = basis - dev uppersl = basis + (dev*3) lowersl = basis - (dev*3) //calculate upper and lower extreme BB bound lines for use in trade exits upperexit = basis + devexit lowerexit = basis - devexit //plot the bollinger bands plot(upper) plot(lower) //calculate the slope of the longer-term moving average used for trade entry qualification //the 10000000 multiplier is arbitrary and just makes the number of decimals used for optimisation more manageable. it may need to be changed depending on the asset ma = sma(source, MASlopeLength) old_MA = (nz(ma[1],0)) MASlope = ma-old_MA MASlope_grade = (MASlope * 10000000)/ma //Plot the longer-term MA line for reference plot (ma, color = green, linewidth = 4) //Create a variable with the current average price in the trade to use for some trade exit qualifications - use SMA length 1 to provide current price PriceinTrade = sma(source, 1) // LONG TRADE ENTRY CONDITION - when the price crosses back over the lower BB and the longer term MA Slope is greater than the threshold EntryConditionLong = (crossover(source, lower) and MASlope_grade > MASlopeThreshold) // Enter 4 simultaneous Trades based on the above entry condition and if at least "WaitBeforeReentry" number of bars has passed since the last valid trade entry. // This prevents burning all our capital on multiple entries across sequential bars, effectively for the same entry condition, when the price is hovering around the lower BB if (EntryConditionLong and barssince(EntryConditionLong[1])>WaitBeforeReentry) // First we cancel all existing Short postions strategy.cancel("Short1") strategy.cancel("Short2") strategy.cancel("Short3") strategy.cancel("Short4") // 4 simultaneous entries - effectively one trade but split up to allow dollar-cost-average exiting strategy.entry("Long1", strategy.long, comment="Long1") strategy.entry("Long2", strategy.long, comment="Long2") strategy.entry("Long3", strategy.long, comment="Long3") strategy.entry("Long4", strategy.long, comment="Long4") // EXIT CRITERIA // EXIT Long1 at profit target 1 or via stop loss strategy.close(id="Long1", when = (PriceinTrade/strategy.position_avg_price) > (1+(ProfitTarget1/100))) strategy.exit(id="Stop1",from_entry="Long1",loss=stop_loss, comment="Long1 Stop") // EXIT Long2 at profit target 2 or via stop loss strategy.close(id="Long2", when = (PriceinTrade/strategy.position_avg_price) > (1+(ProfitTarget2/100))) strategy.exit(id="Stop2",from_entry="Long2",loss=stop_loss, comment="Long 2 Stop") // EXIT Long3 when price closes above upper exit band strategy.close(id="Long3", when = crossover(PriceinTrade,upperexit)) strategy.exit(id="Stop3",from_entry="Long3", trail_price = strategy.position_avg_price*(1+TrailingStopLimit/100), trail_offset=TrailingStopOffset, loss=stop_loss, comment="Long 3 Stop") // Let Long 4 ride to full profit target, but apply a trailing stop when we reach the TrailingStopLimit strategy.exit(id="Stop4",from_entry="Long4", trail_price = strategy.position_avg_price*(1+TrailingStopLimit/100), trail_offset=TrailingStopOffset, loss=stop_loss, comment="Long 4 Stop") //ADDITIONALLY EXIT LONG1 and LONG2 IF PRICE CLOSES ABOVE UPPER EXTREME BB EXIT THRESHOLD if crossover(source, upperexit) strategy.close("Long1") strategy.close("Long2") //SHORT TRADE ENTRY CONDITION //Because the required longer term MA slope for a short will be down (i.e. negative), we make the MASlopeThreshold negative and required the slope to be below this value. EntryConditionShort = (crossunder(source, upper) and MASlope_grade < -1*MASlopeThreshold) //SHORT ENTRIES. The oppposite of the long entries if (EntryConditionShort and barssince(EntryConditionShort[1])>WaitBeforeReentry) strategy.cancel("Long1") strategy.cancel("Long2") strategy.cancel("Long3") strategy.cancel("Long4") strategy.entry("Short1", strategy.short, comment="Short1") strategy.entry("Short2", strategy.short, comment="Short2") strategy.entry("Short3", strategy.short, comment="Short3") strategy.entry("Short4", strategy.short, comment="Short4") // SHORT EXITS // EXIT Short1 at profit target 1 or via stop loss strategy.close(id="Short1", when = (PriceinTrade/strategy.position_avg_price) < (1-(ProfitTarget1/100))) strategy.exit(id="ShStop1",from_entry="Short1",loss=stop_loss, comment="Short 1 Stop") // EXIT Short2 at profit target 2 or via stop loss strategy.close(id="Short2", when = (PriceinTrade/strategy.position_avg_price) < (1-(ProfitTarget2/100))) strategy.exit(id="ShStop2",from_entry="Short2",loss=stop_loss, comment="Short 2 Stop") // EXIT Short3 strategy.close(id="Short3", when = crossunder(PriceinTrade,lowerexit)) strategy.exit(id="ShStop3",from_entry="Short3",trail_price = strategy.position_avg_price*(1-TrailingStopLimit/100), trail_offset=TrailingStopOffset, loss=stop_loss, comment="Short 3 Stop") //EXIT Short 4 strategy.exit(id="ShStop4",from_entry="Short4",trail_price = strategy.position_avg_price*(1-TrailingStopLimit/100), trail_offset=TrailingStopOffset, loss=stop_loss, comment="Short 4 Stop") //ADDITIONALLY EXIT SHORT 1 AND SHORT 2 IF PRICE CLOSES BELOW LOWER exit band if crossunder(source, lowerexit) strategy.close("Short1") strategy.close("Short2")