tvpinescript

open
close

Matrix Oscillator: Precision Market Analysis with Divergence Detection

January 23, 2025 | by admin

bandicam 2025-01-23 10-00-35-468

Understanding market momentum and price action is key to profitable trading. The Matrix Oscillator is a powerful indicator designed to provide traders with comprehensive insights into market trends by combining RSI, MFI, and Stochastic calculations. It helps identify overbought/oversold conditions, divergences, and trend reversals, making it an essential tool for both novice and experienced traders.

⚠ Disclaimer: No trading indicator guarantees profits. The Matrix Oscillator should be used as a supplementary analysis tool within a well-structured trading plan and proper risk management strategies.


🛠 Key Features of the Matrix Oscillator

  1. Signal Line for Trend Direction:
    • Combines RSI, MFI, and Stochastic indicators for a comprehensive market sentiment overview.
    • Smooths out market noise for clear buy/sell signals.
    • Customizable colors for bullish and bearish trends.
  2. Histogram for Momentum Visualization:
    • Displays market strength with easy-to-interpret color-coded bars.
    • Highlights shifts in momentum for potential trend changes.
  3. Divergence Detection (Regular & Hidden):
    • Identifies both regular and hidden divergences to predict possible reversals.
    • Plots bullish (green) and bearish (red) divergence lines.
    • Automatically removes invalid divergence lines for better chart clarity.
  4. Dynamic Reversal Points:
    • Marks potential turning points with color-coded circles.
    • Helps traders anticipate trend shifts before they occur.
  5. Take Profit (TP) Signal System:
    • Suggests optimal take-profit levels based on market conditions.
    • Customizable to match different trading styles.
  6. Custom Alerts for Entry/Exit Points:
    • Alerts for divergence, take-profit signals, and trend shifts.
    • Keeps traders informed without the need for constant monitoring.
  7. Multi-Timeframe Compatibility:
    • Effective across different timeframes, from 1-minute scalping to daily swing trading.
    • Best suited for 5-minute, 15-minute, 1-hour, and 4-hour charts.

📊 Recommended Usage

  1. Scalping (1M-15M Charts):
    • Focus on quick trades using histogram momentum and reversal points.
    • Combine with moving averages for additional confirmation.
  2. Day Trading (30M-1H Charts):
    • Use divergence detection to enter trades at key support/resistance levels.
    • Utilize alerts for trend-following strategies.
  3. Swing Trading (4H-Daily Charts):
    • Leverage take-profit signals for longer-term trend analysis.
    • Identify overbought/oversold zones for high-probability entries.

🔍 Script Evaluation

  • Functionality: 4.8/5
    A comprehensive oscillator that provides multiple trading signals, reducing noise and improving decision-making.
  • Ease of Use: 4.3/5
    Requires some learning curve due to the number of features available, but customizable settings make it flexible.
  • Accuracy: 4.5/5
    Performs well in trending markets but may need additional filters for ranging conditions.
  • Repainting Analysis:
    No repainting detected. The script calculates and confirms values based on closed bars, ensuring reliable signals for live trading.
  • Optimal Timeframes:
    • Scalping: 1-minute to 15-minute charts.
    • Day Trading: 30-minute to 1-hour charts.
    • Swing Trading: 4-hour to daily charts.
  • Overall Score: 4.7/5
    A highly reliable oscillator that combines multiple technical indicators to provide a comprehensive market outlook.



//@version=5
indicator("[𝖬𝖺𝗍𝗋𝗂𝗑] 𝖮𝗌𝖼𝗂𝗅𝗅𝖺𝗍𝗈𝗋", overlay = false, max_lines_count = 500,max_labels_count = 500)

//-----------------------------------------------------------------------------
//              Input | Settings
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{
const string FREQ = alert.freq_once_per_bar_close
const color NO_COLOR = color.new(#000000, 100)

const string MAIN_INPUT = "🚀 Signal Line"
showMainLine    = input.bool    (true,            "Turn On/Off",        group = MAIN_INPUT, inline="Main", display = display.none)
gColor          = input.color   (#00cfba,    "",                   group = MAIN_INPUT, inline="Main", display = display.none)
rColor          = input.color   (#ff5f6a,       "",                   group = MAIN_INPUT, inline="Main", display = display.none)
rsiLen          = input.int     (10,              "Length", minval = 1, group = MAIN_INPUT,                display = display.none)
smoothLen       = input.int     (3,               "Smooth", minval = 1, group = MAIN_INPUT,                display = display.none)
const string HIST_INPUT = "📊 Histogram"
showHist        = input.bool    (true,            "Turn On/Off",        group = HIST_INPUT, inline="hist", display = display.none)
histColorUp     = input.color   (#6de6f693,     "",                   group = HIST_INPUT, inline="hist", display = display.none)
histColorDn     = input.color   (#f66d6d93,     "",                   group = HIST_INPUT, inline="hist", display = display.none)
inputMfiLen     = input.int     (15,              "Length", minval = 5, group = HIST_INPUT,                display = display.none)
smoothHist      = input.int     (1,               "Smooth", minval = 1, group = HIST_INPUT,                display = display.none)
fastMfiLen      = math.round    (inputMfiLen / 1.33)
slowMfiLen      = math.round    (inputMfiLen * 1.33)

const string OTHER_INPUT = "💡 Other"
showDiv         = input.bool    (true,          "Show Divergence Line   ", group = OTHER_INPUT, inline="div",     display = display.none)
bullDivColor    = input.color   (color.white, "",                        group = OTHER_INPUT, inline="div",     display = display.none)
bearDivColor    = input.color   (color.white, "",                        group = OTHER_INPUT, inline="div",     display = display.none)

showHidDiv      = input.bool    (true,         "Show Hidden Divergence",  group = OTHER_INPUT, inline="hiddiv",  display = display.none)
bullHidDivColor = input.color   (#07ffac,     "",                        group = OTHER_INPUT, inline="hiddiv",  display = display.none)
bearHidDivColor = input.color   (#ff5500,     "",                        group = OTHER_INPUT, inline="hiddiv",  display = display.none)

showStatusLine  = input.bool    (true,          "Show Status Line       ", group = OTHER_INPUT, inline="Status",  display = display.none)
gStatColor      = input.color   (#02bcaa,  "",                        group = OTHER_INPUT, inline="Status",  display = display.none)  
rStatColor      = input.color   (#ff475c,  "",                          group = OTHER_INPUT, inline="Status",  display = display.none)

showTpSignal    = input.bool    (true,          "Show TP Signal         ", group = OTHER_INPUT, inline="tp",      display = display.none)
gTpColor        = input.color   (color.teal,  "",                        group = OTHER_INPUT, inline="tp",      display = display.none)  
rTpColor        = input.color   (#da5b52,     "",                        group = OTHER_INPUT, inline="tp",      display = display.none)

showReverseDots = input.bool    (true,          "Show Reversal points    ", group = OTHER_INPUT, inline="rd",     display = display.none)
gRdColor        = input.color   (color.teal,  "",                         group = OTHER_INPUT, inline="rd",     display = display.none)  
rRdColor        = input.color   (#da5b52,     "",                         group = OTHER_INPUT, inline="rd",     display = display.none)

delOldDiv       = input.bool    (true,    "Delete Broken Divergence Lines", group = OTHER_INPUT,                  display = display.none)


//------------------------------------------------------------------------------}

//-----------------------------------------------------------------------------
//              Alerts
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{

const string ALERT_INPUT = "🔔 ALERTS CUSTOMIZATION\n"

alertSigUp = input.bool     (false,     "Signal Line Bull       ",  inline="a1", group = ALERT_INPUT, display = display.none)
alertSigDn = input.bool     (false,     "Bear",                     inline="a1", group = ALERT_INPUT, display = display.none)

alertBullTP = input.bool    (false,     "TP Bull               ",   inline="a2", group = ALERT_INPUT, display = display.none)
alertBearTP = input.bool    (false,     "Bear",                     inline="a2", group = ALERT_INPUT, display = display.none)

alertStatusUp = input.bool  (false,     "Status Bull            ",  inline="a3", group = ALERT_INPUT, display = display.none)
alertStatusDn = input.bool  (false,     "Bear",                     inline="a3", group = ALERT_INPUT, display = display.none)
alertStatusUpP = input.bool (false,     "Status Bull+           ",  inline="a4", group = ALERT_INPUT, display = display.none)
alertStatusDnP = input.bool (false,     "Bear+",                    inline="a4", group = ALERT_INPUT, display = display.none)

alertBullDiv = input.bool   (false,     "Divergence Bull       ",   inline="a5", group = ALERT_INPUT, display = display.none)
alertBearDiv = input.bool   (false,     "Bear",                     inline="a5", group = ALERT_INPUT, display = display.none)

alertBullHidDiv = input.bool(false,     "Hidden Divergence Bull ",  inline="a6", group = ALERT_INPUT, display = display.none)
alertBearHidDiv = input.bool(false,     "Bear",                     inline="a6", group = ALERT_INPUT, display = display.none)

inputMsg = input.text_area("List of Supported Placeholders:\n{{trigger}} - Trigger name ('Buy', 'Bullish Take Profit')\n{{indicator}} - Indicator Value\n{{exchange}} - Exchange ('Binance')\n{{ticker}} - Ticker ('BTCUSD')\n{{interval}} - Timeframe ('1s', '1', 'D')\n{{open}}-{{close}}-{{high}}-{{low}} - Candle price values\n{{volume}} - Candle volume\n{{time}} - Candle open time in UTC timezone\n{{timenow}} - Signal time in UTC timezone\n{{syminfo.currency}} - 'USD' for BTCUSD pair\n{{syminfo.basecurrency}} - 'BTC' for BTCUSD pair", "", group = ALERT_INPUT, display = display.none)


getAlertMasg(string trigger, float ind=0.0)=>
    alertMsg =  str.replace_all(inputMsg, "{{exchange}}", syminfo.prefix)
    alertMsg := str.replace_all(alertMsg, "{{ticker}}",   syminfo.ticker)
    alertMsg := str.replace_all(alertMsg, "{{volume}}",   str.tostring(volume, format.volume))
    alertMsg := str.replace_all(alertMsg, "{{close}}",    str.tostring(close, format.price))
    alertMsg := str.replace_all(alertMsg, "{{open}}",     str.tostring(open, format.price))
    alertMsg := str.replace_all(alertMsg, "{{high}}",     str.tostring(high, format.price))
    alertMsg := str.replace_all(alertMsg, "{{low}}",      str.tostring(low, format.price))
    alertMsg := str.replace_all(alertMsg, "{{time}}",     str.format_time(time, "yyyy-MM-dd", "Etc/UTC")+"T"+str.format_time(time, "HH:mm:ss", "Etc/UTC")+"Z")
    alertMsg := str.replace_all(alertMsg, "{{timenow}}",  str.format_time(timenow, "yyyy-MM-dd", "Etc/UTC")+"T"+str.format_time(timenow, "HH:mm:ss", "Etc/UTC")+"Z")
    alertMsg := str.replace_all(alertMsg, "{{interval}}", timeframe.period)
    alertMsg := str.replace_all(alertMsg, "{{syminfo.currency}}", syminfo.currency)
    alertMsg := str.replace_all(alertMsg, "{{syminfo.basecurrency}}", syminfo.basecurrency)
    alertMsg := str.replace_all(alertMsg, "{{trigger}}", trigger)
    alertMsg := str.replace_all(alertMsg, "{{indicator}}", str.tostring(ind, "##.#"))
    alertMsg

//------------------------------------------------------------------------------}

//-----------------------------------------------------------------------------
//              Main
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{
const int   MFI_LEN     = 7
const int   STOCH_K     = 2
const int   STOCH_D     = 5
const float SMOOTH_LEN  = 1.75
const float STOCH_WEIGHT = 0.4
const float OVERBOUGHT   = 60.0
const float EXTEND_MULT  = 1
var   float mfiWeight    = 0.4

rsiSrc = hlc3

transform(src, mult=1)=>
    tmp = (src / 100 - 0.5)*2
    mult * 100 * ((tmp > 0 ? 1 : -1) * math.pow(math.abs(tmp), 0.75))

//Histogram
fastMfi = ta.mfi(rsiSrc, fastMfiLen)
slowMfi = ta.mfi(rsiSrc, slowMfiLen)
resMfi = transform(ta.sma(fastMfi*0.5 + slowMfi*0.5, smoothHist), 0.7)

midLine = plot(0, color = histColorUp, editable = false, display = display.pane)
histColor = showHist ? resMfi >= 0 ? histColorUp : histColorDn : NO_COLOR
longterm = plot(resMfi, color = histColor, editable = false, display = display.pane) //20*macd/ta.highest(absMACD,20) + 50 
fill(longterm, midLine, resMfi, 0, histColor, NO_COLOR, editable = false)

//Siganl
mfi = ta.mfi(rsiSrc, MFI_LEN)
rsi = ta.rsi(rsiSrc, rsiLen)
stoch = ta.sma(ta.stoch(rsi, rsi, rsi, rsiLen), STOCH_K)
sigStoch = ta.sma(stoch, STOCH_D)
if na(volume) 
    mfi := 0
    mfiWeight := 0

signal = (rsi + mfiWeight*mfi + STOCH_WEIGHT*stoch)/(1+mfiWeight+STOCH_WEIGHT)
avg =  transform(ta.ema(signal, smoothLen), EXTEND_MULT)
avg2 = transform(ta.ema(signal, math.round(smoothLen * SMOOTH_LEN)), EXTEND_MULT)

resColor = showMainLine ? avg2 < avg ? gColor : rColor : NO_COLOR
s1 = plot(avg, "Avg",   resColor, linewidth = 1, editable = false, display = display.pane)
s2 = plot(avg2, "Avg2", NO_COLOR, linewidth = 1, editable = false, display = display.pane)
fill(s1, s2, color.new(resColor, 50), "diff", editable = false)


plot(showMainLine and showReverseDots and avg2 < avg and resColor != resColor[1] and avg[1] < -OVERBOUGHT ? avg2 : na, "Signal Direction Up",       color = gRdColor, display = display.pane, style = plot.style_circles, linewidth = 3, editable = false)
plot(showMainLine and showReverseDots and avg2 < avg and resColor != resColor[1] and avg[1] >= -OVERBOUGHT ? avg2 : na, "Signal Direction Up ch",   color = gRdColor, display = display.pane, style = plot.style_circles, linewidth = 2, editable = false)
plot(showMainLine and showReverseDots and avg2 > avg and resColor != resColor[1] and avg[1] > OVERBOUGHT ? avg2 : na, "Signal Direction Down",      color = rRdColor, display = display.pane, style = plot.style_circles, linewidth = 3, editable = false)
plot(showMainLine and showReverseDots and avg2 > avg and resColor != resColor[1] and avg[1] <= OVERBOUGHT ? avg2 : na, "Signal Direction Down ch",  color = rRdColor, display = display.pane, style = plot.style_circles, linewidth = 2, editable = false)

if alertSigUp and avg2 < avg and avg2[1] >= avg[1]
    alert(getAlertMasg("Signal Line Bull", avg), FREQ)
if alertSigDn and avg2 > avg and avg2[1] <= avg[1]
    alert(getAlertMasg("Signal Line Bear", avg), FREQ)

var allIndVal = array.new<float>()
var allLows = array.new<float>()
var allHighs = array.new<float>()

if barstate.isconfirmed
    allIndVal.unshift(avg)
    allLows.unshift(low)
    allHighs.unshift(high)
    if allIndVal.size() > 100
        allIndVal.pop()
        allLows.pop()
        allHighs.pop()
//------------------------------------------------------------------------------}

//-----------------------------------------------------------------------------
//              Status Line
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{
score = 0
if avg > avg2
    score += 1
if avg > 0
    score += 1
if resMfi > 0
    score += 1

upLimitColor = showStatusLine ? score == 3 ? gStatColor : score == 2 ? color.new(gStatColor, 50) : color.black : NO_COLOR
dnLimitColor = showStatusLine ? score == 0 ? rStatColor : score == 1 ? color.new(rStatColor, 50) : color.black : NO_COLOR

upLimit1 = plot(95, "upLimit1", NO_COLOR, editable = false, display = display.pane)
upLimit2 = plot(105, "upLimit2", NO_COLOR, editable = false, display = display.pane)
fill(upLimit1, upLimit2, upLimitColor, "Up Limit", editable = false)
dnLimit1 = plot(-95, "dnLimit1", NO_COLOR, editable = false, display = display.pane)
dnLimit2 = plot(-105, "dnLimit2", NO_COLOR, editable = false, display = display.pane)
fill(dnLimit1, dnLimit2,  dnLimitColor, "Down Limit", editable = false)

if alertStatusUp and score >= 2 and score[1] < 2
    alert(getAlertMasg("Status Bull", avg), FREQ)
if alertStatusUpP and score >= 3 and score[1] < 3
    alert(getAlertMasg("Status Bull+", avg), FREQ)
if alertStatusDn and score <= 1 and score[1] > 1
    alert(getAlertMasg("Status Bear", avg), FREQ)
if alertStatusDnP and score <= 0 and score[1] > 0
    alert(getAlertMasg("Status Bear+", avg), FREQ)

//------------------------------------------------------------------------------}

//-----------------------------------------------------------------------------
//              Divergence Functions
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{
type Pivot
    float price
    int   ndx
    float indicator

type DiverLine
    line    ln
    label   lb

const int MAX_ARR_PIV_SIZE = 5
const int MAX_ARR_LINE_SIZE = 250
const int PIV_LEN_LEFT = 7 
const int PIV_LEN_RIGHT = 1 
const int MIN_PEAK_DIST = 7
const int MAX_PEAK_DIST = 80

var pivHigh = array.new<Pivot>()
var pivLow  = array.new<Pivot>()  

var bullDivers = array.new<DiverLine>()
var bearDivers = array.new<DiverLine>()
var bullHidDivers = array.new<DiverLine>()
var bearHidDivers = array.new<DiverLine>()

addPivotHigh(Pivot newPiv)=>
    if pivHigh.size() > 0
        prev = pivHigh.first()
        if prev.price < newPiv.price and prev.indicator < newPiv.indicator
            pivHigh.shift()
    pivHigh.unshift(newPiv)
    if pivHigh.size() > MAX_ARR_PIV_SIZE
        pivHigh.pop()

addPivotLow(Pivot newPiv)=>
    if pivLow.size() > 0
        prev = pivLow.first()
        if prev.price > newPiv.price and prev.indicator > newPiv.indicator
            pivLow.shift()
    pivLow.unshift(newPiv)
    if pivLow.size() > MAX_ARR_PIV_SIZE
        pivLow.pop()

method checkArrLineLength(array<DiverLine> arr)=>
    if arr.size() > MAX_ARR_LINE_SIZE
        _ln = arr.shift()
        _ln.ln.delete()
        _ln.lb.delete()

method addDiverLine(array<DiverLine> arr, DiverLine newLine)=>
    x1 = newLine.ln.get_x1()
    x2 = newLine.ln.get_x2()
    if arr.size() > 0
        for i = arr.size() - 1 to 0
            _ln  = arr.get(i)
            if _ln.ln.get_x1() < x1
                break
            else if delOldDiv
                _ln.ln.delete()
                _ln.lb.delete()
                arr.remove(i)
            else
                _ln.ln.set_style(line.style_dotted)
                _ln.ln.set_width(1)
                _ln.lb.set_textcolor(NO_COLOR)
    arr.push(newLine)
    arr.checkArrLineLength()

isGreaterIndValue(int start, int end, float maxIndVal)=>
    res = true
    for i = bar_index - end to bar_index - start
        if allIndVal.get(i) > maxIndVal
            res := false
            break
    res

isLowerIndValue(int start, int end, float minIndVal)=>
    res = true
    for i = bar_index - start to bar_index - end
        if allIndVal.get(i) < minIndVal
            res := false
            break
    res

isGreaterHigh(int start, int end, float pointHigh)=>
    res = true
    for i = bar_index - end to bar_index - start
        if allHighs.get(i) > pointHigh
            res := false
            break
    res

isLowerLow(int start, int end, float pointLow)=>
    res = true
    for i = bar_index - start to bar_index - end
        if allLows.get(i) < pointLow
            res := false
            break
    res

isNoCrossAbove(Pivot piv1, Pivot piv2)=>
    res = true
    speed = (piv2.indicator - piv1.indicator) / (piv2.ndx - piv1.ndx)
    y0 = piv1.indicator - speed * piv1.ndx
    for i = bar_index - piv2.ndx to bar_index - piv1.ndx
        yi = y0 + speed * (bar_index - i)
        if allIndVal.get(i) > yi
            res := false
            break
    res

isNoCrossBelow(Pivot piv1, Pivot piv2)=>
    res = true
    speed = (piv2.indicator - piv1.indicator) / (piv2.ndx - piv1.ndx)
    y0 = piv1.indicator - speed * piv1.ndx
    for i = bar_index - piv2.ndx to bar_index - piv1.ndx
        yi = y0 + speed * (bar_index - i)
        if allIndVal.get(i) < yi
            res := false
            break
    res

drawNewDiv(Pivot piv1, Pivot piv2, bool isBull, bool isHid = false)=>
    clr = switch
        not isHid => isBull ? bullDivColor : bearDivColor
        isHid => isBull ? bullHidDivColor : bearHidDivColor
    _line = line.new(x1 = piv1.ndx, x2 = piv2.ndx, y1 = piv1.indicator, y2 = piv2.indicator, color = color.new(clr, 30), width = 1)
    _label = label.new(x = piv2.ndx, y = piv2.indicator, text = "⊚︎", color = NO_COLOR, style = label.style_text_outline, size = size.small, textcolor = clr)
    divLine = DiverLine.new(_line, _label)
    arr = switch
        not isHid => isBull ? bullDivers : bearDivers
        isHid => isBull ? bullHidDivers : bearHidDivers
    arr.addDiverLine(divLine)

searchBearDiv(Pivot newPiv)=>
    result = false    
    lastIndHigh = newPiv.indicator
    if lastIndHigh > 0
        for piv in pivHigh
            if newPiv.ndx - piv.ndx >= MAX_PEAK_DIST
                break
            if piv.price > newPiv.price
                break 
            if piv.indicator > lastIndHigh
                lastIndHigh := piv.indicator
            if piv.price <= newPiv.price and piv.indicator > newPiv.indicator and piv.indicator >= lastIndHigh and (newPiv.ndx - piv.ndx >= MIN_PEAK_DIST) and piv.indicator > 50
                if isGreaterIndValue(piv.ndx, newPiv.ndx, piv.indicator) and isGreaterHigh(piv.ndx, newPiv.ndx, newPiv.price)
                    drawNewDiv(piv, newPiv, false)
                    result := true
                    break
    result

searchBullDiv(Pivot newPiv)=>
    result = false    
    newIndLow = newPiv.indicator
    if newIndLow < 0
        for piv in pivLow
            if newPiv.ndx - piv.ndx >= MAX_PEAK_DIST
                break
            if piv.price < newPiv.price
                break 
            if piv.indicator < newIndLow
                newIndLow := piv.indicator
            if piv.price >= newPiv.price and piv.indicator < newPiv.indicator and piv.indicator <= newIndLow and (newPiv.ndx - piv.ndx >= MIN_PEAK_DIST) and piv.indicator < -50
                if isLowerIndValue(piv.ndx, newPiv.ndx, piv.indicator) and isLowerLow(piv.ndx, newPiv.ndx, newPiv.price)
                    drawNewDiv(piv, newPiv, true)
                    result := true
                    break
    result

searchHidBullDiv(Pivot newPiv)=>
    result = false    
    maxSpeed = -200.0
    for piv in pivLow
        if newPiv.ndx - piv.ndx >= MAX_PEAK_DIST
            break
        speed = (newPiv.indicator - piv.indicator) / (newPiv.ndx - piv.ndx)
        if speed > maxSpeed
            maxSpeed := speed
            if piv.price <= newPiv.price and piv.indicator > newPiv.indicator and (newPiv.ndx - piv.ndx >= MIN_PEAK_DIST) and piv.indicator < 0
                if isLowerIndValue(piv.ndx, newPiv.ndx, newPiv.indicator) and isLowerLow(piv.ndx, newPiv.ndx, piv.price) and isNoCrossBelow(piv, newPiv)
                    drawNewDiv(piv, newPiv, true, true)
                    result := true
                    break
    result

searchHidBearDiv(Pivot newPiv)=>
    result = false    
    minSpeed = 200.0
    for piv in pivHigh
        if newPiv.ndx - piv.ndx >= MAX_PEAK_DIST
            break
        speed = (newPiv.indicator - piv.indicator) / (newPiv.ndx - piv.ndx)
        if speed < minSpeed
            minSpeed := speed
            if piv.price >= newPiv.price and piv.indicator < newPiv.indicator and (newPiv.ndx - piv.ndx >= MIN_PEAK_DIST) and piv.indicator > 0
                if isGreaterIndValue(piv.ndx, newPiv.ndx, newPiv.indicator) and isGreaterHigh(piv.ndx, newPiv.ndx, piv.price) and isNoCrossAbove(piv, newPiv)
                    drawNewDiv(piv, newPiv, false, true)
                    result := true
                    break
    result
//-----------------------------------------------------------------------------
//              Divergence Calcs
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{
type Point
    float   price
    int     ndx

var Point lastPh = na
var Point lastPl = na

ph = ta.pivothigh(high, PIV_LEN_LEFT, PIV_LEN_RIGHT)
pl = ta.pivotlow(low, PIV_LEN_LEFT, PIV_LEN_RIGHT)
phI = ta.pivothigh(avg, PIV_LEN_LEFT, PIV_LEN_RIGHT)
plI = ta.pivotlow(avg, PIV_LEN_LEFT, PIV_LEN_RIGHT)


if not na(ph)
    lastPh := Point.new(ph, bar_index - PIV_LEN_RIGHT)
if not na(pl)
    lastPl := Point.new(pl, bar_index - PIV_LEN_RIGHT)

if not na(phI) and barstate.isconfirmed and not na(lastPh)
    sig = phI
    sigNdx = bar_index - PIV_LEN_RIGHT
    if sigNdx - lastPh.ndx <= 2
        new = Pivot.new(lastPh.price, sigNdx, sig)
        if showDiv
            added = searchBearDiv(new)
            if added and alertBearDiv
                alert(getAlertMasg("Bear Divergence", avg), FREQ)
        if showHidDiv
            added = searchHidBearDiv(new)
            if added and alertBearHidDiv
                alert(getAlertMasg("Bear Hidden Divergence", avg), FREQ)
        addPivotHigh(new)

if not na(plI) and barstate.isconfirmed and not na(lastPl)
    sig = plI
    sigNdx = bar_index - PIV_LEN_RIGHT
    if sigNdx - lastPl.ndx <= 2
        new = Pivot.new(lastPl.price, sigNdx, sig)
        if showDiv
            added = searchBullDiv(new)
            if added and alertBullDiv
                alert(getAlertMasg("Bull Divergence", avg), FREQ)
        if showHidDiv
            added = searchHidBullDiv(new)
            if added and alertBullHidDiv
                alert(getAlertMasg("Bull Hidden Divergence", avg), FREQ)
        addPivotLow(new)

//------------------------------------------------------------------------------}

//-----------------------------------------------------------------------------
//              Take Profits
//------------------------------------------------------------------------------
//------------------------------------------------------------------------------{
const float UP_BORDER = 50
const float DN_BORDER = -50
var   Point lastIndPh = Point.new(0, 0)
var   Point lastIndPl = Point.new(0, 0)
var   int   lastSigBar = 0

indPh = ta.pivothigh(avg, 5, 5)
indPl = ta.pivotlow(avg, 5, 5)

if not na(indPh)
    lastIndPh.price := indPh
    lastIndPh.ndx := bar_index - 5
if not na(indPl)
    lastIndPl.price := indPl
    lastIndPl.ndx := bar_index - 5

speedH = (avg - lastIndPh.price) / (bar_index - lastIndPh.ndx)
speedL = (avg - lastIndPl.price) / (bar_index - lastIndPl.ndx)

sellSigRule = avg > UP_BORDER and avg > avg[2] and speedH < speedH[1]  and bar_index - lastSigBar >= 10
buySigRule  = avg < DN_BORDER and avg < avg[2] and speedL > speedL[1]  and bar_index - lastSigBar >= 10

if sellSigRule or buySigRule
    lastSigBar := bar_index


plotshape(sellSigRule and showTpSignal ? 120 : na, "Dn", style = shape.triangledown, color = rTpColor, location = location.absolute, size = size.tiny, display = display.pane)
plotshape(buySigRule and showTpSignal ? -120 : na, "Up", style = shape.triangleup,   color = gTpColor, location = location.absolute, size = size.tiny, display = display.pane)

if sellSigRule and alertBullTP
    alert(getAlertMasg("Bull TP", avg), FREQ)
if buySigRule and alertBearTP
    alert(getAlertMasg("Bear TP", avg), FREQ)

//------------------------------------------------------------------------------}
 

🛠 How to Apply the Matrix Oscillator in TradingView

  1. Open TradingView and log in.
  2. Navigate to the Pine Script Editor at the bottom of the screen.
  3. Copy and paste the provided script code.
  4. Click Save, then assign a suitable name (e.g., “Matrix Oscillator”).
  5. Click Add to Chart to visualize the indicator.
  6. Adjust input settings to match your trading style and asset preference.

💡 Additional Trading Tips

  • Combine with Trend-Following Indicators:
    Use moving averages (SMA, EMA) alongside the oscillator to confirm trend direction.
  • Avoid Overtrading in Low-Volatility Periods:
    Focus on high-liquidity sessions for better signal accuracy.
  • Backtest Before Live Trading:
    Test the indicator on historical data to understand its performance in different market conditions.

🎯 Final Thoughts

The Matrix Oscillator is an advanced tool that combines multiple momentum indicators into one, offering traders clear insights into market conditions, trend strength, and reversal opportunities. Whether you’re a day trader or a swing trader, this indicator can enhance your trading decisions with reliable signals.

However, always remember that no indicator guarantees success, and proper analysis combined with solid risk management is crucial to long-term profitability.


Gain an edge in the markets with the Matrix Oscillator – your all-in-one solution for smarter trading decisions! 🚀

RELATED POSTS

View all

view all

You cannot copy content of this page