using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using YLErp.BLL.Eod; using YLErp.BLL; using YLErp.Modules.RiskExposure; using YLErp.Modules.MarketRiskMoudule.Dto; using Dapper; using YLErp.Modules.RiskExposure.Dto; using YLErp.Modules.CalculationModule; using System.Data.Common; using NPOI.OpenXmlFormats.Dml; using MathNet.Numerics.Distributions; using NPOI.SS.Formula.Functions; using YLErp.Modules.DataProviderModule; using System.Diagnostics; using System.Linq.Extend; using YLErp.Modules.EodModule; using Microsoft.Office.Interop.Word; using System.Linq.Expressions; using YLErp.Model; using YLErp.DBModels; using YLErp.Modules.ReportModule; using Qdp.Foundation.Implementations; using MySqlConnector; using NPOI.Util; using Qdp.Foundation.Utilities; using static iTextSharp.text.pdf.XfaForm; namespace YLErp.Modules.MarketRiskMoudule { /// /// 市场风险服务,查询市场风险数据 /// /// public class MarketRiskService : YLBaseService where eodPosition : EodTradePosition { public MarketRiskService(OptUserInfo userInfo) : base(userInfo) { } /// /// 查询市场风险数据 /// /// /// /// /// public RiskExposureReportModel SearchMarketRiskData(RiskRequestModel reqModel) where eodRisk : EodTradeRisk where eodPnl : EodPnl { reqModel = new RiskExposureReportService(OptUser).CheckModel(reqModel); // 1、确定三点 T1 T1~T2 T2 // T1 var startDate = EodOperationBase.GetLastSettlementDate(reqModel.ValueDateStart ?? valuedateBLL.SystemDate.AccruedTotalPnlStartDate ?? DateTime.Today); var dateT1 = EodOperationBase.GetLastSettlementDate(startDate.AddDays(-1)); // T2 var dateT2 = reqModel.ValueDateEnd; var preDateT2 = EodOperationBase.GetLastSettlementDate(dateT2, true); List t1Datas = null; List t2PositionDatas = null; List t2RiskDatas = null; List t2PnlDatas = null; List t1ToT2Datas = null; List eodDatas = null; List preDateT2Datas = null; // 2、查询三点数据 GetT1AndT2SourceData(reqModel, dateT1, dateT2, preDateT2, out t1Datas, out t2PositionDatas, out t2RiskDatas, out t2PnlDatas, out t1ToT2Datas, out eodDatas,out preDateT2Datas); // 3、数组组装 var riskExposureItemModels = GetRisExposureItemList(t1Datas, t2PositionDatas, t2RiskDatas, t2PnlDatas, t1ToT2Datas, eodDatas,preDateT2Datas); var result= GetRiskExposureReportModel(reqModel, startDate, dateT1, riskExposureItemModels, t1ToT2Datas, t2PositionDatas, t2RiskDatas, t2PnlDatas, t1Datas); return result; } public void MakeCondition(RiskRequestModel reqModel, out string tradeWhere, out string onSiteTradeWhere, out string predicateWhere,out string inSiteWhere) { tradeWhere = "IFNULL(ValidState,'')<>'InValid'"; onSiteTradeWhere = " IsValid=1"; predicateWhere = " ValueDate=@EndTime and TradeType<>'结构化交易' and TradeType<>'现金流交易'"; tradeWhere += " and TradeType<>'结构化交易' and TradeType<>'现金流交易'"; inSiteWhere= "TradeType<>'结构化交易' and TradeType<>'现金流交易'"; if (reqModel.UserAssets != null && reqModel.UserAssets.Count > 0 && !(reqModel.UserClients != null && reqModel.UserClients.Count > 0)) { tradeWhere += " and AssetId in @UserAssets"; predicateWhere += " and BookId in @UserAssets"; onSiteTradeWhere += " and AssetBookId in @UserAssets"; inSiteWhere += " and BookId in @UserAssets"; } if (!(reqModel.UserAssets != null && reqModel.UserAssets.Count > 0) && (reqModel.UserClients != null && reqModel.UserClients.Count > 0)) { tradeWhere += " and ClientId in @UserClients"; predicateWhere += " and ClientId in @UserClients"; inSiteWhere += " and ClientId in @UserClients"; } if ((reqModel.UserAssets != null && reqModel.UserAssets.Count > 0) && (reqModel.UserClients != null && reqModel.UserClients.Count > 0)) { tradeWhere += " and (AssetId in @UserAssets or ClientId in @UserClients)"; predicateWhere += " and (BookId in @UserAssets or ClientId in @UserClients)"; onSiteTradeWhere += " and AssetBookId in @UserAssets"; inSiteWhere += " and (BookId in @UserAssets or ClientId in @UserClients)"; } if (reqModel.ClientIds != null && reqModel.ClientIds.Count > 0) { predicateWhere += " and ClientId in @ClientIds"; tradeWhere += " and ClientId in @ClientIds"; inSiteWhere += " and ClientId in @ClientIds"; } if (reqModel.BookIds != null && reqModel.BookIds.Count > 0) { predicateWhere += " and BookId in @BookIds"; tradeWhere += " and AssetId in @BookIds"; onSiteTradeWhere += " and AssetBookId in @BookIds"; inSiteWhere += " and BookId in @BookIds"; } if (reqModel.TradeTypes != null && reqModel.TradeTypes.Any()) { predicateWhere += " and ((IFNULL(StructureType,'')='' and TradeType in @TradeTypes) or (IFNULL(StructureType,'')<>'' and StructureType in @TradeTypes))"; tradeWhere += " and ((IFNULL(StructureType,'')='' and TradeType in @TradeTypes) or (IFNULL(StructureType,'')<>'' and StructureType in @TradeTypes))"; inSiteWhere += " and ((IFNULL(StructureType,'')='' and TradeType in @TradeTypes) or (IFNULL(StructureType,'')<>'' and StructureType in @TradeTypes))"; } if (reqModel.TraderIds != null && reqModel.TraderIds.Any()) { predicateWhere += " and TradeId>0"; tradeWhere += " and TraderId in @TraderIds"; inSiteWhere += " and TradeId>0"; } if (reqModel.TagIds != null && reqModel.TagIds.Count > 0) { tradeWhere += " and id in (select TradeId from trade_tag where TagId in @TagIds)"; } if (reqModel.VarietyIds != null && reqModel.VarietyIds.Any() && reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any()) { predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; inSiteWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; } else { if (reqModel.VarietyIds != null && reqModel.VarietyIds.Any()) { predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; inSiteWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; } if (reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any()) { predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; inSiteWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; } } predicateWhere += String.Format(" and (TradeId<1 or TradeId in (select id from trade where {0}))", tradeWhere); } public RiskExposureReportModel GetRiskExposureReportModel(RiskRequestModel reqModel, DateTime startDate, DateTime preDate, List eodPnlListEnd, List t1ToT2Datas,List t2PositionDatas,List t2RiskDatas,List t2PnlDatas, List t1Datas) where eodRisk : EodTradeRisk { RiskExposureReportModel result; var dataProvider = new EodRiskCalcDataProvider(reqModel.ValueDateEnd, startDate); //合并处理 var underlyingGroup = eodPnlListEnd.GroupBy(e => e.UnderlyingCode.ToUpperInvariant()); var underlyingIdList = underlyingGroup.Select(g => g.Key).ToList(); var underlyingRiskList = new List(); var exchangeOptionRisks = CalculateExchangeListOptionRisks(reqModel.ValueDateEnd, reqModel,t2PositionDatas,t2RiskDatas,t2PnlDatas);//获取场内交易数据 var settlementType = ConsGlobal.SettlePriceMode.GetSettlementType(reqModel.EodSettlePriceMode.TrimToNull() ?? valuedateBLL.SystemDate.EodSettlePriceMode); List umList = null; List varietyList = null; List limitList = null; var umCodeList = underlyingGroup.Select(p => p.Key).Distinct().ToList(); if (umCodeList != null && umCodeList.Count > 0) { umList = DbContext.underlying_manager.AsNoTracking().Where(p => umCodeList.Contains(p.UnderlyingCode)).ToList(); if (umList != null && umList.Count > 0) { var umTypeIds = umList.Select(p => p.UnderlyingTypeId).Distinct().ToList(); varietyList = DbContext.variety.AsNoTracking().Where(p => umTypeIds.Contains(p.id)).ToList(); } if (varietyList != null && varietyList.Count > 0) { var varietyCodes = varietyList.Select(p => p.VarietyCode).Distinct().ToList(); limitList = DbContext.variety_limit.AsNoTracking().Where(p => varietyCodes.Contains(p.VarietyCode)).ToList(); } } if (umList == null) { umList = new List(); } if (varietyList == null) { varietyList = new List(); } if (limitList == null) { limitList = new List(); } #region 1.对于最后一日有持仓数据的合约 foreach (var groupItem in underlyingGroup) { dataProvider.TryGetEodPrice(groupItem.Key, settlementType, out var price); var underlyingRisk = new UnderlyingRiskModel(); var underlying = umList.FirstOrDefault(d => d.UnderlyingCode.Equals(groupItem.Key)); Variety variety = null; if (underlying != null) { variety = varietyList.FirstOrDefault(d => d.id == underlying.UnderlyingTypeId); //var variety_limit = variety == null ? null : DbContext.variety_limit.FirstOrDefault(o => o.VarietyCode == variety.VarietyCode); var variety_limit = variety == null ? null : limitList.FirstOrDefault(o => o.VarietyCode == variety.VarietyCode); underlyingRisk.UnderlyingId = underlying.id; underlyingRisk.UnderlyingCode = underlying.UnderlyingCode; underlyingRisk.UnderlyingPrice = price; underlyingRisk.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType; underlyingRisk.VarietyCode = underlying.CommodityCode == "组合标的" ? "组合标的" : (variety == null ? underlying.UnderlyingType : variety.VarietyCode); underlyingRisk.VarietyOpenLimitIcon = variety == null || !(variety_limit?.IsPercent ?? false) ? "¥" : "%"; underlyingRisk.VarietyLimit = variety_limit; } else { underlying = dataProvider.GetUnderlying(groupItem.Key); if (underlying == null) { throw new ServiceException("标的数据不存在:" + groupItem.Key); } variety = DbContext.variety.Find(underlying.UnderlyingTypeId); var variety_limit = variety == null ? null : DbContext.variety_limit.FirstOrDefault(o => o.VarietyCode == variety.VarietyCode); underlyingRisk.UnderlyingId = underlying.id; underlyingRisk.UnderlyingCode = underlying.UnderlyingCode; underlyingRisk.UnderlyingPrice = price; underlyingRisk.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType; underlyingRisk.VarietyCode = underlying.CommodityCode == "组合标的" ? "组合标的" : (variety == null ? underlying.UnderlyingType : variety.VarietyCode); underlyingRisk.VarietyOpenLimitIcon = variety == null || !(variety_limit?.IsPercent ?? false) ? "¥" : "%"; underlyingRisk.VarietyLimit = variety_limit; } if (underlying.CommodityCode == "组合标的") { underlyingRisk.SyntheticUnderlyingTipsInfo = synthetic_underlyingBLL.GetUnderlyingTipsInfo(underlying.UnderlyingCode); } var otcOptionsTradeType = ConsTrade.OptionTradeTypes.ToList(); otcOptionsTradeType.Add("结构化交易"); otcOptionsTradeType.AddRange(DbContext.Structure_Info.Select(o => o.StructureName)); otcOptionsTradeType.Remove("收益互换"); //场外期权 var otcRiskList = groupItem.Where(g => otcOptionsTradeType.Contains(g.TradeType)); underlyingRisk.OtcRisk = new EodRiskModel { StockEqvNotional = otcRiskList.SumDouble(r => r.StockEqvNotional), StockEqvNotionalReal = otcRiskList.SumDouble(r => r.StockEqvNotionalReal), Pnl = otcRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0), Delta = otcRiskList.SumDouble(r => r.Delta ?? 0), DeltaCash = otcRiskList.SumDouble(r => r.DeltaCash ?? 0), GammaCash = otcRiskList.SumDouble(r => r.GammaCash ?? 0), PositionStockEqvNotional = otcRiskList.SumDouble(r => (r.Amount * r.SpotPrice) ?? 0), Gamma = otcRiskList.SumDouble(r => r.Gamma ?? 0), Theta = otcRiskList.SumDouble(r => r.Theta ?? 0), Vega = otcRiskList.SumDouble(r => r.Vega ?? 0), Rho = otcRiskList.SumDouble(r => r.Rho ?? 0), DailyPnl = otcRiskList.SumDouble(r => r.DailyPnl ?? 0), dPnlDelta = otcRiskList.SumDouble(r => r.dPnlDelta), dPnlGamma = otcRiskList.SumDouble(r => r.dPnlGamma), dPnlTheta = otcRiskList.SumDouble(r => r.dPnlTheta), dPnlVega = otcRiskList.SumDouble(r => r.dPnlVega), dPnlPsi = otcRiskList.SumDouble(r => r.dPnlPsi), CumulativeFloatProfitLoss = otcRiskList.SumDouble(r => r.CumulativeFloatProfitLoss) }; underlyingRisk.OtcRisk.DeltaInLots = TradeLotsCalc.CalcDeltaInLots(Convert.ToDouble(underlyingRisk.OtcRisk.Delta), variety, underlying); underlyingRisk.OtcRisk.GammaInLots = TradeLotsCalc.CalcGammaInLots(Convert.ToDouble(underlyingRisk.OtcRisk.Gamma), variety, underlying); //场内期权 var exchangeRiskList = groupItem.Where(g => g.TradeType == "场内期权"); //var preValueDateCommissionExOptSum = underlyingPreValueDateCommissionList.Where(x => x.AssetType == "场内期权").SumDouble(x => x.TotalCommission); var underlyingExchangeRisks = exchangeOptionRisks.Where(r => r.UnderlyingCode.Equals(groupItem.Key, StringComparison.OrdinalIgnoreCase)); underlyingRisk.ExOptionRisk = new EodRiskModel { Pnl = exchangeRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0), Delta = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize((double)r.Delta)), DeltaCash = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize(r.DeltaCash)), GammaCash = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize(r.GammaCash)), StockEqvNotional = exchangeRiskList.SumDouble(r => { var exoption = DataCacheProvider.GetExchangeListOptionDataSource().GetData(r.OptionCode); return exoption == null ? 0 : NumberHelper.Abs(r.Amount * exoption.Strike); }), Gamma = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize((double)r.Gamma)), Theta = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize((double)r.Theta)), Vega = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize((double)r.Vega)), Rho = underlyingExchangeRisks.SumDouble(r => NumberHelper.Normalize((double)r.Rho)), DailyCommission = exchangeRiskList.SumDouble(r => r.DailyCommission),//当日累计 - 昨日累计 = 当日手续费 DailyPnl = exchangeRiskList.SumDouble(r => r.DailyPnl ?? 0), dPnlDelta = exchangeRiskList.SumDouble(r => r.dPnlDelta), dPnlGamma = exchangeRiskList.SumDouble(r => r.dPnlGamma), dPnlTheta = exchangeRiskList.SumDouble(r => r.dPnlTheta), dPnlVega = exchangeRiskList.SumDouble(r => r.dPnlVega), dPnlPsi = exchangeRiskList.SumDouble(r => r.dPnlPsi), CumulativeFloatProfitLoss = exchangeRiskList.SumDouble(r => r.CumulativeFloatProfitLoss), Commission = exchangeRiskList.SumDouble(r => r.Commission) }; underlyingRisk.ExOptionRisk.StockEqvNotionalReal = underlyingRisk.ExOptionRisk.StockEqvNotional; underlyingRisk.ExOptionRisk.DeltaInLots = TradeLotsCalc.CalcDeltaInLots(Convert.ToDouble(underlyingRisk.ExOptionRisk.Delta), variety, underlying); underlyingRisk.ExOptionRisk.GammaInLots = TradeLotsCalc.CalcGammaInLots(Convert.ToDouble(underlyingRisk.ExOptionRisk.Gamma), variety, underlying); //标的交易 var hedgeRiskList = groupItem.Where(g => g.TradeType == "商品期货" || g.TradeType == "股票" || g.TradeType == "商品现货"); underlyingRisk.FuturesRisk = new EodRiskModel { Pnl = hedgeRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0), Position = hedgeRiskList.SumDouble(r => r.Amount), StockEqvNotional = hedgeRiskList.SumDouble(r => NumberHelper.Abs(r.Amount * price)), Commission = hedgeRiskList.SumDouble(r => r.Commission), DailyCommission = hedgeRiskList.SumDouble(r => r.DailyCommission),//当日累计 - 昨日累计 = 当日手续费 DailyPnl = hedgeRiskList.SumDouble(r => r.DailyPnl ?? 0) }; underlyingRisk.FuturesRisk.StockEqvNotionalReal = underlyingRisk.FuturesRisk.StockEqvNotional; underlyingRisk.FuturesRisk.PositionInLots = TradeLotsCalc.CalcDeltaInLots(Convert.ToDouble(underlyingRisk.FuturesRisk.Position), variety, underlying); underlyingRisk.FuturesRisk.PositionIncrementInLots = underlyingRisk.FuturesRisk.PositionInLots - 0;// tartPositionInLots; underlyingRisk.FuturesRisk.Delta = underlyingRisk.FuturesRisk.Position; underlyingRisk.FuturesRisk.DeltaCash = underlyingRisk.UnderlyingPrice * underlyingRisk.FuturesRisk.Delta ?? 0; underlyingRisk.FuturesRisk.GammaCash = underlyingRisk.UnderlyingPrice * underlyingRisk.FuturesRisk.Gamma ?? 0; underlyingRisk.FuturesRisk.DeltaInLots = underlyingRisk.FuturesRisk.PositionInLots; //远期统计 var forwardRiskList = groupItem.Where(g => g.TradeType == "远期"); underlyingRisk.ForwardRisk = new EodRiskModel { Pnl = forwardRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0), Delta = forwardRiskList.SumDouble(r => r.Delta ?? 0), DeltaCash = forwardRiskList.SumDouble(r => r.DeltaCash ?? 0), GammaCash = forwardRiskList.SumDouble(r => r.GammaCash ?? 0), PositionStockEqvNotional = forwardRiskList.SumDouble(r => (r.Amount * r.SpotPrice) ?? 0), DailyPnl = forwardRiskList.SumDouble(r => r.DailyPnl ?? 0) }; underlyingRisk.ForwardRisk.DeltaInLots = TradeLotsCalc.CalcDeltaInLots(Convert.ToDouble(underlyingRisk.ForwardRisk.Delta), variety, underlying); //收益互换统计 var swapRiskList = groupItem.Where(g => g.TradeType == "收益互换"); underlyingRisk.SwapRisk = new EodRiskModel { StockEqvNotional = swapRiskList.SumDouble(r => NumberHelper.Abs(r.StockEqvNotional)), StockEqvNotionalReal = swapRiskList.SumDouble(r => NumberHelper.Abs(r.StockEqvNotionalReal)), Pnl = swapRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0), Delta = swapRiskList.SumDouble(r => r.Delta ?? 0), DeltaCash = swapRiskList.SumDouble(r => r.DeltaCash ?? 0), GammaCash = swapRiskList.SumDouble(r => r.GammaCash ?? 0), PositionStockEqvNotional = swapRiskList.SumDouble(r => (r.Amount * r.SpotPrice) ?? 0), DailyPnl = swapRiskList.SumDouble(r => r.DailyPnl ?? 0) }; underlyingRisk.SwapRisk.DeltaInLots = TradeLotsCalc.CalcDeltaInLots(Convert.ToDouble(underlyingRisk.SwapRisk.Delta), variety, underlying); //汇总合计 underlyingRisk.PortfolioRisk = new EodRiskModel { StockEqvNotional = underlyingRisk.OtcRisk.StockEqvNotional + underlyingRisk.ExOptionRisk.StockEqvNotional + underlyingRisk.FuturesRisk.StockEqvNotional + /*underlyingRisk.ForwardRisk.StockEqvNotional +*/ underlyingRisk.SwapRisk.StockEqvNotional, StockEqvNotionalReal = underlyingRisk.OtcRisk.StockEqvNotionalReal + underlyingRisk.ExOptionRisk.StockEqvNotionalReal + underlyingRisk.FuturesRisk.StockEqvNotionalReal + /*underlyingRisk.ForwardRisk.StockEqvNotionalReal +*/ underlyingRisk.SwapRisk.StockEqvNotionalReal, OtcStockEqvNotional = underlyingRisk.OtcRisk.StockEqvNotional + underlyingRisk.SwapRisk.StockEqvNotional, OtcStockEqvNotionalReal = underlyingRisk.OtcRisk.StockEqvNotionalReal + underlyingRisk.SwapRisk.StockEqvNotionalReal, Pnl = underlyingRisk.OtcRisk.Pnl + underlyingRisk.ExOptionRisk.Pnl + underlyingRisk.FuturesRisk.Pnl + underlyingRisk.ForwardRisk.Pnl + underlyingRisk.SwapRisk.Pnl, Delta = underlyingRisk.OtcRisk.Delta + underlyingRisk.ExOptionRisk.Delta + underlyingRisk.FuturesRisk.Delta + underlyingRisk.ForwardRisk.Delta + underlyingRisk.SwapRisk.Delta, DeltaCash = underlyingRisk.OtcRisk.DeltaCash + underlyingRisk.ExOptionRisk.DeltaCash + underlyingRisk.FuturesRisk.DeltaCash + underlyingRisk.ForwardRisk.DeltaCash + underlyingRisk.SwapRisk.DeltaCash, GammaCash = underlyingRisk.OtcRisk.GammaCash + underlyingRisk.ExOptionRisk.GammaCash + underlyingRisk.FuturesRisk.GammaCash + underlyingRisk.ForwardRisk.GammaCash + underlyingRisk.SwapRisk.GammaCash, PositionStockEqvNotional = underlyingRisk.OtcRisk.PositionStockEqvNotional + underlyingRisk.ExOptionRisk.PositionStockEqvNotional + underlyingRisk.ForwardRisk.PositionStockEqvNotional + underlyingRisk.SwapRisk.PositionStockEqvNotional, DeltaInLots = underlyingRisk.OtcRisk.DeltaInLots + underlyingRisk.ExOptionRisk.DeltaInLots + underlyingRisk.FuturesRisk.DeltaInLots + underlyingRisk.ForwardRisk.DeltaInLots + underlyingRisk.SwapRisk.DeltaInLots, DailyPnl = underlyingRisk.OtcRisk.DailyPnl + underlyingRisk.ExOptionRisk.DailyPnl + underlyingRisk.FuturesRisk.DailyPnl + +underlyingRisk.ForwardRisk.DailyPnl + +underlyingRisk.SwapRisk.DailyPnl, Commission = underlyingRisk.ExOptionRisk.Commission + underlyingRisk.FuturesRisk.Commission, Gamma = underlyingRisk.OtcRisk.Gamma + underlyingRisk.ExOptionRisk.Gamma, Theta = underlyingRisk.OtcRisk.Theta + underlyingRisk.ExOptionRisk.Theta, Vega = underlyingRisk.OtcRisk.Vega + underlyingRisk.ExOptionRisk.Vega, Rho = underlyingRisk.OtcRisk.Rho + underlyingRisk.ExOptionRisk.Rho, dPnlDelta = underlyingRisk.OtcRisk.dPnlDelta + underlyingRisk.ExOptionRisk.dPnlDelta, dPnlGamma = underlyingRisk.OtcRisk.dPnlGamma + underlyingRisk.ExOptionRisk.dPnlGamma, dPnlTheta = underlyingRisk.OtcRisk.dPnlTheta + underlyingRisk.ExOptionRisk.dPnlTheta, dPnlVega = underlyingRisk.OtcRisk.dPnlVega + underlyingRisk.ExOptionRisk.dPnlVega, dPnlPsi = underlyingRisk.OtcRisk.dPnlPsi + underlyingRisk.ExOptionRisk.dPnlPsi, CumulativeFloatProfitLoss = underlyingRisk.OtcRisk.CumulativeFloatProfitLoss + underlyingRisk.ExOptionRisk.CumulativeFloatProfitLoss, }; underlyingRiskList.Add(underlyingRisk); } #endregion underlyingRiskList = underlyingRiskList.OrderBy(u => u, new UnderlyingRiskModelSortComparer()).ToList(); var varietyRiskExposureReports = underlyingRiskList.GroupBy(u => new { u.VarietyCode, u.VarietyOpenLimit, u.VarietyOpenLimitIcon }).Select(g => { var list = g.ToList(); var portfolioSum = new EodRiskModel { StockEqvNotional = list.SumDouble(l => l.PortfolioRisk.StockEqvNotional), StockEqvNotionalReal = list.SumDouble(l => l.PortfolioRisk.StockEqvNotionalReal), OtcStockEqvNotional = list.SumDouble(l => l.PortfolioRisk.OtcStockEqvNotional), OtcStockEqvNotionalReal = list.SumDouble(l => l.PortfolioRisk.OtcStockEqvNotionalReal), Pnl = list.SumDouble(l => l.PortfolioRisk.Pnl), Delta = list.SumDouble(l => l.PortfolioRisk.Delta), DeltaCash = list.SumDouble(l => l.PortfolioRisk.DeltaCash), GammaCash = list.SumDouble(l => l.PortfolioRisk.GammaCash), PositionStockEqvNotional = list.SumDouble(l => l.PortfolioRisk.PositionStockEqvNotional), DeltaInLots = list.SumDouble(l => l.PortfolioRisk.DeltaInLots), DailyPnl = list.SumDouble(l => l.PortfolioRisk.DailyPnl), Commission = list.SumDouble(l => l.PortfolioRisk.Commission), Gamma = list.SumDouble(l => l.PortfolioRisk.Gamma), Theta = list.SumDouble(l => l.PortfolioRisk.Theta), Vega = list.SumDouble(l => l.PortfolioRisk.Vega), Rho = list.SumDouble(l => l.PortfolioRisk.Rho), dPnlDelta = list.SumDouble(l => l.PortfolioRisk.dPnlDelta), dPnlGamma = list.SumDouble(l => l.PortfolioRisk.dPnlGamma), dPnlTheta = list.SumDouble(l => l.PortfolioRisk.dPnlTheta), dPnlVega = list.SumDouble(l => l.PortfolioRisk.dPnlVega), dPnlPsi = list.SumDouble(l => l.PortfolioRisk.dPnlPsi), CumulativeFloatProfitLoss = list.SumDouble(l => l.PortfolioRisk.CumulativeFloatProfitLoss), }; var otcSum = new EodRiskModel { StockEqvNotional = list.SumDouble(l => l.OtcRisk.StockEqvNotional), StockEqvNotionalReal = list.SumDouble(l => l.OtcRisk.StockEqvNotionalReal), Pnl = list.SumDouble(l => l.OtcRisk.Pnl), Delta = list.SumDouble(l => l.OtcRisk.Delta), DeltaInLots = list.SumDouble(l => l.OtcRisk.DeltaInLots), Gamma = list.SumDouble(l => l.OtcRisk.Gamma), GammaInLots = list.SumDouble(l => l.OtcRisk.GammaInLots), Theta = list.SumDouble(l => l.OtcRisk.Theta), Vega = list.SumDouble(l => l.OtcRisk.Vega), Rho = list.SumDouble(l => l.OtcRisk.Rho), DailyPnl = list.SumDouble(l => l.OtcRisk.DailyPnl), DeltaCash = list.SumDouble(l => l.OtcRisk.DeltaCash), dPnlDelta = list.SumDouble(l => l.OtcRisk.dPnlDelta), dPnlGamma = list.SumDouble(l => l.OtcRisk.dPnlGamma), dPnlTheta = list.SumDouble(l => l.OtcRisk.dPnlTheta), dPnlVega = list.SumDouble(l => l.OtcRisk.dPnlVega), dPnlPsi = list.SumDouble(l => l.OtcRisk.dPnlPsi), CumulativeFloatProfitLoss = list.SumDouble(l => l.OtcRisk.CumulativeFloatProfitLoss), }; var exchangeListOptionSum = new EodRiskModel { Pnl = list.SumDouble(l => l.ExOptionRisk.Pnl), Delta = list.SumDouble(l => l.ExOptionRisk.Delta), DeltaInLots = list.SumDouble(l => l.ExOptionRisk.DeltaInLots), Gamma = list.SumDouble(l => l.ExOptionRisk.Gamma), GammaInLots = list.SumDouble(l => l.ExOptionRisk.GammaInLots), Theta = list.SumDouble(l => l.ExOptionRisk.Theta), Vega = list.SumDouble(l => l.ExOptionRisk.Vega), Rho = list.SumDouble(l => l.ExOptionRisk.Rho), Commission = list.SumDouble(l => l.ExOptionRisk.Commission), DailyPnl = list.SumDouble(l => l.ExOptionRisk.DailyPnl), DailyCommission = list.SumDouble(l => l.ExOptionRisk.DailyCommission), DeltaCash = list.SumDouble(l => l.ExOptionRisk.DeltaCash), StockEqvNotional = list.SumDouble(l => l.ExOptionRisk.StockEqvNotional), StockEqvNotionalReal = list.SumDouble(l => l.ExOptionRisk.StockEqvNotionalReal), dPnlDelta = list.SumDouble(l => l.ExOptionRisk.dPnlDelta), dPnlGamma = list.SumDouble(l => l.ExOptionRisk.dPnlGamma), dPnlTheta = list.SumDouble(l => l.ExOptionRisk.dPnlTheta), dPnlVega = list.SumDouble(l => l.ExOptionRisk.dPnlVega), dPnlPsi = list.SumDouble(l => l.ExOptionRisk.dPnlPsi), CumulativeFloatProfitLoss = list.SumDouble(l => l.ExOptionRisk.CumulativeFloatProfitLoss), }; var futuresSum = new EodRiskModel { Pnl = list.SumDouble(l => l.FuturesRisk.Pnl), Position = list.SumDouble(l => l.FuturesRisk.Position), PositionInLots = list.SumDouble(l => l.FuturesRisk.PositionInLots), PositionIncrementInLots = list.SumDouble(l => l.FuturesRisk.PositionIncrementInLots), Commission = list.SumDouble(l => l.FuturesRisk.Commission), DailyPnl = list.SumDouble(l => l.FuturesRisk.DailyPnl), DailyCommission = list.SumDouble(l => l.FuturesRisk.DailyCommission), StockEqvNotional = list.SumDouble(l => l.FuturesRisk.StockEqvNotional), StockEqvNotionalReal = list.SumDouble(l => l.FuturesRisk.StockEqvNotionalReal) }; var forwardSum = new EodRiskModel { Pnl = list.SumDouble(l => l.ForwardRisk.Pnl), Delta = list.SumDouble(l => l.ForwardRisk.Delta), DeltaInLots = list.SumDouble(l => l.ForwardRisk.DeltaInLots), DailyPnl = list.SumDouble(l => l.ForwardRisk.DailyPnl) }; var swapSum = new EodRiskModel { StockEqvNotional = list.SumDouble(l => l.SwapRisk.StockEqvNotional), StockEqvNotionalReal = list.SumDouble(l => l.SwapRisk.StockEqvNotionalReal), Pnl = list.SumDouble(l => l.SwapRisk.Pnl), Delta = list.SumDouble(l => l.SwapRisk.Delta), DeltaInLots = list.SumDouble(l => l.SwapRisk.DeltaInLots), DailyPnl = list.SumDouble(l => l.SwapRisk.DailyPnl) }; VarietyLimit varietyLimit = list.First().VarietyLimit; //varietyLimit = limitList.FirstOrDefault(o => o.VarietyCode == g.Key.VarietyCode); //if (varietyLimit == null) //{ // varietyLimit= DbContext.variety_limit.FirstOrDefault(o => o.VarietyCode == g.Key.VarietyCode); //} return new VarietyRiskExposureModel { VarietyCode = g.Key.VarietyCode, VarietyOpenLimit = g.Key.VarietyOpenLimit, VarietyOpenLimitIcon = g.Key.VarietyOpenLimitIcon, VarietySum = new RiskExposureReportSumModel { PortfolioSum = portfolioSum, OtcSum = otcSum, ExOptionSum = exchangeListOptionSum, FuturesSum = futuresSum, ForwardSum = forwardSum, SwapSum = swapSum }, UnderlyingRiskList = list, varietyLimit = varietyLimit ?? new VarietyLimit() }; }).ToList(); result = new RiskExposureReportModel { ReportModels = varietyRiskExposureReports, //总和盈亏比例计算元素取值逻辑 TotalPnlRate = PS.Config.Is格林大华? CalcTotalPnlRate(startDate, reqModel.ValueDateEnd,t1ToT2Datas,t2PositionDatas, t1Datas):0, Sum = new RiskExposureReportSumModel { PortfolioSum = varietyRiskExposureReports.Select(r => r.VarietySum.PortfolioSum).Aggregate(new EodRiskModel(), (p, n) => p + n), OtcSum = varietyRiskExposureReports.Select(r => r.VarietySum.OtcSum).Aggregate(new EodRiskModel(), (p, n) => p + n), ExOptionSum = varietyRiskExposureReports.Select(r => r.VarietySum.ExOptionSum).Aggregate(new EodRiskModel(), (p, n) => p + n), FuturesSum = varietyRiskExposureReports.Select(r => r.VarietySum.FuturesSum).Aggregate(new EodRiskModel(), (p, n) => p + n), ForwardSum = varietyRiskExposureReports.Select(r => r.VarietySum.ForwardSum).Aggregate(new EodRiskModel(), (p, n) => p + n), SwapSum = varietyRiskExposureReports.Select(r => r.VarietySum.SwapSum).Aggregate(new EodRiskModel(), (p, n) => p + n) } }; return result; } /// /// 计算综合盈亏比例: ((收取的权利金 - 支付的权利金) + 对冲盈亏 - 期权估值)/对冲账户成本 /// /// 开始日期(包括) /// 结束日期(包括) public double CalcTotalPnlRate(DateTime startDate, DateTime endDate, List t1ToT2Datas, List t2PositionDatas,List t1Datas) { //对冲盈亏 var totalHedgePnl = GetTotalPnlOfExchangeOption(t1ToT2Datas,t2PositionDatas,t1Datas) + GetTotalPnlSumOfFutures(t1ToT2Datas, t2PositionDatas, t1Datas); //公司角度期权估值(场外期权) var totalPv = GetTotalPvOfOptions(t2PositionDatas,t1Datas); //公司角度(收取的权利金 - 支付的权利金) var allTotalTradePrice = -(DbContext.ClientBalanceDaily.Where(x => x.BalanceDate == endDate) .Sum(x => x.OptionPremiumSum) ?? 0) - (DbContext.ClientBalanceDaily.Where(x => x.BalanceDate == endDate) .Sum(x => x.OptionPremiumSwapSum) ?? 0); var preStartDate = GetPreDate(startDate); var lastSettleDateStartDateTotalTradePrice = -(DbContext.ClientBalanceDaily.Where(x => x.BalanceDate == preStartDate) .Sum(x => x.OptionPremiumSum) ?? 0) - (DbContext.ClientBalanceDaily.Where(x => x.BalanceDate == preStartDate) .Sum(x => x.OptionPremiumSwapSum) ?? 0); var totalTradePrice = allTotalTradePrice - lastSettleDateStartDateTotalTradePrice; //对冲账户成本 var totalInitialCost = DbContext.exchange_account.Sum(x => x.InitialCost) ?? 0; if (totalInitialCost < 1) { totalInitialCost = 1; } return (totalTradePrice + totalHedgePnl - Convert.ToDouble(totalPv)) / totalInitialCost; } private DateTime GetPreDate(DateTime date) { var tmpDate = DbContext.Set().Where(n => n.ValueDate < date).Max(t => (DateTime?)t.ValueDate); return tmpDate.HasValue ? tmpDate.Value.Date : DateTime.MinValue; } /// /// 获取取值日的期权估值(公司角度) /// public double GetTotalPvOfOptions(List t2PositionDatas,List t1Datas) { //当前持仓-起算前 var query = from t1 in t2PositionDatas.Where(n => n.TradeId > 0) join t2 in t1Datas.Where(n => n.TradeId > 0) on t1.TradeId equals t2.TradeId into tt from t2 in tt.DefaultIfEmpty() select t1.Pv - (t2 == null ? 0 : t2.Pv); return query.Sum(n => (double?)n) ?? 0; } /// /// 获取区间内的商品期货pnl合计 /// /// 开始日期(包括) /// 结束日期(包括) public double GetTotalPnlSumOfFutures(List t1ToT2Datas, List t2PositionDatas, List t1Datas) { //------------------------------ // 取值日的持仓统计 //------------------------------ var positionQuery = from eodPnl in t2PositionDatas where eodPnl.TradeType == "商品期货" group eodPnl by eodPnl.UnderlyingCode into g select new { g.Key, totalPnl = g.Sum(n => n.TotalPnL) }; //------------------------------ // 区间内的过期标的统计 //------------------------------ var finishedQuery = from eodPnl in t1ToT2Datas where eodPnl.TradeType == "商品期货" group eodPnl by eodPnl.UnderlyingCode into g select new { g.Key, totalPnl = g.Sum(n => n.TotalPnL) }; //------------------------------ // 起算日前一交易日的累计数据 //------------------------------ //var preStartDate = GetPreDate(startDate); var preStartQuery = from n in t1Datas where n.TradeType == "商品期货" select new { n.UnderlyingCode, TotalPnL = (double?)n.TotalPnL }; //------------------------------ // 区间内的数据合计(持仓+到期-起始) //------------------------------ var totalPnlQuery = from t1 in positionQuery.Concat(finishedQuery) join t2 in preStartQuery on t1.Key equals t2.UnderlyingCode into tt from t2 in tt.DefaultIfEmpty() select t1.totalPnl - (t2?.TotalPnL ?? 0); return totalPnlQuery.Sum(n => (double?)n) ?? 0; } /// /// 获取区间内的场内期权pnl合计 /// /// 开始日期(包括) /// 结束日期(包括) public double GetTotalPnlOfExchangeOption(List t1ToT2Datas, List t2PositionDatas, List t1Datas) { //------------------------------ // 取值日的当前持仓统计 //------------------------------ var positionQuery = (from eodPnl in t2PositionDatas where eodPnl.TradeType == "场内期权" group eodPnl by eodPnl.ExchangeOptionCode into g select new { g.Key, totalPnl = g.Sum(n => n.TotalPnL) }).ToList(); // 已了结交易 统计 var finishedQuery =(from eodPnl in t1ToT2Datas where eodPnl.TradeType == "场内期权" group eodPnl by eodPnl.ExchangeOptionCode into g select new { g.Key, totalPnl = g.Sum(n => n.TotalPnL) }).ToList(); //------------------------------ // 起算日前一交易日的累计数据 //------------------------------ var preStartQuery = from n in t1Datas where n.TradeType == "场内期权" select new { n.ExchangeOptionCode, TotalPnL = (double?)n.TotalPnL }; //------------------------------ // 区间内的累计数据(持仓+到期-起始) //------------------------------ var totalPnlQuery = from t1 in positionQuery.Concat(finishedQuery) join t2 in preStartQuery on t1.Key equals t2.ExchangeOptionCode into tt from t2 in tt.DefaultIfEmpty() select t1.totalPnl - (t2?.TotalPnL ?? 0); return totalPnlQuery.Sum(n => (double?)n) ?? 0; } private IEnumerable CalculateExchangeListOptionRisks(DateTime settleDate, RiskRequestModel reqModel, List t2PositionDatas, List t2RiskDatas, List t2PnlDatas) where eodRisk : EodTradeRisk { if (reqModel.ClientIds.Any(n => n > 0) || reqModel.TradeTypes.Any() && !reqModel.TradeTypes.Contains("场内期权")) { return Enumerable.Empty(); } if (t2PositionDatas == null || t2PositionDatas.Count == 0) { return new List(); } var varietyIds = reqModel.VarietyIds != null && reqModel.VarietyIds.Any(n => n > 0) ? reqModel.VarietyIds : Enumerable.Empty(); var underlyingIds = reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any(n => n > 0) ? reqModel.UnderlyingIds : Enumerable.Empty(); var onSitePositionDatas = t2PositionDatas.Where(t => t.TradeId < 1 && t.TradeType == "场内期权").ToList(); if (onSitePositionDatas == null || onSitePositionDatas.Count == 0) { return new List(); } var hedgeUniqueCodeList = onSitePositionDatas.Select(p => p.HedgeUniqueCode).Distinct().ToList(); List onSiteRiskDatas = null; if (t2RiskDatas != null && t2RiskDatas.Count > 0) { onSiteRiskDatas = t2RiskDatas.Where(p => hedgeUniqueCodeList.Contains(p.HedgeUniqueCode)).ToList(); } if (onSiteRiskDatas == null) { onSiteRiskDatas = new List(); } var umCodes = onSitePositionDatas.Select(p => p.UnderlyingCode).Distinct().ToList(); List umList = null; if (umCodes != null && umCodes.Count > 0) { umList = DbContext.underlying_manager.AsNoTracking().Where(p => umCodes.Contains(p.UnderlyingCode)).ToList(); } if (umList == null) { umList = new List(); } var exchangeOptionCodes = onSitePositionDatas.Select(p => p.ExchangeOptionCode).Distinct().ToList(); List exchangeListOptionList = null; if (exchangeOptionCodes != null && exchangeOptionCodes.Count > 0) { exchangeListOptionList = DbContext.exchange_list_option.AsNoTracking().Where(p => exchangeOptionCodes.Contains(p.ContractCode)).ToList(); } if (exchangeListOptionList == null) { exchangeListOptionList = new List(); } var query = from risk in onSiteRiskDatas join pos in onSitePositionDatas on risk.HedgeUniqueCode equals pos.HedgeUniqueCode join un in umList on pos.UnderlyingCode equals un.UnderlyingCode join ex in exchangeListOptionList on pos.ExchangeOptionCode equals ex.ContractCode where (!underlyingIds.Any() || underlyingIds.Contains(un.id)) && (!varietyIds.Any() || varietyIds.Contains(un.UnderlyingTypeId)) select new EodPositionRisksDTO { id = -pos.id, PV = pos.Pv, RoundedPV = pos.RoundedPv, PositionPnl = pos.PositionPnL, RoundedPositionPnl = pos.RoundedPositionPnL, Vega = risk.Vega, Theta = risk.Theta, Rho = risk.Rho, Delta = risk.Delta, Gamma = risk.Gamma, DeltaCash = risk.DeltaCash, GammaCash = risk.GammaCash, VegaCash = risk.VegaCash, Exposure = risk.CreditExposure, CurrentVolatility = risk.Vol, Notional = pos.Amount, OriginalNotional = pos.Amount, TradePrice = pos.Cost, TradeSinglePrice = pos.Amount > 0 ? pos.Cost / pos.Amount : 0, TradeType = pos.TradeType, UnderlyingCode = pos.UnderlyingCode, UnderlyingPrice = un.Price ?? 0, UnderlyingId = un.id, VarietyId = un.UnderlyingTypeId, UnderlyingAssetName = un.UnderlyingName, Margin = pos.Margin, RealizedPnl = pos.TotalPnL - (double)pos.PositionPnL, ExchangeOptionCode = pos.ExchangeOptionCode, Strike = ex.Strike, ExerciseDate = ex.MaturityDate, OptionType = ex.OptionType, TradeDate = ex.OpenDate, GammaLots = NumberHelper.Normalize(risk.Gamma / un.ContractSize), DeltaLots = NumberHelper.Normalize(risk.Delta / un.ContractSize), TradeOriginalAmount = un != null ? pos.Amount / un.CountRatio : pos.Amount }; var datas = query.ToArray(); foreach (var data in datas) { data.RiskFreeRate = valuedateBLL.RiskFreeRate / 100; //var um = DataCacheProvider.GetUnderlyingDataSource().GetData(data.UnderlyingCode); //if (um != null) //{ // data.GammaLots = NumberHelper.Normalize(data.Gamma / um.ContractSize); // data.DeltaLots = NumberHelper.Normalize(data.Delta / um.ContractSize); //} data.Rho *= 100; //data.TradeOriginalAmount = um != null ? data.OriginalNotional / um.CountRatio : data.OriginalNotional; } return datas; } private List GetEodTradeJsonList(List t2PositionDatas, List t1ToT2Datas) { var result = new List(); List queryList = new List(); if (t2PositionDatas != null && t2PositionDatas.Count > 0) { var queryDtos1 = t2PositionDatas.Where(p => p.TradeId > 0).Select(p => new EodTradeJsonQueryDto { ValueDate = p.ValueDate, TradeId = p.ParentTradeId > 0 ? p.ParentTradeId : p.TradeId }).ToList(); if (queryDtos1 != null && queryDtos1.Count > 0) { queryList.AddRange(queryDtos1); } } if (t1ToT2Datas != null && t1ToT2Datas.Count > 0) { var queryDtos2 = t1ToT2Datas.Where(p => p.TradeId > 0).Select(p => new EodTradeJsonQueryDto { ValueDate = p.ValueDate, TradeId = p.ParentTradeId > 0 ? p.ParentTradeId : p.TradeId }).ToList(); if (queryDtos2 != null && queryDtos2.Count > 0) { queryList.AddRange(queryDtos2); } } if (queryList.Count > 0) { var comparer = new EodTradeJsonQueryDtoComparer(); queryList = queryList.Distinct(comparer).ToList(); } DbContext.Database.SetCommandTimeout(1800); result = GetEodTradeList(queryList); return result; } private List GetEodTradeList(List queryList) { if(queryList== null||queryList.Count==0) { return new List(); } if (queryList.Count < 10000) { return GetEodTradeListByQuery(queryList); } List>> tasks = new List>>(); int pageIndex = 1; int pageSize = 15000; var itemList = queryList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); while (itemList != null && itemList.Count > 0) { tasks.Add(CreateGetEodTradeListTask(itemList)); pageIndex++; itemList = queryList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } tasks.ForEach(p => p.Start()); System.Threading.Tasks.Task.WaitAll(tasks.ToArray()); List result = new List(); tasks.ForEach(p => { if (p.Result != null && p.Result.Count > 0) { result.AddRange(p.Result); } }); return result; } private List GetEodTradeListByQuery(List queryList) { var result = new List(); if (queryList.Count > 0) { var sql = "select ValueDate,TradeId,TradeJson from eod_trade where (ValueDate,TradeId) in ({0})"; int pageIndex = 1; int pageSize = 1000; var itemList = queryList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); using (var db = DbContextFactory.GetYLDbContext()) { var conn = db.Database.GetDbConnection(); db.Database.SetCommandTimeout(1800); while (itemList != null && itemList.Count > 0) { var sb = new StringBuilder(); for (int i = 0; i < itemList.Count; i++) { sb.AppendFormat("('{0}',{1})", ((DateTime)(itemList[i].ValueDate)).ToString("yyyy-MM-dd"), itemList[i].TradeId); if (i < (itemList.Count - 1)) { sb.Append(","); } } var datas = conn.Query(String.Format(sql, sb.ToString()),commandTimeout:1800).ToList(); //var datas = GetEodTradeListForDataReader(conn, String.Format(sql, sb.ToString())); if (datas != null && datas.Count > 0) { result.AddRange(datas); } pageIndex++; itemList = queryList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } } } return result; } //private List GetEodTradeListForDataReader(DbConnection conn,string sql) //{ // List result = new List(); // MySqlCommand command = new MySqlCommand(sql, (MySqlConnection)conn); // var dr = command.ExecuteReader(); // while (dr.Read()) // { // result.Add(new EodTradeJsonDto { // ValueDate = DateTime.Parse(dr["ValueDate"].ToString()), // TradeId = int.Parse(dr["TradeId"].ToString()), // TradeJson = dr["TradeJson"].ToString() // }); // } // dr.Close(); // dr.Dispose(); // return result; //} private Task> CreateGetEodTradeListTask(List queryList) { return new Task>(() => { return GetEodTradeListByQuery(queryList); }); } private List GetOnSitePositionDatas(DbConnection conn,List onSiteTradeList) { var onSiteT1ToT2DataSql = "SELECT ValueDate,TradeId,ClientId,HedgeUniqueCode,ParentTradeId,UnderlyingCode,ExchangeOptionCode,UnderlyingId,BookId,StructureType,TradeType,TotalPnL,Commission FROM {0} WHERE (ValueDate,TradeId,HedgeUniqueCode) in ({1})"; var result = new List(); int pageIndex = 1; int pageSize = 1000; var itemList = onSiteTradeList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); while (itemList != null && itemList.Count > 0) { var onSiteSb = new StringBuilder(); for (int i = 0; i < itemList.Count; i++) { onSiteSb.AppendFormat("('{0}',0,'{1}')", ((DateTime)(itemList[i].MaturityDate)).ToString("yyyy-MM-dd"), HedgePnlCalc.GetHedgeUniqueCode(itemList[i].AssetBookId, itemList[i].TradeType, HedgePnlCalc.GetHedgeLongShort(itemList[i].TradeType, itemList[i].TradeSide), itemList[i].UnderlyingCode, itemList[i].OptionCode)); if (i < (itemList.Count - 1)) { onSiteSb.Append(","); } } var t1ToT2Datas = conn.Query(String.Format(onSiteT1ToT2DataSql, DbContext.GetTableName(), onSiteSb.ToString())).ToList(); if(t1ToT2Datas != null&& t1ToT2Datas.Count > 0) { result.AddRange(t1ToT2Datas); } pageIndex++; itemList = onSiteTradeList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } return result; } /// /// 获取时间点 T1 T2 相关数据 /// /// /// /// /// /// /// /// /// /// /// /// /// private bool GetT1AndT2SourceData(RiskRequestModel reqModel,DateTime dateT1, DateTime dateT2, DateTime preDateT2, out List t1Datas,out List t2PositionDatas, out List t2RiskDatas, out List t2PnlDatas,out List t1ToT2Datas, out List eodDatas,out List preDateT2Datas) where eodRisk : EodTradeRisk where eodPnl : EodPnl { var task1 = CreateGetT1DatasTask(dateT1); string tradeWhere, onSiteTradeWhere, predicateWhere,inSiteWhere; MakeCondition(reqModel, out tradeWhere, out onSiteTradeWhere, out predicateWhere,out inSiteWhere); var task2 = CreateGetT2DatasTask(reqModel, dateT2, predicateWhere); tradeWhere = " UnWindDate>@StartTime and UnWindDate<@EndTime and TradeStatus in @TradeCompletedStatus and " + tradeWhere; var task3 = CreateGetT1ToT2DatasTask(reqModel, dateT1, dateT2, onSiteTradeWhere, tradeWhere,inSiteWhere); var task4 = CreateGetPreT2DatasTask(preDateT2); task1.Start(); task2.Start(); task3.Start(); task4.Start(); System.Threading.Tasks.Task.WaitAll(task1, task2, task3,task4); t1Datas = task1.Result; t2PositionDatas = task2.Result.T2PositionDatas; t2RiskDatas = task2.Result.T2RiskDatas; t2PnlDatas = task2.Result.T2PnlDatas; t1ToT2Datas = task3.Result; preDateT2Datas = task4.Result; //eodDatas = GetEodTradeJsonList(t2PositionDatas, t1ToT2Datas); if (t1Datas == null) { t1Datas = new List(); } if (t2PositionDatas == null) { t2PositionDatas = new List(); } if (t2RiskDatas == null) { t2RiskDatas = new List(); } if (t2PnlDatas == null) { t2PnlDatas = new List(); } if (t1ToT2Datas == null) { t1ToT2Datas = new List(); } eodDatas = null; //if (eodDatas == null) //{ // eodDatas = new List(); //} if (preDateT2Datas == null) { preDateT2Datas = new List(); } return true; } /// /// 获取T1 时间点数据 /// /// /// public Task> CreateGetT1DatasTask(DateTime dateT1) { return new Task>(() => { using (var db = DbContextFactory.GetYLDbContext()) { db.Database.SetCommandTimeout(1800); return db.Set().Where(p => p.ValueDate == dateT1).Select(p => new T1DataDto { ValueDate = p.ValueDate, TradeId = p.TradeId, HedgeUniqueCode = p.HedgeUniqueCode, UnderlyingCode = p.UnderlyingCode, ExchangeOptionCode = p.ExchangeOptionCode, TotalPnL = p.TotalPnL, Cost = p.Cost, Pv = p.Pv, TradeType = p.TradeType, ClientId = p.ClientId, BookId= p.BookId, Commission=p.Commission }).ToList(); } }); } /// /// 获取T2-1 时间点数据 /// /// /// private Task> CreateGetPreT2DatasTask(DateTime date) { return new Task>(() => { List tradeTypes = new List() { "场内期权", "商品期货", "股票" }; using (var db = DbContextFactory.GetYLDbContext()) { db.Database.SetCommandTimeout(1800); return db.Set().Where(p => p.ValueDate == date&& tradeTypes.Contains(p.TradeType)).Select(p => new PreDateT2DataDto { ValueDate = p.ValueDate, TradeId = p.TradeId, HedgeUniqueCode = p.HedgeUniqueCode, Commission = p.Commission }).ToList(); } }); } /// /// 获取 T2 时间点 数据 /// /// /// /// /// /// /// private Task CreateGetT2DatasTask(RiskRequestModel reqModel, DateTime dateT2,string predicateWhere) where eodRisk : EodTradeRisk where eodPnl : EodPnl { return new Task(() => { T2DataResult result= new T2DataResult(); using (var db = DbContextFactory.GetYLDbContext()) { var t2PositionDateSql = string.Format("select id,ValueDate,TradeId,HedgeUniqueCode,ParentTradeId,UnderlyingCode,ExchangeOptionCode,UnderlyingId,BookId,StructureType,TradeType,Amount,TotalPnL,Pv,Cost,Commission,DailyPnL,RoundedPv,PositionPnL,RoundedPositionPnL,Margin from {0} where {1}", db.GetTableName(), predicateWhere); db.Database.SetCommandTimeout(1800); var conn = db.Database.GetDbConnection(); var t2PositionDatas = conn.Query(t2PositionDateSql, new { EndTime = dateT2, UserAssets = reqModel.UserAssets, UserClients = reqModel.UserClients, ClientIds = reqModel.ClientIds, BookIds = reqModel.BookIds, TradeTypes = reqModel.TradeTypes, TraderIds = reqModel.TraderIds, TagIds = reqModel.TagIds, UnderlyingIds = reqModel.UnderlyingIds, VarietyIds = reqModel.VarietyIds },commandTimeout:1800).ToList(); var t2RiskDatas = new List(); var t2PnlDatas = new List(); if (t2PositionDatas != null && t2PositionDatas.Count > 0) { var t2TradeIds = t2PositionDatas.Where(p => p.TradeId > 0).Select(p => p.TradeId).Distinct().ToList(); if (t2TradeIds != null && t2TradeIds.Count > 0) { var riskDatas = db.Set().AsNoTracking().Where(p => p.ValueDate == dateT2 && t2TradeIds.Contains(p.TradeId)).Select(p => new T2RiskDataDto { ValueDate = p.ValueDate, TradeId = p.TradeId, HedgeUniqueCode = p.HedgeUniqueCode, Delta = p.Delta, DeltaCash = p.DeltaCash, Gamma = p.Gamma, GammaCash = p.GammaCash, Vega = p.Vega, Rho = p.Rho, Theta = p.Theta, VegaCash = p.VegaCash, CreditExposure = p.CreditExposure, Vol = p.Vol }).ToList(); if (riskDatas != null && riskDatas.Count > 0) { t2RiskDatas.AddRange(riskDatas); } var pnlDatas = db.Set().AsNoTracking().Where(p => p.ValueDate == dateT2 && t2TradeIds.Contains(p.TradeId)).Select(p => new T2PnlDataDto { ValueDate = p.ValueDate, TradeId = p.TradeId, HedgeUniqueCode = p.HedgeUniqueCode, PnLDelta = p.PnLDelta, PnLGamma = p.PnLGamma, PnLPsi = p.PnLPsi, PnLTheta = p.PnLTheta, PnLVega = p.PnLVega }).ToList(); if (pnlDatas != null && pnlDatas.Count > 0) { t2PnlDatas.AddRange(pnlDatas); } } var t2HedgeCodes = t2PositionDatas.Where(p => p.TradeId == 0).Select(p => p.HedgeUniqueCode).Distinct().ToList(); if (t2HedgeCodes != null && t2HedgeCodes.Count > 0) { var riskHegeDatas = db.Set().AsNoTracking().Where(p => p.ValueDate == dateT2 && p.TradeId == 0 && t2HedgeCodes.Contains(p.HedgeUniqueCode)).Select(p => new T2RiskDataDto { ValueDate = p.ValueDate, TradeId = p.TradeId, HedgeUniqueCode = p.HedgeUniqueCode, Delta = p.Delta, DeltaCash = p.DeltaCash, Gamma = p.Gamma, GammaCash = p.GammaCash, Vega = p.Vega, Rho = p.Rho, Theta = p.Theta }).ToList(); if (riskHegeDatas != null && riskHegeDatas.Count > 0) { t2RiskDatas.AddRange(riskHegeDatas); } var pnlHegeDatas = db.Set().AsNoTracking().Where(p => p.ValueDate == dateT2 && p.TradeId == 0 && t2HedgeCodes.Contains(p.HedgeUniqueCode)).Select(p => new T2PnlDataDto { ValueDate = p.ValueDate, TradeId = p.TradeId, HedgeUniqueCode = p.HedgeUniqueCode, PnLDelta = p.PnLDelta, PnLGamma = p.PnLGamma, PnLPsi = p.PnLPsi, PnLTheta = p.PnLTheta, PnLVega = p.PnLVega }).ToList(); if (pnlHegeDatas != null && pnlHegeDatas.Count > 0) { t2PnlDatas.AddRange(pnlHegeDatas); } } } result.T2PositionDatas = t2PositionDatas; result.T2RiskDatas = t2RiskDatas; result.T2PnlDatas = t2PnlDatas; return result; } }); } /// /// 获取 T1 - T2 之间的数据 /// /// /// /// /// /// /// public Task> CreateGetT1ToT2DatasTask(RiskRequestModel reqModel, DateTime dateT1, DateTime dateT2,string onSiteTradeWhere,string tradeWhere,string inSiteWhere) { return new Task>(() => { var t1ToT2Datas = new List(); var onSiteT1ToT2Datas = new List(); using (var db=DbContextFactory.GetYLDbContext()) { db.Database.SetCommandTimeout(1800); var t1ToT2Sql = string.Format("SELECT ValueDate,TradeId,ClientId,HedgeUniqueCode,ParentTradeId,UnderlyingCode,ExchangeOptionCode,UnderlyingId,BookId,StructureType,TradeType,TotalPnL,Commission FROM {0} WHERE (ValueDate,TradeId,HedgeUniqueCode) IN (SELECT UnWindDate AS ValueDate,id AS TradeId,'' AS HedgeUniqueCode FROM trade WHERE {1})", db.GetTableName(), tradeWhere); var conn = db.Database.GetDbConnection(); // 1 获取场外数据 var outSiteT1ToT2Datas = conn.Query(t1ToT2Sql, new { StartTime = dateT1, EndTime = dateT2, UserAssets = reqModel.UserAssets, UserClients = reqModel.UserClients, ClientIds = reqModel.ClientIds, BookIds = reqModel.BookIds, TradeTypes = reqModel.TradeTypes, TraderIds = reqModel.TraderIds, TagIds = reqModel.TagIds, UnderlyingIds = reqModel.UnderlyingIds, VarietyIds = reqModel.VarietyIds, TradeCompletedStatus = ConsTrade.TradeCompleteStatus },commandTimeout:1800).ToList(); if (outSiteT1ToT2Datas != null && outSiteT1ToT2Datas.Count > 0) { t1ToT2Datas.AddRange(outSiteT1ToT2Datas); } //onSiteTradeWhere = " MaturityDate>@StartTime and MaturityDate<@EndTime and" + onSiteTradeWhere; //var onSiteTradeList = conn.Query(String.Format("select MaturityDate,AssetBookId,TradeType,TradeSide,UnderlyingCode,OptionCode from exchange_trade where {0}", onSiteTradeWhere), new //{ // StartTime = dateT1, // EndTime = dateT2, // UserAssets = reqModel.UserAssets, // UserClients = reqModel.UserClients, // ClientIds = reqModel.ClientIds, // BookIds = reqModel.BookIds, // TradeTypes = reqModel.TradeTypes, // TraderIds = reqModel.TraderIds, // TagIds = reqModel.TagIds, // UnderlyingIds = reqModel.UnderlyingIds, // VarietyIds = reqModel.VarietyIds, //},commandTimeout:1800).ToList(); //if (onSiteTradeList != null && onSiteTradeList.Count > 0) //{ // var onSitePostionDatas = GetOnSitePositionDatas(conn, onSiteTradeList); // if (onSitePostionDatas != null && onSitePostionDatas.Count > 0) // { // t1ToT2Datas.AddRange(onSitePostionDatas); // } //} //2、获取场内数据 场内交易对应 eod_trade_position数据获取 从 underlying_manager 取期货数据 exchange_list_option 全部 var instrumentTypes = new List { ConsGlobal.InstrumentType.GetFromDesc("股指期货"), ConsGlobal.InstrumentType.GetFromDesc("商品期货"), ConsGlobal.InstrumentType.GetFromDesc("黄金期货"), ConsGlobal.InstrumentType.GetFromDesc("国债期货"), ConsGlobal.InstrumentType.GetFromDesc("其他期货"), ConsGlobal.InstrumentType.GetFromDesc("境外期货") }; var managerSql = "select MaturityDate,UnderlyingCode from underlying_manager where MaturityDate>@StartTime and MaturityDate<@EndTime and UnderlyingInstrumentType in @UnderlyingInstrumentTypes"; var exchangeSql = "select MaturityDate,ContractCode from exchange_list_option where MaturityDate>@StartTime and MaturityDate<@EndTime"; var managerList = conn.Query(managerSql, new { StartTime = dateT1, EndTime = dateT2, UnderlyingInstrumentTypes= instrumentTypes },commandTimeout:600).ToList(); var onSiteDatas1 = GetOnSiteDataByUnderlyManagerList(reqModel, conn, managerList, inSiteWhere); if (onSiteDatas1 != null && onSiteDatas1.Count > 0) { onSiteT1ToT2Datas.AddRange(onSiteDatas1); } var exchangeList = conn.Query(exchangeSql, new { StartTime = dateT1, EndTime = dateT2, }, commandTimeout: 600).ToList(); var onSiteDatas2 = GetOnSiteDataByUnderlyExchangeList(reqModel,conn, exchangeList, inSiteWhere); if (onSiteDatas2 != null && onSiteDatas2.Count > 0) { onSiteT1ToT2Datas.AddRange(onSiteDatas2); } } if (onSiteT1ToT2Datas != null && onSiteT1ToT2Datas.Count > 0) { if (reqModel.UserAssets != null && reqModel.UserAssets.Count > 0) { onSiteT1ToT2Datas = onSiteT1ToT2Datas.Where(p => reqModel.UserAssets.Contains(p.BookId)).ToList(); } if (reqModel.BookIds != null && reqModel.BookIds.Count > 0) { onSiteT1ToT2Datas = onSiteT1ToT2Datas.Where(p => reqModel.UserAssets.Contains(p.BookId)).ToList(); } //if (reqModel.VarietyIds != null && reqModel.VarietyIds.Any() && reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any()) //{ // predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; // tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; //} //else //{ // if (reqModel.VarietyIds != null && reqModel.VarietyIds.Any()) // { // predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; // tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; // } // if (reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any()) // { // predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; // tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; // } //} t1ToT2Datas.AddRange(onSiteT1ToT2Datas); } return t1ToT2Datas; }); } private List GetOnSiteDataByUnderlyExchangeList(RiskRequestModel reqModel,DbConnection conn, List managerList, string inSiteWhere) { if (managerList == null || managerList.Count == 0) { return new List(); } var onSiteT1ToT2DataSql = "SELECT ValueDate,TradeId,ClientId,HedgeUniqueCode,ParentTradeId,UnderlyingCode,ExchangeOptionCode,UnderlyingId,BookId,StructureType,TradeType,TotalPnL,Commission FROM {0} WHERE (ValueDate,TradeId,ExchangeOptionCode) in ({1}) and " + inSiteWhere; var result = new List(); int pageIndex = 1; int pageSize = 1000; var itemList = managerList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); while (itemList != null && itemList.Count > 0) { var onSiteSb = new StringBuilder(); for (int i = 0; i < itemList.Count; i++) { onSiteSb.AppendFormat("('{0}',0,'{1}')", ((DateTime)(itemList[i].MaturityDate)).ToString("yyyy-MM-dd"), itemList[i].ContractCode); if (i < (itemList.Count - 1)) { onSiteSb.Append(","); } } var t1ToT2Datas = conn.Query(String.Format(onSiteT1ToT2DataSql, DbContext.GetTableName(), onSiteSb.ToString()), new { UserAssets = reqModel.UserAssets, UserClients = reqModel.UserClients, ClientIds = reqModel.ClientIds, BookIds = reqModel.BookIds, TradeTypes = reqModel.TradeTypes, TraderIds = reqModel.TraderIds, TagIds = reqModel.TagIds, UnderlyingIds = reqModel.UnderlyingIds, VarietyIds = reqModel.VarietyIds }, commandTimeout: 600).ToList(); if (t1ToT2Datas != null && t1ToT2Datas.Count > 0) { result.AddRange(t1ToT2Datas); } pageIndex++; itemList = managerList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } return result; } private List GetOnSiteDataByUnderlyManagerList(RiskRequestModel reqModel,DbConnection conn,List managerList,string inSiteWhere) { if (managerList == null || managerList.Count == 0) { return new List(); } var onSiteT1ToT2DataSql = "SELECT ValueDate,TradeId,ClientId,HedgeUniqueCode,ParentTradeId,UnderlyingCode,ExchangeOptionCode,UnderlyingId,BookId,StructureType,TradeType,TotalPnL,Commission FROM {0} WHERE (ValueDate,TradeId,UnderlyingCode) in ({1}) and " + inSiteWhere; var result = new List(); int pageIndex = 1; int pageSize = 1000; var itemList = managerList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); while (itemList != null && itemList.Count > 0) { var onSiteSb = new StringBuilder(); for (int i = 0; i < itemList.Count; i++) { onSiteSb.AppendFormat("('{0}',0,'{1}')", ((DateTime)(itemList[i].MaturityDate)).ToString("yyyy-MM-dd"), itemList[i].UnderlyingCode); if (i < (itemList.Count - 1)) { onSiteSb.Append(","); } } var t1ToT2Datas = conn.Query(String.Format(onSiteT1ToT2DataSql, DbContext.GetTableName(), onSiteSb.ToString()), new { UserAssets = reqModel.UserAssets, UserClients = reqModel.UserClients, ClientIds = reqModel.ClientIds, BookIds = reqModel.BookIds, TradeTypes = reqModel.TradeTypes, TraderIds = reqModel.TraderIds, TagIds = reqModel.TagIds, UnderlyingIds = reqModel.UnderlyingIds, VarietyIds = reqModel.VarietyIds },commandTimeout:600).ToList(); if (t1ToT2Datas != null && t1ToT2Datas.Count > 0) { result.AddRange(t1ToT2Datas); } pageIndex++; itemList = managerList.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } return result; } private List GetRisExposureItemList(List t1Datas, List t2PositionDatas, List t2RiskDatas, List t2PnlDatas, List t1ToT2Datas, List eodDatas, List preDateT2Datas) { var t1DatasDic = t1Datas.ToDictionary(p => p.TradeId + "_" + (String.IsNullOrEmpty(p.HedgeUniqueCode) ? "" : p.HedgeUniqueCode), p => p); //数据整合 if (t1DatasDic == null) { t1DatasDic = new Dictionary(); } var t2RiskDataDic = t2RiskDatas.ToDictionary(p => p.TradeId + "_" + (String.IsNullOrEmpty(p.HedgeUniqueCode) ? "" : p.HedgeUniqueCode), p => p); var t2PnlDataDic = t2PnlDatas.ToDictionary(p => p.TradeId + "_" + (String.IsNullOrEmpty(p.HedgeUniqueCode) ? "" : p.HedgeUniqueCode), p => p); var preDateT2DatasDic= preDateT2Datas.ToDictionary(p => p.TradeId + "_" + (String.IsNullOrEmpty(p.HedgeUniqueCode) ? "" : p.HedgeUniqueCode), p => p); if (preDateT2DatasDic == null) { preDateT2DatasDic = new Dictionary(); } List riskExposureItemModels = new List(); List tradeIds = new List(); if (t2PositionDatas != null && t2PositionDatas.Count > 0) { var t2TradeIds = t2PositionDatas.Where(p => p.TradeId > 0).Select(p => p.TradeId).Distinct().ToList(); if (t2TradeIds != null && t2TradeIds.Count > 0) { tradeIds.AddRange(t2TradeIds); } } if (t1ToT2Datas != null && t1ToT2Datas.Count > 0) { var t1Tot2TradeIds = t1ToT2Datas.Where(p => p.TradeId > 0).Select(p => p.TradeId).Distinct().ToList(); if (t1Tot2TradeIds != null && t1Tot2TradeIds.Count > 0) { tradeIds.AddRange(t1Tot2TradeIds); } } Dictionary tradeDic = null; if (tradeIds != null && tradeIds.Count > 0) { DbContext.Database.SetCommandTimeout(1800); tradeDic = DbContext.trade.AsNoTracking().Where(p => tradeIds.Contains(p.id)).Select(p => new TradeRiskQueryDto { TradeId = p.id, SpotPrice = p.SpotPrice, OriginalNotional = p.OriginalNotional, OriginalStockEqvNotional = p.OriginalStockEqvNotional }).ToDictionary(p => p.TradeId, p => p); } if (tradeDic == null) { tradeDic = new Dictionary(); } List parentTradeList = new List(); //var eodDataDic = eodDatas.ToDictionary(p => p.TradeId + "_" + p.ValueDate.ToString("yyyy-MM-dd"), p => p); if (t2PositionDatas != null && t2PositionDatas.Count > 0) { t2PositionDatas.ForEach(p => { var model = new RiskExposureItemModel { ValueDate = p.ValueDate, TradeId = p.TradeId, ParentTradeId = p.ParentTradeId ?? 0, UnderlyingCode = p.UnderlyingCode, OptionCode = p.ExchangeOptionCode, UnderlyingId = p.UnderlyingId ?? 0, BookId = p.BookId ?? 0, TradeType = p.StructureType == null || p.StructureType == "" ? p.TradeType : p.StructureType, Amount = p.Amount ?? 0, AccruedTotalPnL = p.TotalPnL, CumulativeFloatProfitLoss = (p.Pv ?? 0) - (p.Cost ?? 0), Commission = p.Commission ?? 0,//总计手续费 DailyCommission= p.Commission ?? 0,//总计手续费 DailyPnl = p.DailyPnL, SpotPrice = 0, }; var key = p.TradeId + "_" + (String.IsNullOrEmpty(p.HedgeUniqueCode) ? "" : p.HedgeUniqueCode); var t1Data = t1DatasDic.ContainsKey(key) ? t1DatasDic[key] : null; if (t1Data != null) { if (PS.Config.Company != Configuration.CompanyEnum.中基石化) //中基 在T2点持仓的交易 累积总盈亏 取 交易开始日到T2时间的的盈亏 即T2时间点的TotalPnl { model.AccruedTotalPnL = model.AccruedTotalPnL - (t1Data.TotalPnL ?? 0); } model.CumulativeFloatProfitLoss = model.CumulativeFloatProfitLoss - (t1Data.Pv ?? 0) - (t1Data.Cost ?? 0); model.Commission = model.Commission - t1Data.Commission; } var preDateT2Data = preDateT2DatasDic.ContainsKey(key) ? preDateT2DatasDic[key] : null; if(preDateT2Data != null) { model.DailyCommission = model.DailyCommission - (preDateT2Data.Commission??0); } var riskData = t2RiskDataDic.ContainsKey(key) ? t2RiskDataDic[key] : null; if (riskData != null) { model.Delta = riskData.Delta; model.DeltaCash = riskData.DeltaCash; model.Gamma = riskData.Gamma; model.GammaCash = riskData.GammaCash; model.Vega = riskData.Vega; model.Rho = riskData.Rho ?? 0 * 100; model.Theta = riskData.Theta; } var pnlData = t2PnlDataDic.ContainsKey(key) ? t2PnlDataDic[key] : null; if (pnlData != null) { model.dPnlDelta = pnlData.PnLDelta ?? 0; model.dPnlGamma = pnlData.PnLGamma ?? 0; model.dPnlTheta = pnlData.PnLTheta ?? 0; model.dPnlVega = pnlData.PnLVega ?? 0; model.dPnlPsi = pnlData.PnLPsi ?? 0; } if (p.TradeId > 0 && tradeDic.ContainsKey((int)p.TradeId)) { var tradeInfo = tradeDic[(int)p.TradeId]; model.SpotPrice = tradeInfo.SpotPrice; model.StockEqvNotional = model.Amount > 0 && tradeInfo.OriginalNotional > 0 ? ((double)tradeInfo.OriginalStockEqvNotional * model.Amount / ((double)tradeInfo.OriginalNotional)) : 0; } //if (p.TradeId > 0) //{ // var eodKey = (p.ParentTradeId > 0 ? p.ParentTradeId : p.TradeId) + "_" + p.ValueDate.ToString("yyyy-MM-dd"); // var eodData = eodDataDic.ContainsKey(eodKey) ? eodDataDic[eodKey] : null; // if (eodData != null) // { // model.eodTrade = new xodTradeBase { TradeJson = eodData.TradeJson }; // } // if (model.eodTrade != null) // { // if (p.ParentTradeId > 0) // { // if (!parentTradeList.Contains((int)p.ParentTradeId)) // { // model.StockEqvNotional = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotional : 0; // model.StockEqvNotionalReal = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotionalReal : 0; // parentTradeList.Add((int)p.ParentTradeId); // } // } // else // { // model.StockEqvNotional = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotional : 0; // model.StockEqvNotionalReal = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotionalReal : 0; // } // } //} riskExposureItemModels.Add(model); }); } if (t1ToT2Datas != null && t1ToT2Datas.Count > 0) { t1ToT2Datas.ForEach(p => { var model = new RiskExposureItemModel { ValueDate = p.ValueDate, TradeId = p.TradeId, ParentTradeId = p.ParentTradeId ?? 0, UnderlyingCode = p.UnderlyingCode, OptionCode = p.ExchangeOptionCode, UnderlyingId = p.UnderlyingId ?? 0, BookId = p.BookId, TradeType = p.StructureType == null || p.StructureType == "" ? p.TradeType : p.StructureType, Commission = p.Commission,//总计手续费 Amount = 0, CumulativeFloatProfitLoss = 0, DailyPnl = 0, Delta = 0, Gamma = 0, Vega = 0, Rho = 0, Theta = 0, DeltaCash = 0, GammaCash = 0, dPnlDelta = 0, dPnlGamma = 0, dPnlTheta = 0, dPnlVega = 0, dPnlPsi = 0, AccruedTotalPnL = p.TotalPnL, SpotPrice = 0, }; var key = p.TradeId + "_" + (String.IsNullOrEmpty(p.HedgeUniqueCode) ? "" : p.HedgeUniqueCode); var t1Data = t1DatasDic.ContainsKey(key) ? t1DatasDic[key] : null; if (t1Data != null) { model.AccruedTotalPnL = model.AccruedTotalPnL - (t1Data.TotalPnL ?? 0); model.Commission = model.Commission - t1Data.Commission; } if (p.TradeId > 0 && tradeDic.ContainsKey((int)p.TradeId)) { var tradeInfo = tradeDic[(int)p.TradeId]; model.SpotPrice = tradeInfo.SpotPrice; model.StockEqvNotional = 0; } if (p.TradeId > 0) { //var eodKey = (p.ParentTradeId > 0 ? p.ParentTradeId : p.TradeId) + "_" + p.ValueDate.ToString("yyyy-MM-dd"); //var eodData = eodDataDic.ContainsKey(eodKey) ? eodDataDic[eodKey] : null; //if (eodData != null) //{ // model.eodTrade = new xodTradeBase { TradeJson = eodData.TradeJson }; //} //if (model.eodTrade != null) //{ // if (p.ParentTradeId > 0) // { // if (!parentTradeList.Contains((int)p.ParentTradeId)) // { // model.StockEqvNotional = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotional : 0; // model.StockEqvNotionalReal = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotionalReal : 0; // parentTradeList.Add((int)p.ParentTradeId); // } // } // else // { // model.StockEqvNotional = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotional : 0; // model.StockEqvNotionalReal = model.eodTrade.trade != null ? model.eodTrade.trade.StockEqvNotionalReal : 0; // } //} } riskExposureItemModels.Add(model); }); } return riskExposureItemModels; } /// /// 获取市场风险图表数据 /// /// /// /// /// /// public Dictionary SearchRiskExposureReportsEchart(RiskRequestModel reqModel, List days) where eodRisk : EodTradeRisk where eodPnl : EodPnl { Dictionary dicResult = new Dictionary(); if (days == null || days.Count == 0) { return dicResult; } reqModel = CheckModelForEchart(reqModel, days); string predicateWhere = ""; MakeConditionForEchart(reqModel,out predicateWhere); List t2PositionDatas = GetPositionData(reqModel, days, predicateWhere); if(t2PositionDatas==null|| t2PositionDatas.Count == 0) { return dicResult; } Dictionary> dicExposureItemModels = new Dictionary>(); foreach(var p in t2PositionDatas) { if (!dicExposureItemModels.ContainsKey(p.ValueDate)) { dicExposureItemModels.Add(p.ValueDate, new List()); } var model = new RiskExposureItemModel { ValueDate = p.ValueDate, TradeId = p.TradeId, ParentTradeId = p.ParentTradeId ?? 0, UnderlyingCode = p.UnderlyingCode, OptionCode = p.ExchangeOptionCode, UnderlyingId = p.UnderlyingId ?? 0, BookId = p.BookId ?? 0, TradeType = p.StructureType == null || p.StructureType == "" ? p.TradeType : p.StructureType, Amount = p.Amount ?? 0, AccruedTotalPnL = p.DailyPnL, CumulativeFloatProfitLoss = (p.Pv ?? 0) - (p.Cost ?? 0), Commission = p.Commission ?? 0,//总计手续费 DailyCommission = p.Commission ?? 0,//总计手续费 DailyPnl = p.DailyPnL, SpotPrice = 0, }; dicExposureItemModels[p.ValueDate].Add(model); } var structList = DbContext.Structure_Info.Select(o => o.StructureName).ToList(); days.ForEach(p => { if (dicExposureItemModels.ContainsKey(p)) { dicResult.Add(p, MakeRiskExposureReportsEchartResultData(dicExposureItemModels[p], structList)); } }); return dicResult; } /// /// 获取position数据 /// /// /// /// /// private List GetPositionData(RiskRequestModel reqModel, List days, string predicateWhere) { var result = new List(); List>> taskList = new List>>(); int pageIndex = 1; int pageSize = 20; var itemDays = days.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); while (itemDays != null && itemDays.Count > 0) { taskList.Add(CreateGetPositionDatasTask(reqModel, itemDays, predicateWhere)); pageIndex++; itemDays = days.Skip((pageIndex - 1) * pageSize).Take(pageSize).ToList(); } taskList.ForEach(p => { p.Start(); }); System.Threading.Tasks.Task.WaitAll(taskList.ToArray()); taskList.ForEach(p => { if (p.Result != null && p.Result.Count > 0) { result.AddRange(p.Result); } }); return result; } /// /// 获取一系列时间的position数据 /// /// /// /// /// private Task> CreateGetPositionDatasTask(RiskRequestModel reqModel, List days, string predicateWhere) { return new Task>(() => { using (var db = DbContextFactory.GetYLDbContext()) { var t2PositionDateSql = string.Format("select id,ValueDate,TradeId,HedgeUniqueCode,ParentTradeId,UnderlyingCode,ExchangeOptionCode,UnderlyingId,BookId,StructureType,TradeType,Amount,TotalPnL,Pv,Cost,Commission,DailyPnL,RoundedPv,PositionPnL,RoundedPositionPnL,Margin from {0} where {1}", db.GetTableName(), predicateWhere); db.Database.SetCommandTimeout(1800); var conn = db.Database.GetDbConnection(); return conn.Query(t2PositionDateSql, new { Days = days, UserAssets = reqModel.UserAssets, UserClients = reqModel.UserClients, ClientIds = reqModel.ClientIds, BookIds = reqModel.BookIds, TradeTypes = reqModel.TradeTypes, TraderIds = reqModel.TraderIds, TagIds = reqModel.TagIds, UnderlyingIds = reqModel.UnderlyingIds, VarietyIds = reqModel.VarietyIds }, commandTimeout: 1800).ToList(); } }); } /// /// 构造查询条件 /// /// /// private void MakeConditionForEchart(RiskRequestModel reqModel, out string predicateWhere) { var tradeWhere = "IFNULL(ValidState,'')<>'InValid'"; predicateWhere = " ValueDate in @Days and TradeType<>'结构化交易' and TradeType<>'现金流交易'"; tradeWhere += " and TradeType<>'结构化交易' and TradeType<>'现金流交易'"; //if (reqModel.UserAssets != null && reqModel.UserAssets.Count > 0 && !(reqModel.UserClients != null && reqModel.UserClients.Count > 0)) //{ // tradeWhere += " and AssetId in @UserAssets"; // predicateWhere += " and BookId in @UserAssets"; //} //if (!(reqModel.UserAssets != null && reqModel.UserAssets.Count > 0) && (reqModel.UserClients != null && reqModel.UserClients.Count > 0)) //{ // tradeWhere += " and ClientId in @UserClients"; // predicateWhere += " and ClientId in @UserClients"; //} //if ((reqModel.UserAssets != null && reqModel.UserAssets.Count > 0) && (reqModel.UserClients != null && reqModel.UserClients.Count > 0)) //{ // tradeWhere += " and (AssetId in @UserAssets or ClientId in @UserClients)"; // predicateWhere += " and (BookId in @UserAssets or ClientId in @UserClients)"; //} //if (reqModel.ClientIds != null && reqModel.ClientIds.Count > 0) //{ // predicateWhere += " and ClientId in @ClientIds"; // tradeWhere += " and ClientId in @ClientIds"; //} if (reqModel.BookIds != null && reqModel.BookIds.Count > 0) { predicateWhere += " and BookId in @BookIds"; tradeWhere += " and AssetId in @BookIds"; } if (reqModel.TradeTypes != null && reqModel.TradeTypes.Any()) { predicateWhere += " and ((IFNULL(StructureType,'')='' and TradeType in @TradeTypes) or (IFNULL(StructureType,'')<>'' and StructureType in @TradeTypes))"; tradeWhere += " and ((IFNULL(StructureType,'')='' and TradeType in @TradeTypes) or (IFNULL(StructureType,'')<>'' and StructureType in @TradeTypes))"; } //if (reqModel.TraderIds != null && reqModel.TraderIds.Any()) //{ // predicateWhere += " and TradeId>0"; // tradeWhere += " and TraderId in @TraderIds"; //} //if (reqModel.TagIds != null && reqModel.TagIds.Count > 0) //{ // tradeWhere += " and id in (select TradeId from trade_tag where TagId in @TagIds)"; //} if (reqModel.VarietyIds != null && reqModel.VarietyIds.Any() && reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any()) { predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds and UnderlyingTypeId in @VarietyIds)"; } else { if (reqModel.VarietyIds != null && reqModel.VarietyIds.Any()) { predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where UnderlyingTypeId in @VarietyIds)"; } if (reqModel.UnderlyingIds != null && reqModel.UnderlyingIds.Any()) { predicateWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; tradeWhere += " and UnderlyingCode in (select UnderlyingCode from underlying_manager where id in @UnderlyingIds)"; } } predicateWhere += String.Format(" and (TradeId<1 or TradeId in (select id from trade where {0}))", tradeWhere); } private RiskRequestModel CheckModelForEchart(RiskRequestModel reqModel, List days) { if (reqModel == null) { throw new ServiceException("实体不能为空"); } DateTime settleDate; if (reqModel.EodSettlePriceMode == "结算价") { settleDate = EodOperationBase.GetLastSettlementDate_Settle(false); } else { settleDate = EodOperationBase.GetLastSettlementDate(valuedateBLL.ValueDate); } if (days.Max() > settleDate) { throw new ServiceException($"结束日期不能大于上一次收盘日期{settleDate:yyyy-MM-dd}"); } return reqModel.Normalize(); } /// /// 组装图表数据 /// /// /// private RiskExposureReportModel MakeRiskExposureReportsEchartResultData(List list,List structList) { //合并处理 var underlyingGroup = list.GroupBy(e => e.UnderlyingCode.ToUpperInvariant()); var underlyingRiskList = new List(); #region 1.对于最后一日有持仓数据的合约 foreach (var groupItem in underlyingGroup) { var underlyingRisk = new UnderlyingRiskModel(); var otcOptionsTradeType = ConsTrade.OptionTradeTypes.ToList(); otcOptionsTradeType.Add("结构化交易"); otcOptionsTradeType.AddRange(structList); otcOptionsTradeType.Remove("收益互换"); //场外期权 var otcRiskList = groupItem.Where(g => otcOptionsTradeType.Contains(g.TradeType)); underlyingRisk.OtcRisk = new EodRiskModel { Pnl = otcRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0) }; //场内期权 var exchangeRiskList = groupItem.Where(g => g.TradeType == "场内期权"); underlyingRisk.ExOptionRisk = new EodRiskModel { Pnl = exchangeRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0) }; //标的交易 var hedgeRiskList = groupItem.Where(g => g.TradeType == "商品期货" || g.TradeType == "股票" || g.TradeType == "商品现货"); underlyingRisk.FuturesRisk = new EodRiskModel { Pnl = hedgeRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0) }; //远期统计 var forwardRiskList = groupItem.Where(g => g.TradeType == "远期"); underlyingRisk.ForwardRisk = new EodRiskModel { Pnl = forwardRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0) }; //收益互换统计 var swapRiskList = groupItem.Where(g => g.TradeType == "收益互换"); underlyingRisk.SwapRisk = new EodRiskModel { Pnl = swapRiskList.SumDouble(r => r.AccruedTotalPnL ?? 0) }; //汇总合计 underlyingRisk.PortfolioRisk = new EodRiskModel { Pnl = underlyingRisk.OtcRisk.Pnl + underlyingRisk.ExOptionRisk.Pnl + underlyingRisk.FuturesRisk.Pnl + underlyingRisk.ForwardRisk.Pnl + underlyingRisk.SwapRisk.Pnl, }; underlyingRiskList.Add(underlyingRisk); } #endregion underlyingRiskList = underlyingRiskList.OrderBy(u => u, new UnderlyingRiskModelSortComparer()).ToList(); var varietyRiskExposureReports = underlyingRiskList.GroupBy(u => new { u.VarietyCode, u.VarietyOpenLimit, u.VarietyOpenLimitIcon }).Select(g => { var list = g.ToList(); var portfolioSum = new EodRiskModel { Pnl = list.SumDouble(l => l.PortfolioRisk.Pnl) }; var otcSum = new EodRiskModel { Pnl = list.SumDouble(l => l.OtcRisk.Pnl), }; var exchangeListOptionSum = new EodRiskModel { Pnl = list.SumDouble(l => l.ExOptionRisk.Pnl) }; var futuresSum = new EodRiskModel { Pnl = list.SumDouble(l => l.FuturesRisk.Pnl) }; var forwardSum = new EodRiskModel { Pnl = list.SumDouble(l => l.ForwardRisk.Pnl) }; var swapSum = new EodRiskModel { Pnl = list.SumDouble(l => l.SwapRisk.Pnl) }; return new VarietyRiskExposureModel { VarietySum = new RiskExposureReportSumModel { PortfolioSum = portfolioSum, OtcSum = otcSum, ExOptionSum = exchangeListOptionSum, FuturesSum = futuresSum, ForwardSum = forwardSum, SwapSum = swapSum } }; }).ToList(); var result = new RiskExposureReportModel { Sum = new RiskExposureReportSumModel { PortfolioSum = varietyRiskExposureReports.Select(r => r.VarietySum.PortfolioSum).Aggregate(new EodRiskModel(), (p, n) => p + n), OtcSum = varietyRiskExposureReports.Select(r => r.VarietySum.OtcSum).Aggregate(new EodRiskModel(), (p, n) => p + n), ExOptionSum = varietyRiskExposureReports.Select(r => r.VarietySum.ExOptionSum).Aggregate(new EodRiskModel(), (p, n) => p + n), FuturesSum = varietyRiskExposureReports.Select(r => r.VarietySum.FuturesSum).Aggregate(new EodRiskModel(), (p, n) => p + n), ForwardSum = varietyRiskExposureReports.Select(r => r.VarietySum.ForwardSum).Aggregate(new EodRiskModel(), (p, n) => p + n), SwapSum = varietyRiskExposureReports.Select(r => r.VarietySum.SwapSum).Aggregate(new EodRiskModel(), (p, n) => p + n) } }; return result; } } }