using BaseOUDAL; using Qdp.Foundation.Implementations; using System.Data; using System.Linq.Expressions; using YLErp.BLL; using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.Model; using YLErp.Model.Enum; using YLErp.Models; using YLErp.Modules.DataCacheModule; using YLErp.Modules.DataProviderModule; using YLErp.Modules.EodModule; using YLErp.Modules.TradeModule.DealModule; using YLErp.Modules.TradeModule.QueryModule; using YLErp.Modules.TradeModule.QueryModule.Dto; using YLErp.Modules.TradeRiskCalcModule; using YLErp.QdpModule; namespace YLErp.Modules.TradeModule { /// /// 当日交易(当日成交、提前终止、当日到期、明日到期)查询服务 /// public class TodayTradeQueryService : YLBaseService { public TodayTradeQueryService(OptUserInfo userInfo) : base(userInfo) { } public TdTradesCountSum GetTdTradesCountSum(List userAssets, List userClients, OtcTradeType otcTradeType) { var sum = new TdTradesCountSum(); var curTradingDate = SystemValueDate; var basePredicate = PredicateBuilder.Create(t => t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2); switch (otcTradeType) { case OtcTradeType.Forward: basePredicate = basePredicate.And(t => t.TradeType == "远期"); break; case OtcTradeType.EquitySwap: basePredicate = basePredicate.And(t => t.TradeType == "收益互换"); break; default: basePredicate = basePredicate.And(t => t.TradeType != "远期" && t.TradeType != "收益互换" && t.ClientId > 0); break; } var dateEnd = curTradingDate.AddDays(1); //--------------------------------------------- // 当日到期 //--------------------------------------------- //如果前一天是假日,要显示包含假日的交易 var req = new TdTradeQueryModel { OtcTradeType = otcTradeType, TabIndex = (int)TradeTabIndexEnum.今日到期, UserAssets = userAssets, UserClients = userClients }; var predicate = BuildPredicate(req, curTradingDate); sum.TdExerciseCount = DbContext.trade.Where(predicate).Count(); //--------------------------------------------- // 明日到期 //--------------------------------------------- var nextDay = QdpCalendarHelper.GetNonHoliday(curTradingDate.AddDays(1)); var excludeStatusArr = new[] { ConsTrade.已平仓, ConsTrade.已到期, ConsTrade.已执行 }; predicate = PredicateBuilder.Create(t => t.ExerciseDate == nextDay && !excludeStatusArr.Contains(t.TradeStatus)).And(basePredicate); sum.TmExerciseCount = DbContext.trade.Where(predicate).Count(); //--------------------------------------------- // 当日提前终止 //--------------------------------------------- IQueryable baseTrade; //交易员对应的簿记账户筛选或者客户经理对应的客户筛选 if (userAssets != null || userClients != null) { baseTrade = DbContext.trade.Where(t => userAssets.Contains(t.AssetId) || userClients.Contains(t.ClientId)).AsQueryable(); } else { baseTrade = DbContext.trade.AsQueryable(); } if (otcTradeType == OtcTradeType.Forward) { baseTrade = baseTrade.Where(x => x.TradeType == "远期"); var query1 = from tc in DbContext.trade_cash join t in baseTrade on tc.TradeId equals t.id where tc.ValueDate == curTradingDate && tc.Action == ClientCashInCashOut.系统操作_平仓费 && (t.TradeStatus == "平仓待复核" || tc.ValidState != ConsGlobal.InValid) && !tc.IsDeleted && tc.BarrierPrice == null && t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2 select t.id; sum.TdEarlyStoppedCount = query1.Count(); } else if (otcTradeType == OtcTradeType.EquitySwap) { baseTrade = baseTrade.Where(x => x.TradeType == "收益互换"); var query1 = from tc in DbContext.trade_cash join t in baseTrade on tc.TradeId equals t.id where tc.ValueDate == curTradingDate && (tc.Action == ClientCashInCashOut.系统操作_平仓费 || tc.Action == ClientCashInCashOut.系统操作_互换) && (t.TradeStatus == "平仓待复核" || t.TradeStatus == "互换待复核" || tc.ValidState != "InValid") && !tc.IsDeleted && tc.BarrierPrice == null && t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2 select t.id; sum.TdEarlyStoppedCount = query1.Count(); } else { baseTrade = DbContext.trade.Where(x => x.TradeType != "远期" && x.TradeType != "收益互换"); var query1 = from tc in DbContext.trade_cash join t in baseTrade on tc.TradeId equals t.id where tc.ValueDate == curTradingDate && tc.Action == ClientCashInCashOut.系统操作_平仓费 && (t.TradeStatus == "平仓待复核" || tc.ValidState != "InValid") && !tc.IsDeleted && tc.BarrierPrice == null && t.ValidState != ConsGlobal.InValid && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2 select t.id; var query2 = from tc in DbContext.trade_cash join t in baseTrade on tc.TradeId equals t.id where tc.ValueDate == curTradingDate && tc.Action == ClientCashInCashOut.系统操作_行权费 && (t.TradeStatus == "行权待复核" || tc.ValidState != "InValid" && t.TradeStatus == ConsTrade.已执行) && t.ExerciseMode == "American" && tc.ExerciseWay != "到期行权" && !tc.IsDeleted && tc.BarrierPrice == null //不包含敲出数据 && t.ValidState != ConsGlobal.InValid && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2 select t.id; var dd1 = query1.Count(); var dd2 = query2.Count(); sum.TdEarlyStoppedCount = dd1 + dd2; } //--------------------------------------------- // 当日成交 //--------------------------------------------- predicate = PredicateBuilder.Create(t => t.TradeDate == curTradingDate).And(basePredicate); sum.TdCreatedCount = DbContext.trade.Where(predicate).Count(); //--------------------------------------------- // 当日敲出 //--------------------------------------------- //var knockedOutPredicate = PredicateBuilder.Create(t => t.KnockInOutDate < dateEnd && t.KnockInOutDate >= curTradingDate && t.KnockInOutStatus == trade_barrier_option.KnockedOut); //sum.TdKnockedOutCount = DbContext.trade_barrier_option.Where(knockedOutPredicate).Count(); var knockedOutQuery = from tc in DbContext.trade_cash join t in DbContext.trade on tc.TradeId equals t.id join ao in DbContext.autocall_observation on new { EndDate = tc.ValueDate, TradeId = t.id } equals new { ao.EndDate, ao.TradeId } into tempAo from ao in tempAo.DefaultIfEmpty() where tc.BarrierPrice != null //障碍期权敲出 && tc.HappenedDate >= curTradingDate && tc.HappenedDate < dateEnd && t.ValidState != "InValid" && t.TradeType != "结构化交易" && !tc.IsDeleted select 1; sum.TdKnockedOutCount = knockedOutQuery.Count(); return sum; } //替换TradeBLL.SearchListForTradeConfirm /// /// 获取当日成交/当日到期/明日到期数据列表 /// public SearchListResult GetConfirmList(TdTradeQueryModel req) { var valueDate = SystemValueDate; var predicate = BuildPredicate(req, valueDate); var tQuery = DbContext.trade.Where(predicate); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeNumber"; req.sord = "desc"; } var sList = tQuery.ToSearchList(req); if (sList.rows != null && sList.rows.Any()) { //var realtimerisk = realtime_trade_riskBLL.GetAllrealtime_trade_valueModel(); //var tradeIds = sList.rows.Select(x => x.id).ToList(); //var tradeCashQuery = from tc in DbContext.trade_cash // where tradeIds.Contains(tc.TradeId) && (tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_票息 || tc.Action == ClientCashInCashOut.系统操作_互换) && tc.ValidState != "InValid" // && !tc.IsDeleted && tc.Status == TradeCashStatusEnum.已执行 && tc.BarrierPrice == null //不包含敲出数据 // select tc; //var tradeCashDatas = tradeCashQuery.ToArray(); //未用到 //var underlyingIds = sList.rows.Select(x => x.UnderlyingId).ToList(); //var underlyings = DbContext.underlying_manager.Where(x => underlyingIds.Contains(x.id)).ToArray(); //var underlyingTypeIds = underlyings.Select(x => x.UnderlyingTypeId).Distinct(); //var varietys = DbContext.variety.Where(x => underlyingTypeIds.Contains(x.id)).ToArray(); var result = TradeRiskCalcTaskRunner.GetCalcResult("对冲"); //new TradeDalModule.TradeDalService(this).SetStructureInfo(sList.rows); var tradeIdList = sList.rows.Select(p => p.id).Distinct().ToList(); var realtimerisk = realtime_trade_riskBLL.GetByTradeIds(tradeIdList); if (realtimerisk == null) { realtimerisk = new List(); } List tradeCashList = null; var tradeCacheBatchGetService = new BatchGetTradeRelationDataService(); if (tradeIdList != null && tradeIdList.Count > 0) { //tradeCashList = DbContext.trade_cash.AsNoTracking().Where(t => tradeIdList.Contains(t.TradeId) && t.ValidState != "Invalid" && t.BarrierPrice == null && !t.IsDeleted).ToList(); tradeCashList = tradeCacheBatchGetService.GetListByWhere(t => tradeIdList.Contains(t.TradeId) && t.ValidState != "Invalid" && t.BarrierPrice == null && !t.IsDeleted, DbContext.trade_cash); } if (tradeCashList == null) { tradeCashList = new List(); } var tradeCashDatas = tradeCashList.Where(tc => (tc.Action == ClientCashInCashOut.系统操作_行权费 || tc.Action == ClientCashInCashOut.系统操作_票息 || tc.Action == ClientCashInCashOut.系统操作_互换) && tc.Status == TradeCashStatusEnum.已执行).ToList(); if (tradeCashDatas == null) { tradeCashDatas = new List(); } List childTradeCashList = null; var parentTradeIds = sList.rows.Where(p => p.IsGroup == 1).Select(p => p.id).Distinct().ToList(); List childTradeList = null; if (parentTradeIds != null && parentTradeIds.Count > 0) { childTradeList = DbContext.trade.AsNoTracking().Where(p => parentTradeIds.Contains(p.ParentTradeId) && p.ParentTradeId > 0).Select(p => new TradeQueryDto { id = p.id, TradePrice = p.TradePrice, BuySell = p.BuySell, ParentTradeId = p.ParentTradeId, ValidState = p.ValidState }).ToList(); if (childTradeList != null && childTradeList.Count > 0) { var childTradeIds = childTradeList.Select(p => p.id).Distinct().ToList(); //childTradeCashList= DbContext.trade_cash.AsNoTracking().Where(t => childTradeIds.Contains(t.TradeId)).ToList(); var parentTradeCashIdList = tradeCashList.Where(p => parentTradeIds.Contains(p.TradeId) && p.Action != ClientCashInCashOut.系统操作_期权费).Select(p => p.id).Distinct().ToList(); if (parentTradeCashIdList != null && parentTradeCashIdList.Count > 0) { //childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(t => parentTradeCashIdList.Contains(t.ParentTradeCashId)).ToList(); //childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(t => childTradeIds.Contains(t.TradeId) && parentTradeCashIdList.Contains(t.ParentTradeCashId)).ToList(); childTradeCashList = tradeCacheBatchGetService.GetListByWhere(t => childTradeIds.Contains(t.TradeId) && parentTradeCashIdList.Contains(t.ParentTradeCashId), DbContext.trade_cash); } } } if (childTradeCashList == null) { childTradeCashList = new List(); } if (childTradeList == null) { childTradeList = new List(); } var forwardTradeIds = sList.rows.Where(p => "远期".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList(); List tradeForwardList = null; if (forwardTradeIds != null && forwardTradeIds.Count > 0) { tradeForwardList = DbContext.trade_forward.AsNoTracking().Where(p => forwardTradeIds.Contains(p.TradeId)).ToList(); } if (tradeForwardList == null) { tradeForwardList = new List(); } var swapTradeIds = sList.rows.Where(p => "收益互换".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList(); List tradeCashSwapList = null; if (swapTradeIds != null && swapTradeIds.Count > 0) { var swapTradeCashIds = tradeCashList.Where(t => t.Action == ClientCashInCashOut.系统操作_互换).Select(d => d.id).Distinct().ToList(); if (swapTradeCashIds != null && swapTradeCashIds.Count > 0) { tradeCashSwapList = DbContext.trade_cash_swap.AsNoTracking().Where(p => swapTradeCashIds.Contains(p.TradeCashId)).ToList(); } } if (tradeCashSwapList == null) { tradeCashSwapList = new List(); } Dictionary keyValueSalesC = null; using (var saleCService = new SalesModule.SalesCommissionDataService(OptUser)) { keyValueSalesC = saleCService.GetTradeCommissionInfoByTradeIds(tradeIdList); } List syntheticUnderlyingList = null; var syntheticUnderlyingCodeList = sList.rows.Where(p => "合成价差期权".Equals(p.TradeType)).Select(p => p.UnderlyingCode).Distinct().ToList(); if (syntheticUnderlyingCodeList != null && syntheticUnderlyingCodeList.Count > 0) { syntheticUnderlyingList = DbContext.synthetic_underlying.AsNoTracking().Where(p => syntheticUnderlyingCodeList.Contains(p.Name)).ToList(); } if (syntheticUnderlyingList == null) { syntheticUnderlyingList = new List(); } foreach (var tradeObj in sList.rows) { var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(tradeObj.UnderlyingCode); if (tradeObj.TradeStatus == "已执行" || tradeObj.TradeStatus == "已到期" || tradeObj.TradeStatus == "已平仓") { tradeObj.TradeAmount = 0; } var tradeCash = tradeCashDatas.OrderByDescending(x => x.id).FirstOrDefault(d => d.TradeId == tradeObj.id); ProcessTrade(tradeObj, tradeCash, underlying, syntheticUnderlyings: syntheticUnderlyingList);//最后一笔到期结算流水 if (tradeObj.TradeType == "远期") { //tradeObj.trade_forward = DbContext.trade_forward.First(x => x.TradeId == tradeObj.id); tradeObj.trade_forward = tradeForwardList.First(x => x.TradeId == tradeObj.id); } //var cashTrades = DbContext.trade_cash.Where(t => t.ValidState != "Invalid" && t.TradeId == tradeObj.id && t.BarrierPrice == null && !t.IsDeleted).ToList(); var cashTrades = tradeCashList.Where(t => t.TradeId == tradeObj.id).ToList(); var cashTradesExercise = cashTrades.Where(t => t.Action == ClientCashInCashOut.系统操作_行权费).ToList(); var cashTradesUnwind = cashTrades.Where(t => t.Action == ClientCashInCashOut.系统操作_平仓费).ToList(); if (tradeObj.TradeType == "收益互换") { var cashTradesSwap = cashTrades.Where(t => t.Action == ClientCashInCashOut.系统操作_互换).ToList(); var lastTradeCashSwap = cashTradesSwap.OrderByDescending(x => x.ValueDate).FirstOrDefault(); if (lastTradeCashSwap != null) { //tradeObj.trade_cash.trade_cash_swap = DbContext.trade_cash_swap.FirstOrDefault(x => x.TradeCashId == lastTradeCashSwap.id); tradeObj.trade_cash.trade_cash_swap = tradeCashSwapList.FirstOrDefault(x => x.TradeCashId == lastTradeCashSwap.id); } tradeObj.RealizedPnl = cashTradesSwap.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesSwap.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1) + cashTradesUnwind.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesUnwind.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1); } else { tradeObj.RealizedPnl = cashTradesExercise.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesExercise.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1) + cashTradesUnwind.Sum(x => x.Amount) - tradeObj.TradePrice * cashTradesUnwind.Sum(x => x.UnwindPercentRate) * ((tradeObj.BuySell == "卖出") ? -1 : 1); if (tradeObj.IsGroup == 1) { var cashTradeIds = cashTrades.Where(t => t.Action != ClientCashInCashOut.系统操作_期权费).Select(t => t.id).ToArray(); //var childrenCashTradesSettle = DbContext.trade_cash.Where(t => cashTradeIds.Contains(t.ParentTradeCashId)).ToList(); var childrenCashTradesSettle = childTradeCashList.Where(t => cashTradeIds.Contains(t.ParentTradeCashId)).ToList(); var childrenTradeIds = childrenCashTradesSettle.Select(x => x.TradeId).Distinct().ToArray(); //var childrenTrades = DbContext.trade.Where(t => childrenTradeIds.Contains(t.id)); var childrenTrades = childTradeList.Where(t => childrenTradeIds.Contains(t.id)); var realizedPnl = 0.0; childrenCashTradesSettle.ForEach(x => { var trade = childrenTrades.FirstOrDefault(y => y.id == x.TradeId); realizedPnl += x.Amount - ((trade?.TradePrice * x.UnwindPercentRate * ((trade?.BuySell == "卖出") ? -1 : 1)) ?? 0); }); tradeObj.RealizedPnl = realizedPnl; } } if (result != null && result.TradeRiskList != null) { if (tradeObj.IsGroup == 1) { //var childTradeIds = DbContext.trade.Where(y => y.ParentTradeId == tradeObj.id && y.ValidState != "InValid").Select(y => y.id).ToList(); var childTradeIds = childTradeList.Where(y => y.ParentTradeId == tradeObj.id && y.ValidState != "InValid").Select(y => y.id).ToList(); var risks = result.TradeRiskList.Where(x => childTradeIds.Contains(x.TradeId)); tradeObj.DeltaInLots = risks != null && risks.Any() ? risks.Sum(x => x.DeltaInLots) : 0; } else { var risk = result.TradeRiskList.FirstOrDefault(x => x.TradeId == tradeObj.id); tradeObj.DeltaInLots = risk != null ? risk.DeltaInLots : 0; } } var realStrike = tradeObj.IsMoneynessOptionData ? (tradeObj.SpotPrice ?? 0) * (tradeObj.Strike ?? 0) : tradeObj.Strike ?? 0; tradeObj.ValueStatus = "-"; DataCacheModule.DataCacheManager.GetUnderlyingDataSource().TryGetPrice(tradeObj.UnderlyingCode, out var price); tradeObj.UnderlyingPrice = price; tradeObj.UnderlyingName = underlying?.UnderlyingName; if (tradeObj.IsOption() && price > 0) { if (realStrike == price) { tradeObj.ValueStatus = "ATM 100%"; } else if ((realStrike < price && tradeObj.OptionType == "看涨") || (realStrike > price && tradeObj.OptionType == "看跌")) { tradeObj.ValueStatus = "ITM " + (realStrike / price * 100).ToString("0.00") + "%"; } else { tradeObj.ValueStatus = "OTM " + (realStrike / price * 100).ToString("0.00") + "%"; } } var pv = realtimerisk.Where(t => t.TradeId == tradeObj.id).Select(t => new KeyValuePair(t.VolType, t.Pv)).ToList(); var roundedPv = realtimerisk.Where(t => t.TradeId == tradeObj.id).Select(t => new KeyValuePair(t.VolType, t.RoundedPv)).ToList(); if (PS.Config.IsPVRounded) { if (roundedPv != null && roundedPv.Count > 0) { tradeObj.PV = roundedPv.ToJson(); } } else { if (pv != null && pv.Count > 0) { tradeObj.PV = pv.ToJson(); } } if (tradeObj.TradeType == "合成价差期权") { //tradeObj.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(tradeObj.UnderlyingCode); tradeObj.SyntheticUnderlyingTipsInfo = syntheticUnderlyingList.FirstOrDefault(d => tradeObj.UnderlyingCode.Equals(d.Name))?.UnderlyingTipsInfo; } //tradeObj.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(tradeObj.id); if (keyValueSalesC.ContainsKey(tradeObj.id)) { tradeObj.SalesCommission = keyValueSalesC[tradeObj.id]; } else { tradeObj.SalesCommission = new TradeSalesCommissionInfo(); } if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && tradeObj.SalesCommission?.Commission != null) { tradeObj.SalesCommission.Commission = tradeObj.SalesCommission.Commission * tradeObj.SalesCommission.SalesIds.Count(); } tradeObj.CountRatio = underlying?.CountRatio ?? 1; tradeObj.SettlementDate = tradeObj.SettlementDate ?? tradeObj.ExerciseDate; } } return sList; } /// /// 获取今日敲出数据列表 /// public SearchListResult GetKnockedOutList(TdTradeQueryModel req) { var valueDate = SystemValueDate; var endDate = valueDate.AddDays(1); var predicate = BuildPredicate(req, valueDate); var tQuery = DbContext.trade.Where(predicate); var query1 = from tc in DbContext.trade_cash join t in tQuery on tc.TradeId equals t.id join ao in DbContext.autocall_observation on new { EndDate = tc.ValueDate, TradeId = t.id } equals new { ao.EndDate, ao.TradeId } into tempAo from ao in tempAo.DefaultIfEmpty() where tc.BarrierPrice != null //障碍期权敲出 && tc.HappenedDate >= valueDate && tc.HappenedDate < endDate && t.ValidState != "InValid" && !tc.IsDeleted select new TdPreEndTrade2 { id = t.id, trade = t, trade_cash = new TradeCashDto { Action = tc.Action, Amount = tc.Amount, UnwindTradeAmount = tc.UnwindTradeAmount, FinalPrice = tc.FinalPrice, UnwindPrice = tc.UnwindPrice, Notional = tc.Notional, UnwindNotional = tc.UnwindNotional, TradeAmount = tc.TradeAmount, ValidState = tc.ValidState, ValueDate = tc.ValueDate, UnwindPercentRate = tc.UnwindPercentRate, UnwindPricePercentRate = tc.UnwindPricePercentRate } }; if (string.IsNullOrEmpty(req.sidx)) { query1 = query1.OrderByDescending(s => s.trade.TradeDate); } var sList = query1.ToSearchList(req); foreach (var item in sList.rows) { tradeBLL.SetFieldsByTradeType(item.trade); item.trade.UnWindUnderlyingPrice = DbContext.trade_cash.Where(x => x.TradeId == item.trade.id && !x.IsDeleted && x.BarrierPrice != null).Select(x => x.BarrierPrice).FirstOrDefault(); if (!ConsTrade.TradeTypesForHedge.Contains(item.trade.TradeType)) { var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.UnderlyingCode); if (underlying != null && underlying.UnderlyingInstrumentType != "Stock") { item.trade.TradeOriginalAmount = item.trade.OriginalNotional / underlying.CountRatio; } else { item.trade.TradeOriginalAmount = item.trade.OriginalNotional; } item.trade.UnderlyingName = underlying.UnderlyingName; } if (item.trade.TradeType == "合成价差期权") { item.trade.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(item.trade.UnderlyingCode); } item.trade.CountRatio = DataCacheManager.GetUnderlyingDataSource().GetData(item.trade.UnderlyingCode)?.CountRatio; } return sList; } //替换TradeBLL.SearchHistoryList /// /// 获取当日提前终止数据列表 /// public SearchListResult GetPreEndList(TdTradeQueryModel req, List userAssets, List userClients, bool isShowAll) { var curTradingDate = SystemValueDate; var predicate = BuildPredicate(req, curTradingDate, req.OtcTradeType == DBModels.Enums.OtcTradeType.EquitySwap ? true : false); var tQuery = DbContext.trade.Where(predicate); //交易员对应的簿记账户筛选或者客户经理对应的客户筛选 if (userAssets != null || userClients != null) { tQuery = from source in tQuery where userAssets.Contains(source.AssetId) || userClients.Contains(source.ClientId) select source; } var query1 = from tc in DbContext.trade_cash join t in tQuery on tc.TradeId equals t.id where tc.ValueDate == curTradingDate && (tc.Action == ClientCashInCashOut.系统操作_平仓费 || tc.Action == ClientCashInCashOut.系统操作_互换) && (t.TradeStatus == "平仓待复核" || t.TradeStatus == "互换待复核" || tc.ValidState != "InValid") && !tc.IsDeleted && tc.BarrierPrice == null //不包含敲出数据 select new TdPreEndTrade2 { id = t.id, trade = t, trade_cash = new TradeCashDto { id = tc.id, Action = tc.Action, Amount = tc.Amount, UnwindTradeAmount = tc.UnwindTradeAmount, FinalPrice = tc.FinalPrice, UnwindPrice = tc.UnwindPrice, Notional = tc.Notional, UnwindNotional = tc.UnwindNotional, TradeAmount = tc.TradeAmount, ValidState = tc.ValidState, ValueDate = tc.ValueDate, UnwindPercentRate = tc.UnwindPercentRate, UnwindPricePercentRate = tc.UnwindPricePercentRate } }; //已平仓,部分平仓,美式期权提前行权 //predicate = predicate.And(t => t.ExerciseMode == "American"); tQuery = DbContext.trade.Where(predicate); var query2 = from tc in DbContext.trade_cash join t in tQuery on tc.TradeId equals t.id where tc.ValueDate == curTradingDate && tc.Action == ClientCashInCashOut.系统操作_行权费 && tc.ExerciseWay != "到期行权" && (t.TradeStatus == "行权待复核" || tc.ValidState != ConsGlobal.InValid && t.TradeStatus == ConsTrade.已执行) && !tc.IsDeleted && tc.BarrierPrice == null //不包含敲出数据 select new TdPreEndTrade2 { id = t.id, trade = t, trade_cash = new TradeCashDto { id = tc.id, Action = tc.Action, Amount = tc.Amount, UnwindTradeAmount = tc.UnwindTradeAmount, FinalPrice = tc.FinalPrice, UnwindPrice = tc.UnwindPrice, Notional = tc.Notional, UnwindNotional = tc.UnwindNotional, TradeAmount = tc.TradeAmount, ValidState = tc.ValidState, ValueDate = tc.ValueDate, UnwindPercentRate = tc.UnwindPercentRate, UnwindPricePercentRate = tc.UnwindPricePercentRate } }; var query = query1.Concat(query2); if (string.IsNullOrEmpty(req.sidx)) { query = query.OrderByDescending(s => s.trade.TradeNumber); } var sList = query.ToSearchList(req); if (sList.rows != null && sList.rows.Any()) { var trades = sList.rows.Select(n => n.trade); new TradeDalModule.TradeDalService(this).SetStructureInfo(trades); var forwardIds = trades.Where(p => "远期".Equals(p.TradeType)).Select(p => p.id).Distinct().ToList(); List forwardList = null; if (forwardIds != null && forwardIds.Count > 0) { forwardList = DbContext.trade_forward.AsNoTracking().Where(x => forwardIds.Contains(x.TradeId)).ToList(); } if (forwardList == null) { forwardList = new List(); } var tradeIdList = trades.Select(p => p.id).Distinct().ToList(); Dictionary keyValueSalesC = null; using (var saleCService = new SalesModule.SalesCommissionDataService(OptUser)) { keyValueSalesC = saleCService.GetTradeCommissionInfoByTradeIds(tradeIdList); } var syntheticUnderlyingCodeList = trades.Where(d => "合成价差期权".Equals(d.TradeType)).Select(d => d.UnderlyingCode).Distinct().ToList(); List syntheticUnderlyingList = null; if (syntheticUnderlyingCodeList != null && syntheticUnderlyingCodeList.Count > 0) { syntheticUnderlyingList = synthetic_underlyingBLL.GetListByNames(syntheticUnderlyingCodeList); } if (syntheticUnderlyingList == null) { syntheticUnderlyingList = new List(); } List tradeCashDetailList = null; var isGroupNotEqual1tradeCashIds = sList.rows.Where(d => d.trade.IsGroup != 1).Select(d => d.trade_cash.id).Distinct().ToList(); if (isGroupNotEqual1tradeCashIds != null && isGroupNotEqual1tradeCashIds.Count > 0) { tradeCashDetailList = DbContext.trade_cash_detail.AsNoTracking().Where(x => isGroupNotEqual1tradeCashIds.Contains(x.TradeCashId)).ToList(); } if (tradeCashDetailList == null) { tradeCashDetailList = new List(); } var isGroupEqual1tradeCashIds = sList.rows.Where(d => d.trade.IsGroup == 1).Select(d => d.trade_cash.id).Distinct().ToList(); List childTradeCashList = null; var parentTradeIds = sList.rows.Where(d => d.trade.IsGroup == 1).Select(d => d.id).Distinct().ToList(); if (isGroupEqual1tradeCashIds != null && isGroupEqual1tradeCashIds.Count > 0 && parentTradeIds != null && parentTradeIds.Count > 0) { var childTradeIds = DbContext.trade.Where(p => parentTradeIds.Contains(p.ParentTradeId) && p.ParentTradeId > 0).Select(p => p.id).Distinct().ToList(); if (childTradeIds != null && childTradeIds.Count > 0) { childTradeCashList = DbContext.trade_cash.AsNoTracking().Where(x => childTradeIds.Contains(x.TradeId) && isGroupEqual1tradeCashIds.Contains(x.ParentTradeCashId)).ToList(); } } if (childTradeCashList == null) { childTradeCashList = new List(); } List allChildTradeIds = childTradeCashList.Select(d => d.TradeId).Distinct().ToList(); List allChildTradeList = null; if (allChildTradeIds != null && allChildTradeIds.Count > 0) { allChildTradeList = DbContext.trade.AsNoTracking().Where(d => allChildTradeIds.Contains(d.id)).ToList(); } if (allChildTradeList == null) { allChildTradeList = new List(); } foreach (var item in sList.rows) { var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(item.trade.UnderlyingCode); ProcessTrade(item.trade, null, underlying: underlying, syntheticUnderlyings: syntheticUnderlyingList); if (item.trade.TradeType == "远期") { item.trade.trade_forward = forwardList.FirstOrDefault(x => x.TradeId == item.trade.id); } if (keyValueSalesC.ContainsKey(item.trade.id)) { item.trade.SalesCommission = keyValueSalesC[item.trade.id]; } else { item.trade.SalesCommission = new TradeSalesCommissionInfo(); } //tradeObj.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(tradeObj.id); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && item.trade.SalesCommission?.Commission != null) { item.trade.SalesCommission.Commission = item.trade.SalesCommission.Commission * item.trade.SalesCommission.SalesIds.Count(); } if (item.trade.IsGroup == 1) { //var childTradeCashs = DbContext.trade_cash.Where(x => x.ParentTradeCashId == item.trade_cash.id).ToList(); var childTradeCashs = childTradeCashList.Where(x => x.ParentTradeCashId == item.trade_cash.id).ToList(); var childTradeIds = childTradeCashs.Select(x => x.TradeId).Distinct().ToList(); //var childTrades = DbContext.trade.Where(x => childTradeIds.Contains(x.id)).ToList(); var childTrades = allChildTradeList.Where(x => childTradeIds.Contains(x.id)).ToList(); var tcTradePrice = 0.0; childTradeCashs.ForEach(x => { var trade = childTrades.FirstOrDefault(y => y.id == x.TradeId); tcTradePrice += (x.UnwindPercentRate * trade?.TradePrice * (trade?.BuySell == "买入" ? -1 : 1)) ?? 0; }); item.WinLoss = -(item.trade_cash.Amount + tcTradePrice); } else { //var tradeCashDetail = DbContext.trade_cash_detail.Where(x => x.TradeCashId == item.trade_cash.id); var tradeCashDetail = tradeCashDetailList.Where(x => x.TradeCashId == item.trade_cash.id); var amount = tradeCashDetail.Any() ? tradeCashDetail.Sum(x => x.Amount ?? 0) : item.trade_cash.Amount; item.WinLoss = -(amount + (item.trade.TradePrice ?? 0) * (item.trade_cash.UnwindPercentRate ?? 0) * ((item.trade.BuySell == "卖出" || item.trade.TradeType == "远期") ? 1 : -1)); } item.trade.CountRatio = underlying?.CountRatio ?? 1; item.trade.UnderlyingName = underlying?.UnderlyingName; } } return sList; } public List GetPreEndGroupChildren(int TcId) { var tQuery = DbContext.trade.AsNoTracking(); var query = from tc in DbContext.trade_cash.AsNoTracking().Where(x => x.ValidState != "InValid" && x.ParentTradeCashId == TcId) join t in tQuery on tc.TradeId equals t.id select new TdPreEndTrade2 { id = t.id, trade = t, trade_cash = new TradeCashDto { id = tc.id, Action = tc.Action, Amount = tc.Amount, UnwindTradeAmount = tc.UnwindTradeAmount, FinalPrice = tc.FinalPrice, UnwindPrice = tc.UnwindPrice, Notional = tc.Notional, UnwindNotional = tc.UnwindNotional, TradeAmount = tc.TradeAmount, ValidState = tc.ValidState, ValueDate = tc.ValueDate, UnwindPercentRate = tc.UnwindPercentRate, UnwindPricePercentRate = tc.UnwindPricePercentRate } }; var sList = query.ToList(); var trades = sList.Select(n => n.trade); new TradeDalModule.TradeDalService(this).SetStructureInfo(trades); foreach (var tradeObj in trades) { ProcessTrade(tradeObj, null); if (tradeObj.TradeType == "远期") { tradeObj.trade_forward = DbContext.trade_forward.First(x => x.TradeId == tradeObj.id); } tradeObj.SalesCommission = new SalesModule.SalesCommissionDataService(OptUser).GetTradeCommissionInfo(tradeObj.id); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1" && tradeObj.SalesCommission?.Commission != null) { tradeObj.SalesCommission.Commission = tradeObj.SalesCommission.Commission * tradeObj.SalesCommission.SalesIds.Count(); } } return sList; } /// /// 交易观察状态列表 /// 障碍期权,双鲨期权,凤凰期权,雪球期权分tab展示 /// public SearchListResult GetObservationStatusTradeList(TdTradeQueryModel req) { var valueDate = SystemValueDate; var predicate = BuildObservationStatusPredicate(req, valueDate); var tQuery = DbContext.trade.Where(predicate); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeNumber"; req.sord = "desc"; } var sList = tQuery.ToSearchList(req); if (sList.rows != null && sList.rows.Any()) { var tradeIds = sList.rows.Select(t => t.id).ToList(); //处理障碍期权类型 需要关联表 在内存中处理 var trade_barrier_option = DbContext.trade_barrier_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理双鲨期权 var trade_double_sharkfin_option = DbContext.trade_double_sharkfin_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理凤凰期权 var trade_autocall = DbContext.trade_autocall.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理雪球期权 var trade_snowball = DbContext.trade_snowball.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理二元期权 var trade_binary_option = DbContext.trade_binary_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理累计期权 var trade_accumulator_option = DbContext.trade_accumulator_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); foreach (var trade in sList.rows) { if (trade.TradeType == "障碍期权") { var barrier = trade_barrier_option.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_barrier_option = barrier == null ? new trade_barrier_option() : trade_barrier_option.FirstOrDefault(t => t.TradeId == trade.id); if (string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates)) { trade.trade_barrier_option.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_barrier_option.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_barrier_option.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_barrier_option.LatestObservationDate = null; } } } else if (trade.TradeType == "双鲨期权") { var doubleSharkFin = trade_double_sharkfin_option.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_double_sharkfin_option = doubleSharkFin == null ? new trade_double_sharkfin_option() : trade_double_sharkfin_option.FirstOrDefault(t => t.TradeId == trade.id); if (string.IsNullOrEmpty(trade.trade_double_sharkfin_option.ObservationDates)) { trade.trade_double_sharkfin_option.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_double_sharkfin_option.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_double_sharkfin_option.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_double_sharkfin_option.LatestObservationDate = null; } } } else if (trade.TradeType == "凤凰期权") { var autocall = trade_autocall.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_autocall = autocall == null ? new trade_autocall() : trade_autocall.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_autocall.HappenedObservations = new TradeAutocallBLL(this).QueryHappenedObservations(trade.id, DateTime.MaxValue); if (string.IsNullOrEmpty(trade.trade_autocall.ObservationDates)) { trade.trade_autocall.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_autocall.LatestObservationDate = latestObservationDate.DateTime; } } if (string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates)) { trade.trade_autocall.LatestKOObservationDate = valueDate; trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.KOObservationDates); var koObservationDates = customizedResults.Item1; var customizedKOBarriers = customizedResults.Item2; var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestKOObservationDate != null) { trade.trade_autocall.LatestKOObservationDate = latestKOObservationDate.DateTime; if (customizedKOBarriers == null || !customizedKOBarriers.Any()) { trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier; } else { trade.trade_autocall.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)]; } } } } else if (trade.TradeType == "雪球期权") { var snowball = trade_snowball.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_snowball = snowball == null ? new trade_snowball() : trade_snowball.FirstOrDefault(t => t.TradeId == trade.id); if (string.IsNullOrEmpty(trade.trade_snowball.ObservationDates)) { trade.trade_snowball.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_snowball.LatestObservationDate = latestObservationDate.DateTime; } } if (string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates)) { trade.trade_snowball.LatestKOObservationDate = valueDate; trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.KOObservationDates); var koObservationDates = customizedResults.Item1; var customizedKOBarriers = customizedResults.Item2; var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestKOObservationDate != null) { trade.trade_snowball.LatestKOObservationDate = latestKOObservationDate.DateTime; if (customizedKOBarriers == null || !customizedKOBarriers.Any()) { trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier; } else { trade.trade_snowball.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)]; } } } } else if (trade.TradeType == "二元期权") { var binary = trade_binary_option.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_binary_option = binary == null ? new trade_binary_option() : trade_binary_option.FirstOrDefault(t => t.TradeId == trade.id); if (string.IsNullOrEmpty(trade.trade_binary_option.ObservationDates)) { trade.trade_binary_option.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_binary_option.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_binary_option.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_binary_option.LatestObservationDate = null; } } } else if (trade.TradeType == "累计期权") { var accumulator = trade_accumulator_option.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_accumulator_option = accumulator == null ? new trade_accumulator_option() : accumulator; if (string.IsNullOrEmpty(trade.trade_accumulator_option.KOObservationDates)) { trade.trade_accumulator_option.LatestObservationDate = valueDate; trade.trade_accumulator_option.LatestKOBarrier = trade.trade_accumulator_option.KOBarrier; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_accumulator_option.KOObservationDates); var observationDates = customizedResults.Item1; var latestKOBarrier = customizedResults.Item2; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_accumulator_option.LatestObservationDate = latestObservationDate.DateTime; if (latestKOBarrier == null || !latestKOBarrier.Any()) { trade.trade_accumulator_option.LatestKOBarrier = trade.trade_accumulator_option.KOBarrier; } else { trade.trade_accumulator_option.LatestKOBarrier = latestKOBarrier[GetDateIndex(observationDates, latestObservationDate)]; } } } } DataCacheModule.DataCacheManager.GetUnderlyingDataSource().TryGetPrice(trade.UnderlyingCode, out var price); trade.UnderlyingPrice = price; } } return sList; } public SearchListResult GetObservationEventTradeList(TdTradeQueryModel req) { var valueDate = req.ValueDate ?? SystemValueDate; EodPriceProvider priceProvider = null; var predicate = BuildObservationEventPredicte(req, valueDate); var tQuery = DbContext.trade.Where(predicate); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "trade.TradeNumber"; req.sord = "desc"; } var observationStatus = req.ObservationStatus; if (observationStatus == null) { observationStatus = new List() { "已敲入", "已敲出", "观察中" }; } var querylist = tQuery.ToList(); var knockOutList = new List(); var knockInList = new List(); var couponList = new List(); var customList = new List(); if (querylist != null && querylist.Any()) { var tradeIds = querylist.Select(t => t.id).ToList(); Dictionary manuallyTradeObservationPrices = null; if (valueDate < SystemValueDate) { priceProvider = new EodPriceProvider(valueDate); manuallyTradeObservationPrices = DbContext.manually_trade_observation_price .Where(x => tradeIds.Contains(x.TradeId) && x.ValueDate == valueDate).ToDictionary(n => n.TradeId); } if (req.TabIndex == 3 || req.TabIndex == 99) { var trade_custom = DbContext.trade_custom.Where(t => tradeIds.Contains(t.TradeId)).ToList(); foreach (var trade in querylist) { var custom = trade_custom.FirstOrDefault(t => t.TradeId == trade.id); trade.trade_custom = custom == null ? new trade_custom() : trade_custom.FirstOrDefault(t => t.TradeId == trade.id); var tempTrade = new TdObservationTrade(); if (string.IsNullOrEmpty(trade.trade_custom.ObservationDates)) { continue; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_custom.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_custom.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_custom.LatestObservationDate = null; } } tempTrade.trade = trade.Clone(); if (trade.trade_custom.LatestObservationDate == valueDate) { tempTrade.Type += 8; customList.Add(tempTrade); } else { continue; } var price = 0.0; double? SettlementAmount = null; if (valueDate >= SystemValueDate) { DataCacheManager.GetUnderlyingDataSource().TryGetPrice(trade.UnderlyingCode, out price); } else { if (manuallyTradeObservationPrices.TryGetValue(trade.id, out var manuallyTradeObservationPrice)) { price = manuallyTradeObservationPrice.Price ?? 0; SettlementAmount = manuallyTradeObservationPrice.SettlementAmount; } else if (!priceProvider.TryGetEodPrice(trade.UnderlyingCode, out var eodPrice)) { throw new Exception($"[{trade.TradeType}:{trade.TradeNumber},标的:{trade.UnderlyingCode}]未找到结算价"); } else { price = eodPrice.GetPrice(trade.SettlementType); } } if (tempTrade.trade != null) { tempTrade.trade.UnderlyingPrice = price; } } } if (req.TabIndex != 3) { //处理障碍期权类型 需要关联表 在内存中处理 var trade_barrier_option = DbContext.trade_barrier_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理双鲨期权 var trade_double_sharkfin_option = DbContext.trade_double_sharkfin_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理凤凰期权 var trade_autocall = DbContext.trade_autocall.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理雪球期权 var trade_snowball = DbContext.trade_snowball.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //处理二元期权 var trade_binary_option = DbContext.trade_binary_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //气囊结构 var trade_airbag = DbContext.trade_airbag.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //区间累积 var trade_rangeaccrual = DbContext.trade_rangeaccrual.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //累计期权 var trade_accumulator = DbContext.trade_accumulator_option.Where(t => tradeIds.Contains(t.TradeId)).ToList(); //是否新增观察事件 -- knockOutList,knockInList,couponList,customList bool isAdd = false; foreach (var trade in querylist) { var tempTrade = new TdObservationTrade(); var tempTrade1 = new TdObservationTrade(); switch (trade.TradeType) { case "障碍期权": { var barrier = trade_barrier_option.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_barrier_option(); trade.trade_barrier_option = barrier; if (string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates)) { trade.trade_barrier_option.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_barrier_option.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_barrier_option.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_barrier_option.LatestObservationDate = null; } } if (observationStatus.Contains(trade.trade_barrier_option.KnockInOutStatusCn)) { tempTrade.trade = trade.Clone(); tempTrade.ObservationStatus = trade.trade_barrier_option.KnockInOutStatusCn; tempTrade.konckInOutDate = trade.trade_barrier_option.KnockInOutDate; tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_barrier_option.BarrierPrice * trade.SpotPrice : trade.trade_barrier_option.BarrierPrice; tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_barrier_option.UpperBarrierPrice * trade.SpotPrice : trade.trade_barrier_option.UpperBarrierPrice; if (trade.trade_barrier_option.LatestObservationDate == valueDate) { if (trade.trade_barrier_option.BarrierType.Contains("敲入")) { tempTrade.Type += 1; knockInList.Add(tempTrade); isAdd = true; } if (trade.trade_barrier_option.BarrierType.Contains("敲出")) { tempTrade.Type += 2; knockOutList.Add(tempTrade); isAdd = true; } if (tempTrade.ObservationStatus != "已敲入" && (tempTrade.ObservationStatus == "观察中" || tempTrade.konckInOutDate == valueDate || trade.ExerciseDate == valueDate)) { tempTrade.Type += 4; couponList.Add(tempTrade); isAdd = true; } } } } break; case "双鲨期权": { var doubleSharkFin = trade_double_sharkfin_option.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_double_sharkfin_option(); trade.trade_double_sharkfin_option = doubleSharkFin; if (string.IsNullOrEmpty(trade.trade_double_sharkfin_option.ObservationDates)) { trade.trade_double_sharkfin_option.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_double_sharkfin_option.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_double_sharkfin_option.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_double_sharkfin_option.LatestObservationDate = null; } } if (observationStatus.Contains(trade.trade_double_sharkfin_option.KnockInOutStatusCn)) { tempTrade.trade = trade.Clone(); tempTrade.ObservationStatus = trade.trade_double_sharkfin_option.KnockInOutStatusCn; tempTrade.konckInOutDate = trade.trade_double_sharkfin_option.KnockInOutDate; tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_double_sharkfin_option.BarrierLow * trade.SpotPrice : trade.trade_double_sharkfin_option.BarrierLow; tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_double_sharkfin_option.BarrierHigh * trade.SpotPrice : trade.trade_double_sharkfin_option.BarrierHigh; if (trade.trade_double_sharkfin_option.LatestObservationDate == valueDate) { tempTrade.Type += 2; knockOutList.Add(tempTrade); if (tempTrade.ObservationStatus == "观察中" || tempTrade.konckInOutDate == valueDate) { tempTrade.Type += 4; couponList.Add(tempTrade); } isAdd = true; } } } break; case "凤凰期权": { var autocall = trade_autocall.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_autocall(); trade.trade_autocall = autocall; trade.trade_autocall.HappenedObservations = new TradeAutocallBLL(this).QueryHappenedObservations(trade.id, DateTime.MaxValue); if (string.IsNullOrEmpty(trade.trade_autocall.ObservationDates)) { trade.trade_autocall.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_autocall.LatestObservationDate = latestObservationDate.DateTime; } } if (string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates)) { trade.trade_autocall.LatestKOObservationDate = valueDate; trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier; } else { var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(trade.trade_autocall.KOObservationDates, trade.trade_autocall.CouponBarrier); if (req.TabIndex == 2) { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ko.Item1); var CouponsObservationDates = customizedResults.Item1; var CouponsKOBarriers = customizedResults.Item2; var latestKOObservationDate = CouponsObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestKOObservationDate != null) { trade.trade_autocall.LatestKOObservationDate = latestKOObservationDate.DateTime; if (CouponsKOBarriers == null || !CouponsKOBarriers.Any()) { trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier; } else { trade.trade_autocall.LatestKOBarrier = CouponsKOBarriers[GetDateIndex(CouponsObservationDates, latestKOObservationDate)]; } } } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfoV3(ko.Item2); var koObservationDates = customizedResults.Item1; var customizedKOBarriers = customizedResults.Item2; var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestKOObservationDate != null) { trade.trade_autocall.LatestKOObservationDate = latestKOObservationDate.DateTime; if (customizedKOBarriers == null || !customizedKOBarriers.Any()) { trade.trade_autocall.LatestKOBarrier = trade.trade_autocall.KOBarrier; } else { trade.trade_autocall.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)]; } } } } if (observationStatus.Contains(trade.trade_autocall.KnockInOutStatusCn)) { tempTrade.trade = trade.Clone(); var barrier1 = (trade.IsMoneynessOption == "是" ? trade.trade_autocall.KIBarrier * trade.SpotPrice : trade.trade_autocall.KIBarrier) ?? 0; var barrier2 = (trade.IsMoneynessOption == "是" ? trade.trade_autocall.KOBarrier * trade.SpotPrice : trade.trade_autocall.KOBarrier) ?? 0; if (trade.trade_autocall.LatestObservationDate == valueDate) { tempTrade.ObservationStatus = trade.trade_autocall.KnockInOutStatusCn; tempTrade.konckInOutDate = trade.trade_autocall.KnockInOutDate; tempTrade.BarrierLow = trade.OptionType == "看涨" ? Math.Min(barrier1, barrier2) : Math.Max(barrier1, barrier2); tempTrade.BarrierHigh = trade.OptionType == "看涨" ? Math.Max(barrier1, barrier2) : Math.Min(barrier1, barrier2); tempTrade.Type += 1; knockInList.Add(tempTrade); isAdd = true; } if (trade.trade_autocall.LatestKOObservationDate == valueDate) { tempTrade1.trade = trade.Clone(); tempTrade1.ObservationStatus = trade.trade_autocall.KnockInOutStatusCn; tempTrade1.konckInOutDate = trade.trade_autocall.KnockInOutDate; tempTrade1.BarrierLow = trade.OptionType == "看涨" ? Math.Min(barrier1, barrier2) : Math.Max(barrier1, barrier2); tempTrade1.BarrierHigh = trade.OptionType == "看涨" ? Math.Max(barrier1, barrier2) : Math.Min(barrier1, barrier2); tempTrade.Type += 2; knockOutList.Add(tempTrade1); if (tempTrade1.ObservationStatus != "已敲出" || tempTrade1.konckInOutDate == valueDate) { tempTrade.Type += 4; couponList.Add(tempTrade1); } tempTrade1.Type = tempTrade.Type; isAdd = true; } } } break; case "雪球期权": { var snowball = trade_snowball.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_snowball(); trade.trade_snowball = snowball; if (string.IsNullOrEmpty(trade.trade_snowball.ObservationDates)) { trade.trade_snowball.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_snowball.LatestObservationDate = latestObservationDate.DateTime; } } if (string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates)) { trade.trade_snowball.LatestKOObservationDate = valueDate; trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.KOObservationDates); var koObservationDates = customizedResults.Item1; var customizedKOBarriers = customizedResults.Item2; var latestKOObservationDate = koObservationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestKOObservationDate != null) { trade.trade_snowball.LatestKOObservationDate = latestKOObservationDate.DateTime; if (customizedKOBarriers == null || !customizedKOBarriers.Any()) { trade.trade_snowball.LatestKOBarrier = trade.trade_snowball.KOBarrier; } else { trade.trade_snowball.LatestKOBarrier = customizedKOBarriers[GetDateIndex(koObservationDates, latestKOObservationDate)]; } } } if (observationStatus.Contains(trade.trade_snowball.KnockInOutStatusCn)) { tempTrade.trade = trade.Clone(); if (trade.trade_snowball.LatestObservationDate == valueDate && trade.trade_snowball.KIPayoffType != KIPayoffTypeEnum.None) { tempTrade.ObservationStatus = trade.trade_snowball.KnockInOutStatusCn; tempTrade.konckInOutDate = trade.trade_snowball.KnockInOutDate; tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KIBarrier * trade.SpotPrice : trade.trade_snowball.KIBarrier; tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KOBarrier * trade.SpotPrice : trade.trade_snowball.KOBarrier; tempTrade.Type += 1; knockInList.Add(tempTrade); isAdd = true; } if (trade.trade_snowball.LatestKOObservationDate == valueDate) { tempTrade1.trade = trade.Clone(); tempTrade1.ObservationStatus = trade.trade_snowball.KnockInOutStatusCn; tempTrade1.konckInOutDate = trade.trade_snowball.KnockInOutDate; if (ConsGlobal.CallPut.IsCall(trade.OptionType)) //向下敲入向上敲出 { tempTrade1.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_snowball.LatestKOBarrier * trade.SpotPrice : trade.trade_snowball.LatestKOBarrier; tempTrade1.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KIBarrier * trade.SpotPrice : trade.trade_snowball.KIBarrier; } else //向上敲入向下敲出 { tempTrade1.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_snowball.LatestKOBarrier * trade.SpotPrice : trade.trade_snowball.LatestKOBarrier; tempTrade1.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_snowball.KIBarrier * trade.SpotPrice : trade.trade_snowball.KIBarrier; } tempTrade.Type += 2; knockOutList.Add(tempTrade1); if (tempTrade1.ObservationStatus == "观察中" || tempTrade1.konckInOutDate == valueDate) { tempTrade.Type += 4; couponList.Add(tempTrade1); } tempTrade1.Type = tempTrade.Type; isAdd = true; } } } break; case "二元期权": { var binary = trade_binary_option.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_binary_option(); trade.trade_binary_option = binary; if (trade.ExerciseModeCn == "欧式") { break; } if (string.IsNullOrEmpty(trade.trade_binary_option.ObservationDates)) { trade.trade_binary_option.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_binary_option.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_binary_option.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_binary_option.LatestObservationDate = null; } } tempTrade.trade = trade.Clone(); if (trade.trade_binary_option.LatestObservationDate == valueDate) { tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike; tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.trade_binary_option.UpperBarrier * trade.SpotPrice : trade.trade_binary_option.UpperBarrier; tempTrade.Type += 2; knockOutList.Add(tempTrade); tempTrade.Type += 4; couponList.Add(tempTrade); isAdd = true; } } break; case "气囊结构": { var airbag = trade_airbag.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_airbag(); trade.trade_airbag = airbag; tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.trade_airbag.Barrier * trade.SpotPrice : trade.trade_airbag.Barrier; tempTrade.trade = trade.Clone(); tempTrade.Type = 4; couponList.Add(tempTrade); isAdd = true; //没有观察日,只计算敲入敲出 } break; case "区间累积期权": { var rangeaccrual = trade_rangeaccrual.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_rangeaccrual(); trade.trade_rangeaccrual = rangeaccrual; if (string.IsNullOrEmpty(trade.trade_rangeaccrual.ObservationDates)) { trade.trade_rangeaccrual.LatestObservationDate = valueDate; } else { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_rangeaccrual.ObservationDates); var observationDates = customizedResults.Item1; var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { trade.trade_rangeaccrual.LatestObservationDate = latestObservationDate.DateTime; } else { trade.trade_rangeaccrual.LatestObservationDate = null; } } tempTrade.trade = trade.Clone(); if (trade.trade_rangeaccrual.LatestObservationDate == valueDate) { tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike; tempTrade.Type += 4; couponList.Add(tempTrade); isAdd = true; } } break; case "累计期权": { var accumulator = trade_accumulator.FirstOrDefault(t => t.TradeId == trade.id) ?? new trade_accumulator_option(); trade.trade_accumulator_option = accumulator; DateTime? LatestObservationDate = valueDate; if (!string.IsNullOrEmpty(accumulator.KOObservationDates)) { var observationDates = QdpHelper.ParseObservationDate(accumulator.KOObservationDates); var latestObservationDate = observationDates.Where(x => x.DateTime >= valueDate).OrderBy(x => x.DateTime).FirstOrDefault(); if (latestObservationDate != null) { LatestObservationDate = latestObservationDate.DateTime; } else { LatestObservationDate = null; } } if (accumulator.KnockOutDate.HasValue) { tempTrade.trade = trade.Clone(); tempTrade.ObservationStatus = "敲出"; tempTrade.konckInOutDate = accumulator.KnockOutDate; if (ConsGlobal.CallPut.IsCall(trade.OptionType)) { tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike; tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? accumulator.KOBarrier * trade.SpotPrice : accumulator.KOBarrier; } else { tempTrade.BarrierHigh = trade.IsMoneynessOption == "是" ? trade.Strike * trade.SpotPrice : trade.Strike; tempTrade.BarrierLow = trade.IsMoneynessOption == "是" ? accumulator.KOBarrier * trade.SpotPrice : accumulator.KOBarrier; } if (LatestObservationDate == valueDate) { tempTrade.Type += 2; knockOutList.Add(tempTrade); isAdd = true; if (accumulator.PayoffType == "固定") { tempTrade.Type += 4; couponList.Add(tempTrade); } } } } break; } if (!isAdd) { continue; } var price = 0.0; double? SettlementAmount = null; if (valueDate >= SystemValueDate) { DataCacheManager.GetUnderlyingDataSource().TryGetPrice(trade.UnderlyingCode, out price); } else { if (manuallyTradeObservationPrices.TryGetValue(trade.id, out var manuallyTradeObservationPrice)) { price = manuallyTradeObservationPrice.Price ?? 0; SettlementAmount = manuallyTradeObservationPrice.SettlementAmount; } else if (!priceProvider.TryGetEodPrice(trade.UnderlyingCode, out var eodPrice)) { throw new Exception($"[{trade.TradeType}:{trade.TradeNumber},标的:{trade.UnderlyingCode}]未找到结算价"); } else { price = eodPrice.GetPrice(trade.SettlementType); } } if (tempTrade.trade != null) { tempTrade.trade.UnderlyingPrice = price; } if (tempTrade1.trade != null) { tempTrade1.trade.UnderlyingPrice = price; } tempTrade.CouponPaidStatus = CheckCouponPaid(valueDate, trade, price, SettlementAmount); tempTrade1.CouponPaidStatus = tempTrade.CouponPaidStatus; } } } var sList = new SearchListResult(); switch (req.TabIndex) { case 0: sList = knockOutList.AsQueryable().ToSearchList(req); break; case 1: sList = knockInList.AsQueryable().ToSearchList(req); break; case 2: sList = couponList.AsQueryable().ToSearchList(req); break; case 3: sList = customList.AsQueryable().ToSearchList(req); break; case 99: couponList.AddRange(knockInList); couponList.AddRange(knockOutList); couponList.AddRange(customList); sList = couponList.Distinct().AsQueryable().ToSearchList(req); break; default: break; } return sList; } public SearchListResult GetDelaySettlementTradeQuery(TdTradeQueryModel req) { var valueDate = req.ValueDate ?? SystemValueDate; var predicate = BuildObservationEventPredicte(req, valueDate); var tQuery = DbContext.trade.Where(predicate); if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeNumber"; req.sord = "desc"; } var sList = tQuery.ToSearchList(req); var sysuser = new ErpBaseContext().SystemUsers.Select(x => new { x.Id, x.Name }).ToList(); foreach (var item in sList.rows) { item.SettlementFlagOptName = sysuser?.FirstOrDefault(x => x.Id == item.SettlementFlagOptId)?.Name; } return sList; } /// /// /// /// /// /// 1:已付票息 0:不付票息 2:将付票息 public int CheckCouponPaid(DateTime? valueDate, trade td, double price, double? SettlementAmount) { var hasPaid = DbContext.autocall_observation.Any(o => o.EndDate == valueDate && o.TradeId == td.id); if (hasPaid || ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus)) { return 1; } else { var ret = new CheckTradeObservateStatusService(OptUser).CheckTradeObservateStatus(td, valueDate.Value, new double[3] { price, price, price }, SettlementAmount); if (ret.Value) { return 2; } } return 0; } private int GetDateIndex(Date[] source, Date value) { var index = 0; foreach (var item in source) { if (item.DateTime == value.DateTime) { return index; } index++; } return -1; } public void ProcessTrade(trade tradeObj, trade_cash tradeCash, underlying_manager underlying = null, List syntheticUnderlyings = null) { if (tradeObj.TradeType == "合成价差期权") { if (syntheticUnderlyings != null) { tradeObj.SyntheticUnderlyingTipsInfo = syntheticUnderlyings.FirstOrDefault(d => d.Name.Equals(tradeObj.UnderlyingCode))?.UnderlyingTipsInfo; } else { tradeObj.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(tradeObj.UnderlyingCode); } } tradeObj.FinalPrice = tradeCash?.FinalPrice; if (!ConsTrade.TradeTypesForHedge.Contains(tradeObj.TradeType)) { if (underlying == null) { underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(tradeObj.UnderlyingId); } if (underlying != null && underlying.UnderlyingInstrumentType != "Stock") { tradeObj.TradeOriginalAmount = tradeObj.OriginalNotional / underlying.CountRatio; } else { underlying = new underlying_manager(); tradeObj.TradeOriginalAmount = tradeObj.OriginalNotional; } tradeObj.UnderlyingName = underlying.UnderlyingName; } tradeObj.trade_cash = tradeCash; } public Dictionary getDailyEvents(DateTime? date, List userAssets, List userClients) { try { if (date == null) { date = SystemValueDate; } var ret = new Dictionary(); //到期 var settleTradeQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType != "远期" && o.TradeType != "收益互换" && o.TradeType != "现金流交易"); var settleCashTradeQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType == "现金流交易"); var settleForwardQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType == "远期"); var settleExchangeQuery = DbContext.trade.Where(o => o.ExerciseDate == date && o.ValidState != "InValid" && o.TradeType == "收益互换"); if (settleTradeQuery.Any()) { if (settleTradeQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus))) { ret.Add("到期期权", false); } else { ret.Add("到期期权", true); } } if (settleCashTradeQuery.Any()) { if (settleCashTradeQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus))) { ret.Add("到期现金流", false); } else { ret.Add("到期现金流", true); } } if (settleForwardQuery.Any()) { if (settleForwardQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus))) { ret.Add("到期远期", false); } else { ret.Add("到期远期", true); } } if (settleExchangeQuery.Any()) { if (settleExchangeQuery.Any(o => ConsTrade.PositionTradeStatusList.Contains(o.TradeStatus))) { ret.Add("到期互换", false); } else { ret.Add("到期互换", true); } } //观察日 var req = new TdTradeQueryModel() { TabIndex = 99, ValueDate = date, UserAssets = userAssets, UserClients = userClients }; var observationEvents = GetObservationEventTradeList(req); if (observationEvents != null && observationEvents.rows.Count() > 0) { var Types = observationEvents.rows.Select(o => o.Type).Distinct(); var HasDone = date < SystemValueDate; if (Types.Any(o => o % 4 != 0)) { ret.Add("敲入敲出", HasDone); } if (Types.Any(o => o % 8 != 0 && o >= 4)) { HasDone = observationEvents.rows.Where(o => o.Type >= 4).Any(o => o.CouponPaidStatus == 1); ret.Add("票息", HasDone); } if (Types.Any(o => o >= 8)) { HasDone = observationEvents.rows.Where(o => o.Type >= 4).Where(o => o.trade.TradeType == "自定义交易").All(o => ConsTrade.TradeCompleteStatus.Contains(o.trade.TradeStatus)); ret.Add("自定义交易", HasDone); } } //除权除息 var dividendReq = new DividendTradeReq() { DividendDate = date.Value }; var dividendList = new DividendService(OptUser).QueryDividendTrade(dividendReq); if (dividendList != null && dividendList.Count() > 0) { ret.Add("除权除息", dividendList.All(o => o.DividendStatus)); } //互换 var swapTradeQuery = DbContext.trade.Where(o => o.TradeType == "收益互换" && o.ValidState != "InValid" && o.TradeDate <= date && o.ExerciseDate >= date); var swapTradeIds = swapTradeQuery.Select(o => o.id).ToList(); var swapTrades = DbContext.swap_position.Where(t => swapTradeIds.Contains(t.SwapTradeId)&&t.InterestDirection>0&&t.IsInitial&&!t.Invalid).ToList(); var hasNeedObserveSwapTrade = false; foreach (var item in swapTradeQuery) { var interests = swapTrades.Where(x => x.SwapTradeId == item.id).ToList(); if (interests.Any(s=>s.SwapIntervalList.Any(x=>x.Date==date))) { hasNeedObserveSwapTrade = true; break; } } if (hasNeedObserveSwapTrade) { if (date >= SystemValueDate) { ret.Add("收益互换", false); } else { ret.Add("收益互换", true); } } //目前只有互换有延期结算 var settledelayQuery = DbContext.trade.Where(t => !ConsTrade.UnConfirmTradeStatusList.Contains(t.TradeStatus) && t.ValidState != "InValid" && t.ExerciseDate <= date && t.SettlementFlag == 1 && (!(t.UnWindDate < date && ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus)))); if (settledelayQuery.Any()) { ret.Add("延期互换", true); } ret.Add("日期", date); return ret; } catch (Exception) { throw; } } /// /// /// /// 筛选条件 /// 当前交易日 private Expression> BuildPredicate(TdTradeQueryModel req, DateTime curTradingDate, bool showChildrenGroupTrade = false) { var predicate = PredicateBuilder.True(); if (req.UserAssets != null && req.UserClients != null) { predicate = predicate.And(a => req.UserAssets.Contains(a.AssetId) || req.UserClients.Contains(a.ClientId)); } switch (req.OtcTradeType) { case OtcTradeType.Forward: predicate = predicate.And(t => t.TradeType == "远期"); break; case OtcTradeType.EquitySwap: predicate = predicate.And(t => t.TradeType == "收益互换"); break; default: predicate = predicate.And(t => t.TradeType != "远期" && t.TradeType != "收益互换"); break; } if (!string.IsNullOrEmpty(req.TradeNumber)) { predicate = predicate.And(t => t.TradeNumber.Contains(req.TradeNumber)); } if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n))) { var types = req.TradeTypes.Where(n => !string.IsNullOrEmpty(n)).ToArray(); predicate = predicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType)); } //获取当日到期日数据 if (req.TabIndex == (int)TradeTabIndexEnum.今日到期) { //如果前一天是假日,要显示包含假日的交易 var preday = QdpCalendarHelper.GetNonHolidayDefore(curTradingDate.AddDays(-1)); var dateEnd = curTradingDate.AddDays(1); //存在当日到期的黑箱组合子交易对应的主交易id var parentTradeIds = DbContext.trade.Where(x => x.IsGroup == 2 && x.ExerciseDate > preday && x.ExerciseDate < dateEnd).Select(x => x.ParentTradeId).ToArray(); predicate = predicate.And(t => t.ExerciseDate > preday && t.ExerciseDate < dateEnd || (parentTradeIds.Contains(t.id) && (t.StructureType.Contains("累计") || t.StructureType.Contains("累购") || t.StructureType.Contains("累沽")))); var q = from tradeCash in DbContext.trade_cash where tradeCash.ValueDate > preday && tradeCash.ValueDate < dateEnd && tradeCash.ExerciseWay == TradeCashExerciseWayEnum.到期行权 && (tradeCash.Action == ClientCashInCashOut.系统操作_行权费 || tradeCash.Action == ClientCashInCashOut.系统操作_票息 || tradeCash.Action == ClientCashInCashOut.系统操作_互换) && tradeCash.ValidState != ConsGlobal.InValid && !tradeCash.IsDeleted select tradeCash; predicate = predicate.And(t => ConsTrade.NeedMarginTradeStatusList.Contains(t.TradeStatus) || q.Any(n => n.TradeId == t.id) || q.Any(n => n.ParentTradeId == t.id)); } //获取明日到期日数据 else if (req.TabIndex == (int)TradeTabIndexEnum.明日到期) { var nextDay = QdpCalendarHelper.GetNonHoliday(curTradingDate.AddDays(1)); predicate = predicate.And(t => t.ExerciseDate == nextDay); } else if (req.ExerciseDateStart != null || req.ExerciseDateEnd != null) { var dateStart = req.ExerciseDateStart ?? DateTime.MinValue; var dateEnd = req.ExerciseDateEnd ?? new DateTime(2099, 1, 1); if (req.OtcTradeType == OtcTradeType.EquitySwap) { predicate = predicate.And(t => t.ExerciseDate >= dateStart && t.ExerciseDate <= dateEnd); } else { predicate = predicate.And(t => string.IsNullOrEmpty(t.ExerciseMode) || t.ExerciseDate == null || (t.ExerciseMode == "European" && t.ExerciseDate >= dateStart && t.ExerciseDate <= dateEnd) || (t.ExerciseMode == "American" && ((t.StartDate >= dateStart && t.StartDate <= dateEnd) || (t.StartDate < dateStart && t.ExerciseDate >= dateStart))) ); } } //明日到期过滤已平仓,已到期,已执行数据 if (req.TabIndex == (int)TradeTabIndexEnum.明日到期) { var excludeStatusArr = new[] { ConsTrade.已平仓, ConsTrade.已到期, ConsTrade.已执行 }; predicate = predicate.And(t => !excludeStatusArr.Contains(t.TradeStatus)); } if (req.TabIndex == (int)TradeTabIndexEnum.今日收益结算) { predicate = predicate.And(t => t.ExerciseDate > curTradingDate); var q = from tradeCash in DbContext.trade_cash where tradeCash.ExerciseWay == TradeCashExerciseWayEnum.提前终止行权 && (tradeCash.Action == ClientCashInCashOut.系统操作_行权费 || tradeCash.Action == ClientCashInCashOut.系统操作_票息 || tradeCash.Action == ClientCashInCashOut.系统操作_互换) && tradeCash.ValidState != ConsGlobal.InValid && !tradeCash.IsDeleted && tradeCash.ValueDate == curTradingDate select tradeCash; predicate = predicate.And(t => q.Any(n => n.TradeId == t.id) || q.Any(n => n.ParentTradeId == t.id)); } //获取当日成交的数据 //当日成交包括操作日期和交易日为当前系统日期的数据 if (req.TabIndex == (int)TradeTabIndexEnum.今日成交) { var dateEnd = curTradingDate.AddDays(1); predicate = predicate.And(t => t.TradeDate >= curTradingDate && t.TradeDate < dateEnd); } else { if (req.TradeDateStart != null) { predicate = predicate.And(t => t.TradeDate >= req.TradeDateStart.Value); } if (req.TradeDateEnd != null) { predicate = predicate.And(t => t.TradeDate <= req.TradeDateEnd.Value); } } if (req.TabIndex == (int)TradeTabIndexEnum.今日敲出) { //敲出列表看子交易 predicate = predicate.And(t => !ConsTrade.TradeTypesForHedge.Contains(t.TradeType) && t.ValidState != "InValid" && t.TradeType != "结构化交易"); } else { predicate = predicate.And(t => !ConsTrade.TradeTypesForHedge.Contains(t.TradeType) && t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && (t.IsGroup != 2 || t.TradeType == "收益互换" && showChildrenGroupTrade)); } if (req.UnderlyingIds != null && req.UnderlyingIds.Any(n => n > 0)) { predicate = predicate.And(t => req.UnderlyingIds.Contains(t.UnderlyingId)); } if (req.VarietyId > 0) { var q = DbContext.underlying_manager.Where(n => n.UnderlyingTypeId == req.VarietyId); predicate = predicate.And(t => q.Any(n => n.id == t.UnderlyingId)); } if (req.TradeStatus != null && req.TradeStatus.Any(n => !string.IsNullOrEmpty(n))) { var statuses = req.TradeStatus.Where(n => !string.IsNullOrEmpty(n)).ToArray(); predicate = predicate.And(t => statuses.Contains(t.TradeStatus)); } if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n))) { var types = req.TradeTypes.Where(n => !string.IsNullOrEmpty(n)).ToArray(); predicate = predicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType)); } if (!string.IsNullOrEmpty(req.ExerciseMode)) { predicate = predicate.And(t => t.ExerciseMode == req.ExerciseMode); } if (!string.IsNullOrEmpty(req.BuySell)) { predicate = predicate.And(t => t.BuySell == req.BuySell); } if (!string.IsNullOrEmpty(req.OptionType)) { predicate = predicate.And(t => t.OptionType == req.OptionType); } if (req.AssetIds != null && req.AssetIds.Any()) { predicate = predicate.And(t => req.AssetIds.Contains(t.AssetId)); } if (req.ClientIds != null && req.ClientIds.Any()) { predicate = predicate.And(t => req.ClientIds.Contains(t.ClientId)); } if (req.TraderIds != null && req.TraderIds.Any()) { predicate = predicate.And(t => req.TraderIds.Contains(t.TraderId)); } return predicate; } /// /// /// /// 筛选条件 /// 当前交易日 private Expression> BuildObservationStatusPredicate(TdTradeQueryModel req, DateTime curTradingDate) { var predicate = PredicateBuilder.Create(t => t.ValidState != "InValid"); if (req.UserAssets != null && req.UserClients != null) { Expression> pre2 = null; if (req.UserAssets != null) { pre2 = PredicateBuilder.Create(t => req.UserAssets.Contains(t.AssetId)); } if (req.UserClients != null) { var pre3 = PredicateBuilder.Create(t => req.UserClients.Contains(t.ClientId)); pre2 = pre2 == null ? pre3 : pre2.Or(pre3); } predicate = predicate.And(pre2); } if (!string.IsNullOrEmpty(req.TradeNumber)) { predicate = predicate.And(t => t.TradeNumber.Contains(req.TradeNumber)); } if (req.TabIndex == (int)ObservationStatusTradeEnum.Barrier) { predicate = predicate.And(t => t.TradeType == "障碍期权"); } else if (req.TabIndex == (int)ObservationStatusTradeEnum.DoubleShark) { predicate = predicate.And(t => t.TradeType == "双鲨期权"); } else if (req.TabIndex == (int)ObservationStatusTradeEnum.AutoCall) { predicate = predicate.And(t => t.TradeType == "凤凰期权"); } else if (req.TabIndex == (int)ObservationStatusTradeEnum.SnowBall) { predicate = predicate.And(t => t.TradeType == "雪球期权"); } else if (req.TabIndex == (int)ObservationStatusTradeEnum.Binary) { predicate = predicate.And(t => t.TradeType == "二元期权"); } else if (req.TabIndex == (int)ObservationStatusTradeEnum.Accumulator) { predicate = predicate.And(t => t.TradeType == "累计期权"); } predicate = predicate.And(t => t.TradeDate <= curTradingDate); if (req.AssetIds != null && req.AssetIds.Any()) { predicate = predicate.And(t => req.AssetIds.Contains(t.AssetId)); } if (req.ClientIds != null && req.ClientIds.Any(n => n > 0)) { predicate = predicate.And(t => req.ClientIds.Contains(t.ClientId)); } if (req.UnderlyingIds != null && req.UnderlyingIds.Any(n => n > 0)) { predicate = predicate.And(t => req.UnderlyingIds.Contains(t.UnderlyingId)); } predicate = predicate.And(t => ConsTrade.TradeStatusAfterConfirmed.Contains(t.TradeStatus)); if (req.TradeStatus != null && req.TradeStatus.Any(n => !string.IsNullOrEmpty(n))) { var statuses = req.TradeStatus.Where(n => !string.IsNullOrEmpty(n)).ToArray(); predicate = predicate.And(t => statuses.Contains(t.TradeStatus)); } if (req.TradeDateStart != null) { predicate = predicate.And(t => t.TradeDate >= req.TradeDateStart.Value); } if (req.TradeDateEnd != null) { predicate = predicate.And(t => t.TradeDate <= req.TradeDateEnd.Value); } if (req.ExerciseDateStart != null) { predicate = predicate.And(t => t.ExerciseDate >= req.ExerciseDateStart.Value); } else { predicate = predicate.And(t => t.ExerciseDate >= curTradingDate); } if (req.ExerciseDateEnd != null) { predicate = predicate.And(t => t.ExerciseDate <= req.ExerciseDateEnd.Value); } return predicate; } private Expression> BuildObservationEventPredicte(TdTradeQueryModel req, DateTime curTradingDate) { if (req.TradeTypes == null || req.TradeTypes.All(n => string.IsNullOrEmpty(n))) { switch (req.TabIndex) { case 0: case 1: req.TradeTypes = ConsTrade.HasBarrierPriceOptions; break; case 2: req.TradeTypes = ConsTrade.HasCouponOptions; break; case 3: req.TradeTypes = new List() { "自定义交易" }; break; case 99: req.TradeTypes = ConsTrade.HasCouponOptions.Concat(new List() { "自定义交易" }); break; default: break; } } var predicate = PredicateBuilder.True(); if (req.TabIndex == 11) { predicate = predicate.And(t => !ConsTrade.UnConfirmTradeStatusList.Contains(t.TradeStatus) && t.ValidState != "InValid" && t.ExerciseDate <= curTradingDate && t.SettlementFlag == 1 && (!(t.UnWindDate < curTradingDate && ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus)))); } else { predicate = predicate.And(t => !ConsTrade.UnConfirmTradeStatusList.Contains(t.TradeStatus) && t.ValidState != "InValid" && t.TradeDate <= curTradingDate && t.ExerciseDate >= curTradingDate && (t.UnWindDate == null || t.UnWindDate >= curTradingDate || ConsTrade.LiveTradeStatusList.Contains(t.TradeStatus))); } if (req.UserAssets != null && req.UserClients != null) { predicate = predicate.And(t => req.UserAssets.Contains(t.AssetId) || req.UserClients.Contains(t.ClientId)); } if (req.UnderlyingIds != null && req.UnderlyingIds.Any(n => n > 0)) { predicate = predicate.And(t => req.UnderlyingIds.Contains(t.UnderlyingId)); } if (req.TradeStatus != null && req.TradeStatus.Any(n => !string.IsNullOrEmpty(n))) { var statuses = req.TradeStatus.Where(n => !string.IsNullOrEmpty(n)).ToArray(); predicate = predicate.And(t => statuses.Contains(t.TradeStatus)); } if (req.TradeTypes != null && req.TradeTypes.Any(n => !string.IsNullOrEmpty(n))) { var types = req.TradeTypes.Where(n => !string.IsNullOrEmpty(n)).ToArray(); predicate = predicate.And(t => types.Contains(t.TradeType) || types.Contains(t.StructureType)); } if (!string.IsNullOrEmpty(req.BuySell)) { predicate = predicate.And(t => t.BuySell == req.BuySell); } if (req.TradeDateStart != null) { predicate = predicate.And(t => t.TradeDate >= req.TradeDateStart.Value); } if (req.TradeDateEnd != null) { predicate = predicate.And(t => t.TradeDate <= req.TradeDateEnd.Value); } if (req.ExerciseDateStart != null) { predicate = predicate.And(t => t.ExerciseDate >= req.ExerciseDateStart.Value); } if (req.ExerciseDateEnd != null) { predicate = predicate.And(t => t.ExerciseDate <= req.ExerciseDateEnd.Value); } if (req.AssetIds != null && req.AssetIds.Any()) { predicate = predicate.And(t => req.AssetIds.Contains(t.AssetId)); } if (req.ClientIds != null && req.ClientIds.Any()) { predicate = predicate.And(t => req.ClientIds.Contains(t.ClientId)); } return predicate; } } /// /// 当日场外期权数量统计 /// public class TdTradesCountSum { /// /// 当日到期交易数量 /// public int TdExerciseCount { get; set; } /// /// 明日到期交易数量 /// public int TmExerciseCount { get; set; } /// /// 当日提前终止交易数量 /// public int TdEarlyStoppedCount { get; set; } /// /// 当日成交交易数量 /// public int TdCreatedCount { get; set; } /// /// 当日敲出交易数量 /// public int TdKnockedOutCount { get; set; } } public class TdPreEndTrade { public trade trade { get; set; } public TradeCashDto trade_cash { get; set; } /// /// 实现盈亏 /// public double? WinLoss { get { return -(trade_cash.Amount - (trade.TradePrice ?? 0) * (trade_cash.UnwindPercentRate ?? 0) * ((trade.BuySell == "卖出") ? -1 : 1)); } } } public class TdPreEndTrade2 { public int id { get; set; } public trade trade { get; set; } public TradeCashDto trade_cash { get; set; } public trade_cash_swap trade_cash_swap { get; set; } private double? winloss; /// /// 实现盈亏(客户角度观察) /// public double? WinLoss { get { if (winloss != null) { return winloss; } if (trade.TradeType == "远期") { return -(trade_cash.Amount + (trade.TradePrice ?? 0) * (trade_cash.UnwindPercentRate ?? 0)); } return -(trade_cash.Amount - (trade.TradePrice ?? 0) * (trade_cash.UnwindPercentRate ?? 0) * ((trade.BuySell == "卖出") ? -1 : 1)); } set { winloss = value; } } } public class TdObservationTrade { public int id { get { return trade.id; } } public string EncryptId { get { return trade.EncryptId; } } public trade trade { get; set; } //ObservationStatus konckOutDate konckInDate CouponDate BarrierLow BarrierHigh public string ObservationStatus { get; set; } public DateTime? konckInOutDate { get; set; } public double? BarrierLow { get; set; } public double? BarrierHigh { get; set; } public int Type { get; set; } /// /// 0:默认;1:已付票息2:将付票息 /// public int CouponPaidStatus { get; set; } } }