TW code translation ( Order flow imbalance oscillator)

Viewing 2 posts - 1 through 2 (of 2 total)
  • Author
    Posts
  • #265261 quote
    Msport71Msport71
    Participant
    Senior

    Hi all,

    could you please translate the following oscillator that seems quite interesting.

    Thanks and regards.



    https://www.tradingview.com/script/6dIWwfow-Order-Flow-Imbalance-Oscillator-StrikePriceLabs/

    // This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/ 

    // © StrikePriceLabs 


    //@version=6 

    indicator(“Order Flow Imbalance Oscillator [StrikePriceLabs]”, overlay = false) 


    // ─── INPUTS ───────────────────────────────────────────────────────────────────── 

    col_supply = input.color(color.orange, “Supply”) 

    col_demand = input.color(#009fd4, “Demand”) 


    var vol    = array.new<float>() 

    var BullDelta = array.new<float>() 

    var BearDelta = array.new<float>() 


    // Zone geometry arrays instead of boxes 

    var bearTop = array.new<float>()  // supply zone upper price 

    var bearBot = array.new<float>()  // supply zone lower price 

    var bullTop = array.new<float>()  // demand zone upper price 

    var bullBot = array.new<float>()  // demand zone lower price 


    var count_bear = 0 

    var count_bull = 0 


    // New series for historical totals 

    var float totalSupply = na 

    var float totalDemand = na 


    // ─── CALCULATIONS ────────────────────────────────────────────────────────────── 

    vol.push(volume) 

    if vol.size() > 1000 

      vol.shift() 


    extra_vol  = volume > vol.avg() 

    atr     = ta.atr(200) * 2 

    bear_candle = close < open 

    bull_candle = close > open 


    // ── Bearish zones (Supply) ───────────────────────────────────────────────────── 

    if bear_candle and bear_candle[1] and bear_candle[2] and (extra_vol or extra_vol[1] or extra_vol[2]) and count_bear == 0 

      delta = 0.0 

      for i = 0 to 5 

        if bull_candle[i] 

          count_bear := 1 

          array.push(bearTop, low[i] + atr) 

          array.push(bearBot, low[i]) 

          array.push(BearDelta, delta) 

          break 

        delta += bear_candle[i] ? -volume[i] : volume[i] 


    if count_bear >= 1 

      count_bear += 1 

    if count_bear >= 15 

      count_bear := 0 


    // ── Bullish zones (Demand) ───────────────────────────────────────────────────── 

    if bull_candle and bull_candle[1] and bull_candle[2] and (extra_vol or extra_vol[1] or extra_vol[2]) and count_bull == 0 

      delta = 0.0 

      for i = 0 to 5 

        if bear_candle[i] 

          count_bull := 1 

          array.push(bullTop, high[i]) 

          array.push(bullBot, high[i] – atr) 

          array.push(BullDelta, delta) 

          break 

        delta += bull_candle[i] ? volume[i] : -volume[i] 


    if count_bull >= 1 

      count_bull += 1 

    if count_bull >= 15 

      count_bull := 0 


    // ── Supply invalidation ─────────────────────────────────────────────────────── 

    s = 0 

    while s < bearTop.size() 

      top = array.get(bearTop, s) 

      bot = array.get(bearBot, s) 

      if close > top 

        array.remove(bearTop, s) 

        array.remove(bearBot, s) 

        array.remove(BearDelta, s) 

      else 

        s += 1 


    // ── Demand invalidation ─────────────────────────────────────────────────────── 

    d = 0 

    while d < array.size(bullTop) 

      top = array.get(bullTop, d) 

      bot = array.get(bullBot, d) 

      if close < bot 

        array.remove(bullTop, d) 

        array.remove(bullBot, d) 

        array.remove(BullDelta, d) 

      else 

        d += 1 


    // ── Manage overlapping Supply zones ─────────────────────────────────────────── 

    if array.size(bearTop) > 0 

      i = 0 

      while i < array.size(bearTop) 

        top = array.get(bearTop, i) 

        bot = array.get(bearBot, i) 

        j = 0 

        removed = false 

        while j < array.size(bearTop) 

          if i != j 

            top1 = array.get(bearTop, j) 

            bot1 = array.get(bearBot, j) 

            if top1 < top and top1 > bot 

              array.remove(bearTop, i) 

              array.remove(bearBot, i) 

              array.remove(BearDelta, i) 

              removed := true 

              break 

          j += 1 

        if not removed 

          i += 1 


      // Cap Supply zones 

      while array.size(bearTop) > 5 

        array.shift(bearTop) 

        array.shift(bearBot) 

        array.shift(BearDelta) 


    // ── Manage overlapping Demand zones ─────────────────────────────────────────── 

    if array.size(bullTop) > 0 

      i = 0 

      while i < array.size(bullTop) 

        top = array.get(bullTop, i) 

        bot = array.get(bullBot, i) 

        j = 0 

        removed = false 

        while j < array.size(bullTop) 

          if i != j 

            top1 = array.get(bullTop, j) 

            bot1 = array.get(bullBot, j) 

            if bot1 < top and bot1 > bot 

              array.remove(bullTop, i) 

              array.remove(bullBot, i) 

              array.remove(BullDelta, i) 

              removed := true 

              break 

          j += 1 

        if not removed 

          i += 1 


      // Cap Demand zones 

      while array.size(bullTop) > 5 

        array.shift(bullTop) 

        array.shift(bullBot) 

        array.shift(BullDelta) 


    // ─── Historical totals (EXPANDED with full zone details in PineLogs) ─────────────────────── 

    float supplySum = 0.0 

    supplySize = array.size(BearDelta) 

    if supplySize > 0 

      log.info(“🔴 SUPPLY ZONES ({0} total):”, supplySize) 

      for idx = 0 to supplySize – 1 

        delta = array.get(BearDelta, idx) 

        top  = array.get(bearTop, idx) 

        bot  = array.get(bearBot, idx) 

        supplySum += math.abs(delta) 

        log.info(” #{0}: delta={1,number,#} top={2,number,#.####} bot={3,number,#.####}”, idx, delta, top, bot) 

    else 

      log.info(“🔴 SUPPLY ZONES: 0”) 


    float demandSum = 0.0 

    demandSize = array.size(BullDelta) 

    if demandSize > 0 

      log.info(“🟢 DEMAND ZONES ({0} total):”, demandSize) 

      for idx = 0 to demandSize – 1 

        delta = array.get(BullDelta, idx) 

        top  = array.get(bullTop, idx) 

        bot  = array.get(bullBot, idx) 

        demandSum += math.abs(delta) 

        log.info(” #{0}: delta={1,number,#} top={2,number,#.####} bot={3,number,#.####}”, idx, delta, top, bot) 

    else 

      log.info(“🟢 DEMAND ZONES: 0”) 


    log.info(“📊 FINAL TOTALS – Supply: {0,number,#} | Demand: {1,number,#} | Delta: {2,number,#}”, supplySum, demandSum, demandSum – supplySum) 


    totalSupply := supplySum 

    totalDemand := demandSum 



    // ─── NORMALIZED IMBALANCE OSCILLATOR (-100 to +100) ─────────────────────────── 

    denom = totalDemand + totalSupply 

    imbalanceNorm = denom != 0 ? (totalDemand – totalSupply) / denom * 100 : 0 


    plot( 

       imbalanceNorm, 

       title = “Order Flow Imbalance (-100 to +100)”, 

       style = plot.style_area, 

       color = imbalanceNorm >= 0 ? col_demand : col_supply 



    hline(0,  “Balance”, color = color.new(color.gray, 70)) 

    hline(50, “+50 Strong Demand”, color = color.new(col_demand, 50)) 

    hline(-50, “-50 Strong Supply”, color = color.new(col_supply, 50)) 


    Screenshot-2026-09-22-at-11-36-12-Order-Flow-Imbalance-Oscillator-StrikePriceLabs-—-Indicator-by-StrikePriceLabs-—-TradingView.png Screenshot-2026-09-22-at-11-36-12-Order-Flow-Imbalance-Oscillator-StrikePriceLabs-—-Indicator-by-StrikePriceLabs-—-TradingView.png
    #265266 quote
    Iván GonzálezIván González
    Moderator
    Legend

    here you have:

    //-------------------------------------//
    //PRC_Order Flow Imbalance Oscillator
    //version = 0
    //22.09.26
    //Iván González @ www.prorealcode.com
    //Author: StrikePriceLabs
    //Sharing ProRealTime knowledge
    //-------------------------------------//
    // Inputs
    //-------------------------------------//
    volLen   = 1000   // Lookback of the average volume used to flag a high volume bar
    atrLen   = 200    // ATR length that sets the height of a zone
    atrMult  = 2      // Zone height, in ATR units
    scanBack = 5      // How far back the impulse is scanned for its origin candle
    coolBars = 15     // Counter value that releases the block on a new zone (same side)
    zoneMax  = 5      // Live zones kept per side
    
    // Supply (orange) and demand (blue) colours
    supR = 255
    supG = 152
    supB = 0
    demR = 0
    demG = 159
    demB = 212
    
    //-------------------------------------//
    // Persistent state
    //-------------------------------------//
    ONCE nSup    = 0   // live supply zones
    ONCE nDem    = 0   // live demand zones
    ONCE cntBear = 0   // supply cooldown counter
    ONCE cntBull = 0   // demand cooldown counter
    ONCE supSum  = 0
    ONCE demSum  = 0
    
    //-------------------------------------//
    // Closed-bar inputs
    //-------------------------------------//
    avgVol = average[volLen](volume)
    atrRaw = averagetruerange[atrLen](close)
    
    atrV   = atrRaw[1] * atrMult
    warmUp = max(volLen, atrLen) + scanBack + 2
    
    IF barindex > warmUp THEN
       
       // Three consecutive candles of the same colour, at least one of them on
       // above average volume. On the closed-bar engine those are bars 1, 2 and 3.
       bearRun = 0
       IF close[1] < open[1] AND close[2] < open[2] AND close[3] < open[3] THEN
          bearRun = 1
       ENDIF
       
       bullRun = 0
       IF close[1] > open[1] AND close[2] > open[2] AND close[3] > open[3] THEN
          bullRun = 1
       ENDIF
       
       hotVol = 0
       IF volume[1] > avgVol[1] OR volume[2] > avgVol[2] OR volume[3] > avgVol[3] THEN
          hotVol = 1
       ENDIF
       
       //-------------------------------------//
       // Supply zone (bearish impulse)
       // The zone is anchored to the last bullish candle found within scanBack
       // bars: that candle is where the sellers took over. The delta adds up the
       // volume of every candle between the impulse and that origin.
       //-------------------------------------//
       IF bearRun = 1 AND hotVol = 1 AND cntBear = 0 THEN
          flowDelta = 0
          found     = 0
          origin    = 0
          
          FOR iSc = 0 TO scanBack DO
             IF found = 0 THEN
                IF close[iSc+1] > open[iSc+1] THEN
                   found  = 1
                   origin = iSc
                ELSIF close[iSc+1] < open[iSc+1] THEN
                   flowDelta = flowDelta - volume[iSc+1]
                ELSE
                   flowDelta = flowDelta + volume[iSc+1]
                ENDIF
             ENDIF
          NEXT
          
          // No bullish candle within the scan window means no origin, no zone.
          IF found = 1 THEN
             cntBear = 1
             nSup    = nSup + 1
             $spBot[nSup] = low[origin+1]
             $spTop[nSup] = low[origin+1] + atrV
             $spDlt[nSup] = flowDelta
          ENDIF
       ENDIF
       
       IF cntBear >= 1 THEN
          cntBear = cntBear + 1
       ENDIF
       IF cntBear >= coolBars THEN
          cntBear = 0
       ENDIF
       
       //-------------------------------------//
       // Demand zone (bullish impulse)
       //-------------------------------------//
       IF bullRun = 1 AND hotVol = 1 AND cntBull = 0 THEN
          flowDelta = 0
          found     = 0
          origin    = 0
          
          FOR iSc = 0 TO scanBack DO
             IF found = 0 THEN
                IF close[iSc+1] < open[iSc+1] THEN
                   found  = 1
                   origin = iSc
                ELSIF close[iSc+1] > open[iSc+1] THEN
                   flowDelta = flowDelta + volume[iSc+1]
                ELSE
                   flowDelta = flowDelta - volume[iSc+1]
                ENDIF
             ENDIF
          NEXT
          
          IF found = 1 THEN
             cntBull = 1
             nDem    = nDem + 1
             $dmTop[nDem] = high[origin+1]
             $dmBot[nDem] = high[origin+1] - atrV
             $dmDlt[nDem] = flowDelta
          ENDIF
       ENDIF
       
       IF cntBull >= 1 THEN
          cntBull = cntBull + 1
       ENDIF
       IF cntBull >= coolBars THEN
          cntBull = 0
       ENDIF
       
       //-------------------------------------//
       // Invalidation: a close above a supply top, or below a demand bottom,
       // removes the zone. Compacting in place is safe because the write index
       // never runs ahead of the read index.
       //-------------------------------------//
       kZ = 0
       FOR iZ = 1 TO nSup DO
          IF close[1] <= $spTop[iZ] THEN
             kZ = kZ + 1
             $spTop[kZ] = $spTop[iZ]
             $spBot[kZ] = $spBot[iZ]
             $spDlt[kZ] = $spDlt[iZ]
          ENDIF
       NEXT
       nSup = kZ
       
       kZ = 0
       FOR iZ = 1 TO nDem DO
          IF close[1] >= $dmBot[iZ] THEN
             kZ = kZ + 1
             $dmTop[kZ] = $dmTop[iZ]
             $dmBot[kZ] = $dmBot[iZ]
             $dmDlt[kZ] = $dmDlt[iZ]
          ENDIF
       NEXT
       nDem = kZ
       
       //-------------------------------------//
       // Overlapping supply zones: a zone is dropped when another zone has its
       // top inside it. The scan deletes in place and restarts the inner search
       // after every deletion. That order matters: a single marking pass over the
       // whole list is not the same thing, because it would also drop a zone whose
       // only witness has already been deleted. Keep the loop as it is.
       //-------------------------------------//
       iZ = 1
       WHILE iZ <= nSup DO
          gone = 0
          jZ   = 1
          WHILE jZ <= nSup AND gone = 0 DO
             IF jZ <> iZ AND $spTop[jZ] < $spTop[iZ] AND $spTop[jZ] > $spBot[iZ] THEN
                IF iZ < nSup THEN
                   FOR qZ = iZ TO nSup - 1 DO
                      $spTop[qZ] = $spTop[qZ+1]
                      $spBot[qZ] = $spBot[qZ+1]
                      $spDlt[qZ] = $spDlt[qZ+1]
                   NEXT
                ENDIF
                nSup = nSup - 1
                gone = 1
             ENDIF
             jZ = jZ + 1
          WEND
          IF gone = 0 THEN
             iZ = iZ + 1
          ENDIF
       WEND
       
       // Cap: the oldest zone is dropped first
       WHILE nSup > zoneMax DO
          FOR qZ = 1 TO nSup - 1 DO
             $spTop[qZ] = $spTop[qZ+1]
             $spBot[qZ] = $spBot[qZ+1]
             $spDlt[qZ] = $spDlt[qZ+1]
          NEXT
          nSup = nSup - 1
       WEND
       
       //-------------------------------------//
       // Overlapping demand zones: same idea, tested against the bottom edge
       //-------------------------------------//
       iZ = 1
       WHILE iZ <= nDem DO
          gone = 0
          jZ   = 1
          WHILE jZ <= nDem AND gone = 0 DO
             IF jZ <> iZ AND $dmBot[jZ] < $dmTop[iZ] AND $dmBot[jZ] > $dmBot[iZ] THEN
                IF iZ < nDem THEN
                   FOR qZ = iZ TO nDem - 1 DO
                      $dmTop[qZ] = $dmTop[qZ+1]
                      $dmBot[qZ] = $dmBot[qZ+1]
                      $dmDlt[qZ] = $dmDlt[qZ+1]
                   NEXT
                ENDIF
                nDem = nDem - 1
                gone = 1
             ENDIF
             jZ = jZ + 1
          WEND
          IF gone = 0 THEN
             iZ = iZ + 1
          ENDIF
       WEND
       
       WHILE nDem > zoneMax DO
          FOR qZ = 1 TO nDem - 1 DO
             $dmTop[qZ] = $dmTop[qZ+1]
             $dmBot[qZ] = $dmBot[qZ+1]
             $dmDlt[qZ] = $dmDlt[qZ+1]
          NEXT
          nDem = nDem - 1
       WEND
       
       //-------------------------------------//
       // Totals: the sign of the stored delta only records which side built the
       // zone, so the magnitudes are what is added up.
       //-------------------------------------//
       supSum = 0
       FOR iZ = 1 TO nSup DO
          supSum = supSum + abs($spDlt[iZ])
       NEXT
       
       demSum = 0
       FOR iZ = 1 TO nDem DO
          demSum = demSum + abs($dmDlt[iZ])
       NEXT
       
    ENDIF
    
    //-------------------------------------//
    // Normalised imbalance, -100 to +100
    //-------------------------------------//
    denom = demSum + supSum
    IF denom <> 0 THEN
       ofi = (demSum - supSum) / denom * 100
    ELSE
       ofi = 0
    ENDIF
    
    IF ofi >= 0 THEN
       cr = demR
       cg = demG
       cb = demB
    ELSE
       cr = supR
       cg = supG
       cb = supB
    ENDIF
    
    RETURN ofi COLOURED(cr, cg, cb) STYLE(histogram) AS "Order Flow Imbalance", 0 AS "Balance", 50 AS "+50 Strong Demand", -50 AS "-50 Strong Supply"
    


    TSLA-Diario-4.png TSLA-Diario-4.png
Viewing 2 posts - 1 through 2 (of 2 total)
  • You must be logged in to reply to this topic.
ProRealAI ProRealAI New

Stuck on this ProBuilder code?

Describe what this topic is trying to build, in plain English, and ProRealAI writes the ProRealTime™ indicator, screener or system for you.

Available in 7 languages
Try ProRealAI

TradingView to ProRealTime Translation Center

New Reply
Author
author-avatar
Msport71 @carlo-pasca Participant
Summary

This topic contains 1 reply,
has 2 voices, and was last updated by Iván GonzálezIván González
6 hours, 25 minutes ago.

Topic Details
Forum: TradingView to ProRealTime Translation Center Forum
Started: 09/22/2026
Status: Active
Attachments: 2 files
ProRealCode ProRealCode
Loading...