How to Add Stop Loss and Profit Target Orders

#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 TradeManagementStrategyAPI import *
from AssemblyTradeManagementStrategy_3000_ImportedScripts import *
# ---------------------------------------------------------------

## <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>
class MyTradeManagementStrategy(ScriptCode.TradeManagementStrategyScriptBase): # 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.
    ## </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="stopLossOffset" type="Double" default="0">The stop loss offset in percent from the current price (set to zero to not set a stop loss)</param>	
    ## <param name="profitTargetOffset" type="Double" default="0">The profit target offset in percent from the current price (set to zero to not set a profit target)</param>		
    def OnInitialize(self,stopLossOffset,profitTargetOffset):
        # Set the parameters to script variables. 
        self._stopLossOffset = stopLossOffset
        self._profitTargetOffset = profitTargetOffset
    #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">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>
    def OnBarUpdate(self, symbolIndex, dataSeries, completedBars):
        # OnBarUpdate Content
        pass
    #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>
    def OnEntryOrder(self, symbolIndex, orderIndex):
        # Create a variable to hold whether the stop loss offset should be added or subtracted to the expected price.
        stopLossDirection = 0
        # Create a variable to hold whether the profit target offset should be added or subtracted to the expected price.
        profitTargetDirection = 0
        
		# Check whether the order is a long order.
        if OrderActionType(orderIndex) == C_ActionType.BUY or OrderActionType(orderIndex) == C_ActionType.BUY_TO_COVER:
            # Record that the stop loss offset should be subtracted.
            stopLossDirection = -1
            # Record that the profit target offset should be added.
            profitTargetDirection = 1
        else:
            # Record that the stop loss offset should be added.
            stopLossDirection = 1
            # Record that the profit target offset should be subtracted.
            profitTargetDirection = -1
            
        # Check whether a stop loss has been set.
        if self._stopLossOffset != 0:
            # Calculate the stop loss price.
            stopLossPrice = OrderExpectedPrice(orderIndex) * ((100 + stopLossDirection * self._stopLossOffset) / 100)
            # Set a stop loss for the order.
            stopLossOrderIndex = BrokerSetStopLoss(orderIndex, stopLossPrice, "Stop Loss")
            # Register the stop loss order.
            TradeManagementRegisterOrder(stopLossOrderIndex)
            
        # Check whether a profit target has been set.
        if self._profitTargetOffset != 0:
            # Calculate the profit target price.
            profitTargetPrice = OrderExpectedPrice(orderIndex) * ((100 + profitTargetDirection * self._profitTargetOffset) / 100)
            # Set a profit target for the order.
            profitTargetOrderIndex = BrokerSetTakeProfit(orderIndex, profitTargetPrice, "Take Profit")
            # Register the profit target order.
            TradeManagementRegisterOrder(profitTargetOrderIndex)
    #endregion

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