#region Namespaces
using System;
using System.IO;
using System.Linq;
#endregion
namespace ScriptCode {
/// <summary>
/// Position sizing scripts are used for overriding the quantity of pending orders after those were generated by a trading strategy.
///
/// This script can be used in several ways:
/// (1) It can be used to test the impact of various position sizing methods on a trading strategy's performance.
/// (2) It can be used to separate the logic between the rules used to generate an order and the rules used to set its size.
/// </summary>
public partial class MyPositionSizing : PositionSizingScriptBase // NEVER CHANGE THE CLASS NAME
{
#region Variables
// The percentage of the equity to risk.
private double _fixedFractional;
// Use to indicate whether to enable the position sizing script to determine the size of exit orders.
private bool _enableExitSizing;
#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[]'
/// 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="fixedFractional" type="Double" default="2">The percentage of the equity to risk. (1 to 100) </param>
/// <param name="enableExitSizing" type="Boolean" default="True">Use to indicate whether to enable the position sizing script to determine the size of exit orders.</param>
public void OnInitialize(
double fixedFractional,
bool enableExitSizing) {
// Set the parameters to script variables.
_fixedFractional = fixedFractional;
_enableExitSizing = enableExitSizing;
}
#endregion
#region OnPositionSize
/// <summary>
/// This function is called for each pending order. It should examine the specified order and
/// return the number of shares, contracts or units to assign it.
/// </summary>
/// <param name="symbolIndex" type="Integer">The index of the symbol in the strategy symbol table</param>
/// <param name="orderIndex" type="Integer">The order index to which a size should be assigned</param>
/// <returns type="Double">The number of shares, contracts or units to assign the specified order.</returns>
public override double OnPositionSize(
int symbolIndex,
int orderIndex) {
// Check whether exit sizing is also enabled.
if (_enableExitSizing) {
// Get the open positions indexes for the symbol.
int[] openPositions = PositionByStatus(C_PositionStatus.OPEN);
// Iterate over the open position indexes.
for (int i = 0; i < openPositions.Length; i++) {
// Check whether the current open position is in the opposite direction of the order, which means tha the order is an exit order.
if (PositionDirection(openPositions[i]) != OrderDirection(orderIndex)) {
// Check whether the specified order quantity will not only exit the position but will also reverse it.
if (PositionCurrentQuantity(openPositions[i]) < OrderQuantity(orderIndex))
// Return a quantity that will both close the existing position and start a new one.
return PositionCurrentQuantity(openPositions[i]) + CalculateFEP(symbolIndex);
// Return the quantity of the open position to be used as the exit order.
else return PositionCurrentQuantity(openPositions[i]);
}
}
}
// Calculate the Fixed Equity %.
return CalculateFEP(symbolIndex);
}
#endregion
#region OnShutdown
/// <summary>
/// This function is called when the script is shutdown.
/// </summary>
public override void OnShutdown() {
}
#endregion
#region CalculateFEP
/// <summary>
/// Use to calculate the Fixed Equity %.
/// </summary>
/// <param name="symbolIndex">The symbol index.</param>
/// <returns>The fixed equity %.</returns>
private double CalculateFEP(int symbolIndex) {
// Get the latest close.
double close = DataClose();
// Check whether the close is valid.
if (close > 0) {
// Get the exchange rate from the symbol's currency to the account's currency.
double exchangeRate = StrategyGetExchangeRate(SymbolCurrencyCode(), StrategyCurrencyCode());
// Calculate the number of units to trade.
return Math.Floor((_fixedFractional / 100 * StrategyEquity()) / (exchangeRate * close));
}
else return 0;
}
#endregion
}
}