207 lines
9.1 KiB
C#
207 lines
9.1 KiB
C#
using YLErp.DBModels.Enums;
|
|
|
|
namespace YLErp.Modules.CalculationModule
|
|
{
|
|
/// <summary>
|
|
/// 场内交易手续费计算帮助类
|
|
/// </summary>
|
|
public static class CommissionCalcHelper
|
|
{
|
|
/// <summary>
|
|
/// 计算某交易日某合约商品期货交易的手续费,
|
|
/// 因为手续费计算涉及到是否为平当日开仓,因此需要将当日的交易合并计算才准确
|
|
/// </summary>
|
|
public static Dictionary<int, double> GetCommissionForTrade(underlying_manager underlying, IEnumerable<ExchangeTrade> trades)
|
|
{
|
|
var CommissionDict = new Dictionary<int, double>();
|
|
if (underlying == null)
|
|
{
|
|
return CommissionDict;
|
|
}
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(underlying.UnderlyingTypeId);
|
|
return GetCommissionForFutureTrades(variety, trades);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算某交易日某合约商品期货交易的手续费,
|
|
/// 因为手续费计算涉及到是否为平当日开仓,因此需要将当日的交易合并计算才准确
|
|
/// </summary>
|
|
public static Dictionary<int, double> GetCommissionForFutureTrades(Variety variety, IEnumerable<ExchangeTrade> trades)
|
|
{
|
|
var CommissionDict = new Dictionary<int, double>();
|
|
|
|
if (variety == null)
|
|
{
|
|
return CommissionDict;
|
|
}
|
|
|
|
var todayOpenVolume = trades.Where(x => x.CommissionType == CommissionType.系统计算 && x.TradeSide.IndexOf("开仓") > 0).Sum(y => y.Notional);
|
|
|
|
foreach (var trade in trades)
|
|
{
|
|
if (trade.CommissionType == CommissionType.不收取)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
if (trade.CommissionType == CommissionType.手动录入)
|
|
{
|
|
CommissionDict[trade.id] = trade.Commission;
|
|
continue;
|
|
}
|
|
|
|
//老数据还是自动去算。
|
|
if (trade.TradeSide.IndexOf("开仓") > 0)
|
|
{
|
|
CommissionDict[trade.id] = GetRegularCommissionForFutureTrade(variety, trade.UnderlyingCode, trade.Notional, trade.TradeSinglePrice);
|
|
}
|
|
else
|
|
{
|
|
if (trade.Notional <= todayOpenVolume)
|
|
{
|
|
CommissionDict[trade.id] = GetCloseTodayCommissionForFutrueTrade(variety, trade.UnderlyingCode, trade.Notional, trade.TradeSinglePrice);
|
|
todayOpenVolume -= trade.Notional;
|
|
}
|
|
else
|
|
{
|
|
CommissionDict[trade.id] = GetCloseTodayCommissionForFutrueTrade(variety, trade.UnderlyingCode, todayOpenVolume, trade.TradeSinglePrice)
|
|
+ GetRegularCommissionForFutureTrade(variety, trade.UnderlyingCode, trade.Notional - todayOpenVolume, trade.TradeSinglePrice);
|
|
}
|
|
}
|
|
}
|
|
|
|
return CommissionDict;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算通常的商品期货交易手续费
|
|
/// </summary>
|
|
private static double GetRegularCommissionForFutureTrade(Variety variety, string underlyingCode, double notional, double price)
|
|
{
|
|
//如果有平今仓手续费合约规则
|
|
if (!string.IsNullOrWhiteSpace(variety.CloseTodayContractRule))
|
|
{
|
|
var contractMonthList = variety.CloseTodayContractRule.Split(new char[] { ',' }).Select(x => Int32.Parse(x));
|
|
if (contractMonthList.Contains(int.Parse(underlyingCode.Substring(underlyingCode.Length - 2))))
|
|
{
|
|
return variety.CloseTodayCommissionType == ConsCommissionType.Ratio
|
|
? (variety.CloseTodayCommission ?? 0.0) * notional * price
|
|
: (variety.CloseTodayCommission ?? 0.0) * (int)(notional / variety.TradeUnitValue ?? 1.0);
|
|
}
|
|
else
|
|
{
|
|
return variety.CommissionType == ConsCommissionType.Ratio
|
|
? (variety.Commission ?? 0.0) * notional * price
|
|
: (variety.Commission ?? 0.0) * (int)(notional / variety.TradeUnitValue ?? 1.0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return variety.CommissionType == ConsCommissionType.Ratio
|
|
? (variety.Commission ?? 0.0) * notional * price
|
|
: (variety.Commission ?? 0.0) * (int)(notional / variety.TradeUnitValue ?? 1.0);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算场内期权交易的手续费,
|
|
/// </summary>
|
|
public static Dictionary<int, double> GetCommissionForOptionTrade(IEnumerable<ExchangeTrade> trades)
|
|
{
|
|
var CommissionDict = new Dictionary<int, double>();
|
|
|
|
var umProvider = DataCacheProvider.GetUnderlyingDataSource();
|
|
|
|
foreach (var trade in trades)
|
|
{
|
|
if (trade.CommissionType == CommissionType.不收取)
|
|
{
|
|
CommissionDict[trade.id] = 0;
|
|
continue;
|
|
}
|
|
|
|
if (trade.CommissionType == CommissionType.手动录入)
|
|
{
|
|
CommissionDict[trade.id] = trade.Commission;
|
|
continue;
|
|
}
|
|
|
|
var um = umProvider.GetData(trade.UnderlyingId);
|
|
if (um == null)
|
|
{
|
|
continue;
|
|
}
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(um.UnderlyingTypeId);
|
|
if (variety == null)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
CommissionDict[trade.id] = GetRegularCommissionForOptionTrade(variety, trade.Notional, trade.TradeSinglePrice);
|
|
}
|
|
return CommissionDict;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算通常的场内期权交易手续费
|
|
/// </summary>
|
|
public static double GetRegularCommissionForOptionTrade(Variety variety, double notional, double price)
|
|
{
|
|
return variety.TradedOptionCommissionType == ConsCommissionType.Ratio
|
|
? (variety.TradedOptionCommission ?? 0.0) * notional * price
|
|
: (variety.TradedOptionCommission ?? 0.0) * (int)(notional / variety.TradeUnitValue ?? 1.0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算通常的场内期权交易手续费
|
|
/// </summary>
|
|
public static double GetRegularCommissionForOptionTrade(Variety variety, double notional, double price,double contractSize)
|
|
{
|
|
if (contractSize == 0)
|
|
{
|
|
contractSize = variety.TradeUnitValue ?? 1.0;
|
|
}
|
|
return variety.TradedOptionCommissionType == ConsCommissionType.Ratio
|
|
? (variety.TradedOptionCommission ?? 0.0) * notional * price
|
|
: (variety.TradedOptionCommission ?? 0.0) * (notional / contractSize);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 计算平今仓的商品期货期权手续费
|
|
/// </summary>
|
|
private static double GetCloseTodayCommissionForFutrueTrade(Variety variety, string underlyingCode, double notional, double price)
|
|
{
|
|
//平今仓手续费类型缺失,或者为“正常”,则按正常手续费计算
|
|
if (string.IsNullOrWhiteSpace(variety.CloseTodayCommissionType)
|
|
|| variety.CloseTodayCommissionType == ConsCommissionType.Regular)
|
|
{
|
|
return GetRegularCommissionForFutureTrade(variety, underlyingCode, notional, price);
|
|
}
|
|
else
|
|
{
|
|
//如果有平今仓手续费合约规则
|
|
if (!string.IsNullOrWhiteSpace(variety.CloseTodayContractRule))
|
|
{
|
|
var contractMonthList = variety.CloseTodayContractRule.Split(new char[] { ',' }).Select(x => Int32.Parse(x));
|
|
if (contractMonthList.Contains(Int32.Parse(underlyingCode.Substring(underlyingCode.Length - 2))))
|
|
{
|
|
return variety.CloseTodayCommissionType == ConsCommissionType.Ratio
|
|
? (variety.CloseTodayCommission ?? 0.0) * notional * price
|
|
: (variety.CloseTodayCommission ?? 0.0) * (int)(notional / variety.TradeUnitValue ?? 1.0);
|
|
}
|
|
else
|
|
{
|
|
return GetRegularCommissionForFutureTrade(variety, underlyingCode, notional, price);
|
|
}
|
|
}
|
|
else //没有平今仓手续费合约规则,则统一按平今仓手续费类型计算
|
|
{
|
|
return variety.CloseTodayCommissionType == ConsCommissionType.Ratio
|
|
? (variety.CloseTodayCommission ?? 0.0) * notional * price
|
|
: (variety.CloseTodayCommission ?? 0.0) * (int)(notional / variety.TradeUnitValue ?? 1.0);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|