using System.Data; using System.Linq.Expressions; using System.Text.Json.Serialization; using YLErp.Enums; using YLErp.Office.ExcelModule; namespace YLErp.Modules.TradeModule.SwapModule { public class SwapMultiCloseService : YLBaseService { public SwapMultiCloseService(OptUserInfo userInfo) : base(userInfo) { } /// /// 获取分页数据(互换 -- 目前只有国君定制化的) /// public IPagedList GetPagedDatas(TradeMultiCloseQueryModel queryModel) { if (queryModel is null) { throw new ArgumentNullException(nameof(queryModel)); } BuildPredicate(queryModel, out var tdPredicate, out var tcPredicate); var basicQuery = DbContext.trade.Where(tdPredicate); var query = from t in basicQuery.Where(tdPredicate) join tc in DbContext.trade_cash.Where(tcPredicate) on t.id equals tc.TradeId join optc in DbContext.trade_cash.Where(x => x.ValidState != "InValid" && !x.IsDeleted && x.Action == "系统操作-期权费") on t.id equals optc.TradeId join sw in DbContext.trade_swap on t.id equals sw.TradeId join tcsw in DbContext.trade_cash_swap on tc.id equals tcsw.TradeCashId select new TradeSwapFlowMultiCloseResultModel { id = t.id, TradeNumber = t.TradeNumber, TraderName = t.TraderName, AssetBookName = t.AssetBookName, ClientName = t.ClientName, TradeDate = t.TradeDate, StartDate = t.StartDate, ExerciseDate = t.ExerciseDate, SettlementDate = t.SettlementDate, CloseDate = tc.ValueDate, OriginalNotional = t.OriginalNotional ?? 0, Notional = tc.Notional - (tc.UnwindNotional ?? 0), UnWindNotional = tc.UnwindNotional ?? 0, UnderlyingCode = t.UnderlyingCode, SpotPrice = t.SpotPrice, TradeCommission = sw.GetTradePrice ?? (-sw.PayTradePrice) ?? 0, //导入的期末价格使用的是UnwindPrice UnwindPrice = tc.UnwindPrice ?? tc.FinalPrice ?? 0, TradeCashId = tc.id, CloseType = tc.Action, Amount = tc.Amount, RealizedPnl = tc.Amount + optc.Amount * (tc.UnwindPercentRate ?? 0), QuoteRealizedPnl = (tc.QuoteAmount ?? tc.Amount) + (optc.QuoteAmount ?? optc.Amount) * (tc.UnwindPercentRate ?? 0), OpenCurrencyRate = optc.CurrencyRate ?? 1, CloseCurrencyRate = tc.CurrencyRate ?? 1, trade_swap = sw }; if (queryModel.UnWindTimes != null && queryModel.UnWindTimes >= 0) { var qgp = (from f in query group f by f.id into fgp where fgp.Count() == queryModel.UnWindTimes select fgp.Key).ToList(); query = query.Where(q => qgp.Contains(q.id)); } if (!string.IsNullOrWhiteSpace(queryModel.UnWindType) && queryModel.UnWindType != "全部") { if (queryModel.UnWindType == "终止") { query = query.Where(x => x.CloseType == ClientCashInCashOut.系统操作_平仓费); } else if (queryModel.UnWindType == "到期") { query = query.Where(x => x.CloseType == ClientCashInCashOut.系统操作_互换 && x.CloseDate == x.ExerciseDate); } else if (queryModel.UnWindType == "互换") { query = query.Where(x => x.CloseType == ClientCashInCashOut.系统操作_互换 && x.CloseDate < x.ExerciseDate); } } if (string.IsNullOrEmpty(queryModel.SortExpression)) { query = query.OrderByDescending(x => x.CloseDate).ThenBy(x => x.TradeCashId); } var pagedList = query.ToPagedList(queryModel); TradeSwapFlowMultiCloseResultModel preData = null; foreach (var data in pagedList) { var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(data.UnderlyingCode); underlying.Variety = DataCacheModule.DataCacheManager.GetVarietyDataSource().GetData(underlying.CommodityCode); data.QuoteCurrency = underlying.Variety.QuoteCurrency ?? ConsGlobal.Currency.CNY; data.CountRatio = underlying?.CountRatio ?? 1; data.UnderlyingName = underlying?.UnderlyingName; if (preData?.id == data.id) { data.CloseSeq = preData.CloseSeq + 1; } preData = data; if (data.trade_swap.IsGetFloatingProfit) { data.trade_swap.GetOpenPrice = data.trade_swap.GetSpotPrice + (data.trade_swap.GetLongShort == "多头" ? 1 : -1) * ((data.trade_swap.PaySingleFee ?? 0) / underlying.ContractSize + (data.trade_swap.GetSpotPrice * data.trade_swap.PayUnAnnualRate ?? 0)); } else { data.trade_swap.PayOpenPrice = data.trade_swap.PaySpotPrice + (data.trade_swap.PayLongShort == "多头" ? 1 : -1) * ((data.trade_swap.GetSingleFee ?? 0) / underlying.ContractSize + (data.trade_swap.PaySpotPrice * data.trade_swap.GetUnAnnualRate ?? 0)); } data.OpenPrice = data.trade_swap.GetOpenPrice ?? data.trade_swap.PayOpenPrice ?? 0; data.OriginalStockEqvNotional = data.OpenPrice * data.OriginalNotional * data.OpenCurrencyRate; data.StockEqvNotional = data.OpenPrice * data.Notional * data.OpenCurrencyRate; data.CloseStockEqvNotional = data.OpenPrice * (data.UnWindNotional ?? 0) * data.OpenCurrencyRate; var details = DbContext.trade_cash_detail.Where(x => x.TradeCashId == data.TradeCashId); data.FixedIncome = details.Where(x => x.TradeCashType == TradeCashTypeEnum.利息.ToString()).Sum(x => x.Amount); data.UnwindFee = details.Where(x => x.TradeCashType == TradeCashTypeEnum.了结手续费.ToString()).Sum(x => x.QuoteAmount); data.FloatIncome = data.Amount - data.FixedIncome; if (data.trade_swap.IsGetFloatingProfit) { data.ClosePrice = data.UnwindPrice + ((data.trade_swap.GetLongShort == "多头" ? -1 : 1) * (-data.UnwindFee ?? 0) / data.UnWindNotional).Normalize(); } else { data.ClosePrice = data.UnwindPrice + ((data.trade_swap.PayLongShort == "多头" ? -1 : 1) * (data.UnwindFee ?? 0) / data.UnWindNotional).Normalize(); } if (data.CloseType == "系统操作-互换") { if (data.CloseDate == data.ExerciseDate) { data.CloseType = "到期"; } else { data.CloseType = "互换"; } } else if (data.CloseType == "系统操作-平仓费") { data.CloseType = "终止"; } } return pagedList; } private void BuildPredicate(TradeMultiCloseQueryModel queryModel, out Expression> tdPredicate, out Expression> tcPredicate) { tdPredicate = PredicateBuilder.Create(t => t.ValidState != ConsGlobal.InValid && t.TradeType == "收益互换"); if (queryModel.UserAssets != null && queryModel.UserClients != null) { tdPredicate = tdPredicate.And(n => queryModel.UserAssets.Contains(n.AssetId) || queryModel.UserClients.Contains(n.ClientId)); } if (!string.IsNullOrWhiteSpace(queryModel.TradeNumber)) { var TradeNumber = queryModel.TradeNumber.Trim(); tdPredicate = tdPredicate.And(n => n.TradeNumber.Contains(TradeNumber)); } if (!string.IsNullOrEmpty(queryModel.TraderNames)) { tdPredicate = tdPredicate.And(d => queryModel.TraderNamesList.Contains(d.TraderId)); } if (queryModel.AssetIdList.Any()) { tdPredicate = tdPredicate.And(d => queryModel.AssetIdList.Contains(d.AssetId)); } if (queryModel.ClientIdList.Any()) { tdPredicate = tdPredicate.And(n => queryModel.ClientIdList.Contains(n.ClientId)); } if (queryModel.TradeDateStart != null) { tdPredicate = tdPredicate.And(n => n.TradeDate >= queryModel.TradeDateStart.Value); } if (queryModel.TradeDateEnd != null) { tdPredicate = tdPredicate.And(n => n.TradeDate <= queryModel.TradeDateEnd.Value); } if (queryModel.ExerciseDateStart != null) { tdPredicate = tdPredicate.And(n => n.ExerciseDate >= queryModel.ExerciseDateStart.Value); } if (queryModel.ExerciseDateEnd != null) { tdPredicate = tdPredicate.And(n => n.ExerciseDate <= queryModel.ExerciseDateEnd.Value); } if (queryModel.AssetUnitIds != null && queryModel.AssetUnitIds.Any(a => a > 0)) { tdPredicate = tdPredicate.And(n => queryModel.AssetUnitIds.Contains(n.AssetId)); } var underlyids = queryModel.UnderlyingIdList.ToList(); if (!string.IsNullOrWhiteSpace(queryModel.UnderlyingName)) { var _underlyids = DbContext.underlying_manager.Where(x => x.UnderlyingName.Contains(queryModel.UnderlyingName)).Select(x => x.id).ToHashSet(); if (underlyids.Count() > 0) { underlyids = underlyids.Intersect(_underlyids).Distinct().ToList(); } else { underlyids = _underlyids.ToList(); } } if (queryModel.UnderlyingIdList.Any(n => n > 0) || !string.IsNullOrWhiteSpace(queryModel.UnderlyingName)) { tdPredicate = tdPredicate.And(n => underlyids.Contains(n.UnderlyingId)); } if (!string.IsNullOrWhiteSpace(queryModel.TradeStatus)) { var statuses = queryModel.TradeStatus.Split(',').ToList(); tdPredicate = tdPredicate.And(n => statuses.Contains(n.TradeStatus)); } tcPredicate = PredicateBuilder.Create(tc => tc.ValidState != "InValid" && !tc.IsDeleted && (tc.Action == "系统操作-行权费" || tc.Action == "系统操作-平仓费" || tc.Action == "系统操作-互换")); if (queryModel.UnwindDateStart != null) { tcPredicate = tcPredicate.And(n => n.ValueDate >= queryModel.UnwindDateStart.Value); } if (queryModel.UnwindDateEnd != null) { tcPredicate = tcPredicate.And(n => n.ValueDate <= queryModel.UnwindDateEnd.Value); } if (queryModel.TradeCashIdList.Any()) { tcPredicate = tcPredicate.And(x => queryModel.TradeCashIdList.Contains(x.id)); } } /// /// 导出所有字段 /// public byte[] ExportAllFieldsToExcel(TradeMultiCloseQueryModel queryModel) { var list = GetPagedDatas(queryModel); var results = new List>(list.Count()); var templateFile = OtcAppContext.MapPath("~/App_Docs/导出模板/国君互换了结导出模板.xlsx"); return ExcelGenerator.UseTemplateGenerator(templateFile).AddVariable(new { list = list }).GenerateBytes(); } } public class TradeSwapFlowMultiCloseResultModel : OtcTradeBase { /// /// 了结日期 /// public DateTime? CloseDate { get; set; } /// /// 了结序号 /// public int CloseSeq { get; set; } = 1; /// /// 了结方式 /// public string CloseType { get; set; } /// /// 互换类型 -- 固定为“普通” /// public string SwapType { get; set; } = "普通"; /// /// 了结名义本金 /// public double CloseStockEqvNotional { get; set; } /// /// 开仓标的价格(费后) /// public double OpenPrice { get; set; } /// /// 了结标的价格(费后) /// public double ClosePrice { get; set; } /// /// 平仓费用 /// public double? UnwindFee { get; set; } /// /// 了结标的价格 /// public double UnwindPrice { get; set; } /// /// 浮动收益 /// public double? FloatIncome { get; set; } /// /// 固定收益 /// public double? FixedIncome { get; set; } /// /// 平仓总额 /// public double? Amount { get; set; } /// /// 实现盈亏 /// public double RealizedPnl { get; set; } /// /// 实现盈亏(结算) /// public double QuoteRealizedPnl { get; set; } [JsonIgnore] public int TradeCashId { get; set; } /// /// 成交手续费(了结部分所占的开仓总费用) /// public double TradeCommission { get; set; } /// /// 标的名称 /// public string UnderlyingName { get; set; } /// /// 开仓汇率 /// public double OpenCurrencyRate { get; set; } /// /// 结算汇率 /// public double CloseCurrencyRate { get; set; } public trade_swap trade_swap { get; set; } } }