Normalized Trend Following

#region Namespaces 
using System;
using System.IO;
using System.Linq;
using System.Collections.Generic;
#endregion

namespace ScriptCode {
	/// <summary>
	/// This is a trend following strategy that trades in symbols exhibiting relatively strong upward or downward trends. 
	/// This strategy measures a symbol’s trend strength as the difference between the current Close and an exponentially-weighted moving average (EMA) of the Close divided by an EMA of the absolute value of the change in the Close price. 
	/// Calculating the signal value this way quantifies the strength of the trend by comparing how the most recent change in price compares to the average change in price in the past.
	/// The higher the current change in price relative to the average change in price, the higher the strength of the trend.
	/// 
	/// To determine which symbols to invest in, the strategy ranks each symbol based on the value of their trend strength. 
	/// The strategy will go long in the symbols with the highest trend strength values and go short in the symbols with the lowest trend strength values.
	/// The strategy rebalances after the specified number of periods.
	/// 
	/// This strategy was studied using various asset classes in the 2014 paper “Two centuries of trend following” by Y. Lempérière, C. Deremble, P. Seager, M. Potters, and J. P. Bouchaud.
	/// 
	/// Trading Rules: 
	/// 
	/// Long Entry: A buy market order is generated when the symbol satisfies the trend strength cutoff criteria for long entries and the symbol’s trend strength value is positive.
	/// Long Exit: A sell market order is generated when the position has been held for the specified number of bars.
	/// 
	/// Short Entry: A sell-short market order is generated when the symbol satisfies the trend strength cutoff criteria for short entries and the symbol’s trend strength value is negative.
	/// Short Exit: A buy market order is generated when the position has been held for the specified number of bars.
	/// </summary>
	public partial class MyMultiSymbolTradingStrategy : MultiSymbolTradingStrategyScriptBase  // NEVER CHANGE THE CLASS NAME 
	{
#region Variables
		// Use for holding signal indicators indexed by symbol index.
		private Indicator [] _signal;
		// Use for holding the symbol signal values <symbol index, latest signal value for symbol>.
		private List<Tuple<int, double>> _symbolSignals;
		// The number of symbols to hold for each trade direction (long and short).
		private int _holdSymbols;
		// The number of bars to hold the selected symbols.
		private int _holdBars;
		// Use for counting the number of bars the current open positions have been held.
		private int _heldBars;
		// Indicates whether to enable the trading strategy to short symbols.
		private bool _enableShorting;
		// Indicates whether to enable the trading strategy to long symbols.
		private bool _enableLonging;
		// The percent distance from the entry price in which to place a stop loss order.
		private double _stopLoss;
		// The percent distance from the entry price in which to place a take profit order. 
		private double _takeProfit;
		// The minimum price a symbol can have to be eligible for trading.
		private double _minimumPrice;
		// Indicates whether the strategy is waiting for an open position to close.
		private bool [] _waitingToClose;
#endregion

#region OnInitialize
		/// <summary>
		/// This function is used for accepting the script parameters and for initializing the script prior to all other function calls.
		/// Once the script is assigned to a Desktop, its parameter values can be specified by the user and can be selected for optimization. 
		/// </summary>
		/// --------------------------------------------------------------------------------------------------
		/// PLEASE USE THE SCRIPT WIZARD (CTRL+W) TO ADD, EDIT AND REMOVE THE SCRIPT PARAMETERS
		/// --------------------------------------------------------------------------------------------------
		/// YOU MUST SET A PARAM TAG FOR EACH PARAMETER ACCEPTED BY THIS FUNCTION.
		/// ALL PARAM TAGS SHOULD BE SET IN THE 'OnInitialize' REGION, RIGHT ABOVE THE 'OnInitialize' FUNCTION.
		/// THE ORDER OF THE TAGS MUST MATCH THE ORDER OF THE ACTUAL PARAMETERS.

		/// REQUIRED ATTRIBUTES:
		/// (1) name: The exact parameter name.
		/// (2) type: The type of data to collect from the user: 
		/// Set to "Integer" when the data type is 'int'
		/// Set to "IntegerArray" when the data type is 'int[]'
		/// Set to "DateTime" when the data type is 'long'  
		/// Set to "DateTimeArray" when the data type is 'long[]'  
		/// Set to "Boolean" when the data type is 'bool'
		/// Set to "BooleanArray" when the data type is 'bool[]'
		/// Set to "Double" when the data type is 'double'
		/// Set to "DoubleArray" when the data type is 'double[]'
		/// Set to "String" when the data type is 'string'
		/// Set to "StringArray" when the data type is 'string[]'
		/// Set to "Indicator" when the data type is 'Indicator'
		/// Set to "Pattern" when the data type is 'Pattern'
		/// Set to "Signal" when the data type is 'Signal'
		/// Set to "Drawing" when the data type is 'Drawing'

		/// OPTIONAL ATTRIBUTES:
		/// (3) default: The default parameter value is only valid when the type is Integer, Boolean, Double, String or an API Type. 
		/// (4) min: The minimum parameter value is only valid when the type is Integer or Double.
		/// (5) max: The maximum parameter value is only valid when the type is Integer or Double.

		/// EXAMPLE: <param name="" type="" default="" min="" max="">Enter the parameter description here.</param> 
		/// --------------------------------------------------------------------------------------------------
		/// <param name="trendPeriods" type="Integer" default="24" min="1" max="10000000">The number of periods used to calculate the strength of the trend.</param>
		/// <param name="emaPeriods" type="Integer" default="5" min="1" max="10000000">The number of periods used to calculate the exponential moving average weights.</param>
		/// <param name="holdSymbols" type="Integer" default="10" min="1" max="10000">The number of symbols to hold for each trade direction (long/short).</param>
		/// <param name="holdBars" type="Integer" default="1" min="1" max="10000000">The number of bars to hold the selected symbols.</param>
		/// <param name="enableShorting" type="Boolean" default="True">Indicates whether to enable the trading strategy to short symbols. </param>
		/// <param name="enableLonging" type="Boolean" default="True">Indicates whether to enable the trading strategy to long symbols. </param>
		/// <param name="stopLoss" type="Double" default="0">The percent distance from the entry price in which to place a stop loss order. (0 to ignore). </param>
		/// <param name="takeProfit" type="Double" default="0">The percent distance from the entry price in which to place a take profit order. (0 to ignore). </param>
		/// <param name="minimumPrice" type="Double" default="5">The minimum price a symbol can have to be eligible for trading.</param>
		public void OnInitialize(
			int trendPeriods,
			int emaPeriods,
			int holdSymbols,
			int holdBars,
			bool enableShorting,
			bool enableLonging,
			double stopLoss,
			double takeProfit,
			double minimumPrice) {
			// Set the script parameters to script variables.
			_holdSymbols = holdSymbols;
			_holdBars = holdBars;
			_enableShorting = enableShorting;
			_enableLonging = enableLonging;
			_stopLoss = stopLoss;
			_takeProfit = takeProfit;
			_minimumPrice = minimumPrice;
			// Create an array large enough to hold a single indicator for each symbol.
			Indicator [] closeEMA = new Indicator[SymbolCount()];
			Indicator [] volatilityEMA = new Indicator[SymbolCount()];
			Indicator [] change = new Indicator[SymbolCount()];
			_signal = new Indicator[SymbolCount()];
			// Iterate over all of the symbol indexes.
			for (int symbolIndex = 0; symbolIndex < SymbolCount(); symbolIndex++) {
				// Create the close EMA indicator.
				closeEMA[symbolIndex] = IndicatorEMA(IndicatorCLOSE(symbolIndex), emaPeriods);
				// Create the volatility EMA indicator.
				volatilityEMA[symbolIndex] = IndicatorEMA(IndicatorABS(IndicatorSUB(IndicatorCLOSE(symbolIndex), IndicatorSHF(IndicatorCLOSE(symbolIndex), trendPeriods))), emaPeriods);
				// Create the change indicator. Note a shift is needed to exclude price information covering the time period associated with the most recent signal value.
				change[symbolIndex] = IndicatorSUB(IndicatorCLOSE(symbolIndex), IndicatorSHF(closeEMA[symbolIndex], trendPeriods));
				// Finish calculating the signal value. Note a shift is needed to exclude price information covering the time period associated with the most recent signal value.
				_signal[symbolIndex] = IndicatorDIV(change[symbolIndex], IndicatorSHF(volatilityEMA[symbolIndex], trendPeriods));
			}
			// Create for holding the symbol signal values <symbol index, latest signal value for symbol>.
			_symbolSignals = new List<Tuple<int, double>>();
			// Create for holding whether the strategy is waiting for an open position to close.
			_waitingToClose = new bool[SymbolCount()];
		}
#endregion

#region OnBarUpdate
		/// <summary>
		/// This function is called after each new bar of each symbol assigned to the Desktop strategy. 
		/// It should evaluate the specified symbol and its new bar in order to determine whether to generate new orders for it. 
		/// Never create indicators, signals or patterns from OnBarUpdate, for performance reasons those should be created from OnInitialize.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The index of the symbol in the strategy symbol table</param>
		/// <param name="dataSeries" type="Integer">The number indicating the data series from which the symbol was updated. 
		/// According to the Desktop strategy data series settings: 0 for the main data series, 1 for the second data series, etc.</param>
		/// <param name="completedBars" type="Integer">The number of completed bars for the specified symbol since the last call to OnBarUpdate.
		/// Always 1 unless the bar type can generate multiple completed bars from a single tick/minute/day update (depending on the underlying bar source).</param>
		/// <param name="isLastSymbol" type="Boolean">Indicates whether this is the last symbol to be updated for the current bar. 
		/// The parameter is valid when the bars for different symbols have matching timestamps, e.g. 1m, 5m, 1d, 1w, etc.</param>
		public override void OnBarUpdate(
			int symbolIndex,
			int dataSeries,
			int completedBars,
			bool isLastSymbol) {
			// Check whether all of the symbols have been updated.
			if(isLastSymbol){
				// Switch the API functions to work with the current symbol.
				SymbolSwitch(symbolIndex);
				// Check whether an open position exists and whether the bar is complete.
				if(PositionCountByStatusAll(C_PositionStatus.OPEN) > 0 && DataIsComplete()){
					// Increase the number of held bars.
					_heldBars++;
				}
				// Check whether there are no open positions or whether the number of held bars matches the specified number of hold bars.
				if (PositionCountByStatusAll(C_PositionStatus.OPEN) == 0 || _heldBars == _holdBars) {
					// Clear the list of signals.
					_symbolSignals.Clear();
					// Iterate through each symbol.
					for (int symIndex = 0; symIndex < SymbolCount(); symIndex++) {
						// Switch the API functions to work with the current symbol.
						SymbolSwitch(symIndex);
						// Check whether the strategy is not waiting for a position to be closed and there is currently an open position.
						if(!_waitingToClose[symIndex] && PositionExists(C_PositionStatus.OPEN)){
							// Exit any open positions
							BrokerClosePosition("Time to rebalance");
							// Record that the strategy is waiting for the position to be closed.
							_waitingToClose[symIndex] = true;
						}
						// Check whether the symbol is trading above the minimum price, there was enough history to calculate the first signal value, and whether the symbol is active.
						if(DataClose() > _minimumPrice && !double.IsInfinity(_signal[symIndex][0]) && SymbolIsAvailable()){
							// Get the signal value for the latest bar of the current symbol.
							_symbolSignals.Add(new Tuple<int, double>(symIndex, _signal[symIndex][0]));
						}
					}
					// Sort the symbols by descending signal values so that those with higher signal values come first.
					_symbolSignals.Sort((x, y) => y.Item2.CompareTo(x.Item2));
					// Check whether the trading strategy can go long.
					if(_enableLonging){
						// Iterate over the number of symbols to hold that have positive signal values.
						for (int i = 0; i < _symbolSignals.Count && i < _holdSymbols && _symbolSignals[i].Item2 > 0; i++) {
							// Switch the API functions to work with the current symbol.
							SymbolSwitch(_symbolSignals[i].Item1);
							// Check to ensure there is not an open position or pending order.
							if (!PositionExists(C_PositionStatus.OPEN) && !OrderExists(C_Status.PENDING)) {
								// Buy the current symbol while assuming that a position sizing script will assign the quantity.
								int orderIndex = BrokerMarket(C_ActionType.BUY, 0, C_TIF.DAY, "Ranked "+(i+1));
								// Set a stop loss on the order. 
								BrokerSetStopLossPercent(orderIndex, _stopLoss, true, "Stop loss");
								// Set a take profit on the order. 
								BrokerSetTakeProfitPercent(orderIndex, _takeProfit, true, "Profit target");
							}
						}
					}
					// Check whether the trading strategy can go short.
					if(_enableShorting){
						// Iterate over the number of symbols to hold that have negative signal values.
						for (int i = _symbolSignals.Count - 1; i >= 0 && (_symbolSignals.Count - 1 - i) < _holdSymbols && _symbolSignals[i].Item2 < 0; i--) {
							// Switch the API functions to work with the current symbol.
							SymbolSwitch(_symbolSignals[i].Item1);
							// Check to ensure there is not an open position or pending order.
							if (!PositionExists(C_PositionStatus.OPEN) && !OrderExists(C_Status.PENDING)) {
								// Buy the current symbol while assuming that a position sizing script will assign the quantity.
								int orderIndex = BrokerMarket(C_ActionType.SELL_SHORT, 0, C_TIF.DAY, "Ranked "+(i+1));
								// Set a stop loss on the order. 
								BrokerSetStopLossPercent(orderIndex, _stopLoss, true, "Stop loss");
								// Set a take profit on the order. 
								BrokerSetTakeProfitPercent(orderIndex, _takeProfit, true, "Profit target");
							}
						}
					}
					// Clear the number of held bars.
					_heldBars = 0;
				}
			}
		}
#endregion

#region OnOrderFillUpdate
		/// <summary>
		/// This function is called for each new order fill.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index</param>
		/// <param name="orderIndex" type="Integer">The order index</param>
		/// <param name="orderFillIndex" type="Integer">The order fill index</param>
		public override void OnOrderFillUpdate(
			int symbolIndex,
			int orderIndex,
			int orderFillIndex) {
			// OnOrderFillUpdate Content
		}
#endregion

#region OnOrderUpdate
		/// <summary>
		/// This function is called when an order is executed or cancelled.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The underlying symbol index of the order</param>
		/// <param name="orderIndex" type="Integer">The order index</param>
		/// <param name="status" type="C_Status">The updated status of the order</param>
		public override void OnOrderUpdate(
			int symbolIndex,
			int orderIndex,
			C_Status status) {
			// OnOrderUpdate Content
		}
#endregion

#region OnPositionUpdate
		/// <summary>
		/// This function is called when a position is opened or closed. 
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The underlying symbol index of the position</param>
		/// <param name="positionIndex" type="Integer">The position index</param>
		/// <param name="status" type="C_PositionStatus">The updated status of the position</param>
		public override void OnPositionUpdate(
			int symbolIndex,
			int positionIndex,
			C_PositionStatus status) {
			// Switch the API functions to work with the current symbol.
			SymbolSwitch(symbolIndex);
			// Check whether the position just closed.
			if(status == C_PositionStatus.CLOSED){
				// Record that the strategy is no longer waiting for the position to be closed.
				_waitingToClose[symbolIndex] = false;
			}
		}
#endregion

#region OnSessionUpdate
		/// <summary>
		/// This function is called when a session is opened or closed.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index whose session is updated</param>
		/// <param name="status" type="C_SessionStatus">The session status</param>
		public override void OnSessionUpdate(
			int symbolIndex,
			C_SessionStatus status) {
		}
#endregion

#region OnNewsUpdate
		/// <summary>
		/// This function is called when a news update is received and only if the NO_NEWS_UPDATES comment is removed.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index for the update</param>
		/// <param name="dateTime" type="DateTime">The date/time in which the update was received by the platform</param>
		/// <param name="title" type="String">The update title</param>
		/// <param name="message" type="String">The update message</param>   
		/// <param name="type" type="C_MessageType">The update message type</param>
		public override void OnNewsUpdate(
			int symbolIndex,
			long dateTime,
			string title,
			string message,
			C_MessageType type) {
			// OnNewsUpdate Content
			// [NO_NEWS_UPDATES] - Delete this comment to enable news updates to this strategy.
		}
#endregion

#region OnRSSUpdate
		/// <summary>
		/// This function is called when an RSS update is received and only if the NO_RSS_UPDATES comment is removed.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index for the update</param>
		/// <param name="dateTime" type="DateTime">The date/time in which the update was received by the platform</param>
		/// <param name="title" type="String">The update title</param>
		/// <param name="message" type="String">The update message</param>   
		/// <param name="type" type="C_MessageType">The update message type</param>
		public override void OnRSSUpdate(
			int symbolIndex,
			long dateTime,
			string title,
			string message,
			C_MessageType type) {
			// OnRSSUpdate Content
			// [NO_RSS_UPDATES] - Delete this comment to enable RSS updates to this strategy.
		}
#endregion

#region OnAlertUpdate
		/// <summary>
		/// This function is called when an alert update is received and only if the NO_ALERT_UPDATES comment is removed.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index for the update</param>
		/// <param name="dateTime" type="DateTime">The date/time in which the update was received by the platform</param>
		/// <param name="message" type="String">The update message</param>   
		/// <param name="type" type="C_MessageType">The update message type</param>
		public override void OnAlertUpdate(
			int symbolIndex,
			long dateTime,
			string message,
			C_MessageType type) {
			// OnAlertUpdate Content
			// [NO_ALERT_UPDATES] - Delete this comment to enable alert updates to this strategy.
		}
#endregion

#region OnJournalUpdate
		/// <summary>
		/// This function is called when a journal update is received and only if the NO_JOURNAL_UPDATES comment is removed.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index for the update</param>
		/// <param name="dateTime" type="DateTime">The date/time in which the update was received by the platform</param>
		/// <param name="title" type="String">The update title</param>
		/// <param name="message" type="String">The update message</param>   
		/// <param name="type" type="C_MessageType">The message type</param>
		public override void OnJournalUpdate(
			int symbolIndex,
			long dateTime,
			string title,
			string message,
			C_MessageType type) {
			// OnJournalUpdate Content
			// [NO_JOURNAL_UPDATES] - Delete this comment to enable journal updates to this strategy.
		}
#endregion

#region OnDataConnectionUpdate
		/// <summary>
		/// This function is called when a data connection update is received and only if the NO_DATA_CONNECTION_UPDATES comment is removed.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index for the update</param>
		/// <param name="dateTime" type="DateTime">The date/time in which the update was received by the platform</param>
		/// <param name="message" type="String">The update message</param>   
		/// <param name="type" type="C_MessageType">The update message type</param>
		public override void OnDataConnectionUpdate(
			int symbolIndex,
			long dateTime,
			string message,
			C_MessageType type) {
			// OnDataConnectionUpdate Content
			// [NO_DATA_CONNECTION_UPDATES] - Delete this comment to enable data connection updates to this strategy.
		}
#endregion

#region OnBrokerConnectionUpdate
		/// <summary>
		/// This function is called when a broker connection update is received and only if the NO_BROKER_CONNECTION_UPDATES comment is removed.
		/// </summary>
		/// <param name="dateTime" type="DateTime">The date/time in which the update was received by the platform</param>
		/// <param name="message" type="String">The update message</param>   
		/// <param name="type" type="C_MessageType">The update message type</param>
		public override void OnBrokerConnectionUpdate(
			long dateTime,
			string message,
			C_MessageType type) {
			// OnBrokerConnectionUpdate Content
			// [NO_BROKER_CONNECTION_UPDATES] - Delete this comment to enable broker connection updates to this strategy.
		}
#endregion

#region OnShutdown
		/// <summary>
		/// This function is called when the script is shutdown.
		/// </summary>
		public override void OnShutdown() {
			// OnShutdown Content
		}
#endregion
	}
}