DMI Crossover Alerts with Sequential Condition

ridingthewav

New member
Plus
I am looking to create an alert with a specific sequential condition: The alert should trigger only when two events occur in order.

First, the DI- (Directional Indicator minus) and DI+ (Directional Indicator plus) lines must cross each other. Following this event, and only if it occurs first, the second condition that must be met is the crossing of the ADX (Average Directional Index) line above a predefined level known as the 'Level Trend'. The alert is designed to activate only when these two conditions are fulfilled in this exact sequence.

I tried with ChatGPT4 but the alert isn't triggering or sounding. Can someone tell me what I'm doing wrong and identify a solution?

The relevant part is here:
Code:
# Define a flag that turns on after DI- and DI+ cross and stays on for one bar
def crossFlag = if crossDi then 1 else if crossFlag[1] == 1 then 0 else crossFlag[1];

# Define the ADX crossing condition separately
def adxCrossingAboveTrend = adx crosses above Level_Trend;

# Now check if the ADX crossing happens after the DI cross
def alertCondition = crossFlag[1] == 1 and adxCrossingAboveTrend;

# The Alert function will then use this condition
Alert(alertCondition and alertOn, "Sequential Alert: DI- and DI+ crossed followed by ADX crossing above Level_Trend", Alert.Bar, Sound.Chimes);


Here's the full script:
Code:
# https://my.tradingview.com/script/RNcqYq6w-ADX-Di-Di-Gu5/
# This source code is subject to these terms:
#// You are free to:
#// Share, copy and redistribute this script
#// Adapt, transform and build on this script.
#// Under the following terms:
#// NonCommercial: You may not use the material for commercial purposes.
#// Attribution: You must give appropriate credit
#// https://www.safecreative.org/work/2302153511401-adx-di-di-gu5-
#// © gu5tavo71 (Gustavo Cardelle)
#indicator(title = 'ADX Di+ Di- [Gu5]', shorttitle = 'ADX', overlay = false,
#// Indicator to helps determine the strength of a trend
#// Average Directional movement indeX (ADX) Developed by J. Welles
#// This script reuses open source code from another authors:
#// @PineCoders, Built-in Library, and Community Scripts
#// Disclaimer: I am not a financial advisor.
#//             For purpose educate only. Use at your own risk.
# Converted by Sam4Cok@Samer800 - 03/2023
declare lower;
#// ——————————— <inputs> {
input adxSmoothing = 7;#        'ADX Smoothing'
input diLength     = 7;#        'DI Length'
input Level_Range  = 25;#       'Level Range'
input Level_Trend  = 50;#       'Level Trend'
input Level_Upper  = 75;#       'Level Upper'     
input alertOn      = yes;#      "Alert On/Off"
input barColor     = yes;#      "Bar Color On/Off"

def na = Double.NaN;
def last = isNaN(close);
def isconfirmed = !IsNaN(close);
#--- Color---
DefineGlobalColor("green"  , CreateColor(0, 100, 0));
DefineGlobalColor("lgreen" , CreateColor(56,142,60));
DefineGlobalColor("red"    , CreateColor(139,0,0));
DefineGlobalColor("lred"   , CreateColor(183,28,28));
DefineGlobalColor("orange" , CreateColor(255,152,0));

DefineGlobalColor("cgreen"  , CreateColor(0,61,0));
DefineGlobalColor("clgreen" , CreateColor(39,100,42));
DefineGlobalColor("cred"    , CreateColor(61,0,0));
DefineGlobalColor("clred"   , CreateColor(149,23,23));
DefineGlobalColor("corange" , CreateColor(118, 70, 0));

# function_declarations> {
script nz {
    input data  = close;
    def ret_val = if !isNaN(data) then data else 0;
    plot return = ret_val;
}
script fixnan {
    input source = close;
    def fix = if !IsNaN(source) then source else fix[1];
    plot result = fix;
}
#f_dirMov(_len) =>
script f_dirMov {
    input _len = 14;
    def _up        = (high - high[1]);
    def _down      = -(low - low[1]);
    def _plusDM    = if IsNaN(_up) then Double.NaN else if _up > _down and _up   > 0 then _up else 0;
    def _minusDM   = if IsNaN(_down) then Double.NaN else if _down > _up and _down > 0 then _down else 0;
    def tr = TrueRange(high, close, low);
    def _trueRange = WildersAverage(tr, _len);
    def _plus      = (100 * WildersAverage(_plusDM,  _len) / _trueRange);
    def _minus     = (100 * WildersAverage(_minusDM, _len) / _trueRange);
    def plus_      = if isNaN(_plus) then plus_[1] else _plus;
    def minus_     = if isNaN(_minus) then minus_[1] else _minus;
    plot plus = plus_;
    plot min  = minus_;
}
#f_sig(_diLen, _sigLen) =>
script f_sig {
    input _diLen = 14;
    input _sigLen = 14;
    def _plus = f_dirMov(_diLen).plus;
    def _minus = f_dirMov(_diLen).min;
    def _sum = _plus + _minus;
    def _sig = 100 * WildersAverage(AbsValue(_plus - _minus) / (if _sum == 0 then 1 else _sum), _sigLen);
    plot out = _sig;
}
#— <calculations> {
#//<set initial values>
def condition;#    = 0.0

def sig = f_sig(diLength, adxSmoothing);
def diPlus = f_dirMov(diLength).plus;
def diMinus = f_dirMov(diLength).min;

def hlRange     = sig     <= Level_Range;
def diUp        = diPlus  >= diMinus;
def diUpUp      = diPlus  >= Level_Trend;
def diDn        = diMinus >  diPlus;
def diDnDn      = diMinus >  Level_Trend;

def crossDi     = (diPlus>diMinus and diPlus[1]<=diMinus[1]) or (diPlus<diMinus and diPlus[1]>=diMinus[1]);
def sigUp       = sig > sig[1];
def sigDir      = if sig > sig[1] and diUp and !hlRange then 1 else
                  if sig > sig[1] and diDn and !hlRange then -1 else 0;
#//Rules
def entryLong    = !hlRange and diUp and sigUp and !diUp[1] or
                   !hlRange and diUp and sigUp and sig > Level_Range and hlRange[1];
def entryShort   = !hlRange and diDn and sigUp and !diDn[1] or
                   !hlRange and diDn and sigUp and sig > Level_Range and hlRange[1];
def entryLongStr = !hlRange and diUp and sigUp and diUpUp;
def entryShortSt = !hlRange and diDn and sigUp and diDnDn;
def exitLong     = crossDi and diUp[1] or hlRange and !hlRange[1];
def exitShort    = crossDi and diDn[1] or hlRange and !hlRange[1];
condition   = if condition[1] !=  1   and entryLongStr then 1 else
              if condition[1] != -1   and entryShortSt then -1 else
              if condition[1] != 0.5 and entryLong    then 0.5 else
              if condition[1] != -0.5 and entryShort  then -0.5 else
              if condition[1] !=  0   and exitLong    then 0  else
              if condition[1] !=  0   and exitShort   then 0  else nz(condition[1]);
def longE     = isconfirmed and
               condition[1] !=  0.5 and condition ==    0.5;
def shortE    = isconfirmed and
               condition[1] != -0.5 and condition ==   -0.5;
def longEStr  = isconfirmed and
               condition[1] !=  1   and condition ==    1;
def shortEStr = isconfirmed and
               condition[1] != -1   and condition ==   -1;
def longX     = isconfirmed and
             ((condition[1] ==  0.5 and condition ==    0) or
              (condition[1] ==  1   and condition ==    0));
def shortX    = isconfirmed and
             ((condition[1] == -0.5 and condition ==    0) or
              (condition[1] == -1   and condition ==    0));
#//<color>
def c_sig    = if hlRange then 0 else
               if sigUp   and diUp then 2 else
               if !sigUp  and diUp then 1 else
               if sigUp   and diDn then -2 else
               if !sigUp  and diDn then -1 else na;
def c_Adx    = if hlRange then 0 else
               if !hlRange and diUp and diUpUp  then 2 else
               if !hlRange and diUp and !diUpUp then 1 else
               if !hlRange and diDn and diDnDn then -2 else
               if !hlRange and diDn and !diDnDn then -1 else na;

#// ——————————— <plots> {
plot adx = if last or isNaN(c_sig) then na else sig;
adx.SetLineWeight(3);
adx.AssignValueColor(if c_sig==0 then GlobalColor("orange") else
                     if c_sig==2 then GlobalColor("green") else
                     if c_sig==1 then GlobalColor("lgreen") else
                     if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

plot p_diPlus     = if last then na else diPlus;
p_diPlus.SetDefaultColor(GlobalColor("green"));

plot p_diMinus    = if last then na else diMinus;
p_diMinus.SetDefaultColor(GlobalColor("red"));

AddCloud(if isNaN(c_Adx) then na else if c_Adx==0 then p_diPlus else na, p_diMinus, GlobalColor("corange"),GlobalColor("corange"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==2 then p_diPlus else na, p_diMinus, GlobalColor("cgreen"),GlobalColor("cgreen"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==1 then p_diPlus else na, p_diMinus, GlobalColor("clgreen"),GlobalColor("clgreen"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==-2 then p_diPlus else na, p_diMinus, GlobalColor("cred"),GlobalColor("cred"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==-1 then p_diPlus else na, p_diMinus, GlobalColor("clred"),GlobalColor("clred"));

plot LevelRange = if last then na else Level_Range;
LevelRange.SetDefaultColor(Color.GRAY);
LevelRange.SetPaintingStrategy(PaintingStrategy.DASHES);

plot LevelTrend = if last then na else Level_Trend;
LevelTrend.SetDefaultColor(Color.GRAY);
LevelTrend.SetPaintingStrategy(PaintingStrategy.DASHES);

plot LevelUpper = if last then na else Level_Upper;
LevelUpper.SetDefaultColor(Color.GRAY);
LevelUpper.SetPaintingStrategy(PaintingStrategy.DASHES);

AssignPriceColor(if !barColor or isNaN(c_sig) then Color.CURRENT else
                 if c_sig==0 then GlobalColor("orange") else
                 if c_sig==2 then GlobalColor("green") else
                 if c_sig==1 then GlobalColor("lgreen") else
                 if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

#// ——————————— <alerts> {
plot Bullish = if alertOn and longE then Level_Trend + 10 else na;
Bullish.SetDefaultColor(GlobalColor("green"));
Bullish.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#  style      = shape.triangleup,
#  size       = size.tiny,
#  location   = location.absolute)
plot Bearish = if alertOn and shortE then Level_Trend + 10 else na;
Bearish.SetDefaultColor(GlobalColor("red"));
Bearish.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#  style      = shape.triangledown,
#  size       = size.tiny,
#  location   = location.absolute)
plot StrongBull = if alertOn and longEStr then Level_Trend + 10 else na;
StrongBull.SetDefaultColor(GlobalColor("green"));
StrongBull.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
StrongBull.SetLineWeight(3);
#  style      = shape.triangleup,
#  size       = size.small,
#  location   = location.absolute)
plot StrongBear = if alertOn and shortEStr then Level_Trend + 10 else na;
StrongBear.SetDefaultColor(GlobalColor("red"));
StrongBear.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
StrongBear.SetLineWeight(3);
#  style      = shape.triangledown,
#  size       = size.small,
#  location   = location.absolute)
plot EndTrend = if alertOn and (longX or shortX) then Level_Trend + 10 else na;
EndTrend.SetDefaultColor(GlobalColor("orange"));
EndTrend.SetPaintingStrategy(PaintingStrategy.SQUARES);
EndTrend.SetLineWeight(3);
#  style      = shape.xcross,
#  size       = size.small,
#  location   = location.absolute)


# Define a flag that turns on after DI- and DI+ cross and stays on for one bar
def crossFlag = if crossDi then 1 else if crossFlag[1] == 1 then 0 else crossFlag[1];

# Define the ADX crossing condition separately
def adxCrossingAboveTrend = adx crosses above Level_Trend;

# Now check if the ADX crossing happens after the DI cross
def alertCondition = crossFlag[1] == 1 and adxCrossingAboveTrend;

# The Alert function will then use this condition
Alert(alertCondition and alertOn, "Sequential Alert: DI- and DI+ crossed followed by ADX crossing above Level_Trend", Alert.Bar, Sound.Chimes);

#-- END of Code
 
Solution
I am looking to create an alert with a specific sequential condition: The alert should trigger only when two events occur in order.

First, the DI- (Directional Indicator minus) and DI+ (Directional Indicator plus) lines must cross each other. Following this event, and only if it occurs first, the second condition that must be met is the crossing of the ADX (Average Directional Index) line above a predefined level known as the 'Level Trend'. The alert is designed to activate only when these two conditions are fulfilled in this exact sequence.

I tried with ChatGPT4 but the alert isn't triggering or sounding. Can someone tell me what I'm doing wrong and identify a solution?

The relevant part is here:
Code:
# Define a flag that turns...
I am looking to create an alert with a specific sequential condition: The alert should trigger only when two events occur in order.

First, the DI- (Directional Indicator minus) and DI+ (Directional Indicator plus) lines must cross each other. Following this event, and only if it occurs first, the second condition that must be met is the crossing of the ADX (Average Directional Index) line above a predefined level known as the 'Level Trend'. The alert is designed to activate only when these two conditions are fulfilled in this exact sequence.

I tried with ChatGPT4 but the alert isn't triggering or sounding. Can someone tell me what I'm doing wrong and identify a solution?

The relevant part is here:
Code:
# Define a flag that turns on after DI- and DI+ cross and stays on for one bar
def crossFlag = if crossDi then 1 else if crossFlag[1] == 1 then 0 else crossFlag[1];

# Define the ADX crossing condition separately
def adxCrossingAboveTrend = adx crosses above Level_Trend;

# Now check if the ADX crossing happens after the DI cross
def alertCondition = crossFlag[1] == 1 and adxCrossingAboveTrend;

# The Alert function will then use this condition
Alert(alertCondition and alertOn, "Sequential Alert: DI- and DI+ crossed followed by ADX crossing above Level_Trend", Alert.Bar, Sound.Chimes);


Here's the full script:
Code:
# https://my.tradingview.com/script/RNcqYq6w-ADX-Di-Di-Gu5/
# This source code is subject to these terms:
#// You are free to:
#// Share, copy and redistribute this script
#// Adapt, transform and build on this script.
#// Under the following terms:
#// NonCommercial: You may not use the material for commercial purposes.
#// Attribution: You must give appropriate credit
#// https://www.safecreative.org/work/2302153511401-adx-di-di-gu5-
#// © gu5tavo71 (Gustavo Cardelle)
#indicator(title = 'ADX Di+ Di- [Gu5]', shorttitle = 'ADX', overlay = false,
#// Indicator to helps determine the strength of a trend
#// Average Directional movement indeX (ADX) Developed by J. Welles
#// This script reuses open source code from another authors:
#// @PineCoders, Built-in Library, and Community Scripts
#// Disclaimer: I am not a financial advisor.
#//             For purpose educate only. Use at your own risk.
# Converted by Sam4Cok@Samer800 - 03/2023
declare lower;
#// ——————————— <inputs> {
input adxSmoothing = 7;#        'ADX Smoothing'
input diLength     = 7;#        'DI Length'
input Level_Range  = 25;#       'Level Range'
input Level_Trend  = 50;#       'Level Trend'
input Level_Upper  = 75;#       'Level Upper'   
input alertOn      = yes;#      "Alert On/Off"
input barColor     = yes;#      "Bar Color On/Off"

def na = Double.NaN;
def last = isNaN(close);
def isconfirmed = !IsNaN(close);
#--- Color---
DefineGlobalColor("green"  , CreateColor(0, 100, 0));
DefineGlobalColor("lgreen" , CreateColor(56,142,60));
DefineGlobalColor("red"    , CreateColor(139,0,0));
DefineGlobalColor("lred"   , CreateColor(183,28,28));
DefineGlobalColor("orange" , CreateColor(255,152,0));

DefineGlobalColor("cgreen"  , CreateColor(0,61,0));
DefineGlobalColor("clgreen" , CreateColor(39,100,42));
DefineGlobalColor("cred"    , CreateColor(61,0,0));
DefineGlobalColor("clred"   , CreateColor(149,23,23));
DefineGlobalColor("corange" , CreateColor(118, 70, 0));

# function_declarations> {
script nz {
    input data  = close;
    def ret_val = if !isNaN(data) then data else 0;
    plot return = ret_val;
}
script fixnan {
    input source = close;
    def fix = if !IsNaN(source) then source else fix[1];
    plot result = fix;
}
#f_dirMov(_len) =>
script f_dirMov {
    input _len = 14;
    def _up        = (high - high[1]);
    def _down      = -(low - low[1]);
    def _plusDM    = if IsNaN(_up) then Double.NaN else if _up > _down and _up   > 0 then _up else 0;
    def _minusDM   = if IsNaN(_down) then Double.NaN else if _down > _up and _down > 0 then _down else 0;
    def tr = TrueRange(high, close, low);
    def _trueRange = WildersAverage(tr, _len);
    def _plus      = (100 * WildersAverage(_plusDM,  _len) / _trueRange);
    def _minus     = (100 * WildersAverage(_minusDM, _len) / _trueRange);
    def plus_      = if isNaN(_plus) then plus_[1] else _plus;
    def minus_     = if isNaN(_minus) then minus_[1] else _minus;
    plot plus = plus_;
    plot min  = minus_;
}
#f_sig(_diLen, _sigLen) =>
script f_sig {
    input _diLen = 14;
    input _sigLen = 14;
    def _plus = f_dirMov(_diLen).plus;
    def _minus = f_dirMov(_diLen).min;
    def _sum = _plus + _minus;
    def _sig = 100 * WildersAverage(AbsValue(_plus - _minus) / (if _sum == 0 then 1 else _sum), _sigLen);
    plot out = _sig;
}
#— <calculations> {
#//<set initial values>
def condition;#    = 0.0

def sig = f_sig(diLength, adxSmoothing);
def diPlus = f_dirMov(diLength).plus;
def diMinus = f_dirMov(diLength).min;

def hlRange     = sig     <= Level_Range;
def diUp        = diPlus  >= diMinus;
def diUpUp      = diPlus  >= Level_Trend;
def diDn        = diMinus >  diPlus;
def diDnDn      = diMinus >  Level_Trend;

def crossDi     = (diPlus>diMinus and diPlus[1]<=diMinus[1]) or (diPlus<diMinus and diPlus[1]>=diMinus[1]);
def sigUp       = sig > sig[1];
def sigDir      = if sig > sig[1] and diUp and !hlRange then 1 else
                  if sig > sig[1] and diDn and !hlRange then -1 else 0;
#//Rules
def entryLong    = !hlRange and diUp and sigUp and !diUp[1] or
                   !hlRange and diUp and sigUp and sig > Level_Range and hlRange[1];
def entryShort   = !hlRange and diDn and sigUp and !diDn[1] or
                   !hlRange and diDn and sigUp and sig > Level_Range and hlRange[1];
def entryLongStr = !hlRange and diUp and sigUp and diUpUp;
def entryShortSt = !hlRange and diDn and sigUp and diDnDn;
def exitLong     = crossDi and diUp[1] or hlRange and !hlRange[1];
def exitShort    = crossDi and diDn[1] or hlRange and !hlRange[1];
condition   = if condition[1] !=  1   and entryLongStr then 1 else
              if condition[1] != -1   and entryShortSt then -1 else
              if condition[1] != 0.5 and entryLong    then 0.5 else
              if condition[1] != -0.5 and entryShort  then -0.5 else
              if condition[1] !=  0   and exitLong    then 0  else
              if condition[1] !=  0   and exitShort   then 0  else nz(condition[1]);
def longE     = isconfirmed and
               condition[1] !=  0.5 and condition ==    0.5;
def shortE    = isconfirmed and
               condition[1] != -0.5 and condition ==   -0.5;
def longEStr  = isconfirmed and
               condition[1] !=  1   and condition ==    1;
def shortEStr = isconfirmed and
               condition[1] != -1   and condition ==   -1;
def longX     = isconfirmed and
             ((condition[1] ==  0.5 and condition ==    0) or
              (condition[1] ==  1   and condition ==    0));
def shortX    = isconfirmed and
             ((condition[1] == -0.5 and condition ==    0) or
              (condition[1] == -1   and condition ==    0));
#//<color>
def c_sig    = if hlRange then 0 else
               if sigUp   and diUp then 2 else
               if !sigUp  and diUp then 1 else
               if sigUp   and diDn then -2 else
               if !sigUp  and diDn then -1 else na;
def c_Adx    = if hlRange then 0 else
               if !hlRange and diUp and diUpUp  then 2 else
               if !hlRange and diUp and !diUpUp then 1 else
               if !hlRange and diDn and diDnDn then -2 else
               if !hlRange and diDn and !diDnDn then -1 else na;

#// ——————————— <plots> {
plot adx = if last or isNaN(c_sig) then na else sig;
adx.SetLineWeight(3);
adx.AssignValueColor(if c_sig==0 then GlobalColor("orange") else
                     if c_sig==2 then GlobalColor("green") else
                     if c_sig==1 then GlobalColor("lgreen") else
                     if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

plot p_diPlus     = if last then na else diPlus;
p_diPlus.SetDefaultColor(GlobalColor("green"));

plot p_diMinus    = if last then na else diMinus;
p_diMinus.SetDefaultColor(GlobalColor("red"));

AddCloud(if isNaN(c_Adx) then na else if c_Adx==0 then p_diPlus else na, p_diMinus, GlobalColor("corange"),GlobalColor("corange"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==2 then p_diPlus else na, p_diMinus, GlobalColor("cgreen"),GlobalColor("cgreen"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==1 then p_diPlus else na, p_diMinus, GlobalColor("clgreen"),GlobalColor("clgreen"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==-2 then p_diPlus else na, p_diMinus, GlobalColor("cred"),GlobalColor("cred"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==-1 then p_diPlus else na, p_diMinus, GlobalColor("clred"),GlobalColor("clred"));

plot LevelRange = if last then na else Level_Range;
LevelRange.SetDefaultColor(Color.GRAY);
LevelRange.SetPaintingStrategy(PaintingStrategy.DASHES);

plot LevelTrend = if last then na else Level_Trend;
LevelTrend.SetDefaultColor(Color.GRAY);
LevelTrend.SetPaintingStrategy(PaintingStrategy.DASHES);

plot LevelUpper = if last then na else Level_Upper;
LevelUpper.SetDefaultColor(Color.GRAY);
LevelUpper.SetPaintingStrategy(PaintingStrategy.DASHES);

AssignPriceColor(if !barColor or isNaN(c_sig) then Color.CURRENT else
                 if c_sig==0 then GlobalColor("orange") else
                 if c_sig==2 then GlobalColor("green") else
                 if c_sig==1 then GlobalColor("lgreen") else
                 if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

#// ——————————— <alerts> {
plot Bullish = if alertOn and longE then Level_Trend + 10 else na;
Bullish.SetDefaultColor(GlobalColor("green"));
Bullish.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#  style      = shape.triangleup,
#  size       = size.tiny,
#  location   = location.absolute)
plot Bearish = if alertOn and shortE then Level_Trend + 10 else na;
Bearish.SetDefaultColor(GlobalColor("red"));
Bearish.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#  style      = shape.triangledown,
#  size       = size.tiny,
#  location   = location.absolute)
plot StrongBull = if alertOn and longEStr then Level_Trend + 10 else na;
StrongBull.SetDefaultColor(GlobalColor("green"));
StrongBull.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
StrongBull.SetLineWeight(3);
#  style      = shape.triangleup,
#  size       = size.small,
#  location   = location.absolute)
plot StrongBear = if alertOn and shortEStr then Level_Trend + 10 else na;
StrongBear.SetDefaultColor(GlobalColor("red"));
StrongBear.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
StrongBear.SetLineWeight(3);
#  style      = shape.triangledown,
#  size       = size.small,
#  location   = location.absolute)
plot EndTrend = if alertOn and (longX or shortX) then Level_Trend + 10 else na;
EndTrend.SetDefaultColor(GlobalColor("orange"));
EndTrend.SetPaintingStrategy(PaintingStrategy.SQUARES);
EndTrend.SetLineWeight(3);
#  style      = shape.xcross,
#  size       = size.small,
#  location   = location.absolute)


# Define a flag that turns on after DI- and DI+ cross and stays on for one bar
def crossFlag = if crossDi then 1 else if crossFlag[1] == 1 then 0 else crossFlag[1];

# Define the ADX crossing condition separately
def adxCrossingAboveTrend = adx crosses above Level_Trend;

# Now check if the ADX crossing happens after the DI cross
def alertCondition = crossFlag[1] == 1 and adxCrossingAboveTrend;

# The Alert function will then use this condition
Alert(alertCondition and alertOn, "Sequential Alert: DI- and DI+ crossed followed by ADX crossing above Level_Trend", Alert.Bar, Sound.Chimes);

#-- END of Code

The alert condition appears to occur rarely, but when it does the alert sounds.
The image shows a message alert and the chart where it occrred.
Screenshot 2023-12-29 122544.png
Screenshot 2023-12-29 122630.png
Add the following to the bottom of your code to test your condtions.
Code:
AddChartBubble(alertCondition, 30, alertCondition, Color.GRAY);
AddChartBubble(adxCrossingAboveTrend, 20, adxCrossingAboveTrend, Color.YELLOW);
AddChartBubble(crossFlag, 10, crossFlag, Color.WHITE);


View attachment 20563View attachment 20564
 
Solution

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

I am looking to create an alert with a specific sequential condition: The alert should trigger only when two events occur in order.

First, the DI- (Directional Indicator minus) and DI+ (Directional Indicator plus) lines must cross each other. Following this event, and only if it occurs first, the second condition that must be met is the crossing of the ADX (Average Directional Index) line above a predefined level known as the 'Level Trend'. The alert is designed to activate only when these two conditions are fulfilled in this exact sequence.

I tried with ChatGPT4 but the alert isn't triggering or sounding. Can someone tell me what I'm doing wrong and identify a solution?

The relevant part is here:
Code:
# Define a flag that turns on after DI- and DI+ cross and stays on for one bar
def crossFlag = if crossDi then 1 else if crossFlag[1] == 1 then 0 else crossFlag[1];

# Define the ADX crossing condition separately
def adxCrossingAboveTrend = adx crosses above Level_Trend;

# Now check if the ADX crossing happens after the DI cross
def alertCondition = crossFlag[1] == 1 and adxCrossingAboveTrend;

# The Alert function will then use this condition
Alert(alertCondition and alertOn, "Sequential Alert: DI- and DI+ crossed followed by ADX crossing above Level_Trend", Alert.Bar, Sound.Chimes);


Here's the full script:
Code:
# https://my.tradingview.com/script/RNcqYq6w-ADX-Di-Di-Gu5/
# This source code is subject to these terms:
#// You are free to:
#// Share, copy and redistribute this script
#// Adapt, transform and build on this script.
#// Under the following terms:
#// NonCommercial: You may not use the material for commercial purposes.
#// Attribution: You must give appropriate credit
#// https://www.safecreative.org/work/2302153511401-adx-di-di-gu5-
#// © gu5tavo71 (Gustavo Cardelle)
#indicator(title = 'ADX Di+ Di- [Gu5]', shorttitle = 'ADX', overlay = false,
#// Indicator to helps determine the strength of a trend
#// Average Directional movement indeX (ADX) Developed by J. Welles
#// This script reuses open source code from another authors:
#// @PineCoders, Built-in Library, and Community Scripts
#// Disclaimer: I am not a financial advisor.
#//             For purpose educate only. Use at your own risk.
# Converted by Sam4Cok@Samer800 - 03/2023
declare lower;
#// ——————————— <inputs> {
input adxSmoothing = 7;#        'ADX Smoothing'
input diLength     = 7;#        'DI Length'
input Level_Range  = 25;#       'Level Range'
input Level_Trend  = 50;#       'Level Trend'
input Level_Upper  = 75;#       'Level Upper'    
input alertOn      = yes;#      "Alert On/Off"
input barColor     = yes;#      "Bar Color On/Off"

def na = Double.NaN;
def last = isNaN(close);
def isconfirmed = !IsNaN(close);
#--- Color---
DefineGlobalColor("green"  , CreateColor(0, 100, 0));
DefineGlobalColor("lgreen" , CreateColor(56,142,60));
DefineGlobalColor("red"    , CreateColor(139,0,0));
DefineGlobalColor("lred"   , CreateColor(183,28,28));
DefineGlobalColor("orange" , CreateColor(255,152,0));

DefineGlobalColor("cgreen"  , CreateColor(0,61,0));
DefineGlobalColor("clgreen" , CreateColor(39,100,42));
DefineGlobalColor("cred"    , CreateColor(61,0,0));
DefineGlobalColor("clred"   , CreateColor(149,23,23));
DefineGlobalColor("corange" , CreateColor(118, 70, 0));

# function_declarations> {
script nz {
    input data  = close;
    def ret_val = if !isNaN(data) then data else 0;
    plot return = ret_val;
}
script fixnan {
    input source = close;
    def fix = if !IsNaN(source) then source else fix[1];
    plot result = fix;
}
#f_dirMov(_len) =>
script f_dirMov {
    input _len = 14;
    def _up        = (high - high[1]);
    def _down      = -(low - low[1]);
    def _plusDM    = if IsNaN(_up) then Double.NaN else if _up > _down and _up   > 0 then _up else 0;
    def _minusDM   = if IsNaN(_down) then Double.NaN else if _down > _up and _down > 0 then _down else 0;
    def tr = TrueRange(high, close, low);
    def _trueRange = WildersAverage(tr, _len);
    def _plus      = (100 * WildersAverage(_plusDM,  _len) / _trueRange);
    def _minus     = (100 * WildersAverage(_minusDM, _len) / _trueRange);
    def plus_      = if isNaN(_plus) then plus_[1] else _plus;
    def minus_     = if isNaN(_minus) then minus_[1] else _minus;
    plot plus = plus_;
    plot min  = minus_;
}
#f_sig(_diLen, _sigLen) =>
script f_sig {
    input _diLen = 14;
    input _sigLen = 14;
    def _plus = f_dirMov(_diLen).plus;
    def _minus = f_dirMov(_diLen).min;
    def _sum = _plus + _minus;
    def _sig = 100 * WildersAverage(AbsValue(_plus - _minus) / (if _sum == 0 then 1 else _sum), _sigLen);
    plot out = _sig;
}
#— <calculations> {
#//<set initial values>
def condition;#    = 0.0

def sig = f_sig(diLength, adxSmoothing);
def diPlus = f_dirMov(diLength).plus;
def diMinus = f_dirMov(diLength).min;

def hlRange     = sig     <= Level_Range;
def diUp        = diPlus  >= diMinus;
def diUpUp      = diPlus  >= Level_Trend;
def diDn        = diMinus >  diPlus;
def diDnDn      = diMinus >  Level_Trend;

def crossDi     = (diPlus>diMinus and diPlus[1]<=diMinus[1]) or (diPlus<diMinus and diPlus[1]>=diMinus[1]);
def sigUp       = sig > sig[1];
def sigDir      = if sig > sig[1] and diUp and !hlRange then 1 else
                  if sig > sig[1] and diDn and !hlRange then -1 else 0;
#//Rules
def entryLong    = !hlRange and diUp and sigUp and !diUp[1] or
                   !hlRange and diUp and sigUp and sig > Level_Range and hlRange[1];
def entryShort   = !hlRange and diDn and sigUp and !diDn[1] or
                   !hlRange and diDn and sigUp and sig > Level_Range and hlRange[1];
def entryLongStr = !hlRange and diUp and sigUp and diUpUp;
def entryShortSt = !hlRange and diDn and sigUp and diDnDn;
def exitLong     = crossDi and diUp[1] or hlRange and !hlRange[1];
def exitShort    = crossDi and diDn[1] or hlRange and !hlRange[1];
condition   = if condition[1] !=  1   and entryLongStr then 1 else
              if condition[1] != -1   and entryShortSt then -1 else
              if condition[1] != 0.5 and entryLong    then 0.5 else
              if condition[1] != -0.5 and entryShort  then -0.5 else
              if condition[1] !=  0   and exitLong    then 0  else
              if condition[1] !=  0   and exitShort   then 0  else nz(condition[1]);
def longE     = isconfirmed and
               condition[1] !=  0.5 and condition ==    0.5;
def shortE    = isconfirmed and
               condition[1] != -0.5 and condition ==   -0.5;
def longEStr  = isconfirmed and
               condition[1] !=  1   and condition ==    1;
def shortEStr = isconfirmed and
               condition[1] != -1   and condition ==   -1;
def longX     = isconfirmed and
             ((condition[1] ==  0.5 and condition ==    0) or
              (condition[1] ==  1   and condition ==    0));
def shortX    = isconfirmed and
             ((condition[1] == -0.5 and condition ==    0) or
              (condition[1] == -1   and condition ==    0));
#//<color>
def c_sig    = if hlRange then 0 else
               if sigUp   and diUp then 2 else
               if !sigUp  and diUp then 1 else
               if sigUp   and diDn then -2 else
               if !sigUp  and diDn then -1 else na;
def c_Adx    = if hlRange then 0 else
               if !hlRange and diUp and diUpUp  then 2 else
               if !hlRange and diUp and !diUpUp then 1 else
               if !hlRange and diDn and diDnDn then -2 else
               if !hlRange and diDn and !diDnDn then -1 else na;

#// ——————————— <plots> {
plot adx = if last or isNaN(c_sig) then na else sig;
adx.SetLineWeight(3);
adx.AssignValueColor(if c_sig==0 then GlobalColor("orange") else
                     if c_sig==2 then GlobalColor("green") else
                     if c_sig==1 then GlobalColor("lgreen") else
                     if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

plot p_diPlus     = if last then na else diPlus;
p_diPlus.SetDefaultColor(GlobalColor("green"));

plot p_diMinus    = if last then na else diMinus;
p_diMinus.SetDefaultColor(GlobalColor("red"));

AddCloud(if isNaN(c_Adx) then na else if c_Adx==0 then p_diPlus else na, p_diMinus, GlobalColor("corange"),GlobalColor("corange"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==2 then p_diPlus else na, p_diMinus, GlobalColor("cgreen"),GlobalColor("cgreen"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==1 then p_diPlus else na, p_diMinus, GlobalColor("clgreen"),GlobalColor("clgreen"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==-2 then p_diPlus else na, p_diMinus, GlobalColor("cred"),GlobalColor("cred"));
AddCloud(if isNaN(c_Adx) then na else if c_Adx==-1 then p_diPlus else na, p_diMinus, GlobalColor("clred"),GlobalColor("clred"));

plot LevelRange = if last then na else Level_Range;
LevelRange.SetDefaultColor(Color.GRAY);
LevelRange.SetPaintingStrategy(PaintingStrategy.DASHES);

plot LevelTrend = if last then na else Level_Trend;
LevelTrend.SetDefaultColor(Color.GRAY);
LevelTrend.SetPaintingStrategy(PaintingStrategy.DASHES);

plot LevelUpper = if last then na else Level_Upper;
LevelUpper.SetDefaultColor(Color.GRAY);
LevelUpper.SetPaintingStrategy(PaintingStrategy.DASHES);

AssignPriceColor(if !barColor or isNaN(c_sig) then Color.CURRENT else
                 if c_sig==0 then GlobalColor("orange") else
                 if c_sig==2 then GlobalColor("green") else
                 if c_sig==1 then GlobalColor("lgreen") else
                 if c_sig==-2 then GlobalColor("red") else GlobalColor("lred"));

#// ——————————— <alerts> {
plot Bullish = if alertOn and longE then Level_Trend + 10 else na;
Bullish.SetDefaultColor(GlobalColor("green"));
Bullish.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#  style      = shape.triangleup,
#  size       = size.tiny,
#  location   = location.absolute)
plot Bearish = if alertOn and shortE then Level_Trend + 10 else na;
Bearish.SetDefaultColor(GlobalColor("red"));
Bearish.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
#  style      = shape.triangledown,
#  size       = size.tiny,
#  location   = location.absolute)
plot StrongBull = if alertOn and longEStr then Level_Trend + 10 else na;
StrongBull.SetDefaultColor(GlobalColor("green"));
StrongBull.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
StrongBull.SetLineWeight(3);
#  style      = shape.triangleup,
#  size       = size.small,
#  location   = location.absolute)
plot StrongBear = if alertOn and shortEStr then Level_Trend + 10 else na;
StrongBear.SetDefaultColor(GlobalColor("red"));
StrongBear.SetPaintingStrategy(PaintingStrategy.TRIANGLES);
StrongBear.SetLineWeight(3);
#  style      = shape.triangledown,
#  size       = size.small,
#  location   = location.absolute)
plot EndTrend = if alertOn and (longX or shortX) then Level_Trend + 10 else na;
EndTrend.SetDefaultColor(GlobalColor("orange"));
EndTrend.SetPaintingStrategy(PaintingStrategy.SQUARES);
EndTrend.SetLineWeight(3);
#  style      = shape.xcross,
#  size       = size.small,
#  location   = location.absolute)


# Define a flag that turns on after DI- and DI+ cross and stays on for one bar
def crossFlag = if crossDi then 1 else if crossFlag[1] == 1 then 0 else crossFlag[1];

# Define the ADX crossing condition separately
def adxCrossingAboveTrend = adx crosses above Level_Trend;

# Now check if the ADX crossing happens after the DI cross
def alertCondition = crossFlag[1] == 1 and adxCrossingAboveTrend;

# The Alert function will then use this condition
Alert(alertCondition and alertOn, "Sequential Alert: DI- and DI+ crossed followed by ADX crossing above Level_Trend", Alert.Bar, Sound.Chimes);

#-- END of Code

this is a generic study that,
. checks if 3 true/false conditions happen in the desired sequence , 1,2,3
. each pair is within x bars of each other
. output is true on bar of last condition

it uses crossing averages for the test conditions.
then it compares the barnumbers of the conditions.
a white bubble is drawn on 3rd condition if there are 3 sequential conditions.


Code:
# test_seq_signals_withinx


# check if 3 T/F conditions happen in desired sequence , 1,2,3
#  each pair is within x bars
#  output is true on bar of last condition

def na = double.nan;
def bn = barnumber();
def data = close;

input within_x_bars = 15;

def big = 99999;

#------------------------
# test signals

#input avg1_type = AverageType.exponential;
input avg1_type = AverageType.Simple;
input avg1_length = 33;
def avg1 = MovingAverage(avg1_type, data, avg1_length);

input avg2_type = AverageType.Simple;
input avg2_length = 66;
def avg2 = MovingAverage(avg2_type, data, avg2_length);

input avg3_type = AverageType.Simple;
input avg3_length = 99;
def avg3 = MovingAverage(avg3_type, data, avg3_length);

input avg4_type = AverageType.Simple;
input avg4_length = 140;
def avg4 = MovingAverage(avg4_type, data, avg4_length);

input show_average_lines = yes;
plot zavg1 = if show_average_lines then avg1 else na;
plot zavg2 = if show_average_lines then avg2 else na;
plot zavg3 = if show_average_lines then avg3 else na;
plot zavg4 = if show_average_lines then avg4 else na;
zavg1.setdefaultcolor(color.cyan);
#zavg2.setdefaultcolor(color.gray);
#zavg3.setdefaultcolor(color.gray);
#zavg4.setdefaultcolor(color.gray);


#---------------------------------
# conditions

# cyan
def cond1 = avg1 crosses avg2;
# yellow
def cond2 = avg1 crosses avg3;
# magenta
def cond3 = avg1 crosses avg4;

def c1_bn = if bn == 1 then 0 else if cond1 then bn else c1_bn[1];
def c2_bn = if bn == 1 then 0 else if cond2 then bn else c2_bn[1];
def c3_bn = if bn == 1 then 0 else if cond3 then bn else c3_bn[1];

def seq =  (c1_bn < c2_bn and c2_bn < c3_bn);

def c12_diff = if (c1_bn > 0 and c2_bn > 0) then (c2_bn - c1_bn) else big;
def c23_diff = if (c2_bn > 0 and c3_bn > 0) then (c3_bn - c2_bn) else big;

def cond123 = if (cond3 and seq and c12_diff <= within_x_bars and c23_diff <= within_x_bars) then 1 else 0; 


input seq_cond_bubble = yes;
addchartbubble(seq_cond_bubble and cond123, avg1*1.01,
"3 seq cond\n"+
"within " + within_x_bars + " bars"
, color.white, yes);


input test1 = yes;
addchartbubble(test1 and (cond1 or cond2 or cond3), avg1*0.99,
 bn + " bn\n" +
 cond1 + "  C1\n" +
 cond2 + "  C2\n" +
 cond3 + "  C3\n" +
 c1_bn + "  C1 bn\n" +
 c2_bn + "  C2 bn\n" +
 c3_bn + "  C3 bn\n" +
 c12_diff + "  c12\n" +
 c23_diff + "  c23\n" +
 cond123 + "  c123"
, (if cond1 then color.cyan else if cond2 then color.yellow else if cond3 then color.magenta else color.gray), no);
#

AXP day
on the left,
. 3 colored bubbles, in the correct order and spacing
. have a white bubble above 3rd condition
on the right,
. 3 colored bubbles, are not in the correct order, but do have correct spacing
. no white bubble
IGjnhTU.jpg
 

Similar threads

Not the exact question you're looking for?

Start a new thread and receive assistance from our community.

87k+ Posts
532 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