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