using BaseOUDAL; using YLErp.BLL.Eod; using YLErp.Configuration; using YLErp.Model; using YLErp.Modules; namespace YLErp.BLL { public class EodPnlBLL { private readonly YLContext db = new YLContext(); public SearchListResult SearchListByGroupStr(EodPnlReq req, out EodPnlGridSum gsum, List userAssetIds = null) { var query = from tpnl in db.eod_pnl join tpos in db.eod_trade_position on new { tpnl.ValueDate, tpnl.TradeId } equals new { tpos.ValueDate, tpos.TradeId } join td in db.trade on tpnl.TradeId equals td.id select new EodPnlGroup { BookId = td.AssetId, BookName = td.AssetBookName, TradeType = td.TradeType, UnderlyingAssetClass = td.UnderlyingAssetClass, UnderlyingCode = td.UnderlyingCode, ValueDate = tpnl.ValueDate, TradeNumber = td.TradeNumber, OptionType = td.OptionType, BuySell = td.BuySell, Strike = td.Strike, MaturityDate = td.ExerciseDate, Notional = td.Notional, TraderId = td.TraderId, LastPv = tpos.LastPv, Pv = tpos.Pv, DailyPnL = tpos.DailyPnL, PnLPriceResidual = tpnl.PnLPriceResidual, PnLVolResidual = tpnl.PnLVolResidual, PnLPrice = tpnl.PnLPrice, PnLDelta = tpnl.PnLDelta, PnLGamma = tpnl.PnLGamma, PnLVega = tpnl.PnLVega, PnLTheta = tpnl.PnLTheta, PnLVol = tpnl.PnLVol, UnexplainedPnL = tpnl.UnexplainedPnL, ExplainedPnL = tpnl.ExplainedPnL, OptId = tpnl.OptId, OptName = tpnl.OptName, OptDate = tpnl.OptDate, HedgeUniqueCode = tpnl.HedgeUniqueCode, RealizedPnL = tpos.ClosedPnL, PositionPnL = tpos.PositionPnL, TotalPnl = tpos.TotalPnL, AccruedTotalPnl = tpos.TotalPnL//该条件只能查询出场外期权的盈亏信息,场外期权的累积总盈亏就是该条交易的总盈亏; }; //先按用户的权限限制,设置簿记账户 if (userAssetIds != null) { query = query.Where(x => userAssetIds.Contains(x.BookId.Value)); } //如果查询指定了特定簿记账户,再过滤 if (null != req.BookId) { query = query.Where(d => d.BookId == req.BookId); } //过滤簿记账户 if (null != req.BookIds) { query = query.Where(d => req.BookIdList.Contains(d.BookId ?? 0)); } if (null != req.TraderIds) { query = query.Where(d => req.TraderIdList.Contains(d.TraderId ?? 0)); } if (req.ValueDate != DateTime.MinValue && req.ValueDate != null) { query = query.Where(d => d.ValueDate == req.ValueDate); } if (!string.IsNullOrEmpty(req.PositionType)) { query = query.Where(d => d.PositionType.Equals(req.PositionType)); } if (!string.IsNullOrEmpty(req.TradeTypes)) { query = query.Where(d => req.TradeTypesList.Contains(d.TradeType)); } if (!string.IsNullOrEmpty(req.UnderlyingCode)) { query = query.Where(d => req.UnderlyingCode.Equals(d.UnderlyingCode)); } if (req.OptId != null) { query = query.Where(d => d.OptId == req.OptId); } if (!string.IsNullOrEmpty(req.OptName)) { query = query.Where(d => d.OptName.Contains(req.OptName)); } if (req.OptDateStart != DateTime.MinValue) { query = query.Where(d => d.OptDate >= req.OptDateStart); } if (req.OptDateEnd != DateTime.MinValue) { var OptDateTemp = req.OptDateEnd.AddDays(1); query = query.Where(d => d.OptDate < OptDateTemp); } if (req.ValueDateStart != DateTime.MinValue) { if (req.ValueDateStart == req.ValueDateEnd) { query = query.Where(d => req.ValueDateStart == d.ValueDate); } else { query = query.Where(d => req.ValueDateStart <= d.ValueDate); } } if (req.ValueDateEnd != DateTime.MinValue && req.ValueDateEnd != req.ValueDateStart) { query = query.Where(d => req.ValueDateEnd >= d.ValueDate); } if (req.TradeNumberList != null) { query = query.Where(d => req.TradeNumberList.Contains(d.TradeNumber)); } if (req.BookNameList != null) { query = query.Where(d => req.BookNameList.Contains(d.BookName)); } if (req.LastPvStart != null) { if (req.LastPvStart == req.LastPvEnd) { query = query.Where(d => req.LastPvStart == d.LastPv); } else { query = query.Where(d => req.LastPvStart <= d.LastPv); } } if (req.LastPvEnd != null && req.LastPvStart != req.LastPvEnd) { query = query.Where(d => req.LastPvEnd >= d.LastPv); } if (req.PvStart != null) { if (req.PvStart == req.PvEnd) { query = query.Where(d => req.PvStart == d.Pv); } else { query = query.Where(d => req.PvStart <= d.Pv); } } if (req.PvEnd != null && req.PvStart != req.PvEnd) { query = query.Where(d => req.PvEnd >= d.Pv); } if (req.DailyPnLStart != null) { if (req.DailyPnLStart == req.DailyPnLEnd) { query = query.Where(d => req.DailyPnLStart == d.DailyPnL); } else { query = query.Where(d => req.DailyPnLStart <= d.DailyPnL); } } if (req.DailyPnLEnd != null && req.DailyPnLStart != req.DailyPnLEnd) { query = query.Where(d => req.DailyPnLEnd >= d.DailyPnL); } if (req.RealizedPnLStart != null) { if (req.RealizedPnLStart == req.RealizedPnLEnd) { query = query.Where(d => req.RealizedPnLStart == d.RealizedPnL); } else { query = query.Where(d => req.RealizedPnLStart <= d.RealizedPnL); } } if (req.RealizedPnLEnd != null && req.RealizedPnLStart != req.RealizedPnLEnd) { query = query.Where(d => req.RealizedPnLEnd >= d.RealizedPnL); } if (req.UnRealizedPnLStart != null) { if (req.UnRealizedPnLStart == req.UnRealizedPnLEnd) { query = query.Where(d => req.UnRealizedPnLStart == d.UnRealizedPnL); } else { query = query.Where(d => req.UnRealizedPnLStart <= d.UnRealizedPnL); } } if (req.UnRealizedPnLEnd != null && req.UnRealizedPnLStart != req.UnRealizedPnLEnd) { query = query.Where(d => req.UnRealizedPnLEnd >= d.UnRealizedPnL); } if (req.ActualPnLStart != null) { if (req.ActualPnLStart == req.ActualPnLEnd) { query = query.Where(d => req.ActualPnLStart == d.ActualPnL); } else { query = query.Where(d => req.ActualPnLStart <= d.ActualPnL); } } if (req.ActualPnLEnd != null && req.ActualPnLStart != req.ActualPnLEnd) { query = query.Where(d => req.ActualPnLEnd >= d.ActualPnL); } if (req.EstimatePnLStart != null) { if (req.EstimatePnLStart == req.EstimatePnLEnd) { query = query.Where(d => req.EstimatePnLStart == d.EstimatePnL); } else { query = query.Where(d => req.EstimatePnLStart <= d.EstimatePnL); } } if (req.EstimatePnLEnd != null && req.EstimatePnLStart != req.EstimatePnLEnd) { query = query.Where(d => req.EstimatePnLEnd >= d.EstimatePnL); } if (req.UnexplainedPnLStart != null) { if (req.UnexplainedPnLStart == req.UnexplainedPnLEnd) { query = query.Where(d => req.UnexplainedPnLStart == d.UnexplainedPnL); } else { query = query.Where(d => req.UnexplainedPnLStart <= d.UnexplainedPnL); } } if (req.UnexplainedPnLEnd != null && req.UnexplainedPnLStart != req.UnexplainedPnLEnd) { query = query.Where(d => req.UnexplainedPnLEnd >= d.UnexplainedPnL); } if (req.ExplainedPnLStart != null) { if (req.ExplainedPnLStart == req.ExplainedPnLEnd) { query = query.Where(d => req.ExplainedPnLStart == d.ExplainedPnL); } else { query = query.Where(d => req.ExplainedPnLStart <= d.ExplainedPnL); } } if (req.ExplainedPnLEnd != null && req.ExplainedPnLStart != req.ExplainedPnLEnd) { query = query.Where(d => req.ExplainedPnLEnd >= d.ExplainedPnL); } if (req.PositionPnLStart != null) { if (req.PositionPnLStart == req.PositionPnLEnd) { query = query.Where(d => req.PositionPnLStart == d.PositionPnL); } else { query = query.Where(d => req.PositionPnLStart <= d.PositionPnL); } } if (req.PositionPnLEnd != null && req.PositionPnLStart != req.PositionPnLEnd) { query = query.Where(d => req.PositionPnLEnd >= d.PositionPnL); } if (req.TotalPnlStart != null) { if (req.TotalPnlStart == req.TotalPnlEnd) { query = query.Where(d => req.TotalPnlStart == d.TotalPnl); } else { query = query.Where(d => req.TotalPnlStart <= d.TotalPnl); } } if (req.TotalPnlEnd != null && req.TotalPnlStart != req.TotalPnlEnd) { query = query.Where(d => req.TotalPnlEnd >= d.TotalPnl); } if (req.AccruedTotalPnlStart != null) { if (req.AccruedTotalPnlStart == req.AccruedTotalPnlEnd) { query = query.Where(d => req.AccruedTotalPnlStart == d.AccruedTotalPnl); } else { query = query.Where(d => req.AccruedTotalPnlStart <= d.AccruedTotalPnl); } } if (req.AccruedTotalPnlEnd != null && req.AccruedTotalPnlStart != req.AccruedTotalPnlEnd) { query = query.Where(d => req.AccruedTotalPnlEnd >= d.AccruedTotalPnl); } if (req.TradeTypeList != null) { query = query.Where(d => req.TradeTypeList.Contains(d.TradeType)); } if (req.UnderlyingCodeList != null) { query = query.Where(d => req.UnderlyingCodeList.Contains(d.UnderlyingCode)); } if (req.GroupStr != null) { var eodPnlList = query.ToList(); var resultList = new List(); List tempList = null; EodPnlGroup tempObj = null; if (eodPnlList != null) { eodPnlList.ForEach(t => { if (resultList.Count == 0) { resultList.Add(t.Clone()); } else { tempList = resultList; if (req.GroupStr.Contains("标的代码")) { tempList = tempList.Where(a => a.UnderlyingCode == t.UnderlyingCode).ToList(); } if (req.GroupStr.Contains("簿记账户")) { tempList = tempList.Where(a => a.BookName == t.BookName).ToList(); } if (req.GroupStr.Contains("标的品种")) { tempList = tempList.Where(a => a.UnderlyingAssetClass == t.UnderlyingAssetClass).ToList(); } if (req.GroupStr.Contains("结构类型")) { tempList = tempList.Where(a => a.TradeType == t.TradeType).ToList(); } if (tempList != null && tempList.Count > 0) { tempObj = tempList.First(); tempObj.Aggregation(t); } else { resultList.Add(t.Clone()); } } }); } IOrderedEnumerable orderSource = null; if (req.GroupStr.Contains("簿记账户")) { orderSource = resultList.OrderBy(a => a.BookName); } if (req.GroupStr.Contains("标的品种")) { if (orderSource != null) { orderSource = orderSource.ThenBy(a => a.UnderlyingAssetClass); } else { orderSource = resultList.OrderBy(a => a.UnderlyingAssetClass); } } if (req.GroupStr.Contains("标的代码")) { if (orderSource != null) { orderSource = orderSource.ThenBy(a => a.UnderlyingCode); } else { orderSource = resultList.OrderBy(a => a.UnderlyingCode); } } if (req.GroupStr.Contains("结构类型")) { if (orderSource != null) { orderSource = orderSource.ThenBy(a => a.TradeType); } else { orderSource = resultList.OrderBy(a => a.TradeType); } } resultList = orderSource.ToList(); if (req.rows == 0) { req.rows = 100000; } if (req.page <= 0) { req.page = 1; } var retListResult1 = new SearchListResult(); resultList = resultList.OrderBy(t => t.UnderlyingCode).ToList(); retListResult1.records = resultList.Count(); retListResult1.rows = resultList.Skip((req.page - 1) * req.rows).Take(req.rows).ToList(); retListResult1.page = req.page; retListResult1.total = (retListResult1.records - 1) / req.rows + 1; gsum = new EodPnlGridSum(); if (query.Any()) { gsum.LastPvSum = query.Sum(q => q.LastPv); gsum.PvSum = query.Sum(q => q.Pv); gsum.DailyPnLSum = query.Sum(q => q.DailyPnL); gsum.PnLPriceSum = query.Sum(q => q.PnLPrice); gsum.PnLDeltaSum = query.Sum(q => q.PnLDelta); gsum.PnLGammaSum = query.Sum(q => q.PnLGamma); gsum.PnLVegaSum = query.Sum(q => q.PnLVega); gsum.PnLThetaSum = query.Sum(q => q.PnLTheta); gsum.PnLVolSum = query.Sum(q => q.PnLVol); gsum.UnexplainedPnLSum = query.Sum(q => q.UnexplainedPnL); gsum.ExplainedPnLSum = query.Sum(q => q.ExplainedPnL); } retListResult1.Sum = gsum; return retListResult1; } else { if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "UnderlyingCode"; req.sord = "desc"; } var retListResult = BllExtension.ToSearchList(query, req); gsum = new EodPnlGridSum(); if (query.Any()) { gsum.LastPvSum = query.Sum(q => q.LastPv); gsum.PvSum = query.Sum(q => q.Pv); gsum.DailyPnLSum = query.Sum(q => q.DailyPnL); gsum.PnLPriceSum = query.Sum(q => q.PnLPrice); gsum.PnLDeltaSum = query.Sum(q => q.PnLDelta); gsum.PnLGammaSum = query.Sum(q => q.PnLGamma); gsum.PnLVegaSum = query.Sum(q => q.PnLVega); gsum.PnLThetaSum = query.Sum(q => q.PnLTheta); gsum.PnLVolSum = query.Sum(q => q.PnLVol); gsum.UnexplainedPnLSum = query.Sum(q => q.UnexplainedPnL); gsum.ExplainedPnLSum = query.Sum(q => q.ExplainedPnL); } retListResult.Sum = gsum; return retListResult; } } /// /// 盯市报告持仓明细总数(除去互换交易) /// public int SearchPositionCount(int clientId, DateTime valueDate) { //if (IsBaseClient(clientId)) //{ // clientId = 0; //} if (valueDate > EodOperationBase.GetLastSettlementDate(DateTime.Now.Date)) { var suspensionUnderlyingIdList = db.underlying_manager.Where(t => t.UnderlyingStatus == underlying_manager.Status_Suspension).Select(t => t.id).ToList(); var query = from trade in db.trade where ConsTrade.NeedMarginTradeStatusList.Contains(trade.TradeStatus) && (trade.TradeType != "结构化交易" || trade.IsGroup == 1) && trade.IsGroup != 2 && trade.TradeType != "收益互换" && (trade.ExerciseDate >= valueDate || suspensionUnderlyingIdList.Contains(trade.UnderlyingId)) && trade.ValidState != "InValid" && !ConsTrade.TradeTypesForHedge.Contains(trade.TradeType) && (clientId == 0 || trade.ClientId == clientId) select trade.id; return query.Count(); } else { var query = from trade in db.eod_trade join tradeOrigin in db.trade on trade.TradeId equals tradeOrigin.id where ConsTrade.NeedMarginTradeStatusList.Contains(trade.TradeStatus) && !ConsTrade.TradeTypesForHedge.Contains(trade.TradeType) && (tradeOrigin.TradeType != "结构化交易" || tradeOrigin.IsGroup == 1) && tradeOrigin.IsGroup != 2 && tradeOrigin.TradeType != "收益互换" && trade.ValueDate == valueDate && (clientId == 0 || trade.ClientId == clientId) select trade.id; return query.Count(); } } /// /// 盯市报告持仓明细互换总数 /// /// /// /// public int SearchSwapPositionCount(int clientId, DateTime valueDate) { //if (IsBaseClient(clientId)) //{ // clientId = 0; //} if (valueDate > EodOperationBase.GetLastSettlementDate(DateTime.Now.Date)) { var suspensionUnderlyingIdList = db.underlying_manager.Where(t => t.UnderlyingStatus == underlying_manager.Status_Suspension).Select(t => t.id).ToList(); var query = from trade in db.trade where ConsTrade.NeedMarginTradeStatusList.Contains(trade.TradeStatus) && trade.IsGroup != 1 && trade.TradeType == "收益互换" && (trade.ExerciseDate >= valueDate || suspensionUnderlyingIdList.Contains(trade.UnderlyingId)) && trade.ValidState != "InValid" && !ConsTrade.TradeTypesForHedge.Contains(trade.TradeType) && (clientId == 0 || trade.ClientId == clientId) select trade.id; return query.Count(); } else { var query = from trade in db.eod_trade join tradeOrigin in db.trade on trade.TradeId equals tradeOrigin.id where ConsTrade.NeedMarginTradeStatusList.Contains(trade.TradeStatus) && !ConsTrade.TradeTypesForHedge.Contains(trade.TradeType) && tradeOrigin.IsGroup != 1 && tradeOrigin.TradeType == "收益互换" && trade.ValueDate == valueDate && (clientId == 0 || trade.ClientId == clientId) select trade.id; return query.Count(); } } /// /// 获取最新持仓列表信息 /// public SearchListResult SearchLatestPositionList(TradeSpanReq req, out EodPnlGridSum gsum) { var suspensionUnderlyingIdList = db.underlying_manager.Where(t => t.UnderlyingStatus == underlying_manager.Status_Suspension).Select(t => t.id).ToList(); var query = from trade in db.trade where ConsTrade.NeedMarginTradeStatusList.Contains(trade.TradeStatus) && (trade.ExerciseDate >= req.ValueDate || suspensionUnderlyingIdList.Contains(trade.UnderlyingId)) && trade.ValidState != "InValid" && !ConsTrade.TradeTypesForHedge.Contains(trade.TradeType) && trade.ParentTradeId == 0 join underlying in db.underlying_manager on trade.UnderlyingId equals underlying.id join risk in (from tr in db.realtime_trade_risk where tr.ValueDate == req.ValueDate && tr.VolType == "持仓" select tr) on trade.id equals risk.TradeId into risks from risk in risks.DefaultIfEmpty() select new eod_position { TradeId = trade.id, ClientId = trade.ClientId, TradeNumber = trade.TradeNumber, UnderlyingCode = trade.UnderlyingCode, UnderlyingPrice = underlying.Price, //tradeOrigin = trade, ValueDate = req.ValueDate, TradeJson = "", Pv = 0, Pnl = 0, PvDouble = risk.Pv * -1, PnlDouble = risk.Pnl * -1, Vol = risk == null ? 0 : risk.Vol, Delta = risk == null ? 0 : risk.Delta, Gamma = risk == null ? 0 : risk.Gamma, Theta = risk == null ? 0 : risk.Theta, Vega = risk == null ? 0 : risk.Vega, Rho = risk == null ? 0 : risk.Rho }; //var isBaseClient = false; if (req.ClientId != null) { //isBaseClient = IsBaseClient(req.ClientId.Value); //if (!isBaseClient) //{ query = query.Where(d => d.ClientId == req.ClientId); //} } if (req.ValueDate != null && req.ValueDate != DateTime.MinValue) { query = query.Where(d => d.ValueDate == req.ValueDate); } if (string.IsNullOrEmpty(req.sidx)) { req.sidx = "TradeNumber"; req.sord = "desc"; } else { req.sidx = req.sidx.Split(' ')[0]; req.sord = "desc"; } var retListResult = query.ToSearchList(req); foreach (var x in retListResult.rows) { x.Pv = x.PvDouble; x.Pnl = x.PnlDouble; var um = DataCacheProvider.GetUnderlyingDataSource().GetData(x.UnderlyingCode); x.ContractSize = um?.ContractSize ?? 1; } ////判断是否 平台方 //if (isBaseClient) //{ // foreach (var x in retListResult.rows) // { // x.Pv = -x.Pv; // x.Pnl = -x.Pnl; // } //} gsum = new EodPnlGridSum(); if (retListResult.rows.Any()) { gsum.PvSum = retListResult.rows.Sum(q => q.Pv); gsum.DailyPnLSum = retListResult.rows.Sum(q => q.Pnl); gsum.StockEqvNotionalSum = retListResult.rows.Sum(q => q.OriginalStockEqvNotional); } retListResult.Sum = gsum; return retListResult; } /// /// 判断是否 平台方客户(平台方配置的客户本身) /// public static bool IsBaseClient(int clientId) { using (var db = DbContextFactory.GetClientDbContext(null)) { var baseName = PS.Config.CompanyFullName; return db.client.Any(t => t.id == clientId && baseName.Equals(t.Name)); } } public List GetPositionList(TradeSpanReq req) { var eodTradeQuery = from eod_trade in db.eod_trade where ConsTrade.NeedMarginTradeStatusList.Contains(eod_trade.TradeStatus) && eod_trade.ValueDate == req.ValueDate select eod_trade; var query = from tpos in db.eod_trade_position join trade in eodTradeQuery on new { tpos.TradeId, tpos.ValueDate } equals new { trade.TradeId, trade.ValueDate } join um in db.underlying_manager on trade.UnderlyingId equals um.id select new eod_position { TradeId = trade.id, ClientId = trade.ClientId, TradeNumber = trade.TradeNumber, UnderlyingCode = trade.UnderlyingCode, UnderlyingPrice = um.Price, Pv = tpos.Pv, Pnl = tpos.DailyPnL, ValueDate = tpos.ValueDate, TradeJson = trade.TradeJson }; if (req.ClientId != null) { query = query.Where(d => d.ClientId == req.ClientId); } if (req.ValueDate != null && req.ValueDate != DateTime.MinValue) { query = query.Where(d => d.ValueDate == req.ValueDate); } return query.ToList(); } } }