Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Renko Backtesting

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

    Renko Backtesting

    Hi all,

    I've been looking around for a long time to find a way to backtest strategies on a renko chart correctly, with no success.

    The problem with Renko charts is that they give you better entries/exits than the actual market would have given you.

    So I thought of a "method" to code any strategy in order to make it realistic when it comes to backtesting. I don't know if it's going to work, nor if it is possible, but I think it has a good chance of success.



    Here's the idea : we want to get our entry/exit signals from a Renko chart, but we want to enter on another "timeframe", or "chart type", like a tick chart.

    So we have to use 2 chart types, or periods (I'm not sure) in the strategy. When a certain condition is met on the primary chart (Renko), we send an order to our secondary chart (tick).


    I don't have the skills to build such a code, but I've done enough research on the subject to strongly believe that such code is very possible to build.

    I would thank anyone who could code such a strategy and share it with everyone. If it does work, I think every trader trying to develop Renko based trading strategies would be grateful.


    Thanks a lot.

    Jérémy Mayer-Boisvert

    #2
    Hello jmayerb,

    Thank you for your post.

    Adding intra-bar granularity can give you more accurate fills.

    This would involve adding a secondary series, and placing the order to that secondary series. (This is what you have suggested in your post).

    Below I am including a link to an example of intra-bar granularity.
    http://www.ninjatrader.com/support/f...ead.php?t=6652

    Also, below I am including a link that highlights the differences of real-time vs backtest.
    http://www.ninjatrader.com/support/h...ime_vs_bac.htm
    Chelsea B.NinjaTrader Customer Service

    Comment


      #3
      Code

      I've included the code I'm working on with the help of your last post.

      There must be some errors in my code, because I can't compile the strategy.

      Can you help me with that ?

      Please!





      HTML Code:
          /// <summary>
          /// Enter the description of your strategy here
          /// </summary>
          [Description("Enter the description of your strategy here")]
          public class RenkoTick : Strategy
          {
              #region Variables
              // Wizard generated variables
              private int size = 1; // Default setting for Size
              private int brickSize = 4; // Default setting for BrickSize
              // 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()
              {
                  AddRenko("brickSize",MarketDataType.Last);
      			
      			CalculateOnBarClose = true;
              }
      
              /// <summary>
              /// Called on each bar update event (incoming tick)
              /// </summary>
              protected override void OnBarUpdate()
              {
      			if(BarsInProgress == 1)
      				{
      					if(Close[0]>Open[0]) & (Close[1]>Open[1]) &(Close[2]>Open[2]);
      						{
      							EnterLong(0,"Size");
      						}
      					if(Open[0]>Close[0]) & (Open[1]>Close[1]) &(Open[2]>Close[2]);
      						{
      						EnterShort(0,"Size");
      						}
      				}
      			else
      				{
      					return;
      				}
              }
      
              #region Properties
              [Description("")]
              [GridCategory("Parameters")]
              public int Size
              {
                  get { return size; }
                  set { size = Math.Max(1, value); }
              }
      
              [Description("")]
              [GridCategory("Parameters")]
              public int BrickSize
              {
                  get { return brickSize; }
                  set { brickSize = Math.Max(1, value); }
              }
              #endregion
          }
      }

      Comment


        #4
        the condition and is && and not only one &.
        The EnterLong or short condition is:
        EnterLong(1, size, " ");
        -the 1 is the bars in progress for the price of the entry;
        i your case renko, but if you want tick you can place the 0 and not the 1.
        -the size is how many contract you use for entry;
        -" " is the name of the entry position.
        Last edited by bergimax; 02-03-2015, 12:36 AM.

        Comment


          #5
          Hi jmayerb,

          bergimax is correct, the & should be &&.

          For example:

          Code:
          if (BarsInProgress == 0 && Close[0] > Open[0] [B]&&[/B] Close[1 ]> Open[1] [B]&&[/B] Close[2] > Open[2])
          EnterLong([B]1[/B], [B]Size[/B], "longEntry1");
          }
          Below are links to the help guide on BarsInProgress and EnterLong().
          BarsInProgress - http://www.ninjatrader.com/support/h...inprogress.htm
          EnterLong - http://www.ninjatrader.com/support/h.../enterlong.htm


          Also, are you going to be testing this on a Renko Bar type? If so, adding a Renko secondary series would defeat the purpose.

          Instead, you should make the chart or Strategy Analyzer Renko and add a 1 Tick series to the script.

          For example:
          Code:
          Add(PeriodType.Tick, 1);
          Below is a link to the help guide on Add() for data series.
          http://www.ninjatrader.com/support/h...s/nt7/add3.htm
          Last edited by NinjaTrader_ChelseaB; 02-03-2015, 08:15 AM.
          Chelsea B.NinjaTrader Customer Service

          Comment


            #6
            This is what I have so far

            Ok, here's what I have so far (thanks to all the replies I got).

            The strategy doesn't work correctly. Can anyone see something wrong ?

            [HTML] #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>
            /// Enter the description of your strategy here
            /// </summary>
            [Description("Enter the description of your strategy here")]
            public class RenkoTick : Strategy
            {
            #region Variables
            // Wizard generated variables
            private int size = 1; // Default setting for Size
            private int brickSize = 1; // Default setting for BrickSize
            // 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()
            {

            Add(PeriodType.Tick,1);
            CalculateOnBarClose = true;
            }

            /// <summary>
            /// Called on each bar update event (incoming tick)
            /// </summary>
            protected override void OnBarUpdate()
            {
            if(BarsInProgress==0)
            {
            if((Closes[0][0]>Opens[0][0])&&(Closes[0][1]>Opens[0][1])&&(Closes[0][2]>Opens[0][2]));
            {
            EnterLong(0,Size,"LongEntry1");
            }

            if((Opens[0][0]>Closes[0][0])&&(Opens[0][1]>Closes[0][1])&&(Closes[0][2]>Opens[0][2]));
            {
            EnterShort(0,Size,"ShortEntry1");
            }
            }
            else
            {
            if(Opens[0][0]>Closes[0][0])
            {
            ExitLong();
            }
            if(Closes[0][0]>Opens[0][0])
            {
            ExitShort();
            }
            }
            }

            #region Properties
            [Description("")]
            [GridCategory("Parameters")]
            public int Size
            {
            get { return size; }
            set { size = Math.Max(1, value); }
            }

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

            Comment


              #7
              sorry..but why do you add the secondary timeframe but don't use it? you work with the timeframe that you selected in a startegy selection(using the 0)..but you use the function closes work with the equal timeframe? [0] and you place the order on this.. you can try to place order in 1 instead 0 and tell if it is correct or not

              Comment


                #8
                Hi Jérémy

                That's great advice from Chelsea and Berimax.

                May I just point out some trivial things: if there's just one action after an 'if', you don't need curly brackets. (Two or more, yes.)

                Re your logical sequence:

                Code:
                else
                {
                if(Opens[0][0]>Closes[0][0])
                {
                ExitLong();
                }
                if(Closes[0][0]>Opens[0][0])
                {
                ExitShort();
                One mistake is that there wouldn't be a curly bracket between 'else' and 'if'. Also, in a sequence of 'if' statements, I don't think you can put an 'if' after an 'else if'.

                I think the best approach here would be to have:

                if (condition 1)

                Action 1

                else if (condition 2)

                Action 2

                else if (condition 3)

                Action 3

                else if (condition 4)

                Action 4


                (or just 'else' if there is no longer any logical alternative.)

                Like you, I'm a fan of Renko bars. Applying them to trades and backtesting can be difficult. May I suggest that, once you've finalized your order entry strategy, you may like to enter trades using ATMs. I'm sure most Ninjas feel that it's the ATMs that, among many other things, make NT7 such a powerful platform.

                Comment


                  #9
                  Hi jmayerb,

                  What is the incorrect behavior?

                  Are orders not placing at the correct time?

                  Are orders not exiting at the correct time or price?

                  Is the script not compiling?
                  Chelsea B.NinjaTrader Customer Service

                  Comment


                    #10
                    Follow Up

                    Ok everyone,

                    I have followed your advices and come up with a new script.

                    It it working almost 100%,except on some exits!

                    I have included a screenshot of the results I get to simplify the explanations.

                    Here's my code :


                    HTML 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>
                        /// Enter the description of your strategy here
                        /// </summary>
                        [Description("Enter the description of your strategy here")]
                        public class RenkoBacktesting : Strategy
                        {
                            #region Variables
                            // Wizard generated variables
                            private int size = 1; // Default setting for Size
                            // 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()
                            {
                                Add(PeriodType.Tick,1);
                    			
                    			CalculateOnBarClose = true;
                            }
                    
                            /// <summary>
                            /// Called on each bar update event (incoming tick)
                            /// </summary>
                            protected override void OnBarUpdate()
                            {
                                // Condition set 1
                                if (Closes[0][0] > Opens[0][0]
                                    && Closes[0][1] > Opens[0][1]
                                    && Closes[0][2] > Opens[0][2])
                                {
                                    EnterLong(1,Size, "");
                                }
                    
                                // Condition set 2
                                if (Closes[0][0] < Opens[0][0]
                                    && Closes[0][1] < Opens[0][1]
                                    && Closes[0][2] < Opens[0][2])
                                {
                                    EnterShort(1,Size, "");
                                }
                    
                                // Condition set 3
                                if (Closes[0][0] < Opens[0][0])
                                {
                                    ExitLong(1,"","");
                                }
                    
                                // Condition set 4
                                if (Closes[0][0] > Opens[0][0])
                                {
                                    ExitShort(1,"","");
                                }
                            }
                    
                            #region Properties
                            [Description("")]
                            [GridCategory("Parameters")]
                            public int Size
                            {
                                get { return size; }
                                set { size = Math.Max(1, value); }
                            }
                            #endregion
                        }
                    }
                    Attached Files

                    Comment


                      #11
                      Done!!!

                      Ok guys, I found the solution.

                      All I had to do was to include a quantity for the exit orders.

                      Here's the final code (hope it will help all of those traders who always wanted to do backtesting with Renko charts!!!)



                      HTML 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>
                          /// Enter the description of your strategy here
                          /// </summary>
                          [Description("Enter the description of your strategy here")]
                          public class RenkoBacktestingRange : Strategy
                          {
                              #region Variables
                              // Wizard generated variables
                              private int size = 1; // Default setting for Size
                              // 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()
                              {
                                  Add(PeriodType.Range,1);
                      			
                      			CalculateOnBarClose = true;
                              }
                      
                              /// <summary>
                              /// Called on each bar update event (incoming tick)
                              /// </summary>
                              protected override void OnBarUpdate()
                              {
                                  // Condition set 1
                                  if (Closes[0][0] > Opens[0][0]
                                      && Closes[0][1] > Opens[0][1]
                                      && Closes[0][2] > Opens[0][2])
                                  {
                                      EnterLong(1,Size, "");
                                  }
                      
                                  // Condition set 2
                                  if (Closes[0][0] < Opens[0][0]
                                      && Closes[0][1] < Opens[0][1]
                                      && Closes[0][2] < Opens[0][2])
                                  {
                                      EnterShort(1,Size, "");
                                  }
                      
                                  // Condition set 3
                                  if (Closes[0][0] < Opens[0][0])
                                  {
                                      ExitLong(1,1,"","");
                                  }
                      
                                  // Condition set 4
                                  if (Closes[0][0] > Opens[0][0])
                                  {
                                      ExitShort(1,1,"","");
                                  }
                              }
                      
                              #region Properties
                              [Description("")]
                              [GridCategory("Parameters")]
                              public int Size
                              {
                                  get { return size; }
                                  set { size = Math.Max(1, value); }
                              }
                              #endregion
                          }
                      }
                      Attached Files

                      Comment


                        #12
                        Jérémy,

                        It was very interesting to see how you finalized this strategy.

                        Renko is brilliant for getting into trades but there are serious issues with exiting them using Renko, which will certainly affect your own strategy.

                        May I suggest you may like to study the following thread carefully in which this issue is discussed by myself and others:



                        I'd like to quote Koganam in this thread:

                        "...That is one of the vagaries of Renko at reversal. Regardless the posture of the bar, at a reversal, the Open of the next bar is the other extreme of the previous bar."
                        which effectively means you get exits you didn't bargain for!

                        Cheers,

                        Ed
                        Last edited by arbuthnot; 02-04-2015, 04:11 PM.

                        Comment


                          #13
                          Adding Limit Orders

                          Hey all,

                          I need your help again. I'm trying to add accuracy to my strategy by entering with limit orders at actual bid and ask prices. It works great with market orders, but now I'm trying to enter with a limit order (trying to get a better price). The problem is that my limit orders either get canceled after one bar only (liveUntilCancelled set to false), which is undesirable when working with 1 tick range bars, or they stay alive for way too long and get filled way too late.

                          The solution seemed fairly simple : add a CancelOrder condition. The problem is that I must be doing something wrong, because I always get these error messages :

                          ''The name ''LongLimitOrder'' does not exist in the current context''
                          ''The name ''ShortLimitOrder'' does not exist in the current context''
                          (translated from french).

                          What am I doing wrong here (concerning the CancelOrder condition)?

                          Thank you guys


                          HTML 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>
                              /// Enter the description of your strategy here
                              /// </summary>
                              [Description("Enter the description of your strategy here")]
                              public class Renko33BacktestingBidAskLimit : Strategy
                              {
                                  #region Variables
                                  // Wizard generated variables
                                  private int size = 1; // Default setting for Size
                          		private int limit = 2; // Default setting for Limit
                                  // 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()
                                  {
                                      Add(Instrument.FullName,PeriodType.Range,1,MarketDataType.Ask);
                          			
                          			Add(Instrument.FullName,PeriodType.Range,1,MarketDataType.Bid);
                          			
                          			CalculateOnBarClose = true;
                                  }
                          
                                  /// <summary>
                                  /// Called on each bar update event (incoming tick)
                                  /// </summary>
                                  protected override void OnBarUpdate()
                                  {
                                      // Condition set 1
                                      if (Closes[0][0] > Opens[0][0]
                                          && Closes[0][1] > Opens[0][1]
                          				&& Closes[0][2] > Opens[0][2])
                                      {
                                          EnterLongLimit(2,false,Size,GetCurrentBid(2)-limit*TickSize,"LongLimitOrder");
                          				ExitShort(1,1,"","");
                                      }
                          
                                      // Condition set 2
                                      if (Closes[0][0] < Opens[0][0]
                                          && Closes[0][1] < Opens[0][1]
                          				&& Closes[0][2] < Opens[0][2])
                                      {
                                          EnterShortLimit(1,false,Size,GetCurrentAsk(1)+limit*TickSize,"ShortLimitOrder");
                          				ExitLong(2,1,"","");
                                      }
                          			
                          			//Condition set 3
                          			if(Closes[0][0] > Opens[0][0]
                                          && Closes[0][1] > Opens[0][1]
                          				&& Closes[0][2] > Opens[0][2]
                          				&& Closes[0][3] > Opens[0][3])
                          			{
                          				CancelOrder(LongLimitOrder);
                          			}
                          			
                          			//Condtition set 4
                          			if(Closes[0][0] < Opens[0][0]
                                          && Closes[0][1] < Opens[0][1]
                          				&& Closes[0][2] < Opens[0][2]
                          				&& Closes[0][3] < Opens[0][3])
                          			{
                          				CancelOrder(ShortLimitOrder);
                          			}
                                  }
                          
                                  #region Properties
                                  [Description("")]
                                  [GridCategory("Parameters")]
                                  public int Size
                                  {
                                      get { return size; }
                                      set { size = Math.Max(1, value); }
                                  }
                                  #endregion
                              }
                          }

                          Comment


                            #14
                            Hi jmayerb,

                            I am not seeing that these variables are declared anywhere.

                            For example in #region Variables:
                            private IOrder LongLimitOrder = null;
                            private IOrder ShortLimitOrder = null;

                            Below is a link to the help guide on IOrder.
                            http://www.ninjatrader.com/support/h...nt7/iorder.htm

                            All variables in C# must be declared before they can be used.

                            With NinjaTrader specific items, these are declared behind the scenes. With any variables you create you will need to declare.
                            Chelsea B.NinjaTrader Customer Service

                            Comment

                            Latest Posts

                            Collapse

                            Topics Statistics Last Post
                            Started by Shansen, 08-30-2019, 10:18 PM
                            24 responses
                            938 views
                            0 likes
                            Last Post spwizard  
                            Started by Max238, Today, 01:28 AM
                            0 responses
                            3 views
                            0 likes
                            Last Post Max238
                            by Max238
                             
                            Started by rocketman7, Today, 01:00 AM
                            0 responses
                            2 views
                            0 likes
                            Last Post rocketman7  
                            Started by wzgy0920, 04-20-2024, 06:09 PM
                            2 responses
                            27 views
                            0 likes
                            Last Post wzgy0920  
                            Started by wzgy0920, 02-22-2024, 01:11 AM
                            5 responses
                            32 views
                            0 likes
                            Last Post wzgy0920  
                            Working...
                            X