using BaseOUDAL; using System; using System.Data; using System.Diagnostics; using System.Linq.Expressions; using YLErp.BLL; using YLErp.BLL.EodSettlement; using YLErp.Commons; using YLErp.DBModels.Helpers; using YLErp.Helpers; using YLErp.Model; using YLErp.Modules.DataProviderModule; using YLErp.Modules.UnderlyingModule; using YLErp.Office.ExcelModule; using YLErp.QdpModule; using Path = System.IO.Path; namespace YLErp.Modules.EodModule { /// /// 日终持仓风险查询服务 /// public class EodPositionRisksQueryService : YLBaseService { public EodPositionRisksQueryService(OptUserInfo userInfo) : base(userInfo) { } #region----from tadeBLL---- //from tradecontroller.EodPositionRisksQuery public SearchListResult SearchList(EodPositionRisksReq req, bool isSwapTrades = false) { var voltype = req?.VolType ?? string.Empty; string ZeroDividendRateType = "分红率0"; if (req.DividendRateType == "采集") { voltype = ZeroDividendRateType; } switch (req?.EodSettlePriceMode) { case "结算价": if (voltype == "开仓") { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades, false); } else { return SearchEodPositionRisksList(req, isSwapTrades, false); } } else if (voltype == "对冲") { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades, false); } else { return SearchEodPositionRisksList(req, isSwapTrades, false); } } else if (voltype == "风控" || voltype == ZeroDividendRateType) { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades); } else { return SearchEodPositionRisksList(req, isSwapTrades); } } else { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades, false); } else { return SearchEodPositionRisksList(req, isSwapTrades, false); } } default: //不确定该逻辑的目的,但会影响到非远期期权查询到的数据,所以先注释掉; //if (req.TradeTypes != null && req.TradeTypes.Contains("远期")) //{ // result = new tradeBLL().SearchEodPositionRisksList(req); //} //if (req.TradeTypes != null && req.TradeTypes.Contains("远期")) //{ // result = new tradeBLL().SearchEodPositionRisksList(req); //} if (voltype == "开仓") { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades); } else { return SearchEodPositionRisksList(req, isSwapTrades); } } else if (voltype == "对冲") { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades); } else { return SearchEodPositionRisksList(req, isSwapTrades); } } else if (voltype == "风控" || voltype == ZeroDividendRateType) { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades); } else { return SearchEodPositionRisksList(req, isSwapTrades); } } else { if (req?.IsParentTrade == true) { return SearchEodOptionPositionRisksList(req, isSwapTrades); } else { return SearchEodPositionRisksList(req, isSwapTrades); } } } } public SearchListResult SearchEodOptionPositionRisksList(EodPositionRisksReq req , bool isSwapTrades, bool useClosePrice = true) where T1 : EodTradePosition where T2 : EodTradeRisk where T3 : EodPnl { var statusList = new List { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 }; if (req.needSettleData) { statusList = new List(); } var eodPredicate = BuildPredicateOfEodTrade(req, isSwapTrades); var tradePredicate = PredicateBuilder.Create(t => t.ValidState != "InValid" && (t.TradeType != "结构化交易" || t.IsGroup == 1) && t.IsGroup != 2); if (req.UserAssets != null && req.UserClients != null) { tradePredicate = tradePredicate.And(a => req.UserAssets.Contains(a.AssetId) || req.UserClients.Contains(a.ClientId)); } if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x))) { tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0)); } if (!string.IsNullOrWhiteSpace(req.TradeNumber)) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber)); } if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue) { var TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1); tradePredicate = tradePredicate.And(d => (d.SettlementDate ?? d.ExerciseDate) < TradeDateTemp); } if (req.SettlementDateStart != null && req.SettlementDateStart != DateTime.MinValue) { tradePredicate = tradePredicate.And(d => (d.SettlementDate ?? d.ExerciseDate) >= req.SettlementDateStart); } if (req.SettlementFlags != null && req.SettlementFlags.Any()) { tradePredicate = tradePredicate.And(d => req.SettlementFlags.Contains(d.SettlementFlag)); } if (!string.IsNullOrEmpty(req.GroupNames) && req.GroupNamesList != null && req.GroupNamesList.Count > 0) { var gname = req.GroupNamesList[0]; var groupNamePredicate = PredicateBuilder.Create(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname.ToString())); if (req.GroupNamesList.Count > 1) { for (int i = 1; i < req.GroupNamesList.Count; i++) { var gname1 = req.GroupNamesList[i]; groupNamePredicate = groupNamePredicate.Or(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname1.ToString())); } } tradePredicate = tradePredicate.And(groupNamePredicate); } if (req.TagIds != null && req.TagIds.Count > 0) { var tradeTagIdQuery = from tt in DbContext.trade_tag where req.TagIds.Contains(tt.TagId) select tt.TradeId; tradePredicate = tradePredicate.And(p => tradeTagIdQuery.Contains(p.id)); } var query = from eodTrade in DbContext.eod_trade.Where(eodPredicate) join trade in DbContext.trade.Where(tradePredicate) on eodTrade.TradeId equals trade.id join tr in DbContext.trade_contract_r.Where(O => O.Type == "交易确认书" && O.IsValid) on trade.id equals tr.TradeId into trs from tr in trs.DefaultIfEmpty() join eodPos in DbContext.Set().Where(O => O.ValueDate == req.ValueDate) on eodTrade.TradeId equals eodPos.TradeId into eodPoss from eodPos in eodPoss.DefaultIfEmpty() join eodRisk in DbContext.Set().Where(t => t.ValueDate == req.ValueDate) on eodTrade.TradeId equals eodRisk.TradeId into eodrisk_t from eodRisk in eodrisk_t.DefaultIfEmpty() join eodPnl in DbContext.Set().Where(O => O.ValueDate == req.ValueDate && O.TradeId > 0) on eodTrade.TradeId equals eodPnl.TradeId into eodPnls from eodPnl in eodPnls.DefaultIfEmpty() join tradespan in DbContext.trade_span.Where(O => O.ValueDate == req.ValueDate) on eodTrade.TradeId equals tradespan.TradeId into tradespans from tradespan in tradespans.DefaultIfEmpty() join assetUnit in DbContext.assetunit on trade.AssetId equals assetUnit.id into assetUnits from assetUnit in assetUnits.DefaultIfEmpty() join parentTrade in DbContext.trade.Where(tr => tr.ValidState != "InValid") on trade.ParentTradeId equals parentTrade.id into parentTrades from parentTrade in parentTrades.DefaultIfEmpty() join binary in DbContext.trade_binary_option on eodTrade.TradeId equals binary.TradeId into binary_t from binary in binary_t.DefaultIfEmpty() join asian in DbContext.trade_asian_option on eodTrade.TradeId equals asian.TradeId into asian_t from asian in asian_t.DefaultIfEmpty() join barrier in DbContext.trade_barrier_option on eodTrade.TradeId equals barrier.TradeId into barrier_t from barrier in barrier_t.DefaultIfEmpty() join risky in DbContext.trade_risky_option on eodPos.TradeId equals risky.TradeId into risky_t from risky in risky_t.DefaultIfEmpty() join accumulator in DbContext.trade_accumulator_option on eodTrade.TradeId equals accumulator.TradeId into accumulator_t from accumulator in accumulator_t.DefaultIfEmpty() join um in DbContext.underlying_manager on eodTrade.UnderlyingCode equals um.UnderlyingCode into um_t from um in um_t.DefaultIfEmpty() where !statusList.Contains(eodTrade.TradeStatus) && (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId)) && (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id)) select new EodPositionRisksDTO { PayoffType = (binary != null && trade.TradeType == "二元期权") ? binary.PayoffType : null, CashOrNothingAmount = (binary != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmount : null, CashOrNothingAmountRate = (binary != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmountRate : null, MonitorType = (binary != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? (binary.MonitorType ?? "否") : null, RebateType = (binary != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? binary.RebateType : null, StrikeType = (asian != null && trade.TradeType == "亚式期权") ? asian.StrikeType : null, AveragingPeriodStartDate = (asian != null && trade.TradeType == "亚式期权") ? asian.AveragingPeriodStartDate : null, PayoffType2 = (asian != null && trade.TradeType == "亚式期权") ? asian.PayoffType : null, ParticipationRate = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate1 : trade != null ? trade.ParticipationRate ?? 1 : 1, StrikeGearingFactor = (asian != null && trade.TradeType == "亚式期权") ? asian.StrikeGearingFactor : null, EnhancedPrice = (asian != null && trade.TradeType == "亚式期权") ? asian.EnhancedPrice : 0, BarrierType = (barrier != null && trade.TradeType == "障碍期权") ? barrier.BarrierType : null, Discrete = (barrier != null && trade.TradeType == "障碍期权") ? barrier.Discrete : null, BarrierPrice = (barrier != null && trade.TradeType == "障碍期权") ? barrier.BarrierPrice : null, UpperBarrierPrice = (barrier != null && trade.TradeType == "障碍期权" && barrier.BarrierType.Contains("双障碍")) ? barrier.UpperBarrierPrice : null, Rebate = (barrier != null && trade.TradeType == "障碍期权") ? barrier.Rebate : null, RebateRate = (barrier != null && trade.TradeType == "障碍期权") ? barrier.RebateRate : null, BarrierShift = (barrier != null && trade.TradeType == "障碍期权") ? barrier.BarrierShift : null, RebateType3 = (barrier != null && trade.TradeType == "障碍期权") ? barrier.RebateType : null, AccumulatorStructureTypeStr = (accumulator != null && trade.TradeType == "累计期权") ? accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented ? "三段式" : "标准" : null, GroupName = trade.GroupName, Strike2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike2 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike2 : null), Strike3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike3 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike3 : null), ParticipationRate2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate2 : null, ParticipationRate3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate3 : null, id = trade.id, InitMargin = trade.InitialMargin, OptionType = trade.OptionType, ClientName = trade.ClientName, TraderName = trade.TraderName, AssetBookName = assetUnit != null ? assetUnit.Name : null, CurrentVolatility = eodRisk.Vol, PositionPnl = eodPos != null ? eodPos.PositionPnL : 0,//浮动盈亏 RoundedPositionPnl = eodPos != null ? eodPos.RoundedPositionPnL : 0, PV = eodPos != null ? eodPos.Pv : 0, RoundedPV = eodPos != null ? eodPos.RoundedPv : 0, Vega = eodRisk.Vega, //实现盈亏 Theta = eodRisk.Theta, Rho = eodRisk.Rho, Delta = eodRisk.Delta, Gamma = eodRisk.Gamma, DeltaCash = eodRisk.DeltaCash, GammaCash = eodRisk.GammaCash, VegaCash = eodRisk.VegaCash, ExerciseDate = trade.ExerciseDate, ExerciseMode = trade.ExerciseMode, Notional = eodPos != null ? eodPos.Amount : 0, StockEqvNotionalMax = trade.StockEqvNotionalMax, OriginalStockEqvNotional = trade.OriginalStockEqvNotional, Strike = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike1 : trade != null ? trade.Strike : null, IsMoneynessOption = trade.IsMoneynessOption, ExchangeOptionCode = eodPos != null ? eodPos.ExchangeOptionCode : "", IsUsePremiumRate = trade.IsUsePremiumRate, PremiumRate = trade.PremiumRate, TradeDate = trade.TradeDate, ParentTradeNumber = parentTrade != null ? parentTrade.TradeNumber : trade.TradeNumber, ContractCode = tr.ContractCode, TradeNumber = trade.TradeNumber, ParentTradeId = trade.ParentTradeId, TradePrice = trade.TradePrice, BuySell = trade.BuySell, TradeSinglePrice = trade.TradeSinglePrice, TradeType = trade.TradeType, StructureType = trade.StructureType != "结构化交易" ? trade.StructureType : null, UnderlyingCode = eodTrade.UnderlyingCode, IsGroup = trade.IsGroup, TradeJson = eodTrade.TradeJson, Margin = eodPos != null ? eodPos.Margin : 0, Spv1 = tradespan.Spv1, Spv2 = tradespan.Spv2, Spv3 = tradespan.Spv3, Exposure = eodRisk.CreditExposure, RealizedPnl = eodPos != null ? eodPos.ClosedPnL : 0, PnLDelta = eodPnl.PnLDelta, PnLGamma = eodPnl.PnLGamma, PnLVega = eodPnl.PnLVega, PnLTheta = eodPnl.PnLTheta, PnLPsi = eodPnl.PnLPsi, dailyPnl = eodPos != null ? eodPos.DailyPnL : 0, HedgeUniqueCode = eodPos != null ? eodPos.HedgeUniqueCode : "", OriginalPrincipalSum = trade.OriginalPrincipalSum, SurvivingNominalPrincipal = trade.SpotPrice * eodPos.Amount, Comments = trade.Comments }; query = query.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber); var searchResult = query.ToSearchList(req, isWithOrder: true); var priceDict = new EodPriceProvider(req.ValueDate); var tcActions = new[] { ClientCashInCashOut.系统操作_平仓费, ClientCashInCashOut.系统操作_行权费,ClientCashInCashOut.系统操作_票息,ClientCashInCashOut.系统操作_互换,ClientCashInCashOut.人工操作_其他}; var underlyingCodes = searchResult.rows.Select(O => O.UnderlyingCode).Distinct().ToList(); var greeksHandleService = new GLMSGreeksHandleService(); greeksHandleService.InitData(req.ValueDate, underlyingCodes); foreach (var r in searchResult.rows) { var um = DataCacheProvider.GetUnderlyingDataSource().GetData(r.UnderlyingCode); if (um == null) { um = new underlying_manager(); } else { r.UnderlyingPrice = um.Price ?? 0; r.UnderlyingId = um.id; r.VarietyId = um.UnderlyingTypeId; r.UnderlyingAssetName = um.UnderlyingName; r.CountRatio = um.CountRatio; if (PS.Config.IsGuoJun) { r.UnderlyingVariety = UnderlyingHelper.GetUnderlyingVarietyCode(r.UnderlyingCode); } } //争取直接从eodrisk表取 r.UnderlyingPrice = priceDict.GetPrice(r.UnderlyingCode, useClosePrice ? r.trade?.SettlementType ?? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice); r.RiskFreeRate = r.trade?.NoRiskRate ?? valuedateBLL.RiskFreeRate / 100; r.DividendRate = r.trade?.DividendRate ?? r.RiskFreeRate; r.OriginalNotional = r.trade?.OriginalNotional; r.TradeOriginalAmount = r.OriginalNotional / um.CountRatio; r.TradeStatus = r.trade?.TradeStatus; r.StockEqvNotional = r.trade?.StockEqvNotional; r.InitialSpotPrice = r.trade?.SpotPrice; if (r.trade != null) { r.PosiInitMargin = r.InitMargin * r.trade.Notional / r.trade.OriginalNotional; } switch (r.TradeType) { case "雪球期权": r.KnockInOutStatus = r.trade?.trade_snowball.KnockInOutStatusCn; break; case "凤凰期权": r.KnockInOutStatus = r.trade?.trade_autocall.KnockInOutStatusCn; break; case "双鲨期权": r.KnockInOutStatus = r.trade?.trade_double_sharkfin_option.KnockInOutStatusCn; break; case "障碍期权": r.KnockInOutStatus = r.trade?.trade_barrier_option.KnockInOutStatusCn; break; case "气囊结构": r.KnockInOutStatus = r.trade?.trade_airbag.KnockInOutStatusCn; break; case "累计期权": r.Strike = r.trade?.Strike; var settleMode = DbContext.autocall_observation.Where(n => n.TradeId == r.id && n.EndDate <= req.ValueDate) .OrderByDescending(n => n.EndDate).Select(n => n.SettlementMode).FirstOrDefault(); r.KnockInOutStatus = settleMode == "敲出" ? "敲出" : "观察中"; break; } r.etcTradePrice = ConsTrade.TradeTypesForHedge.Contains(r.TradeType) ? r.TradePrice : r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional); if (r.id > 0) { if (r.trade != null) { r.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? r.RoundedPV : r.PV, r.Notional , PS.Config.ErpElement.IsPVIncludePrincipal ? r.trade.PrincipalSum() : 0, r.trade.BuySell, r.trade.TradeType, false); } if (r.trade != null) { r.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(r.trade.ClientId)?.Number; } if (r.trade != null && r.trade.IsGroup == 1) { var eodtrade = DbContext.eod_trade.Where(x => x.ValueDate == req.ValueDate && x.ParentTradeId == r.id && ConsTrade.LiveTradeStatusList.Contains(x.TradeStatus)).ToList(); r.etcTradePrice = eodtrade.Select(x => (x.trade.BuySell == "买入" ? -1 : 1) * x.trade.TradePrice * x.trade.StockEqvNotional / x.trade.OriginalStockEqvNotional).Sum(); } if (r.ParentTradeId > 0) { var childTrades = DbContext.trade.Where(x => x.ParentTradeId == r.ParentTradeId).OrderBy(x => x.TradeNumber).Select(x => x.id).ToList(); r.ChildLeg = (childTrades.IndexOf(r.id) + 1).ToString(); } } if (r.IsGroup == 1) { var childTradeIds = DbContext.trade.Where(y => y.ParentTradeId == r.id && y.ValidState != "InValid").Select(y => y.id).ToList(); var childTrades = DbContext.trade.Where(y => childTradeIds.Contains(y.id)).ToList(); var childTradeCashs = DbContext.trade_cash.Where(t => childTradeIds.Contains(t.TradeId) && t.ValidState != ConsGlobal.InValid && t.ValueDate <= req.ValueDate && !t.IsDeleted && tcActions.Contains(t.Action)).ToList(); var childEodPositions = DbContext.Set().Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList(); var eodTradeRisks = DbContext.Set().Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList(); var eodTradePnls = DbContext.Set().Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList(); var tradeSpans = DbContext.trade_span.Where(tr => tr.ValueDate == req.ValueDate && childTradeIds.Contains(tr.TradeId)).ToList(); r.PV = childEodPositions.Sum(y => y.Pv); r.RoundedPV = childEodPositions.Sum(y => y.RoundedPv); r.PositionPnl = childEodPositions.Sum(y => y.PositionPnL); r.RoundedPositionPnl = childEodPositions.Sum(y => y.RoundedPositionPnL); r.RealizedPnl = childTradeCashs.Sum(n => n.Amount + (n.Action == ClientCashInCashOut.系统操作_票息 ? 0 : (n.UnwindPercentRate == null ? 0 : n.UnwindPercentRate)) * (childTrades.FirstOrDefault(x => x.id == n.TradeId) == null || childTrades.First(x => x.id == n.TradeId).TradePrice == null ? 0 : childTrades.First(x => x.id == n.TradeId).TradePrice * ((childTrades.First(x => x.id == n.TradeId).BuySell == "卖出") ? 1 : -1))) ?? 0; r.Margin = childEodPositions.Sum(y => y.Margin); r.Delta = eodTradeRisks.Sum(y => y.Delta); r.Gamma = eodTradeRisks.Sum(y => y.Gamma); r.Vega = eodTradeRisks.Sum(y => y.Vega); r.Theta = eodTradeRisks.Sum(y => y.Theta); r.Rho = eodTradeRisks.Sum(y => y.Rho); r.Exposure = eodTradeRisks.Sum(y => y.CreditExposure); r.PnLDelta = eodTradePnls.Sum(y => y.PnLDelta); r.PnLGamma = eodTradePnls.Sum(y => y.PnLGamma); r.PnLVega = eodTradePnls.Sum(y => y.PnLVega); r.PnLTheta = eodTradePnls.Sum(y => y.PnLTheta); r.PnLPsi = eodTradePnls.Sum(y => y.PnLPsi); r.Spv1 = tradeSpans.Sum(y => y.Spv1); r.Spv2 = tradeSpans.Sum(y => y.Spv2); r.Spv3 = tradeSpans.Sum(y => y.Spv3); r.Notional = r.trade.Notional; r.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? r.RoundedPV : r.PV, r.Notional , PS.Config.ErpElement.IsPVIncludePrincipal ? r.trade.PrincipalSum() : 0, r.trade.BuySell, r.trade.TradeType, false); } if (um != null) { r.GammaLots = (r.Gamma ?? 0) / um.ContractSize; r.DeltaLots = (r.Delta ?? 0) / um.ContractSize; } r.Rho *= 100; greeksHandleService.Handle(r,um); if (r.trade == null) { r.TradeSinglePrice = r.etcTradePrice / r.TradeAmount; } } if (!isSwapTrades) { searchResult.Sum = new { dpnl = GetDPnL(req, DbContext) }; } return searchResult; } private Expression> BuildPredicateOfEodTrade(EodPositionRisksReq reqModel, bool isSwapTrades) { var predicate = PredicateBuilder.Create(t => t.ValueDate == reqModel.ValueDate); if (reqModel.UserAssets != null || reqModel.UserClients != null) { predicate = predicate.And(t => reqModel.UserAssets.Contains(t.AssetId) || reqModel.UserClients.Contains(t.ClientId)); } if (reqModel.ClientIds != null && reqModel.ClientIds.Any(x => x > 0)) { predicate = predicate.And(q => reqModel.ClientIds.Contains(q.ClientId)); } if (reqModel.BookIds.Any()) { predicate = predicate.And(q => reqModel.BookIds.Contains(q.AssetId)); } if (reqModel.TradeIds != null && reqModel.TradeIds.Any(x => x != 0)) { predicate = predicate.And(q => reqModel.TradeIds.Contains(q.TradeId) || reqModel.TradeIds.Contains(-q.id)); } reqModel.VarietyIds = reqModel.VarietyIds == null ? Enumerable.Empty() : reqModel.VarietyIds.Where(n => n > 0).ToArray(); reqModel.UnderlyingIds = reqModel.UnderlyingIds == null ? Enumerable.Empty() : reqModel.UnderlyingIds.Where(n => n > 0).ToArray(); reqModel.SettlementFlags = reqModel.SettlementFlags == null ? Enumerable.Empty() : reqModel.SettlementFlags.ToArray(); if (isSwapTrades) { predicate = predicate.And(q => q.TradeType == "收益互换"); } else { predicate = predicate.And(q => q.TradeType != "收益互换"); } return predicate; } public SearchListResult SearchEodPositionRisksListV2(EodPositionRisksReq req , bool isSwapTrades, bool useClosePrice = true) where T1 : EodTradePosition where T2 : EodTradeRisk where T3 : EodPnl { var statusList = new List { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 }; DateTime? TradeDateTemp = null; if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue) { TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1); } if (req.needSettleData) { statusList = new List(); } var eodPredicate = BuildPredicateOfEodTradePosition(req, isSwapTrades); var tradePredicate = PredicateBuilder.Create(t => t.ValidState != "InValid"); var exTradeTypes = ConsTrade.TradeTypesForHedge.AsEnumerable(); //场内交易类型 if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x))) { exTradeTypes = ConsTrade.TradeTypesForHedge.Intersect(req.TradeTypes).ToArray(); if (req.TradeTypes.Count() == 1 && req.TradeTypes.Contains("收益互换")) { tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType ?? d.TradeType) && d.IsGroup != 1); } else { tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0)); } } if (!string.IsNullOrWhiteSpace(req.TradeNumber)) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber)); } if (!string.IsNullOrEmpty(req.GroupNames) && req.GroupNamesList != null && req.GroupNamesList.Count > 0) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); var gname = req.GroupNamesList[0]; var groupNamePredicate = PredicateBuilder.Create(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname.ToString())); if (req.GroupNamesList.Count > 1) { for (int i = 1; i < req.GroupNamesList.Count; i++) { var gname1 = req.GroupNamesList[i]; groupNamePredicate = groupNamePredicate.Or(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname1.ToString())); } } tradePredicate = tradePredicate.And(groupNamePredicate); } using (var db = DbContextFactory.GetYLDbContext()) { var eodPos = db.Set().Where(eodPredicate).ToArray(); var tradeIds = eodPos.Select(O => O.TradeId); var hedgeCodes = eodPos.Where(O => !O.HedgeUniqueCode.IsNullOrWhiteSpace()).Select(O => O.HedgeUniqueCode); var bookIds = eodPos.Select(O => O.BookId); var umCodes = eodPos.Select(O => O.UnderlyingCode); var parentTradeIds = eodPos.Where(O => O.ParentTradeId > 0).Select(O => O.ParentTradeId); var trDict = db.trade_contract_r .Where(O => O.Type == "交易确认书" && O.IsValid && tradeIds.Contains(O.TradeId)).ToDictionary(O => O.TradeId, V => V.ContractCode); var eodRiskDict = db.Set() .Where(t => t.ValueDate == req.ValueDate && (tradeIds.Contains(t.TradeId) || hedgeCodes.Contains(t.HedgeUniqueCode + ""))) .GroupBy(O => O.TradeId + O.HedgeUniqueCode).ToDictionary(K => K.Key, V => V.FirstOrDefault()); var eodPnlDict = db.Set().Where(O => O.ValueDate == req.ValueDate && tradeIds.Contains(O.TradeId)) .GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var tradespanDict = db.trade_span.Where(O => O.ValueDate == req.ValueDate && tradeIds.Contains(O.TradeId)) .GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var assetUnitDict = DataCacheProvider.GetAssetUnitDataSource().AsQueryable(O => bookIds.Contains(O.id)).ToDictionary(K => K.id, V => V.Name); var eodTradeDict = db.eod_trade.Where(O => O.ValueDate == req.ValueDate && tradeIds.Contains(O.TradeId)) .GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var tradeDict = db.trade.Where(t => t.ValidState != "InValid" && t.TradeType != "结构化交易" && (tradeIds.Contains(t.id) || parentTradeIds.Contains(t.id))) .GroupBy(O => O.id).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var binaryDict = db.trade_binary_option.Where(O => tradeIds.Contains(O.TradeId)) .GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var asianDict = db.trade_asian_option.Where(O => tradeIds.Contains(O.TradeId)) .GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var barrierDict = db.trade_barrier_option.Where(O => tradeIds.Contains(O.TradeId)) .GroupBy(O => O.TradeId).ToDictionary(O => O.Key, V => V.FirstOrDefault()); var umDict = DataCacheProvider.GetUnderlyingDataSource().AsQueryable(O => umCodes.Contains(O.UnderlyingCode)).ToDictionary(K => K.UnderlyingCode, V => V); var tradeIdList = db.trade.Where(tradePredicate).Select(O => O.id); var priceDict = new EodPriceProvider(req.ValueDate); var list = new List(); foreach (var item in eodPos) { eodTradeDict.TryGetValue(item.TradeId, out var eodTrade); umDict.TryGetValue(item.UnderlyingCode, out var um); tradeDict.TryGetValue(item.TradeId, out var trade); //原Linq条件,满足取反条件则跳过; if (!((item.TradeId == 0 || eodTrade == null || !statusList.Contains(eodTrade.TradeStatus)) && (item.TradeId > 0 || exTradeTypes.Contains(item.TradeType)) && (item.TradeId < 1 || tradeIdList.Any(n => n == item.TradeId)) && (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId)) && (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id)) && (!req.SettlementFlags.Any() || trade != null && req.SettlementFlags.Contains(trade.SettlementFlag)) && (!TradeDateTemp.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) < TradeDateTemp) && (!req.SettlementDateStart.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) >= req.SettlementDateStart) || (!req.SettlementFlags.Any() && !TradeDateTemp.HasValue && !req.SettlementDateStart.HasValue && trade == null))) { continue; } tradeDict.TryGetValue(item.ParentTradeId, out var parentTrade); assetUnitDict.TryGetValue(item.BookId, out var assetUnitName); eodRiskDict.TryGetValue(item.TradeId + (item.HedgeUniqueCode ?? ""), out var eodRisk); trDict.TryGetValue(item.TradeId, out var trCode); tradespanDict.TryGetValue(item.TradeId, out var tradespan); eodPnlDict.TryGetValue(item.TradeId, out var eodPnl); var parentEodTradeList = eodTradeDict.Values.Where(O => O.ParentTradeId == item.ParentTradeId).ToArray(); var obj = new EodPositionRisksDTO(); if (trade != null) { if (trade?.TradeType == "二元期权" && binaryDict.TryGetValue(item.TradeId, out var binary)) { obj.PayoffType = binary.PayoffType; obj.CashOrNothingAmount = binary.CashOrNothingAmount; obj.CashOrNothingAmountRate = binary.CashOrNothingAmountRate; if (trade.ExerciseMode != "European") { obj.MonitorType = binary.MonitorType ?? "否"; obj.RebateType = binary.RebateType; } } if (trade?.TradeType == "亚式期权" && asianDict.TryGetValue(item.TradeId, out var asian)) { obj.StrikeType = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeType : null; obj.AveragingPeriodStartDate = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.AveragingPeriodStartDate : null; obj.PayoffType2 = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.PayoffType : null; obj.StrikeGearingFactor = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeGearingFactor : null; } if (trade?.TradeType == "障碍期权" && barrierDict.TryGetValue(item.TradeId, out var barrier)) { obj.BarrierType = barrier.BarrierType; obj.Discrete = barrier.Discrete; obj.BarrierPrice = barrier.BarrierPrice; obj.Rebate = barrier.Rebate; obj.RebateRate = barrier.RebateRate; obj.BarrierShift = barrier.BarrierShift; obj.RebateType3 = barrier.RebateType; if (barrier.BarrierType.Contains("双障碍")) { obj.UpperBarrierPrice = barrier.UpperBarrierPrice; } } obj.OptionType = trade.OptionType; obj.ClientName = trade.ClientName; obj.TraderName = trade.TraderName; } obj.ParticipationRate = trade?.ParticipationRate ?? 1; obj.GroupName = trade?.GroupName ?? ""; obj.id = trade?.id ?? -item.id; obj.AssetBookName = assetUnitName; obj.CurrentVolatility = eodRisk?.Vol; obj.Vega = eodRisk?.Vega; obj.Theta = eodRisk?.Theta; obj.Rho = eodRisk?.Rho; obj.Delta = eodRisk?.Delta; obj.Gamma = eodRisk?.Gamma; obj.DeltaCash = eodRisk?.DeltaCash; obj.GammaCash = eodRisk?.GammaCash; obj.VegaCash = eodRisk?.VegaCash; obj.Exposure = eodRisk?.CreditExposure; obj.PositionPnl = item.PositionPnL;//浮动盈亏 obj.RoundedPositionPnl = item.RoundedPositionPnL; obj.PV = item.Pv; obj.RoundedPV = item.RoundedPv; obj.ExerciseDate = trade?.ExerciseDate; obj.ExerciseMode = trade?.ExerciseMode; obj.SettlementDate = trade?.SettlementDate ?? trade?.ExerciseDate; obj.SettlementFlag = trade?.SettlementFlag ?? 0; obj.OriginalNotional = trade?.OriginalNotional ?? item.Amount; obj.Notional = item.Amount; obj.StockEqvNotionalMax = trade?.StockEqvNotionalMax; obj.OriginalStockEqvNotional = trade?.OriginalStockEqvNotional; obj.Strike = trade?.Strike; obj.IsMoneynessOption = trade?.IsMoneynessOption ?? ""; obj.ExchangeOptionCode = item.ExchangeOptionCode; obj.IsUsePremiumRate = trade?.IsUsePremiumRate; obj.PremiumRate = trade?.PremiumRate; obj.TradeDate = trade?.TradeDate; obj.ParentTradeNumber = parentTrade?.TradeNumber ?? trade?.TradeNumber; obj.ContractCode = trCode; obj.TradeNumber = trade?.TradeNumber; obj.ParentTradeId = trade?.ParentTradeId ?? 0; obj.TradePrice = trade?.TradePrice ?? item.Cost; obj.BuySell = ConsTrade.TradeTypesForHedge.Contains(item.TradeType) ? (item.Amount < 0 ? "空头开仓" : "多头开仓") : item.BuySell; obj.TradeSinglePrice = trade?.TradeSinglePrice ?? (item.Amount > 0 ? item.Cost / item.Amount : 0); obj.TradeType = item.TradeType; obj.StructureType = trade != null && trade.StructureType != "结构化交易" ? trade.StructureType : null; obj.UnderlyingCode = eodTrade?.UnderlyingCode ?? item.UnderlyingCode; obj.TradeJson = eodTrade?.TradeJson; obj.Margin = item.Margin; obj.Spv1 = tradespan?.Spv1; obj.Spv2 = tradespan?.Spv2; obj.Spv3 = tradespan?.Spv3; obj.RealizedPnl = item.ClosedPnL; //实现盈亏 obj.PnLDelta = eodPnl?.PnLDelta; obj.PnLGamma = eodPnl?.PnLGamma; obj.PnLVega = eodPnl?.PnLVega; obj.PnLTheta = eodPnl?.PnLTheta; obj.PnLPsi = eodPnl?.PnLPsi; obj.dailyPnl = item.DailyPnL; obj.HedgeUniqueCode = item.HedgeUniqueCode; obj.OriginalPrincipalSum = trade?.OriginalPrincipalSum; if (obj.TradeType == "场内期权") { var exoption = DataCacheProvider.GetExchangeListOptionDataSource().GetData(obj.ExchangeOptionCode); if (exoption != null) { obj.Strike = exoption.Strike; obj.ExerciseDate = exoption.MaturityDate; obj.OptionType = exoption.OptionType; } } else if (obj.id < 0 && !obj.Delta.HasValue) { obj.Delta = obj.Notional ?? 0; } if (um == null) { um = new underlying_manager(); } else { obj.UnderlyingPrice = um.Price ?? 0; obj.UnderlyingId = um.id; obj.VarietyId = um.UnderlyingTypeId; obj.UnderlyingAssetName = um.UnderlyingName; obj.CountRatio = um.CountRatio; if (PS.Config.IsGuoJun) { obj.UnderlyingVariety = UnderlyingHelper.GetUnderlyingVarietyCode(obj.UnderlyingCode); } } //争取直接从eodrisk表取 obj.UnderlyingPrice = priceDict.GetPrice(obj.UnderlyingCode, useClosePrice ? obj.trade?.SettlementType ?? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice); obj.RiskFreeRate = obj.trade?.NoRiskRate ?? valuedateBLL.RiskFreeRate / 100; obj.DividendRate = obj.trade?.DividendRate ?? obj.RiskFreeRate; obj.TradeStatus = obj.trade?.TradeStatus; obj.StockEqvNotional = obj.trade?.StockEqvNotional; //如果时场内期权交易,没有收盘eod_trade数据,那就保留eod_position的数据 if (obj.trade != null) { obj.OriginalNotional = obj.trade.OriginalNotional; } obj.InitialSpotPrice = obj.trade?.SpotPrice; switch (obj.TradeType) { case "雪球期权": obj.KnockInOutStatus = obj.trade?.trade_snowball.KnockInOutStatusCn; break; case "凤凰期权": obj.KnockInOutStatus = obj.trade?.trade_autocall.KnockInOutStatusCn; break; case "双鲨期权": obj.KnockInOutStatus = obj.trade?.trade_double_sharkfin_option.KnockInOutStatusCn; break; case "障碍期权": obj.KnockInOutStatus = obj.trade?.trade_barrier_option.KnockInOutStatusCn; break; case "气囊结构": obj.KnockInOutStatus = obj.trade?.trade_airbag.KnockInOutStatusCn; break; case "累计期权": obj.Strike = obj.trade?.Strike; var settleMode = db.autocall_observation.Where(n => n.TradeId == obj.id && n.EndDate <= req.ValueDate) .OrderByDescending(n => n.EndDate).Select(n => n.SettlementMode).FirstOrDefault(); obj.KnockInOutStatus = settleMode == "敲出" ? "敲出" : "观察中"; break; } if (um != null) { obj.GammaLots = (obj.Gamma ?? 0) / um.ContractSize; obj.DeltaLots = (obj.Delta ?? 0) / um.ContractSize; } obj.Rho *= 100; obj.CountRatio = um.CountRatio; obj.TradeOriginalAmount = obj.OriginalNotional / um.CountRatio; obj.etcTradePrice = ConsTrade.TradeTypesForHedge.Contains(obj.TradeType) ? obj.TradePrice : obj.TradePrice * (obj.trade == null ? obj.Notional / obj.OriginalNotional : obj.trade?.StockEqvNotional / obj.trade?.OriginalStockEqvNotional); if (obj.id > 0) { if (obj.trade != null) { obj.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? obj.RoundedPV : obj.PV, obj.Notional , PS.Config.ErpElement.IsPVIncludePrincipal ? obj.trade.PrincipalSum() : 0, obj.trade.BuySell, obj.trade.TradeType, false); } if (obj.trade != null) { obj.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(obj.trade.ClientId)?.Number; } if (obj.trade != null && obj.trade.IsGroup == 1 && parentEodTradeList != null) { obj.etcTradePrice = parentEodTradeList.Select(x => (x.trade.BuySell == "买入" ? -1 : 1) * x.trade.TradePrice * x.trade.StockEqvNotional / obj.trade.OriginalStockEqvNotional).Sum() ?? 0; } if (obj.ParentTradeId > 0 && parentEodTradeList != null) { obj.ChildLeg = (parentEodTradeList.Select(O => O.id).ToList().IndexOf(obj.id) + 1).ToString(); } } else { obj.SinglePV = obj.PV.HasValue && obj.Notional.HasValue && obj.Notional.Value != 0 ? Math.Abs(obj.PV.Value / obj.Notional.Value) : 0; if (obj.TradeType == "场内期权") { obj.OptionType = DataCacheProvider.GetExchangeListOptionDataSource().GetData(obj.ExchangeOptionCode).OptionType; } } list.Add(obj); } list = list.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber).ToList(); var searchResult = new SearchListResult(); searchResult.total = 1; searchResult.records = list.Count; searchResult.page = 1; searchResult.rows = list; if (!isSwapTrades) { searchResult.Sum = new { dpnl = GetDPnL(req, db) }; } return searchResult; } } public SearchListResult SearchEodPositionRisksList(EodPositionRisksReq req , bool isSwapTrades, bool useClosePrice = true) where T1 : EodTradePosition where T2 : EodTradeRisk where T3 : EodPnl { var statusList = new List { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 }; DateTime? TradeDateTemp = null; if (req.SettlementDateEnd != null && req.SettlementDateEnd != DateTime.MinValue) { TradeDateTemp = req.SettlementDateEnd.Value.AddDays(1); } if (req.needSettleData) { statusList = new List(); } var eodPredicate = BuildPredicateOfEodTradePosition(req, isSwapTrades); var tradePredicate = PredicateBuilder.Create(t => t.ValidState != "InValid"); var exTradeTypes = ConsTrade.TradeTypesForHedge.AsEnumerable(); //场内交易类型 if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x))) { exTradeTypes = ConsTrade.TradeTypesForHedge.Intersect(req.TradeTypes).ToArray(); if (req.TradeTypes.Count() == 1 && req.TradeTypes.Contains("收益互换")) { tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType ?? d.TradeType) && d.IsGroup != 1); } else { tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0)); } } if (!string.IsNullOrWhiteSpace(req.TradeNumber)) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber)); } if (!string.IsNullOrEmpty(req.GroupNames) && req.GroupNamesList != null && req.GroupNamesList.Count > 0) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); var gname = req.GroupNamesList[0]; var groupNamePredicate = PredicateBuilder.Create(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname.ToString())); if (req.GroupNamesList.Count > 1) { for (int i = 1; i < req.GroupNamesList.Count; i++) { var gname1 = req.GroupNamesList[i]; groupNamePredicate = groupNamePredicate.Or(t => !string.IsNullOrEmpty(t.GroupName) && t.GroupName.Contains(gname1.ToString())); } } tradePredicate = tradePredicate.And(groupNamePredicate); } if (req.TagIds != null && req.TagIds.Count > 0) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); var tradeTagIdQuery = from tt in DbContext.trade_tag where req.TagIds.Contains(tt.TagId) select tt.TradeId; tradePredicate = tradePredicate.And(p => tradeTagIdQuery.Contains(p.id)); } var query = from eodPos in DbContext.Set().Where(eodPredicate) join tr in DbContext.trade_contract_r.Where(O => O.Type == "交易确认书" && O.IsValid) on eodPos.TradeId equals tr.TradeId into trs from tr in trs.DefaultIfEmpty() join eodRisk in DbContext.Set().Where(t => t.ValueDate == req.ValueDate) on new { id = eodPos.TradeId, code = eodPos.HedgeUniqueCode + "" } equals new { id = eodRisk.TradeId, code = eodRisk.HedgeUniqueCode + "" } into eodrisk_t from eodRisk in eodrisk_t.DefaultIfEmpty() join eodPnl in DbContext.Set().Where(O => O.ValueDate == req.ValueDate && O.TradeId > 0) on eodPos.TradeId equals eodPnl.TradeId into eodPnls from eodPnl in eodPnls.DefaultIfEmpty() join tradespan in DbContext.trade_span.Where(O => O.ValueDate == req.ValueDate) on eodPos.TradeId equals tradespan.TradeId into tradespans from tradespan in tradespans.DefaultIfEmpty() join assetUnit in DbContext.assetunit on eodPos.BookId equals assetUnit.id into assetUnits from assetUnit in assetUnits.DefaultIfEmpty() join eodTrade in DbContext.eod_trade.Where(O => O.ValueDate == req.ValueDate) on eodPos.TradeId equals eodTrade.TradeId into eodTrades from eodTrade in eodTrades.DefaultIfEmpty() join trade in DbContext.trade.Where(t => t.ValidState != "InValid" && t.TradeType != "结构化交易") on eodPos.TradeId equals trade.id into trades from trade in trades.DefaultIfEmpty() join parentTrade in DbContext.trade.Where(tr => tr.ValidState != "InValid" && tr.TradeType == "结构化交易") on trade.ParentTradeId equals parentTrade.id into parentTrades from parentTrade in parentTrades.DefaultIfEmpty() join binary in DbContext.trade_binary_option on eodPos.TradeId equals binary.TradeId into binary_t from binary in binary_t.DefaultIfEmpty() join asian in DbContext.trade_asian_option on eodPos.TradeId equals asian.TradeId into asian_t from asian in asian_t.DefaultIfEmpty() join barrier in DbContext.trade_barrier_option on eodPos.TradeId equals barrier.TradeId into barrier_t from barrier in barrier_t.DefaultIfEmpty() join risky in DbContext.trade_risky_option on eodPos.TradeId equals risky.TradeId into risky_t from risky in risky_t.DefaultIfEmpty() join accumulator in DbContext.trade_accumulator_option on eodTrade.TradeId equals accumulator.TradeId into accumulator_t from accumulator in accumulator_t.DefaultIfEmpty() join um in DbContext.underlying_manager on eodPos.UnderlyingCode equals um.UnderlyingCode into um_t from um in um_t.DefaultIfEmpty() where (eodPos.TradeId == 0 || !statusList.Contains(eodTrade.TradeStatus)) && (eodPos.TradeId > 0 || exTradeTypes.Contains(eodPos.TradeType)) && (eodPos.TradeId < 1 || DbContext.trade.Where(n => n.id == eodPos.TradeId).Where(tradePredicate).Any()) && (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId)) && (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id)) // req.SettlementFlags.Any() && TradeDateTemp.HasValue && req.SettlementDateStart.HasValue 是场外期权的筛选条件 trade != null 会把场内交易过滤掉,所以三个筛选条件都没有的情况下要让 trade 可以 == null && ((!req.SettlementFlags.Any() || trade != null && req.SettlementFlags.Contains(trade.SettlementFlag)) && (!TradeDateTemp.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) < TradeDateTemp) && (!req.SettlementDateStart.HasValue || trade != null && (trade.SettlementDate ?? trade.ExerciseDate) >= req.SettlementDateStart) || (!req.SettlementFlags.Any() && !TradeDateTemp.HasValue && !req.SettlementDateStart.HasValue && trade == null)) select new EodPositionRisksDTO { PayoffType = (binary != null && trade != null && trade.TradeType == "二元期权") ? binary.PayoffType : null, CashOrNothingAmount = (binary != null && trade != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmount : null, CashOrNothingAmountRate = (binary != null && trade != null && trade.TradeType == "二元期权") ? binary.CashOrNothingAmountRate : null, MonitorType = (binary != null && trade != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? (binary.MonitorType ?? "否") : null, RebateType = (binary != null && trade != null && trade.TradeType == "二元期权" && trade.ExerciseMode != "European") ? binary.RebateType : null, StrikeType = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeType : null, AveragingPeriodStartDate = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.AveragingPeriodStartDate : null, PayoffType2 = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.PayoffType : null, ParticipationRate = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate1 : trade != null ? trade.ParticipationRate ?? 1 : 1, StrikeGearingFactor = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.StrikeGearingFactor : null, EnhancedPrice = (asian != null && trade != null && trade.TradeType == "亚式期权") ? asian.EnhancedPrice : 0, BarrierType = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.BarrierType : null, Discrete = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.Discrete : null, BarrierPrice = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.BarrierPrice : null, UpperBarrierPrice = (barrier != null && trade != null && trade.TradeType == "障碍期权" && barrier.BarrierType.Contains("双障碍")) ? barrier.UpperBarrierPrice : null, Rebate = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.Rebate : null, RebateRate = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.RebateRate : null, BarrierShift = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.BarrierShift : null, RebateType3 = (barrier != null && trade != null && trade.TradeType == "障碍期权") ? barrier.RebateType : null, AccumulatorStructureTypeStr = (accumulator != null && trade.TradeType == "累计期权") ? accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented ? "三段式" : "标准" : null, GroupName = trade != null ? trade.GroupName : "", Strike2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike2 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike2 : null), Strike3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike3 : ((accumulator != null && trade.TradeType == "累计期权" && accumulator.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) ? accumulator.Strike3 : null), ParticipationRate2 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate2 : null, ParticipationRate3 = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.ParticipationRate3 : null, id = trade != null ? trade.id : -eodPos.id, InitMargin = trade != null ? trade.InitialMargin : null, OptionType = trade != null ? trade.OptionType : null, ClientName = trade != null ? trade.ClientName : null, TraderName = trade != null ? trade.TraderName : null, AssetBookName = assetUnit != null ? assetUnit.Name : null, CurrentVolatility = eodRisk.Vol, PositionPnl = eodPos.PositionPnL,//浮动盈亏 RoundedPositionPnl = eodPos.RoundedPositionPnL, PV = eodPos.Pv, RoundedPV = eodPos.RoundedPv, Vega = eodRisk.Vega, Theta = eodRisk.Theta, Rho = eodRisk.Rho, Delta = eodRisk.Delta, Gamma = eodRisk.Gamma, DeltaCash = eodRisk.DeltaCash, GammaCash = eodRisk.GammaCash, VegaCash = eodRisk.VegaCash, ExerciseDate = trade != null ? trade.ExerciseDate : null, ExerciseMode = trade != null ? trade.ExerciseMode : null, SettlementDate = trade != null ? trade.SettlementDate ?? trade.ExerciseDate : null, SettlementFlag = trade != null ? trade.SettlementFlag : 0, OriginalNotional = trade != null ? trade.OriginalNotional : eodPos.Amount, Notional = eodPos.Amount, StockEqvNotionalMax = trade != null ? trade.StockEqvNotionalMax : null, OriginalStockEqvNotional = trade != null ? trade.OriginalStockEqvNotional : null, Strike = (risky != null && trade != null && trade.TradeType == "Risky期权") ? risky.Strike1 : trade != null ? trade.Strike : null, IsMoneynessOption = trade != null ? trade.IsMoneynessOption : "", ExchangeOptionCode = eodPos.ExchangeOptionCode, IsUsePremiumRate = trade != null ? trade.IsUsePremiumRate : null, PremiumRate = trade != null ? trade.PremiumRate : null, TradeDate = trade != null ? trade.TradeDate : null, ParentTradeNumber = parentTrade != null ? parentTrade.TradeNumber : (trade != null ? trade.TradeNumber : null), ContractCode = tr.ContractCode, TradeNumber = trade != null ? trade.TradeNumber : null, ParentTradeId = trade != null ? trade.ParentTradeId : 0, TradePrice = trade != null ? trade.TradePrice : eodPos.Cost, BuySell = ConsTrade.TradeTypesForHedge.Contains(eodPos.TradeType) ? (eodPos.Amount < 0 ? "空头开仓" : "多头开仓") : eodPos.BuySell, TradeSinglePrice = trade != null ? trade.TradeSinglePrice : eodPos.Amount != 0 ? eodPos.Cost / eodPos.Amount : 0, TradeType = eodPos.TradeType, StructureType = trade.TradeType == "自定义交易" ? trade.StructureType : trade.TradeType, UnderlyingCode = eodTrade != null ? eodTrade.UnderlyingCode : eodPos.UnderlyingCode, //UnderlyingPrice,UnderlyingId,VarietyId,UnderlyingAssetName TradeJson = eodTrade != null ? eodTrade.TradeJson : null, Margin = eodPos.Margin, Spv1 = tradespan.Spv1, Spv2 = tradespan.Spv2, Spv3 = tradespan.Spv3, Exposure = eodRisk.CreditExposure, RealizedPnl = eodPos.ClosedPnL, //实现盈亏 PnLDelta = eodPnl.PnLDelta, PnLGamma = eodPnl.PnLGamma, PnLVega = eodPnl.PnLVega, PnLTheta = eodPnl.PnLTheta, PnLPsi = eodPnl.PnLPsi, dailyPnl = eodPos.DailyPnL, HedgeUniqueCode = eodPos.HedgeUniqueCode, OriginalPrincipalSum = trade != null ? trade.OriginalPrincipalSum : null, SurvivingNominalPrincipal = trade.SpotPrice * eodPos.Amount, Comments = trade.Comments }; //if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x))) //{ // query = query.Where(x => req.TradeTypes.Contains(x.TradeType) || req.TradeTypes.Contains(x.StructureType)); //} query = query.OrderByDescending(O => O.id).ThenBy(O => O.ParentTradeNumber).ThenBy(O => O.TradeNumber); var searchResult = query.ToSearchList(req, isWithOrder: true); var priceDict = new EodPriceProvider(req.ValueDate); var parentTradeIds = searchResult.rows.Where(O => O.ParentTradeId > 0).Select(O => O.ParentTradeId); var parentTradeIdDict = DbContext.trade .Where(x => parentTradeIds.Contains(x.ParentTradeId)) .AsEnumerable() .GroupBy(O => O.ParentTradeId).ToDictionary( K => K.Key, V => V.OrderBy(x => x.TradeNumber).Select(x => x.id).ToList()); var groupTradeIds = searchResult.rows.Where(O => O.ParentTradeId > 0 && O.trade != null && O.trade.IsGroup == 1).Select(O => O.ParentTradeId).ToList(); var eodtradeDict = DbContext.eod_trade .Where(x => x.ValueDate == req.ValueDate && groupTradeIds.Contains(x.ParentTradeId) && ConsTrade.LiveTradeStatusList.Contains(x.TradeStatus)) .AsEnumerable() .GroupBy(O => O.ParentTradeId) .ToDictionary(K => K.Key, V => V.Select(O => new xodTradeBase() { TradeJson = O.TradeJson })); var underlyingCodes = searchResult.rows.Select(O => O.UnderlyingCode).Distinct().ToList(); var greeksHandleService = new GLMSGreeksHandleService(); greeksHandleService.InitData(req.ValueDate, underlyingCodes); foreach (var r in searchResult.rows) { if (r.TradeType == "场内期权") { var exoption = DataCacheProvider.GetExchangeListOptionDataSource().GetData(r.ExchangeOptionCode); if (exoption != null) { r.Strike = exoption.Strike; r.ExerciseDate = exoption.MaturityDate; r.OptionType = exoption.OptionType; } } else if (r.id < 0 && !r.Delta.HasValue) { r.Delta = r.Notional ?? 0; } var um = DataCacheProvider.GetUnderlyingDataSource().GetData(r.UnderlyingCode); if (um == null) { um = new underlying_manager(); } else { r.UnderlyingPrice = um.Price ?? 0; r.UnderlyingId = um.id; r.VarietyId = um.UnderlyingTypeId; r.UnderlyingAssetName = um.UnderlyingName; r.CountRatio = um.CountRatio; if (PS.Config.IsGuoJun) { r.UnderlyingVariety = UnderlyingHelper.GetUnderlyingVarietyCode(r.UnderlyingCode); } } //争取直接从eodrisk表取 r.UnderlyingPrice = priceDict.GetPrice(r.UnderlyingCode, useClosePrice ? r.trade?.SettlementType ?? SettlementTypeEnum.ClosePrice : SettlementTypeEnum.SettlePrice); r.RiskFreeRate = r.trade?.NoRiskRate ?? valuedateBLL.RiskFreeRate / 100; r.DividendRate = r.trade?.DividendRate ?? r.RiskFreeRate; r.TradeStatus = r.trade?.TradeStatus; r.StockEqvNotional = r.trade?.StockEqvNotional; //如果时场内期权交易,没有收盘eod_trade数据,那就保留eod_position的数据 if (r.trade != null) { r.OriginalNotional = r.trade.OriginalNotional; r.PosiInitMargin = r.InitMargin * r.trade.Notional / r.trade.OriginalNotional; } r.InitialSpotPrice = r.trade?.SpotPrice; switch (r.TradeType) { case "雪球期权": r.KnockInOutStatus = r.trade?.trade_snowball.KnockInOutStatusCn; break; case "凤凰期权": r.KnockInOutStatus = r.trade?.trade_autocall.KnockInOutStatusCn; break; case "双鲨期权": r.KnockInOutStatus = r.trade?.trade_double_sharkfin_option.KnockInOutStatusCn; break; case "障碍期权": r.KnockInOutStatus = r.trade?.trade_barrier_option.KnockInOutStatusCn; break; case "气囊结构": r.KnockInOutStatus = r.trade?.trade_airbag.KnockInOutStatusCn; break; case "累计期权": r.Strike = r.trade?.Strike; var settleMode = DbContext.autocall_observation.Where(n => n.TradeId == r.id && n.EndDate <= req.ValueDate) .OrderByDescending(n => n.EndDate).Select(n => n.SettlementMode).FirstOrDefault(); r.KnockInOutStatus = settleMode == "敲出" ? "敲出" : "观察中"; break; } if (um != null) { r.GammaLots = (r.Gamma ?? 0) / um.ContractSize; r.DeltaLots = (r.Delta ?? 0) / um.ContractSize; } r.Rho *= 100; greeksHandleService.Handle(r,um); r.CountRatio = um.CountRatio; r.TradeOriginalAmount = r.OriginalNotional / um.CountRatio; r.etcTradePrice = ConsTrade.TradeTypesForHedge.Contains(r.TradeType) ? r.TradePrice : r.TradePrice * (r.trade == null ? r.Notional / r.OriginalNotional : r.trade?.StockEqvNotional / r.trade?.OriginalStockEqvNotional); if (r.id > 0) { if (r.trade != null) { r.SinglePV = TradeHelper.GetTradeSinglePriceByTradePrice(PS.Config.IsPVRounded ? r.RoundedPV : r.PV, r.Notional , PS.Config.ErpElement.IsPVIncludePrincipal ? r.trade.PrincipalSum() : 0, r.trade.BuySell, r.trade.TradeType, false); } if (r.trade != null) { r.ClientNumber = DataCacheProvider.GetClientDataSource().GetData(r.trade.ClientId)?.Number; } if (r.trade != null && r.trade.IsGroup == 1 && eodtradeDict.TryGetValue(r.ParentTradeId, out var et)) { r.etcTradePrice = et.Select(x => (x.trade.BuySell == "买入" ? -1 : 1) * x.trade.TradePrice * x.trade.StockEqvNotional / r.trade.OriginalStockEqvNotional).Sum() ?? 0; } if (r.ParentTradeId > 0 && parentTradeIdDict.TryGetValue(r.ParentTradeId, out var legs)) { r.ChildLeg = (legs.IndexOf(r.id) + 1).ToString(); } } else { r.SinglePV = r.PV.HasValue && r.Notional.HasValue && r.Notional.Value != 0 ? Math.Abs(r.PV.Value / r.Notional.Value) : 0; if (r.TradeType == "场内期权") { r.OptionType = DataCacheProvider.GetExchangeListOptionDataSource().GetData(r.ExchangeOptionCode).OptionType; } } if (r.trade == null) { r.TradeSinglePrice = r.etcTradePrice / r.TradeAmount; } } if (!isSwapTrades) { searchResult.Sum = new { dpnl = GetDPnL(req, DbContext) }; } return searchResult; } //构建EodTradePositionBase对象查询预测 private Expression> BuildPredicateOfEodTradePosition(EodPositionRisksReq reqModel, bool isSwapTrades = false) { var predicate = PredicateBuilder.Create(t => t.ValueDate == reqModel.ValueDate && (reqModel.needSettleData || t.Amount != 0)); if (reqModel.UserAssets != null || reqModel.UserClients != null) { predicate = predicate.And(q => reqModel.UserAssets.Contains(q.BookId) || reqModel.UserClients.Contains(q.ClientId)); } if (reqModel.ClientIds != null && reqModel.ClientIds.Any(x => x > 0)) { predicate = predicate.And(q => reqModel.ClientIds.Contains(q.ClientId)); } if (reqModel.BookIds != null && reqModel.BookIds.Any()) { predicate = predicate.And(q => reqModel.BookIds.Contains(q.BookId)); } if (reqModel.TradeIds != null && reqModel.TradeIds.Any(x => x != 0)) { predicate = predicate.And(q => reqModel.TradeIds.Contains(q.TradeId) || reqModel.TradeIds.Contains(-q.id)); } if (isSwapTrades) { predicate = predicate.And(q => q.TradeType == "收益互换"); } else { predicate = predicate.And(q => q.TradeType != "收益互换"); } reqModel.VarietyIds = reqModel.VarietyIds == null ? Enumerable.Empty() : reqModel.VarietyIds.Where(n => n > 0).ToArray(); reqModel.UnderlyingIds = reqModel.UnderlyingIds == null ? Enumerable.Empty() : reqModel.UnderlyingIds.Where(n => n > 0).ToArray(); reqModel.SettlementFlags = reqModel.SettlementFlags == null ? Enumerable.Empty() : reqModel.SettlementFlags.ToArray(); return predicate; } #endregion /// /// 查询指定交易在eodTradeRisk相关表中的数据 /// /// /// /// /// 交易编号和交易Id的键值对 /// public List SearchEodRisk(string[] tradeNumbers, DateTime valueDate, out Dictionary tradeNumberDict) where T : EodTradeRisk { if (tradeNumbers == null || !tradeNumbers.Any(O => !string.IsNullOrWhiteSpace(O))) { throw new ServiceException($"“{nameof(tradeNumbers)}”不能为 null 或空白。"); } var numbers = tradeNumbers.Where(O => !string.IsNullOrWhiteSpace(O)); tradeNumberDict = DbContext.trade .Where(O => numbers.Contains(O.TradeNumber) && O.ValidState != "InValid") .Select(O => new { O.id, O.TradeNumber }) .ToDictionary(K => K.id, V => V.TradeNumber); var tradeIds = tradeNumberDict.Keys; return (from r in DbContext.Set() where r.ValueDate == valueDate && tradeIds.Contains(r.TradeId) select r).ToList(); } //每天盈亏dPnL = Theta + Old Vega + Psi + Old Delta + Old Gamma + New Gamma + New Delta + New Vega public double GetDPnL(EodPositionRisksReq req, YLContext db = null) where T1 : EodTradePosition where T2 : EodPnl { if (db == null) { db = DbContext; } var statusList = new List { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 }; var eodPredicate = BuildPredicateOfEodTradePosition(req, false); var tradePredicate = PredicateBuilder.Create(t => t.ValidState != "InValid"); var exTradeTypes = ConsTrade.TradeTypesForHedge.AsEnumerable(); //场内交易类型 if (req.TradeTypes != null && req.TradeTypes.Any(x => !string.IsNullOrWhiteSpace(x))) { exTradeTypes = ConsTrade.TradeTypesForHedge.Intersect(req.TradeTypes).ToArray(); tradePredicate = tradePredicate.And(d => req.TradeTypes.Contains(d.StructureType) || req.TradeTypes.Contains(d.TradeType) || (req.TradeTypes.Contains("黑箱结构") && d.IsGroup != 0)); } if (!string.IsNullOrWhiteSpace(req.TradeNumber)) { eodPredicate = eodPredicate.And(n => n.TradeId > 0); tradePredicate = tradePredicate.And(q => q.TradeNumber.Contains(req.TradeNumber)); } var query = from eodPos in db.Set().Where(eodPredicate) join eodPnl in db.Set().Where(O => O.ValueDate == req.ValueDate && O.TradeId > 0) on eodPos.TradeId equals eodPnl.TradeId join eodTrade in db.eod_trade.Where(O => O.ValueDate == req.ValueDate) on eodPos.TradeId equals eodTrade.TradeId into eodTrades from eodTrade in eodTrades.DefaultIfEmpty() join um in db.underlying_manager on eodPos.UnderlyingCode equals um.UnderlyingCode into um_t from um in um_t.DefaultIfEmpty() where (eodPos.TradeId == 0 || !statusList.Contains(eodTrade.TradeStatus)) && (eodPos.TradeId > 0 || exTradeTypes.Contains(eodPos.TradeType)) && (eodPos.TradeId < 1 || db.trade.Where(n => n.id == eodPos.TradeId).Where(tradePredicate).Any()) && (!req.VarietyIds.Any() || um != null && req.VarietyIds.Contains(um.UnderlyingTypeId)) && (!req.UnderlyingIds.Any() || um != null && req.UnderlyingIds.Contains(um.id)) select new { eodPnl.PnLDelta, eodPnl.PnLGamma, eodPnl.PnLVega, eodPnl.PnLTheta, eodPnl.PnLPsi }; var dpnl = query.Sum(n => (double?)(n.PnLDelta + n.PnLGamma + n.PnLVega + n.PnLTheta + n.PnLPsi)); return dpnl ?? 0; } /// /// from tradecontroller.DownloadEodPositionRisks /// public byte[] ExportEodPositionRisksToExcel_Swap(EodPositionRisksReq req) { if (req.TradeIds == null || !req.TradeIds.Any()) { req.page = 0; req.rows = 10000; } req.IsOnlyExport = true; req.TradeTypes = new List() { "收益互换" }; var sList = SearchList(req, true).rows; if (sList == null) { throw new ServiceException("没有可导出的数据"); } var isPvRounded = PS.Config.IsPVRounded; var results = new List>(sList.Count()); var tradeids = sList.Select(O => O.id).ToHashSet(); var parentTradeIds = sList.Select(x => x.trade?.ParentTradeId).ToHashSet(); var tradeSwaps = DbContext.trade_swap.Where(x => tradeids.Contains(x.TradeId)).ToDictionary(n => n.TradeId); var parentTrades = DbContext.trade.Where(x => parentTradeIds.Contains(x.id)).ToDictionary(n => n.id); foreach (var item in sList) { if (item.trade == null) { continue; } if (item.trade != null && tradeSwaps.TryGetValue(item.trade.id, out var swap)) { item.trade.trade_swap = swap; } if (parentTrades.TryGetValue(item.trade.ParentTradeId, out var parentTrade)) { item.ContractCode = parentTrade.TradeNumber; } var dic = new Dictionary(); if (string.IsNullOrWhiteSpace(item.UnderlyingCode)) { item.DeltaLots = 0; item.GammaLots = 0; } dic.Add("交易编号", item.ParentTradeNumber); dic.Add("确认书编号", item.ContractCode); dic.Add("交易对手方", item.ClientName); dic.Add("交易对手编号", item.ClientNumber); dic.Add("簿记账户", item.AssetBookName); dic.Add("成交日期", item.TradeDate.OtcFormatDate()); dic.Add("到期日期", item.ExerciseDate.OtcFormatDate()); dic.Add("结算日期", item.SettlementDate.OtcFormatDate()); dic.Add("是否延期结算", item.SettlementFlag == 1 ? "是" : "否"); dic.Add("结构类型", item.StructureType.TrimToNull() ?? item.TradeType); dic.Add("名义本金", item.StockEqvNotionalToShow.OtcFormat(OtcFormatFlag.StockEqvNotional)); var pv = Convert.ToDouble((isPvRounded ? item.RoundedPV : item.PV) ?? 0); dic.Add("存续市值", pv.OtcFormatMoney()); dic.Add("标的代码", item.UnderlyingCode); dic.Add("标的名称", item.UnderlyingAssetName); dic.Add("期初标的价格", item.InitialSpotPrice.OtcFormatUmPrice()); dic.Add("浮动盈亏", (isPvRounded ? item.RoundedPositionPnl : item.PositionPnl).OtcFormatMoney()); dic.Add("实现盈亏", item.RealizedPnl.OtcFormatMoney()); dic.Add("Delta", item.Delta.OtcFormat(OtcFormatFlag.greek)); dic.Add("Delta手数", OtcFormatExtensions.OtcFormat(item.DeltaLots, OtcFormatFlag.notional)); dic.Add("收取浮动收益", item.trade.trade_swap.IsGetFloatingProfit ? "是" : "否"); dic.Add("收取标的代码", item.trade.trade_swap.GetUnderlyingCode); dic.Add("收取标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.GetUnderlyingCode)?.UnderlyingName); dic.Add("收取多头空头", item.trade.trade_swap.GetLongShort); dic.Add("收取标的期初价格", item.trade.trade_swap.GetSpotPrice.OtcFormatUmPrice()); dic.Add("收取交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.GetTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.GetTradeAmount, OtcFormatFlag.notional)); dic.Add("收取交易费用", item.trade.trade_swap.GetTradePrice.OtcFormatMoney()); dic.Add("收取初始预付金率", item.trade.trade_swap.GetMarginRate.OtcFormatFlex(2, 2, percent: true)); var getCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.GetSwapTimeAndRate); var getSwapRates = getCustomizedResults.Item2; double? GetSwapRate = getSwapRates?.FirstOrDefault(); dic.Add("收取互换利率年化", GetSwapRate.OtcFormatPercent(4)); dic.Add("支付浮动收益", item.trade.trade_swap.IsPayFloatingProfit ? "是" : "否"); dic.Add("支付标的代码", item.trade.trade_swap.PayUnderlyingCode); dic.Add("支付标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.PayUnderlyingCode)?.UnderlyingName); dic.Add("支付多头空头", item.trade.trade_swap.PayLongShort); dic.Add("支付标的期初价格", item.trade.trade_swap.PaySpotPrice.OtcFormatUmPrice()); dic.Add("支付交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.PayTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.PayTradeAmount, OtcFormatFlag.notional)); dic.Add("支付交易费用", item.trade.trade_swap.PayTradePrice.OtcFormatMoney()); dic.Add("支付初始预付金率", item.trade.trade_swap.PayMarginRate.OtcFormatFlex(2, 2, percent: true)); var payCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.PaySwapTimeAndRate); var paySwapRates = payCustomizedResults.Item2; double? PaySwapRate = paySwapRates?.FirstOrDefault(); dic.Add("支付互换利率年化", PaySwapRate.OtcFormatPercent(4)); results.Add(dic); } var list2 = results.Select(n => new ExpandoDictionary(n)).ToArray(); var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/日终持仓风险_互换.xlsx"); return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = list2 }).GenerateBytes(); } public bool BatchDownloadEodPositionRisks_Swap(EodPositionRisksReq req) { req.IsOnlyExport = true; req.TradeTypes = new List() { "收益互换" }; //获取区间日期起始日期和结束日期(不包含结束日期所以日期加一) var dates = QdpCalendarHelper.AllBizDays(req.StartDate, req.ValueDate.AddDays(1)); //for循环根据日期期间生产多个表格 DateTime endetime = req.ValueDate; //路径名称和文档名 var minDate = dates.Min(); var maxDate = dates.Max(); var fileName = $"日终互换_{minDate:yyyy-MM-dd}-{maxDate:yyyy-MM-dd}.xlsx"; var extendParams = new DataSet(fileName); //定义容器集合实例化 List reqList = dates.Select(O => { var temp_req = req.Clone(); temp_req.ValueDate = O; return temp_req; }).ToList(); return ProgressHelper.Start(reqList, "ExportEodPositionRisksSwap", ExportEodPositionRisksToExcel_SwapTwo, GenerateFile, extendParams); } /// /// 互换日期区间导出 /// /// /// public string ExportEodPositionRisksToExcel_SwapTwo(EodPositionRisksReq req, object extends, ProgressInfo info) { info.ignoreIndex = false; if (!(extends is DataSet excelFile)) { return "参数错误"; } if (barTask == null) { barTask = Task.Run(() => { //var temp_req = req.Clone(); //temp_req.ValueDate = date; Debug.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff => ") + req.ValueDate.ToString("yyyy-MM-dd")); //获取所有的数据 var results = GetEodPositionRisksDataHandleS(req, true); //判断区间日期内是否存在数据 if (results == null || results.Count == 0) { return $"{req.ValueDate.ToString("yyyy-MM-dd")} 数据不存在,跳过"; } //结束日期为sheet命名 DataTable dt = new DataTable(req.ValueDate.ToString("yyyyMMdd")); dt.Columns.AddRange(results.First().Keys.Select(O => new DataColumn(O)).ToArray()); //循环所有数据的每个单元格数据到表格里面 for (int i = 0; i < results.Count; i++) { DataRow row = dt.NewRow(); foreach (var cell in results[i]) { row[cell.Key] = cell.Value; } dt.Rows.Add(row); } excelFile.Tables.Add(dt); return $"{req.ValueDate.ToString("yyyy-MM-dd")} 导出完成"; }); info.ignoreIndex = true; return $"正在导出 {req.ValueDate.ToString("yyyy-MM-dd")}"; } else { Task.WaitAll(barTask); var message = barTask.Result; barTask = null; return message; } } public List> GetEodPositionRisksDataHandleS(EodPositionRisksReq req, bool isUseemptydate = false) { if (req.TradeIds == null || !req.TradeIds.Any()) { req.page = 0; req.rows = 10000; } req.IsOnlyExport = true; req.TradeTypes = new List() { "收益互换" }; IEnumerable sList = null; sList = SearchList(req, true).rows; if (sList == null) { throw new ServiceException("没有可导出的数据"); } var isPvRounded = PS.Config.IsPVRounded; var results = new List>(sList.Count()); var tradeids = sList.Select(O => O.id).ToHashSet(); var parentTradeIds = sList.Select(x => x.trade?.ParentTradeId).ToHashSet(); Dictionary tradeSwaps = null; Dictionary parentTrades = null; using (var db = DbContextFactory.GetYLDbContext()) { tradeSwaps = db.trade_swap.Where(x => tradeids.Contains(x.TradeId)).ToDictionary(n => n.TradeId); parentTrades = db.trade.Where(x => parentTradeIds.Contains(x.id)).ToDictionary(n => n.id); } foreach (var item in sList) { if (item.trade == null) { continue; } if (item.trade != null && tradeSwaps != null && tradeSwaps.TryGetValue(item.trade.id, out var swap)) { item.trade.trade_swap = swap; } if (parentTrades != null && parentTrades.TryGetValue(item.trade.ParentTradeId, out var parentTrade)) { item.ContractCode = parentTrade.TradeNumber; } var dic = new Dictionary(); if (string.IsNullOrWhiteSpace(item.UnderlyingCode)) { item.DeltaLots = 0; item.GammaLots = 0; } dic.Add("交易编号", item.ParentTradeNumber); dic.Add("确认书编号", item.ContractCode); dic.Add("交易对手方", item.ClientName); dic.Add("交易对手编号", item.ClientNumber); dic.Add("簿记账户", item.AssetBookName); dic.Add("成交日期", item.TradeDate.OtcFormatDate()); dic.Add("到期日期", item.ExerciseDate.OtcFormatDate()); dic.Add("结算日期", item.SettlementDate.OtcFormatDate()); dic.Add("是否延期结算", item.SettlementFlag == 1 ? "是" : "否"); dic.Add("结构类型", item.StructureType.TrimToNull() ?? item.TradeType); dic.Add("名义本金", item.StockEqvNotionalToShow.OtcFormat(OtcFormatFlag.StockEqvNotional)); var pv = Convert.ToDouble((isPvRounded ? item.RoundedPV : item.PV) ?? 0); dic.Add("存续市值", pv.OtcFormatMoney()); dic.Add("标的代码", item.UnderlyingCode); dic.Add("标的名称", item.UnderlyingAssetName); dic.Add("期初标的价格", item.InitialSpotPrice.OtcFormatUmPrice()); dic.Add("浮动盈亏", (isPvRounded ? item.RoundedPositionPnl : item.PositionPnl).OtcFormatMoney()); dic.Add("实现盈亏", item.RealizedPnl.OtcFormatMoney()); dic.Add("Delta", item.Delta.OtcFormat(OtcFormatFlag.greek)); dic.Add("Delta手数", OtcFormatExtensions.OtcFormat(item.DeltaLots, OtcFormatFlag.notional)); dic.Add("收取浮动收益", item.trade.trade_swap.IsGetFloatingProfit ? "是" : "否"); dic.Add("收取标的代码", item.trade.trade_swap.GetUnderlyingCode); dic.Add("收取标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.GetUnderlyingCode)?.UnderlyingName); dic.Add("收取多头空头", item.trade.trade_swap.GetLongShort); dic.Add("收取标的期初价格", item.trade.trade_swap.GetSpotPrice.OtcFormatUmPrice()); dic.Add("收取交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.GetTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.GetTradeAmount, OtcFormatFlag.notional)); dic.Add("收取交易费用", item.trade.trade_swap.GetTradePrice.OtcFormatMoney()); dic.Add("收取初始预付金率", item.trade.trade_swap.GetMarginRate.OtcFormatFlex(2, 2, percent: true)); var getCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.GetSwapTimeAndRate); var getSwapRates = getCustomizedResults.Item2; double? GetSwapRate = getSwapRates?.FirstOrDefault(); dic.Add("收取互换利率年化", GetSwapRate.OtcFormatPercent(4)); dic.Add("支付浮动收益", item.trade.trade_swap.IsPayFloatingProfit ? "是" : "否"); dic.Add("支付标的代码", item.trade.trade_swap.PayUnderlyingCode); dic.Add("支付标的名称", DataCacheProvider.GetUnderlyingDataSource().GetData(item.trade.trade_swap.PayUnderlyingCode)?.UnderlyingName); dic.Add("支付多头空头", item.trade.trade_swap.PayLongShort); dic.Add("支付标的期初价格", item.trade.trade_swap.PaySpotPrice.OtcFormatUmPrice()); dic.Add("支付交易数量", OtcFormatExtensions.OtcFormat(PS.Config.IsUseDisplayNotional ? item.trade.trade_swap.PayTradeAmount * (item.trade.CountRatio ?? 1) : item.trade.trade_swap.PayTradeAmount, OtcFormatFlag.notional)); dic.Add("支付交易费用", item.trade.trade_swap.PayTradePrice.OtcFormatMoney()); dic.Add("支付初始预付金率", item.trade.trade_swap.PayMarginRate.OtcFormatFlex(2, 2, percent: true)); var payCustomizedResults = QdpHelper.ParseAutocallCustomizedInfo(item.trade.trade_swap.PaySwapTimeAndRate); var paySwapRates = payCustomizedResults.Item2; double? PaySwapRate = paySwapRates?.FirstOrDefault(); dic.Add("支付互换利率年化", PaySwapRate.OtcFormatPercent(4)); results.Add(dic); } if (results.Count == 0 && (isUseemptydate = true)) { var dic = new Dictionary(); dic.Add("交易编号", ""); dic.Add("确认书编号", ""); dic.Add("交易对手方", ""); dic.Add("交易对手编号", ""); dic.Add("簿记账户", ""); dic.Add("成交日期", ""); dic.Add("到期日期", ""); dic.Add("结算日期", ""); dic.Add("是否延期结算", ""); dic.Add("结构类型", ""); dic.Add("名义本金", ""); dic.Add("存续市值", ""); dic.Add("标的代码", ""); dic.Add("标的名称", ""); dic.Add("期初标的价格", ""); dic.Add("浮动盈亏", ""); dic.Add("实现盈亏", ""); dic.Add("Delta", ""); dic.Add("Delta手数", ""); dic.Add("收取浮动收益", ""); dic.Add("收取标的代码", ""); dic.Add("收取标的名称", ""); dic.Add("收取多头空头", ""); dic.Add("收取标的期初价格", ""); dic.Add("收取交易数量", ""); dic.Add("收取交易费用", ""); dic.Add("收取初始预付金率", ""); dic.Add("收取互换利率年化", ""); dic.Add("支付浮动收益", ""); dic.Add("支付标的代码", ""); dic.Add("支付标的名称", ""); dic.Add("支付多头空头", ""); dic.Add("支付标的期初价格", ""); dic.Add("支付交易数量", ""); dic.Add("支付交易费用", ""); dic.Add("支付初始预付金率", ""); dic.Add("支付互换利率年化", ""); results.Add(dic); } return results; } /// /// from tradecontroller.DownloadEodPositionRisks /// public byte[] ExportEodPositionRisksToExcel(EodPositionRisksReq req) { var results = GetEodPositionRisksDataHandle(req); var list2 = results.Select(n => new ExpandoDictionary(n)).ToArray(); var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/日终持仓风险_国联.xlsx"); if (PS.Config.ErpElement.NeedShowSpv) { templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/日终持仓风险-Spv_国联.xlsx"); } return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = list2 }).GenerateBytes(); } #region 日终持仓风险-期权区间 public bool BatchDownloadEodPositionRisks(EodPositionRisksReq req) { //获取区间日期起始日期和结束日期(不包含结束日期所以日期加一) var dates = QdpCalendarHelper.AllBizDays(req.StartDate, req.ValueDate.AddDays(1)); //for循环根据日期期间生产多个表格 DateTime endetime = req.ValueDate; //路径名称和文档名 var minDate = dates.Min(); var maxDate = dates.Max(); var fileName = $"日终_{minDate:yyyy-MM-dd}-{maxDate:yyyy-MM-dd}.xlsx"; var extendParams = new DataSet(fileName); //定义容器集合实例化 List reqList = dates.Select(O => { var temp_req = req.Clone(); temp_req.ValueDate = O; return temp_req; }).ToList(); return ProgressHelper.Start(reqList, "ExportEodPositionRisks", ExportEodPositionRisksToExcelTo, GenerateFile, extendParams); } private object GenerateFile(object extends) { if (!(extends is DataSet excelFile)) { return "参数错误"; } //用户路径 string path = "/App_Docs/Temp/"; path = OtcAppContext.MapPath(path); //判断路径是否为空 if (!Directory.Exists(path)) { Directory.CreateDirectory(path); } var filePath = Path.Combine(path, excelFile.DataSetName); new ExcelHelper().DataSetToExcel(excelFile, true, out var tempBuffer); File.WriteAllBytes(filePath, tempBuffer); return Path.Combine("/App_Docs/Temp/", excelFile.DataSetName); } private Task barTask = null; /// /// 日期区间导出 /// /// /// private string ExportEodPositionRisksToExcelTo(EodPositionRisksReq req, object extends, ProgressInfo info) { info.ignoreIndex = false; if (!(extends is DataSet excelFile)) { return "参数错误"; } if (barTask == null) { barTask = Task.Run(() => { //var temp_req = req.Clone(); //temp_req.ValueDate = date; Debug.WriteLine(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff => ") + req.ValueDate.ToString("yyyy-MM-dd")); //获取所有的数据 var results = GetEodPositionRisksDataHandle(req, true); //判断区间日期内是否存在数据 if (results == null || results.Count == 0) { return $"{req.ValueDate.ToString("yyyy-MM-dd")} 数据不存在,跳过"; } //结束日期为sheet命名 DataTable dt = new DataTable(req.ValueDate.ToString("yyyyMMdd")); dt.Columns.AddRange(results.First().Keys.Select(O => new DataColumn(O == "TraderName" ? "交易员" : O)).ToArray()); //循环所有数据的每个单元格数据到表格里面 for (int i = 0; i < results.Count; i++) { DataRow row = dt.NewRow(); foreach (var cell in results[i]) { //如果为tradenumber的时候该为交易员 if (cell.Key == "TraderName") { row["交易员"] = cell.Value; } else { row[cell.Key] = cell.Value; } } dt.Rows.Add(row); } excelFile.Tables.Add(dt); return $"{req.ValueDate.ToString("yyyy-MM-dd")} 导出完成"; }); info.ignoreIndex = true; return $"正在导出 {req.ValueDate.ToString("yyyy-MM-dd")}"; } else { Task.WaitAll(barTask); var message = barTask.Result; barTask = null; return message; } } public List> GetEodPositionRisksDataHandle(EodPositionRisksReq req, bool isUseemptydate = false) { if (req.TradeIds == null || !req.TradeIds.Any()) { req.page = 0; req.rows = 10000; } req.IsOnlyExport = true; IEnumerable sList = null; sList = SearchList(req).rows; if (sList == null) { throw new ServiceException("没有可导出的数据"); } var isPvRounded = PS.Config.IsPVRounded; var results = new List>(sList.Count()); foreach (var item in sList) { var dic = new Dictionary(); if (string.IsNullOrWhiteSpace(item.UnderlyingCode)) { item.DeltaLots = 0; item.GammaLots = 0; } dic.Add("交易编号", item.TradeNumber); dic.Add("分组名", item.GroupName); dic.Add("确认书编号", item.ContractCode); dic.Add("期权代码", item.ExchangeOptionCode); dic.Add("多腿编号", item.ChildLeg); dic.Add("浮动盈亏", (isPvRounded ? item.RoundedPositionPnl : item.PositionPnl).OtcFormatMoney()); dic.Add("实现盈亏", item.RealizedPnl.OtcFormatMoney()); dic.Add("TraderName", item.TraderName); dic.Add("当前波动率", item.CurrentVolatility.OtcFormat(OtcFormatFlag.premiumRateP)); dic.Add("Delta", OtcFormatExtensions.OtcFormat(item.Delta, OtcFormatFlag.greek)); dic.Add("Delta手数", OtcFormatExtensions.OtcFormat(item.DeltaLots, OtcFormatFlag.notional)); dic.Add("Gamma", OtcFormatExtensions.OtcFormat(item.Gamma, OtcFormatFlag.greek)); dic.Add("Gamma手数", OtcFormatExtensions.OtcFormat(item.GammaLots, OtcFormatFlag.notional)); dic.Add("Theta", OtcFormatExtensions.OtcFormat(item.Theta, OtcFormatFlag.greek)); dic.Add("Rho", OtcFormatExtensions.OtcFormat(item.Rho, OtcFormatFlag.greek)); dic.Add("Vega", OtcFormatExtensions.OtcFormat(item.Vega, OtcFormatFlag.greek)); dic.Add("到期日期", item.ExerciseDate.OtcFormatDate()); dic.Add("行权方式", TradeHelper.GetExerciseModeCn(item.ExerciseMode)); dic.Add("结构类型", item.StructureType.TrimToNull() ?? item.TradeType); dic.Add("观察状态", item.KnockInOutStatus); dic.Add("交易对手方", item.ClientName); dic.Add("交易对手编号", item.ClientNumber); dic.Add("簿记账户", item.AssetBookName); dic.Add("成交日期", item.TradeDate.OtcFormatDate()); dic.Add("看涨看跌", item.OptionType); dic.Add("买卖方向", item.BuySell); dic.Add("标的代码", item.UnderlyingCode); dic.Add("标的品种", item.UnderlyingVariety); dic.Add("标的名称", item.UnderlyingAssetName); dic.Add("期初标的价格", item.InitialSpotPrice.OtcFormatUmPrice()); dic.Add("保底收益总额", item.OriginalPrincipalSum.OtcFormatUmPrice()); if (item.TradeType == "自定义交易") { dic.Add("执行价格", string.Empty); } else { dic.Add("执行价格", item.Strike.OtcFormatUmPrice(item.IsMoneynessOption == "是")); } if (item.IsUsePremiumRate == true) { dic.Add("权利金成交", item.PremiumRate.OtcFormat(OtcFormatFlag.premiumRateP)); } else { dic.Add("权利金成交", (item.TradeSinglePrice ?? 0).OtcFormat(OtcFormatFlag.tradeSinglePrice)); } var tradeOriginalAmount = PS.Config.IsUseDisplayNotional ? Math.Abs((item.TradeOriginalAmount ?? 0) * (item.CountRatio ?? 1)) : Math.Abs(item.TradeOriginalAmount ?? 0); var strTradeOriginalAmount = tradeOriginalAmount.OtcFormatNotional(); dic.Add("有效成交数量", strTradeOriginalAmount); if (item.trade != null) { strTradeOriginalAmount = Math.Abs(CalculationModule.TradeCalcHelper.GetTradeAmountV(item.trade, tradeOriginalAmount, 1)).OtcFormatNotional(); } dic.Add("成交数量", strTradeOriginalAmount); var tradeDirection = item.BuySell == "买入" || item.BuySell == "多头开仓" || item.BuySell == "空头开仓" ? -1 : 1; dic.Add("成交金额", (item.TradePrice * tradeDirection).OtcFormatMoney()); dic.Add("存续成本", (item.IsGroup == 1 ? item.etcTradePrice : item.etcTradePrice * tradeDirection).OtcFormatMoney()); dic.Add("名义本金", item.StockEqvNotionalToShow.OtcFormat(OtcFormatFlag.StockEqvNotional)); dic.Add("存续名义本金", item.SurvivingNominalPrincipal.OtcFormat(OtcFormatFlag.StockEqvNotional)); dic.Add("最新标的价格", item.UnderlyingPrice.OtcFormatUmPrice()); dic.Add("无风险利率", item.RiskFreeRate.OtcFormatFlex(2, 2, percent: true)); dic.Add("分红率", item.DividendRate.OtcFormatFlex(2, 2, percent: true)); if (item.IsUsePremiumRate == true) { var dd = TradeHelper.GetPremiumRateByTradeSinglePrice(item.SinglePV, item.InitialSpotPrice); dic.Add("权利金存续", dd.OtcFormat(OtcFormatFlag.premiumRateP)); } else { dic.Add("权利金存续", item.SinglePV.HasValue ? Convert.ToDouble(item.SinglePV.Value).OtcFormat(OtcFormatFlag.tradePrice) : ""); } var tradeAmount = PS.Config.IsUseDisplayNotional ? Math.Abs((item.TradeAmount * (item.CountRatio ?? 1)) ?? 0) : Math.Abs(item.TradeAmount ?? 0); var strTradeAmount = tradeAmount.OtcFormatNotional(); dic.Add("有效存续数量", strTradeAmount); if (item.trade != null) { strTradeAmount = Math.Abs(CalculationModule.TradeCalcHelper.GetTradeAmountV(item.trade, tradeAmount, 1)).OtcFormatNotional(); } dic.Add("存续数量", strTradeAmount); var pv = Convert.ToDouble((isPvRounded ? item.RoundedPV : item.PV) ?? 0); dic.Add("存续市值", pv.OtcFormatMoney()); dic.Add("维持预付金", item.Margin.OtcFormatMoney()); dic.Add("信用风险敞口", item.Exposure.OtcFormatMoney()); if (PS.Config.IsGuoJun) { dic.Add("持仓初始预付金", (item.PosiInitMargin ?? 0).OtcFormatMoney()); } #region 奇异期权导出列(二元/亚式/单障碍/Risky) //二元 dic.Add("二元类型", item.PayoffType); if (item.IsUsePremiumRate == true) { dic.Add("二元_补偿金额", item.CashOrNothingAmountRate.OtcFormat(OtcFormatFlag.premiumRateP)); } else { dic.Add("二元_补偿金额", item.CashOrNothingAmount.OtcFormat(OtcFormatFlag.tradeSinglePrice)); } dic.Add("是否离散观察", item.IsDiscreteMonitored); dic.Add("补偿方式", TradeHelper.GetRebateTypeCn(item.RebateType ?? item.RebateType3)); var IsMoneynessOption = item.IsMoneynessOption == "是"; //亚式 dic.Add("执行价类型", TradeHelper.GetAsianStrikeTypeCn(item.StrikeType)); dic.Add("均价起算日", item.AveragingPeriodStartDate.OtcFormatDate()); dic.Add("均价起算方式", TradeHelper.GetAsianPayoffTypeCn(item.PayoffType2)); dic.Add("参与率", item.ParticipationRate.OtcFormatPercent()); dic.Add("杠杆率", item.StrikeGearingFactor.OtcFormatPercent()); if (item.TradeType == "亚式期权" && item.PayoffType2 == "EnhancedArithmeticAverage" && item.StrikeType != "Floating") { dic.Add("增强价格", item.EnhancedPrice.OtcFormatUmPrice(IsMoneynessOption)); } else { dic.Add("增强价格", ""); } //障碍 dic.Add("障碍类型", item.BarrierType); dic.Add("观察类型", item.Discrete); dic.Add("障碍价格", item.BarrierPrice.OtcFormatUmPrice(IsMoneynessOption)); dic.Add("高障碍价格", item.UpperBarrierPrice.OtcFormatUmPrice(IsMoneynessOption)); if (item.IsUsePremiumRate == true) { dic.Add("补偿金额", item.RebateRate.OtcFormat(OtcFormatFlag.premiumRateP)); } else { dic.Add("补偿金额", item.Rebate.OtcFormat(OtcFormatFlag.tradeSinglePrice)); } dic.Add("障碍偏移", item.BarrierShift?.ToString("F2")); dic.Add("补偿支付", TradeHelper.GetRebateTypeCn(item.RebateType ?? item.RebateType3)); //Risky dic.Add("参与率2", item.ParticipationRate2.OtcFormatPercent()); dic.Add("参与率3", item.ParticipationRate3.OtcFormatPercent()); //Risky、累计三段式 dic.Add("执行价格2", item.Strike2.OtcFormatUmPrice(item.IsMoneynessOption == "是")); dic.Add("执行价格3", item.Strike3.OtcFormatUmPrice(item.IsMoneynessOption == "是")); #endregion dic.Add("dPnLDelta", item.PnLDelta.OtcFormat(OtcFormatFlag.greek)); dic.Add("dPnLGamma", item.PnLGamma.OtcFormat(OtcFormatFlag.greek)); dic.Add("dPnLVega", item.PnLVega.OtcFormat(OtcFormatFlag.greek)); dic.Add("dPnLTheta", item.PnLTheta.OtcFormat(OtcFormatFlag.greek)); dic.Add("dPnLPsi", item.PnLPsi.OtcFormat(OtcFormatFlag.greek)); if (PS.Config.ErpElement.NeedShowSpv) { dic.Add("Spv1", item.PnLDelta.OtcFormat(OtcFormatFlag.greek)); dic.Add("Spv2", item.PnLDelta.OtcFormat(OtcFormatFlag.greek)); dic.Add("Spv3", item.PnLDelta.OtcFormat(OtcFormatFlag.greek)); } if (PS.Config.Company == Configuration.CompanyEnum.国联) { dic.Add("Delta_r", OtcFormatExtensions.OtcFormat(item.Delta_r, OtcFormatFlag.greek)); dic.Add("Delta_r_1bp", OtcFormatExtensions.OtcFormat(item.Delta_r_1bp, OtcFormatFlag.greek)); dic.Add("Dv01", OtcFormatExtensions.OtcFormat(item.Dv01, OtcFormatFlag.greek)); dic.Add("Gamma_r", OtcFormatExtensions.OtcFormat(item.Gamma_r, OtcFormatFlag.greek)); dic.Add("Gamma_r_1bp", OtcFormatExtensions.OtcFormat(item.Gamma_r_1bp, OtcFormatFlag.greek)); dic.Add("Vega_r", OtcFormatExtensions.OtcFormat(item.Vega_r, OtcFormatFlag.greek)); dic.Add("Vega_r_1bp", OtcFormatExtensions.OtcFormat(item.Vega_r_1bp, OtcFormatFlag.greek)); dic.Add("Vega_1bp", OtcFormatExtensions.OtcFormat(item.Vega_1bp, OtcFormatFlag.greek)); } dic.Add("备注", item.Comments); results.Add(dic); } if (isUseemptydate && results.Count == 0) { var dic = new Dictionary(); dic.Add("交易编号", ""); dic.Add("分组名", ""); dic.Add("确认书编号", ""); dic.Add("期权代码", ""); dic.Add("多腿编号", ""); dic.Add("浮动盈亏", ""); dic.Add("实现盈亏", ""); dic.Add("TraderName", ""); dic.Add("当前波动率", ""); dic.Add("Delta", ""); dic.Add("Delta手数", ""); dic.Add("Gamma", ""); dic.Add("Gamma手数", ""); dic.Add("Theta", ""); dic.Add("Rho", ""); dic.Add("Vega", ""); dic.Add("到期日期", ""); dic.Add("行权方式", ""); dic.Add("结构类型", ""); dic.Add("观察状态", ""); dic.Add("交易对手方", ""); dic.Add("交易对手编号", ""); dic.Add("簿记账户", ""); dic.Add("成交日期", ""); dic.Add("看涨看跌", ""); dic.Add("买卖方向", ""); dic.Add("标的代码", ""); dic.Add("标的品种", ""); dic.Add("标的名称", ""); dic.Add("期初标的价格", ""); dic.Add("保底收益总额", ""); dic.Add("执行价格", ""); dic.Add("权利金成交", ""); dic.Add("有效成交数量", ""); dic.Add("成交数量", ""); dic.Add("成交金额", ""); dic.Add("存续成本", ""); dic.Add("名义本金", ""); dic.Add("最新标的价格", ""); dic.Add("无风险利率", ""); dic.Add("分红率", ""); dic.Add("权利金存续", ""); dic.Add("有效存续数量", ""); dic.Add("存续数量", ""); dic.Add("存续市值", ""); dic.Add("维持预付金", ""); dic.Add("信用风险敞口", ""); if (PS.Config.IsGuoJun) { dic.Add("持仓初始预付金", ""); } #region 奇异期权导出列(二元/亚式/单障碍) //二元 dic.Add("二元类型", ""); dic.Add("二元_补偿金额", ""); dic.Add("是否离散观察", ""); dic.Add("补偿方式", ""); //亚式 dic.Add("执行价类型", ""); dic.Add("均价起算日", ""); dic.Add("均价起算方式", ""); dic.Add("参与率", ""); dic.Add("杠杆率", ""); //障碍 dic.Add("障碍类型", ""); dic.Add("观察类型", ""); dic.Add("障碍价格", ""); dic.Add("高障碍价格", ""); dic.Add("补偿金额", ""); dic.Add("障碍偏移", ""); dic.Add("补偿支付", ""); //累计 dic.Add("执行价格2", ""); dic.Add("执行价格3", ""); #endregion dic.Add("dPnLDelta", ""); dic.Add("dPnLGamma", ""); dic.Add("dPnLVega", ""); dic.Add("dPnLTheta", ""); dic.Add("dPnLPsi", ""); if (PS.Config.ErpElement.NeedShowSpv) { dic.Add("Spv1", ""); dic.Add("Spv2", ""); dic.Add("Spv3", ""); } if (PS.Config.Company == Configuration.CompanyEnum.国联) { dic.Add("Delta_r", ""); dic.Add("Delta_r_1bp", ""); dic.Add("Dv01", ""); dic.Add("Gamma_r", ""); dic.Add("Gamma_r_1bp", ""); dic.Add("Vega_r", ""); dic.Add("Vega_r_1bp", ""); dic.Add("Vega_1bp", ""); } results.Add(dic); } return results; } #endregion public byte[] ExportEodRiskReport(EodPositionRisksReq req, double todayHedgeCashInOut) { try { #region 准备数据 var sList = SearchList(req).rows; if (sList == null) { throw new ServiceException("没有可导出的数据"); } var tradeParentIds = sList.Where(o => o.ParentTradeId > 0).Select(o => o.ParentTradeId).Distinct().ToList(); var count = sList.Where(o => o.ParentTradeId == 0 && !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Count() + tradeParentIds.Count(); var results = new List>(sList.Count()); var tradeIds = sList.Select(o => o.id); var beforeDate = QdpCalendarHelper.GetNonHolidayDefore(req.ValueDate.AddDays(-1)); var riskQuery = DbContext.eod_trade_risk_hedgevol.Where(o => tradeIds.Contains(o.TradeId) && o.ValueDate == beforeDate); var riskQueryDic = riskQuery.ToDictionary(o => o.TradeId, o => OtcFormatExtensions.OtcFormatValue(o.Delta, 2)); var dayUnwindTradeQuery = DbContext.trade_cash.Where(o => (o.Action == "系统操作-平仓费" || o.Action == "系统操作-行权费" || (o.Action == "系统操作-票息" && o.IsLastAction == true)) && o.ValueDate == req.ValueDate && o.ValidState != "InVaild" && !o.IsDeleted); var groups = dayUnwindTradeQuery.AsEnumerable().GroupBy(o => o.TradeId).ToList(); var dayUnwindPercentDic = groups.ToDictionary(o => o.Key, o => o.Sum(x => x.UnwindPercentRate)); var priceDict = new EodPriceProvider(beforeDate, true); //var totalPnl = sList.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Sum(o => o.dailyPnl); //var totalProfit = sList.Sum(o => (riskQueryDic.ContainsKey(o.id) ? (double)riskQueryDic[o.id] : 0) * (o.UnderlyingPrice - priceDict.GetPrice(o.UnderlyingCode))); double dayUnwindValue = 0; req.VolType = "对冲"; var sList2 = SearchList(req).rows; //var totalPnl2 = 0.0; var startPv = 0.0; var PVSum = 0.0; var dailyPnlSum = 0.0; var profitSum = 0.0; var calcProfitSum = 0.0; var DeltaRateSum = 0.0; var DeltaSum = 0.0; var GammaSum = 0.0; var VegaSum = 0.0; var DeltaCashSum = 0.0; var GammaCashSum = 0.0; var VegaCashSum = 0.0; var StockEqvNotionalToShowSum = 0.0; var TradePriceSum = 0.0; var i = 1; var tcActions = new[] { ClientCashInCashOut.系统操作_平仓费, ClientCashInCashOut.系统操作_行权费,ClientCashInCashOut.系统操作_票息,ClientCashInCashOut.系统操作_互换,ClientCashInCashOut.人工操作_其他}; var statusList = new List { ConsTrade.已到期, ConsTrade.已执行, ConsTrade.已平仓 }; var beforeEodMeta = DbContext.EodMeta.FirstOrDefault(o => o.ValueDate == beforeDate && o.MetaKey == EodMeta.UFX_FundSummary); var todayEodMeta = DbContext.EodMeta.FirstOrDefault(o => o.ValueDate == req.ValueDate && o.MetaKey == EodMeta.UFX_FundSummary); var beforeMeta = new UFX_FundSummary(); var todayMeta = new UFX_FundSummary(); if (beforeEodMeta != null) { beforeMeta = JsonHelper.Deserialize(beforeEodMeta.MetaValue); } if (todayEodMeta != null) { todayMeta = JsonHelper.Deserialize(todayEodMeta.MetaValue); } var HedgeMarkingCash = todayMeta.HedgeMarkingCash; var beforeHedgeMarkingCash = beforeMeta.HedgeMarkingCash; var todayHedgeMarkingPro = HedgeMarkingCash - beforeHedgeMarkingCash - todayHedgeCashInOut; todayHedgeMarkingPro = OtcFormatExtensions.OtcFormatValue(todayHedgeMarkingPro, 2); var todayPositionQuery = DbContext.eod_trade_position.Where(o => o.ValueDate == req.ValueDate && o.TradeType != "收益互换").ToList(); var todayHedgeClosePnlSum = todayPositionQuery.Any() ? todayPositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.ClosedPnL).Sum() : 0; //var todayHedgePositionPnlSum = todayPositionQuery.Any() ? todayPositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.PositionPnL).Sum() : 0; //var todayDailyPnlSum = todayPositionQuery.Any() ? todayPositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.DailyPnL).Sum() : 0; var todayPV = todayPositionQuery.Any() ? todayPositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.Pv).Sum() : 0; var ids = todayPositionQuery.Select(x => x.TradeId); var todayTrades = DbContext.eod_trade.Where(o => o.ValueDate == req.ValueDate && ids.Contains(o.TradeId)).ToList().Select(o => o.trade); var NotSettledIds = todayTrades.Where(o => !statusList.Contains(o.TradeStatus) && o.IsGroup != 2).Select(o => o.id); //var totalProfit2 = sList2.Sum( // o => OtcFormatExtensions.OtcFormatValue( // (riskQueryDic.ContainsKey(o.id) && NotSettledIds.Contains(o.id) ? (double)riskQueryDic[o.id] : 0) // * (o.UnderlyingPrice - priceDict.GetPrice(o.UnderlyingCode, SettlementTypeEnum.ClosePrice)) // , 2)); var todayPositonPnl = todayPositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Sum(o => o.PositionPnL); var todayRealizedPnl = 0.0; var todayCashAmount = 0.0; foreach (var r in todayTrades) { if (statusList.Contains(r.TradeStatus)) { continue; } var tradePrice = (r.TradePrice ?? 0) * ((r.BuySell == "卖出") ? 1 : -1); var cashQuery = DbContext.trade_cash.Where(t => t.TradeId == r.id && t.ValidState != ConsGlobal.InValid && t.ValueDate <= req.ValueDate && !t.IsDeleted && tcActions.Contains(t.Action)); var tradeRealizedPnl = cashQuery.Any() ? cashQuery .Sum(n => n.Amount + (n.Action == ClientCashInCashOut.系统操作_票息 ? 0 : n.UnwindPercentRate) * tradePrice) ?? 0 : 0; var tradeCashAmount = cashQuery.Any() ? cashQuery .Sum(n => n.Amount) : 0; todayRealizedPnl += tradeRealizedPnl; todayCashAmount += tradeCashAmount; } var beforePositionQuery = DbContext.eod_trade_position.Where(o => o.ValueDate == beforeDate && o.TradeType != "收益互换").ToList(); var beforeHedgeClosePnlSum = beforePositionQuery.Any() ? beforePositionQuery.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.ClosedPnL).Sum() : 0; var beforePV = beforePositionQuery.Any() ? beforePositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.Pv).Sum() : 0; ids = beforePositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(x => x.TradeId); var beforeTrades = DbContext.eod_trade.Where(o => o.ValueDate == beforeDate && ids.Contains(o.TradeId)).ToList().Select(o => o.trade); var beforeRealizedPnl = 0.0; foreach (var r in beforeTrades) { var tradePrice = (r.TradePrice ?? 0) * ((r.BuySell == "卖出") ? 1 : -1); var cashQuery = DbContext.trade_cash.Where(t => t.TradeId == r.id && t.ValidState != ConsGlobal.InValid && t.ValueDate <= beforeDate && !t.IsDeleted && tcActions.Contains(t.Action)); var tradeRealizedPnl = cashQuery.Any() ? cashQuery .Sum(n => n.Amount + (n.Action == ClientCashInCashOut.系统操作_票息 ? 0 : n.UnwindPercentRate) * tradePrice) ?? 0 : 0; beforeRealizedPnl += tradeRealizedPnl; } var parentTrades = DbContext.trade.Where(o => tradeParentIds.Contains(o.id)).ToList(); var dayIncreaseValue = (sList.Where(o => o.TradeDate == req.ValueDate && o.ParentTradeId == 0).Any() ? sList.Where(o => o.TradeDate == req.ValueDate && o.ParentTradeId == 0).Sum(o => o.OriginalStockEqvNotional ?? 0) : 0) + (parentTrades.Where(o => o.TradeDate == req.ValueDate).Any() ? parentTrades.Where(o => o.TradeDate == req.ValueDate).Sum(o => o.OriginalStockEqvNotional ?? 0) : 0); dayIncreaseValue = OtcFormatExtensions.OtcFormatValue(dayIncreaseValue, 2); //非结构化交易的先算上 var todayDayHoldValue = (todayTrades.Where(o => o.ParentTradeId == 0).Any() ? todayTrades.Where(o => o.ParentTradeId == 0).Sum(o => o.StockEqvNotional) : 0); var hedges = new HashSet(); //var hedgeList = sList.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)); var hedgeList2 = sList2.Where(o => ConsTrade.TradeTypesForHedge.Contains(o.TradeType)); #endregion //LogFactory.GetLogger("调试").Debug(sList.ToJson()); //LogFactory.GetLogger("调试").Debug(sList2.ToJson()); #region sheet var parentEodList = DbContext.eod_trade.Where(o => o.ValueDate == req.ValueDate && tradeParentIds.Contains(o.TradeId)).ToList(); foreach (var item in sList) { var IsHedge = false; var item2 = sList2.FirstOrDefault(o => o.id == item.id); if (ConsTrade.TradeTypesForHedge.Contains(item.TradeType)) { item2 = sList2.FirstOrDefault(o => o.HedgeUniqueCode == item.HedgeUniqueCode); IsHedge = true; } var IsSettled = false; var eod = todayTrades.Where(o => (o.id == item.id) && o.ParentTradeId == 0).FirstOrDefault(); var parentEod = item.ParentTradeId > 0 ? parentEodList.Where(O => O.TradeId == item.ParentTradeId).FirstOrDefault() : null; if (eod != null) { IsSettled = !IsHedge && statusList.Contains(eod.TradeStatus); //存续统计减掉已了结的 count -= IsSettled ? 1 : 0; } else if (parentEod != null) { IsSettled = !IsHedge && statusList.Contains(parentEod.TradeStatus) && tradeParentIds.Contains(item.ParentTradeId); //存续统计减掉已了结的 count -= IsSettled ? 1 : 0; } if (item2 == null) { throw new ServiceException($"对冲波动率收盘数据与持仓波动率数据不匹配!({item.id}--{item.HedgeUniqueCode})"); } var StockEqvNotionalToShow = item.StockEqvNotionalToShow; var beforeDelta = riskQueryDic.ContainsKey(item.id) ? (double)riskQueryDic[item.id] : 0; if (item.ParentTradeId > 0) { if (tradeParentIds.Contains(item.ParentTradeId)) { var parentTrade = parentTrades.FirstOrDefault(o => o.id == item.ParentTradeId); var isgroup = parentTrade.IsGroup == 1; var legs = sList.Where(o => o.ParentTradeId == item.ParentTradeId); var legs2 = sList2.Where(o => o.ParentTradeId == item.ParentTradeId); var eods = todayTrades.Where(o => o.ParentTradeId == item.ParentTradeId); if (legs.Count() != legs2.Count()) { throw new ServiceException($"对冲波动率收盘数据与持仓波动率数据不匹配![{item.id}--{item.HedgeUniqueCode}]"); } var childIds = legs.Select(o => o.id); beforeDelta = riskQueryDic.Where(o => childIds.Contains(o.Key)).Sum(o => o.Value); //结构化交易[非分组]加腿里的较大值 if (isgroup) { //startPv = parentTrade.TradePrice ?? 0; if (parentEod != null) { var eodtrade = parentEod.trade; todayDayHoldValue += eodtrade.StockEqvNotional; } if (dayUnwindPercentDic.TryGetValue(item.ParentTradeId, out var rate)) { dayUnwindValue += (rate ?? 0) * (parentTrade.OriginalStockEqvNotional ?? 0); } } else { //结构化交易[非分组]加腿里的较大值 var pairs = eods.Select(o => new KeyValuePair(o.id, o.StockEqvNotional)); var maxTradeId = pairs.OrderByDescending(x => x.Value).FirstOrDefault().Key; todayDayHoldValue += pairs.Max(o => o.Value); if (dayUnwindPercentDic.TryGetValue(maxTradeId, out var rate)) { dayUnwindValue += (rate ?? 0) * (item.OriginalStockEqvNotional ?? 0); } } item.ClientName = parentTrade.ClientName; item.TraderName = parentTrade.TraderName; //item.TradePrice = parentTrade.TradePrice; item.TradeType = string.IsNullOrWhiteSpace(parentTrade.StructureType) ? parentTrade.TradeType : parentTrade.StructureType; item.TradeDate = parentTrade.TradeDate; item.ExerciseDate = parentTrade.ExerciseDate; item.UnderlyingAssetName = parentTrade.UnderlyingAssetName; item.UnderlyingCode = parentTrade.UnderlyingCode; StockEqvNotionalToShow = parentTrade.OriginalStockEqvNotional; startPv = legs.Sum(o => (o.BuySell == "买入" || o.BuySell == "多头开仓" || o.BuySell == "空头平仓" ? 1 : -1) * (o.TradePrice ?? 0)); item.PV = legs.Sum(o => o.PV); item.RoundedPV = legs.Sum(o => o.RoundedPV); item.BuySell = parentTrade.BuySell; item2.DeltaCash = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.DeltaCash ?? 0, 2)); item2.GammaCash = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.GammaCash ?? 0, 2)); item2.VegaCash = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.VegaCash ?? 0, 2)); item2.Delta = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.Delta ?? 0, 2)); item2.Gamma = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.Gamma ?? 0, 2)); item2.Vega = legs2.Sum(o => OtcFormatExtensions.OtcFormatValue(o.Vega ?? 0, 2)); tradeParentIds.Remove(item.ParentTradeId); } else { continue; } } else { if (dayUnwindPercentDic.TryGetValue(item.id, out var rate)) { dayUnwindValue += (rate ?? 0) * (item.OriginalStockEqvNotional ?? 0); } startPv = (item.BuySell == "买入" || item.BuySell == "多头开仓" || item.BuySell == "空头平仓" ? 1 : -1) * (item.TradePrice ?? 0); } StockEqvNotionalToShow = OtcFormatExtensions.OtcFormatValue(StockEqvNotionalToShow ?? 0, 2); item2.DeltaCash = OtcFormatExtensions.OtcFormatValue(item2.DeltaCash ?? 0, 2); item2.GammaCash = OtcFormatExtensions.OtcFormatValue(item2.GammaCash ?? 0, 2); item2.VegaCash = OtcFormatExtensions.OtcFormatValue(item2.VegaCash ?? 0, 2); item2.Delta = OtcFormatExtensions.OtcFormatValue(item2.Delta ?? 0, 2); item2.Gamma = OtcFormatExtensions.OtcFormatValue(item2.Gamma ?? 0, 2); item2.Vega = OtcFormatExtensions.OtcFormatValue(item2.Vega ?? 0, 2); if (IsHedge) { //合计 var hedgeCodes = item.HedgeUniqueCode.Split('_'); var hedgeCode = hedgeCodes[0] + hedgeCodes[1] + hedgeCodes[3]; if (hedges.Contains(hedgeCode)) { continue; } else { hedges.Add(hedgeCode); //var SameUnderlyingHedges = hedgeList.Where(o => o.AssetBookName == item.AssetBookName // && o.TradeType == item.TradeType && (o.UnderlyingCode == item.UnderlyingCode || (o.TradeType == "场内期权" && o.ExchangeOptionCode == item.ExchangeOptionCode))).ToList(); var SameUnderlyingHedges2 = hedgeList2.Where(o => o.AssetBookName == item.AssetBookName && o.TradeType == item.TradeType && ((o.TradeType != "场内期权" && o.UnderlyingCode == item.UnderlyingCode) || (o.TradeType == "场内期权" && o.ExchangeOptionCode == item.ExchangeOptionCode))).ToList(); item2.DeltaCash = SameUnderlyingHedges2.Sum(o => o.DeltaCash); item.Notional = SameUnderlyingHedges2.Sum(o => o.Notional); } item2.DeltaCash = OtcFormatExtensions.OtcFormatValue(item2.DeltaCash ?? 0, 2); DeltaCashSum += item2.DeltaCash ?? 0; //DeltaCashSum += item2.DeltaCash ?? 0; var um = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode); var dic = new Dictionary { { "序号", '-' }, { "交易对手名称", um.MarketName }, { "起始日期", "-" }, { "终止日期", (item.ExerciseDate ?? um.MaturityDate).OtcFormatDate() }, { "标的证券", item.UnderlyingAssetName }, { "标的代码", item.UnderlyingCode }, { "合约本金规模", item.Notional / (um.ContractSize == 0 ? 1 : um.ContractSize) + "手" }, { "期初期权价值", "-" }, { "当前期权价值", "-" }, { "Delta比例", "-" }, { "Delta对应总市值", item2.DeltaCash }, { "GammaCash", "-" }, { "VegaCash", "-" }, { "Delta", item2.Delta }, { "Gamma", "-" }, { "Vega", "-" }, { "期权端我方收益", "-" }, { "产品结构", item.TradeType } }; results.Add(dic); } else if (!IsSettled) { var dic = new Dictionary { { "序号", i.ToString() }, { "交易对手名称", item.ClientName }, { "起始日期", item.TradeDate.OtcFormatDate() }, { "终止日期", item.ExerciseDate.OtcFormatDate() }, { "标的证券", item.UnderlyingAssetName }, { "标的代码", item.UnderlyingCode } }; startPv = OtcFormatExtensions.OtcFormatValue(startPv, 2); item.PV = OtcFormatExtensions.OtcFormatValue(item.PV ?? 0, 2); item2.DeltaCash = OtcFormatExtensions.OtcFormatValue(item2.DeltaCash ?? 0, 2); DeltaCashSum += item2.DeltaCash ?? 0; item2.GammaCash = OtcFormatExtensions.OtcFormatValue(item2.GammaCash ?? 0, 2); item2.VegaCash = OtcFormatExtensions.OtcFormatValue(item2.VegaCash ?? 0, 2); item2.Delta = OtcFormatExtensions.OtcFormatValue(item2.Delta ?? 0, 2); item2.Gamma = OtcFormatExtensions.OtcFormatValue(item2.Gamma ?? 0, 2); item2.Vega = OtcFormatExtensions.OtcFormatValue(item2.Vega ?? 0, 2); TradePriceSum += startPv; PVSum += item.PV ?? 0; var deltaRate = (StockEqvNotionalToShow == null || StockEqvNotionalToShow == 0) ? 0.0 : ((double)item2.DeltaCash / StockEqvNotionalToShow); DeltaRateSum += OtcFormatExtensions.OtcFormatValue(deltaRate ?? 0, 2); dic.Add("合约本金规模", StockEqvNotionalToShow); StockEqvNotionalToShowSum += IsHedge ? 0 : (StockEqvNotionalToShow ?? 0); dic.Add("期初期权价值", startPv); dic.Add("当前期权价值", item.PV); dic.Add("Delta比例", OtcFormatExtensions.OtcFormatValue(deltaRate ?? 0, 2)); dic.Add("Delta对应总市值", item2.DeltaCash); dic.Add("GammaCash", item2.GammaCash ?? 0); dic.Add("VegaCash", item2.VegaCash); dic.Add("Delta", item2.Delta ?? 0); dic.Add("Gamma", item2.Gamma ?? 0); dic.Add("Vega", item2.Vega ?? 0); DeltaCashSum += item2.DeltaCash ?? 0; GammaCashSum += item2.GammaCash ?? 0; VegaCashSum += item2.VegaCash ?? 0; DeltaSum += item2.Delta ?? 0; GammaSum += item2.Gamma ?? 0; VegaSum += item2.Vega ?? 0; var profit = beforeDelta * (item.UnderlyingPrice - priceDict.GetPrice(item.UnderlyingCode, SettlementTypeEnum.ClosePrice)); profit = OtcFormatExtensions.OtcFormatValue(profit, 2); profitSum += profit; var dailyPnl = item.PV - startPv; dailyPnlSum += dailyPnl ?? 0; dic.Add("期权端我方收益", dailyPnl); //dic.Add("对冲端当日收益", OtcFormatExtensions.OtcFormatValue(calcProfit, 2)); dic.Add("中性对冲端当日收益", OtcFormatExtensions.OtcFormatValue(profit, 2)); //dic.Add("存续期浮动盈亏", calcProfit + item.PV - startPv); dic.Add("产品结构", item.TradeType); dic.Add("TradeNumber", item.TradeNumber); results.Add(dic); i++; } } foreach (var item in results) { if (!item.Keys.Contains("中性对冲端当日收益")) { continue; } var profitStr = item["中性对冲端当日收益"].ToString(); if (string.IsNullOrWhiteSpace(profitStr)) { item.Add("对冲端当日收益", ""); } else { var profit = double.Parse(profitStr); var calcProfit = todayHedgeMarkingPro * profit / profitSum; calcProfit = OtcFormatExtensions.OtcFormatValue(calcProfit, 2); calcProfitSum += calcProfit; item.Add("对冲端当日收益", OtcFormatExtensions.OtcFormatValue(calcProfit, 2)); } } #endregion #region sheet1_sum var dicSum = new Dictionary(); //todayHedgePositionPnlSum = OtcFormatExtensions.OtcFormatValue(todayHedgePositionPnlSum, 2); calcProfitSum = OtcFormatExtensions.OtcFormatValue(calcProfitSum, 2); var calcProfitDiff = todayHedgeMarkingPro - calcProfitSum; results.ElementAt(0)["对冲端当日收益"] = (double)results.ElementAt(0)["对冲端当日收益"] + calcProfitDiff; //results.ElementAt(0)["存续期浮动盈亏"] = (double)results.ElementAt(0)["存续期浮动盈亏"] + calcProfitDiff; calcProfitSum += calcProfitDiff; dicSum.Add("序号", "总计"); dicSum.Add("合约本金规模", OtcFormatExtensions.OtcFormatValue(StockEqvNotionalToShowSum, 2)); dicSum.Add("期初期权价值", OtcFormatExtensions.OtcFormatValue(TradePriceSum, 2)); dicSum.Add("当前期权价值", OtcFormatExtensions.OtcFormatValue(PVSum, 2)); dicSum.Add("Delta比例", ""); dicSum.Add("Delta对应总市值", OtcFormatExtensions.OtcFormatValue(DeltaCashSum, 2)); dicSum.Add("GammaCash", OtcFormatExtensions.OtcFormatValue(GammaCashSum, 2)); dicSum.Add("VegaCash", OtcFormatExtensions.OtcFormatValue(VegaCashSum, 2)); dicSum.Add("Delta", OtcFormatExtensions.OtcFormatValue(DeltaSum, 2)); dicSum.Add("Gamma", OtcFormatExtensions.OtcFormatValue(GammaSum, 2)); dicSum.Add("Vega", OtcFormatExtensions.OtcFormatValue(VegaSum, 2)); dicSum.Add("期权端我方收益", OtcFormatExtensions.OtcFormatValue((dailyPnlSum), 2)); dicSum.Add("对冲端当日收益", calcProfitSum); dicSum.Add("中性对冲端当日收益", OtcFormatExtensions.OtcFormatValue(profitSum, 2)); dicSum.Add("存续期浮动盈亏", OtcFormatExtensions.OtcFormatValue((calcProfitSum + PVSum - TradePriceSum), 2)); results.Add(dicSum); #endregion #region sheet2 //todayPositionQuery.Any() ? todayPositionQuery.Where(o => !ConsTrade.TradeTypesForHedge.Contains(o.TradeType)).Select(o => o.ClosedPnL).Sum() : 0; //var todayTrades = DbContext.eod_trade.Where(o => o.ValueDate == req.ValueDate && todayPositionQuery.Select(x => x.TradeId).Contains(o.TradeId)).ToList(); var Futu_UseMargin = todayMeta.Futu_MarginUsed; var Futu_MarginBalance = todayMeta.Futu_MarginBalance; var PositionAsset = todayMeta.StockAsset; dayUnwindValue = OtcFormatExtensions.OtcFormatValue(dayUnwindValue, 2); var AssetValuePerDay = new Dictionary { { "日期", req.ValueDate.OtcFormatDate() }, { "存续笔数", count }, { "日新增名义金额", dayIncreaseValue }, { "日平仓名义金额", -1 * Math.Abs(dayUnwindValue) }, { "存续名义本金", todayDayHoldValue }, { "日估值损益", OtcFormatExtensions.OtcFormatValue(todayPV - beforePV, 2) }, { "存续累计损益", OtcFormatExtensions.OtcFormatValue(todayPositonPnl, 2) }, { "日平仓实现损益", OtcFormatExtensions.OtcFormatValue(todayRealizedPnl - beforeRealizedPnl, 2) }, { "了结累计损益", OtcFormatExtensions.OtcFormatValue(todayRealizedPnl, 2) }, { "累计总收益", OtcFormatExtensions.OtcFormatValue(todayPositonPnl + todayRealizedPnl - todayCashAmount, 2) }, { "对冲端盯市金额", OtcFormatExtensions.OtcFormatValue(HedgeMarkingCash, 2) }, { "当日出入金", OtcFormatExtensions.OtcFormatValue(todayHedgeCashInOut, 2) }, { "实际日收益", todayHedgeMarkingPro }, { "了结对冲累计收益", OtcFormatExtensions.OtcFormatValue(todayHedgeClosePnlSum, 2) }, { "期货预付金占用", OtcFormatExtensions.OtcFormatValue(Futu_UseMargin, 2) }, { "期货可用预付金", OtcFormatExtensions.OtcFormatValue(Futu_MarginBalance, 2) }, { "现货资产", OtcFormatExtensions.OtcFormatValue(PositionAsset, 2) }, { "未入金预付金", "" } }; #endregion var list1 = results.Select(n => new ExpandoDictionary(n)).ToArray(); var list2 = new ExpandoDictionary[] { new ExpandoDictionary(AssetValuePerDay) }; var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/场外风控报送模板.xlsx"); return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { tradelist = list1, dayreport = list2 }).GenerateBytes(true); } catch (Exception e) { LogFactory.GetLogger().Error("导出场外风控报送模板出错:" + e); throw; } } /// /// 计算风险敞口 /// /// /// 现价 /// public static double ExposureCalc(trade td, double price, DateTime valueDate) { var list = ConsTrade.TradeCompleteStatus; if (td == null || td.BuySell != "买入" || list.Contains(td.TradeStatus))//或者了结了 { return 0; } if (td.TradeType == "亚式期权" && td.trade_asian_option?.AveragingPeriodStartDate > valueDate) { return 0; } var tdClone = td.Clone(); var tc = new trade_cash(); SettlementCalcCommons.SetPossibleExec(tc, tdClone, price, true, valueDate); return tc.Amount; } } }