Indicator · Pine Script v6 · Own pane

Simple Decision Matrix Classification

by Nguyenthang2292

A machine-learning style indicator that classifies each bar using a decision matrix built from two chosen independent variables, such as Stochastic, RSI, Z-Score, MFI, volume or a moving-average distance.

View on GitHub

GitHub stars1on the repository
Pine versionv6current
Lines of code268
Settings14inputs
LicenceMIT
Last update6 months ago2 May 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 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

268 lines of Pine Script v6 from modules/decision_matrix/source_pine.txt, published under MIT. Keep the author's credit and licence lines when you reuse it.

source_pine.txt
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
//  /$$$$$$   /$$                                                         /$$                                            
// /$$__  $$ | $$                                                        | $$                                            
//| $$  \__//$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$   /$$$$$$$ /$$$$$$    /$$$$$$  /$$    /$$ /$$$$$$   /$$$$$$$
//|  $$$$$$|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$__  $$ /$$_____/|_  $$_/   /$$__  $$|  $$  /$$//$$__  $$ /$$_____/
// \____  $$ | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$| $$  \__/|  $$$$$$   | $$    | $$$$$$$$ \  $$/$$/| $$$$$$$$|  $$$$$$ 
// /$$  \ $$ | $$ /$$| $$_____/  \  $$$/ | $$_____/| $$       \____  $$  | $$ /$$| $$_____/  \  $$$/ | $$_____/ \____  $$
//|  $$$$$$/ |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$| $$       /$$$$$$$/  |  $$$$/|  $$$$$$$   \  $/  |  $$$$$$$ /$$$$$$$/
// \______/   \___/   \_______/    \_/    \_______/|__/      |_______/    \___/   \_______/    \_/    \_______/|_______/ 

//@version=6
indicator("Simple Decision Matrix Classification Algorithm [SS]", shorttitle = "DMCA [SS]", overlay=false)
g1 = "Model Parameters",
g2 = "EMA"
g3 = "RSI"
g4 = "MFI"
g5 = "Z-Score"
g6 = "ATR"
training = input.int(850, "Training Length", group = g1)
select_x1 = input.string("Stochastic", "Select Independent Variable X1", ["Stochastic", "RSI", "Z-Score", "MFI", "Volume", "EMA", "SMA"], group = g1)
select_x2 = input.string("Volume", "Select Independent Variable X1", ["Stochastic", "RSI", "Z-Score", "MFI", "Volume", "EMA", "SMA"], group = g1)
select_y = input.string("Red/Green Candle", "Select desired target Classification Prediction", ["Red/Green Candle", "Bullish / Bearish ATR", "ATR Range Breakout"], group = g1)
showtable = input.bool(true, "Show Table", group = g1)
// EMA 
emalen = input.int(14, "EMA/SMA Length", group = g2),   emasrc = input.source(close, "EMA/ SMA Source", group = g2)
// RSI 
rsilen = input.int(14, "RSI Length", group = g3),       rsisrc = input.source(close, "RSI Source", group = g3)
// MFI 
mfilen = input.int(14, "MFI Length", group = g4),       mfisrc = input.source(hlc3, "MFI Source", group = g4)
// Z-Score
zlen = input.int(14, "Z-Score Length", group = g5),     zsrc = input.source(close, "Z-Score Source", group = g5)
// atr 
atrlen = input.int(14, "ATR Length", group = g6)



atr = ta.atr(atrlen)
sent = close > open ? 1 : 0
sentiment = high - open > open - low ? 1 : 0 
rsi = ta.rsi(rsisrc, rsilen) 
sto = ta.stoch(close, high, low, 14) 
mfi = ta.mfi(mfisrc, mfilen)
z = (zsrc - ta.sma(zsrc,zlen)) / ta.stdev(zsrc, zlen)
ema = ta.ema(emasrc, emalen)
sma = ta.sma(emasrc, emalen)
atr_breakout = high-open > atr or open-low < atr ? 1 : 0 

float x1_input = switch select_x1 
    "Stochastic" => sto 
    "RSI" => rsi 
    "Z-Score" => z 
    "MFI" => mfi 
    "Volume" => volume
    "EMA" => close - ema 
    "SMA" => close - sma 
float x2_input = switch select_x2
    "Stochastic" => sto 
    "RSI" => rsi 
    "Z-Score" => z 
    "MFI" => mfi 
    "Volume" => volume
    "EMA" => close - ema 
    "SMA" => close - sma 
float y_input = switch select_y
    "Red/Green Candle" => sent 
    "Bullish / Bearish ATR" => sentiment 
    "ATR Range Breakout" => atr_breakout 

float x1_threshold = 0
float x2_threshold = 0 
if select_x1 == "Volume"
    x1_threshold := ta.stdev(volume, 14) 
else  if select_x1 == "Z-Score"
    x1_threshold := 0.05
else 
    x1_threshold := 0.5

if select_x2 == "Volume" 
    x2_threshold := ta.stdev(volume, 14) 
else if select_x2 == "Z-Score"
    x2_threshold := 0.05
else 
    x2_threshold := 0.5
// Function to shuffle a list of indices
shuffle_indices(n) =>
    indices = array.new_int(n)
    for i = 0 to n - 1
        array.set(indices, i, i)
    for i = 0 to n - 1
        rand_index = math.floor(math.random(0, n))
        temp = array.get(indices, i)
        array.set(indices, i, array.get(indices, rand_index))
        array.set(indices, rand_index, temp)
    indices

// Function to shuffle the rows of a matrix
shuffle_matrix(matrix, rows) =>
    shuffled_matrix = matrix.new<float>(rows, matrix.columns(matrix), 0)
    indices = shuffle_indices(rows)
    for i = 0 to rows - 1
        for j = 0 to matrix.columns(matrix) - 1
            matrix.set(shuffled_matrix, i, j, matrix.get(matrix, array.get(indices, i), j))
    shuffled_matrix

radnom_forest_classification(x1, x2, y, train) => 
    x1m = matrix.new<float>(train , 2, 0)
    x2m = matrix.new<float>(train, 2, 0) 
    lx1 = x1[1]
    lx2 = x2[1]
    ly = y
    for i = 0 to train - 1
        matrix.set(x1m, i, 0, lx1[i])
        matrix.set(x1m, i, 1, ly[i])
        matrix.set(x2m, i, 0, lx2[i])
        matrix.set(x2m, i, 1, ly[i])
    x1m_random = shuffle_matrix(x1m, train)
    x2m_random = shuffle_matrix(x2m, train)
    int y1_pass = 0 
    int y1_fail = 0 
    for i = 0 to train - 2
        if matrix.get(x1m_random, i, 0) > 0
            if matrix.get(x1m_random, i, 0) >= x1 - x1_threshold and matrix.get(x1m_random, i, 0) <= x1 + x1_threshold
                if matrix.get(x1m_random, i, 1) == 1 
                    y1_pass += 1 
                else if matrix.get(x1m_random, i, 1) != 1 
                    y1_fail += 1 
    int y2_pass = 0 
    int y2_fail = 0 
    int x1_vote = y1_pass > y1_fail ? 1 : 0 
    for i = 0 to train - 2 
        if matrix.get(x2m_random, i, 0) >= x2 - x2_threshold and matrix.get(x2m_random, i, 0) <= x2 + x2_threshold
            if matrix.get(x2m_random, i, 1) == 1 
                y2_pass += 1 
            else if matrix.get(x2m_random, i, 1) != 1 
                y2_fail += 1 
    passes = y1_pass + y2_pass 
    
    fails = y1_fail + y2_fail 
    vote = passes > fails ? 1 : 0 
    x2_vote = y2_pass > y2_fail ? 1 : 0 
    // X1 independent accuracy 
    int x1_ia_pass = 0 
    int x1_ia_fail = 0 
    int x2_ia_pass = 0 
    int x2_ia_fail = 0
    x2_vote_pass = x2_vote == y 
    x1_vote_pass = x1_vote == y 
    for i = 0 to train 
        if x1_vote_pass[i]
            x1_ia_pass += 1 
        else 
            x1_ia_fail += 1 
        if x2_vote_pass[i]
            x2_ia_pass += 1 
        else 
            x2_ia_fail += 1 

    x1_accuracy = x1_ia_pass / (x1_ia_pass + x1_ia_fail) * 100 
    x2_accuracy = x2_ia_pass / (x2_ia_pass + x2_ia_fail) * 100 
    // Accuracy 
    int success = 0 
    int failure = 0 
    for i = 0 to train - 1
        if vote[i] == y[i]  
            success += 1 
        else if vote[i] != y[i] 
            failure += 1 
    accurcay = success / (success + failure) * 100 

    [vote, accurcay, y1_pass, y1_fail, y2_pass, y2_fail, x1_vote, x2_vote, x1_accuracy, x2_accuracy] 


[result, acc, y1p, y1f, y2p, y2f, x1v, x2v, x1a, x2a] = radnom_forest_classification(x1_input, x2_input, y_input, training)

// Demographics 

total_sorted_cases_x1 = y1p + y1f 
total_sorted_cases_x2 = y2p + y2f 
x1_voted_result = y1p > y1f ? 1 : 0 
x2_voted_result = y2p > y2f ? 1 : 0 
total_cases = total_sorted_cases_x1 + total_sorted_cases_x2 
x1_total_weight = (total_sorted_cases_x1 / total_cases) * 100
x2_total_weight = (total_sorted_cases_x2 / total_cases) * 100 

string_Result = result == 1 ? "Bullish" : "Bearish" 

if barstate.islast 
    for lin in line.all
        line.delete(lin) 
    for txt in label.all
        label.delete(txt) 

// Feature Importance 

feature_importance_color(current_variable, other_variable) => 
    color feature_color = na 
    if current_variable > other_variable 
        if current_variable <= 45 
            feature_color := color.rgb(5, 46, 7)
        else if current_variable > 45 and current_variable <= 55 
            feature_color := color.rgb(10, 99, 14)
        else if current_variable > 55 
            feature_color := color.rgb(5, 235, 15)
    else if other_variable > current_variable 
        if  current_variable > 50 and current_variable <= 55 
            feature_color := color.rgb(22, 110, 26)
        else if current_variable > 55 
            feature_color := color.rgb(5, 235, 15)
        else if current_variable <= 50 and current_variable > 45 
            feature_color := color.rgb(89, 6, 31)
        else if current_variable <= 45 
            feature_color := color.rgb(247, 0, 75)
    feature_color 
if barstate.islast 
    label.new(bar_index - 200, y = 20, text = str.tostring(select_x1), color = feature_importance_color(x1a, x2a), style = label.style_circle, size = size.large)
    label.new(bar_index - 250, y = 10, text = str.tostring(y1p), color = color.lime, style = label.style_circle, size = size.large)
    label.new(bar_index - 150, y = 10, text = str.tostring(y1f), color = color.red, style = label.style_circle, size = size.large)
    label.new(bar_index - 200, y = 0, text = str.tostring(x1v), color = color.purple, style = label.style_circle, size = size.large)
    line.new(bar_index - 200, y1 = 20, x2 = bar_index - 250, y2 = 10, color = color.gray, width = 3)
    line.new(bar_index - 250, y1 = 10, x2 = bar_index - 200, y2 = 0, color = color.gray, width = 3)
    line.new(bar_index - 200, y1 = 20, x2 = bar_index - 150, y2 = 10, color = color.gray, width = 3)
    line.new(bar_index - 150, y1 = 10, x2 = bar_index - 200, y2 = 0, color = color.gray, width = 3)
    line.new(bar_index, y1 = 20, x2 = bar_index - 50, y2 = 10, color = color.gray, width = 3)
    line.new(bar_index - 50, y1 = 10, x2 = bar_index, y2 = 0, color = color.gray, width = 3)
    line.new(bar_index, y1 = 20, x2 = bar_index + 50, y2 = 10, color = color.gray, width = 3)
    line.new(bar_index + 50, y1 = 10, x2 = bar_index, y2 = 0, color = color.gray, width = 3)
    label.new(bar_index, y = 20, text = str.tostring(select_x2), color = feature_importance_color(x2a, x1a), style = label.style_circle, size = size.large)
    label.new(bar_index - 50, y = 10, text = str.tostring(y2p), color = color.lime, style = label.style_circle, size = size.large)
    label.new(bar_index + 50, y = 10, text = str.tostring(y2f), color = color.red, style = label.style_circle, size = size.large)
    label.new(bar_index, y = 0, text = str.tostring(x2v), color = color.purple, style = label.style_circle, size = size.large)
    label.new(bar_index - 100, y = - 10,  text = str.tostring(result), color = color.orange, style = label.style_circle, size = size.large)
    line.new(bar_index - 200, y1 = 0, x2 = bar_index - 100, y2 = -10, color = color.gray, width = 3)
    line.new(bar_index, y1 = 0, x2 = bar_index - 100, y2 = -10, color = color.gray, width = 3)
    label.new(bar_index - 100, y = 30, text = str.tostring(select_y), color = color.navy, style = label.style_circle, size = size.large)
    line.new(bar_index - 100, y1 = 30, x2 = bar_index - 200, y2 = 20, color = color.gray, width = 3)
    line.new(bar_index - 100, y1 = 30, x2 = bar_index, y2 = 20, color = color.gray, width = 3)
    
data = table.new(position.middle_left, 10, 10, bgcolor = color.rgb(0, 0, 0), frame_color = color.white, frame_width = 3) 

if showtable
    table.merge_cells(data, 1, 0, 2, 0)
    table.merge_cells(data, 3, 0, 4, 0)
    table.cell(data, 1, 0, text = str.tostring(select_x1), bgcolor = color.new(color.gray, 75), text_color = color.white, text_halign = text.align_center) 
    table.cell(data, 3, 0, text = str.tostring(select_x2), bgcolor = color.new(color.gray, 75), text_color = color.white, text_halign = text.align_center) 
    table.cell(data, 1, 1, text = "X1 Independent: ", text_color = color.white) 
    table.cell(data, 2, 1, text = str.tostring(select_x1), text_color = color.white)
    table.cell(data, 1, 2, text = "X1 Total Sorted Cases: ", text_color = color.white) 
    table.cell(data, 2, 2, text = str.tostring(total_sorted_cases_x1), text_color = color.white)
    table.cell(data, 1, 2, text = "X1 Weighted Impact: ", text_color = color.white) 
    table.cell(data, 2, 2, text = str.tostring(math.round(x1_total_weight, 2)), text_color = color.white)
    table.cell(data, 1, 3, text = "X1 Independent Accuracy: ", text_color = color.white) 
    table.cell(data, 2, 3, text = str.tostring(math.round(x1a, 2)) + "%", text_color = color.white)
    table.cell(data, 1, 4, text = "X1 Voted Result: ", text_color = color.white) 
    table.cell(data, 2, 4, text = str.tostring(x1_voted_result), text_color = color.white)
    table.cell(data, 3, 1, text = "X2 Independent: ", text_color = color.white) 
    table.cell(data, 4, 1, text = str.tostring(select_x2), text_color = color.white)
    table.cell(data, 3, 2, text = "X2 Total Sorted Cases: ", text_color = color.white) 
    table.cell(data, 4, 2, text = str.tostring(total_sorted_cases_x2), text_color = color.white)
    table.cell(data, 3, 2, text = "X2 Weighted Impact: ", text_color = color.white) 
    table.cell(data, 4, 2, text = str.tostring(math.round(x2_total_weight, 2)), text_color = color.white)
    table.cell(data, 3, 3, text = "X2 Independent Accuracy: ", text_color = color.white) 
    table.cell(data, 4, 3, text = str.tostring(math.round(x2a, 2)) + "%", text_color = color.white)
    table.cell(data, 3, 4, text = "X2 Voted Result: ", text_color = color.white) 
    table.cell(data, 4, 4, text = str.tostring(x2_voted_result), text_color = color.white)
    table.merge_cells(data, 1, 5, 4, 5)
    table.cell(data, 1, 5, text = "Model Accuracy: " + str.tostring(math.round(acc, 2)), text_color = color.white, text_halign = text.align_center) 
    table.merge_cells(data, 1, 6, 4, 6)
    table.cell(data, 1, 6, text = "Model Prediction: " + str.tostring(string_Result), text_color = color.white, text_halign = text.align_center)

Overview

The target to predict can be red or green candle, bullish or bearish ATR move, or ATR range breakout. A training length sets the history used, and a table can display the results. It draws in a separate pane and issues no trade orders.

Details

Published by

Nguyenthang2292 on GitHub

Type

Indicator, Pine Script v6

Draws

Separate pane below the chart

Category

AI / machine learning, Oscillators & momentum

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

algorithmic-tradingbacktesting-enginefinancial-analysisfintechquantitative-tradingtradingbot

Settings

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

SettingTypeDefaultVariable
Training Lengthint850training
Select Independent Variable X1stringStochasticselect_x1
Select Independent Variable X1stringVolumeselect_x2
Select desired target Classification PredictionstringRed/Green Candleselect_y
Show Tablebooltrueshowtable
EMA/SMA Lengthint14emalen
EMA/ SMA Sourcesourcecloseemasrc
RSI Lengthint14rsilen
RSI Sourcesourceclosersisrc
MFI Lengthint14mfilen
MFI Sourcesourcehlc3mfisrc
Z-Score Lengthint14zlen
Show all 14 settings
SettingTypeDefaultVariable
Z-Score Sourcesourceclosezsrc
ATR Lengthint14atrlen
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 indicator combines a dynamic Seasonal Random Index (SRI) with a dynamic Karobein Oscillator and a pattern-similarity search algorithm in a separate pane. It normalizes SRI into seasoned and deseasoned series, shading the area green or red to signal trend

Indicator v4 Oscillators & momentumTrend
Updated 1 year ago · None stated GitHub repository of Similarity Search, Karobein and Seasonal Random Index

This indicator plots an oscillator in a separate pane. It builds several SuperTrend series across a user-defined factor range and step, using ATR as the band width. On each bar it measures the distance between the close and each SuperTrend output, then groups

Indicator v5 TrendVolatility & bands
Updated 2 years ago · GPL-3.0 GitHub repository of AI SuperTrend Clustering Oscillator [LuxAlgo]
7 stars

Lorentzian Classification is a machine learning indicator that applies a k-nearest neighbors algorithm using Lorentzian distance to analyze market patterns. It processes configurable technical indicators, including RSI, WaveTrend, CCI, and ADX, as feature vect

Indicator v6 AI / machine learningOscillators & momentum
Updated 1 year ago · MPL-2.0 GitHub repository of Lorentzian Classification
2 stars

The ANN MACD Future Forecast is an experimental indicator serving as a true deep learning sample on TradingView. It calculates Bollinger Bands and Squeeze Momentum using custom functions for SMA, EMA, standard deviation, highest and lowest values. The script p

Indicator v4 AI / machine learningVolatility & bands
Updated 7 years ago · MIT GitHub repository of ANN MACD Future Forecast (SPY 1D)

This indicator plots an optimal RSI in a separate pane and uses a k-nearest neighbour machine learning routine to adjust lookback and RSI count. It can mark RSI crossings, draw adaptive Bollinger bands around the RSI, and show tables of current settings. Users

Indicator v5 Oscillators & momentumVolatility & bands
Updated 2 years ago · None stated GitHub repository of Machine Learning: Optimal RSI [YinYangAlgorithms]

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