FREE Profitable Forex Breakout Fading Strategy
This profitable strategy attempts to "fade" breakouts in the forex markets. In other words, it trades counter-trend to breakouts.
Check out my other free lessons!Source Code
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ // © ZenAndTheArtOfTrading / www.PineScriptMastery.com // @version=6 strategy( title = "FX Breakout Fader", currency = "USD", initial_capital = 10000, calc_on_order_fills=true, // Pepperstone margin & costs: margin_long = 3.33, margin_short = 3.33, commission_type = strategy.commission.cash_per_contract, commission_value = 0.000035 ) //! Import ZenLibrary import ZenAndTheArtOfTrading/ZenLibrary/10 as zen //! Get user input var string G_STRATEGY = "Strategy Settings" string INPUT_TIMEFRAME = input.timeframe(title="Higher Timeframe", defval="D", group=G_STRATEGY) float INPUT_STRETCH = input.float(title="Limit Order ATR Stretch", defval=1.0, group=G_STRATEGY, display=display.none, tooltip="ATR X from previous HTF high/low to place buy/short orders.") float INPUT_RISKRATIO = input.float(title="Risk:Reward", defval=1.0, group=G_STRATEGY, display=display.none, tooltip="Risk:Reward ratio (2 = 2x profit target distance vs stop loss distance)") float INPUT_SL_MULTIPLIER = input.float(title="Stop Multiplier", defval=2.0, group=G_STRATEGY, display=display.none, tooltip="Stop Loss ATR multiplier (2 = 2x ATR from limit order price)") bool INPUT_CANCEL_ORDERS = input.bool(title="Cancel Orders After Fill", defval=true, group=G_STRATEGY, display=display.none, tooltip="If an order is filled, cancel the other order (eg. if a bullish breakout is triggered, cancel the short breakout order)") bool INPUT_USE_TRAILSTOP = input.bool(title="Use Trailing Stop", defval=true, group=G_STRATEGY, display=display.none, tooltip="Enable/Disable ATR based trailing stop exit.") var string G_FILTERS = "Strategy Filters" bool INPUT_HTF_EMA_FILTER = input.bool(title="Use HTF EMA Filter", defval=true, group=G_FILTERS, display=display.none, tooltip="Enable/Disable HTF EMA filter.") int INPUT_HTF_EMA_LENGTH = input.int(title="HTF EMA Filter Length", defval=20, group=G_FILTERS, display=display.none, tooltip="HTF EMA period length.") var string G_TESTER = "Backtesting Settings" bool INPUT_USE_LOTS = input.bool(title="Use Lots", defval=true, group=G_TESTER, tooltip="Use lots instead of units (rounds position size to multiplies of 1,000, 10,000 or 100,000)", display=display.none) float INPUT_RISK_PER_TRADE = input.float(title="Risk Per Trade", defval=1.0, group=G_TESTER, tooltip="Your desired risk per trade as % of account balance (as a whole number)", display=display.none) //! Non-repainting and non-cheating security function reference rp_security(_symbol, _timeframe, _src) => request.security(_symbol, _timeframe, _src[1], lookahead=barmerge.lookahead_on, gaps=barmerge.gaps_off) //! Long order variables var float longStopOrder = na var float longStopLoss = na var float longTarget = na //! Short order variables var float shortStopOrder = na var float shortStopLoss = na var float shortTarget = na //! General variables var bool tookTradeToday = false var bool cancelledPendingOrders = false //! Get HTF data dailyOpen = rp_security(syminfo.tickerid, INPUT_TIMEFRAME, open) dailyHigh = rp_security(syminfo.tickerid, INPUT_TIMEFRAME, high) dailyLow = rp_security(syminfo.tickerid, INPUT_TIMEFRAME, low) dailyClose = rp_security(syminfo.tickerid, INPUT_TIMEFRAME, close) dailyEMA = rp_security(syminfo.tickerid, INPUT_TIMEFRAME, ta.ema(close, INPUT_HTF_EMA_LENGTH)) //! Get indicator values float atr = ta.atr(14) //! Check filters bool readyToTrade = not na(atr) bool generalFilters = readyToTrade bool shortSetupConditionsMet = generalFilters and (not INPUT_HTF_EMA_FILTER or dailyClose < dailyEMA) bool longSetupConditionsMet = generalFilters and (not INPUT_HTF_EMA_FILTER or dailyClose > dailyEMA) bgcolor(shortSetupConditionsMet ? color.red : na) bgcolor(longSetupConditionsMet ? color.green : na) bgcolor(not shortSetupConditionsMet and not longSetupConditionsMet ? color.gray : na) //! Detect unique breakout for today bool newDay = bool(ta.change(time(INPUT_TIMEFRAME))) bgcolor(newDay ? color.new(color.white, 99) : na, force_overlay=true) //! If a new day has begun, place our pending orders if (newDay) // Cancel any pending orders from yesterday strategy.cancel("Short Entry") strategy.cancel("Long Entry") tookTradeToday := false // If we are flat with no open trades, we are free to place new orders if (strategy.position_size == 0) shortStopOrder := dailyHigh + (atr * INPUT_STRETCH) shortStopLoss := shortStopOrder + (atr * INPUT_SL_MULTIPLIER) shortStopDist = math.abs(shortStopLoss - shortStopOrder) shortTargetDist = shortStopDist * INPUT_RISKRATIO shortTarget := shortStopOrder - shortTargetDist longStopOrder := dailyLow - (atr * INPUT_STRETCH) longStopLoss := longStopOrder - (atr * INPUT_SL_MULTIPLIER) longStopDist = math.abs(longStopLoss - longStopOrder) longTargetDist = longStopDist * INPUT_RISKRATIO longTarget := longStopOrder + longTargetDist if (shortSetupConditionsMet) strategy.order("Short Entry", strategy.short, qty=zen.getFxPositionSize(INPUT_RISK_PER_TRADE, zen.toWhole(shortStopLoss - shortStopOrder), lots=INPUT_USE_LOTS), limit=shortStopOrder) cancelledPendingOrders := false else shortStopOrder := na if (longSetupConditionsMet) strategy.order("Long Entry", strategy.long, qty=zen.getFxPositionSize(INPUT_RISK_PER_TRADE, zen.toWhole(longStopOrder - longStopLoss), lots=INPUT_USE_LOTS), limit=longStopOrder) cancelledPendingOrders := false else longStopOrder := na //! Update trailing stop if (INPUT_USE_TRAILSTOP) shortTarget := na longTarget := na if (strategy.position_size > 0) // Long trailing stop float newLongStop = low - (atr * INPUT_SL_MULTIPLIER) if (newLongStop > longStopLoss) longStopLoss := newLongStop if (strategy.position_size < 0) // Short trailing stop float newShortStop = high + (atr * INPUT_SL_MULTIPLIER) if (newShortStop < shortStopLoss) shortStopLoss := newShortStop //! Check stops & targets being hit strategy.exit(id="Long Exit", from_entry="Long Entry", limit=longTarget, stop=longStopLoss) strategy.exit(id="Short Exit", from_entry="Short Entry", limit=shortTarget, stop=shortStopLoss) //! For stopping drawing the order lines and cancelling any remaining buy/short orders if necessary if (strategy.equity != strategy.equity[1] and not tookTradeToday) tookTradeToday := true if (INPUT_CANCEL_ORDERS and not cancelledPendingOrders) cancelledPendingOrders := true strategy.cancel("Short Entry") strategy.cancel("Long Entry") //! Draw indicator data plot(dailyEMA, force_overlay=true, color=color.white, display=display.pane, title="HTF EMA") //! Draw highs and lows to the chart plot(newDay ? na : dailyHigh, color=color.yellow, linewidth=2, style=plot.style_linebr, display=display.pane, force_overlay=true, title="HTF High") plot(newDay ? na : dailyLow, color=color.blue, linewidth=2, style=plot.style_linebr, display=display.pane, force_overlay=true, title="HTF Low") //! Draw stops & targets plot(strategy.position_size > 0 ? longStopLoss : na, color=color.red, style=plot.style_linebr, force_overlay=true, title="Trade Stop") plot(strategy.position_size > 0 ? longTarget : na, color=color.green, style=plot.style_linebr, force_overlay=true, title="Trade Target") plot(strategy.position_size < 0 ? shortStopLoss : na, color=color.red, style=plot.style_linebr, force_overlay=true, title="Trade Stop") plot(strategy.position_size < 0 ? shortTarget : na, color=color.green, style=plot.style_linebr, force_overlay=true, title="Trade Target") //! Draw entries plot(tookTradeToday or newDay ? na : longStopOrder, color=color.gray, force_overlay=true, style=plot.style_linebr, title="Long Entry Price") plot(tookTradeToday or newDay ? na : shortStopOrder, color=color.gray, force_overlay=true, style=plot.style_linebr, title="Short Entry Price")