Indicator · Pine Script v5 · On the chart

Flip Flop

by harryguiacorn· code credited to FxCloudTrader

Flip Flop is an overlay indicator that analyzes candle data over a customizable lookback period to track structural market extremes.

View on GitHub

GitHub stars219on the repository
Pine versionv5runs as is
Lines of code169
Settings5inputs
LicenceNone statedfile: MPL-2.0
Last update1 year ago8 May 2025

Add It to Your TradingView Chart

  1. 1Copy the scriptPress Copy script above, or the copy button on the code below.
  2. 2Open the Pine EditorOpen a TradingView chart and choose Pine Editor at the bottom of the screen.
  3. 3Paste over the templateCreate a new indicator, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart, then adjust the settings with the gear icon next to its name.

Source Code

169 lines of Pine Script v5 from Flip Flop.pine, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

Flip Flop.pine
// This Pine Script™ code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © FxCloudTrader

//@version=5
indicator(title="Flip Flop", shorttitle="Flip Flop", overlay=true, precision =4)
var group_bars = "Flip Flop"
lookbackInput = input.int(20, "Lookback in bars", minval = 1, maxval = 4999, group =  group_bars)
display_low_of_highest_bull_bar = input(true,"display_low_of_highest_bull_bar", group =  group_bars)
display_high_of_lowest_bear_bar = input(true,"display_high_of_lowest_bear_bar", group =  group_bars)

isBullish(i) =>
    close[i] > open[i]

isBearish(i) =>
    close[i] < open[i]

candle_highs = array.new_float(lookbackInput)
candle_lows = array.new_float(lookbackInput)
candle_bull_bar_highs = array.new_float(lookbackInput)
candle_bull_bar_lows = array.new_float(lookbackInput)

var int index_highest_bull_count_from_left = na
var int index_highest_bull = na
var float value_highest_bull = na
var float value_low_of_highest_bull = na

var bool low_of_highest_bull_mode_activated = false
var bool high_of_lowest_bear_mode_activated = false

// Define the arrays to store bullish bars' highs and lows
float[] bullishBarsHighs = array.new_float(na)
float[] bullishBarsLows = array.new_float(na)
float[] bearishBarsHighs = array.new_float(na)
float[] bearishBarsLows = array.new_float(na)
float[] array_bar_highs = array.new_float(na)
float[] array_bar_lows = array.new_float(na)

// Method 3

float lowOfHighestBullishBar = na
float highOfLowestBearishhBar = na
int index_low_of_highest_bull_counted_from_left = na
int index_low_of_highest_bull_counted_from_right = na
int index_high_of_lowest_bear_counted_from_left = na
int index_low_of_lowest_bear_counted_from_right = na

bool draw_bullish_signal = false
bool draw_bearish_signal = false

if array.size(array_bar_highs) > lookbackInput
    array.shift(array_bar_highs)
    array.shift(array_bar_lows)

for index = lookbackInput - 1 to 0 by 1
    array.push(array_bar_highs, high[index])
    array.push(array_bar_lows, low[index])
    
    // ------------ find bearish scenario ------------

    // put only bullish bars in the array, use na for bearish ones
    if isBullish(index)
        array.push(bullishBarsHighs, high[index])
        array.push(bullishBarsLows, low[index])
    else
        array.push(bullishBarsHighs, na)
        array.push(bullishBarsLows, na)

    // log.info("bullishBarsHighs array:"+ str.tostring(bullishBarsHighs))

    // Find the index of the highest bullish bar
    index_low_of_highest_bull_counted_from_left := array.indexof(array_bar_highs,array.max(bullishBarsHighs))
    index_low_of_highest_bull_counted_from_right := lookbackInput - index_low_of_highest_bull_counted_from_left - 1
    
    // log.info("index " + str.tostring(index) + " array.max(bullishBarsHighs) "+ str.tostring(bullishBarsHighs)+ " index_low_of_highest_bull_counted_from_left " + str.tostring(index_low_of_highest_bull_counted_from_left))

    if index_low_of_highest_bull_counted_from_left == -1
        index_low_of_highest_bull_counted_from_left := 0
        log.error("setting index " + str.tostring(index) + " array.max(bullishBarsHighs) "+ str.tostring(bullishBarsHighs)+ " index_low_of_highest_bull_counted_from_left to " + str.tostring(index_low_of_highest_bull_counted_from_left))

    // log.info("index " + str.tostring(index))
    // log.info("array_bar_highs "+str.tostring(array_bar_highs))
    // log.info("bullishBarsHighs " + str.tostring(bullishBarsHighs))
    // log.info("array.max(bullishBarsHighs) " + str.tostring(array.max(bullishBarsHighs)))
    // log.info("index_low_of_highest_bull_counted_from_left " + str.tostring(index_low_of_highest_bull_counted_from_left))
    // log.info("index_low_of_highest_bull_counted_from_right " + str.tostring(index_low_of_highest_bull_counted_from_right))

    // ------------ find bullish scenario ------------

    // put only bearish bars in the array, use na for bullish ones
    if isBearish(index)
        array.push(bearishBarsHighs, high[index])
        array.push(bearishBarsLows, low[index])
    else
        array.push(bearishBarsHighs, na)
        array.push(bearishBarsLows, na)

    // Find the index of the lowest bearish bar
    index_high_of_lowest_bear_counted_from_left := array.indexof(array_bar_lows,array.min(bearishBarsLows))
    index_low_of_lowest_bear_counted_from_right := lookbackInput - index_high_of_lowest_bear_counted_from_left - 1
    
    if index_high_of_lowest_bear_counted_from_left == -1
        index_high_of_lowest_bear_counted_from_left := 0
        // log.error("setting index " + str.tostring(index) + " array.max(bullishBarsHighs) "+ str.tostring(bullishBarsHighs)+ " index_low_of_highest_bull_counted_from_left to " + str.tostring(index_low_of_highest_bull_counted_from_left))

if bar_index >= lookbackInput
    // log.info("index from left:" + str.tostring(index_low_of_highest_bull_counted_from_left) + " bullishBarsLows "+ str.tostring(bullishBarsLows))
    
    // ------------ find bearish scenario ------------

    // Retrieve the low of the highest bullish bar
    lowOfHighestBullishBar := array.get(bullishBarsLows, index_low_of_highest_bull_counted_from_left)

    // label.new(bar_index, na, str.tostring(bar_index) + "\n•= " + str.tostring(array.max(bullishBarsHighs), format.mintick) + "\n"+str.tostring(bar_index) + "\n🠇", yloc = yloc.belowbar, style = label.style_none, textcolor = color.yellow, size = size.normal)
    // log.info("bar_index close " + str.tostring(bar_index) + " "+str.tostring(close))
    // log.info("index_low_of_highest_bull_counted_from_right " + str.tostring(index_low_of_highest_bull_counted_from_right))
    // log.info("lowOfHighestBullishBar " + str.tostring(lowOfHighestBullishBar))

    // Plot a down arrow once a bar closes below the low of the highest bullish bar, the subsequent signals will be ignored until one bar closes above its current threshold.
    if close < lowOfHighestBullishBar and not low_of_highest_bull_mode_activated
        low_of_highest_bull_mode_activated := true
        // label.new(bar_index, high[index_low_of_highest_bull_counted_from_right], yloc = yloc.abovebar, color = color.blue, size = size.tiny)
        draw_bearish_signal := true
    
    if close > lowOfHighestBullishBar
        low_of_highest_bull_mode_activated := false
    
    // ------------ find bullish scenario ------------
    // Retrieve the high of the lowest bearish bar
    highOfLowestBearishhBar := array.get(bearishBarsHighs, index_high_of_lowest_bear_counted_from_left)

    // Plot an up arrow once a bar closes above the high of the lowest bearish bar, the subsequent signals will be ignored until one bar closes below its current threshold.
    if close > highOfLowestBearishhBar and not high_of_lowest_bear_mode_activated
        high_of_lowest_bear_mode_activated := true
        // label.new(bar_index, low[index_high_of_lowest_bear_counted_from_left], yloc = yloc.belowbar, style = label.style_label_up, color = color.green, size = size.tiny)
        draw_bullish_signal := true
    
    if close < highOfLowestBearishhBar
        high_of_lowest_bear_mode_activated := false
        
// Plot the low of the highest bullish bar
plot(display_low_of_highest_bull_bar?lowOfHighestBullishBar:na, "Low of Highest Bullish Bar", color=color.red, style = plot.style_stepline)

// Plot the high of the lowest bearish bar
plot(display_high_of_lowest_bear_bar?highOfLowestBearishhBar:na, "High of Lowest Bearish Bar", color=color.green, style = plot.style_stepline)

// Buy and Sell signals
sellSignal = ta.crossunder(close, highOfLowestBearishhBar) 
buySignal = ta.crossover(close, lowOfHighestBullishBar)

// Plotting Buy and Sell signals
plotshape(series=draw_bullish_signal, location=location.belowbar, color=color.green, style=shape.triangleup, text="FF", title="FF Buy Signal")
plotshape(series=draw_bearish_signal, location=location.abovebar, color=color.red, style=shape.triangledown, text="FF", title="FF Sell Signal")

// End of Method 3

// Highlight chart background between specific hours
display_hours_highlight = input(false, "Display background colours for specific hours")
display_bgcolor = (timeframe.isintraday and display_hours_highlight)

t_highlight = time(timeframe.period, "1000-1300,1600-2000,2400-0700:23456", "Europe/London")
bgcolor((not na(t_highlight) and display_bgcolor) ? color.new(color.silver, 90) : na, title = "Highlight Quiet Hours")

// Bollinger Bands
var group_bb = "Bollinger Bands"
display_bb = input.bool(true, "Display Bollinger Bands", "BB", group = group_bb)
[bb_middle, bb_upper, bb_lower] = ta.bb(close, 20, 2)
plot(display_bb? bb_lower : na, "BB Lower", color = color.new(color.blue, 0), linewidth = 1, style = plot.style_stepline)
plot(display_bb? bb_upper : na, "BB Upper", color = color.new(color.blue, 0), linewidth = 1, style = plot.style_stepline)
plot(display_bb? bb_middle : na, "BB Middle", color = color.new(color.blue, 0), linewidth = 1, style = plot.style_stepline, display = display.none)

Overview

Flip Flop locates key levels, including the low of the highest bullish candle and the high of the lowest bearish candle within the window. The script also includes optional features to plot Bollinger Bands and highlight specific hours on the chart. It draws directly on the price chart to help identify dynamic support and resistance levels driven by recent candlestick extremes.

Details

Published by

harryguiacorn on GitHub

Code credit

FxCloudTrader, as written in the script's header

Type

Indicator, Pine Script v5

Draws

On the price chart

Category

Support & resistance, Volatility & bands, Candlestick patterns

Markets

Any symbol

Timeframes

Any timeframe

Risk Notes

No repainting, lookahead or stacked entries were found in its code or README. That says nothing about how well it works: test it first.

Topics

bollingerbollinger-bandbollinger-bandsichimokuichimoku-cloudichimoku-indicatorpinepinescriptpinescript-guidespinescript-indicators

Settings

The inputs you can change from the gear icon on the chart. Defaults are the author's.

SettingTypeDefaultVariable
Lookback in barsint20lookbackInput
display_low_of_highest_bull_barbooltruedisplay_low_of_highest_bull_bar
display_high_of_lowest_bear_barbooltruedisplay_high_of_lowest_bear_bar
Display background colours for specific hoursboolfalsedisplay_hours_highlight
Display Bollinger Bandsbooltruedisplay_bb
Third-party code. ForexR did not write, test or endorse this script, and the summary above was generated automatically from its code and README. Indicators describe the past, and a strategy's backtest can look better than live trading, especially when a script repaints. Check it in the Strategy Tester and on a demo account before you rely on it.

Similar Pine Scripts

Signal Quality Engine [WavesUnchained] is a range-fade indicator that identifies exhaustion at range extremes and signals potential reversals. It applies an ADX and EMA slope regime gate to stand down during strong trends. Using distance, structure, and moment

Indicator v6 Mean reversionSupport & resistance
Updated yesterday · MIT GitHub repository of Signal Quality Engine [WavesUnchained]

ICT Liquidity Void Fill

by ArunKBhaskar
575 stars

This overlay indicator marks ICT liquidity void fills on the price chart and can show long and short signals. It places a Fibonacci level inside a displacement candle, defaulting to the midpoint, and draws lines in a chosen style. Optional filters limit the fi

Indicator v6 SMC / ICT / price actionSupport & resistance
Updated 1 year ago · MPL-2.0 GitHub repository of ICT Liquidity Void Fill

[RS]Donchian Fans

by ricardosantos79
261 stars

This indicator plots Donchian Channel boundary lines along with dynamic fan projections directly on the price chart. It calculates the highest high, lowest low, and median price over a customizable lookback period. Whenever price establishes a new channel high

Indicator v4 Support & resistanceTrend
Updated 4 years ago · None stated GitHub repository of [RS]Donchian Fans

Snag - VWAP

by dearvn
257 stars

This indicator plots a custom Anchored Volume-Weighted Average Price (VWAP) directly on the price chart along with optional standard deviation bands. Users can anchor the VWAP to standard time periods like sessions, weeks, or months, or to corporate events suc

Indicator v5 Moving averagesVolatility & bands Repaints
Updated 6 weeks ago · None stated GitHub repository of Snag - VWAP

Dynamic Linear Regression

by TradersPost
218 stars

Dynamic Linear Regression calculates and plots linear regression trendlines and standard deviation channels directly on the price chart over a user-selected time period. Traders can configure static channels locked at the end time, dynamic channels that contin

Indicator v6 TrendSupport & resistance
Updated 3 months ago · None stated GitHub repository of Dynamic Linear Regression

More indicators

Trade Your Charts With a Regulated Broker

Compare brokers that connect to TradingView, with spreads, minimum deposits and leverage side by side.

Compare brokers