#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
}
}