Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Indicator for EMA crossing strategy not working properly

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

    Indicator for EMA crossing strategy not working properly

    Hi,
    I was working on an indicator that would draw text on my chart whenever conditions of my EMA strategy are met. Now I have this specific situation, where the crossing of the various EMAs are VALID or INVALD. According to the respective condition the indicator shoudl draw a different text.
    The idea is as follows:


    I need to extend two conditions where 50-period EMA crosses above the 200-period EMA and the 20-period EMA is above the 50-period EMA,

    OR when the 50-period EMA crosses below the 200-period EMA and the 20-period EMA is below the 50-period EMA.

    Letīs name these crossings "X2" and letīs name the first variant of that condition "ABOVE200" and the second variant "BELOW200".

    First I discribe the whole situation on the ABOVE200 variant. Before the EMA 50 crosses above the EMA 200, the EMA 20 had to cross above the EMA 200 earlier, but more importantly at a certain point in the past the EMA 20 had to cross above the EMA 50 when they were both below the EMA 200. Letīs call this crossing "X1". Now we have a certain period of time or numbers of bars on the chart where the market price is moving up and down and if the price development is rising long enough it causes first the EMA 20 to cross above the EMA 200 and when also EMA 50 crosses above EMA 200 we got the X2.

    BUT in my strategy I am using this indivator for, there is one condition that invalidates the X2 and that is when: the market price between the X1 and X2 hits the EMA 20 value, or in other words if market price is equal or lower than ema20 between X1 and X2. If that happens the X2 is not valid anymore. Letīs call this situation "invalidX2".

    Now I would need my code to tak this into account so when the discribed situation happens (invalidX2), it triggers the Draw.Text with a different text. Of course that should be applied for the ABOVE200 variant and in the opposite also for the BELOW200 variant.

    If the condition is valid, meaning invaldX2 doesnīt happen the code for the ABOVE200 and BELOW200 conditions should print the VALID text in the NinjaScript Output and the Draw.Text shall show the valid versions "AV-X2" and "BV-X2".

    And here is another thing: applying the invalidX2 situation should work on the whole chart, for every situation where the ABOVE200 and BELOW200 conditions are met, not only from the current bar.

    Here is my current version of the code:
    Code:
    #region Using declarations
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.ComponentModel.DataAnnotations;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Xml.Serialization;
    using NinjaTrader.Cbi;
    using NinjaTrader.Gui;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Gui.SuperDom;
    using NinjaTrader.Gui.Tools;
    using NinjaTrader.Data;
    using NinjaTrader.NinjaScript;
    using NinjaTrader.Core.FloatingPoint;
    using NinjaTrader.NinjaScript.DrawingTools;
    #endregion
    
    //This namespace holds Indicators in this folder and is required. Do not change it.
    namespace NinjaTrader.NinjaScript.Indicators
    {
        public class EMAX2SymbolWithN : Indicator
        {
    private EMA ema20;
    private EMA ema50;
    private EMA ema200;
    
            bool validX2;
            bool invalidX2;
    
    [Range(1, int.MaxValue), NinjaScriptProperty]
    public int EMAPeriod1 { get; set; }
    
    [Range(1, int.MaxValue), NinjaScriptProperty]
    public int EMAPeriod2 { get; set; }
    
    [Range(1, int.MaxValue), NinjaScriptProperty]
    public int EMAPeriod3 { get; set; }
    
        [Range(1, int.MaxValue), NinjaScriptProperty]
        public int TextOffset { get; set; }
    
    
    protected override void OnStateChange()
    {
        if (State == State.SetDefaults)
        {
            Name = "EMA X2 Symbol wN";
            EMAPeriod1 = 20;
            EMAPeriod2 = 50;
            EMAPeriod3 = 200;
            TextOffset = 30;
    
        }
    
    }
    
    protected override void OnBarUpdate()
    {
    
            ema20 = EMA(EMAPeriod1);
        ema50 = EMA(EMAPeriod2);
        ema200 = EMA(EMAPeriod3);
    
    
        //ABOVE200 condition
                    if(CrossAbove(ema50, ema200, 1) && ema20[0] > ema50[0])
                    {
                        validX2 = true;
                        invalidX2 = false;
    
                        //check if market price is equal or lower than ema20
                            if(Close[0] <= ema20[0])
                            {
                                invalidX2 = true;
                                validX2 = false;
                            }
    
                        else if(validX2 && !invalidX2)
                        {
                            //original Draw.Text() call
                            Print("ABOVE200: VALID  " + Instrument.FullName + "  at: " + Time[0]);
                            Draw.Text(this, "AV-X2"+CurrentBar, "AV-X2", 0, Low[0] - (TickSize*TextOffset), Brushes.Blue);
                        }
    
                            else if (!validX2 && invalidX2)
                        {
                            //Draw.Text() call for invalidX2
                            Print("ABOVE200: INVALID  " + Instrument.FullName + "  at: " + Time[0]);
                            Draw.Text(this, "AnX2"+CurrentBar, "AnX2", 0, Low[0] - (TickSize*TextOffset), Brushes.Gold);
                        }
    
    
                    }
    
    //BELOW200 condition
                    else if(CrossBelow(ema50, ema200, 1) && ema20[0] < ema50[0])
                    {
    
                        validX2 = true;
                        invalidX2 = false;
    
                        //check if market price is equal or higher than ema20
                            if(Close[0] >= ema20[0])
                            {
                                invalidX2 = true;
                                validX2 = false;
                            }
    
                        else if(validX2 && !invalidX2)
                        {
                            //original Draw.Text() call
                            Print("BELOW200: VALID  " + Instrument.FullName + "  at: " + Time[0]);
                            Draw.Text(this, "BV-X2"+CurrentBar, "BV-X2", 0, Low[0] - (TickSize*TextOffset), Brushes.Green);
                        }
    
                            else if (!validX2 && invalidX2)
                        {
                            //Draw.Text() call for invalidX2
                            Print("BELOW200: INVALID  " + Instrument.FullName + "  at: " + Time[0]);
                            Draw.Text(this, "BnX2"+CurrentBar, "BnX2", 0, Low[0] - (TickSize*TextOffset), Brushes.Orange);
                        }
        }    
        }
    }
    }    ​
    Hope someone can help me with this.

    Thanks!
    Peter

    #2
    Hello Peter,

    Thank you for your post.

    At first glance, it looks like you might be using else if statements improperly. I see they are nested inside of your if statements that are meant to set the bools to true/false. Else if statements are meant to be used for a new condition in the case that your original condition from the if statement is false. I suggest adding Print() statements along the way to print the values being used in your conditions along with the values of your bools. You could also comment/uncomment different sections of code to spot-check which parts are behaving as expected and which parts are not. There is more information about using prints to debug your scripts here:


    Here is a publicly available resource about else if statements:
    W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.


    Please let us know if we may be of further assistance.

    Comment


      #3
      Hi Emily,

      I have only very basic coding skills. So I am using chat.openai. But unfortunately it is providing codes that donīt work the way I need.
      I have this updated code now, but although there are several situations on the tested chart where the conditions for the X2Above are met I am still getting no Draw.Text nor any print message in the output window.
      I have tried to find the reason of the problem, as the compiler did not find any error, but as I said, my skills are limited.
      Maybe you can help? The logic as discribed in my first message is still the same.

      Code:
      namespace NinjaTrader.NinjaScript.Indicators
      {
          public class EMA200TEST : Indicator
          {
              private EMA ema20;
              private EMA ema50;
              private EMA ema200;
      
              [Range(1, int.MaxValue), NinjaScriptProperty]
              public int EMAPeriod1 { get; set; }
      
              [Range(1, int.MaxValue), NinjaScriptProperty]
              public int EMAPeriod2 { get; set; }
      
              [Range(1, int.MaxValue), NinjaScriptProperty]
              public int EMAPeriod3 { get; set; }
      
              [Range(1, int.MaxValue), NinjaScriptProperty]
              public int TextOffset { get; set; }
      
              bool X1Above = false;
              bool X2Above = false;
              bool invalidX2 = false;
              bool X1AboveFound = false;
              bool X2AboveFound = false;
      
          protected override void OnStateChange()
          {
              if (State == State.SetDefaults)
              {
              Name = "EMA 200 TEST";
              IsOverlay = true;
              EMAPeriod1 = 20;
              EMAPeriod2 = 50;
              EMAPeriod3 = 200;
              TextOffset = 30;
      
          }
      
      }
      
          protected override void OnBarUpdate()
          {
      
              ema20 = EMA(EMAPeriod1);
              ema50 = EMA(EMAPeriod2);
              ema200 = EMA(EMAPeriod3);
      
                  // Initialize variables
              X1Above = false;
              X2Above = false;
              invalidX2 = false;
              X1AboveFound = false;
              X2AboveFound = false;
      
      
              //X1 ABOVE condition
              if (CrossAbove(ema20, ema50, 1))    
              {
                  Print("X1 ABOVE " + Instrument.FullName + "  at: " + Time[0]);
                  Draw.Text(this, "X1-A"+CurrentBar, "X1-A", 0, Low[0] - (TickSize*TextOffset), Brushes.Gray);
              }
      
              //X1 BELOW condition
              if (CrossBelow(ema20, ema50, 1))    
              {
                  Print("X1 BELOW " + Instrument.FullName + "  at: " + Time[0]);
                  Draw.Text(this, "X1-B"+CurrentBar, "X1-B", 0, Low[0] - (TickSize*TextOffset), Brushes.Gray);
              }
      
      
          // Check for X1 condition
          if (EMA(EMAPeriod1)[0] > EMA(EMAPeriod2)[0] && EMA(EMAPeriod1)[0] < EMA(EMAPeriod3)[0])
          {
              X1Above = true;
          }
      
          // Check for X2 condition
          if (X1Above == true && EMA(EMAPeriod2)[0] > EMA(EMAPeriod3)[0] && EMA(EMAPeriod1)[0] > EMA(EMAPeriod2)[0])
          {
              X2AboveFound = true;
          }
          // Check for invalidX2 situation
          if (X2AboveFound == true)
          {
              for (int i = CurrentBar - 50; i > 0; i--)
              {
                  if (X1Above == true && X2Above == true && Close[i] <= EMA(EMAPeriod1)[i])
                  {
                      invalidX2 = true;
                      break;
                  }
              }
          }
      
      // Draw.Text for X2Above condition
      if (X2AboveFound == true && invalidX2 == false)
      {
      Draw.Text(this, "AX2-V"+CurrentBar, "AX2-V", 0, Low[0] - (TickSize*TextOffset), Brushes.Green);
          Print("AX2-V " + Instrument.FullName + "  at: " + Time[0]);
      }
      else if (X2AboveFound == true && invalidX2 == true)
      {
      Draw.Text(this, "AX2-INVALID"+CurrentBar, "AX2-INVALID", 0, Low[0] - (TickSize*TextOffset), Brushes.Red);
          Print("AX2-INVALID " + Instrument.FullName + "  at: " + Time[0]);
      }
      
      
              }    
          }
      }​
      ​
      Last edited by cyberpete76; 01-27-2023, 12:07 PM.

      Comment


        #4
        Please ignore my previous code, I have an updated version but still I am not getting any Draw.Text nor print.

        Code:
        namespace NinjaTrader.NinjaScript.Indicators
        {
            public class EMA200TEST : Indicator
            {
                private EMA ema20;
                private EMA ema50;
                private EMA ema200;
        
                [Range(1, int.MaxValue), NinjaScriptProperty]
                public int EMAPeriod1 { get; set; }
        
                [Range(1, int.MaxValue), NinjaScriptProperty]
                public int EMAPeriod2 { get; set; }
        
                [Range(1, int.MaxValue), NinjaScriptProperty]
                public int EMAPeriod3 { get; set; }
        
                [Range(1, int.MaxValue), NinjaScriptProperty]
                public int TextOffset { get; set; }
        
                bool X1Above = false;
                bool X2Above = false;
                bool invalidX2 = false;
                bool X1AboveFound = false;
                bool X2AboveFound = false;
        
            protected override void OnStateChange()
            {
                if (State == State.SetDefaults)
                {
                Name = "EMA 200 TEST";
                IsOverlay = true;
                EMAPeriod1 = 20;
                EMAPeriod2 = 50;
                EMAPeriod3 = 200;
                TextOffset = 30;
        
            }
        
        }
        
            protected override void OnBarUpdate()
            {
        
                ema20 = EMA(EMAPeriod1);
                ema50 = EMA(EMAPeriod2);
                ema200 = EMA(EMAPeriod3);
        
                    // Initialize variables
                X1Above = false;
                X2Above = false;
                invalidX2 = false;
                X1AboveFound = false;
                X2AboveFound = false;
        
        
                //X1 ABOVE condition
                if (CrossAbove(ema20, ema50, 1))    
                {
                    Print("X1 ABOVE " + Instrument.FullName + "  at: " + Time[0]);
                    Draw.Text(this, "X1-A"+CurrentBar, "X1-A", 0, Low[0] - (TickSize*TextOffset), Brushes.Gray);
                }
        
                //X1 BELOW condition
                if (CrossBelow(ema20, ema50, 1))    
                {
                    Print("X1 BELOW " + Instrument.FullName + "  at: " + Time[0]);
                    Draw.Text(this, "X1-B"+CurrentBar, "X1-B", 0, Low[0] - (TickSize*TextOffset), Brushes.Gray);
                }
        
        
            // Check for X1 condition
            if (EMA(EMAPeriod1)[0] > EMA(EMAPeriod2)[0] && EMA(EMAPeriod1)[0] < EMA(EMAPeriod3)[0])
            {
                X1Above = true;
            }
        
            if (X1Above == true && EMA(EMAPeriod2)[0] > EMA(EMAPeriod3)[0] && EMA(EMAPeriod1)[0] > EMA(EMAPeriod2)[0])
            {
                X2Above = true;
            }
        
            // Check for X2 condition
            if (X1Above == true && EMA(EMAPeriod2)[0] > EMA(EMAPeriod3)[0] && EMA(EMAPeriod1)[0] > EMA(EMAPeriod2)[0])
            {
                X2AboveFound = true;
            }
            // Check for invalidX2 situation
            if (X2AboveFound == true)
            {
                for (int i = CurrentBar - 500; i > 0; i--)
                {
                    if (X1Above == true && Close[i] <= EMA(EMAPeriod1)[i])
                    {
                        invalidX2 = true;
                        break;
                    }
                }
            }
        
        // Draw.Text for X2Above condition
        if (X2AboveFound == true && invalidX2 == false)
        {
        Draw.Text(this, "AX2-V"+CurrentBar, "AX2-V", 0, Low[0] - (TickSize*TextOffset), Brushes.Green);
            Print("AX2-V " + Instrument.FullName + "  at: " + Time[0]);
        }
        else if (X2AboveFound == true && invalidX2 == true)
        {
        Draw.Text(this, "AX2-INVALID"+CurrentBar, "AX2-INVALID", 0, Low[0] - (TickSize*TextOffset), Brushes.Red);
            Print("AX2-INVALID " + Instrument.FullName + "  at: " + Time[0]);
        }
        
        
                }    
            }
        }​

        Comment


          #5
          Hello cyberpete76,

          Thank you for your patience.

          Unfortunately, in the support department at NinjaTrader, it is against our policy to create, debug, or modify, code or logic for our clients. Further, we do not provide C# programming education services or one on one educational support in our NinjaScript Support department. This is so that we can maintain a high level of service for all of our clients as well as our associates.

          That said, through email or on the forum we are happy to answer any questions you may have about NinjaScript if you decide to code this yourself. We are also happy to assist with finding resources in our help guide as well as simple examples, and we are happy to assist with guiding you through the debugging process to assist you with understanding unexpected behavior.

          You can also contact a professional NinjaScript Consultant who would be eager to create or modify this script at your request or assist you with your script. The NinjaTrader Ecosystem has affiliate contacts who provide educational as well as consulting services. Please let me know if you would like our NinjaTrader Ecosystem team to follow up with you with a list of affiliate consultants who would be happy to create this script or any others at your request or provide one on one educational services.

          I see you have added print statements, though you said you are not getting any prints or text drawn. I suggest adding print statements outside of your condition statements just to print out the values of the EMAs and bools involved in the conditions. This will help you to understand if your condition logic should be evaluated to be true or not.​ Additionally, did you add your inputs for EMA periods and TextOffset via the new indicator wizard or manually? Typically it is a best practice to add them via the wizard in order to prevent any user error. This will put them into the "Properties" region that is generated at the bottom of the script.

          Please add prints outside of your conditions, and let me know if those prints are coming up or not. If they do not show in the NinjaScript Output window, please check the Log tab of the Control Center for errors.

          I look forward to your reply.

          Comment

          Latest Posts

          Collapse

          Topics Statistics Last Post
          Started by Geovanny Suaza, 02-11-2026, 06:32 PM
          0 responses
          562 views
          0 likes
          Last Post Geovanny Suaza  
          Started by Geovanny Suaza, 02-11-2026, 05:51 PM
          0 responses
          325 views
          1 like
          Last Post Geovanny Suaza  
          Started by Mindset, 02-09-2026, 11:44 AM
          0 responses
          101 views
          0 likes
          Last Post Mindset
          by Mindset
           
          Started by Geovanny Suaza, 02-02-2026, 12:30 PM
          0 responses
          547 views
          1 like
          Last Post Geovanny Suaza  
          Started by RFrosty, 01-28-2026, 06:49 PM
          0 responses
          547 views
          1 like
          Last Post RFrosty
          by RFrosty
           
          Working...
          X