The backtest strategy below uses the ES 60min bars to test for a condition: if true, 2 positions are entered LONG on the 1min. Stoploss and profit targets are also intended to execute on 1min. The stoploss is adjusted if the 1st target is reached. (Note: I could do this entirely on the sub-time frame, but then the 60min/primary chart can not be viewed in the strategy analyzer.)
The problem is that on large 60min down bars (e.g., 12/7/10), the trade is entered and the stoploss is executed for each minute. When I look at execution of the trades it looks like this:
12/7/2010 2:03:00 PM Entry Long1
12/7/2010 2:03:00 PM Entry Long2
12/7/2010 3:00:00 PM Stoploss
12/7/2010 3:00:00 PM Stoploss
12/7/2010 2:04:00 PM Entry Long1
12/7/2010 2:04:00 PM Entry Long2
12/7/2010 3:00:00 PM Stoploss
12/7/2010 3:00:00 PM Stoploss
etc...
From the timestamp above, it appears the Stoploss is being applied on 60min, which doesn't make sense to me in two ways: 1. the stoploss was entered on the 1min, and 2. the time is not chronological.
Please help me understand how to correctly implement the strategy given below.
Thanks in Advance!
#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> /// ExampleIntrabarStopLoss /// </summary> [Description("ExampleIntrabarStopLoss")] public class ExampleIntrabarStopLoss : Strategy { #region Variables // Wizard generated variables private int nContracts = 1; // Default setting for NContracts private double currentHrBarOpen = 1000000; // set high so entry not falsely triggered private double target1 = 2.000; // Default setting for Target1 private double target2 = 4.000; // Default setting for Target2 private double target3 = 1; // Default setting for Target3 private double target4 = 0.000; // Default setting for Target4 private double stopLoss = 4.000; // Default setting for StopLoss // User defined variables (add any user defined variables below) #endregion // Strategy: ExampleIntrabarStopLoss // Instrument: ES // Series: Primary: 60min // Secondary: 1min // Description: Backtest of simple strategy the uses the 60min bars for entry // signals. // Entry and Exit on 1min timeframe // // This method is used to configure the strategy and is called once before any strategy method is called. protected override void Initialize() { // Buy 2*NContracts and have separate exits EntriesPerDirection = 2; //Note: The primary bar series is whatever you choose for the strategy at startup. // Strategy Analyzer Chart displays primary bars ONLY //Primary: 60min //Add Secondary: 1min Add(PeriodType.Minute, 1); CalculateOnBarClose = true; // set to true for historical testing } /// Called after each bar close if CalculateOnBarClose == true protected override void OnBarUpdate() { // Sets the back color to empty when Time is between 9am-4:15pm EST, and to Lavender otherwise BackColor = (ToTime(Time[0]) >= 90000 && ToTime(Time[0]) <= 161500) ? Color.Empty : Color.Lavender; // Return unless time between 9:00am and 4:15pm. if (ToTime(Time[0]) < ToTime(9, 00, 0) || ToTime(Time[0]) > ToTime(16, 15, 0)) return; // BarsInProgress = 0 for 60min bars; 1 for 1min bars if (BarsInProgress == 1) { int nbar1 = 0; double exitPrice = 0; double entryPrice = 0; // Check for zeroth minute if( Time[0].Minute == 0 ) { nbar1 = 1; //1min 00min called after 60min 00min, therefore need to index previous 60min bar } // Check for 1st minute of hour to set open value (for hour) else if ( Time[0].Minute == 1 ) { CurrentHrBarOpen = Open[0]; Print("CurrentHrBarOpen: " + " nBar: " + CurrentBar.ToString() + " Time: " + ToTime(Time[0]).ToString() + " Open[0]: " + Open[0].ToString() + " CurrentHrBarOpen " + CurrentHrBarOpen.ToString()); } // Order entry note: Long entry order only valid for current bar of current barArray unless 'LiveToCancelled' == 1 // Only check for long entry condition if no position is open //if (Position.Quantity == 0) if (Position.MarketPosition == MarketPosition.Flat) { if ( Closes[0][nbar1] > Highs[0][nbar1+1] && ToTime(Time[0]) < ToTime(16, 0, 0)) { entryPrice = Highs[0][nbar1] + 0.25; // if minute 0: will not know open at minute 1, so execute a 'EnterLongStop' if( Time[0].Minute == 0 ) { EnterLongStop( NContracts, entryPrice, "Long1"); EnterLongStop( NContracts, entryPrice, "Long2"); } else if (CurrentHrBarOpen < Highs[0][nbar1]) { EnterLongLimit( NContracts, entryPrice, "Long1"); EnterLongLimit( NContracts, entryPrice, "Long2"); } Variable0 = 1; SetStopLoss("Long1", CalculationMode.Ticks, 4.0*StopLoss, true); SetStopLoss("Long2", CalculationMode.Ticks, 4.0*StopLoss, true); SetProfitTarget("Long1", CalculationMode.Ticks, 4.0*Target1); SetProfitTarget("Long2", CalculationMode.Ticks, 4.0*Target2); } } // Check targets else if (Position.Quantity == 2*NContracts) { //SetStopLoss("Long1", CalculationMode.Ticks, 16.0, true); //SetStopLoss("Long2", CalculationMode.Ticks, 16.0, true); if (ToTime(Time[0]) == ToTime(16, 14, 0) ) { ExitLong("Time Exit L1", "Long1"); ExitLong("Time Exit L2", "Long2"); } } else if (Position.Quantity == NContracts) { //adjust stop loss to Target4 (breakeven) SetStopLoss("Long2", CalculationMode.Ticks, 0.0, true); if (ToTime(Time[0]) == ToTime(16, 14, 0) ) { ExitLong("Time Exit L2", "Long2"); //ExitLong("Long2"); } } } //Print out section outside of BarsInProgress condition statement if (Position.Quantity != 1000) { Print(Time[0].ToString() //+ "BarsInProgress: " + BarsInProgress.ToString() + " nBar: " + CurrentBar.ToString() + " AvgPrice " + Position.AvgPrice.ToString() + " Qnty: " + Position.Quantity.ToString()); } } #region Properties [Description("")] [GridCategory("Parameters")] public int NContracts { get { return nContracts; } set { nContracts = Math.Max(1, value); } } [Description("")] [GridCategory("Parameters")] public double CurrentHrBarOpen { get { return currentHrBarOpen; } set { currentHrBarOpen = Math.Max(0, value); } } [Description("")] [GridCategory("Parameters")] public double Target1 { get { return target1; } set { target1 = Math.Max(0, value); } } [Description("")] [GridCategory("Parameters")] public double Target2 { get { return target2; } set { target2 = Math.Max(0, value); } } [Description("")] [GridCategory("Parameters")] public double Target3 { get { return target3; } set { target3 = Math.Max(0, value); } } [Description("")] [GridCategory("Parameters")] public double Target4 { get { return target4; } set { target4 = Math.Max(0, value); } } [Description("")] [GridCategory("Parameters")] public double StopLoss { get { return stopLoss; } set { stopLoss = Math.Max(-1000.000, value); } } #endregion } }
Comment