/* * QUANTCONNECT.COM - Democratizing Finance, Empowering Individuals. * Lean Algorithmic Trading Engine v2.0. Copyright 2014 QuantConnect Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */ using QuantConnect.Securities; namespace QuantConnect.Orders.Fees { /// /// Represents a fee model specific to Public.com. /// /// /// /// Equity trades are free during regular market hours and $2.99 per trade during extended hours. /// Options on stocks and ETFs are free; index options cost $0.50 per contract. /// Crypto trades carry a fee that depends on the order amount in USD. /// The model uses the regular member tier and does not detect OTC stocks. /// public class PublicFeeModel : FeeModel { /// /// Flat per-trade fee for US-listed equity trades placed during extended market hours. /// private const decimal _extendedHoursEquityFee = 2.99m; /// /// Per-contract fee for index options (regular member tier). /// private const decimal _indexOptionContractFee = 0.50m; /// /// Crypto fee charged on orders above the flat-tier range: 1.25% of the order amount. /// private const decimal _cryptoPercentFee = 0.0125m; /// /// Gets the order fee for a given security and order. /// /// The parameters including the security and order details. /// A in USD for the order. public override OrderFee GetOrderFee(OrderFeeParameters parameters) { var order = parameters.Order; var security = parameters.Security; decimal fee; switch (security.Type) { case SecurityType.Equity: fee = GetEquityFee(security, order); break; case SecurityType.IndexOption: fee = order.AbsoluteQuantity * _indexOptionContractFee; break; case SecurityType.Crypto: fee = GetCryptoFee(security, order); break; default: // Options on stocks and ETFs are commission-free on Public.com. return OrderFee.Zero; } return new OrderFee(new CashAmount(fee, Currencies.USD)); } /// /// Returns the equity fee: free during regular market hours, a flat fee during extended hours. /// /// The traded security. /// The order, whose time decides whether the trade is during regular hours. /// The equity fee in USD. private static decimal GetEquityFee(Security security, Order order) { var localOrderTime = order.Time.ConvertFromUtc(security.Exchange.TimeZone); var isRegularHours = security.Exchange.Hours.IsOpen(localOrderTime, extendedMarketHours: false); return isRegularHours ? 0m : _extendedHoursEquityFee; } /// /// Returns the crypto fee for the order, tiered by the order amount in USD. /// /// The traded security. /// The order being placed. /// The crypto fee in USD. private static decimal GetCryptoFee(Security security, Order order) { var orderAmount = security.Price * security.SymbolProperties.ContractMultiplier * order.AbsoluteQuantity; if (orderAmount <= 10m) { return 0.49m; } if (orderAmount <= 25m) { return 0.69m; } if (orderAmount <= 50m) { return 1.19m; } if (orderAmount <= 100m) { return 1.69m; } if (orderAmount <= 250m) { return 3.29m; } if (orderAmount <= 500m) { return 6.29m; } return orderAmount * _cryptoPercentFee; } } }