How to Apply a Long-Term Capital Gains Tax

How to Apply a Long-Term Capital Gains Tax

#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 TaxSystemAPI import *
from AssemblyTaxSystem_3000_ImportedScripts import *
# ---------------------------------------------------------------
#endregion

## <summary>
## Tax system scripts are used for calculating and reducing the capital gain taxes created by the strategies.
## </summary>
class MyTaxSystem(ScriptCode.TaxSystemScriptBase): # 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="longTermCapitalGainsTax" type="Double" default="15">The long term (over 12 months) capital gains tax on stock profits.</param>
	## <param name="taxMonth" type="Integer" default="4" min="1" max="12">The tax month (in the local time zone).</param>		
	## <param name="taxDay" type="Integer" default="15" min="1" max="31">The tax day (in the local time zone).</param>     
    def OnInitialize(self, longTermCapitalGainsTax, taxMonth, taxDay):
        # Set the script time zone to the local time zone. 
        DateTimeSetLocalZone()
        # Set the parameters to script variables. 
        self._longTermCapitalGainsTax = longTermCapitalGainsTax
        self._taxMonth = taxMonth
        self._taxDay = taxDay
    #endregion

    #region OnTax
    ## <summary>
    ## This function is called daily at the desktop EOD time, at which point it should calculate and reduce capital gain taxes 
    ## from the desktop strategys as needed. Since taxes are usually calculated only once a year or once a quarter it should start by checking 
    ## the current date before running any time-consuming calculations (see the Tax functions).
    ## </summary>
    def OnTax(self):
        # Check whether the date should be skipped.
        if DateTimeMonth(DateTimeCurrent()) != self._taxMonth or DateTimeDay(DateTimeCurrent()) != self._taxDay:
            return
        
        # Get the current tax year. 
        taxYear = DateTimeYear(DateTimeCurrent()) - 1
        # Iterate over all of the strategies.
        for i in range(StrategyCount()):
            # Check whether the strategy isn't active.
            if not StrategyIsActive(i):
                continue
            
            # The tax cost for the new strategy.
            taxCost = 0
            # Get the closed trades indexes for the current strategy. 
            closedTrades = PositionByStatus(i, C_PositionStatus.CLOSED, None)
            # Iterate over all of the closed trade indexes. 
            for j in range(len(closedTrades)):
                # Get the year in which the current trade was closed. 
                tradeExitYear = DateTimeYear(PositionExitDateTime(i, closedTrades[j]))
                # Check whether the trade year equals to the current tax year.
                if taxYear == tradeExitYear:
                    # Get the exchange rate from the symbol currency code to the strategy currency code.
                    exchangeRate = StrategyGetExchangeRate(PositionCurrencyCode(i, closedTrades[j]), StrategyCurrencyCode(i))
                    # Get the trade profit/loss. 
                    PL = exchangeRate * PositionProfitLoss(i, closedTrades[j])
                    # Get the trade symbol index. 
                    symbolIndex = PositionSymbolIndex(i, closedTrades[j])
                    # Check whether the trade is for a stock symbol.
                    if SymbolInstrument(i, symbolIndex) == C_Instrument.STOCK or SymbolInstrument(i, symbolIndex) == C_Instrument.ETF or SymbolInstrument(i, symbolIndex) == C_Instrument.INDEX:
                        # Check whether the trade was a long term trade. (More than a year).
                        if PositionDays(i, closedTrades[j]) > 365:
                            taxCost = taxCost + PL * (self._longTermCapitalGainsTax / 100)
            # Check whether there were taxes to be paid.
            if taxCost > 0:
                # Pay the taxes.
                TaxPay(i, taxCost, "Taxes paid for the tax year of " + str(taxYear))
    #endregion

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