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

153 lines
5.8 KiB
C#

using YLErp.DBModels.Enums;
using YLErp.Modules.CalculationModule.Abstract;
namespace YLErp.Modules.CalculationModule
{
/// <summary>
/// 交易佣金计算
/// </summary>
public class ExchangeTradeCommissionCalc : IExchangeTradeCommissionCalc
{
/// <summary>
/// 计算交易手续费
/// </summary>
public ITradeCommissionCalcResult GetTradeCommission(IEnumerable<ExchangeTrade> tradeList, bool actualTrade = true)
{
if (tradeList == null || !tradeList.Any())
{
return TradeCommissionResult.Empty;
}
var dic = new Dictionary<int, double>();
//当日成交的对冲交易计算
var futureTradeDict = tradeList.Where(t => t.TradeType == "商品期货").ToLookup(t => t.UnderlyingId);
foreach (var item in futureTradeDict)
{
var trads = item.ToList();
var underlying = GetUnderlying(item.Key);
if (underlying == null) { continue; }
var vareity = GetVariety(underlying.UnderlyingTypeId);
var commissionDict = CommissionCalcHelper.GetCommissionForFutureTrades(vareity, trads);
if (commissionDict != null && commissionDict.Count > 0)
{
foreach (var tempItem in commissionDict)
{
dic[tempItem.Key] = tempItem.Value;
}
}
}
var insiteTradeList = tradeList.Where(t => t.TradeType == "场内期权").ToList();
Dictionary<string, double> insiteTradeContractSizeDic = null;
if (insiteTradeList != null&& insiteTradeList.Count>0)
{
insiteTradeContractSizeDic = GetInsiteTradeContractSize(insiteTradeList.Select(p => p.OptionCode).Distinct().ToList());
}
if (insiteTradeContractSizeDic == null)
{
insiteTradeContractSizeDic = new Dictionary<string, double>();
}
foreach (var td in tradeList)
{
if (td.TradeType == "商品期货")
{
continue;
}
if (td.CommissionType == CommissionType.手动录入)
{
dic[td.id] = td.Commission;
continue;
}
if (td.TradeType == "场内期权") //当日成交的场内期权交易计算手续费
{
var underlying = GetUnderlying(td.UnderlyingId);
if (underlying == null)
{
continue;
}
var variety = GetVariety(underlying.UnderlyingTypeId);
if (variety == null)
{
continue;
}
dic[td.id] = CommissionCalcHelper.GetRegularCommissionForOptionTrade(variety, td.Notional, td.TradeSinglePrice, insiteTradeContractSizeDic.ContainsKey(td.OptionCode) ? insiteTradeContractSizeDic[td.OptionCode] : 0);
}
else if (td.TradeType == "股票") //股票交易交易费计算
{
var stockCommissionConfig = GetStock_Commission_Config(td.ExchangeAccountId);
if (stockCommissionConfig != null && stockCommissionConfig.Enabled == 1)
{
dic[td.id] = StockTradeCalcHelper.GetStockAllTradeExpenses(td, stockCommissionConfig, actualTrade);
}
}
}
return new TradeCommissionResult(dic);
}
/// <summary>
/// 获取场内期权合约乘数
/// </summary>
/// <param name="contractCodes"></param>
/// <returns></returns>
private Dictionary<string, double> GetInsiteTradeContractSize(List<string> contractCodes)
{
using (var db = DbContextFactory.GetYLDbContext())
{
return db.exchange_list_option.AsNoTracking().Where(p => contractCodes.Contains(p.ContractCode)).ToDictionary(p => p.ContractCode, p => p.ContractSize);
}
}
protected virtual StockCommissionConfig GetStock_Commission_Config(int exchangeAccountId)
{
// 同步簿记账户 对应 多个 对冲账户的情况下,可能出现异常问题,取不到正确的值,需产品重新规划
var account = DataCacheProvider.GetExchangeAccountDataSource().AsQueryable().FirstOrDefault(n => n.id == exchangeAccountId);
return account == null ? null : DataCacheProvider.GetStockCommissionDataSource().AsQueryable().FirstOrDefault(n => n.ExchangeAccountCode == account.AccountCode);
}
protected virtual underlying_manager GetUnderlying(int underlyingId)
{
return DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingId);
}
protected virtual Variety GetVariety(int varietyId)
{
return DataCacheProvider.GetVarietyDataSource().GetData(varietyId);
}
class TradeCommissionResult : ITradeCommissionCalcResult
{
readonly Dictionary<int, double> _dic;
public TradeCommissionResult(Dictionary<int, double> dic)
{
_dic = dic;
}
public double GetTradeCommission(int tradeId)
{
if (_dic != null && _dic.TryGetValue(tradeId, out double dd))
{
return dd;
}
return 0;
}
public static readonly TradeCommissionResult Empty;
static TradeCommissionResult()
{
Empty = new TradeCommissionResult(null);
}
}
}
}