United States Tax System

#region Namespaces
using System;
using System.IO;
using System.Linq;
#endregion

namespace ScriptCode
{
    /// <summary>
    /// Tax system scripts are used for calculating and reducing the capital gain taxes created by the strategies.
    /// </summary>
    public partial class MyTaxSystem : TaxSystemScriptBase // NEVER CHANGE THE CLASS NAME 
    {
        #region Variables
        // The short term (under 12 months) capital gain tax on equity profits. 
		private double _shortTermCapitalGainsTax;
		// The long term (over 12 months) capital gains tax on equity profits.
		private double _longTermCapitalGainsTax;
		// Use for futures capital gains tax. 
		private double _futuresCapitalGainsTax;
		// Use for FOREX capital gains tax.
		private double _FOREXCapitalGainsTax;
		// The tax month.
		private int _taxMonth;
		// The tax day.
		private int _taxDay;
        #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>
        /// --------------------------------------------------------------------------------------------------
        /// PLEASE USE THE SCRIPT WIZARD (CTRL+W) TO ADD, EDIT AND REMOVE THE SCRIPT PARAMETERS
        /// --------------------------------------------------------------------------------------------------
        /// 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'  
        /// Set to "DateTimeArray" when the data type is 'long[]'  
        /// 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="shortTermCapitalGainsTax" type="Double" default="35">The short term (under 12 months) capital gain tax on stock profits.</param>		
		/// <param name="longTermCapitalGainsTax" type="Double" default="15">The long term (over 12 months) capital gains tax on stock profits.</param>		
		/// <param name="futuresCapitalGainsTax" type="Double" default="23">Use for futures capital gains tax.</param>		
		/// <param name="FOREXCapitalGainsTax" type="Double" default="23">Use for FOREX capital gains tax.</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>     
		public void OnInitialize(
			double shortTermCapitalGainsTax,
			double longTermCapitalGainsTax,
			double futuresCapitalGainsTax,
			double FOREXCapitalGainsTax,
			int taxMonth,
			int taxDay)
        {
            // Set the script time zone to the local time zone. 
			DateTimeSetLocalZone();
			// Set the parameters to script variables. 
			_shortTermCapitalGainsTax = shortTermCapitalGainsTax;
			_longTermCapitalGainsTax = longTermCapitalGainsTax;
			_futuresCapitalGainsTax = futuresCapitalGainsTax;
			_FOREXCapitalGainsTax = FOREXCapitalGainsTax;
			_taxMonth = taxMonth;
			_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 strategies 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>
        public override void OnTax()
        {
		    // Check whether the date should be skipped.
			if (DateTimeMonth(DateTimeCurrent()) != _taxMonth || DateTimeDay(DateTimeCurrent()) != _taxDay)
				return ;

			// Use for holding the closed trades indexes. 
			int[] closedTrades = null;
			// The current trade symbol index. 
			int symbolIndex = 0;
			// The current year tax amount. 
			double taxCost = 0;
			// The current trade P/L. 
			double PL = 0;
			// Get the current tax year. 
			int taxYear = DateTimeYear(DateTimeCurrent()) - 1;
			// Iterate over all of the strategies.
			for (int i = 0; i < StrategyCount(); i++) {
				// Check whether the strategy isn't active.
				if (!StrategyIsActive(i))
					continue ;
				
				// Reset the tax cost for the new strategy.
				taxCost = 0;
				// Get the closed trades indexes for the current strategy. 
				closedTrades = PositionByStatus(i, C_PositionStatus.CLOSED);
				// Iterate over all of the closed trade indexes. 
				for (int j = 0; j < closedTrades.Length; j++) {
					// Get the year in which the current trade was closed. 
					int 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.
						double 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 ||
							SymbolInstrument(i, symbolIndex) == C_Instrument.ETF ||
							SymbolInstrument(i, symbolIndex) == C_Instrument.INDEX) {
							// Check whether the trade was a short term trade. (Less than a year).
							if (PositionDays(i, closedTrades[j]) < 365)
								taxCost = taxCost + PL * (_shortTermCapitalGainsTax / 100);
							else
								taxCost = taxCost + PL * (_longTermCapitalGainsTax / 100);
						}
						// Check whether the trade is for a futures/CFD symbol.
						else if (SymbolInstrument(i, symbolIndex) == C_Instrument.FUTURE ||
								 SymbolInstrument(i, symbolIndex) == C_Instrument.CFD)
							taxCost = taxCost + PL * (_futuresCapitalGainsTax / 100);
						// Check whether the trade is for a FOREX symbol.
						else if (SymbolInstrument(i, symbolIndex) == C_Instrument.FOREX)
							taxCost = taxCost + PL * (_FOREXCapitalGainsTax / 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 " + taxYear);
				}
				else {
					// Don't pay taxes.
					TaxPay(i, 0, "Zero capital gains for the tax year of " + taxYear);
				}
			}
        }
        #endregion

        #region OnShutdown
        /// <summary>
        /// This function is called when the script is shutdown.
        /// </summary>
        public override void OnShutdown()
        {
            
        }
        #endregion
    }
}