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

Building a historical bid and ask price

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

    Building a historical bid and ask price

    I'm trying to build a simple indicator that you can overlay on your whatever chart you have; I intend to construct an historical "midpoint" series (bid+ask)/2 in order to plot or using in others indicators.

    Since I'm not a programmer I've been trying to Cut and Paste lines of codes references from help guide but I'm struggling here

    Following is the main code that I'm writing, using GetcurrentBid() and GetcurrentAsk(), but I see they don't work for historical data, if anybody has a solution to this please let me know, it'll be highly appreciated.

    public class Midpoint : Indicator
    {
    #region Variables
    private DataSeries myDataSeries;
    // Wizard generated variables
    // User defined variables (add any user defined variables below)
    #endregion

    /// <summary>
    /// This method is used to configure the indicator and is called once before any bar data is loaded.
    /// </summary>
    protected override void Initialize()
    {
    Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "Mpoint"));
    CalculateOnBarClose = false;
    Overlay = true;
    myDataSeries = new DataSeries(this); // this refers to the indicator/strategy itself
    // and syncs the DataSeries object to historical
    // data bars
    }

    /// <summary>
    /// Called on each bar update event (incoming tick)
    /// </summary>
    protected override void OnBarUpdate()
    {
    // Use this method for calculating your indicator values. Assign a value to each
    // plot below by replacing 'Close[0]' with your own formula.
    // Calculate the range of the current bar and set the value
    myDataSeries.Set((GetCurrentBid() + GetCurrentAsk())/2);
    Mpoint.Set(myDataSeries[0]);
    Print("Bid: " + GetCurrentBid(0).ToString() + " Ask: " + GetCurrentAsk(0).ToString() + " Avg: " + ((GetCurrentBid() + GetCurrentAsk()) / 2).ToString());
    }

    #2
    Could it be possible using SusbscribeMarketData() and MarketData() ? please I need help with this

    Thanks in advance

    Comment


      #3
      pstrusi, I was just speaking with AdamP, who said he also has an open ticket with you for this issue. That puts my count at four tickets you've opened for this same exact issue. In the future, please do not send in an email and open three forum threads to ask the same question, we will get back to you no matter how you choose to communicate with us. The forum has the additional benefit of being open to everyone, so we will continue your ticket right here in this thread and close all the others.

      This indicator will be quite complex if done correctly. Basically, you'll need to use historical bid/ask data until the indicator goes live, at which point you should start using the incoming market data, from OnMarketData() - http://www.ninjatrader.com/support/h...marketdata.htm.

      The historical bid/ask data is accessed like a regular data series (Close, High, Low, etc) but the bid/ask will be secondary/tertiary data series.

      To add the historical bid/ask, you can do this:
      Code:
      Initialize()
      {
         // assuming one minute es12-11 bars
         Add("ES 12-11", PeriodType.Minute, 1, MarketDataType.Ask); // series index 1
         Add("ES 12-11", PeriodType.Minute, 1, MarketDataType.Bid); // series index 2
      }
      Then you can access these values directly:
      Code:
      OnBarUpdate()
      {
        if (Historical)
        {
          double historical_ask = Close[1][0] // because the ask series index = 1;
          double historical_bid = Close[2][0] // bid series index = 2;
      
          double midpoint = (historical_ask + historical_bid) / 2;
         }
      }
      But since you want to use real-time values when not on historical data, it becomes more complicated. You will have to add additional private data series to store this data, so the code will start looking something like this:
      Code:
      private double realtime_bid, realtime_ask, realtime_mid;
      private DataSeries askSeries;
      private DataSeries bidSeries;
      private DataSeries midPointSeries;
      
      Initialize()
      {
         // add midpoint plot 
         Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "MPline"));
      
         Overlay = true;
         // assuming one minute es12-11 bars
         Add("ES 12-11", PeriodType.Minute, 1, MarketDataType.Ask); // series index 1
         Add("ES 12-11", PeriodType.Minute, 1, MarketDataType.Bid); // series index 2
         midPointSeries = new DataSeries(this);
         askSeries = new DataSeries(this);
         bidSeries = new DataSeries(this);
      }
      
      OnMarketData()
      {
                  if (e.MarketDataType == MarketDataType.Bid)
                      realtime_bid = e.Price;
                  else if (e.MarketDataType == MarketDataType.Ask)
                      realtime_ask = e.Price;
                  
                  if (realtime_bid != 0 && realtime_ask != 0)
                      realtime_mid = (realtime_ask + realtime_bid)/2;
      }
      
      OnBarUpdate()
      {
         if (Historical)
         {
           double historical_ask = Close[1][0] // because the ask series index = 1;
           double historical_bid = Close[2][0] // bid series index = 2;
      
           double midpoint = (historical_ask + historical_bid) / 2;
           MPline.Set(midpoint);
         }
         else
         {
           // not historical, use real-time bid/ask
           MPline.Set(realtime_mid);
         }
      }
      
      #region Properties
      [Browsable(false)]    // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
      [XmlIgnore()]        // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
      public DataSeries MPline
      {
          get { return Values[0]; }
      }
      Please be aware we do not typically write nearly this much code for customers due to bandwidth constrains, but since this is a complex topic, it was necessary.

      Look over the code very carefully and let us know if you have any additional questions.
      AustinNinjaTrader Customer Service

      Comment


        #4
        Thanks a lot Austin for this support; I'll try this code, it seems that will be very useful.
        The most important data to me is the historical one cause backtesting to do.

        Generally I post here for everything but sent e-mails cause it had code and it seemed to me that would be too much garbage for this forum, but don't worry, I'll be posting everything here.

        If I need some additional support regarding my indicator I'll be addressing it in this post

        Best regards,

        Comment


          #5
          By the way Austin, despite I already did the suggestion in the feedback forum, it seems pretty useful and important that NT consider to include Bid/Ask/Midpoint data as input for indicators/strategy in the coming versions.

          I appreciate a lot the constant and good attention of all NT support team

          Best regards,
          PS

          Comment


            #6
            Austin and Adam, I had to finish my historical module for Midpooint (Bid+Ask)/2 in other way, it took me time cause I'm not a programmer but applying logic could be solved. The key here was understanding and using well "BarsInProgress"

            In order to be useful for this forum here is what I did:

            HISTORICAL MIDPOINT FOR ES 12-11

            #region Using declarations
            using System;
            using System.ComponentModel;
            using System.Diagnostics;
            using System.Drawing;
            using System.Drawing.Drawing2D;
            using System.Xml.Serialization;
            using NinjaTrader.Cbi;
            using NinjaTrader.Data;
            using NinjaTrader.Gui.Chart;
            #endregion

            // This namespace holds all indicators and is required. Do not change it.
            namespace NinjaTrader.Indicator
            {
            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            [Description("MIDP = ( Bid + Ask )/2")]
            public class MIDP : Indicator
            {
            #region Variables
            private int seconds = 5; // Default setting for Seconds
            private DataSeries historical_ask;
            private DataSeries historical_bid;
            #endregion

            /// <summary>
            /// This method is used to configure the indicator and is called once before any bar data is loaded.
            /// </summary>
            protected override void Initialize()
            {
            Add(new Plot(Color.FromKnownColor(KnownColor.Orange), PlotStyle.Line, "Midpointdata"));
            Overlay = true;
            Add("ES 12-11", PeriodType.Second, seconds, MarketDataType.Ask); // series index 1
            Add("ES 12-11", PeriodType.Second, seconds, MarketDataType.Bid); // series index 2
            historical_ask = new DataSeries(this);
            historical_bid = new DataSeries(this);
            }

            /// <summary>
            /// Called on each bar update event (incoming tick)
            /// </summary>
            protected override void OnBarUpdate()
            {
            if ( BarsInProgress == 0)
            {
            historical_bid.Set(Closes[2][0]);
            historical_ask.Set(Closes[1][0]);
            Midpointdata.Set((historical_ask[0]+historical_bid[0])/2);
            Print("Bid: " + historical_bid[0].ToString() + " Ask: " + historical_ask[0].ToString() + " Avg: " + Midpointdata[0].ToString());
            }

            }

            #region Properties
            [Browsable(false)] // this line prevents the data series from being displayed in the indicator properties dialog, do not remove
            [XmlIgnore()] // this line ensures that the indicator can be saved/recovered as part of a chart template, do not remove
            public DataSeries Midpointdata
            {
            get { return Values[0]; }
            }

            [Description("")]
            [GridCategory("Parameters")]
            public int Seconds
            {
            get { return seconds; }
            set { seconds = Math.Max(1, value); }
            }
            #endregion
            }
            }

            #region NinjaScript generated code. Neither change nor remove.
            // This namespace holds all indicators and is required. Do not change it.
            namespace NinjaTrader.Indicator
            {
            public partial class Indicator : IndicatorBase
            {
            private MIDP[] cacheMIDP = null;

            private static MIDP checkMIDP = new MIDP();

            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            /// <returns></returns>
            public MIDP MIDP(int seconds)
            {
            return MIDP(Input, seconds);
            }

            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            /// <returns></returns>
            public MIDP MIDP(Data.IDataSeries input, int seconds)
            {
            if (cacheMIDP != null)
            for (int idx = 0; idx < cacheMIDP.Length; idx++)
            if (cacheMIDP[idx].Seconds == seconds && cacheMIDP[idx].EqualsInput(input))
            return cacheMIDP[idx];

            lock (checkMIDP)
            {
            checkMIDP.Seconds = seconds;
            seconds = checkMIDP.Seconds;

            if (cacheMIDP != null)
            for (int idx = 0; idx < cacheMIDP.Length; idx++)
            if (cacheMIDP[idx].Seconds == seconds && cacheMIDP[idx].EqualsInput(input))
            return cacheMIDP[idx];

            MIDP indicator = new MIDP();
            indicator.BarsRequired = BarsRequired;
            indicator.CalculateOnBarClose = CalculateOnBarClose;
            #if NT7
            indicator.ForceMaximumBarsLookBack256 = ForceMaximumBarsLookBack256;
            indicator.MaximumBarsLookBack = MaximumBarsLookBack;
            #endif
            indicator.Input = input;
            indicator.Seconds = seconds;
            Indicators.Add(indicator);
            indicator.SetUp();

            MIDP[] tmp = new MIDP[cacheMIDP == null ? 1 : cacheMIDP.Length + 1];
            if (cacheMIDP != null)
            cacheMIDP.CopyTo(tmp, 0);
            tmp[tmp.Length - 1] = indicator;
            cacheMIDP = tmp;
            return indicator;
            }
            }
            }
            }

            // This namespace holds all market analyzer column definitions and is required. Do not change it.
            namespace NinjaTrader.MarketAnalyzer
            {
            public partial class Column : ColumnBase
            {
            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            /// <returns></returns>
            [Gui.Design.WizardCondition("Indicator")]
            public Indicator.MIDP MIDP(int seconds)
            {
            return _indicator.MIDP(Input, seconds);
            }

            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            /// <returns></returns>
            public Indicator.MIDP MIDP(Data.IDataSeries input, int seconds)
            {
            return _indicator.MIDP(input, seconds);
            }
            }
            }

            // This namespace holds all strategies and is required. Do not change it.
            namespace NinjaTrader.Strategy
            {
            public partial class Strategy : StrategyBase
            {
            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            /// <returns></returns>
            [Gui.Design.WizardCondition("Indicator")]
            public Indicator.MIDP MIDP(int seconds)
            {
            return _indicator.MIDP(Input, seconds);
            }

            /// <summary>
            /// MIDP = ( Bid + Ask )/2
            /// </summary>
            /// <returns></returns>
            public Indicator.MIDP MIDP(Data.IDataSeries input, int seconds)
            {
            if (InInitialize && input == null)
            throw new ArgumentException("You only can access an indicator with the default input/bar series from within the 'Initialize()' method");

            return _indicator.MIDP(input, seconds);
            }
            }
            }
            #endregion

            Comment


              #7
              Hi,

              I add the following statements:

              In Initialize:
              Add("ES", PeriodType.Minute, 15, MarketDataType.Bid);
              Add("ES", PeriodType.Minute, 15, MarketDataType.Ask);
              In OnBarUpdate, I try plotting historical bid:
              Value.Set(Closes[1][0]);
              But the plot just shows a constant line at zero level.

              So apparently there are no data for bid and ask series if added?

              Thanks.
              Pi
              Last edited by ninZa; 11-29-2014, 04:00 AM.
              ninZa
              NinjaTrader Ecosystem Vendor - ninZa.co

              Comment


                #8
                Hi Pi,

                Please consider that I'm not a NT support member, but I'd try to help you with some basics:

                1. Go to "tools", "Historical Data Manager", Edit" and check that effectively you've downloaded all tick and minutes data ( bid, ask and close ) and not just close

                2. Be sure that "Bars required" accordingly to your needs

                3. Pick the right colors in order to be able to see your indicator ( check how is built MACD and you'll see )

                4. Uses of:
                if ( BarsInProgress == 0)
                {
                // print or do whatever you want once a new close price is seen
                }

                I hope you can solve it

                Comment


                  #9
                  Originally posted by pstrusi View Post
                  Hi Pi,

                  Please consider that I'm not a NT support member, but I'd try to help you with some basics:

                  1. Go to "tools", "Historical Data Manager", Edit" and check that effectively you've downloaded all tick and minutes data ( bid, ask and close ) and not just close

                  2. Be sure that "Bars required" accordingly to your needs

                  3. Pick the right colors in order to be able to see your indicator ( check how is built MACD and you'll see )

                  4. Uses of:
                  if ( BarsInProgress == 0)
                  {
                  // print or do whatever you want once a new close price is seen
                  }

                  I hope you can solve it
                  Thanks for your reply.

                  Even though I have chosen to include Bid and Ask in Historical Data Manager (tab Download), I cannot display a Bid or Ask chart of EUR/USD. Screenshot attached.
                  Attached Files
                  ninZa
                  NinjaTrader Ecosystem Vendor - ninZa.co

                  Comment


                    #10
                    Hello ninZa,

                    Thank you for your post.

                    Who do you connect to for data? This is viewed in the bottom left hand corner of the Control Center in green.

                    Comment


                      #11
                      Sure I connect to Kinetick (not EOD).

                      Thanks.
                      Pi
                      ninZa
                      NinjaTrader Ecosystem Vendor - ninZa.co

                      Comment


                        #12
                        Hello NinZa,

                        Thank you for your response.

                        Unfortunately, historical Bid and Ask data is not supplied for Minute or Day data from Kinetick. Historical Bid and Ask data is supplied for Tick data. Please visit the following link for more information: http://www.ninjatrader.com/support/h...rical_data.htm

                        Comment


                          #13
                          Thank you. I got it, Patrick
                          ninZa
                          NinjaTrader Ecosystem Vendor - ninZa.co

                          Comment

                          Latest Posts

                          Collapse

                          Topics Statistics Last Post
                          Started by Jon17, Today, 04:33 PM
                          0 responses
                          1 view
                          0 likes
                          Last Post Jon17
                          by Jon17
                           
                          Started by Javierw.ok, Today, 04:12 PM
                          0 responses
                          4 views
                          0 likes
                          Last Post Javierw.ok  
                          Started by timmbbo, Today, 08:59 AM
                          2 responses
                          10 views
                          0 likes
                          Last Post bltdavid  
                          Started by alifarahani, Today, 09:40 AM
                          6 responses
                          40 views
                          0 likes
                          Last Post alifarahani  
                          Started by Waxavi, Today, 02:10 AM
                          1 response
                          19 views
                          0 likes
                          Last Post NinjaTrader_LuisH  
                          Working...
                          X