CODE FOR NINJATRADER

Code to accompany the article “An Expert Of A System” by Sylvain Vervoort, in the October 2013 issue of Technical Analysis of Stocks & Commodities magazine.

  1. SVEHaTypCross - Color Coding Expert
  2. SVEHaTypCrossInd - Digital Indicator
  3. SVEHaTypCross - Strategy

SVEHaTypCross - Color Coding Expert

// SVEHaTypCross is Copyright (C)2013, Sylvain Vervoort < stocata.org> .
// stocata.org reserves the right to modify this NinjaScript with each release.
// Release V1.0 January, 2013.

#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
#endregion

// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
/// < summary> 
/// A typical and heikin-ashi price crossover color coding the candle chart.
/// < /summary> 
[Description("")]
public class SVEHaTypCross : Indicator
{
#region Variables

private int haCaverage 		=	8; // Default heikin-ashi Closing price average
private int typicalaverage	=	5; // Default typical price average

private DataSeries 		haOpen;	// heikin ashi open price
private DataSeries 		haC;		// heikin ashi closing price
private DataSeries 		typical;	// typical price
private DataSeries 		AVGtyp;	// typical price average
private DataSeries 		AVGhaC;	// heikin-ashi average
private DataSeries 		cross;	// typical average crossing HA average

private Color candlefillup		= 	Color.White;
private Color candlednfill		= 	Color.Gray;
private Color candleupfill		= 	Color.LimeGreen;
private Color outlineup			= 	Color.LimeGreen;
private Color outlinedn			= 	Color.Black;

#endregion

/// < summary> 
/// Configuring the indicator called once before any bar data.
/// < /summary> 
protected override void Initialize()
{	
haOpen 	= new DataSeries(this);
haC 		= new DataSeries(this);
typical 	= new DataSeries(this);
AVGtyp	= new DataSeries(this);
AVGhaC	= new DataSeries(this);
cross		= new DataSeries(this);

PaintPriceMarkers	= false;
Overlay				= true;
}

/// < summary> 
/// Called on each bar update event (incoming tick)
/// < /summary> 
protected override void OnBarUpdate()
{	
if (CurrentBar <  1) // minimum 2 bars required
return;

// Create crossover data sets
haOpen.Set((((Open[1] + High[1] + Low[1] + Close[1]) / 4) + haOpen[1]) / 2);
haC.Set(((Open[0] + High[0] + Low[0] + Close[0]) / 4 + haOpen[0] + 
	  Math.Max(High[0], haOpen[0]) + Math.Min(Low[0], haOpen[0])) / 4);
typical.Set((High[0] + Low[0] + Close[0]) / 3);

// Create the averages
AVGtyp.Set(EMA(typical, typicalaverage)[0]);
AVGhaC.Set(EMA(haC, haCaverage)[0]);

// Crossover condition
if(AVGtyp[0] >  AVGhaC[0] && Close[0] >  Open[0]) cross[0] = 1;
else if(AVGtyp[0] <  AVGhaC[0] && Close[0] <  Open[0]) cross[0] = 0;
else cross[0] = cross[1];

// Color coding the candle chart
if(cross[0] == 1)
{
BarColorSeries[0] = candleupfill;
CandleOutlineColorSeries[0] = outlineup;
if(ChartControl.ChartStyleType == ChartStyleType.CandleStick)  
	if(Close[0] > = Open[0]) 
   	BarColorSeries[0] = candlefillup;
else BarColorSeries[0] 	= candleupfill;
}
else if(cross[0] == 0)
{
BarColorSeries[0] = candlednfill;
CandleOutlineColorSeries[0] = outlinedn;
if(ChartControl.ChartStyleType == ChartStyleType.CandleStick)  
	if(Close[0] > = Open[0])  
   	BarColorSeries[0] = candlefillup;
else BarColorSeries[0] 	= candlednfill;
}
}

#region Properties

/// < summary> 
/// < /summary> 
[Description("Heikin-ashi Average DEF = 8")]
[Category("Parameters")]
[Gui.Design.DisplayName("1. Heikin-Ashi average")]
public int AVG__slow
{
get { return haCaverage; }
set { haCaverage = Math.Max(1, value); }
}

/// < summary> 
/// < /summary> 
[Description("Typical average DEF = 5")]
[Category("Parameters")]
[Gui.Design.DisplayName("2. Typical Price Average")]
public int AVG_fast
{
get { return typicalaverage; }
set { typicalaverage = Math.Max(1, value); }
}

[Description("Color for an UP candle DEFAULT = White")]
[Category("Parameters")]
[Gui.Design.DisplayName("3. Up candle color")]
public Color Candlefillup
{
get { return candlefillup; }
set { candlefillup = value; }
}
[Browsable(false)]
public string CandlefillupSerialize
{
get { return NinjaTrader.Gui.Design.SerializableColor.ToString(candlefillup); }
set { candlefillup = NinjaTrader.Gui.Design.SerializableColor.FromString(value); }
}

[Description("Down candle fill color DEFAULT = Gray")]
[Category("Parameters")]
[Gui.Design.DisplayName("4. Down fill color")]
public Color Candlednfill
{
get { return candlednfill; }
set { candlednfill = value; }
}
[Browsable(false)]
public string CandlednfillSerialize
{
get { return NinjaTrader.Gui.Design.SerializableColor.ToString(candlednfill); }
set { candlednfill = NinjaTrader.Gui.Design.SerializableColor.FromString(value); }
}

[Description("Up candle fill color DEFAULT = LimeGreen")]
[Category("Parameters")]
[Gui.Design.DisplayName("5. Up fill color")]
public Color Candleupfill
{
get { return candleupfill; }
set { candleupfill = value; }
}
[Browsable(false)]
public string CandleupfillSerialize
{
get { return NinjaTrader.Gui.Design.SerializableColor.ToString(candleupfill); }
set { candleupfill = NinjaTrader.Gui.Design.SerializableColor.FromString(value); }
}	

[Description("Outline Up color DEFAULT = LimeGreen")]
[Category("Parameters")]
[Gui.Design.DisplayName("6. Outline Up color")]
public Color Outlineup
{
get { return outlineup; }
set { outlineup = value; }
}
[Browsable(false)]
public string OutlineupSerialize
{
get { return NinjaTrader.Gui.Design.SerializableColor.ToString(outlineup); }
set { outlineup = NinjaTrader.Gui.Design.SerializableColor.FromString(value); }
}	

[Description("Outline Down color DEFAULT = Black")]
[Category("Parameters")]
[Gui.Design.DisplayName("7. Outline Down color")]
public Color Outlinedn
{
get { return outlinedn; }
set { outlinedn = value; }
}
[Browsable(false)]
public string OutlinednSerialize
{
get { return NinjaTrader.Gui.Design.SerializableColor.ToString(outlinedn); }
set { outlinedn = NinjaTrader.Gui.Design.SerializableColor.FromString(value); }
}	

#endregion
}
}

SVEHaTypCrossInd - Digital Indicator

// 
// SVEHaTypCrossInd is Copyright (C) 2013, Sylvain Vervoort < stocata.org> .
// stocata.org reserves the right to modify/overwrite this NinjaScript with each release.
// Release V1.1 January, 2013.

#region Using declarations
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Xml.Serialization;
using NinjaTrader.Data;
using NinjaTrader.Gui.Chart;
#endregion

// This namespace holds all indicators and is required. Do not change it.
namespace NinjaTrader.Indicator
{
/// < summary> 
/// A typical and heikin-ashi price crossover digital indicator.
/// < /summary> 
[Description("Typical price and heikin ashi crossover digital indicator")]
public class SVEHaTypCrossInd : Indicator
{
#region Variables

private int haCaverage 			=	8; 	// Default heikin-ashi Closing price average
private int typicalaverage 	=	5; 	// Default typical price average

private DataSeries 		haOpen;		// heikin ashi open price
private DataSeries 		haC;			// heikin ashi closing price
private DataSeries 		typical;		// typical price
private DataSeries 		AVGtyp;		// typical price average
private DataSeries 		AVGhaC;		// heikin-ashi average
private DataSeries 		cross;		// typical average crossing HA average

#endregion

/// < summary> 
/// Configuring the indicator called once before any bar data.
/// < /summary> 
protected override void Initialize()
{	
Add(new Plot(Color.DodgerBlue, "Cross Ind"));

haOpen 	= new DataSeries(this);
haC 		= new DataSeries(this);
typical 	= new DataSeries(this);
AVGtyp	= new DataSeries(this);
AVGhaC	= new DataSeries(this);
cross	= new DataSeries(this);

PaintPriceMarkers 	= false;
Overlay					= false;
}

/// < summary> 
/// Called on each bar update event (incoming tick)
/// < /summary> 
protected override void OnBarUpdate()
{	
if (CurrentBar <  1) // minimum 2 bars required
	return;

// Create crossover data sets
haOpen.Set((((Open[1] + High[1] + Low[1] + Close[1]) / 4) + haOpen[1]) / 2);
haC.Set(((Open[0] + High[0] + Low[0] + Close[0]) / 4 + haOpen[0] + 
		  Math.Max(High[0], haOpen[0]) + Math.Min(Low[0], haOpen[0])) / 4);
typical.Set((High[0] + Low[0] + Close[0]) / 3);

// Create the averages
AVGtyp.Set(EMA(typical, typicalaverage)[0]);
AVGhaC.Set(EMA(haC, haCaverage)[0]);

// Crossover condition
if(AVGtyp[0] >  AVGhaC[0] && Close[0] >  Open[0]) cross[0] = 1;
else if(AVGtyp[0] <  AVGhaC[0] && Close[0] <  Open[0]) cross[0] = 0;
else cross[0] = cross[1];
Value.Set(cross[0]);
}

#region Properties

/// < summary> 
/// < /summary> 
[Description("Heikin-ashi Average DEF = 8")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("1. Heikin-Ashi average")]
public int AVG__slow
{
get { return haCaverage; }
set { haCaverage = Math.Max(1, value); }
}

/// < summary> 
/// < /summary> 
[Description("Typical average DEF = 5")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("2. Typical Price Average")]
public int AVG_fast
{
get { return typicalaverage; }
set { typicalaverage = Math.Max(1, value); }
}

#endregion
}
}

SVEHaTypCross - Strategy

// SVEHaTypCross strategy is Copyright (C) 2013, Sylvain Vervoort < stocata.org> .
// stocata.org reserves the right to modify/overwrite this NinjaScript with each release.
// Release V1.1 February, 2013.
// This strategy is for training purposes only. Any other use is strictly at your own risk.

#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;
using System.IO;
using System.Collections;
using System.Windows.Forms;
#endregion

// This namespace holds all strategies and is required. Do not change it.
namespace NinjaTrader.Strategy
{
/// < summary> 
/// Typical price cross over with Heikin-Ashi prices for stocks
/// < /summary> 
[Description("SVEHaTypCross Price cross over system for trading Stocks")]
public class SVEHaTypCross : Strategy
{
// Variables----------------------------------------------------------------------------
#region Variables
private int 		haCaverage 		= 8;		// Heikin-Ashi average
private int 		typicalaverage	= 5;		// Typical price average
private double 	stoplossperc 	= 25;		// Stop loss percentage
private double 	breakevenperc 	= 15;		// Break even percentage
private int     	stocksqty 		= 100;	// Basic stock buying quantity

bool OpnBuyClsSell = false, OpnSellClsBuy = false;

private IOrder sOrderLong 		= null; 	// Long order identity
private IOrder sStopLong 		= null;	// Stop loss long order identity
private IOrder sOrderShort 	= null; 	// Short order identity
private IOrder sStopShort 		= null;	// Stop loss short order identity
private IOrder sOrdExLong 		= null; 	// Exit long order identity
private IOrder sOrdExShort 	= null;	// Exit short order identity

#endregion

// Initialize ----------------------------------------------------------------------------
protected override void Initialize()
{	
CalculateOnBarClose 	= true;
TraceOrders 			= true;
EntryHandling 			= EntryHandling.UniqueEntries;
ExitOnClose 			= false; 
SyncAccountPosition 	= false;
StopTargetHandling 	= StopTargetHandling.ByStrategyPosition;
}

// On bar update  ----------------------------------------------------------------------------
protected override void OnBarUpdate()
{	
OpnBuyClsSell = false; OpnSellClsBuy = false;
		
// The single autotrade signal crossovers
if (SVEHaTypCrossInd(haCaverage,typicalaverage)[0] >  0 &&
	SVEHaTypCrossInd(haCaverage,typicalaverage)[1] <  1)
	OpnBuyClsSell = true;

if (SVEHaTypCrossInd(haCaverage,typicalaverage)[0] <  1 &&
	SVEHaTypCrossInd(haCaverage,typicalaverage)[1] >  0)
	OpnSellClsBuy = true;

// Opening the trade
if (OpnBuyClsSell == true && Position.MarketPosition == MarketPosition.Flat) 
	sOrderLong = EnterLong(stocksqty,"sOrderLong");
else if (OpnBuyClsSell == true && Position.MarketPosition == MarketPosition.Short)
{
	sOrdExShort = ExitShort(Position.Quantity,"sOrdExShort","sOrderShort");
	sOrderLong 	= EnterLong(stocksqty,"sOrderLong");
}

if (OpnSellClsBuy == true && Position.MarketPosition == MarketPosition.Flat) 		
	sOrderShort = EnterShort(stocksqty, "sOrderShort");
else if (OpnSellClsBuy == true && Position.MarketPosition == MarketPosition.Long)
{
	sOrdExLong 	= ExitLong(Position.Quantity,"sOrdExLong","sOrderLong");
	sOrderShort = EnterShort(stocksqty,"sOrderShort");
}

// Modify stop-loss setting to breakeven for a long position
if (Position.MarketPosition == MarketPosition.Long && 
	Close[0] > = Position.AvgPrice + breakevenperc * 0.01 * Position.AvgPrice)
{
	// Check if a Stop Order exists, modify it to breakeven
	if (sStopLong != null && sStopLong.StopPrice <  Position.AvgPrice)
	{
	// Modify stop-loss to breakeven 
	sStopLong = ExitLongStop(0,true, sStopLong.Quantity, 
				Position.AvgPrice, "sStopLong", "sOrderLong");
	}
}
// Modify stop-loss to breakeven for a short position
if (Position.MarketPosition == MarketPosition.Short && 
	Close[0] < = Position.AvgPrice - breakevenperc * 0.01 * Position.AvgPrice)
{
	// Check if a Stop Order exists, modify it to breakeven
	if (sStopShort != null && sStopShort.StopPrice >  Position.AvgPrice)
	{
	// Modify stop-loss to breakeven 
	sStopShort = ExitShortStop(0,true, sStopShort.Quantity, 
				 Position.AvgPrice, "sStopShort", "sOrderShort");
	}
}
}

// -----------------------------------------------------------------------------------------
protected override void OnOrderUpdate(IOrder order)
{
// Identify the entry order by calling the OnOrderUpdate() method.
if (sOrderLong != null && sOrderLong == order)
	{	
	// Reset the entryOrder object to null if order was cancelled without any fill
	if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
		{
		sOrderLong = null;
		}
	}
if (sOrderShort != null && sOrderShort == order)
	{	
	if (order.OrderState == OrderState.Cancelled && order.Filled == 0)
		{
		sOrderShort = null;
		}
	}
}

// ------------------------------------------------------------------------------------------
protected override void OnExecution(IExecution execution)
{
// Monitoring order Execution to submit a stop order for a long position.
// OnExecution() is called after OnOrderUpdate().
if (sOrderLong != null && sOrderLong == execution.Order)
{
	if (execution.Order.OrderState == OrderState.Filled || 
		execution.Order.OrderState == OrderState.PartFilled || 
	   (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled >  0))
	{
		sStopLong = ExitLongStop(0, true, execution.Order.Filled, 
		  execution.Order.AvgFillPrice - stoplossperc * 0.01 * execution.Order.AvgFillPrice, 
			"sStopLong", "sOrderLong");
		
		// Resetting the entryOrder object to null after the order is filled
		if (execution.Order.OrderState != OrderState.PartFilled) 	
		sOrderLong = null;
	}
}

// Reset exit long order when position is closed
if (sOrdExLong == execution.Order) 
{
	sOrdExLong	 	= null; 
}

// Reset when stop long position is closed
if (sStopLong == execution.Order) 
{
	sStopLong	= null;
}

// Submitting stop order for a short position...
if (sOrderShort != null && sOrderShort == execution.Order)
{
	if (execution.Order.OrderState == OrderState.Filled || 
		execution.Order.OrderState == OrderState.PartFilled || 
	   (execution.Order.OrderState == OrderState.Cancelled && execution.Order.Filled >  0))
	{
		sStopShort = ExitShortStop(0, true, execution.Order.Filled, 
		  execution.Order.AvgFillPrice + stoplossperc * 0.01 * execution.Order.AvgFillPrice, 
			"sStopShort", "sOrderShort");
		
		// Resetting the entryOrder object to null after the order is filled
		if (execution.Order.OrderState != OrderState.PartFilled) 
		sOrderShort = null;
	}
}

// Reset exit short order when position is closed
if (sOrdExShort == execution.Order) 
{
	sOrdExShort	 	= null; 
}

// Reset when stop short position is closed
if (sStopShort == execution.Order) 
{
	sStopShort	= null;
}
}

#region Properties

[Description("Heikin-Ashi average: DEFAULT = 8")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("1. Heikin-Ashi average")]
public int P01_haCaverage
{
get { return haCaverage; }
set { haCaverage = Math.Max(1, value); }
}

[Description("Typical average: DEFAULT = 5")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("2. Typical average")]
public int P02_typicalaverage
{
get { return typicalaverage; }
set { typicalaverage = Math.Max(1, value); }
}

[Description("Emergency stop percentage: DEFAULT = 25.0 percent")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("3. Emergency stop percentage")]
public double P05_stoplossPercentage
{
get { return stoplossperc; }
set { stoplossperc = Math.Max(0.001, value); }
}

[Description("Breakeven percentage: DEFAULT = 15.0 percent")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("4. Breakeven percentage")]
public double P06_breakevenPercentage
{
get { return breakevenperc; }
set { breakevenperc = Math.Max(0.001, value); }
}		
	
[Description("Number of stocks traded: DEFAULT = 100")]
[GridCategory("Parameters")]
[Gui.Design.DisplayName("5. Buy/Sell quantity")]
public int P07_stocks_Quantity
{
get { return stocksqty; }
set { stocksqty = Math.Max(1, value); }
}			

#endregion
}
}