Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Order on close

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

    #16
    Along these lines I tried to following and ran into this problem

    Essentially we are trying to calculate and indicator using the partial bar. I set this up as follows:

    a) I was using continuous futures with the CME RTH session ( 405 minute )
    b) Strategy adds a 400 minute series ( more efficient than using a 5 minute as the code iterates less)
    c) Create a DataSeries aligned with the 405 minute session but offset by 1 where the last entry is the close of the FirstBarOfSession of 400 minute bar series.
    d) I tried doing calculations on the modified dataseries ( named PartialClose ) but the value is incorrect. Probably because I correct the prior element with the actual close of the 405 minute bar. My guess is there is some cacheing of the values when using an indicator. Is there a way to correct this?

    The below strategy will plot the value of
    a) sma using the 405 minute bar
    b) sma using the partial close dataseries (some how calculated wrong)
    c) manually calculate it by using SUM function and adding the most recent partial close and dividing by the length of the average (verified correct calculation)

    I was trying to figure out a clean way to achieve an entry or exit on close that leverages all of the indicators code base instead of creating a series of partial bar calculations for every indicator but I haven't figured out a way to make it work.

    Any thoughts?

    Code:
    #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.Indicator;
    using NinjaTrader.Gui.Chart;
    using NinjaTrader.Strategy;
    #endregion
    
    // This namespace holds all strategies and is required. Do not change it.
    namespace NinjaTrader.Strategy
    {
        /// <summary>
        /// 
        /// </summary>
        [Description("")]
        public class TestOnClose : Strategy
        {
            #region Variables
    		double p0 = 0, p1 = 0;	
    		private DataSeries PartialClose;
            // Wizard generated variables
            private int fastLength = 10; // Default setting for FastLength
            private int slowLength = 30; // Default setting for SlowLength
            // User defined variables (add any user defined variables below)
            #endregion
    
            /// <summary>
            /// This method is used to configure the strategy and is called once before any strategy method is called.
            /// </summary>
            protected override void Initialize()
            {
    			//	ALIGNED WITH MAIN SESSION BUT DISPLACED BY ONE
    			PartialClose = new DataSeries(this);
    			
    			Add(PeriodType.Minute, 400);
    			
    			//	ACTUAL 405M CLOSE
    			Add(SMA(fastLength));
    			SMA(fastLength).Plots[0].Pen.Color = Color.Cyan;
    			
    			Add(StrategyPlot(0));
    			Add(StrategyPlot(1));
    			StrategyPlot(0).Plots[0].Pen.Color = Color.Magenta;
    			StrategyPlot(1).Plots[0].Pen.Color = Color.Red;
    			StrategyPlot(0).PanelUI = 1;
    			StrategyPlot(1).PanelUI = 1;
    			
                CalculateOnBarClose = true;
            }
    
            /// <summary>
            /// Called on each bar update event (incoming tick)
            /// </summary>
            protected override void OnBarUpdate()
            {
    			//	FULL SESSION SERIES
    			if(BarsInProgress == 0)
    			{
    				//	UPDATE PARTIAL CLOSE SERIES WITH FINAL CLOSE
    				if(PartialClose.Count > 1) PartialClose.Set(1,Closes[0][1]);
    				
    				StrategyPlot(0).Value.Set(p0);
    				StrategyPlot(1).Value.Set(p1);				
    			}
    			//	PARTIAL SESSION SERIES
    			else if(BarsInProgress == 1)
    			{
    				//	USING A BAR SETTING OF 5 MINUTE LESS RESULTS IN 2 BARS PER SESSION, SO FIRSTBAROFSESSION WORKS
    				if(BarsArray[1].FirstBarOfSession)
    				{
    					//	UPDATE PARTIAL CLOSE SERIES WITH PARTIAL CLOSE
    					if(PartialClose.Count > 0) PartialClose.Set(0, Closes[1][0]);
    					
    					//	ENSURE YOU HAVE ENOUGH BARS
    					if(PartialClose.Count < slowLength) return;
    
    					//	CALCULATE USING PARTIALCLOSE SERIES AND EXECUTE ORDER ON SECOND SERIES
    					double fastAvg = SMA(PartialClose,fastLength)[0];
    					double slowAvg = SMA(PartialClose,slowLength)[0];
    					
    					p0 = (SUM(PartialClose,fastLength - 1)[1] + Closes[1][0]) / fastLength;
    					p1 = fastAvg;
    					
    					if(Position.MarketPosition == MarketPosition.Flat && fastAvg > slowAvg)
    						EnterLong(1,1,"LE");
    					
    					if(Position.MarketPosition == MarketPosition.Long && fastAvg < slowAvg)
    						ExitLong(1,1,"LX","LE");
    				}
    			}
            }
    
            #region Properties
            [Description("")]
            [GridCategory("Parameters")]
            public int FastLength
            {
                get { return fastLength; }
                set { fastLength = Math.Max(1, value); }
            }
    
            [Description("")]
            [GridCategory("Parameters")]
            public int SlowLength
            {
                get { return slowLength; }
                set { slowLength = Math.Max(1, value); }
            }
            #endregion
        }
    }

    Comment


      #17
      Hello GrumpyTrader,

      Thank you for your response.

      What is your primary series? 405 minute or 5 minute?

      Comment


        #18
        Hi Patrick,
        The primary series is 405M when using the CME RTH session (should be equivalent to the RTH daily bar). The added series is the 400M bar (3:10pm CST).

        So I believe the OnBarUpdate order should be:

        400M BarsInProgress == 1 (3:10pm CST)
        405M BarsInProgress == 0 (3:15pm CST)
        400M BarsInProgress == 1 (3:15pm CST)

        The thought was for daily strategies executing at the close you only will get 3 calls to OnBarUpdate this way instead of the 85 calls when using a 5 minute data series.

        Originally posted by NinjaTrader_PatrickH View Post
        Hello GrumpyTrader,

        Thank you for your response.

        What is your primary series? 405 minute or 5 minute?
        Last edited by GrumpyTrader; 06-16-2015, 03:53 PM.

        Comment


          #19
          Hello GrumpyTrader,

          Thank you for your patience.

          Your code is working as expected on my end. The executions are occurring on the close of the 400 Minute Bar.

          Comment


            #20
            Thanks Patrick, but the problem is that the SMA calculations are coming out inconsistent (see the descriptions in my first post). Was wondering if you had any incite into that?

            Comment


              #21
              Hello GrumpyTrader,

              You descriptions are a little unclear, but I believe I resolved this by simply changing the following line to use the current value: if(PartialClose.Count > 1) PartialClose.Set(1,Closes[0][0]);

              Comment


                #22
                Thanks Patrick, you are correct that was a bug. Even after the correction though you will notice that there is a difference in the values between:

                a) double fastAvg = SMA(PartialClose,fastLength)[0];

                and

                b) p0 = (SUM(PartialClose,fastLength - 1)[1] + Closes[1][0]) / fastLength;

                or

                c) p0 = (SUM(BarsArray[0],fastLength - 1)[0] + Closes[1][0]) / fastLength;

                I believe they should all be equivalent. Here is an updated script demonstrating what i mean.

                Code:
                #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.Indicator;
                using NinjaTrader.Gui.Chart;
                using NinjaTrader.Strategy;
                #endregion
                
                // This namespace holds all strategies and is required. Do not change it.
                namespace NinjaTrader.Strategy
                {
                    /// <summary>
                    /// 
                    /// </summary>
                    [Description("")]
                    public class TestOnClose : Strategy
                    {
                        #region Variables
                		double p0 = 0, p1 = 0, p3 = 0;	
                		private DataSeries PartialClose;
                        // Wizard generated variables
                        private int fastLength = 10; // Default setting for FastLength
                        private int slowLength = 30; // Default setting for SlowLength
                        // User defined variables (add any user defined variables below)
                        #endregion
                
                        /// <summary>
                        /// This method is used to configure the strategy and is called once before any strategy method is called.
                        /// </summary>
                        protected override void Initialize()
                        {
                			//	ALIGNED WITH MAIN SESSION BUT DISPLACED BY ONE
                			PartialClose = new DataSeries(this);
                			
                			Add(PeriodType.Minute, 400);
                			
                			Add(StrategyPlot(0));
                			Add(StrategyPlot(1));
                			Add(StrategyPlot(2));
                			Add(StrategyPlot(3));
                			StrategyPlot(0).Plots[0].Pen.Color = Color.Magenta;
                			StrategyPlot(1).Plots[0].Pen.Color = Color.Red;
                			StrategyPlot(2).Plots[0].Pen.Color = Color.Cyan;
                			StrategyPlot(3).Plots[0].Pen.Color = Color.Green;
                			StrategyPlot(0).PanelUI = 1;
                			StrategyPlot(1).PanelUI = 1;
                			StrategyPlot(2).PanelUI = 1;
                			StrategyPlot(3).PanelUI = 1;
                			StrategyPlot(0).Plots[0].Name = "SMA PartialClose";
                			StrategyPlot(1).Plots[0].Name = "SUM PartialClose";
                			StrategyPlot(2).Plots[0].Name = "SMA Actual Close";
                			StrategyPlot(3).Plots[0].Name = "SMA Manual";
                			
                            CalculateOnBarClose = true;
                        }
                
                        /// <summary>
                        /// Called on each bar update event (incoming tick)
                        /// </summary>
                        protected override void OnBarUpdate()
                        {
                			Print(string.Format("{0}  {1}  {2}",BarsInProgress,Times[1][0].ToShortDateString(), Times[1][0].ToShortTimeString()));
                			
                			//	FULL SESSION SERIES
                			if(BarsInProgress == 0)
                			{
                				//	UPDATE PARTIAL CLOSE SERIES WITH FINAL CLOSE
                				if(PartialClose.Count > 1) PartialClose.Set(1,Closes[0][0]);
                				
                				StrategyPlot(0).Value.Set(p0);
                				StrategyPlot(1).Value.Set(p1);
                				StrategyPlot(2).Value.Set(SMA(BarsArray[0],fastLength)[0]);
                				StrategyPlot(3).Value.Set(p3);
                			}
                			//	PARTIAL SESSION SERIES
                			else if(BarsInProgress == 1)
                			{
                				//	USING A BAR SETTING OF 5 MINUTE LESS RESULTS IN 2 BARS PER SESSION, SO FIRSTBAROFSESSION WORKS
                				if(BarsArray[1].FirstBarOfSession)
                				{
                					//	UPDATE PARTIAL CLOSE SERIES WITH PARTIAL CLOSE
                					if(PartialClose.Count > 0) PartialClose.Set(0, Closes[1][0]);
                					
                					//	ENSURE YOU HAVE ENOUGH BARS
                					if(PartialClose.Count < slowLength) return;
                
                					double fastAvg = SMA(PartialClose,fastLength)[1];
                					
                					
                					//	CALCULATE USING PARTIALCLOSE SERIES AND EXECUTE ORDER ON SECOND SERIES
                					fastAvg = SMA(PartialClose,fastLength)[0];
                					double slowAvg = SMA(PartialClose,slowLength)[0];
                					
                					//	SMA CALCULATED USING PARTIALCLOSE SERIES
                					p0 = fastAvg;
                					//	SMA CALCULATED USING 405M CLOSES + LAST 400M CLOSE
                					p1 = (SUM(BarsArray[0],fastLength - 1)[0] + Closes[1][0]) / fastLength;
                					//	SMA MANUAL
                					p3 = MYSUM(PartialClose, fastLength);
                					
                					if(Position.MarketPosition == MarketPosition.Flat && fastAvg > slowAvg)
                						EnterLong(1,1,"LE");
                					
                					if(Position.MarketPosition == MarketPosition.Long && fastAvg < slowAvg)
                						ExitLong(1,1,"LX","LE");
                				}
                			}
                        }
                		
                		private double MYSUM( DataSeries ds, int length )
                		{
                			double sum = 0;
                			for(int i = 0; i < length; i++)
                			{
                				sum += ds[i];
                			}
                			return sum / length;
                		}
                
                        #region Properties
                        [Description("")]
                        [GridCategory("Parameters")]
                        public int FastLength
                        {
                            get { return fastLength; }
                            set { fastLength = Math.Max(1, value); }
                        }
                
                        [Description("")]
                        [GridCategory("Parameters")]
                        public int SlowLength
                        {
                            get { return slowLength; }
                            set { slowLength = Math.Max(1, value); }
                        }
                        #endregion
                    }
                }
                Last edited by GrumpyTrader; 06-17-2015, 12:15 PM.

                Comment


                  #23
                  Hello GrumpyTrader,

                  Thank you for your response.

                  The p0 should be the following:
                  Code:
                  p0  = ((SMA(PartialClose,fastLength)[1] * fastLength) + PartialClose[0] - PartialClose[fastLength]) / fastLength;

                  Comment


                    #24
                    Hi Patrick,
                    I appreciate your time on this issue. Your fix is similar to what I did by recalculating the SMA using the SUM method. The whole spirit of my original question is to avoid having to create all of these adjusted indicator calculations such as you suggested for p0 above. Ideally, I would like to have a dataseries like PartialCloses and just be able to go "SMA(PartialCloses,5)[0]" to get the value instead of all the adjustments. Otherwise I would need to create a library of methods that does all these calculations for me which seems a bit redundant.

                    The spirit of the whole exercise is to be able to back test strategies where I enter/exit on the close of daily bar. The ability of a strategy to be able to test this easily is important because a) over the past decade there is a strong positive bias during the overnight sessions in the equity markets, b) when running statistical analysis it is critical to be able to breakout between "close to open" movements from the others, c) and lastly the ability to test these scenarios are easy to test in every other platform I've used (and lets just say I've been around the block a few times).

                    Is it possible this functionality could be implemented in NT8 at some point?

                    Comment


                      #25
                      Hello GrumpyTrader,

                      Thank you for your response.

                      The PartialClose you created is working on my end with our added fixes.

                      Comment

                      Latest Posts

                      Collapse

                      Topics Statistics Last Post
                      Started by FrancisMorro, Today, 03:24 AM
                      0 responses
                      1 view
                      0 likes
                      Last Post FrancisMorro  
                      Started by Segwin, 05-07-2018, 02:15 PM
                      10 responses
                      1,770 views
                      0 likes
                      Last Post Leafcutter  
                      Started by Rapine Heihei, 04-23-2024, 07:51 PM
                      2 responses
                      31 views
                      0 likes
                      Last Post Max238
                      by Max238
                       
                      Started by Shansen, 08-30-2019, 10:18 PM
                      24 responses
                      944 views
                      0 likes
                      Last Post spwizard  
                      Started by Max238, Today, 01:28 AM
                      0 responses
                      11 views
                      0 likes
                      Last Post Max238
                      by Max238
                       
                      Working...
                      X