Bracket in Ticks

Trade Management Strategy

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

namespace ScriptCode {
	/// <summary>
	/// Trade Management Strategy scripts have multiple use-cases such as implementing position entry strategies,
	/// implementing position exit strategies and implementing advanced order management systems, among others.
	/// </summary>
	public partial class MyTradeManagementStrategy : TradeManagementStrategyScriptBase // NEVER CHANGE THE CLASS NAME
	{
#region Variables
		// The order index that started the strategy.
		private int _parentOrderIndex;
		// The quantity of the entry order.
		private double _quantity;
		// The stop loss offset in ticks from the current price (set to zero to not set a stop loss)
		private double _stopLossOffset;
		// Indicates whether the position should be reversed once the stop loss is triggered
		private bool _reverseAtStopLoss;
		// The profit target offset in ticks from the current price (set to zero to not set a profit target)
		private double _profitTargetOffset;
		// Indicates whether the position should be reversed once the target is triggered
		private bool _reverseAtTarget;
		// The stop loss order index.
		private int _stopLossOrderIndex;
		// The profit target order index.
		private int _profitTargetOrderIndex;
		// The reversed order index.
		private int _reversedOrderIndex;
#endregion

#region OnInitialize
		/// <summary>
		/// This function is used for accepting the script parameters and for initializing the script prior to all other function calls.
		/// </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[]'

		/// 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="stopLossOffset" type="Double" default="0">The stop loss offset in ticks from the current price (set to zero to not set a stop loss)</param>		
		/// <param name="reverseAtStopLoss" type="Boolean" default="false">Indicates whether the position should be reversed once the stop loss is triggered</param>		
		/// <param name="profitTargetOffset" type="Double" default="0">The profit target offset in ticks from the current price (set to zero to not set a profit target)</param>		
		/// <param name="reverseAtTarget" type="Boolean" default="false">Indicates whether the position should be reversed once the target is triggered</param>                
		public void OnInitialize(
			 double stopLossOffset,
			 bool reverseAtStopLoss,
			 double profitTargetOffset,
			 bool reverseAtTarget) {
			_stopLossOffset = stopLossOffset;
			_reverseAtStopLoss = reverseAtStopLoss;
			_profitTargetOffset = profitTargetOffset;
			_reverseAtTarget = reverseAtTarget;
			_reversedOrderIndex = - 1;
		}
#endregion

#region OnBarUpdate
		/// <summary>
		/// This function is called after each new bar belonging to the symbol that triggered the trade management strategy. 
		/// It can be used to evaluate the symbol and its new bar in order to submit, modify or cancel orders.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The index of the symbol in the symbol table</param>
		/// <param name="dataSeries" type="Integer">The number indicating the data series from which the symbol was updated.
		/// 0 for the main data series which streams tick data, 1 for the second data series which streams minute bars that are updated on bar update.</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>
		public override void OnBarUpdate(
			int symbolIndex,
			int dataSeries,
			int completedBars) {
			// Check whether the order should reverse on stop loss and the stop loss has been executed, yet the order has not been reversed.
			if (_reverseAtStopLoss && _reversedOrderIndex == - 1 && _stopLossOrderIndex != -1 &&
				OrderStatus(_stopLossOrderIndex) == C_Status.EXECUTED) {
				// Check whether the stop loss order was for a long position.
				if (OrderActionType(_stopLossOrderIndex) == C_ActionType.SELL) {
					// Enter a short position.
					_reversedOrderIndex = BrokerMarket(C_ActionType.SELL, _quantity, C_TIF.DAY, "Reverse Long to Short");
				}
				// Check whether the stop loss order was for a short position.
				else {
					// Enter a long position.
					_reversedOrderIndex = BrokerMarket(C_ActionType.BUY, _quantity, C_TIF.DAY, "Reverse Short to Long");
				}
				// Register the reversed order index.
				TradeManagementRegisterOrder(_reversedOrderIndex);
			}

			// Check whether the order should reverse on profit target and the take profit has been executed, yet the order has not been reversed.
			if (_reverseAtTarget && _reversedOrderIndex == - 1 && _profitTargetOrderIndex != -1 &&
				OrderStatus(_profitTargetOrderIndex) == C_Status.EXECUTED) {
				// Check whether the take profit order was for a long position.
				if (OrderActionType(_profitTargetOrderIndex) == C_ActionType.SELL) {
					// Enter a short position.
					_reversedOrderIndex = BrokerMarket(C_ActionType.SELL, _quantity, C_TIF.DAY, "Reverse Long to Short");
				}
				// Check whether the take profit order was for a short position.
				else {
					// Enter a long position.
					_reversedOrderIndex = BrokerMarket(C_ActionType.BUY, _quantity, C_TIF.DAY, "Reverse Short to Long");
				}
				// Register the reversed order index.
				TradeManagementRegisterOrder(_reversedOrderIndex);
			}
			// Check whether the order has been reversed and thus bar updates are no longer required or both the SL and TP orders have been cancelled.
			if (_reversedOrderIndex != - 1 ||
			   ((_stopLossOrderIndex == -1 || OrderStatus(_stopLossOrderIndex) == C_Status.CANCELLED) && (_profitTargetOrderIndex == -1 || OrderStatus(_profitTargetOrderIndex) == C_Status.CANCELLED)) ||
				OrderStatus(_parentOrderIndex) == C_Status.CANCELLED)
			// Stop receiving bar updates.
				TradeManagementStop();
		}
#endregion

#region OnEntryOrder
		/// <summary>
		/// This function is called once for the entry order that triggered the script. 
		/// It's called before the order is submitted and can be used for setting attached orders or OCA groups.
		/// </summary>
		/// <param name="symbolIndex" type="Integer">The symbol index of the order that triggered the script</param>
		/// <param name="orderIndex" type="Integer">The order index that triggered the script</param>
		public override void OnEntryOrder(
			int symbolIndex,
			int orderIndex) {
			// Keep the order index of the order that started the strategy.
			_parentOrderIndex = orderIndex;
			_quantity = OrderQuantity(orderIndex);	

			// Check whether bar updates are required.
			if (_reverseAtStopLoss || _reverseAtTarget)
			// Start receiving bar updates as required by the strategy.
				TradeManagementStart();

			// Check whether the order is a long order.
			if (OrderActionType(orderIndex) == C_ActionType.BUY || OrderActionType(orderIndex) == C_ActionType.BUY_TO_COVER) {

				// Check whether a stop loss has been set.
				if (_stopLossOffset != 0) {
					// Set a stop loss for the order
					_stopLossOrderIndex = BrokerSetStopLoss(orderIndex, OrderExpectedPrice(orderIndex) - _stopLossOffset * SymbolTickSize(), "Stop Loss");
					// Register the stop loss order.
					TradeManagementRegisterOrder(_stopLossOrderIndex);
				}

				// Check whether a profit target has been set.
				if (_profitTargetOffset != 0) {
					// Set a profit target for the order
					_profitTargetOrderIndex = BrokerSetTakeProfit(orderIndex, OrderExpectedPrice(orderIndex) + _profitTargetOffset * SymbolTickSize(), "Take Profit");
					// Register the profit target order.
					TradeManagementRegisterOrder(_profitTargetOrderIndex);
				}
			}
			else {

				// Check whether a stop loss has been set.
				if (_stopLossOffset != 0) {
					// Set a stop loss for the order
					_stopLossOrderIndex = BrokerSetStopLoss(orderIndex, OrderExpectedPrice(orderIndex) + _stopLossOffset * SymbolTickSize(), "Stop Loss");
					// Register the stop loss order.
					TradeManagementRegisterOrder(_stopLossOrderIndex);
				}

				// Check whether a profit target has been set.
				if (_profitTargetOffset != 0) {
					// Set a profit target for the order
					_profitTargetOrderIndex = BrokerSetTakeProfit(orderIndex, OrderExpectedPrice(orderIndex) - _profitTargetOffset * SymbolTickSize(), "Take Profit");
					// Register the profit target order.
					TradeManagementRegisterOrder(_profitTargetOrderIndex);
				}
			}
		}
#endregion

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