/*
* 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 System;
using QuantConnect.Securities;
namespace QuantConnect.Orders.Fees
{
///
/// Provides an implementation of that models Exante order fees.
/// According to:
///
/// - https://support.exante.eu/hc/en-us/articles/115005873143-Fees-overview-exchange-imposed-fees?source=search
/// - https://exante.eu/markets/
///
///
public class ExanteFeeModel : FeeModel
{
///
/// Market USA rate
///
public const decimal MarketUsaRate = 0.02m;
///
/// Default rate
///
public const decimal DefaultRate = 0.02m;
private readonly decimal _forexCommissionRate;
///
/// Creates a new instance
///
/// Commission rate for FX operations
public ExanteFeeModel(decimal forexCommissionRate = 0.25m)
{
_forexCommissionRate = forexCommissionRate;
}
///
/// Gets the order fee associated with the specified order.
///
/// A object
/// containing the security and order
/// The cost of the order in a instance
public override OrderFee GetOrderFee(OrderFeeParameters parameters)
{
var order = parameters.Order;
var security = parameters.Security;
decimal feeResult;
string feeCurrency;
switch (security.Type)
{
case SecurityType.Forex:
var totalOrderValue = order.GetValue(security);
feeResult = Math.Abs(_forexCommissionRate * totalOrderValue);
feeCurrency = Currencies.USD;
break;
case SecurityType.Equity:
var equityFee = ComputeEquityFee(order);
feeResult = equityFee.Amount;
feeCurrency = equityFee.Currency;
break;
case SecurityType.Option:
case SecurityType.IndexOption:
var optionsFee = ComputeOptionFee(order);
feeResult = optionsFee.Amount;
feeCurrency = optionsFee.Currency;
break;
case SecurityType.Future:
case SecurityType.FutureOption:
feeResult = 1.5m;
feeCurrency = Currencies.USD;
break;
default:
throw new ArgumentException(Messages.FeeModel.UnsupportedSecurityType(security));
}
return new OrderFee(new CashAmount(feeResult, feeCurrency));
}
///
/// Computes fee for equity order
///
/// LEAN order
private static CashAmount ComputeEquityFee(Order order)
{
switch (order.Symbol.ID.Market)
{
case Market.USA:
return new CashAmount(order.AbsoluteQuantity * MarketUsaRate, Currencies.USD);
default:
return new CashAmount(order.AbsoluteQuantity * order.Price * DefaultRate, Currencies.USD);
}
}
///
/// Computes fee for option order
///
/// LEAN order
private static CashAmount ComputeOptionFee(Order order)
{
return order.Symbol.ID.Market switch
{
Market.USA => new CashAmount(order.AbsoluteQuantity * 1.5m, Currencies.USD),
_ =>
// ToDo: clarify the value for different exchanges
throw new ArgumentException(Messages.ExanteFeeModel.UnsupportedExchange(order))
};
}
}
}