Files
zszq-trs/YLErpDAL/Modules/CalculationModule/CommissionCalcHelper.cs
2024-05-09 14:06:26 +08:00

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);
}
}
}
}
}