using BaseOUDAL; using MathNet.Numerics; using System.Linq.Dynamic.Core; using YLErp.Commons; using YLErp.Model; using YLErp.Modules.DataProviderModule; namespace YLErp.Modules.SuperviseReportModule.ChangJiangReport.Service { public class SuperviseReportPositionService : YLBaseService { public SuperviseReportPositionService(OptUserInfo userInfo) : base(userInfo) { } public SuperviseReportPositionService(YLBaseService baseService) : base(baseService) { } /// /// 从数据库中查询场外业务持仓信息 /// 长江数据采集用 /// public SearchListResult SearchSuperviseReportList(SuperviseReportReq req) { if (string.IsNullOrWhiteSpace(req.sidx)) { req.sidx = nameof(SupervisePositionDbModel.id); } var query = from db in DbContext.SuperviseReportPosition where db.ValueDate == req.ValueDate select db; switch (req.DataSource) { case "不为零": query = query.Where(O => !(O.DeltaCash == 0 && O.GammaCash == 0 && O.HoldCash == 0 && O.PositionPnl == 0 && O.StockEqvNotional == 0 && O.TradePrice == 0)); break; case "全量": default: break; } return query.ToSearchList(req); } /// /// 保存场外业务持仓信息到数据库 /// 长江数据采集用 /// /// 数据日期 public int SaveReportData(DateTime valueDate, string exposureDataSourceType = null, bool clearExsitings = false) { var models = DbContext.SuperviseReportPosition.Where(a => a.ValueDate == valueDate); if (models.Any()) { if (!clearExsitings) { return 0; } SupervisePositionDbModel t; DbContext.BulkDelete($"{nameof(t.ValueDate)}='{valueDate:yyyy-MM-dd}'"); } IQueryable tRisk; var useClosePrice = true; switch (exposureDataSourceType) { default: tRisk = DbContext.eod_trade_risk_hedgevol; break; case "收盘价+持仓波动率": tRisk = DbContext.eod_trade_risk; break; case "结算价+持仓波动率": useClosePrice = false; tRisk = DbContext.eod_trade_risk_s; break; case "结算价+对冲波动率": useClosePrice = false; tRisk = DbContext.eod_trade_risk_hedgevol_s; break; } //长江-依文文2022-04-20 提出需要排除新基差簿记的交易; var bookIds = DbContext.assetunit.Where(O => O.Name.Contains("新基差")).Select(O => O.id); var query = from position in DbContext.eod_trade_position join risk in tRisk on new { position.ValueDate, HedgeUniqueCode = position.HedgeUniqueCode + "_" + position.TradeId, } equals new { risk.ValueDate, HedgeUniqueCode = risk.HedgeUniqueCode + "_" + risk.TradeId, } into tempRisk from risk in tempRisk.DefaultIfEmpty() join trade in DbContext.eod_trade on new { position.ValueDate, position.TradeId } equals new { trade.ValueDate, trade.TradeId } into tempTrade from trade in tempTrade.DefaultIfEmpty() where position.ValueDate == valueDate && position.TradeType != "现金流交易" && !bookIds.Contains(position.BookId) select new { risk, position.Pv, position.Cost, position.Amount, position.BuySell, position.TradeType, position.PositionPnL, position.PositionType, position.UnderlyingCode, position.ExchangeOptionCode, eodTrade = trade, }; var objs = new List(); var positionTypes = new List() { "卖出", "多头平仓", "空头开仓" }; var tradeTypes = new List() { "远期", "收益互换" }; var priceProvider = new EodPriceProvider(valueDate, isDiviendPrice: false); foreach (var item in query) { var trade = item.eodTrade?.trade; var variety = DataCacheProvider.GetVariety(item.UnderlyingCode); var obj = new SupervisePositionDbModel(); obj.ValueDate = valueDate; if (trade == null || ConsTrade.TradeTypesForHedge.Contains(trade.TradeType)) { obj.Trade_Number = ""; priceProvider.TryGetEodPrice(item.UnderlyingCode, out var eodPrice); var price = eodPrice?.GetPrice(SettlementTypeEnum.SettlePrice) ?? 0; obj.StockEqvNotional = Math.Abs(price * item.Amount); obj.BusinessType = "场外期权成交自主对冲"; obj.TradeType = item.TradeType; obj.ClientName = variety.TradingMarket; obj.DeltaCash = item.risk?.DeltaCash ?? 0; if (item.TradeType == "场内期权") { var exchangeOptionInfo = DataCacheProvider.GetExchangeListOptionDataSource().GetData(item.ExchangeOptionCode);//ExchangeOptionCode场内标的 obj.StockEqvNotional = Math.Abs(exchangeOptionInfo.Strike * item.Amount); if (positionTypes.Contains(item.BuySell)) { obj.BuySell = "卖出"; obj.HoldCash = obj.StockEqvNotional * variety.Margin ?? 0; } else { obj.BuySell = "买入"; obj.HoldCash = 0; } obj.TradePrice = -item.Cost; } else { obj.HoldCash = obj.StockEqvNotional * variety.Margin ?? 0; obj.Amount = Math.Abs(item.Amount); if (useClosePrice) { price = eodPrice?.GetPrice(SettlementTypeEnum.ClosePrice) ?? 0; ; } obj.DeltaCash = item.Amount * price; if (item.PositionType == "long") { obj.BuySell = "买入"; } else { obj.BuySell = "卖出"; } obj.isFutures = true; } } else { if (!ConsTrade.LiveTradeStatusList.Contains(trade.TradeStatus)) { continue; } var type = (trade.Comments?.Trim().FirstOrDefault() ?? '0').ToString(); //1.套利和通道业务 //2.场外期权成交自主对冲 //3.商业类和政策类保险 + 期货 //4.交易所项目; //5.融资业务 switch (type) { case "1": obj.BusinessType = "套利业务"; break; case "3": obj.BusinessType = "商业类和政策类保险 + 期货"; break; case "4": obj.BusinessType = "交易所项目"; break; case "5": obj.BusinessType = "其他业务"; break; case "2": default: obj.BusinessType = "场外期权成交自主对冲"; break; } obj.Trade_Number = trade.TradeNumber; obj.ClientName = trade.ClientName; obj.BuySell = trade.BuySell; if (tradeTypes.Contains(trade.TradeType)) { obj.TradeType = trade.StructureType ?? trade.TradeType; } else { obj.TradeType = trade.ExerciseModeCn + trade.OptionType; } var strike = (trade.IsMoneynessOptionData ? (trade.Strike * trade.SpotPrice) : trade.Strike) ?? 0; if (trade.TradeType == "收益互换") { strike = trade.SpotPrice ?? 0; } obj.StockEqvNotional = strike * trade.Notional; obj.TradeId = trade.id; obj.TradePrice = (trade.TradePrice * (trade.StockEqvNotional / trade.OriginalStockEqvNotional) * (trade.BuySell == "买入" ? -1 : 1)) ?? 0; obj.DeltaCash = item.risk?.DeltaCash ?? 0; } obj.Project = $"{variety.VarietyName}{obj.BusinessType}"; obj.VarietyCode = variety.VarietyCode; obj.UnderlyingCode = item.UnderlyingCode; obj.PositionPnl = item.PositionPnL; obj.GammaCash = item.risk?.GammaCash ?? 0; obj.ExchangeOptionCode = item.ExchangeOptionCode; objs.Add(obj); } var listGroup = objs.GroupBy(O => $"{O.Project}_{O.ClientName}_{O.BuySell}_{O.TradeType}_{O.ExchangeOptionCode ?? O.UnderlyingCode}_{O.TradeId}") .ToDictionary(K => K.Key); var futureAmountInfos = new Dictionary(); var dict = objs.GroupBy(O => $"{O.Project}_{O.ClientName}_{O.BuySell}_{O.TradeType}_{O.ExchangeOptionCode ?? O.UnderlyingCode}_{O.TradeId}") .ToDictionary(K => K.Key, V => { var obj = V.First(); var i = 0; V.ToList().ForEach(O => { i++; if (i == 1) { return; } obj.StockEqvNotional += O.StockEqvNotional; obj.TradePrice += O.TradePrice; obj.PositionPnl += O.PositionPnl; if (O.isFutures) { obj.HoldCash += O.HoldCash; obj.Amount += O.Amount; } else if (O.TradeType == "场内期权") { obj.HoldCash += O.HoldCash; } obj.DeltaCash += O.DeltaCash; obj.GammaCash += O.GammaCash; }); if (obj.isFutures) { if (!futureAmountInfos.ContainsKey(obj.UnderlyingCode)) { futureAmountInfos[obj.UnderlyingCode] = obj; return obj; } if (futureAmountInfos[obj.UnderlyingCode].Amount > obj.Amount) { obj.HoldCash = 0; } else { futureAmountInfos[obj.UnderlyingCode].HoldCash = 0; } } obj.HoldCash = OtcFormatHelper.FormatValue(obj.HoldCash, 6); obj.TradePrice = OtcFormatHelper.FormatValue(obj.TradePrice, 6); obj.StockEqvNotional = OtcFormatHelper.FormatValue(obj.StockEqvNotional, 6); obj.PositionPnl = OtcFormatHelper.FormatValue(obj.PositionPnl, 6); obj.DeltaCash = OtcFormatHelper.FormatValue(obj.DeltaCash, 6); obj.GammaCash = OtcFormatHelper.FormatValue(obj.GammaCash, 6); return obj; }); var list = dict.Values.OrderBy(O => $"{O.Project}_{O.ClientName}_{O.BuySell}_{O.TradeType}_{O.ExchangeOptionCode ?? O.UnderlyingCode}_{O.TradeId}").ToList(); if (list.Any()) { DbContext.SuperviseReportPosition.AddRange(list); return DbContext.SaveChanges(); } return 0; } public void BatchSupervisePosition(List Ids, DateTime ValueDate, bool IsAll, string Type) { var predicate = PredicateBuilder.True().And(a => a.ValueDate == ValueDate); if (!IsAll)//非全选 { predicate = predicate.And(a => Ids.Contains(a.id)); } using (var db = DbContextFactory.GetYLDbContext()) { var clietnCashs = db.SuperviseReportPosition.Where(predicate); if (clietnCashs.Any()) { if (Type == "update")//更新确认状态 { foreach (var item in clietnCashs) { item.Status = true; } } else { db.SuperviseReportPosition.RemoveRange(clietnCashs); } } else { throw new ServiceException("没有数据进行批量操作"); } db.SaveChanges(); } } } }