Announcement

Collapse
No announcement yet.

Partner 728x90

Collapse

Inconsistent entry/ exit prices and times in backtests when I export values

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

    Inconsistent entry/ exit prices and times in backtests when I export values

    Hi... I'm backtesting a strategy on ES, using renko bars. I wrote a bit of code that exports certain values for each trade to a sql server table, so I can do some data analysis on it in excel. I use a simple type I wrote I call MarketDataExporter.

    I manually check for exit conditions in my strategy, and one line before calling ExitLong/Short(), I call a method that exports the values. For the entry price, I use Position.AveragePrice. For time of entry, I use Time[BarsSinceEntry()-1]. When I view the exported results, the entry times I get vs the trade info in the Trades tab of strategy analyzer are close, but off by a few seconds. The entry prices are off significantly, by 6+ points. Interestingly, even though the entry/ exit prices are off by several points, the profit in points appears to be accurate for all of them (at least the 10 or so I checked).

    So my questions are, why the wide discrepancy, and what am I doing wrong, and/ or what can be done to fix it?

    As an example, based on info in the Trades tab, I enter short @ 1302.5 at 1/26/12, 10:00:37 AM. In my exported info, I enter short @ 1308.75 at 1/26/12, 10:01:00 AM. My code is below..

    Code:
    public class EminiRenko3Bars013013 : Strategy
        {
            #region Variables
            // Wizard generated variables
            private int myInput0 = 1; // Default setting for MyInput0
            // User defined variables (add any user defined variables below)
            MarketDataExporter exp;
            string tableName;
            #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()
            {
                CalculateOnBarClose = true;
                tableName = "EminiRenko3Bars013013";
                exp = new MarketDataExporter(tableName);
            }
            
            /// <summary>
            /// Called on each bar update event (incoming tick)
            /// </summary>
            
            protected override void OnBarUpdate()
            {
                if (CurrentBars[0] <= BarsRequired) return;
                
                if(Position.MarketPosition == MarketPosition.Flat && Time[0].Hour != 12 && (ToTime(Time[0])<=160000))
                {
                    if(Close[0] > Open[0] && Close[1] > Open[1] && Close[2] > Open[2] && Close[3] < Open[3])
                    {
                        EnterLong();
                    }
                    else if(Close[0] < Open[0] && Close[1] < Open[1] && Close[2] < Open[2] && Close[3] > Open[3])
                    {
                        EnterShort();
                    }
                }
                else
                {
                    if(Position.MarketPosition == MarketPosition.Long && Close[0] < Open[0] && Close[1] < Open[1])
                    {
                        WriteStatsToDb();
                        ExitLong();
                    }
                    else if(Position.MarketPosition == MarketPosition.Short && Close[0] > Open[0] && Close[1] > Open[1])
                    {
                        WriteStatsToDb();
                        ExitShort();
                    }    
                }
            }
            
            void WriteStatsToDb()
            {
                //Entry time variables
                string longOrshort = Position.MarketPosition.ToString();
                double entryPrice = Position.AvgPrice;
                double exitPrice = Close[0];
                double profitInPoints;
                if(Position.MarketPosition == MarketPosition.Long)
                    profitInPoints = exitPrice - entryPrice;
                else
                    profitInPoints = entryPrice - exitPrice;
                
                DateTime entryDate = Time[BarsSinceEntry() - 1];
                DateTime exitDate = Time[0];
                double ema5 = EMA(5)[BarsSinceEntry() - 1];
                double ema10 = EMA(10)[BarsSinceEntry() - 1];
                double ema20 = EMA(20)[BarsSinceEntry() - 1];
                double ema50 = EMA(50)[BarsSinceEntry() - 1];
                double adx5 = ADX(5)[BarsSinceEntry() - 1];
                double adx10 = ADX(10)[BarsSinceEntry() - 1];
                double adx20 = ADX(20)[BarsSinceEntry() - 1];
                double adx50 = ADX(50)[BarsSinceEntry() - 1];
                double linReg5 = LinReg(5)[BarsSinceEntry() - 1];
                double linReg10 = LinReg(10)[BarsSinceEntry() - 1];
                double linReg20 = LinReg(20)[BarsSinceEntry() - 1];
                double linReg50 = LinReg(50)[BarsSinceEntry() - 1];
                double rsi14Per3AvgRsi = RSI(14,3)[BarsSinceEntry() - 1];
                double rsi14Per3AvgAvg = RSI(14,3).Avg[BarsSinceEntry() - 1];
                double daysHigh = High[HighestBar(High,Bars.BarsSinceSession - 1)];
                double daysLow = Low[LowestBar(Low,Bars.BarsSinceSession - 1)];
                
                exp.Add("LongOrShort;Char;" + longOrshort + "!" +
                    "EntryPrice;Decimal;" + entryPrice + "!" +
                    "ExitPrice;Decimal;" + exitPrice + "!" +
                    "ProfitInPoints;Decimal;" + profitInPoints + "!" +
                    "EntryDate;Date;" + entryDate + "!" +
                    "ExitDate;Date;" + exitDate + "!" +
                    "Ema5;Decimal;" + ema5 + "!" +
                    "Ema10;Decimal;" + ema10 + "!" +
                    "Ema20;Decimal;" + ema20 + "!" +
                    "Ema50;Decimal;" + ema50 + "!" +
                    "Adx5;Decimal;" + adx5 + "!" +
                    "Adx10;Decimal;" + adx10 + "!" +
                    "Adx20;Decimal;" + adx20 + "!" +
                    "Adx50;Decimal;" + adx50 + "!" +
                    "LinReg5;Decimal;" + linReg5 + "!" +
                    "LinReg10;Decimal;" + linReg10 + "!" +
                    "LinReg20;Decimal;" + linReg20 + "!" +
                    "LinReg50;Decimal;" + linReg50 + "!" +
                    "Rsi14Per3AvgRsi;Decimal;" + rsi14Per3AvgRsi + "!" +
                    "Rsi14Per3AvgAvg;Decimal;" + rsi14Per3AvgAvg + "!" +
                    "DaysHigh;Decimal;" + daysHigh + "!" +
                    "DaysLow;Decimal;" + daysLow);
            }
            
            protected override void OnTermination()
            {
                exp.WriteMarketDataRecordsToDb();
            }
    Last edited by CSharpTrader; 02-02-2013, 08:37 AM. Reason: Additional info

    #2
    Hello,

    Unfortunately I'm not able to debug your custom Class but when backtesting on the Renko bars are you using a multi-series script to account for the data loss on the Renko bars?

    Do these errors only occur with Renko Bars, or with Minute bars as well?
    LanceNinjaTrader Customer Service

    Comment


      #3
      Hi Lance, thanks. It was a single series script, only on renko bars. I've rerun it without changing code, and the results look more "as expected." I'll chalk it up to some of the inconsistencies I've heard I can expect sometimes with renko..

      Comment


        #4
        Hello,

        Typically when backtesting on Renko data you will want to add a minute or tick series in order to ensure the data is properly being looked at.



        You can submit orders to different Bars objects. This allows you the flexibility of submitting orders to different timeframes. Like in live trading, taking entry conditions from a 5min chart means executing your order as soon as possible instead of waiting until the next 5min bar starts building. You can achieve this by


        Backtesting over pure Renko bars is often very inaccurate as price trades at values that are not recorded in the Renko bars. In otherwords price could have hit 100.25 in real trading but the Renko bar may have a high of 100 depending on the bar size and direction.

        Please let me know if I can be of further assistance.
        LanceNinjaTrader Customer Service

        Comment


          #5
          Thanks. To your point, if I only want to look purely at signals of price as shown on the renkos, can it be trusted? Using your example, what if I don't need to know if 100.25 was hit? Am I missing something in my understanding of how they affect backtesting? As I see it, if I want to use just the renkos and I'm not worried about highs/ lows not shown, I should be able to trust the strategy code. Unless you tell me otherwise...

          Comment


            #6
            Hello,

            Yes this is likely correct. While I can't verify 100% without testing the code myself I'd imagine all the signals would be the same. The differences will typically come when exiting positions.
            LanceNinjaTrader Customer Service

            Comment

            Latest Posts

            Collapse

            Topics Statistics Last Post
            Started by KennyK, 05-29-2017, 02:02 AM
            3 responses
            1,282 views
            0 likes
            Last Post NinjaTrader_Clayton  
            Started by AttiM, 02-14-2024, 05:20 PM
            11 responses
            184 views
            0 likes
            Last Post NinjaTrader_ChelseaB  
            Started by fernandobr, Today, 09:11 AM
            1 response
            3 views
            0 likes
            Last Post NinjaTrader_Erick  
            Started by timmbbo, Today, 08:59 AM
            1 response
            3 views
            0 likes
            Last Post NinjaTrader_ChelseaB  
            Started by itrader46, Today, 09:04 AM
            1 response
            7 views
            0 likes
            Last Post NinjaTrader_Clayton  
            Working...
            X