// SFP Inquisitor // 1.0 // // coded by Bogdan Vaida // Code for Swing High, Swing Low and Swing Failure Pattern. // Note that the number you set in your Swing History variable // will also be the minimum delay you see until the apples appear. // This is because we're checking the forward "history" too. // The SFP will only check for these conditions: // - high above Swing History high and close below it // - low below Swing History high and close above it // In some cases you may see an apple before the SFP that "doesn't fit" // with the SFP conditions. That's because that apple was drawn later and // the SFP actually appeared because of the previous apple. // 20 candles later. // Legend: // 🍏 - swing high // 🍎 - swing low // 🍌 - swing failure pattern // 🍎🍌 - hungry scenario: swing low but also a SFP compared to the last swing // 🍰 - cake is for stronger SFPs / SFPs in a row (but with a the secret sauce) // IDEAS: // - show potential swing highs/lows (where current bar is < Swing History) // - different types of bananas (or kiwi on 1' and a mango on a HTF SFP) (credits: @imal_max) // Tested on 5' BTCUSDT and 4h ETHUSD //@version=5 indicator(title='SFP + Triple EMA', overlay=true) // 🔥 Uncomment the lines below for the strategy and revert for the study // strategy(title="🍏🍎🍌 Swing Failure Pattern Inquisitor", shorttitle="SFP-I", overlay=true, pyramiding=1, // process_orders_on_close=true, calc_on_every_tick=true, // initial_capital=1000, currency = currency.USD, default_qty_value=10, // default_qty_type=strategy.percent_of_equity, // commission_type=strategy.commission.percent, commission_value=0.1, slippage=2) swingHistory = input.int(10, title='Swing history:', minval=1) plotSwings = input(true, title='Plot swings') plotFirstSFPOnly = input(false, title='Plot only first SFP candle') plotStrongerSFPs = input.int(10, title='Plot stronger SFPs:', minval=0) tradingDirection = input.string(title='Trading Direction: ', group='Strategy', defval='L', options=['L&S', 'L', 'S']) stopLoss = input.float(1.0, title='Stop Loss %', group='Strategy') / 100 takeProfit = input.float(3.0, title='Take Profit %', group='Strategy') / 100 plotTP = input.bool(true, title='Take Profit?', group='Strategy', inline='plot1') plotSL = input.bool(true, title='Stop-Loss?', group='Strategy', inline='plot1') plotBgColor = input.bool(true, title='Plot Background Color?', group='Strategy') startDate = input.int(title='Start Date', defval=1, minval=1, maxval=31, group='Backtesting range') startMonth = input.int(title='Start Month', defval=5, minval=1, maxval=12, group='Backtesting range') startYear = input.int(title='Start Year', defval=2021, minval=1800, maxval=2100, group='Backtesting range') endDate = input.int(title='End Date', defval=1, minval=1, maxval=31, group='Backtesting range') endMonth = input.int(title='End Month', defval=1, minval=1, maxval=12, group='Backtesting range') endYear = input.int(title='End Year', defval=2040, minval=1800, maxval=2100, group='Backtesting range') // Date range filtering inDateRange = time >= timestamp(syminfo.timezone, startYear, startMonth, startDate, 0, 0) and time < timestamp(syminfo.timezone, endYear, endMonth, endDate, 23, 59) // Swing Lows and Swing Highs code isSwingHigh = false isSwingLow = false swingHigh = high[swingHistory] swingLow = low[swingHistory] range_1 = swingHistory * 2 for i = 0 to range_1 by 1 isSwingHigh := true if i < swingHistory if high[i] > swingHigh isSwingHigh := false break if i > swingHistory if high[i] >= swingHigh isSwingHigh := false break for i = 0 to range_1 by 1 isSwingLow := true if i < swingHistory if low[i] < swingLow isSwingLow := false break if i > swingHistory if low[i] <= swingLow isSwingLow := false break // Swing Failure Pattern isSwingHighFailure = false isSwingLowFailure = false var lastSwingHigh = float(na) var lastSwingLow = float(na) lastSwingHigh := isSwingHigh ? swingHigh : lastSwingHigh lastSwingLow := isSwingLow ? swingLow : lastSwingLow strengthOfHighSFP = 0 if lastSwingHigh < high and lastSwingHigh > close and ta.barssince(lastSwingHigh) <= swingHistory isSwingHighFailure := true if plotFirstSFPOnly lastSwingHigh := na else for i = 0 to plotStrongerSFPs by 1 if isSwingHighFailure[i] strengthOfHighSFP += 1 // it will be at least 1 else if high[i] > high strengthOfHighSFP -= 1 strengthOfLowSFP = 0 if lastSwingLow > low and lastSwingLow < close and ta.barssince(lastSwingLow) <= swingHistory isSwingLowFailure := true if plotFirstSFPOnly lastSwingLow := na else for i = 0 to plotStrongerSFPs by 1 if isSwingHighFailure[i] strengthOfLowSFP += 1 // it will be at least 1 else if low[i] < low strengthOfLowSFP -= 1 // Debugging plotchar(isSwingHighFailure, 'Swing High Failure', '', location.top) plotchar(isSwingLowFailure, 'Swing Low Failure', '', location.top) plotchar(lastSwingHigh, 'Last Swing High', '', location.top) plotchar(lastSwingLow, 'Last Swing Low', '', location.top) // Alerting alertcondition(condition=isSwingHighFailure, title='SFP: Swing High Failure', message='Swing High Failure') alertcondition(condition=isSwingLowFailure, title='SFP: Swing Low Failure', message='Swing Low Failure') alertcondition(condition=isSwingHighFailure or isSwingLowFailure, title='SFP: Any Swing Failure Pattern', message='Any Swing Failure Pattern') // Plotting plotchar(series=plotSwings ? isSwingHigh : na, char='🍏', location=location.abovebar, size=size.tiny, offset=-swingHistory) plotchar(series=plotSwings ? isSwingLow : na, char='🍎', location=location.belowbar, size=size.tiny, offset=-swingHistory) plotchar(series=isSwingHighFailure and strengthOfHighSFP <= 1, char='🍌', location=location.abovebar, size=size.tiny) plotchar(series=isSwingHighFailure and strengthOfHighSFP >= 3, char='🍰', location=location.abovebar, size=size.tiny) plotchar(series=isSwingLowFailure and strengthOfLowSFP <= 1, char='🍌', location=location.belowbar, size=size.tiny) plotchar(series=isSwingLowFailure and strengthOfLowSFP >= 3, char='🍰', location=location.belowbar, size=size.tiny) // 🔥 Uncomment the lines below for the strategy and revert for the study // TP = strategy.position_size > 0 ? strategy.position_avg_price * (1 + takeProfit) : // strategy.position_size < 0 ? strategy.position_avg_price * (1 - takeProfit) : na // SL = strategy.position_size > 0 ? strategy.position_avg_price * (1 - stopLoss) : // strategy.position_size < 0 ? strategy.position_avg_price * (1 + stopLoss) : na // plot(series = (plotTP and strategy.position_size != 0) ? TP : na, style=plot.style_linebr, color=color.green, title="TP") // plot(series = (plotSL and strategy.position_size != 0) ? SL : na, style=plot.style_linebr, color=color.red, title="SL") // bgcolor(plotBgColor ? strategy.position_size > 0 ? color.new(color.green, 75) : strategy.position_size < 0 ? color.new(color.red,75) : color(na) : color(na)) // strategy.risk.allow_entry_in(tradingDirection == "L&S" ? strategy.direction.all : // tradingDirection == "L" ? strategy.direction.long : // tradingDirection == "S" ? strategy.direction.short : na) // strategy.entry("SFP", strategy.long, comment="Long", when=isSwingLowFailure) // strategy.entry("SFP", strategy.short, comment="Short", when=isSwingHighFailure) // strategy.exit(id="TP-SL", from_entry="SFP", limit=TP, stop=SL) // if (not inDateRange) // strategy.close_all() //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Triple EMA /////////////////////////////////////////////////////////////////////////////////////////////////////////// length = input.int(9, minval=1) ema1 = ta.ema(close, length) ema2 = ta.ema(ema1, length) ema3 = ta.ema(ema2, length) out = 3 * (ema1 - ema2) + ema3 plot(out, "TEMA", color=#2962FF)