How to Add Profit Taking Functionality

How to Add Profit Taking Functionality

#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 AddOnAPI import *
from AssemblyAddOn_3000_ImportedScripts import *
# ---------------------------------------------------------------

# Import the math package to gain access to the floor function.
import math

## <summary>
## Add-on scripts are used for adding functionality to the platform by allowing custom code to be triggered manually from its trading tools. 
## Common use-cases include sending orders, sending basket orders, exporting data to files, communicating with social media and running automated processes.
## </summary>
class MyAddOn(ScriptCode.AddOnScriptBase): # 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 '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.

    ## --------------------------------------------------------------------------------------------------
    ## <param name="profitPercentThreshold" type="Double" default="5" min="0" >The minimum amount of profit in percent a position must have in order to qualify for profit taking. </param>
    ## <param name="positionReductionPercent" type="Double" default="50" min="0" max="100">The percentage amount used to reduce the profitable position.</param>
    def OnInitialize(self,profitPercentThreshold,positionReductionPercent):
        # Set the parameters to script variables. 
        self._profitPercentThreshold = profitPercentThreshold
        self._positionReductionPercent = positionReductionPercent
    #endregion

    #region OnTriggered
    ## <summary>
    ## This function is called when the add-on is triggered by the user.
    ## </summary>
    ## <param name="strategyNumber" type="Integer">The strategy number on which the add-on was called (or -1 if none is available)</param>
    ## <param name="symbolIndex" type="Integer">The symbol index of the symbol on which the add-on was called (or -1 if none is available)</param>
    ## <param name="index" type="Integer">The item index of the item on which the add-on was called, such as the order index, trade index and position index (or -1 if none is available)</param>
    def OnTriggered(self, strategyNumber, symbolIndex, index):
        # Iterate through each strategy.
        for tempStrategyIndex in range(StrategyCount()):
            # Create a list to hold the open position indices.
            openPositions = PositionByStatus(tempStrategyIndex, C_PositionStatus.OPEN, None)
            # Iterate through all open positions in the current strategy.
            for tempOpenPositionIndex in openPositions:
                # Check whether the position satisfies the threshold for profit taking.
                if PositionProfitLossPercent(tempStrategyIndex, tempOpenPositionIndex) >= self._profitPercentThreshold:
                    # Determine whether the profit taking order needs to buy to sell to reduce the position.
                    actionType = C_ActionType.BUY_TO_COVER if PositionDirection(tempStrategyIndex, tempOpenPositionIndex) == C_Direction.SHORT_SIDE else C_ActionType.SELL
                    # Calculate the number of shares to trade.
                    quantity = math.floor(PositionCurrentQuantity(tempStrategyIndex, tempOpenPositionIndex) * self._positionReductionPercent / 100)
                    # Generate a market order.
                    BrokerMarket(tempStrategyIndex, PositionSymbolIndex(tempStrategyIndex, tempOpenPositionIndex), actionType, quantity, C_TIF.GTC, "Profit taking.")
    #endregion