Smart Money Concept

Apa Itu Order Flow Dan Cara Guna Untuk Trading FCPO

Candle je tak cukup untuk tahu SIAPA yang sebenarnya mengawal pergerakan harga. Kenali footprint chart, delta, dan absorption — cara sahkan setup SMC anda dengan data order sebenar.

Kongsi:
Apa Itu Order Flow Dan Cara Guna Untuk Trading FCPO

Apa Itu Order Flow?

Order flow ialah analisis pergerakan sebenar order beli dan jual yang berlaku di pasaran secara masa nyata — bukan sekadar candle hijau/merah pada chart biasa, tapi SIAPA yang sebenarnya agresif membeli (order market yang hentam harga ask) berbanding SIAPA yang agresif menjual (order market yang hentam harga bid) pada setiap paras harga.

Kalau chart biasa (candlestick) bagi anda tahu HARGA bergerak ke mana, order flow bagi anda tahu KENAPA ia bergerak ke situ — siapa yang sebenarnya "menang" pertarungan antara pembeli dan penjual pada setiap tick harga.

Footprint Chart: Cara Baca Delta Setiap Candle

Cara paling biasa untuk visualkan order flow ialah melalui footprint chart — setiap candle dipecahkan kepada beberapa paras harga, dan pada setiap paras tu, anda nampak berapa banyak volume dijual (sell) berbanding dibeli (buy).

Delta ialah beza antara jumlah buy dan sell pada satu candle — Delta = Total Buy − Total Sell.

  • Delta positif bermaksud lebih banyak agresif membeli berlaku berbanding menjual — biasanya (tapi tak semestinya) diikuti candle hijau/naik.
  • Delta negatif bermaksud lebih banyak agresif menjual — biasanya diikuti candle merah/turun.

Cara Baca Footprint Chart

Dalam contoh di atas, panel BULLISH menunjukkan nombor "Beli" (hijau) lebih besar pada setiap paras harga berbanding "Jual" (merah) — jumlah Delta +130. Panel BEARISH pula terbalik — "Jual" mendominasi pada setiap paras, Delta -140.

Absorption — Bila Volume Besar Tapi Harga Tak Bergerak

Ini salah satu signal order flow paling bernilai: bila volume SANGAT besar berlaku pada satu paras harga, tapi harga tak bergerak banyak (atau langsung tak bergerak) — ini dipanggil absorption. Ia bermaksud ada pihak besar (institusi/big player) yang "menyerap" semua order lawan pada paras tu tanpa biarkan harga tembus.

Contoh: harga cuba turun ke satu zon, jualan agresif sangat tinggi (delta sangat negatif) — tapi harga cuma bergerak sikit sahaja sebelum berbalik naik. Ini tanda ada pembeli besar yang defend zon tu, menyerap semua jualan tanpa biar harga jatuh lagi. Ini selalunya berlaku betul-betul di zon Order Block atau Support yang sah.

Cara Guna Order Flow Untuk Sahkan Setup SMC

Order flow paling berguna bila digabungkan dengan konsep SMC yang anda dah tahu — bukan berdiri sendiri:

  • Order Block: Bila harga sampai ke zon Order Block, semak delta di situ. Delta yang kukuh ke arah yang anda jangka (contoh delta positif di Order Block bullish) menyokong setup anda — delta lemah atau bertentangan adalah amaran untuk tunggu dulu.
  • Fair Value Gap (FVG): Bila harga isi balik FVG, order flow tunjukkan sama ada "pengisian" tu datang dengan tekanan beli/jual yang kukuh, atau cuma pergerakan lembab tanpa keyakinan.
  • Liquidity Sweep: Absorption selepas satu sweep (harga tembus liquidity, terus berbalik) adalah salah satu signal order flow paling kukuh — ia mengesahkan yang sweep tu memang untuk "kutip" liquidity, bukan permulaan trend baru ke arah tu.

Baca Order Block Dalam SMC, Fair Value Gap (FVG), dan Liquidity dan Liquidity Sweep untuk faham asas setiap konsep ni sebelum gabungkan dengan order flow.

Nak belajar lebih mendalam?

Maverick Trader Advance (MTA) beri anda akses penuh — seminar, AI Trading Assistant, dan lagi.

Ketahui Lagi

Cuba Sendiri: Pine Script Percuma Di TradingView

Data order flow yang 100% tepat (bid/ask sebenar) memang perlukan platform berbayar — tapi anda masih boleh belajar KONSEP footprint, delta, dan value area secara PERCUMA di TradingView, menggunakan Pine Script yang kami sediakan di bawah.

Penting untuk faham dulu: Pine Script (macam semua bahasa skrip carta yang lain) tak ada akses kepada data bid/ask sebenar. Skrip di bawah adalah anggaran — ia ambil bar yang lebih kecil di dalam setiap candle carta anda (contohnya bar 1 minit di dalam candle 15 minit), dan kira setiap bar kecil tu sebagai "beli" kalau ia tutup naik, atau "jual" kalau ia tutup turun. Ini teknik yang biasa digunakan dalam kebanyakan skrip order flow percuma di TradingView — berguna untuk berlatih baca konsep, tapi bukan gantian penuh untuk data bid/ask sebenar.

Apa yang skrip ni tunjukkan, semuanya dalam SATU tetingkap carta:

  • Footprint — nombor "beli x jual" pada setiap paras harga, terus di atas candle
  • Delta — bar kecil warna hijau/merah di bawah setiap candle, menunjukkan kekuatan beli/jual relatif
  • Volume Heatmap + POC/VAH/VAL — zon warna di sebelah kanan carta menunjukkan paras harga paling banyak volume (Point of Control), berserta garis Value Area (70% volume) — konsep yang sama macam zon Order Block, cuma dikira dari volume, bukan struktur candle
  • Panel Ringkasan — jadual kecil di sudut carta menunjukkan sejarah beli/jual/delta beberapa candle terkini, jumlah Delta harian, dan nilai POC/VAH/VAL

Cara Pasang Di TradingView

  1. Buka TradingView, pergi ke Pine Editor (menu di bahagian bawah skrin carta).
  2. Klik NewBlank indicator, padam kod contoh yang ada, dan salin-tampal (copy-paste) kod di bawah.
  3. Klik Save, kemudian Add to Chart.
//@version=5
// Order Flow: Footprint + Delta + Volume Heatmap — One Window (Approximation)
//
// Combines three pieces into a single overlay script so everything shows in
// one chart window:
//   1) Footprint grid (buy x sell volume per price level, per recent candle)
//   2) A mini delta bar under each candle (net buy/sell strength)
//   3) A volume-at-price heatmap strip + POC/VAH/VAL lines, drawn just to
//      the right of price, plus a fixed side-panel table (recent-bar
//      history + running totals + POC/VAH/VAL) docked to a screen corner
//
// IMPORTANT — read this before trusting the numbers:
//   - Pine Script has no access to real bid/ask (Level 2) trade data. Every
//     buy/sell figure here is inferred from whether a smaller "lower
//     timeframe" bar closed up or down — a widely used approximation, but
//     not the real order tape.
//   - The heatmap/profile uses your CHART's own bar volume (not the lower
//     timeframe), spread evenly across each bar's high-low range — the
//     standard simplified approach most Pine volume-profile scripts use.
//   - POC/VAH/VAL and the heatmap only recalculate on the most recent bar
//     (not every historical bar) to keep the script fast.
indicator("Order Flow: Footprint + Delta + Heatmap (One Window)", overlay=true,
     max_labels_count=500, max_boxes_count=500, max_lines_count=50)

// ---------------- Inputs ----------------
lowerTF = input.timeframe("1", "Lower timeframe (intrabar source)",
     tooltip="Must be smaller than your chart's own timeframe. '1' (1 minute) works well for charts of 15m and above.")
tickSize = input.float(1.0, "Price step per row (e.g. FCPO = 1.0)", minval=0.0001)

grpPrint = "Footprint"
footprintBars = input.int(40, "Draw footprint for last N bars only", minval=1, maxval=150, group=grpPrint)
textSizeOpt = input.string("Tiny", "Footprint text size", options=["Tiny", "Small", "Normal"], group=grpPrint)
textSize = textSizeOpt == "Tiny" ? size.tiny : textSizeOpt == "Small" ? size.small : size.normal

grpDelta = "Mini Delta Bar (drawn below each candle)"
showDeltaBars    = input.bool(true, "Show mini delta bar under each candle", group=grpDelta)
deltaLookback    = input.int(50, "Normalize delta against last N bars", minval=5, group=grpDelta)
deltaHeightTicks = input.float(15, "Max mini-bar height (in ticks)", minval=1, group=grpDelta)
deltaGapTicks    = input.float(3, "Gap between candle low and mini-bar (in ticks)", minval=0, group=grpDelta)

grpHeat = "Volume Heatmap / Profile"
showHeatmap     = input.bool(true, "Show volume heatmap strip", group=grpHeat)
profileLookback = input.int(200, "Profile lookback (bars)", minval=10, maxval=500, group=grpHeat,
     tooltip="Large values can slow the script down since it re-scans this many bars on every price update.")
profileRows     = input.int(24, "Heatmap rows (price buckets)", minval=5, maxval=100, group=grpHeat)
heatmapWidth    = input.int(6, "Heatmap strip width (bars, cosmetic)", minval=1, maxval=20, group=grpHeat)
valueAreaPct    = input.float(70, "Value Area %", minval=10, maxval=100, group=grpHeat)
heatColor       = input.color(color.blue, "Heatmap color", group=grpHeat)
showPocLines    = input.bool(true, "Show POC / VAH / VAL lines", group=grpHeat)

grpColor = "Colors"
buyColor     = input.color(color.new(color.lime, 0), "Buy-dominant color", group=grpColor)
sellColor    = input.color(color.new(color.red, 0), "Sell-dominant color", group=grpColor)
neutralColor = input.color(color.new(color.gray, 0), "Balanced color (footprint only)", group=grpColor)

grpPanel = "Side Panel"
showSidePanel    = input.bool(true, "Show side panel", group=grpPanel)
panelPositionOpt = input.string("Top Right", "Panel position", group=grpPanel,
     options=["Top Right", "Middle Right", "Bottom Right", "Top Left", "Middle Left", "Bottom Left"])
panelRows        = input.int(10, "Rows of recent-bar history", minval=1, maxval=30, group=grpPanel)

panelPosition(p) =>
    result = position.bottom_left
    if p == "Top Right"
        result := position.top_right
    else if p == "Middle Right"
        result := position.middle_right
    else if p == "Bottom Right"
        result := position.bottom_right
    else if p == "Top Left"
        result := position.top_left
    else if p == "Middle Left"
        result := position.middle_left
    result

// ---------------- Delta / Footprint data source ----------------
[iopen, iclose, ivolume] = request.security_lower_tf(syminfo.tickerid, lowerTF, [open, close, volume])
n = array.size(iclose)

float totalBuy  = 0.0
float totalSell = 0.0
if n > 0
    for i = 0 to n - 1
        vol = array.get(ivolume, i)
        c   = array.get(iclose, i)
        o   = array.get(iopen, i)
        if c >= o
            totalBuy += vol
        else
            totalSell += vol
delta = totalBuy - totalSell
// Resets to 0 at the start of each new day instead of accumulating since
// the start of the chart's history.
var float cumDelta = 0.0
if ta.change(time("D")) != 0
    cumDelta := delta
else
    cumDelta += delta

maxAbsDelta = ta.highest(math.abs(delta), deltaLookback)

// ---------------- Rolling per-bar history (for the side panel) ----------------
var buyHist   = array.new<float>()
var sellHist  = array.new<float>()
var deltaHist = array.new<float>()

if barstate.isnew
    array.push(buyHist, totalBuy)
    array.push(sellHist, totalSell)
    array.push(deltaHist, delta)
    if array.size(deltaHist) > panelRows
        array.shift(buyHist)
        array.shift(sellHist)
        array.shift(deltaHist)
else if array.size(deltaHist) > 0
    lastIdx = array.size(deltaHist) - 1
    array.set(buyHist, lastIdx, totalBuy)
    array.set(sellHist, lastIdx, totalSell)
    array.set(deltaHist, lastIdx, delta)

// ---------------- Mini delta bar under each candle ----------------
if showDeltaBars and not na(maxAbsDelta) and maxAbsDelta > 0
    heightTicks = (math.abs(delta) / maxAbsDelta) * deltaHeightTicks
    barTop    = low - deltaGapTicks * tickSize
    barBottom = barTop - heightTicks * tickSize
    box.new(bar_index, barTop, bar_index, barBottom, border_color=na, bgcolor=delta >= 0 ? buyColor : sellColor)

// ---------------- Footprint grid, last N bars only ----------------
drawHere = bar_index >= last_bar_index - footprintBars + 1

if drawHere and n > 0
    levels   = array.new<float>()
    buyVols  = array.new<float>()
    sellVols = array.new<float>()

    for i = 0 to n - 1
        vol   = array.get(ivolume, i)
        c     = array.get(iclose, i)
        o     = array.get(iopen, i)
        isBuy = c >= o
        level = math.round(c / tickSize) * tickSize

        idx = -1
        if array.size(levels) > 0
            for j = 0 to array.size(levels) - 1
                if array.get(levels, j) == level
                    idx := j
                    break

        if idx == -1
            array.push(levels, level)
            array.push(buyVols, isBuy ? vol : 0.0)
            array.push(sellVols, isBuy ? 0.0 : vol)
        else
            if isBuy
                array.set(buyVols, idx, array.get(buyVols, idx) + vol)
            else
                array.set(sellVols, idx, array.get(sellVols, idx) + vol)

    for k = 0 to array.size(levels) - 1
        lvl = array.get(levels, k)
        bv  = array.get(buyVols, k)
        sv  = array.get(sellVols, k)
        dominant = bv > sv ? buyColor : sv > bv ? sellColor : neutralColor
        txt = str.tostring(math.round(bv)) + " x " + str.tostring(math.round(sv))
        label.new(bar_index, lvl, txt, xloc=xloc.bar_index, yloc=yloc.price,
             style=label.style_label_center, size=textSize,
             color=color.new(dominant, 80), textcolor=dominant)

// ---------------- Volume Heatmap + POC / VAH / VAL ----------------
var boxArr  = array.new<box>()
var line pocLine = na
var line vahLine = na
var line valLine = na
var float pocPrice = na
var float vahPrice = na
var float valPrice = na

if showHeatmap and barstate.islast
    if array.size(boxArr) > 0
        for i = 0 to array.size(boxArr) - 1
            box.delete(array.get(boxArr, i))
        array.clear(boxArr)

    hi = ta.highest(high, profileLookback)
    lo = ta.lowest(low, profileLookback)
    step = (hi - lo) / profileRows

    if step > 0
        volAtLevel = array.new<float>(profileRows, 0.0)
        for i = 0 to profileLookback - 1
            bh = high[i]
            bl = low[i]
            bv = volume[i]
            if not na(bh) and not na(bl) and not na(bv)
                startBucket = int(math.max(0, math.floor((bl - lo) / step)))
                endBucket   = int(math.min(profileRows - 1, math.floor((bh - lo) / step)))
                if endBucket >= startBucket
                    bucketsSpanned = endBucket - startBucket + 1
                    volPerBucket = bv / bucketsSpanned
                    for b = startBucket to endBucket
                        array.set(volAtLevel, b, array.get(volAtLevel, b) + volPerBucket)

        maxVol = array.max(volAtLevel)
        pocBucket = array.indexof(volAtLevel, maxVol)

        if pocBucket >= 0
            totalVol = array.sum(volAtLevel)
            targetVol = totalVol * valueAreaPct / 100
            vaTop = pocBucket
            vaBottom = pocBucket
            accumulated = array.get(volAtLevel, pocBucket)
            while accumulated < targetVol and (vaTop < profileRows - 1 or vaBottom > 0)
                aboveVol = vaTop < profileRows - 1 ? array.get(volAtLevel, vaTop + 1) : -1.0
                belowVol = vaBottom > 0 ? array.get(volAtLevel, vaBottom - 1) : -1.0
                if aboveVol >= belowVol
                    vaTop += 1
                    accumulated += aboveVol
                else
                    vaBottom -= 1
                    accumulated += belowVol

            pocPrice := lo + (pocBucket + 0.5) * step
            vahPrice := lo + (vaTop + 1) * step
            valPrice := lo + vaBottom * step

            for b = 0 to profileRows - 1
                v = array.get(volAtLevel, b)
                intensity = maxVol > 0 ? v / maxVol : 0.0
                transp = int(90 - intensity * 80)
                boxColor = color.new(heatColor, transp)
                top = lo + (b + 1) * step
                bottom = lo + b * step
                newBox = box.new(bar_index + 2, top, bar_index + 2 + heatmapWidth, bottom, border_color=na, bgcolor=boxColor)
                array.push(boxArr, newBox)

            if showPocLines
                line.delete(pocLine)
                line.delete(vahLine)
                line.delete(valLine)
                pocLine := line.new(bar_index - profileLookback, pocPrice, bar_index + heatmapWidth + 2, pocPrice,
                     color=color.new(color.yellow, 0), width=1, style=line.style_dashed)
                vahLine := line.new(bar_index - profileLookback, vahPrice, bar_index + heatmapWidth + 2, vahPrice,
                     color=color.new(color.aqua, 30), width=1, style=line.style_dotted)
                valLine := line.new(bar_index - profileLookback, valPrice, bar_index + heatmapWidth + 2, valPrice,
                     color=color.new(color.aqua, 30), width=1, style=line.style_dotted)

// ---------------- Side panel: fixed to a screen corner ----------------
var table panel = table.new(panelPosition(panelPositionOpt), 4, panelRows + 5, border_width=1)

if showSidePanel and barstate.islast
    headerBg = color.new(color.gray, 60)
    table.cell(panel, 0, 0, "Bar", text_color=color.white, bgcolor=headerBg)
    table.cell(panel, 1, 0, "Buy", text_color=color.white, bgcolor=headerBg)
    table.cell(panel, 2, 0, "Sell", text_color=color.white, bgcolor=headerBg)
    table.cell(panel, 3, 0, "Delta", text_color=color.white, bgcolor=headerBg)

    rows = array.size(deltaHist)
    for r = 0 to panelRows - 1
        if r < rows
            idxFromEnd = rows - 1 - r
            d  = array.get(deltaHist, idxFromEnd)
            bv = array.get(buyHist, idxFromEnd)
            sv = array.get(sellHist, idxFromEnd)
            rowBg = color.new(d >= 0 ? buyColor : sellColor, 65)
            barLabel = r == 0 ? "Now" : str.tostring(r) + " back"
            table.cell(panel, 0, r + 1, barLabel, text_color=color.white, bgcolor=color.new(color.gray, 80))
            table.cell(panel, 1, r + 1, str.tostring(math.round(bv)), text_color=color.white, bgcolor=rowBg)
            table.cell(panel, 2, r + 1, str.tostring(math.round(sv)), text_color=color.white, bgcolor=rowBg)
            table.cell(panel, 3, r + 1, str.tostring(math.round(d)), text_color=color.white, bgcolor=rowBg)
        else
            table.cell(panel, 0, r + 1, "", bgcolor=color.new(color.gray, 90))
            table.cell(panel, 1, r + 1, "", bgcolor=color.new(color.gray, 90))
            table.cell(panel, 2, r + 1, "", bgcolor=color.new(color.gray, 90))
            table.cell(panel, 3, r + 1, "", bgcolor=color.new(color.gray, 90))

    table.cell(panel, 0, panelRows + 1, "Cum Δ (Day)", text_color=color.white, bgcolor=color.new(color.blue, 60))
    table.cell(panel, 1, panelRows + 1, str.tostring(math.round(cumDelta)), text_color=color.white, bgcolor=color.new(color.blue, 60))
    table.cell(panel, 2, panelRows + 1, "", bgcolor=color.new(color.blue, 60))
    table.cell(panel, 3, panelRows + 1, "", bgcolor=color.new(color.blue, 60))

    table.cell(panel, 0, panelRows + 2, "POC", text_color=color.white, bgcolor=color.new(color.yellow, 70))
    table.cell(panel, 1, panelRows + 2, str.tostring(pocPrice), text_color=color.white, bgcolor=color.new(color.yellow, 70))
    table.cell(panel, 2, panelRows + 2, "", bgcolor=color.new(color.yellow, 70))
    table.cell(panel, 3, panelRows + 2, "", bgcolor=color.new(color.yellow, 70))

    table.cell(panel, 0, panelRows + 3, "VAH", text_color=color.white, bgcolor=color.new(color.aqua, 70))
    table.cell(panel, 1, panelRows + 3, str.tostring(vahPrice), text_color=color.white, bgcolor=color.new(color.aqua, 70))
    table.cell(panel, 2, panelRows + 3, "", bgcolor=color.new(color.aqua, 70))
    table.cell(panel, 3, panelRows + 3, "", bgcolor=color.new(color.aqua, 70))

    table.cell(panel, 0, panelRows + 4, "VAL", text_color=color.white, bgcolor=color.new(color.aqua, 70))
    table.cell(panel, 1, panelRows + 4, str.tostring(valPrice), text_color=color.white, bgcolor=color.new(color.aqua, 70))
    table.cell(panel, 2, panelRows + 4, "", bgcolor=color.new(color.aqua, 70))
    table.cell(panel, 3, panelRows + 4, "", bgcolor=color.new(color.aqua, 70))

Tetapan disyorkan untuk FCPO:

  • Price step per row (tickSize): 1
  • Lower timeframe: 1 (guna pada carta 15 minit ke atas)
  • Profile lookback: 200 bar (boleh kurangkan kalau nak fokus sesi terkini sahaja)

Semua tetapan lain (warna, saiz teks, kedudukan panel) boleh anda ubah suai terus dalam menu tetapan skrip di TradingView selepas ditambah ke carta.

Had Order Flow — Bukan "Holy Grail"

Beberapa perkara penting untuk faham sebelum anda terlalu bergantung pada order flow:

  • Data order flow yang 100% tepat (bid/ask sebenar) masih perlukan platform berbayar. Skrip Pine Script percuma di atas bagus untuk belajar konsep, tapi ia anggaran sahaja — untuk data footprint/delta yang benar-benar tepat dan masa nyata, anda perlukan platform khusus seperti Bookmap, ATAS, atau Sierra Chart dengan data feed sebenar.
  • Ia satu lapisan konfirmasi, bukan strategi berdiri sendiri. Order flow paling berkesan bila digabung dengan struktur pasaran dan konsep SMC yang anda dah faham — bukan sebagai satu-satunya sebab untuk masuk trade.
  • Ia memerlukan latihan mata yang banyak. Membaca footprint chart dengan pantas dan tepat dalam masa nyata mengambil masa dan pengalaman — jangan terus guna dalam akaun sebenar sebelum anda selesa baca dalam simulasi dulu.

Baca Market Structure: BOS dan CHoCH untuk faham struktur pasaran asas yang order flow sepatutnya sahkan, bukan gantikan.

Kesimpulan

Order flow bagi anda pandangan yang lebih mendalam tentang SIAPA yang sebenarnya mengawal setiap pergerakan harga — melalui delta dan absorption, ia mengesahkan (atau meragui) setup SMC yang anda dah kenal pasti. Tapi ia bukan holy grail — perlukan data berkualiti, latihan membaca, dan paling penting, digabungkan dengan struktur pasaran yang anda dah faham, bukan berdiri sendiri.

Ini adalah konten pendidikan sahaja, bukan nasihat kewangan. Sentiasa buat kajian sendiri dan faham risiko sebelum trading.

Cuba Sendiri

Cari pattern yang baru anda pelajari dalam data pasaran sebenar guna Real Data Simulator — salah satu manfaat ahli MTA.

Cuba Real Data Simulator
Suka artikel ini? Kongsi: