How to Apply a Fixed Equity Limit

#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 RiskManagementAPI import *
from AssemblyRiskManagement_3000_ImportedScripts import *
# ---------------------------------------------------------------
#endregion

## <summary>
## Risk management scripts are used for managing risk by modifying or cancelling trading strategy orders based on portfolio level risk analysis. 
## Common use-cases include managing risk during extreme market conditions and limiting overexposure to a single symbol due to multiple trading strategies that are trading it.
## </summary>
class MyRiskManagement(ScriptCode.RiskManagementScriptBase): # 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 'int'
    ## Set to "IntegerArray" when the data type is 'int[]'
    ## Set to "DateTime" when the data type is 'long' (The 'long' data type can only be used for date/time representation)
    ## Set to "DateTimeArray" when the data type is 'long[]' (The 'long' data type can only be used for date/time representation)
    ## 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="maxEquity" type="Double" default="10000">Use for the maximum equity that a single symbol can be allocated.</param>
	## <param name="currencyCode" type="String" default="USD">Use for the currency code the equity is denominated in.</param>
    def OnInitialize(self,maxEquity,currencyCode):
        # Set the parameters to script variables. 
        self._maxEquity = maxEquity
        self._currencyCode = currencyCode
    #endregion

    #region OnRiskManagement
    ## <summary>
    ## This function is called once for each new pending order so that it may modify or cancel it if necessary.   
    ## </summary>
    ## <param name="strategyNumber" type="Integer">The strategy number to which the order belongs</param>
    ## <param name="orderIndex" type="Integer">The order index in the orders table</param>
    def OnRiskManagement(self, strategyNumber, orderIndex):
        # Check whether the order is an exit order which should never be cancelled as it decreases risk.
        if OrderActionType(strategyNumber, orderIndex) == C_ActionType.BUY_TO_COVER or OrderActionType(strategyNumber, orderIndex) == C_ActionType.SELL:
            return
        
        # Get the specified order's symbol index.
        symbolIndex = OrderSymbolIndex(strategyNumber, orderIndex)
        # Get the underlying symbol code for the order symbol. 
        symbolCode = SymbolID(strategyNumber, symbolIndex)
        # Get the exchange rate between the symbol and the specified currency code.
        exchangeRate = StrategyGetExchangeRate(SymbolCurrencyCode(strategyNumber, symbolIndex), self._currencyCode)
		# The total symbol equity.
        symbolEquity = 0
        # Iterate over all of the strategies. 
        for strategyIndex in range(StrategyCount()):
            # Check whether the current strategy is active.
            if StrategyIsActive(strategyIndex):
                # The symbol index of the order's symbol in the current strategy (the strategy might not have this symbol at all).
                symbolIndex = -1
                # Iterate over all of the current strategy's symbols while searching for a matching symbol.
                for tempSymbolIndex in range(SymbolCount(strategyIndex)):
                    # Check whether a matching symbol has been found in the current strategy.
                    if SymbolID(strategyIndex, tempSymbolIndex) == symbolCode:
                        # Keep the symbol index of the order's symbol in the current strategy.
                        symbolIndex = tempSymbolIndex
                        break
                # Check whether a matching symbol has been found.
                if symbolIndex >= 0:
                    # Get the pending orders of the order symbol in the current strategy. 
                    pendingOrderIndexes = OrderByStatus(strategyIndex, C_Status.PENDING, symbolIndex)
                    # Iterate over all of the pending orders.
                    for pendingOrderIndex in pendingOrderIndexes:
                        # Check whether the pending order is an entry order.
                        if (OrderActionType(strategyIndex, pendingOrderIndex) == C_ActionType.BUY or OrderActionType(strategyIndex, pendingOrderIndex) == C_ActionType.SELL_SHORT):
                            # Add the expected equity of the current pending order.
                            symbolEquity += exchangeRate * OrderExpectedPrice(strategyIndex, pendingOrderIndex) * OrderQuantity(strategyIndex, pendingOrderIndex)
					# Get the open position indexes of the specifieed symbol in the current strategy.
                    openPositionIndexes = PositionByStatus(strategyIndex, C_PositionStatus.OPEN, symbolIndex)
                    # Iterate over all of the open position indexes.
                    for openPositionIndex in openPositionIndexes:
                        # Add the equity of the current position.
                        symbolEquity += exchangeRate * PositionCurrentValue(strategyIndex, openPositionIndex)
        
        # Check whether the symbol equity is too much.
        if symbolEquity >= self._maxEquity:
            BrokerCancelOrder(strategyNumber, orderIndex, "Risk management, max equity limit.")
    #endregion

    #region OnShutdown
    ## <summary>
    ## This function is called when the script is shutdown.
    ## </summary>
    def OnShutdown(self):
        # OnShutdown Content
        pass
    #endregion