Skip to content

Commit

Permalink
revert redundnacies, fix bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
LouisSzeto committed Dec 8, 2024
1 parent e66ab8e commit 84e4be8
Show file tree
Hide file tree
Showing 5 changed files with 441 additions and 440 deletions.
28 changes: 5 additions & 23 deletions Common/Orders/Fees/InteractiveBrokersFeeHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,6 @@ namespace QuantConnect.Orders.Fees
/// </summary>
internal static class InteractiveBrokersFeeHelper
{
// List of Option exchanges susceptible to pay ORF regulatory fee.
private static readonly List<string> _optionExchangesOrfFee = new() { Market.CBOE, Market.USA };

/// <summary>
/// Determines which tier an account falls into based on the monthly trading volume of Equities (in shares)
/// </summary>
Expand Down Expand Up @@ -195,16 +192,8 @@ internal static decimal CalculateOptionFee(Security security, Order order, decim
// applying commission function to the order
var orderPrice = GetPotentialOrderPrice(order, security);
var optionFee = optionsCommissionFunc(quantity, orderPrice);
// Regulatory Fee: Options Regulatory Fee (ORF) + FINRA Consolidated Audit Trail Fees
var regulatory = _optionExchangesOrfFee.Contains(market) ?
(0.01915m + 0.0048m) * quantity :
0.0048m * quantity;
// Transaction Fees: SEC Transaction Fee + FINRA Trading Activity Fee (only charge on sell)
var transaction = order.Quantity < 0 ? 0.0000278m * Math.Abs(order.GetValue(security)) + 0.00279m * quantity : 0m;
// Clearing Fee
var clearing = Math.Min(0.02m * quantity, 55m);

fee = optionFee.Amount + regulatory + transaction + clearing;

fee = optionFee.Amount;
currency = optionFee.Currency;

return orderPrice * quantity;
Expand Down Expand Up @@ -247,7 +236,7 @@ internal static decimal CalculateEquityFee(Security security, Order order, decim
switch (market)
{
case Market.USA:
equityFee = new EquityFee(Currencies.USD, feePerShare: usFeeRate, minimumFee: usMinimumFee, maximumFeeRate: 0.005m);
equityFee = new EquityFee(Currencies.USD, feePerShare: usFeeRate, minimumFee: usMinimumFee, maximumFeeRate: 0.01m);
break;
case Market.India:
equityFee = new EquityFee(Currencies.INR, feePerShare: 0.01m, minimumFee: 6, maximumFeeRate: 20);
Expand All @@ -271,16 +260,9 @@ internal static decimal CalculateEquityFee(Security security, Order order, decim
tradeFee = maximumPerOrder;
}

// FINRA Trading Activity Fee only applies to sale of security.
var finraTradingActivityFee = order.Quantity < 0 ? Math.Min(8.3m, quantity * 0.000166m) : 0m;
// Regulatory Fees.
var regulatoryFee = tradeValue * 0.0000278m // SEC Transaction Fee
+ finraTradingActivityFee // FINRA Trading Activity Fee
+ quantity * 0.000048m; // FINRA Consolidated Audit Trail Fees

currency = equityFee.Currency;
//Always return a positive fee.
fee = Math.Abs(tradeFee + regulatoryFee);
fee = Math.Abs(tradeFee);

return tradeFee;
}
Expand Down Expand Up @@ -606,4 +588,4 @@ public EquityFee(string currency,
}
}
}
}
}
4 changes: 2 additions & 2 deletions Common/Orders/Fees/InteractiveBrokersFeeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -164,8 +164,8 @@ private static CashAmount UnitedStatesFutureFees(Security security)
exchangeFeePerContract = 1.60m;
}

// Add exchange fees
return new CashAmount(ibFeePerContract + exchangeFeePerContract, Currencies.USD);
// Add exchange fees + IBKR regulatory fee (0.02)
return new CashAmount(ibFeePerContract + exchangeFeePerContract + 0.02m, Currencies.USD);
}

/// <summary>
Expand Down
25 changes: 22 additions & 3 deletions Common/Orders/Fees/InteractiveBrokersTieredFeeModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ public class InteractiveBrokersTieredFeeModel : FeeModel
new Dictionary<string, Func<decimal, decimal, CashAmount>>();
private Dictionary<SecurityType, decimal> _monthlyTradeVolume;
private DateTime _lastOrderTime = DateTime.MinValue;
// List of Option exchanges susceptible to pay ORF regulatory fee.
private static readonly List<string> _optionExchangesOrfFee = new() { Market.CBOE, Market.USA };

/// <summary>
/// Initializes a new instance of the <see cref="InteractiveBrokersTieredFeeModel"/>
Expand Down Expand Up @@ -143,6 +145,17 @@ public override OrderFee GetOrderFee(OrderFeeParameters parameters)
case SecurityType.Option:
case SecurityType.IndexOption:
var orderPrice = InteractiveBrokersFeeHelper.CalculateOptionFee(security, order, quantity, market, _optionFee, out feeResult, out feeCurrency);
// Regulatory Fee: Options Regulatory Fee (ORF) + FINRA Consolidated Audit Trail Fees
var regulatory = _optionExchangesOrfFee.Contains(market) ?
(0.01915m + 0.0048m) * quantity :
0.0048m * quantity;
// Transaction Fees: SEC Transaction Fee + FINRA Trading Activity Fee (only charge on sell)
var transaction = order.Quantity < 0 ? 0.0000278m * Math.Abs(order.GetValue(security)) + 0.00279m * quantity : 0m;
// Clearing Fee
var clearing = Math.Min(0.02m * quantity, 55m);

feeResult += regulatory + transaction + clearing;

// Update the monthly value traded
_monthlyTradeVolume[SecurityType.Option] += quantity * orderPrice;
break;
Expand All @@ -159,14 +172,20 @@ public override OrderFee GetOrderFee(OrderFeeParameters parameters)
var tradeFee = InteractiveBrokersFeeHelper.CalculateEquityFee(security, order, quantity, tradeValue, market, _equityCommissionRate, EquityMinimumOrderFee, out feeResult, out feeCurrency);

// Tiered fee model has the below extra cost.
// FINRA Trading Activity Fee only applies to sale of security.
var finraTradingActivityFee = order.Direction == OrderDirection.Sell ? Math.Min(8.3m, quantity * 0.000166m) : 0m;
// Regulatory Fees.
var regulatoryFee = tradeValue * 0.0000278m // SEC Transaction Fee
+ finraTradingActivityFee // FINRA Trading Activity Fee
+ quantity * 0.000048m; // FINRA Consolidated Audit Trail Fees
// Clearing Fee: NSCC, DTC Fees.
var clearingFee = Math.Min(quantity * 0.0002m, tradeValue * 0.005m);
// Exchange related handling fees.
var exchangeFee = InteractiveBrokersFeeHelper.GetEquityExchangeFee(order, (security as Equity).PrimaryExchange, tradeValue, tradeFee);
// FINRA Pass Through Fees.
var passThroughFee = Math.Min(8.3m, tradeFee * 0.00056m);

feeResult = feeResult + clearingFee + exchangeFee + passThroughFee;
feeResult = feeResult + regulatoryFee + clearingFee + exchangeFee + passThroughFee;

// Update the monthly volume shares traded
_monthlyTradeVolume[SecurityType.Equity] += quantity;
Expand Down Expand Up @@ -227,8 +246,8 @@ private CashAmount UnitedStatesFutureFees(Security security)
exchangeFeePerContract = 1.60m;
}

// Add exchange fees
return new CashAmount(ibFeePerContract[_futureCommissionTier] + exchangeFeePerContract, Currencies.USD);
// Add exchange fees + IBKR regulatory fee (0.02)
return new CashAmount(ibFeePerContract[_futureCommissionTier] + exchangeFeePerContract + 0.02m, Currencies.USD);
}

/// <summary>
Expand Down
Loading

0 comments on commit 84e4be8

Please sign in to comment.