using Newtonsoft.Json; using System.Data; using System.Linq.Expressions; using YLErp.Commons; using YLErp.DBModels.Converts; using YLErp.Models.Tag; using YLErp.Modules.TagModule; namespace YLErp.Modules.TradeModule.ForwardModule { /// /// 远期多次了结查询服务 /// public class ForwardMultiCloseService : YLBaseService { public ForwardMultiCloseService(OptUserInfo userInfo) : base(userInfo) { } /// /// 获取分页数据(远期) /// public IPagedList GetPagedDatas(TradeMultiCloseQueryModel queryModel) { if (queryModel is null) { throw new ArgumentNullException(nameof(queryModel)); } var tradPredicate = BuildPredicate(queryModel); var basicQuery = from t in DbContext.trade.Where(tradPredicate) select t; var tradCashPredicate = PredicateBuilder.Create(tc => tc.ValidState != "InValid" && !tc.IsDeleted && (tc.Action == "系统操作-行权费" || tc.Action == "系统操作-平仓费")); if (queryModel.UnwindDateStart != null) { tradCashPredicate = tradCashPredicate.And(n => n.ValueDate >= queryModel.UnwindDateStart.Value); } if (queryModel.UnwindDateEnd != null) { tradCashPredicate = tradCashPredicate.And(n => n.ValueDate <= queryModel.UnwindDateEnd.Value); } var query = from t in basicQuery.Where(tradPredicate) join tc in DbContext.trade_cash.Where(tradCashPredicate) on t.id equals tc.TradeId join ft in DbContext.trade_forward on t.id equals ft.TradeId //join client in DbContext.client on t.ClientId equals client.id where "远期" == t.TradeType && !tc.IsDeleted select new TradeForwardMultiCloseResultModel { id = t.id, TradeNumber = t.TradeNumber, ClientName = t.ClientName, TradeDate = t.TradeDate, ExerciseDate = t.ExerciseDate, BuySell = t.BuySell, TradeType = t.TradeType, OptionType = t.OptionType == "看涨" ? "多头" : "空头", UnderlyingCode = t.UnderlyingCode, SpotPrice = t.SpotPrice, Strike = t.Strike, TradeSinglePrice = t.TradeSinglePrice ?? 0, TradeAmount = t.TradeAmount, CloseDate = tc.ValueDate, StrikePrice = tc.FinalPrice ?? 0, UnwindPrice = tc.UnwindPrice ?? 0, FinalPrice = tc.FinalPrice ?? 0, UnWindNotional = tc.UnwindNotional ?? tc.Notional, OriginalNotional = t.OriginalNotional ?? 0, ClosePnl = tc.Amount, UnwindFee = tc.Amount, CloseType = tc.Action, UnWindTradeAmount = tc.UnwindTradeAmount ?? 0, UnWindCapitalCost = tc.ExtraAmount ?? 0,//了结资金成本(预付金占用) TradePrice = t.TradePrice, //远期开仓总费用 ForwardValue = ft.ForwardValue,//远期价值-成交 OrderSeq = tc.Action == "系统操作-行权费" ? 2 : 1, TradeCashId = tc.id, StructureType = t.StructureType, Comments = t.Comments }; query = query.OrderByDescending(x => x.id).ThenBy(x => x.OrderSeq).ThenBy(x => x.CloseDate).ThenBy(x => x.TradeCashId); var pagedList = query.ToPagedList(queryModel); TradeForwardMultiCloseResultModel preData = null; Dictionary> tradeTagList = null; if (pagedList != null && pagedList.Any()) { using (var service = new TagService(OptUser)) { tradeTagList = service.GetTagByTradeIds(pagedList.Select(p => p.id).Distinct().ToList()); } } if (tradeTagList == null) { tradeTagList = new Dictionary>(); } foreach (var data in pagedList) { var underlying = DataCacheModule.DataCacheManager.GetUnderlyingDataSource().GetData(data.UnderlyingCode); if (preData?.id == data.id) { data.CloseSeq = preData.CloseSeq + 1; } preData = data; var openFee = data.OriginalNotional > 0 ? (data.UnWindNotional ?? 0) / data.OriginalNotional.Value * (data.TradePrice ?? 0) : 0; data.RealizedPnl = data.ClosePnl + openFee; if (data.CloseType == "系统操作-行权费") { data.CloseType = "到期"; } else if (data.CloseType == "系统操作-平仓费") { data.CloseType = "终止"; } data.TradeCommission = openFee; data.CountRatio = underlying?.CountRatio ?? 1; var buySell = BuySellConvert.GetClientBuySell(data.BuySell);//客户角度 买入卖出 data.UnWindForwardValue = new ForwardTradeImportService(OptUser).GetForwardValue(data.Strike ?? 0, data.FinalPrice ?? 0, data.UnWindTradeAmount, data.CountRatio ?? 1, data.OptionType, data.BuySell); data.UnderlyingName = underlying.UnderlyingName; //拼装标签值 if (tradeTagList.ContainsKey(data.id)) { data.Tags = tradeTagList[data.id]; } } return pagedList; } /// /// 导出远期数据(最多10000行) /// /// public byte[] ExportExcel2007(TradeMultiCloseQueryModel queryModel) { if (queryModel is null) { queryModel = new TradeMultiCloseQueryModel(); } queryModel.PageSize = 10000; //var mapper = new Mapper { IgnoreNotMapped = true }; //mapper.MapClass() // .Map("交易编号", o => o.TradeNumber) // .Map("交易对手方", o => o.ClientName) // .Map("成交日期", o => o.TradeDate) // .Map("到期日期", o => o.ExerciseDate) // .Map("买卖方向", o => o.BuySell) // .Map("结构类型", o => o.TradeType) // .Map("多空方向", o => o.OptionType) // .Map("标的代码", o => o.UnderlyingCode) // .Map("期初标的价格", o => o.SpotPrice) // .Map("执行价格", o => o.Strike) // .Map("远期价值(成交)", o => o.ForwardValue) // .Map("成交数量", o => o.OriginalNotional) // .Map("成交手续费", o => o.TradeCommission) // .Map("了结序号", o => o.CloseSeq) // .Map("了结方式", o => o.CloseType) // .Map("了结日期", o => o.CloseDate) // .Map("了结标的价格", o => o.StrikePrice) // .Map("远期价值(了结)", o => o.UnWindForwardValue) // .Map("了结数量", o => o.UnWindNotional) // .Map("了结手续费", o => o.UnWindCommission) // .Map("了结资金成本", o => o.UnWindCapitalCost) // .Map("了结金额", o => o.UnwindFee) // .Map("实现盈亏", o => o.RealizedPnl) // .Format("yyyy-MM-dd", o => o.TradeDate) // .Format("yyyy-MM-dd", o => o.ExerciseDate) // .Format("yyyy-MM-dd", o => o.CloseDate) // .Format("0.00", o => o.Strike); //mapper.ForHeader(cell => //{ // if (cell.ColumnIndex < 2) // { // cell.Sheet.SetColumnWidth(cell.ColumnIndex, 20 * 256); // } // else if (cell.StringCellValue.EndsWith("日期")) // { // cell.Sheet.SetColumnWidth(cell.ColumnIndex, 12 * 256); // } // else // { // cell.Sheet.SetColumnWidth(cell.ColumnIndex, 10 * 256); // } //}); var pagedData = GetPagedDatas(queryModel); Func formatValue = (cv) => { return cv.ToString("yyyy-MM-dd"); }; var dc = new List(); dc.Add(new ExcelHelper.DataColumnModel("交易编号", "TradeNumber")); dc.Add(new ExcelHelper.DataColumnModel("交易对手方", "ClientName")); dc.Add(new ExcelHelper.DataColumnModel("成交日期", "TradeDate", (cv, obj) => formatValue(((DateTime)cv)))); dc.Add(new ExcelHelper.DataColumnModel("到期日期", "ExerciseDate", (cv, obj) => formatValue(((DateTime)cv)))); dc.Add(new ExcelHelper.DataColumnModel("买卖方向", "BuySell")); dc.Add(new ExcelHelper.DataColumnModel("结构类型", "TradeType", (cv, obj) => {//掉期类型展示 if (obj is TradeForwardMultiCloseResultModel model) { return model.StructureType ?? cv; } return cv; } )); dc.Add(new ExcelHelper.DataColumnModel("多空方向", "OptionType")); dc.Add(new ExcelHelper.DataColumnModel("标的名称", "UnderlyingName")); dc.Add(new ExcelHelper.DataColumnModel("标的代码", "UnderlyingCode")); dc.Add(new ExcelHelper.DataColumnModel("期初标的价格", "SpotPrice", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("执行价格", "Strike", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("远期价值(成交)", "ForwardValue", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("成交数量", "OriginalNotional", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("成交手续费", "TradeCommission", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("了结序号", "CloseSeq", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("了结方式", "CloseType")); dc.Add(new ExcelHelper.DataColumnModel("了结日期", "CloseDate", (cv, obj) => formatValue(((DateTime)cv)))); dc.Add(new ExcelHelper.DataColumnModel("了结标的价格", "StrikePrice", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("远期价值(了结)", "UnWindForwardValue", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("了结数量", "UnWindNotional", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("了结手续费", "UnWindCommission", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("了结资金成本", "UnWindCapitalCost", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("了结金额", "UnwindFee", typeof(double))); dc.Add(new ExcelHelper.DataColumnModel("实现盈亏", "RealizedPnl", typeof(double))); new ExcelHelper().ListToExcel(dc.ToArray(), pagedData.Items.ToList(), "多次了结", true, out var buffer); return buffer; //using (var stream = new MemoryStream()) //{ // mapper.Save(stream, pagedData.Items, "多次了结", overwrite: true); // return stream.ToArray(); //} } private Expression> BuildPredicate(TradeMultiCloseQueryModel queryModel) { var predicate = PredicateBuilder.Create(t => t.ValidState != ConsGlobal.InValid); if (queryModel.UserAssets != null || queryModel.UserClients != null) { predicate = predicate.And(n => queryModel.UserAssets.Contains(n.AssetId) || queryModel.UserClients.Contains(n.ClientId)); } if (queryModel.TradeDateStart != null) { predicate = predicate.And(n => n.TradeDate >= queryModel.TradeDateStart.Value); } if (queryModel.TradeDateEnd != null) { predicate = predicate.And(n => n.TradeDate <= queryModel.TradeDateEnd.Value); } if (queryModel.ExerciseDateStart != null) { predicate = predicate.And(n => n.ExerciseDate >= queryModel.ExerciseDateStart.Value); } if (queryModel.ExerciseDateEnd != null) { predicate = predicate.And(n => n.ExerciseDate <= queryModel.ExerciseDateEnd.Value); } if (queryModel.AssetUnitIds != null && queryModel.AssetUnitIds.Any(a => a > 0)) { predicate = predicate.And(n => queryModel.AssetUnitIds.Contains(n.AssetId)); } if (queryModel.ClientIdList.Any()) { predicate = predicate.And(n => queryModel.ClientIdList.Contains(n.ClientId)); } if (!string.IsNullOrWhiteSpace(queryModel.TradeNumber)) { var TradeNumber = queryModel.TradeNumber.Trim(); predicate = predicate.And(n => n.TradeNumber.Contains(TradeNumber)); } if (queryModel.UnderlyingIdList != null && queryModel.UnderlyingIdList.Any(n => n > 0)) { predicate = predicate.And(n => queryModel.UnderlyingIdList.Contains(n.UnderlyingId)); } if (queryModel.TagIds != null && queryModel.TagIds.Count > 0) { var tradeTagIdQuery = from tt in DbContext.trade_tag where queryModel.TagIds.Contains(tt.TagId) select tt.TradeId; predicate = predicate.And(p => tradeTagIdQuery.Contains(p.id)); } return predicate; } private int GetDirection(string buySell, string callPut) { if ((buySell == "买入" && callPut == "空头") || (buySell == "卖出" && callPut == "多头")) { return 1; } else if ((buySell == "买入" && callPut == "多头") || (buySell == "卖出" && callPut == "空头")) { return -1; } else { return 1; } } } /// /// 多次了结服务结果Model /// public class TradeForwardMultiCloseResultModel : OtcTradeBase { /// /// 行权方式 /// public string ExerciseWay { get; set; } /// /// 了结方式 /// public string CloseType { get; set; } /// /// 了结日期 /// public DateTime? CloseDate { get; set; } /// /// 了结标的价格 /// public double StrikePrice { get; set; } /// /// 权利金(了结) /// public double UnwindPrice { get; set; } /// /// 了结金额 /// public double UnwindFee { get; set; } /// /// 平仓盈亏 /// public double ClosePnl { get; set; } /// /// 实现盈亏 /// public double RealizedPnl { get; set; } /// /// 排序序号 /// [JsonIgnore] public int OrderSeq { get; set; } [JsonIgnore] public int TradeCashId { get; set; } /// /// 了结序号 /// public int CloseSeq { get; set; } = 1; /// /// 远期价值(了结) /// public double UnWindForwardValue { get; set; } /// /// 远期价值(成交) /// public double ForwardValue { get; set; } /// /// 平仓数量 /// public double UnWindTradeAmount { get; set; } /// /// 成交手续费(了结部分所占的开仓总费用) /// public double TradeCommission { get; set; } /// /// 了结远期价值(远期收益) /// public double UnWindForwardProfits { get; set; } /// /// 了结手续费(平仓费用 * 了结数量 / 每手数量) /// public double UnWindCommission { get; set; } /// /// 了结资金成本(了结部分的预付金占用成本) /// public double UnWindCapitalCost { get; set; } /// /// 标的名称 /// public string UnderlyingName { get; set; } /// /// 交易标签 /// public List Tags { get; set; } } }