Announcement

Collapse

Looking for a User App or Add-On built by the NinjaTrader community?

Visit NinjaTrader EcoSystem and our free User App Share!

Have a question for the NinjaScript developer community? Open a new thread in our NinjaScript File Sharing Discussion Forum!
See more
See less

Partner 728x90

Collapse

How to fire Alarm sound only once per bar?

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

    How to fire Alarm sound only once per bar?

    How can i fire alarm once when my condition is met (and not on the next ticks on same bar)?

    for example,

    if Close[0] > Open[0] {
    PlaySound (.....);
    }

    want to happen this one only once per bar. What is simplest method?

    btw, i know complex methods, like saving unique identifier in array and re-checking...

    #2
    Hello TazoTodua,

    Thank you for your note.

    You could use a bool.

    For example,
    Code:
    Private bool doOnce=false;
    
    if(Close[0]>0 && doOnce==False)
    {
    PlaySound;
    doOnce=true;
    }
    Please let us know if you need further assistance.
    Alan P.NinjaTrader Customer Service

    Comment


      #3
      Originally posted by NinjaTrader_AlanP View Post
      Hello TazoTodua,

      Thank you for your note.

      You could use a bool.

      For example,
      Code:
      Private bool doOnce=false;
      
      if(Close[0]>0 && doOnce==False)
      {
      PlaySound;
      doOnce=true;
      }
      Please let us know if you need further assistance.
      P/private and F/false Typos correction:

      Code:
      private bool doOnce=false;
      
      if(Close[0]>0 && doOnce==false)
      {
      PlaySound;
      doOnce=true;
      }

      Comment


        #4
        I'm trying to get the VolumeUpDown built-in NT8 Indicator to fire an Alert just once, when nb of contract get >= VOLMA (5)[1]. Calculation is set OnEachTick.

        It does fires the alarm without the statements used below (but many times once VolumeUpDown gets >= VOLMA (5)[1] until the end of the candle) :

        private bool doOnce = false;
        (doOnce == false))
        doOnce = true;


        It doesn't fire the alarm anymore once the above statements are added.
        But it compiles so I don't see what's wrong.
        Any solution is much appreciated.
        Thanks.

        In bold bellow is the BRIEF CODE and FULL CODE:

        Code:
        BRIEF CODE
        
        {
        [B]private bool doOnce = false;[/B]
        
        ...
        
        protected override void OnBarUpdate()
        {
        if(CurrentBar < 1)return;
        if (VOL()[0] >= VOLMA(5)[1] &&
        [B](doOnce == false))[/B]
        {
        PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\VolumeSpike.wav");
        [B]doOnce = true;
        
        ...[/B]
        }
        Here's the complete VolumeUpDown Code I have:

        Code:
        FULL CODE
        
        //
        // Copyright (C) 2020, NinjaTrader LLC <www.ninjatrader.com>.
        // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
        //
        #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.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 VolumeUpDown_Alert : Indicator
        {
        [B]private bool doOnce = false;[/B]
        
        protected override void OnStateChange()
        {
        if (State == State.SetDefaults)
        {
        Name = "VolumeUpDown_Alert";
        Calculate = Calculate.OnEachTick;
        DrawOnPricePanel = false;
        IsOverlay = false;
        IsSuspendedWhileInactive = true;
        
        AddPlot(new Stroke(Brushes.DarkCyan, 2), PlotStyle.Bar, NinjaTrader.Custom.Resource.VolumeUp);
        AddPlot(new Stroke(Brushes.Crimson, 2), PlotStyle.Bar, NinjaTrader.Custom.Resource.VolumeDown);
        AddLine(Brushes.DarkGray, 0, NinjaTrader.Custom.Resource.NinjaScriptIndicatorZe roLine);
        }
        else if (State == State.Historical)
        {
        if (Calculate == Calculate.OnPriceChange)
        {
        Draw.TextFixed(this, "NinjaScriptInfo", string.Format(NinjaTrader.Custom.Resource.NinjaScr iptOnPriceChangeError, Name), TextPosition.BottomRight);
        Log(string.Format(NinjaTrader.Custom.Resource.Ninj aScriptOnPriceChangeError, Name), LogLevel.Error);
        }
        }
        }
        
        protected override void OnBarUpdate()
        {
        if(CurrentBar < 1)return;
        if (VOL()[0] >= VOLMA(5)[1] &&
        [B](doOnce == false))[/B]
        {
        PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\VolumeSpike.wav");
        [B]doOnce = true; // prevent additional alerts[/B]
        }
        
        if (Close[0] >= Open[0])
        {
        UpVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
        DownVolume.Reset();
        }
        else
        {
        UpVolume.Reset();
        DownVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
        }
        }
        
        #region Properties
        [Browsable(false)]
        [XmlIgnore]
        public Series<double> DownVolume
        {
        get { return Values[1]; }
        }
        
        [Browsable(false)]
        [XmlIgnore]
        public Series<double> UpVolume
        {
        get { return Values[0]; }
        }
        #endregion
        }
        }
        
        #region NinjaScript generated code. Neither change nor remove.
        
        namespace NinjaTrader.NinjaScript.Indicators
        {
        public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
        {
        private VolumeUpDown_Alert[] cacheVolumeUpDown_Alert;
        public VolumeUpDown_Alert VolumeUpDown_Alert()
        {
        return VolumeUpDown_Alert(Input);
        }
        
        public VolumeUpDown_Alert VolumeUpDown_Alert(ISeries<double> input)
        {
        if (cacheVolumeUpDown_Alert != null)
        for (int idx = 0; idx < cacheVolumeUpDown_Alert.Length; idx++)
        if (cacheVolumeUpDown_Alert[idx] != null && cacheVolumeUpDown_Alert[idx].EqualsInput(input))
        return cacheVolumeUpDown_Alert[idx];
        return CacheIndicator<VolumeUpDown_Alert>(new VolumeUpDown_Alert(), input, ref cacheVolumeUpDown_Alert);
        }
        }
        }
        
        namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
        {
        public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
        {
        public Indicators.VolumeUpDown_Alert VolumeUpDown_Alert()
        {
        return indicator.VolumeUpDown_Alert(Input);
        }
        
        public Indicators.VolumeUpDown_Alert VolumeUpDown_Alert(ISeries<double> input )
        {
        return indicator.VolumeUpDown_Alert(input);
        }
        }
        }
        
        namespace NinjaTrader.NinjaScript.Strategies
        {
        public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
        {
        public Indicators.VolumeUpDown_Alert VolumeUpDown_Alert()
        {
        return indicator.VolumeUpDown_Alert(Input);
        }
        
        public Indicators.VolumeUpDown_Alert VolumeUpDown_Alert(ISeries<double> input )
        {
        return indicator.VolumeUpDown_Alert(input);
        }
        }
        }
        
        #endregion

        Comment


          #5
          Hello Cormick,

          Are you setting doOnce back to false when you are ready to reset and allow a new alert?
          Chelsea B.NinjaTrader Customer Service

          Comment


            #6
            Hello Chelsea,
            Thanks for the suggestion.
            I'm not sure I understand how to set doOnce back to false and allow a new alert on next bars.
            Following the logic of https://ninjatrader.com/support/foru...725#post813725
            what am I missing?


            Here's how I interpret it:
            Code:
            [B]private bool doOnce = false;[/B]
            // set doOnce to false by default ...

            Code:
            if(CurrentBar < 1) return;
            if (VOL()[0] >= VOLMA(5)[1] && [B](doOnce == false)) [/B]
            // ... if volume gets >= VOLMA and doOnce is currently false, then ...

            Code:
            { PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\VolumeSpike.wav");
            // ... fire the sound alert
            Code:
            [B]doOnce = true; ...[/B] }
            // ... and limit the alert to only one firing

            Do I need to add back

            Code:
            [B]doOnce = false;[/B]
            Code:
            { [B]private bool doOnce = false;[/B] ...
            
            if(CurrentBar < 1)return;
            if (VOL()[0] >= VOLMA(5)[1] &&
            [B](doOnce == false)[/B])
            {
            PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\VolumeSpike.wav");
            [B]doOnce = true;
            doOnce = false;[/B]
            }
            The goal is for the alert to fire once per bar max, to avoid the current issue of the alerts firing endlessly upon each new contract past the VOLMA(5)[1] threshold.

            How to get it to fire once only per bar? with reset on every bar?

            Comment


              #7
              Hello Cormick,

              The condition requires doOnce to be false. Then it is set to true.
              If it is never back to false the condition can never run again.

              If you want to reset you will need to set doOnce to false. This could be when IsFirstTickOfBar is true if you want to reset on a new bar.
              Chelsea B.NinjaTrader Customer Service

              Comment


                #8
                Thanks a lot for the IsFirstTickOfBar suggestion.



                The initial problem was that it doesn't fire the alert with the BRIEF CODE version of https://ninjatrader.com/support/foru...08#post1141108

                in the first place.

                Shouldn't it at least fire it once with the BRIEF CODE version above (as per the NinjaTrader_AlanP's answer)?


                About the IsFirstTickOfBar suggestion:

                Is that the correct way to get it back to false?

                Code:
                { [B]private bool doOnce = false;[/B] ...
                
                
                protected override void OnBarUpdate()
                {
                if(CurrentBar < 1)return;
                if (VOL()[0] >= VOLMA(5)[1]) &&
                [B](doOnce == false)[/B])
                {
                PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\VolumeSpike.wav");
                [B]doOnce = true;[/B]
                }
                
                if (IsFirstTickOfBar)
                {
                [B]doOnce = false;[/B]
                }
                
                if (Close[0] >= Open[0])
                {
                UpVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
                DownVolume.Reset();
                }
                else
                {
                UpVolume.Reset();
                DownVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
                }
                }

                Comment


                  #9
                  Hello Cormick,

                  Sounds and Alerts will only trigger in real-time.

                  To understand the behavior, use prints.

                  Print the time of the bar, print State, print VOL()[0], print VOLMA(5)[1], print doOnce. Include labels with the prints.

                  Below is a link to a forum post that demonstrates using prints to understand behavior and includes videos.
                  https://ninjatrader.com/support/foru...121#post791121

                  Save the output to a text file and include this with your reply.


                  Where you have mentioned:
                  "About the IsFirstTickOfBar suggestion:
                  Is that the correct way to get it back to false?"

                  Yes, assigning doOnce a value of false will make the variable hold a false value. This value you are looking for in the condition.

                  Think of a light switch. If the light switch is on, the bool is true. If the light switch is off, the bool is false.
                  You place a person in a dark room with the instruction 'if the light is off, and some other action happens, then turn the light on and also ring a buzzer'.
                  The room is dark, the other action happens, so they turn the light on.
                  The light is still on a few minutes later and the action happens again. The person does not ring buzzer because the light was already on.
                  They will not turn the light back off unless you tell them to.
                  Wait one minute. If the light is on, turn the light back off.
                  Now that the light is off, the person will again ring the buzzer and turn on the light of the action occurs. Again they will wait to turn the light off until you give them that instruction.

                  I am happy to assist with analyzing the output.
                  Last edited by NinjaTrader_ChelseaB; 02-10-2021, 03:16 PM.
                  Chelsea B.NinjaTrader Customer Service

                  Comment


                    #10
                    Thanks for the tutorial and Youtube channel. Subscribed.

                    Here's the Print code I used:
                    Code:
                    Print(string.Format("{0} | VOL()[0]: {1} | State: {2} | VOLMA(5)[1]: {3} | doOnce: {4}", Time[0], VOL()[0], State, VOLMA(5)[1], doOnce));
                    Within this context:
                    Code:
                     protected override void OnBarUpdate()
                    {
                    if(CurrentBar < 1)return;
                    if (VOL()[0] >= VOLMA(5)[1] &&
                    (doOnce == false))
                    {
                    PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\CrudeVolumeSpike.wav");
                    doOnce = true; // prevent additional alerts
                    }
                    
                    if (IsFirstTickOfBar)
                    {
                    doOnce = false;
                    }
                    
                    Print(string.Format("{0} | VOL()[0]: {1} | State: {2} | VOLMA(5)[1]: {3} | doOnce: {4}", Time[0], VOL()[0], State, VOLMA(5)[1], doOnce));
                    
                    if (Close[0] >= Open[0])
                    {
                    UpVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
                    DownVolume.Reset();
                    }
                    else
                    {
                    UpVolume.Reset();
                    DownVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
                    }
                    }

                    Full Indicator Code:
                    Code:
                    //
                    // Copyright (C) 2020, NinjaTrader LLC <www.ninjatrader.com>.
                    // NinjaTrader reserves the right to modify or overwrite this NinjaScript component with each release.
                    //
                    #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.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 VolumeUpDown_AlertX : Indicator
                    {
                    private bool doOnce = false;
                    
                    protected override void OnStateChange()
                    {
                    if (State == State.SetDefaults)
                    {
                    Name = "VolumeUpDown_AlertX";
                    Calculate = Calculate.OnEachTick;
                    DrawOnPricePanel = false;
                    IsOverlay = false;
                    IsSuspendedWhileInactive = true;
                    
                    AddPlot(new Stroke(Brushes.DarkCyan, 2), PlotStyle.Bar, NinjaTrader.Custom.Resource.VolumeUp);
                    AddPlot(new Stroke(Brushes.Crimson, 2), PlotStyle.Bar, NinjaTrader.Custom.Resource.VolumeDown);
                    AddLine(Brushes.DarkGray, 0, NinjaTrader.Custom.Resource.NinjaScriptIndicatorZe roLine);
                    }
                    else if (State == State.Historical)
                    {
                    if (Calculate == Calculate.OnPriceChange)
                    {
                    Draw.TextFixed(this, "NinjaScriptInfo", string.Format(NinjaTrader.Custom.Resource.NinjaScr iptOnPriceChangeError, Name), TextPosition.BottomRight);
                    Log(string.Format(NinjaTrader.Custom.Resource.Ninj aScriptOnPriceChangeError, Name), LogLevel.Error);
                    }
                    }
                    }
                    
                    protected override void OnBarUpdate()
                    {
                    if(CurrentBar < 1)return;
                    if (VOL()[0] >= VOLMA(5)[1] &&
                    (doOnce == false))
                    {
                    PlaySound(@"C:\Program Files (x86)\NinjaTrader 8\sounds\CrudeVolumeSpike.wav");
                    doOnce = true; // prevent additional alerts
                    }
                    
                    if (IsFirstTickOfBar)
                    {
                    doOnce = false;
                    }
                    
                    Print(string.Format("{0} | VOL()[0]: {1} | State: {2} | VOLMA(5)[1]: {3} | doOnce: {4}", Time[0], VOL()[0], State, VOLMA(5)[1], doOnce));
                    
                    if (Close[0] >= Open[0])
                    {
                    UpVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
                    DownVolume.Reset();
                    }
                    else
                    {
                    UpVolume.Reset();
                    DownVolume[0] = Instrument.MasterInstrument.InstrumentType == InstrumentType.CryptoCurrency ? Core.Globals.ToCryptocurrencyVolume((long)Volume[0]) : Volume[0];
                    }
                    }
                    
                    #region Properties
                    [Browsable(false)]
                    [XmlIgnore]
                    public Series<double> DownVolume
                    {
                    get { return Values[1]; }
                    }
                    
                    [Browsable(false)]
                    [XmlIgnore]
                    public Series<double> UpVolume
                    {
                    get { return Values[0]; }
                    }
                    #endregion
                    }
                    }
                    
                    #region NinjaScript generated code. Neither change nor remove.
                    
                    namespace NinjaTrader.NinjaScript.Indicators
                    {
                    public partial class Indicator : NinjaTrader.Gui.NinjaScript.IndicatorRenderBase
                    {
                    private VolumeUpDown_AlertX[] cacheVolumeUpDown_AlertX;
                    public VolumeUpDown_AlertX VolumeUpDown_AlertX()
                    {
                    return VolumeUpDown_AlertX(Input);
                    }
                    
                    public VolumeUpDown_AlertX VolumeUpDown_AlertX(ISeries<double> input)
                    {
                    if (cacheVolumeUpDown_AlertX != null)
                    for (int idx = 0; idx < cacheVolumeUpDown_AlertX.Length; idx++)
                    if (cacheVolumeUpDown_AlertX[idx] != null && cacheVolumeUpDown_AlertX[idx].EqualsInput(input))
                    return cacheVolumeUpDown_AlertX[idx];
                    return CacheIndicator<VolumeUpDown_AlertX>(new VolumeUpDown_AlertX(), input, ref cacheVolumeUpDown_AlertX);
                    }
                    }
                    }
                    
                    namespace NinjaTrader.NinjaScript.MarketAnalyzerColumns
                    {
                    public partial class MarketAnalyzerColumn : MarketAnalyzerColumnBase
                    {
                    public Indicators.VolumeUpDown_AlertX VolumeUpDown_AlertX()
                    {
                    return indicator.VolumeUpDown_AlertX(Input);
                    }
                    
                    public Indicators.VolumeUpDown_AlertX VolumeUpDown_AlertX(ISeries<double> input )
                    {
                    return indicator.VolumeUpDown_AlertX(input);
                    }
                    }
                    }
                    
                    namespace NinjaTrader.NinjaScript.Strategies
                    {
                    public partial class Strategy : NinjaTrader.Gui.NinjaScript.StrategyRenderBase
                    {
                    public Indicators.VolumeUpDown_AlertX VolumeUpDown_AlertX()
                    {
                    return indicator.VolumeUpDown_AlertX(Input);
                    }
                    
                    public Indicators.VolumeUpDown_AlertX VolumeUpDown_AlertX(ISeries<double> input )
                    {
                    return indicator.VolumeUpDown_AlertX(input);
                    }
                    }
                    }
                    
                    #endregion
                    Txt attached.

                    Thanks a lot.
                    Attached Files

                    Comment


                      #11
                      2 New txts Output attached.

                      I did get several sound alerts.

                      But I'm not sure it limits it to 1 alert per bar.

                      The alerts seem to trigger at the start of the New bar (00 minute) on the output files. Why don't they trigger 'on the fly'/the instant the VOL >= VOLMA?

                      I checked and the indicator is set to calculate on each tick.



                      Attached Files

                      Comment


                        #12
                        One 2 new txts:
                        Attached Files

                        Comment


                          #13
                          Hello Cormick,

                          It is triggering 'on the fly' when the condition is true.

                          There are 61 ticks received within the first second before the condition is true.

                          Line 5514 is where the bar opens and the state becomes real-time.
                          Line 5567 is where the VOL becomes greater than or equal to the VOLMA.

                          2/11/2021 12:01:00 AM | VOL()[0]: 61 | State: Realtime | VOLMA(5)[1]: 61.8637396321256 | doOnce: False
                          2/11/2021 12:01:00 AM | VOL()[0]: 62 | State: Realtime | VOLMA(5)[1]: 61.8637396321256 | doOnce: True

                          This all happens in 12:01:00 AM before 12:01:01 AM.

                          VOLMA is producing a value of 61.86. The VOL is 62 and is greater than the VOLMA.

                          Is this not what you wanted?

                          If you don't want the action when the VOL is greater than the VOLMA from 2 bars ago, then when would you prefer the action?
                          Chelsea B.NinjaTrader Customer Service

                          Comment


                            #14
                            Thanks for the details.
                            Seems to work as intended.
                            Here a short screen capture demo:


                            What do you think?
                            Last edited by Cormick; 02-10-2021, 05:45 PM.

                            Comment


                              #15
                              Seems all right for now.

                              Another question.
                              I noticed you have some flash tutorials here:

                              Free online storage and sharing with Screencast.com. 2 GB of storage and 2 GB of bandwidth per month for free. We won't compress, alter or take ownership of your content.


                              Flash player is no longer supported and we can't download it anymore.

                              Could you convert these flash videos and post them on the Youtube channel? I checked and the 1st one at least is not in the Youtube channel videos.
                              Or if you'd like you can use this free for basic use Active Presenter 8 app (you can export files with custom pfs (I used 5 fps on the previous video for small files):
                              Download ActivePresenter - eLearning Authoring Tool, Screen Recorder, and Video Editor



                              Thanks a lot.

                              Comment

                              Latest Posts

                              Collapse

                              Topics Statistics Last Post
                              Started by geddyisodin, Today, 05:20 AM
                              1 response
                              11 views
                              0 likes
                              Last Post NinjaTrader_Gaby  
                              Started by Max238, Today, 01:28 AM
                              3 responses
                              31 views
                              0 likes
                              Last Post Max238
                              by Max238
                               
                              Started by timko, Today, 06:45 AM
                              2 responses
                              13 views
                              0 likes
                              Last Post NinjaTrader_ChristopherJ  
                              Started by habeebft, Today, 07:27 AM
                              0 responses
                              5 views
                              0 likes
                              Last Post habeebft  
                              Started by Tim-c, Today, 03:54 AM
                              1 response
                              8 views
                              0 likes
                              Last Post NinjaTrader_BrandonH  
                              Working...
                              X