Machine Learning Signal Filter For ThinkOrSwim

apdusp

Active member
VIP
This week I decided to test this very interesting indicator as a stop/trend.
It reminds me of a simple indicator I made years ago using the Ulcer Index, but this one is clearly more elaborated.

The author states: an innovative trading indicator designed to leverage the power of machine learning to enhance trading strategies. This tool combines advanced data processing capabilities with user-friendly customization options, offering traders a sophisticated yet accessible means to optimize their market analysis and decision-making processes. Importantly, this indicator does not repaint, ensuring that signals remain consistent and reliable after they are generated.

Machine Learning Integration

The "Machine Learning Signal Filter" employs machine learning algorithms to analyze historical price data and identify patterns that may not be immediately apparent through traditional technical analysis. By utilizing techniques such as regression analysis and neural networks, the indicator continuously learns from new data, refining its predictive capabilities over time. This dynamic adaptability allows the indicator to adjust to changing market conditions, potentially improving the accuracy of trading signals.

8iY3EXF.png

ps: on wishful thinking mode, since a table with some info is part of the original indicator, I would add to it some additional info, such as an initial date as well as the average gain/loss ($) for both, bullish and bearish trades, assuming entry/exit at close time, which might show how effective the indicator with a given setup can be.

Here is the original Tradingview code:
https://www.tradingview.com/script/QJgA4bP9-Machine-Learning-Signal-Filter/

The new ThinkOrSwim code can be found in the next post.
 
Last edited by a moderator:

Join useThinkScript to post your question to a community of 21,000+ developers and traders.

This week I decided to test this very interesting indicator as a stop/trend, particularly when I changed the setup as shown in the picture below ( I haven't explored much of changing the setup). It reminds me of a simple indicator I made years ago using the Ulcer Index, but this one is clearly more elaborated.
Would you be so kind to convert it to thinkscript?
Thanks in advance

ps: on wishful thinking mode, since a table with some info is part of the original indicator, I would add to it some additional info, such as an initial date as well as the average gain/loss ($) for both, bullish and bearish trades, assuming entry/exit at close time, which might show how effective the indicator with a given setup can be.

https://www.tradingview.com/script/QJgA4bP9-Machine-Learning-Signal-Filter/

View attachment 23094
View attachment 23093
check the below:

CSS:
# Indicator for TOS
#// @ Julien_Eche
#indicator('Machine Learning Signal Filter', '', true)
# Converted by Sam4Cok@Samer800    - 10/2024

input showBacktestLabel = yes;
input DisplaySignalCurves = no;     # 'Display Signal Curves?')
input useSignalCalculations = yes;  # 'Activate Signal Calculations?'
input useDataForSignal = yes;       # 'Use Data for Signal Generation?'
input source = close;          # 'Data Type'
input CycleWindow = 5;         # 'Chrono Window (minimum 2)'
input NormalizationLockback = 100;  # 'Temporal Normalization (range: 2 to 240)'
input NeuralPulseRate = 0.001; # (range: 0.0001 to 0.01)'
input CycleIterations = 1500;  # (range: 50 to 2000)', minval=50)
input showTradingLines = yes;
input tradeAllSignals = no;
input lot_size = 0.1; #, 'Signal Lot Size',
input minimumIntradeHolding = 5;
input takeProfitMulti = 3.5;
input stopLossMulti = 2.5;


def na = Double.NaN;
def time = GetTime();

script stellarNormalize {
    input dataStream = close;
    input dimension = 100;
    input minimum = 0;
    input maximum = 100;
    def highestValue = Highest(dataStream, dimension);
    def lowestValue  = Lowest(dataStream, dimension);
    def diff = (highestValue - lowestValue);
    def norm = (maximum - minimum) * (dataStream - lowestValue) / diff + minimum;
    plot out = norm;
}
script cyberneticRegression {
    input inputX = close;
    input inputY = close;
    input dimension = 5;
    input learningRate = 0.001;
    input iterations = 1500;
    def hypothesis = 1 / (1 + Exp(-Sum(inputX * 0.0, dimension)));
    def entropy = -1 / dimension * Sum(Sum(inputY * (Log(hypothesis) + 1 - inputY), dimension) * Log(1 - hypothesis), dimension);
    def gradient = 1 / dimension * Sum(inputX * (hypothesis - inputY), dimension);
    def weight = fold cycle = 1 to iterations with p do
                p - (learningRate * gradient);
    def forecast = 1 / (1 + (-Sum(inputX * weight, dimension)));
    plot entro = entropy;
    plot cast = forecast;
}

def syntheticStream = Log(AbsValue(Power(source, 2) - 1) + .5);
def baseInput = if useSignalCalculations then time else source;
def syntheticInput = if useSignalCalculations then source else syntheticStream;

#//**** Cybernetic Regression and Normalization ****
def entropy  = cyberneticRegression(baseInput, syntheticInput, CycleWindow, NeuralPulseRate, CycleIterations).entro;
def forecast = cyberneticRegression(baseInput, syntheticInput, CycleWindow, NeuralPulseRate, CycleIterations).cast;
def hiBase = Highest(source, NormalizationLockback);
def loBase = Lowest(source, NormalizationLockback);
def normalizedEntropy  = stellarNormalize(entropy, NormalizationLockback, loBase, hiBase);
def normalizedForecast = stellarNormalize(forecast, NormalizationLockback, loBase, hiBase);


#//**** Signal Processing ****
def filter = yes; #  // Disable additional filters
def entroCrossUp = (normalizedEntropy < normalizedForecast) and (normalizedEntropy[1] >= normalizedForecast[1]);
def entroCrossDn = (normalizedEntropy > normalizedForecast) and (normalizedEntropy[1] <= normalizedForecast[1]);
def signalBeacon = if useDataForSignal then
                   if source < normalizedEntropy and filter then -1 else
                   if source > normalizedEntropy and filter then 1 else signalBeacon[1] else
                   if entroCrossDn and filter then -1 else
                   if entroCrossUp and filter then 1 else signalBeacon[1];
def changed = signalBeacon - signalBeacon[1];
#def timeTracker = if changed then 0 else timeTracker[1] + 1;

#//**** Plotting and Alerts ****
plot NormEnteropy = if DisplaySignalCurves then normalizedEntropy else na;
plot NormForecase = if DisplaySignalCurves then normalizedForecast else na;
NormEnteropy.SetDefaultColor(Color.CYAN);
NormForecase.SetDefaultColor(Color.DARK_ORANGE);

#//**** Trade Conditions ****
def inTradeLong; def inTradeShort;
def tradeUp = if tradeAllSignals then yes else !inTradeShort[1];
def tradeDn = if tradeAllSignals then yes else !inTradeLong[1];
def startLongTrade  = tradeUp and !inTradeLong[1] and changed and signalBeacon == 1;
def startShortTrade = tradeDn and !inTradeShort[1] and changed and signalBeacon == -1;

#//**** Trade Calculations ****
def ohl3 = (open + high + low) / 3;
def tp = atr(Length = 200) * takeProfitMulti;
def sl = atr(Length = 200) * stopLossMulti;
def start_long_trade;
def cntLong; def ldiff; def wonLong; def long_trades; def slLong; def tpLong; def cntUp;
if startLongTrade {
    cntUp = 0;
    inTradeLong = yes;
    cntLong = 0;
    ldiff = 0;
    wonLong = 0;
    long_trades = 0;
    start_long_trade = open[-1];
    tpLong = open[-1] + tp;
    slLong = open[-1] - sl;
} else if (if cntUp[1]>= minimumIntradeHolding then (high >= tpLong[1]) or (close <= slLong[1]) else no) {
    cntUp = na;
    inTradeLong = no;
    cntLong = 1;
    ldiff = ohl3 - start_long_trade[1];
    wonLong = if ldiff > 0 then 1 else 0;
    long_trades = ldiff * lot_size;
    start_long_trade = na;
    tpLong = na;
    slLong = na;
    } else {
    cntUp = cntUp[1] + 1;
    inTradeLong = inTradeLong[1];
    cntLong = 0;
    ldiff = ldiff[1];
    wonLong = 0;
    long_trades = 0;
    start_long_trade = start_long_trade[1];
    tpLong = tpLong[1];
    slLong = slLong[1];
}
def start_short_trade;
def cntShort; def sdiff; def wonShort; def short_trades;def slShort; def tpShort; def cntDn;
if startShortTrade  {
    cntDn = 0;
    inTradeShort = yes;
    cntShort = 0;
    sdiff = 0;
    wonShort = 0;
    short_trades = 0;
    start_short_trade = open[-1];
    tpShort = open[-1] - tp;
    slShort = open[-1] + sl;
} else if (if cntDn[1]>=minimumIntradeHolding then (low <= tpShort[1]) or (close >= slShort[1]) else no) {
    cntDn = na;
    inTradeShort = no;
    cntShort = 1;
    sdiff = start_short_trade[1] - ohl3;
    wonShort = if sdiff > 0 then 1 else 0;
    short_trades = sdiff * lot_size;
    start_short_trade = na;
    tpShort = na;
    slShort = na;
    } else {
    cntDn = cntDn[1] + 1;
    inTradeShort = inTradeShort[1];
    cntShort = 0;
    sdiff = sdiff[1];
    wonShort = 0;
    short_trades = 0;
    start_short_trade = start_short_trade[1];
    tpShort = tpShort[1];
    slShort = slShort[1];
}
plot endLong = if long_trades[-1] then if wonLong[-1] then tpLong else slLong else na;
plot entryL = if showTradingLines and start_long_trade then start_long_trade else na;
plot tpL = if showTradingLines and tpLong then tpLong else na;
plot slL = if showTradingLines and slLong then slLong else na;

plot endShort = if short_trades[-1] then if wonShort[-1] then tpShort else slShort else na;
plot entryS = if showTradingLines and start_short_trade then start_short_trade else na;
plot tpS = if showTradingLines and tpShort then tpShort else na;
plot slS = if showTradingLines and slShort then slShort else na;

endLong.SetPaintingStrategy(PaintingStrategy.SQUARES);
endShort.SetPaintingStrategy(PaintingStrategy.SQUARES);
endLong.AssignValueColor(if wonLong[-1] then Color.CYAN else Color.MAGENTA);
endShort.AssignValueColor(if wonShort[-1] then Color.CYAN else Color.MAGENTA);
entryL.SetDefaultColor(Color.GRAY);
entryS.SetDefaultColor(Color.GRAY);
tpL.SetDefaultColor(Color.GREEN);
slL.SetDefaultColor(Color.RED);
tpS.SetDefaultColor(Color.GREEN);
slS.SetDefaultColor(Color.RED);

AddCloud(tpL, entryL, Color.DARK_GREEN);
AddCloud(entryL, slL, Color.DARK_RED);
AddCloud(entryS, tpS, Color.DARK_GREEN);
AddCloud(slS, entryS, Color.DARK_RED);

AddChartBubble(startLongTrade, low, "B", Color.GREEN, no);
AddChartBubble(startShortTrade, high, "S", Color.RED);

# Backtest
def totTradesLong  = TotalSum(if isNaN(long_trades) then 0 else long_trades);
def totTradesShort = TotalSum(if isNaN(short_trades) then 0 else short_trades);
def totWonLong = TotalSum(if isNaN(wonLong) then 0 else wonLong);
def totWonShort = TotalSum(if isNaN(wonShort) then 0 else wonShort);
def neuralReturn = totTradesLong + totTradesShort;
def tradeGalaxy = TotalSum(cntLong) + TotalSum(cntShort);
def victoryCount = totWonLong + totWonShort;
def defeatCount = if tradeGalaxy - victoryCount == 0 then 1 else tradeGalaxy - victoryCount;
def won = victoryCount / tradeGalaxy;
def wl = victoryCount / defeatCount;

AddLabel(showBacktestLabel, "Trades(" + tradeGalaxy + ")", Color.WHITE);
AddLabel(showBacktestLabel, "Return(" + AsDollars(neuralReturn) + ")", if neuralReturn>0 then Color.GREEN else Color.RED);
AddLabel(showBacktestLabel, "Win(" + AsPercent(won) + ")", if won>=0.5 then Color.GREEN else Color.RED);
AddLabel(showBacktestLabel, "Win/Los(" + AsPercent(wl) + ")", if wl>=1 then Color.GREEN else Color.RED);

#-- END of CODE
 
check the below:

CSS:
# Indicator for TOS
#// @ Julien_Eche
#indicator('Machine Learning Signal Filter', '', true)
# Converted by Sam4Cok@Samer800    - 10/2024

input showBacktestLabel = yes;
input DisplaySignalCurves = no;     # 'Display Signal Curves?')
input useSignalCalculations = yes;  # 'Activate Signal Calculations?'
input useDataForSignal = yes;       # 'Use Data for Signal Generation?'
input source = close;          # 'Data Type'
input CycleWindow = 5;         # 'Chrono Window (minimum 2)'
input NormalizationLockback = 100;  # 'Temporal Normalization (range: 2 to 240)'
input NeuralPulseRate = 0.001; # (range: 0.0001 to 0.01)'
input CycleIterations = 1500;  # (range: 50 to 2000)', minval=50)
input showTradingLines = yes;
input tradeAllSignals = no;
input lot_size = 0.1; #, 'Signal Lot Size',
input minimumIntradeHolding = 5;
input takeProfitMulti = 3.5;
input stopLossMulti = 2.5;


def na = Double.NaN;
def time = GetTime();

script stellarNormalize {
    input dataStream = close;
    input dimension = 100;
    input minimum = 0;
    input maximum = 100;
    def highestValue = Highest(dataStream, dimension);
    def lowestValue  = Lowest(dataStream, dimension);
    def diff = (highestValue - lowestValue);
    def norm = (maximum - minimum) * (dataStream - lowestValue) / diff + minimum;
    plot out = norm;
}
script cyberneticRegression {
    input inputX = close;
    input inputY = close;
    input dimension = 5;
    input learningRate = 0.001;
    input iterations = 1500;
    def hypothesis = 1 / (1 + Exp(-Sum(inputX * 0.0, dimension)));
    def entropy = -1 / dimension * Sum(Sum(inputY * (Log(hypothesis) + 1 - inputY), dimension) * Log(1 - hypothesis), dimension);
    def gradient = 1 / dimension * Sum(inputX * (hypothesis - inputY), dimension);
    def weight = fold cycle = 1 to iterations with p do
                p - (learningRate * gradient);
    def forecast = 1 / (1 + (-Sum(inputX * weight, dimension)));
    plot entro = entropy;
    plot cast = forecast;
}

def syntheticStream = Log(AbsValue(Power(source, 2) - 1) + .5);
def baseInput = if useSignalCalculations then time else source;
def syntheticInput = if useSignalCalculations then source else syntheticStream;

#//**** Cybernetic Regression and Normalization ****
def entropy  = cyberneticRegression(baseInput, syntheticInput, CycleWindow, NeuralPulseRate, CycleIterations).entro;
def forecast = cyberneticRegression(baseInput, syntheticInput, CycleWindow, NeuralPulseRate, CycleIterations).cast;
def hiBase = Highest(source, NormalizationLockback);
def loBase = Lowest(source, NormalizationLockback);
def normalizedEntropy  = stellarNormalize(entropy, NormalizationLockback, loBase, hiBase);
def normalizedForecast = stellarNormalize(forecast, NormalizationLockback, loBase, hiBase);


#//**** Signal Processing ****
def filter = yes; #  // Disable additional filters
def entroCrossUp = (normalizedEntropy < normalizedForecast) and (normalizedEntropy[1] >= normalizedForecast[1]);
def entroCrossDn = (normalizedEntropy > normalizedForecast) and (normalizedEntropy[1] <= normalizedForecast[1]);
def signalBeacon = if useDataForSignal then
                   if source < normalizedEntropy and filter then -1 else
                   if source > normalizedEntropy and filter then 1 else signalBeacon[1] else
                   if entroCrossDn and filter then -1 else
                   if entroCrossUp and filter then 1 else signalBeacon[1];
def changed = signalBeacon - signalBeacon[1];
#def timeTracker = if changed then 0 else timeTracker[1] + 1;

#//**** Plotting and Alerts ****
plot NormEnteropy = if DisplaySignalCurves then normalizedEntropy else na;
plot NormForecase = if DisplaySignalCurves then normalizedForecast else na;
NormEnteropy.SetDefaultColor(Color.CYAN);
NormForecase.SetDefaultColor(Color.DARK_ORANGE);

#//**** Trade Conditions ****
def inTradeLong; def inTradeShort;
def tradeUp = if tradeAllSignals then yes else !inTradeShort[1];
def tradeDn = if tradeAllSignals then yes else !inTradeLong[1];
def startLongTrade  = tradeUp and !inTradeLong[1] and changed and signalBeacon == 1;
def startShortTrade = tradeDn and !inTradeShort[1] and changed and signalBeacon == -1;

#//**** Trade Calculations ****
def ohl3 = (open + high + low) / 3;
def tp = atr(Length = 200) * takeProfitMulti;
def sl = atr(Length = 200) * stopLossMulti;
def start_long_trade;
def cntLong; def ldiff; def wonLong; def long_trades; def slLong; def tpLong; def cntUp;
if startLongTrade {
    cntUp = 0;
    inTradeLong = yes;
    cntLong = 0;
    ldiff = 0;
    wonLong = 0;
    long_trades = 0;
    start_long_trade = open[-1];
    tpLong = open[-1] + tp;
    slLong = open[-1] - sl;
} else if (if cntUp[1]>= minimumIntradeHolding then (high >= tpLong[1]) or (close <= slLong[1]) else no) {
    cntUp = na;
    inTradeLong = no;
    cntLong = 1;
    ldiff = ohl3 - start_long_trade[1];
    wonLong = if ldiff > 0 then 1 else 0;
    long_trades = ldiff * lot_size;
    start_long_trade = na;
    tpLong = na;
    slLong = na;
    } else {
    cntUp = cntUp[1] + 1;
    inTradeLong = inTradeLong[1];
    cntLong = 0;
    ldiff = ldiff[1];
    wonLong = 0;
    long_trades = 0;
    start_long_trade = start_long_trade[1];
    tpLong = tpLong[1];
    slLong = slLong[1];
}
def start_short_trade;
def cntShort; def sdiff; def wonShort; def short_trades;def slShort; def tpShort; def cntDn;
if startShortTrade  {
    cntDn = 0;
    inTradeShort = yes;
    cntShort = 0;
    sdiff = 0;
    wonShort = 0;
    short_trades = 0;
    start_short_trade = open[-1];
    tpShort = open[-1] - tp;
    slShort = open[-1] + sl;
} else if (if cntDn[1]>=minimumIntradeHolding then (low <= tpShort[1]) or (close >= slShort[1]) else no) {
    cntDn = na;
    inTradeShort = no;
    cntShort = 1;
    sdiff = start_short_trade[1] - ohl3;
    wonShort = if sdiff > 0 then 1 else 0;
    short_trades = sdiff * lot_size;
    start_short_trade = na;
    tpShort = na;
    slShort = na;
    } else {
    cntDn = cntDn[1] + 1;
    inTradeShort = inTradeShort[1];
    cntShort = 0;
    sdiff = sdiff[1];
    wonShort = 0;
    short_trades = 0;
    start_short_trade = start_short_trade[1];
    tpShort = tpShort[1];
    slShort = slShort[1];
}
plot endLong = if long_trades[-1] then if wonLong[-1] then tpLong else slLong else na;
plot entryL = if showTradingLines and start_long_trade then start_long_trade else na;
plot tpL = if showTradingLines and tpLong then tpLong else na;
plot slL = if showTradingLines and slLong then slLong else na;

plot endShort = if short_trades[-1] then if wonShort[-1] then tpShort else slShort else na;
plot entryS = if showTradingLines and start_short_trade then start_short_trade else na;
plot tpS = if showTradingLines and tpShort then tpShort else na;
plot slS = if showTradingLines and slShort then slShort else na;

endLong.SetPaintingStrategy(PaintingStrategy.SQUARES);
endShort.SetPaintingStrategy(PaintingStrategy.SQUARES);
endLong.AssignValueColor(if wonLong[-1] then Color.CYAN else Color.MAGENTA);
endShort.AssignValueColor(if wonShort[-1] then Color.CYAN else Color.MAGENTA);
entryL.SetDefaultColor(Color.GRAY);
entryS.SetDefaultColor(Color.GRAY);
tpL.SetDefaultColor(Color.GREEN);
slL.SetDefaultColor(Color.RED);
tpS.SetDefaultColor(Color.GREEN);
slS.SetDefaultColor(Color.RED);

AddCloud(tpL, entryL, Color.DARK_GREEN);
AddCloud(entryL, slL, Color.DARK_RED);
AddCloud(entryS, tpS, Color.DARK_GREEN);
AddCloud(slS, entryS, Color.DARK_RED);

AddChartBubble(startLongTrade, low, "B", Color.GREEN, no);
AddChartBubble(startShortTrade, high, "S", Color.RED);

# Backtest
def totTradesLong  = TotalSum(if isNaN(long_trades) then 0 else long_trades);
def totTradesShort = TotalSum(if isNaN(short_trades) then 0 else short_trades);
def totWonLong = TotalSum(if isNaN(wonLong) then 0 else wonLong);
def totWonShort = TotalSum(if isNaN(wonShort) then 0 else wonShort);
def neuralReturn = totTradesLong + totTradesShort;
def tradeGalaxy = TotalSum(cntLong) + TotalSum(cntShort);
def victoryCount = totWonLong + totWonShort;
def defeatCount = if tradeGalaxy - victoryCount == 0 then 1 else tradeGalaxy - victoryCount;
def won = victoryCount / tradeGalaxy;
def wl = victoryCount / defeatCount;

AddLabel(showBacktestLabel, "Trades(" + tradeGalaxy + ")", Color.WHITE);
AddLabel(showBacktestLabel, "Return(" + AsDollars(neuralReturn) + ")", if neuralReturn>0 then Color.GREEN else Color.RED);
AddLabel(showBacktestLabel, "Win(" + AsPercent(won) + ")", if won>=0.5 then Color.GREEN else Color.RED);
AddLabel(showBacktestLabel, "Win/Los(" + AsPercent(wl) + ")", if wl>=1 then Color.GREEN else Color.RED);

#-- END of CODE
thanks a lot @samer800 . you're the man!!
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
163 Online
Create Post

Similar threads

Similar threads

The Market Trading Game Changer

Join 2,500+ subscribers inside the useThinkScript VIP Membership Club
  • Exclusive indicators
  • Proven strategies & setups
  • Private Discord community
  • ‘Buy The Dip’ signal alerts
  • Exclusive members-only content
  • Add-ons and resources
  • 1 full year of unlimited support

Frequently Asked Questions

What is useThinkScript?

useThinkScript is the #1 community of stock market investors using indicators and other tools to power their trading strategies. Traders of all skill levels use our forums to learn about scripting and indicators, help each other, and discover new ways to gain an edge in the markets.

How do I get started?

We get it. Our forum can be intimidating, if not overwhelming. With thousands of topics, tens of thousands of posts, our community has created an incredibly deep knowledge base for stock traders. No one can ever exhaust every resource provided on our site.

If you are new, or just looking for guidance, here are some helpful links to get you started.

What are the benefits of VIP Membership?
VIP members get exclusive access to these proven and tested premium indicators: Buy the Dip, Advanced Market Moves 2.0, Take Profit, and Volatility Trading Range. In addition, VIP members get access to over 50 VIP-only custom indicators, add-ons, and strategies, private VIP-only forums, private Discord channel to discuss trades and strategies in real-time, customer support, trade alerts, and much more. Learn all about VIP membership here.
How can I access the premium indicators?
To access the premium indicators, which are plug and play ready, sign up for VIP membership here.
Back
Top