#region Namespaces
# ---------- DON'T REMOVE OR EDIT THESE LINES -------------------
# These lines are required for integrating Python with our .NET platform.
import clr
clr.AddReference("Tickblaze.Model")
import ScriptCode
from PositionSizingAPI import *
from AssemblyPositionSizing_3000_ImportedScripts import *
# ---------------------------------------------------------------
#endregion
# Import the math package to gain access to the floor function.
import math
## <summary>
## Position Sizing scripts are used for overriding the quantity of pending orders after those were generated by a Trading Strategy script.
## Common use-cases include testing the impact of various position sizing methods on a trading strategy's performance, as well as sharing sophisticated position sizing logic between strategies.
## Using Position Sizing scripts is completely optional as Trading Strategy scripts already assign quantity to all of their orders.
## </summary>
class MyPositionSizing(ScriptCode.PositionSizingScriptBase): # NEVER CHANGE THE CLASS NAME
#region Variables
# Variables Content
#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>
## --------------------------------------------------------------------------------------------------
## INSTRUCTIONS - PLEASE READ CAREFULLY
## --------------------------------------------------------------------------------------------------
## 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 an integer.
## Set to "IntegerArray" when the data type is an integer list.
## Set to "DateTime" when the data type is is an integer representing a date/time.
## Set to "DateTimeArray" when the data type is an integer list representing a list of date/time.
## Set to "Boolean" when the data type is a boolean.
## Set to "BooleanArray" when the data type is a list of booleans.
## Set to "Double" when the data type is a number.
## Set to "DoubleArray" when the data type is a list of numbers.
## Set to "String" when the data type is a string.
## Set to "StringArray" when the data type is a list of strings.
## 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="fixedEquityPerTrade" type="Double" default="5000">The fixed amount of equity to invest in a single trade, denominated in the account currency.</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>
def OnInitialize(self,fixedEquityPerTrade,enableExitSizing):
## Set the parameters to script variables.
self._fixedEquityPerTrade = fixedEquityPerTrade
self._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>
def OnPositionSize(self, symbolIndex, orderIndex):
# Check if a position already exists and the script should size exit orders based on position size.
if PositionExists(C_PositionStatus.OPEN) and self._enableExitSizing:
# Get the indices of open positions.
positionIndices = PositionByStatus(C_PositionStatus.OPEN)
# Iterate through the open positions.
for positionIndex in positionIndices:
# Check if the current order is meant to close the open position.
if PositionDirection(positionIndex) != OrderDirection(orderIndex):
# Return the current quantity of the open position.
return PositionCurrentQuantity(positionIndex)
else:
# Return the number of shares that can be traded for the provided fixed equity amount.
return self.CalculateFE(symbolIndex)
#endregion
#region OnShutdown
## <summary>
## This function is called when the script is shutdown.
## </summary>
def OnShutdown(self):
# OnShutdown Content
pass
#endregion
def CalculateFE(self, symbolIndex):
# Get the latest close.
close = DataClose(0)
# Get the exchange rate from the symbol's currency code to the strategy's currency code.
exchangeRate = StrategyGetExchangeRate(SymbolCurrencyCode(), StrategyCurrencyCode())
# Check whether the bar close is valid.
if close > 0:
# Calculate the number of shares and round down.
return math.floor(self._fixedEquityPerTrade / (exchangeRate * close))
else:
return 0