Strategy · Pine Script v5 · On the chart

Combined Strategy - Supply/Demand + AO Divergence

by GeneralTradingSarl

This strategy combines fractal-based supply and demand order blocks with Awesome Oscillator divergence detection.

View on GitHub

GitHub stars3on the repository
Pine versionv5runs as is
Lines of code356
Settings9inputs
LicenceNone statedfile: MPL-2.0
Last update5 weeks ago18 Sep 2026

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 strategy, select all of the template text and paste. Press Save and give it a name.
  4. 4Add it to the chartPress Add to chart. The trades and results appear in the Strategy Tester tab; adjust the settings with the gear icon.

Source Code

356 lines of Pine Script v5 from 60%Profitable Strategy.txt, published under MPL-2.0 (file header). Keep the author's credit and licence lines when you reuse it.

60%Profitable Strategy.txt
// This Pine Script® code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// Combined Strategy: Supply/Demand Order Blocks + Awesome Oscillator Divergence

//@version=5
strategy('Combined Strategy - Supply/Demand + AO Divergence', overlay=true, default_qty_type=strategy.percent_of_equity, default_qty_value=10)

// =================================
// INDICATOR 1: SUPPLY AND DEMAND ORDER BLOCKS
// =================================

changeColor = input(false, title='Change Box Colors?')
breakType = input.string('Wick+Body', title='Fractal Break Type:', options=['Wick+Body', 'Body'])
n = input.int(title='Periods', defval=9, minval=2)

transGreenClr = input.color(color.new(#00fe08, 80), title='Demand Bg:', inline='a_1')
greenClr = input.color(color.new(#00ff08, 0), title='Border:', inline='a_1')

transRedClr = input.color(color.new(#ff0000, 80), title='Supply Bg:', inline='b_1')
redClr = input.color(color.new(#ff0000, 0), title='Border:', inline='b_1')

//Fractals{
// UpFractal
bool upflagDownFrontier = true
bool upflagUpFrontier0 = true
bool upflagUpFrontier1 = true
bool upflagUpFrontier2 = true
bool upflagUpFrontier3 = true
bool upflagUpFrontier4 = true

for i = 1 to n by 1
    upflagDownFrontier := upflagDownFrontier and high[n - i] < high[n]
    upflagUpFrontier0 := upflagUpFrontier0 and high[n + i] < high[n]
    upflagUpFrontier1 := upflagUpFrontier1 and high[n + 1] <= high[n] and high[n + i + 1] < high[n]
    upflagUpFrontier2 := upflagUpFrontier2 and high[n + 1] <= high[n] and high[n + 2] <= high[n] and high[n + i + 2] < high[n]
    upflagUpFrontier3 := upflagUpFrontier3 and high[n + 1] <= high[n] and high[n + 2] <= high[n] and high[n + 3] <= high[n] and high[n + i + 3] < high[n]
    upflagUpFrontier4 := upflagUpFrontier4 and high[n + 1] <= high[n] and high[n + 2] <= high[n] and high[n + 3] <= high[n] and high[n + 4] <= high[n] and high[n + i + 4] < high[n]
    upflagUpFrontier4
flagUpFrontier = upflagUpFrontier0 or upflagUpFrontier1 or upflagUpFrontier2 or upflagUpFrontier3 or upflagUpFrontier4

upFractal = upflagDownFrontier and flagUpFrontier

//DownFractal
bool downflagDownFrontier = true
bool downflagUpFrontier0 = true
bool downflagUpFrontier1 = true
bool downflagUpFrontier2 = true
bool downflagUpFrontier3 = true
bool downflagUpFrontier4 = true

for i = 1 to n by 1
    downflagDownFrontier := downflagDownFrontier and low[n - i] > low[n]
    downflagUpFrontier0 := downflagUpFrontier0 and low[n + i] > low[n]
    downflagUpFrontier1 := downflagUpFrontier1 and low[n + 1] >= low[n] and low[n + i + 1] > low[n]
    downflagUpFrontier2 := downflagUpFrontier2 and low[n + 1] >= low[n] and low[n + 2] >= low[n] and low[n + i + 2] > low[n]
    downflagUpFrontier3 := downflagUpFrontier3 and low[n + 1] >= low[n] and low[n + 2] >= low[n] and low[n + 3] >= low[n] and low[n + i + 3] > low[n]
    downflagUpFrontier4 := downflagUpFrontier4 and low[n + 1] >= low[n] and low[n + 2] >= low[n] and low[n + 3] >= low[n] and low[n + 4] >= low[n] and low[n + i + 4] > low[n]
    downflagUpFrontier4
flagDownFrontier = downflagUpFrontier0 or downflagUpFrontier1 or downflagUpFrontier2 or downflagUpFrontier3 or downflagUpFrontier4

downFractal = downflagDownFrontier and flagDownFrontier
//}

var float topValue = na
var float bottomValue = na
var int lastRedIndex = na
var float lastRedLow = na
var float lastRedHigh = na
var int lastGreenIndex = na
var float lastGreenLow = na
var float lastGreenHigh = na

var line topLine = na
var line bottomLine = na
var box demandBox = na
var box supplyBox = na

var topBreakBlock = false
var bottomBreakBlock = false
var isLongBreak = false
var isShortBreak = false

topBreakCheckSource = breakType == 'Wick+Body' ? high : close
bottomBreakCheckSource = breakType == 'Wick+Body' ? low : close

//Last red check
if close < open
    lastRedIndex := bar_index
    lastRedLow := low
    lastRedHigh := high
    lastRedHigh

//Last green check
if close > open
    lastGreenIndex := bar_index
    lastGreenLow := low
    lastGreenHigh := high
    lastGreenHigh

// Variables to track demand/supply zone creation
var bool newDemandZone = false
var bool newSupplyZone = false

//Top break
if ta.crossover(topBreakCheckSource, topValue) and topBreakBlock == false
    topBreakBlock := true
    isLongBreak := true
    line.set_x2(topLine, bar_index)
    demandBox := box.new(lastRedIndex - 1, lastRedHigh, lastRedIndex + 1, lastRedLow, bgcolor=transGreenClr, border_color=greenClr)
    newDemandZone := true

//Bottom break
if ta.crossunder(bottomBreakCheckSource, bottomValue) and bottomBreakBlock == false
    bottomBreakBlock := true
    isShortBreak := true
    line.set_x2(bottomLine, bar_index)
    supplyBox := box.new(lastGreenIndex - 1, lastGreenHigh, lastGreenIndex + 1, lastGreenLow, bgcolor=transRedClr, border_color=redClr)
    newSupplyZone := true

//New up fractal
if upFractal
    topBreakBlock := false
    isLongBreak := false
    topValue := high[n]
    topLine := line.new(bar_index[n], topValue, bar_index, topValue, color=color.rgb(208, 255, 0), style=line.style_dotted, width=2)
    if isLongBreak[1] == false
        line.delete(topLine[1])

//New down fractal
if downFractal
    bottomBreakBlock := false
    isShortBreak := false
    bottomValue := low[n]
    bottomLine := line.new(bar_index[n], bottomValue, bar_index, bottomValue, color=color.rgb(212, 255, 0), style=line.style_dotted, width=2)
    if isShortBreak[1] == false
        line.delete(bottomLine[1])

//Box state update
activeBoxes = box.all
if array.size(activeBoxes) > 0 and changeColor
    for i = 0 to array.size(activeBoxes) - 1 by 1
        bVal = box.get_bottom(array.get(activeBoxes, i))
        tVal = box.get_top(array.get(activeBoxes, i))
        if close < bVal
            box.set_bgcolor(array.get(activeBoxes, i), transRedClr)
            box.set_border_color(array.get(activeBoxes, i), redClr)
        if close > tVal
            box.set_bgcolor(array.get(activeBoxes, i), transGreenClr)
            box.set_border_color(array.get(activeBoxes, i), greenClr)

//PLOTS for Supply/Demand
plotshape(downFractal, style=shape.triangleup, location=location.belowbar, offset=-n, color=color.new(#b3ff00, 0), size=size.tiny)
plotshape(upFractal, style=shape.triangledown, location=location.abovebar, offset=-n, color=color.new(#d9ff00, 0), size=size.tiny)

// =================================
// INDICATOR 2: AWESOME OSCILLATOR WITH DIVERGENCE
// =================================

// Calcolo dell'AO
ao = ta.sma(hl2, 5) - ta.sma(hl2, 34)
diff = ao - ao[1]

// Cambio colore per gli alert
changeToGreen = ta.crossover(diff, 0)
changeToRed = ta.crossunder(diff, 0)

// Configurazione Divergenza
lookbackRight = 5
lookbackLeft = 5
rangeUpper = 60
rangeLower = 5
bearColor = color.red
bullColor = color.green
textColor = color.white
noneColor = color.new(color.white, 100)

_inRange(bool cond) =>
    bars = ta.barssince(cond)
    rangeLower <= bars and bars <= rangeUpper

plFound = false
phFound = false

bullCond = false
bearCond = false

aoLBR = ao[lookbackRight]

if true
    // Divergenza rialzista regolare (Regular Bullish)
    plFound := not na(ta.pivotlow(ao, lookbackLeft, lookbackRight))
    aoHL = aoLBR > ta.valuewhen(plFound, aoLBR, 1) and _inRange(plFound[1])
    lowLBR = low[lookbackRight]
    priceLL = lowLBR < ta.valuewhen(plFound, lowLBR, 1)
    bullCond := priceLL and aoHL and plFound

    // Divergenza ribassista regolare (Regular Bearish)
    phFound := not na(ta.pivothigh(ao, lookbackLeft, lookbackRight))
    aoLH = aoLBR < ta.valuewhen(phFound, aoLBR, 1) and _inRange(phFound[1])
    highLBR = high[lookbackRight]
    priceHH = highLBR > ta.valuewhen(phFound, highLBR, 1)
    bearCond := priceHH and aoLH and phFound

// =================================
// ADDITIONAL TRADING LOGIC
// =================================


// =================================
// ADDITIONAL TRADING LOGIC
// =================================

// Risk Management Settings
riskPercent = input.float(2.0, title="Risk Percentage", minval=0.1, maxval=10.0) / 100
riskRewardRatio = input.float(2.5, title="Risk:Reward Ratio", minval=1.0, maxval=10.0)

// Trading State Variables
var int tradingState = 0  // 0=waiting for divergence, 1=waiting for fractal break, 2=waiting for pullback
var bool waitingForBullishBreak = false
var bool waitingForBearishBreak = false
var float lastHighFractal = na
var float lastLowFractal = na
var box targetDemandBox = na
var box targetSupplyBox = na
var bool bullishDivergenceDetected = false
var bool bearishDivergenceDetected = false

// Store the last fractals when they occur
if upFractal
    lastHighFractal := high[n]

if downFractal
    lastLowFractal := low[n]

// Step 1: Detect Divergence Signals (only once per signal)
if bullCond and not bullCond[1] and tradingState == 0
    bullishDivergenceDetected := true
    bearishDivergenceDetected := false
    waitingForBullishBreak := true
    waitingForBearishBreak := false
    tradingState := 1

if bearCond and not bearCond[1] and tradingState == 0
    bearishDivergenceDetected := true
    bullishDivergenceDetected := false
    waitingForBearishBreak := true
    waitingForBullishBreak := false
    tradingState := 1

// Step 2: Check for Fractal Breaks (Body only)
var bool highFractalBroken = false
var bool lowFractalBroken = false

if waitingForBullishBreak and not na(lastHighFractal)
    if close > lastHighFractal and not highFractalBroken
        highFractalBroken := true
        targetDemandBox := demandBox  // Store the current demand box
        tradingState := 2

if waitingForBearishBreak and not na(lastLowFractal)
    if close < lastLowFractal and not lowFractalBroken
        lowFractalBroken := true
        targetSupplyBox := supplyBox  // Store the current supply box
        tradingState := 2

// Step 3: Check for Pullback to Order Block
var bool readyForLongEntry = false
var bool readyForShortEntry = false

if tradingState == 2 and highFractalBroken and not na(targetDemandBox)
    boxTop = box.get_top(targetDemandBox)
    boxBottom = box.get_bottom(targetDemandBox)
    if low <= boxTop and high >= boxBottom  // Price touching the demand zone
        readyForLongEntry := true

if tradingState == 2 and lowFractalBroken and not na(targetSupplyBox)
    boxTop = box.get_top(targetSupplyBox)
    boxBottom = box.get_bottom(targetSupplyBox)
    if low <= boxTop and high >= boxBottom  // Price touching the supply zone
        readyForShortEntry := true

// Position Sizing Calculation
accountBalance = strategy.equity
riskAmount = accountBalance * riskPercent

// Step 4: Execute Trades
if readyForLongEntry and strategy.position_size == 0
    boxTop = box.get_top(targetDemandBox)
    boxBottom = box.get_bottom(targetDemandBox)
    stopLoss = boxBottom
    orderBlockSize = boxTop - boxBottom
    takeProfit = close + (orderBlockSize * riskRewardRatio)
    
    // Calculate position size based on risk
    stopDistance = close - stopLoss
    if stopDistance > 0
        positionSize = riskAmount / stopDistance
        strategy.entry("Long", strategy.long, qty=positionSize)
        strategy.exit("Long Exit", "Long", stop=stopLoss, limit=takeProfit)
    
    // Reset states
    readyForLongEntry := false
    bullishDivergenceDetected := false
    waitingForBullishBreak := false
    highFractalBroken := false
    tradingState := 0

if readyForShortEntry and strategy.position_size == 0
    boxTop = box.get_top(targetSupplyBox)
    boxBottom = box.get_bottom(targetSupplyBox)
    stopLoss = boxTop
    orderBlockSize = boxTop - boxBottom
    takeProfit = close - (orderBlockSize * riskRewardRatio)
    
    // Calculate position size based on risk
    stopDistance = stopLoss - close
    if stopDistance > 0
        positionSize = riskAmount / stopDistance
        strategy.entry("Short", strategy.short, qty=positionSize)
        strategy.exit("Short Exit", "Short", stop=stopLoss, limit=takeProfit)
    
    // Reset states
    readyForShortEntry := false
    bearishDivergenceDetected := false
    waitingForBearishBreak := false
    lowFractalBroken := false
    tradingState := 0

// Visual Signals for Debugging (only show once per signal)
plotshape(bullCond and not bullCond[1], title="Bullish Divergence", location=location.belowbar, color=color.lime, style=shape.triangleup, text="BULL DIV")
plotshape(bearCond and not bearCond[1], title="Bearish Divergence", location=location.abovebar, color=color.red, style=shape.triangledown, text="BEAR DIV")

// Trade Entry Markers
var bool longEntryExecuted = false
var bool shortEntryExecuted = false

if readyForLongEntry and strategy.position_size == 0
    longEntryExecuted := true

if readyForShortEntry and strategy.position_size == 0
    shortEntryExecuted := true

plotshape(longEntryExecuted, title="Long Entry", location=location.belowbar, color=color.green, style=shape.labelup, text="LONG", size=size.normal)
plotshape(shortEntryExecuted, title="Short Entry", location=location.abovebar, color=color.red, style=shape.labeldown, text="SHORT", size=size.normal)

// Reset entry flags after plotting
longEntryExecuted := false
shortEntryExecuted := false

// Remove the old simple strategy logic (replace the existing longCondition/shortCondition section)
// Comment out or remove these lines from your original code:
// longCondition = bullCond and newDemandZone
// shortCondition = bearCond and newSupplyZone
// if longCondition
//     strategy.entry("Long", strategy.long)
// if shortCondition
//     strategy.entry("Short", strategy.short)

Overview

Combined Strategy - Supply/Demand + AO Divergence generates long signals when price interacts with a demand zone alongside a confirmed bullish divergence, and short signals at supply zones with bearish divergence. Risk management uses position sizing calculated from a customizable risk percentage per trade, placing stop-loss orders around the order block boundaries and take-profit targets based on a configurable risk-to-reward ratio. Zones are drawn directly on the price chart.

Details

Published by

GeneralTradingSarl on GitHub

Type

Strategy, Pine Script v5

Draws

On the price chart

Category

SMC / ICT / price action, Oscillators & momentum, Support & resistance, Divergence

Markets

Forex

Timeframes

M15-H1, H4 and above

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

pinescripttrading-strategytradingview

Settings

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

SettingTypeDefaultVariable
Change Box Colors?boolfalsechangeColor
Fractal Break Type:stringWick+BodybreakType
Periodsint9n
Demand Bg:colorcolor.new(#00fe08, 80)transGreenClr
Border:colorcolor.new(#00ff08, 0)greenClr
Supply Bg:colorcolor.new(#ff0000, 80)transRedClr
Border:colorcolor.new(#ff0000, 0)redClr
Risk Percentagefloat2.0riskPercent
Risk:Reward Ratiofloat2.5riskRewardRatio
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

This strategy identifies reversal opportunities based on liquidity sweeps and multi-gate confluence scoring. It evaluates setups using mandatory conditions such as swing sweeps, body and ATR filters, and dual EMA higher-timeframe trend alignment, alongside opt

Strategy v6 SMC / ICT / price actionTrend
Updated yesterday · MIT GitHub repository of Reversal Engine Score [WavesUnchained] Strategy

ScarAlgo v1

by g-moe
3 stars

ScarAlgo v1 is a trend-following and market-structure strategy plotted directly on the main price chart. It triggers entries using an ATR-based trailing envelope filtered by a configurable multi-timeframe moving average, while employing a WaveTrend momentum os

Strategy v5 TrendSMC / ICT / price action
Updated 5 months ago · None stated GitHub repository of ScarAlgo v1
1 stars

This strategy plots market structure on the price chart from confirmed swing highs and lows and flags breaks of those levels. Breaks can use the wick or the close, and structure logic can stay standard or include sweeps. ChoCH mode selects Ping, Verify, or bot

Strategy v6 SMC / ICT / price actionSupport & resistance
Updated 2 days ago · None stated GitHub repository of CHOCH-Strategy (Structure Only)

Stratégie Vumanchu-SMC

by matlaenousse
1 stars

Stratégie Vumanchu-SMC combines Smart Money Concepts with Vumanchu momentum signals to execute trades directly on the price chart. It detects market structure transitions such as breaks of structure and changes of character, while mapping order blocks and fair

Strategy v5 SMC / ICT / price actionOscillators & momentum
Updated 10 months ago · None stated GitHub repository of Stratégie Vumanchu-SMC
1 stars

This strategy detects liquidity sweeps and break of structure events using SMC concepts. It plots BOS labels, sweep markers, and matrix floor ceiling lines on the price chart. The SMC structure sensitivity setting adjusts lookback for scalping, standard, or sw

Strategy v6 SMC / ICT / price actionBreakout
Updated 2 months ago · None stated GitHub repository of TN SMC Matrix Sovereign v6
1 stars

The strategy detects smoothed RSI divergences on the price chart. It calculates smoothed RSI as the EMA of 3 applied to the 14-period RSI of close. Bullish divergence signals when smoothed RSI is below 40, with smoothed RSI rising over five bars while close ex

Strategy v6 Oscillators & momentumDivergence
Updated 5 days ago · Apache-2.0 GitHub repository of VCP probe 03 - rsi smooth divergence

More strategys

Trade Your Charts With a Regulated Broker

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

Compare brokers