using System.Data; using System.Globalization; using System.Text.RegularExpressions; using YLErp.BLL; using YLErp.Commons; using YLErp.CustomizedBizLogic; using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.DBModels.Helpers; using YLErp.Enums; using YLErp.Model.Enum; using YLErp.Modules.CalculationModule; using YLErp.Modules.EodModule; using YLErp.Modules.TradeModule.DocGenerateModule; using YLErp.Modules.TradeModule.OrderModule; namespace YLErp.Modules.TradeModule.SwapModule { /// /// 场外期权交易导入服务 /// public class SwapTradeFlowImportService : TradeServiceBase { public SwapTradeFlowImportService(OptUserInfo userInfo) : base(userInfo) { } public SwapTradeFlowImportService(YLBaseService baseService) : base(baseService) { } /// /// 导入交易 /// /// /// 当前文件中的目标期权总条数 /// 成功入库的数量 public void ImportSwapTradeFlowFromExcel(Stream streamIn, out int totalNum, out int successNum) { totalNum = 0; successNum = 0; var rowIndex = 0; var tradeFlowIds = new List(); try { var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0); if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2) { throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" }; } var table = ds.Tables[0]; var reader = new DataRowReader(table); rowIndex = 1; totalNum = table.Rows.Count - rowIndex; using (var trans = BeginTransaction()) { foreach (var row in table.Rows.Cast().Skip(1)) { rowIndex++; if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString()))) { totalNum--; continue; } reader.SetDataRow(row); //映射导入数据到交易对象 var tradeFlow = MapSwapTradeFlow(reader); tradeFlowIds.Add(tradeFlow.id); HandleSwapTrade(tradeFlow); tradeFlow.Status = "已完成"; DbContext.SaveChanges(); successNum++; } trans.Commit(); } //generateSettleDocument(trade_Cashes); //生成确认书 //new ConfirmationGenerateService(this).Generate(tradeIds, "PDF"); } catch (ServiceException se) { if (se.Tag != null) { throw; } throw new ServiceException($"第{rowIndex}行,{se.Message}"); } catch (Exception ex) { LogFactory.GetLogger("导入互换交易").Error(ex); throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex); } } /// /// 导入交易 /// /// /// 当前文件中的目标期权总条数 /// 成功入库的数量 public void ImportSwapTradeFlowGroupFromExcel(Stream streamIn, out int totalNum, out int successNum) { totalNum = 0; successNum = 0; var rowIndex = 0; try { var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0); if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2) { throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" }; } var table = ds.Tables[0]; var reader = new DataRowReader(table); rowIndex = 1; totalNum = table.Rows.Count - rowIndex; using (var trans = BeginTransaction()) { foreach (var row in table.Rows.Cast().Skip(1)) { rowIndex++; if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString()))) { totalNum--; continue; } reader.SetDataRow(row); //映射导入数据到交易对象 MapSwapTradeFlowGroup(reader); successNum++; } trans.Commit(); } } catch (ServiceException se) { if (se.Tag != null) { throw; } throw new ServiceException($"第{rowIndex}行,{se.Message}"); } catch (Exception ex) { LogFactory.GetLogger("导入互换交易").Error(ex); throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex); } } /// /// 导入交易 /// /// /// 当前文件中的目标期权总条数 /// 成功入库的数量 public void ImportTradeFlowHistoryFromExcel(Stream streamIn, out int totalNum, out int successNum) { totalNum = 0; successNum = 0; var rowIndex = 0; try { var ds = Office.ExcelHelper.ReadExcelAsDataSet(streamIn, new[] { 0 }, 0); if (ds.Tables.Count < 1 || ds.Tables[0].Rows.Count < 2) { throw new ServiceException("读取导入数据失败:数据为空") { Tag = "111" }; } var table = ds.Tables[0]; var reader = new DataRowReader(table); rowIndex = 1; totalNum = table.Rows.Count - rowIndex; using (var trans = BeginTransaction()) { foreach (var row in table.Rows.Cast().Skip(1)) { rowIndex++; if (row.ItemArray.All(n => string.IsNullOrWhiteSpace(n?.ToString()))) { totalNum--; continue; } reader.SetDataRow(row); var clientName = reader.GetString("客户名称"); var client = ClientModule.ClientDataQueryService.GetClient(clientName); if (client == null) { throw new ServiceException($"客户{clientName}不存在"); } var tradeFlowHistory = new trade_flow_history() { ClientId = client.id, ContractId = reader.GetString("交易编码"), FlagExpired = reader.GetString("是否到期"), QuoteCurrency = reader.GetString("计价货币"), SettleCurrency = reader.GetString("结算货币"), TradeDate = reader.GetDate("交易日"), ExpireDate = reader.GetDate("到期日"), SettleDate = reader.GetDate("交割日(LME Prompt)"), Direction = reader.GetString("客户买/卖"), PremiumDate = reader.GetDate("权利金日"), PremiumCNY = reader.GetDouble("期权费¥"), TradeType = reader.GetString("衍生品类型"), UnderlyingCode = reader.GetString("标的代码"), InitialLots = reader.GetDouble("初始开仓手数"), Lots = reader.GetDouble("剩余手数"), Size = reader.GetDouble("合约乘数"), InitialSpotPrice = reader.GetDouble("初始价格"), InitialRate = reader.GetDouble("初始汇率"), SpotPrice = reader.GetDouble("最新价格"), Rate = reader.GetDouble("最新汇率"), CommissionRate = reader.GetString("佣金费率"), EstimateCommision = reader.GetDouble("预估佣金¥"), AnnualRate = reader.GetPercent("年化手续费率"),// EstimateAnnualFee = reader.GetDouble("预估年化手续费¥"), FloatingWinLossQuote = reader.GetDouble("浮动收益(计价货币)"), FloatingWinLoss = reader.GetDouble("浮动收益(结算货币)"),// UnRealizedPnl = reader.GetDouble("未实现收益(结算货币)"), RealizedPnl = reader.GetDouble("已实现收益(结算货币)"), OptId = UserId, OptName = UserName, OptDate = DateTime.Now }; checkFlowHis(tradeFlowHistory); DbContext.trade_flow_history.Add(tradeFlowHistory); DbContext.SaveChanges(); successNum++; } trans.Commit(); } } catch (ServiceException se) { if (se.Tag != null) { throw; } throw new ServiceException($"第{rowIndex}行,{se.Message}"); } catch (Exception ex) { LogFactory.GetLogger("导入历史交易流水").Error(ex); throw new ServiceException($"第{rowIndex}行,发生错误:{ex.Message}", ex); } } public bool checkFlowHis(trade_flow_history req) { if (DbContext.trade_flow_history.Any(o => o.ContractId == req.ContractId)) { throw new ServiceException($"历史交易已存在{req.ContractId}"); } return true; } public void HandleSwapTrade(trade_swap_flow tradeFlow) { var importTrade = MapSwapTradeHandle(tradeFlow); var tradeSwapPositionsOtherSide = (from td in DbContext.trade join ts in DbContext.trade_swap on td.id equals ts.TradeId where td.ClientId == importTrade.ClientId && td.UnderlyingId == importTrade.UnderlyingId && td.TradeStatus == ConsTrade.确认成交 && td.ParentTradeId == 0 && td.ValidState != "InValid" && ts.SwapType != "多空组合" && ts.PayLongShort != importTrade.trade_swap.PayLongShort && td.TradeDate <= importTrade.TradeDate select new { td, ts }).ToList().OrderBy(x => x.td.TradeDate); if (tradeSwapPositionsOtherSide.Any()) { //按时间顺序一次平仓 foreach (var item in tradeSwapPositionsOtherSide) { if (importTrade.Notional > 0) { item.td.trade_swap = item.ts; UnwindSwapTrade(item.td, importTrade); } } //如果存续反向交易均被平仓,新增交易还有剩余部分,需要重新开仓 if (importTrade.Notional > 0) { InnerSaveSwapTrade(importTrade); } } else { //无反向存续交易,则直接开仓 InnerSaveSwapTrade(importTrade); } } private void InnerSaveSwapTrade(trade importTrade) { var varitey = DataCacheProvider.GetVariety(importTrade.UnderlyingCode); double marginRate = 0d; if (PS.Config.Company == Configuration.CompanyEnum.中金) { var credit = DbContext.credit.FirstOrDefault(x => x.CreditStartDate <= importTrade.TradeDate && x.CreditDeadLine >= importTrade.TradeDate && x.ClientId == importTrade.ClientId && x.ProcessStatus == "已审批"); var hasCredit = credit != null && credit.PFECredit > 0; var clientVarietyMarginRate = DbContext.client_variety_marginrate.Where(x => x.ClientId == importTrade.ClientId && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault(); if (clientVarietyMarginRate == null) { clientVarietyMarginRate = DbContext.client_variety_marginrate.Where(x => x.ClientId == 0 && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault(); } if (clientVarietyMarginRate == null) { throw new ServiceException($"该客户[{importTrade.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{importTrade.TradeDate}]相关的预付金率配置"); } marginRate = hasCredit ? clientVarietyMarginRate.LowMarginRate : clientVarietyMarginRate.HighMarginRate; } else { var clientMarginRate = DbContext.client_marginrate.Where(x => x.ClientId == importTrade.ClientId && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault(); if (clientMarginRate == null) { clientMarginRate = DbContext.client_marginrate.Where(x => x.ClientId == 0 && x.VarietyId == varitey.id && x.ValueDate <= importTrade.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault(); } if (clientMarginRate == null) { throw new ServiceException($"该客户[{importTrade.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{importTrade.TradeDate}]相关的预付金率配置"); } marginRate = clientMarginRate.InitMarginRate; } importTrade.TradeStatus = ConsTrade.确认成交; if (!GuolianContractNoGenerator.IsGuolianSwapTrade(importTrade)) { importTrade.TradeNumber = BizLogicSingleton.Instance.GenerateTradeNumberBeforeConfirm(importTrade, DbContext); } var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(importTrade.QuoteCurrency, importTrade.SettlementCurrency, importTrade.TradeDate.Value, seekPreday: importTrade.TradeDate.Value == valuedateBLL.ValueDate); var tradePriceQuote = 0.0; if (importTrade.trade_swap.IsTradePriceWhenOpen) { tradePriceQuote = ((importTrade.trade_swap.GetSingleFee ?? 0) * (importTrade.Lots ?? 0) + importTrade.StockEqvNotional * (importTrade.trade_swap.GetUnAnnualRate ?? 0)).FormatValue(2); importTrade.TradePrice = (tradePriceQuote * currencyRate).FormatValue(2); } importTrade.InitialMargin = marginRate * importTrade.StockEqvNotional; importTrade.OriginalNotional = importTrade.Notional; importTrade.OriginalStockEqvNotional = importTrade.StockEqvNotional; importTrade.StockEqvNotionalReal = importTrade.StockEqvNotionalReal; importTrade.trade_swap.RateCalcMode = "01"; importTrade.IsUsePremiumRate = true; importTrade.MarginTemplateName = null; importTrade.MarginType = MarginTypeEnum.DEFAULT; importTrade.IsTradePricePayType = true; importTrade.TradeSource = TradeSourceEnum.导入交易.ToString(); importTrade.OptId = UserId; importTrade.OptName = UserName; importTrade.OptDate = DateTime.Now; SetDBModelCreator(importTrade); DbContext.trade.Add(importTrade); DbContext.SaveChanges(); if (GuolianContractNoGenerator.TryGenerateTradeNumberAfterSave(DbContext, importTrade)) { DbContext.SaveChanges(); } importTrade.trade_swap.GetTradePrice = (importTrade.trade_swap.GetSingleFee ?? 0) * (importTrade.Lots ?? 0) + (importTrade.trade_swap.GetUnAnnualRate ?? 0) * importTrade.StockEqvNotional; importTrade.trade_swap.GetMarginRate = marginRate; importTrade.trade_swap.TradeId = importTrade.id; importTrade.trade_swap.PaySpotPrice = importTrade.SpotPrice; importTrade.trade_swap.PayUnderlyingId = importTrade.UnderlyingId; importTrade.trade_swap.PayUnderlyingCode = importTrade.UnderlyingCode; importTrade.trade_swap.PayNotional = importTrade.Notional; importTrade.trade_swap.PayTradeAmount = importTrade.TradeAmount; importTrade.trade_swap.IsPayFloatingProfit = true; importTrade.trade_swap.SwapType = "普通"; importTrade.trade_swap.OptId = UserId; importTrade.trade_swap.OptName = UserName; importTrade.trade_swap.OptDate = DateTime.Now; DbContext.trade_swap.Add(importTrade.trade_swap); SaveTradeMeta(importTrade); var tc = new trade_cash { ValidState = "Valid" }; DbContext.trade_cash.Add(tc); tc.OptId = UserId; tc.OptName = UserName; tc.OptDate = DateTime.Now; tc.Action = ClientCashInCashOut.系统操作_期权费; tc.Amount = (importTrade.TradePrice ?? 0) * (importTrade.BuySell == "买入" ? -1 : 1); tc.QuoteAmount = tradePriceQuote * (importTrade.BuySell == "买入" ? -1 : 1); tc.CurrencyRate = currencyRate; tc.ExceciseType = "现金"; tc.TradeId = importTrade.id; tc.ValueDate = importTrade.TradeDate.Value; tc.Notional = importTrade.Notional; tc.TradeAmount = importTrade.TradeAmount; tc.Status = TradeCashStatusEnum.已执行; tc.TradeType = importTrade.BuySell; DbContext.SaveChanges(); new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(importTrade, tc, tc.ValueDate); var tcdGet = new trade_cash_detail { TradeId = tc.TradeId, TradeCashId = tc.id, Action = tc.Action, Amount = tc.Amount, QuoteAmount = tc.QuoteAmount, TradeCashType = TradeCashTypeEnum.开仓手续费.ToString(), ValueDate = tc.ValueDate, IsForGet = true, OptId = tc.OptId, OptName = tc.OptName, OptDate = DateTime.Now }; DbContext.trade_cash_detail.Add(tcdGet); DbContext.SaveChanges(); } private void UnwindSwapTrade(trade tradePosition, trade tradeImport) { var unwindType = tradePosition.Notional > tradeImport.Notional ? "部分平仓" : "全部平仓"; if (tradePosition.trade_swap.SettlementPayType == 0) { UnwindSwapTradeCashHandle(tradePosition, tradeImport, unwindType); } else if (tradePosition.trade_swap.SettlementPayType == 1) { UnwindSwapTradeCashPreHandle(tradePosition, tradeImport, unwindType); } SaveTradeOperationHistory(tradePosition, "互换导入平仓"); //删除E/Bod数据 RemoveEodTradeAndFutureInfo(true, tradePosition.id, tradeImport.TradeDate.Value); } private void UnwindSwapTradeCashHandle(trade tradePosition, trade tradeImport, string unwindType) { var tradeCashs = DbContext.trade_cash.Where(x => x.TradeId == tradePosition.id && x.ValidState != "InValid"); var num = tradeCashs.Where(x => x.Action != ClientCashInCashOut.系统操作_期权费).Count() + 1; var tradeCashList = tradeCashs.Where(y => y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tradeImport.TradeDate.Value); var tradeCashIds = tradeCashList.Select(x => x.id); var client = DataCacheProvider.GetClientDataSource().GetData(tradePosition.ClientId); var currencyRate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(tradePosition.QuoteCurrency, tradePosition.SettlementCurrency, tradeImport.TradeDate.Value, seekPreday: tradeImport.TradeDate.Value == valuedateBLL.ValueDate); var currencyRateTradeDate = new EodCurrencyRateService(UserInfo).GetCurrencyRate(tradePosition.QuoteCurrency, tradePosition.SettlementCurrency, tradePosition.TradeDate.Value, seekPreday: tradePosition.TradeDate.Value == valuedateBLL.ValueDate); //增加现金交割交易记录 var tc = new trade_cash(); DbContext.trade_cash.Add(tc); tc.OptId = UserId; tc.OptName = UserName; tc.OptDate = OptDate; tc.ExceciseType = "现金"; tc.TradeType = tradePosition.BuySell; tc.CallPut = tradePosition.CallPut; tc.Notional = tradePosition.Notional; tc.TradeAmount = tradePosition.TradeAmount; tc.IsLastAction = unwindType == "全部平仓"; tc.TradeId = tradePosition.id; tc.FinalPrice = tradeImport.SpotPrice; tc.UnwindType = unwindType; if (tc.UnwindType == "全部平仓") { tc.UnwindNotional = tradePosition.Notional; tc.UnwindTradeAmount = tradePosition.TradeAmount; tc.UnwindPercentRate = tradePosition.Notional / tradePosition.OriginalNotional; } else { tc.UnwindNotional = tradeImport.Notional; tc.UnwindTradeAmount = tradeImport.TradeAmount; tc.UnwindPercentRate = tradeImport.Notional / tradePosition.OriginalNotional; } tc.NotionalPercentRate = tc.UnwindPercentRate; tradeBLL.SetFieldsByTradeType(tradePosition); var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(tradePosition, tradePosition.trade_swap, tradePosition.trade_swap.PaySpotPrice ?? 0 , tradeImport.SpotPrice ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0), tradeImport.TradeDate.Value, null); var initialAmountPay = (initialAmountPayQuote * currencyRate).FormatValue(2); var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == tradePosition.id && tradeCashIds.Contains(x.TradeCashId)).ToArray(); //取最后一次手动收益; var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto); var lastManualCash = lastManualCashSwap != null ? tradeCashList.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null; DateTime endDate; var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDate(tradePosition, tradePosition.trade_swap, tradeImport.TradeDate.Value, null, lastManualCash, tradePosition.trade_swap.IsGetFloatingProfit, out endDate); var extraAmountGetQuote = PayoffSwapCalcService.GetExtraAmountBySwapRate(tradePosition.ClientId, tradePosition.TradeDate, tradePosition.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, tradePosition.trade_swap.AnnualDays ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tc.UnwindPercentRate ?? 0)); var extraAmountGet = extraAmountGetQuote * (PS.Config.Company == Configuration.CompanyEnum.中金 && client.BoundSide == BoundSideEnum.南向 ? currencyRateTradeDate : currencyRate); var costFeeGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradeImport, tc, true, false); var costFeeGet = (costFeeGetQuote * currencyRate).FormatValue(2); var costTradePriceGetQuote = 0.0; var costTradePriceGet = 0.0; if (!tradePosition.trade_swap.IsTradePriceWhenOpen) { costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradePosition, tc, true, true); costTradePriceGet = (costTradePriceGetQuote * currencyRate).FormatValue(2); } tc.Amount = extraAmountGet + costFeeGet + costTradePriceGet - initialAmountPay; tc.QuoteAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote; tc.CurrencyRate = currencyRate; tc.Action = ClientCashInCashOut.系统操作_平仓费; tc.Status = TradeCashStatusEnum.已执行; tc.ValueDate = tradeImport.TradeDate.Value; tc.ValidState = "Valid"; tc.ExerciseWay = tradeImport.TradeDate == tradePosition.ExerciseDate ? TradeCashExerciseWayEnum.到期行权 : TradeCashExerciseWayEnum.提前终止行权; if (client.BoundSide == BoundSideEnum.北向) { tc.Number = tradePosition.TradeNumber + "_UW_" + num; } DbContext.SaveChanges(); if (unwindType == "全部平仓") { tradePosition.TradeStatus = "已平仓"; } else { tradePosition.HasPartialUnWind = 1; } tradePosition.UnWindDate = tc.ValueDate; tradePosition.StockEqvNotional -= (tradePosition.SpotPrice ?? 0) * (tc.UnwindNotional ?? 0); tradePosition.Notional -= tc.UnwindNotional ?? 0; tradePosition.TradeAmount -= tc.UnwindTradeAmount ?? 0; tradePosition.UnWindNotional = tc.UnwindNotional; //增加出入金记录 new ClientCashinCashoutBLL(this).CloseTrade_ClientCashInCashOutSave(tradePosition, tc, tc.ValueDate); var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tc.TradeId); var trade_cash_swap = new trade_cash_swap(); trade_cash_swap.StartDate = tradePosition.StartDate.Value; trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice; trade_cash_swap.PayFinalPrice = tc.FinalPrice; trade_cash_swap.PayInitialAmount = initialAmountPay; trade_cash_swap.PayAmount = initialAmountPay; trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.PaySwapTimeAndRate, tradePosition.UnWindDate.Value); trade_cash_swap.GetExtraAmount = extraAmountGet; trade_cash_swap.GetCostFee = costFeeGet + costTradePriceGet; trade_cash_swap.GetAmount = extraAmountGet + costFeeGet + costTradePriceGet; trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.GetSwapTimeAndRate, tradePosition.UnWindDate.Value); trade_cash_swap.TradeId = tc.TradeId; trade_cash_swap.TradeCashId = tc.id; trade_cash_swap.FlowId = tradeImport.trade_swap.FlowId; trade_cash_swap.OptId = tc.OptId; trade_cash_swap.OptName = tc.OptName; trade_cash_swap.OptDate = DateTime.Now; DbContext.trade_cash_swap.Add(trade_cash_swap); var tcdGet = new trade_cash_detail { TradeId = tc.TradeId, TradeCashId = tc.id, Action = tc.Action, Amount = extraAmountGet, QuoteAmount = extraAmountGetQuote, ValueDate = tc.ValueDate, IsForGet = true, OptId = tc.OptId, OptName = tc.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.利息.ToString() }; DbContext.trade_cash_detail.Add(tcdGet); var tcdCostFeeGet = new trade_cash_detail { TradeId = tc.TradeId, TradeCashId = tc.id, Action = tc.Action, Amount = costFeeGet, QuoteAmount = costFeeGetQuote, ValueDate = tc.ValueDate, IsForGet = true, OptId = tc.OptId, OptName = tc.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.了结手续费.ToString() }; DbContext.trade_cash_detail.Add(tcdCostFeeGet); var tcdCostTradePriceGet = new trade_cash_detail { TradeId = tc.TradeId, TradeCashId = tc.id, Action = tc.Action, Amount = costTradePriceGet, QuoteAmount = costTradePriceGetQuote, ValueDate = tc.ValueDate, IsForGet = true, OptId = tc.OptId, OptName = tc.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.开仓手续费.ToString() }; DbContext.trade_cash_detail.Add(tcdCostTradePriceGet); var tcdPay = new trade_cash_detail { TradeId = tc.TradeId, TradeCashId = tc.id, Action = tc.Action, Amount = -initialAmountPay, QuoteAmount = -initialAmountPayQuote, ValueDate = tc.ValueDate, IsForGet = false, OptId = tc.OptId, OptName = tc.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.浮动收益.ToString() }; DbContext.trade_cash_detail.Add(tcdPay); tradeImport.Notional -= tc.UnwindNotional ?? 0; tradeImport.TradeAmount -= tc.UnwindTradeAmount ?? 0; var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeImport.UnderlyingCode); tradeImport.Lots -= tc.UnwindNotional / underlying.ContractSize; tradeImport.StockEqvNotional -= (tc.UnwindNotional ?? 0) * (tradeImport.SpotPrice ?? 0); DbContext.SaveChanges(); } private void UnwindSwapTradeCashPreHandle(trade tradePosition, trade tradeImport, string unwindType) { var tradeCashPres = DbContext.trade_cash_pre.Where(x => x.TradeId == tradePosition.id && x.ValidState != "InValid"); var tradeCashPreList= tradeCashPres.Where(y => y.Action == "系统操作-互换" && y.ValidState != "InValid" && !y.IsDeleted && y.ValueDate <= tradeImport.TradeDate.Value); var num = tradeCashPres.Where(x => x.Action != ClientCashInCashOut.系统操作_期权费).Count() + 1; var client = DataCacheProvider.GetClientDataSource().GetData(tradePosition.ClientId); //增加Pre现金交割交易记录 var tcPre = new trade_cash_pre(); DbContext.trade_cash_pre.Add(tcPre); tcPre.OptId = UserId; tcPre.OptName = UserName; tcPre.OptDate = OptDate; tcPre.ExceciseType = "现金"; tcPre.TradeType = tradePosition.BuySell; tcPre.CallPut = tradePosition.CallPut; tcPre.Notional = tradePosition.Notional; tcPre.TradeAmount = tradePosition.TradeAmount; tcPre.IsLastAction = unwindType == "全部平仓"; tcPre.TradeId = tradePosition.id; tcPre.FinalPrice = tradeImport.SpotPrice; tcPre.UnwindType = unwindType; if (tcPre.UnwindType == "全部平仓") { tcPre.UnwindNotional = tradePosition.Notional; tcPre.UnwindTradeAmount = tradePosition.TradeAmount; tcPre.UnwindPercentRate = tradePosition.Notional / tradePosition.OriginalNotional; } else { tcPre.UnwindNotional = tradeImport.Notional; tcPre.UnwindTradeAmount = tradeImport.TradeAmount; tcPre.UnwindPercentRate = tradeImport.Notional / tradePosition.OriginalNotional; } tcPre.NotionalPercentRate = tcPre.UnwindPercentRate; tradeBLL.SetFieldsByTradeType(tradePosition); var initialAmountPayQuote = PayoffSwapCalcService.GetInitialAmountSwapPay(tradePosition, tradePosition.trade_swap, tradePosition.trade_swap.PaySpotPrice ?? 0 , tradeImport.SpotPrice ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tcPre.UnwindPercentRate ?? 0), tradeImport.TradeDate.Value, null); var cashSwaps = DbContext.trade_cash_swap.Where(x => x.TradeId == tradePosition.id).ToArray(); //取最后一次手动收益; var lastManualCashSwap = cashSwaps.OrderByDescending(o => o.StartDate).FirstOrDefault(x => !x.IsAuto); var lastManualCash = lastManualCashSwap != null ? tradeCashPreList.FirstOrDefault(x => x.id == lastManualCashSwap.TradeCashId) : null; DateTime endDate; var preSwapDate = PayoffSwapCalcService.GetSwapRateStartDatePre(tradePosition, tradePosition.trade_swap, tradeImport.TradeDate.Value, null, lastManualCash, tradePosition.trade_swap.IsGetFloatingProfit, out endDate); var extraAmountGetQuote = PayoffSwapCalcService.GetExtraAmountBySwapRate(tradePosition.ClientId, tradePosition.TradeDate, tradePosition.trade_swap.GetSwapTimeAndRate, preSwapDate, endDate, tradePosition.trade_swap.AnnualDays ?? 0, (tradePosition.OriginalStockEqvNotional ?? 0) * (tcPre.UnwindPercentRate ?? 0)); var tradeCash = new trade_cash() { UnwindNotional = tcPre.UnwindNotional, UnwindTradeAmount = tcPre.UnwindTradeAmount, UnwindPercentRate = tcPre.UnwindPercentRate, FinalPrice = tcPre.FinalPrice }; var costFeeGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradeImport, tradeCash, true, false); var costTradePriceGetQuote = 0.0; if (!tradePosition.trade_swap.IsTradePriceWhenOpen) { costTradePriceGetQuote = PayoffSwapCalcService.GetCostFee(tradePosition, tradePosition, tradeCash, true, true); } tcPre.Amount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote - initialAmountPayQuote; tcPre.Action = ClientCashInCashOut.系统操作_平仓费; tcPre.Status = TradeCashStatusEnum.已执行; tcPre.ValueDate = tradePosition.SettlementDate.Value; tcPre.HappenedDate = tradeImport.TradeDate.Value; tcPre.ValidState = "Valid"; tcPre.ExerciseWay = TradeCashExerciseWayEnum.到期行权; tcPre.IsFinished = false; if (client.BoundSide == BoundSideEnum.北向) { tcPre.Number = tradePosition.TradeNumber + "_UW_" + num; } DbContext.SaveChanges(); if (unwindType == "全部平仓") { tradePosition.TradeStatus = "已平仓"; } else { tradePosition.HasPartialUnWind = 1; } tradePosition.UnWindDate = tcPre.HappenedDate; tradePosition.StockEqvNotional -= (tradePosition.SpotPrice ?? 0) * (tcPre.UnwindNotional ?? 0); tradePosition.Notional -= tcPre.UnwindNotional ?? 0; tradePosition.TradeAmount -= tcPre.UnwindTradeAmount ?? 0; tradePosition.UnWindNotional = tcPre.UnwindNotional; var trade_swap = DbContext.trade_swap.FirstOrDefault(x => x.TradeId == tcPre.TradeId); var trade_cash_swap = new trade_cash_swap(); trade_cash_swap.StartDate = tradePosition.StartDate.Value; trade_cash_swap.PayStartPrice = trade_swap.PayFinalPrice ?? trade_swap.PaySpotPrice; trade_cash_swap.PayFinalPrice = tcPre.FinalPrice; trade_cash_swap.PayInitialAmount = initialAmountPayQuote; trade_cash_swap.PayAmount = initialAmountPayQuote; trade_cash_swap.PaySwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.PaySwapTimeAndRate, tradePosition.UnWindDate.Value); trade_cash_swap.GetExtraAmount = extraAmountGetQuote; trade_cash_swap.GetCostFee = costFeeGetQuote + costTradePriceGetQuote; trade_cash_swap.GetAmount = extraAmountGetQuote + costFeeGetQuote + costTradePriceGetQuote; trade_cash_swap.GetSwapRate = PayoffSwapCalcService.GetSwapRateByDate(tradePosition.trade_swap.GetSwapTimeAndRate, tradePosition.UnWindDate.Value); trade_cash_swap.TradeId = tcPre.TradeId; trade_cash_swap.TradeCashPreId = tcPre.id; trade_cash_swap.FlowId = tradeImport.trade_swap.FlowId; trade_cash_swap.OptId = tcPre.OptId; trade_cash_swap.OptName = tcPre.OptName; trade_cash_swap.OptDate = DateTime.Now; DbContext.trade_cash_swap.Add(trade_cash_swap); var tcdGet = new trade_cash_detail { TradeId = tcPre.TradeId, TradeCashPreId = tcPre.id, Action = tcPre.Action, QuoteAmount = extraAmountGetQuote, ValueDate = tcPre.ValueDate, IsForGet = true, OptId = tcPre.OptId, OptName = tcPre.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.利息.ToString() }; DbContext.trade_cash_detail.Add(tcdGet); var tcdCostFeeGet = new trade_cash_detail { TradeId = tcPre.TradeId, TradeCashPreId = tcPre.id, Action = tcPre.Action, QuoteAmount = costFeeGetQuote, ValueDate = tcPre.ValueDate, IsForGet = true, OptId = tcPre.OptId, OptName = tcPre.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.了结手续费.ToString() }; DbContext.trade_cash_detail.Add(tcdCostFeeGet); var tcdCostTradePriceGet = new trade_cash_detail { TradeId = tcPre.TradeId, TradeCashPreId = tcPre.id, Action = tcPre.Action, QuoteAmount = costTradePriceGetQuote, ValueDate = tcPre.ValueDate, IsForGet = true, OptId = tcPre.OptId, OptName = tcPre.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.开仓手续费.ToString() }; DbContext.trade_cash_detail.Add(tcdCostTradePriceGet); var tcdPay = new trade_cash_detail { TradeId = tcPre.TradeId, TradeCashPreId = tcPre.id, Action = tcPre.Action, QuoteAmount = -initialAmountPayQuote, ValueDate = tcPre.ValueDate, IsForGet = false, OptId = tcPre.OptId, OptName = tcPre.OptName, OptDate = DateTime.Now, TradeCashType = TradeCashTypeEnum.浮动收益.ToString() }; DbContext.trade_cash_detail.Add(tcdPay); DbContext.SaveChanges(); tradeImport.Notional -= tcPre.UnwindNotional ?? 0; tradeImport.TradeAmount -= tcPre.UnwindTradeAmount ?? 0; var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeImport.UnderlyingCode); tradeImport.Lots -= tcPre.UnwindNotional / underlying.ContractSize; DbContext.SaveChanges(); } private trade_swap_flow MapSwapTradeFlow(DataRowReader reader) { var needCostFee = reader.GetString("是否收取手续费"); var isTradePriceWhenOpen = reader.GetString("是否开仓时收取手续费"); var isNight = reader.GetString("是否夜盘"); var swapFlow = new trade_swap_flow() { TradeDate = reader.GetDate("交易日", true), StartDate = reader.GetDate("北京时间自然日", true), ExerciseDate = reader.GetDate("到期日"), SettlementDate = reader.GetDate("结算日"), BuySell = reader.GetString("买卖方向", true), AssetUnitName = reader.GetString("簿记账户"), ClientNumber = reader.GetString("客户编号", true), ClientShortName = reader.GetString("客户简称"), UnderlyingCode = reader.GetString("标的全称", true), Lots = reader.GetDouble("手数", true).Value, SpotPrice = reader.GetDouble("价格", true), SingleFee = reader.GetDouble("按手数收费", false), UnAnnualRate = reader.GetDouble("按名义本金收费", false), ClearingAgency = reader.GetString("清算机构"), NeedCostFee = needCostFee == "否" || needCostFee == "N" ? false : true, IsTradePriceWhenOpen = isTradePriceWhenOpen == "是" || isTradePriceWhenOpen == "Y" ? true : false, IsNight = isNight == "是" || isNight == "Y" ? true : false, Comments = reader.GetString("备注"), Number = "", OptId = UserId, OptName = UserName, OptDate = DateTime.Now }; var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlow.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]在系统中不存在"); } else { if (swapFlow.ExerciseDate == null) { swapFlow.ExerciseDate = underlying.MaturityDate; } if (swapFlow.ExerciseDate == null) { throw new ServiceException($"客户编号[{swapFlow.ClientNumber}]标的代码[{swapFlow.UnderlyingCode}]到期日不能为空"); } if (swapFlow.SettlementDate == null) { swapFlow.SettlementDate = underlying.CloseDate; } if (swapFlow.AssetUnitName == null) { swapFlow.AssetUnitName = string.Empty; } if (swapFlow.SettlementDate != null && swapFlow.SettlementDate < swapFlow.ExerciseDate) { throw new ServiceException($"客户编号[{swapFlow.ClientNumber}]标的代码[{swapFlow.UnderlyingCode}]的结算日期不应该小于到期日"); } } var variety = DataCacheProvider.GetVariety(swapFlow.UnderlyingCode); if (variety == null) { throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]对应的品种在系统中不存在"); } else { if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any()) { throw new ServiceException($"标的代码[{swapFlow.UnderlyingCode}]对应的品种币种不能为空"); } else { swapFlow.QuoteCurrency = variety.QuoteCurrency; } } swapFlow.Number = new BizLogicZJ().GenerateFlowNumber(swapFlow, DbContext); SetDBModelCreator(swapFlow); DbContext.trade_swap_flow.Add(swapFlow); DbContext.SaveChanges(); return swapFlow; } private trade_swap_flow MapSwapTradeFlowGroup(DataRowReader reader) { var tradeAmount = reader.GetDouble("数量", false); var lots = reader.GetDouble("手数", false); var stockEqvNotional = reader.GetDouble("名义本金", false); var swapFlow = new trade_swap_flow() { TradeNumber = reader.GetString("交易编号", true), TradeDate = reader.GetDate("交易日", true), UnderlyingCode = reader.GetString("标的代码", true), BuySell = reader.GetString("买卖方向", true), SpotPrice = reader.GetDouble("价格", true), SingleFee = reader.GetDouble("按手数收费", false), UnAnnualRate = reader.GetDouble("按名义本金收费", false), NeedCostFee = true, IsTradePriceWhenOpen = true, OptId = UserId, OptName = UserName, OptDate = DateTime.Now, CreatorId = UserId, CreatorName = UserName, CreateDate = DateTime.Now }; swapFlow.StartDate = swapFlow.TradeDate; var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(swapFlow.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]在系统中不存在"); } else { if (stockEqvNotional != null && swapFlow.SpotPrice != 0) { tradeAmount = stockEqvNotional / swapFlow.SpotPrice; } if (tradeAmount != null) { lots = tradeAmount * underlying.CountRatio / underlying.ContractSize; } if (lots == null) { throw new ServiceException($"数量手数名义本金不能同时为空"); } else { swapFlow.Lots = lots.Value; } } var variety = DataCacheProvider.GetVariety(swapFlow.UnderlyingCode); if (variety == null) { throw new ServiceException($"该标的[{swapFlow.UnderlyingCode}]对应的品种在系统中不存在"); } else { if (string.IsNullOrWhiteSpace(variety.QuoteCurrency) && DbContext.currency.Any()) { throw new ServiceException($"标的代码[{swapFlow.UnderlyingCode}]对应的品种币种不能为空"); } else { swapFlow.QuoteCurrency = variety.QuoteCurrency; } } DbContext.trade_swap_flow.Add(swapFlow); DbContext.SaveChanges(); return swapFlow; } private trade MapSwapTradeHandle(trade_swap_flow swapFlow) { var client = DataCacheProvider.GetClientDataSource().AsQueryable().FirstOrDefault(n => swapFlow.ClientNumber.Equals(n.Number, StringComparison.OrdinalIgnoreCase)); if (client == null) { throw new ServiceException($"该客户编号[{swapFlow.ClientNumber}]在系统中不存在"); } if (!client.DerivativesInvestmentVarieties.Contains((int)DerivativesInvestmentVarietiesEnum.场外互换 + "")) { throw new ServiceException($"客户:{client.Name}未设置交易种类“场外互换”,无法生成互换交易!"); } if (swapFlow.Lots <= 0) { throw new ServiceException($"客户[{swapFlow.ClientNumber}]对应的流水手数[{swapFlow.Lots}]需要为正数"); } var td = new trade { TradeDate = swapFlow.TradeDate, StartDate = swapFlow.StartDate, ExerciseDate = swapFlow.ExerciseDate, SettlementDate = swapFlow.SettlementDate == null ? swapFlow.ExerciseDate : swapFlow.SettlementDate, BuySell = "卖出", TradeType = "收益互换", StructureType = "收益互换", ClientId = client.id, ClientName = client.Name, QuoteCurrency = swapFlow.QuoteCurrency, SettlementCurrency = client.SettlementCurrency, UnderlyingCode = swapFlow.UnderlyingCode, SpotPrice = swapFlow.SpotPrice, Lots = swapFlow.Lots, IsNight = swapFlow.IsNight, OpponentRole = "甲方", MarginType = MarginTypeEnum.DEFAULT, trade_swap = new trade_swap() { FlowId = swapFlow.id } }; td.MetaDic["交易场所"] = "柜台市场"; if (string.IsNullOrWhiteSpace(swapFlow.ClearingAgency) && string.IsNullOrWhiteSpace(client.ClearingAgency)) { throw new ServiceException($"该流水需要维护清算机构信息或该客户[{td.ClientName}]需要维护清算机构信息"); } td.MetaDic["清算机构"] = string.IsNullOrWhiteSpace(swapFlow.ClearingAgency) ? client.ClearingAgency : swapFlow.ClearingAgency; //if (string.IsNullOrWhiteSpace(client.MainProtocolCode)) //{ // throw new ServiceException($"该客户[{td.ClientName}]需要维护主协议编号信息"); //} td.MetaDic["主协议编号"] = client.MainProtocolCode; //if (string.IsNullOrWhiteSpace(client.SupProtocolCode)) //{ // throw new ServiceException($"该客户[{td.ClientName}]需要维护补充协议编号信息"); //} td.MetaDic["补充协议编号"] = client.SupProtocolCode; var varitey = DataCacheProvider.GetVariety(td.UnderlyingCode); var clientVarietyConfig = DbContext.client_variety_config.Where(x => x.ClientId == td.ClientId && x.VarietyId == varitey.id && x.ValueDate <= td.TradeDate).OrderByDescending(x => x.ValueDate).FirstOrDefault(); if (clientVarietyConfig == null) { throw new ServiceException($"该客户[{td.ClientName}]需要维护品种[{varitey.VarietyCode}]在[{td.TradeDate}]相关的收费参数配置"); } //标的代码(必需) var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); if (underlying == null) { throw new ServiceException($"该标的代码[{td.UnderlyingCode}]在系统中不存在"); } else { td.UnderlyingId = underlying.id; td.UnderlyingAssetClass = underlying.UnderlyingType; td.MaturityDate = underlying.MaturityDate; if (td.ExerciseDate == null) { td.ExerciseDate = underlying.MaturityDate; swapFlow.ExerciseDate = underlying.MaturityDate; } td.UnderlyingInstrumentType = underlying.UnderlyingInstrumentType; td.UnderlyingAssetName = underlying.UnderlyingName; } if (td.ExerciseDate == null) { throw new ServiceException($"客户编号[{swapFlow.ClientNumber}]标的代码[{swapFlow.UnderlyingCode}]到期日不能为空"); } var variety = DataCacheProvider.GetVarietyDataSource().GetData(underlying.UnderlyingTypeId); //交易份额 td.Notional = (td.Lots ?? 0) * underlying.ContractSize; td.TradeAmount = td.Notional / variety.CountRatio; td.OriginalNotional = td.Notional; td.StockEqvNotional = (td.SpotPrice ?? 0) * td.Notional; td.StockEqvNotionalReal = td.StockEqvNotional; td.OriginalStockEqvNotional = td.StockEqvNotional; td.PrincipalRate = 0; td.ParticipationRate = 1; var assetUnit = DataCacheProvider.GetAssetUnitDataSource().AsQueryable().FirstOrDefault(x => ("," + x.TraderIds + ",").Contains("," + UserId + ",")); if (!string.IsNullOrWhiteSpace(swapFlow.AssetUnitName)) { assetUnit = DataCacheProvider.GetAssetUnitDataSource().AsQueryable().FirstOrDefault(x => x.Name == swapFlow.AssetUnitName); if (assetUnit == null) { throw new ServiceException($"不存在该簿记账户[{swapFlow.AssetUnitName}]"); } } if (assetUnit == null) { throw new ServiceException($"不存在和交易员[{UserName}]匹配的簿记账户"); } td.AssetId = assetUnit.id; td.AssetBookName = assetUnit.Name; td.TraderId = UserId; td.TraderName = UserName; td.trade_swap.GetSwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";" + (clientVarietyConfig?.AnnualRate ?? 0).ToString(); td.trade_swap.PaySwapTimeAndRate = td.ExerciseDate.Value.ToString("yyyy-MM-dd") + ";0"; //0代表了结时支付,1代表结算日支付 td.trade_swap.SettlementPayType = swapFlow.SettlementDate == null ? 0 : 1; td.trade_swap.IsTradePriceWhenOpen = swapFlow.IsTradePriceWhenOpen; var isAnnualSet = swapFlow.SingleFee != null || swapFlow.UnAnnualRate != null; td.trade_swap.GetSingleFee = swapFlow.NeedCostFee ? (isAnnualSet ? (swapFlow.SingleFee ?? 0) : clientVarietyConfig?.SingleFee) : 0; td.trade_swap.GetUnAnnualRate = swapFlow.NeedCostFee ? (isAnnualSet ? (swapFlow.UnAnnualRate ?? 0) : clientVarietyConfig?.UnAnnualRate) : 0; td.trade_swap.AnnualDays = clientVarietyConfig?.AnnualDays; //交易方向 var longshort = swapFlow.BuySell; switch (longshort) { case "买入": case "B": td.trade_swap.PayLongShort = "多头"; break; case "卖出": case "S": td.trade_swap.PayLongShort = "空头"; break; default: throw new ServiceException("买卖方向 填写错误:" + longshort); } return td; } public void BackSwapTradeByTradeFlow(trade_swap_flow flow) { var client = ClientModule.ClientDataQueryService.GetClientByNumber(flow.ClientNumber); var tradeCashList = (from tradeCash in DbContext.trade_cash join trade in DbContext.trade on tradeCash.TradeId equals trade.id join tradeSwap in DbContext.trade_swap on trade.id equals tradeSwap.TradeId join tradeCashSwap in DbContext.trade_cash_swap on tradeCash.id equals tradeCashSwap.TradeCashId where trade.UnderlyingCode == flow.UnderlyingCode && tradeSwap.OriginalTradeId == null && trade.ClientId == client.id && (tradeCashSwap.FlowId >= flow.id && tradeCash.ValueDate == flow.TradeDate || tradeCash.ValueDate > flow.TradeDate) select new { tradeCash, tradeCashSwap }).OrderByDescending(x => x.tradeCash.id).ToList(); tradeCashList.ForEach(x => { var trade = DbContext.trade.Find(x.tradeCash.TradeId); trade.Notional = x.tradeCash.Notional; var variety = DataCacheProvider.GetVarietyDataSource().GetData(trade.VarietyId ?? 0); if (variety != null && variety.CountRatio != 0) { trade.TradeAmount = x.tradeCash.Notional / variety.CountRatio; } else { trade.TradeAmount = x.tradeCash.Notional; } trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor); //分步回退时将倒数第二条平仓记录赋值给trade var lastSecondTradeCash = DbContext.trade_cash.Where(y => y.TradeId == x.tradeCash.TradeId && y.id < x.tradeCash.id && y.ValidState != "InValid" && y.Action != "系统操作-期权费").OrderByDescending(y => y.id).FirstOrDefault(); if (lastSecondTradeCash != null && lastSecondTradeCash.Action == "系统操作-平仓费") { trade.UnWindDate = lastSecondTradeCash.ValueDate; trade.FinalPrice = lastSecondTradeCash.FinalPrice; trade.UnWindNotional = lastSecondTradeCash.UnwindNotional; trade.UnWindPrice = lastSecondTradeCash.UnwindPrice; trade.HasPartialUnWind = 1; } else { trade.UnWindDate = null; trade.FinalPrice = null; trade.UnWindNotional = null; trade.UnWindPrice = null; trade.HasPartialUnWind = null; } trade.CheckStatus = null; trade.OptId = UserId; trade.OptName = UserName; trade.OptDate = DateTime.Now; trade.TradeStatus = ConsTrade.确认成交; trade.ProcessOrderId = 0; trade.ProcessOptDate = null; trade.ProcessStatus = null; DbContext.SaveChanges(); RemoveEodTradeAndFutureInfo(true, trade.id, x.tradeCash.ValueDate, new List() { x.tradeCash.id }); AddTradeOperationHistoryAndSetParentTradeInfo(true, trade, "修改交易流水"); }); var tradeCashPreList = (from tradeCashPre in DbContext.trade_cash_pre join tradeCashSwap in DbContext.trade_cash_swap on tradeCashPre.id equals tradeCashSwap.TradeCashPreId where tradeCashSwap.FlowId == flow.id select new { tradeCashPre, tradeCashSwap }).ToList(); tradeCashPreList.ForEach(x => { var trade = DbContext.trade.Find(x.tradeCashPre.TradeId); trade.Notional = x.tradeCashPre.Notional; var variety = DataCacheProvider.GetVarietyDataSource().GetData(trade.VarietyId ?? 0); if (variety != null && variety.CountRatio != 0) { trade.TradeAmount = x.tradeCashPre.Notional / variety.CountRatio; } else { trade.TradeAmount = x.tradeCashPre.Notional; } trade.StockEqvNotional = TradeHelper.GetStockEqvNotional(trade.Notional * trade.SpotPrice, trade.ParticipationRate, trade.AnnualizeFactor); //分步回退时将倒数第二条平仓记录赋值给trade var lastSecondTradeCashPre = DbContext.trade_cash_pre.Where(y => y.TradeId == x.tradeCashPre.TradeId && y.id < x.tradeCashPre.id && y.ValidState != "InValid" && y.Action != "系统操作-期权费").OrderByDescending(y => y.id).FirstOrDefault(); if (lastSecondTradeCashPre != null && lastSecondTradeCashPre.Action == "系统操作-平仓费") { trade.UnWindDate = lastSecondTradeCashPre.HappenedDate; trade.FinalPrice = lastSecondTradeCashPre.FinalPrice; trade.UnWindNotional = lastSecondTradeCashPre.UnwindNotional; trade.UnWindPrice = lastSecondTradeCashPre.UnwindPrice; trade.HasPartialUnWind = 1; } else { trade.UnWindDate = null; trade.FinalPrice = null; trade.UnWindNotional = null; trade.UnWindPrice = null; trade.HasPartialUnWind = null; } trade.CheckStatus = null; trade.OptId = UserId; trade.OptName = UserName; trade.OptDate = DateTime.Now; trade.TradeStatus = ConsTrade.确认成交; trade.ProcessOrderId = 0; trade.ProcessOptDate = null; trade.ProcessStatus = null; DbContext.SaveChanges(); var tradeCashPreIds = DbContext.trade_cash_pre.Where(y => y.TradeId == x.tradeCashPre.TradeId && y.id >= x.tradeCashPre.id).Select(y => y.id).ToList(); RemoveEodTradeAndFutureInfo(true, trade.id, x.tradeCashPre.HappenedDate ?? x.tradeCashPre.ValueDate, tradeCashPreIds: tradeCashPreIds); AddTradeOperationHistoryAndSetParentTradeInfo(true, trade, "修改交易流水"); }); var tradeList = (from trade in DbContext.trade join swap in DbContext.trade_swap on trade.id equals swap.TradeId where trade.UnderlyingCode == flow.UnderlyingCode && swap.OriginalTradeId == null && trade.ClientId == client.id && (swap.FlowId >= flow.id && trade.TradeDate == flow.TradeDate || trade.TradeDate > flow.TradeDate) && trade.ValidState != "InValid" select new { trade, swap }).ToList(); var baseService = new TradeServiceBase(UserInfo, DbContext); tradeList.ForEach(x => new TradeInvalidService(baseService).InvalidTrade(x.trade.id, false)); } private void SaveTradeMeta(trade t) { if (t != null && t.MetaDic != null && t.MetaDic.Count() > 0) { foreach (var kv in t.MetaDic) { if (!string.IsNullOrEmpty(kv.Value)) { AddTradeMeta(false, t.id, kv.Key, kv.Value); } } } } //public void generateSettleDocument(List cashes) //{ // if (cashes.Count() > 0) // { // var clientTradeDict = // cashes.GroupBy(O => O.ClientName + "|" + O.ValueDate) // .ToDictionary(K => K.Key, V => V.Select(O => O.id).ToList()); // foreach (var tradeCashs in clientTradeDict) // { // var clienName = cashes.FirstOrDefault().ClientName; // var client = DbContextFactory.GetClientDbContext(OptUser).client.Where(o => o.Name == clienName).FirstOrDefault(); // if (client != null && client.BoundSide == BoundSideEnum.北向) // { // foreach (var tc in tradeCashs.Value) // { // new RDBatchEndBillGenerateService(OptUser) // .Generate(new List { tc }, null, "PDF", OptUser.UserId, OptUser.UserName).ToList(); // } // } // else // { // new RDBatchEndBillGenerateService(OptUser) // .Generate(tradeCashs.Value, null, "PDF", OptUser.UserId, OptUser.UserName).ToList(); // } // } // } //} #region---内部业务类---- class DataRowReader { DataRow _row; readonly Dictionary _colMap; public DataRowReader(DataTable table) { var colCount = table.Columns.Count; _colMap = new Dictionary(colCount, StringComparer.OrdinalIgnoreCase); var row1 = table.Rows[0]; var preCol1 = string.Empty; for (var index = 0; index < colCount; index++) { var col1 = row1[index]?.ToString()?.Trim(); if (!string.IsNullOrWhiteSpace(col1)) { preCol1 = col1; } else { continue; } _colMap[preCol1] = index; } } /// /// 设置datarow /// public void SetDataRow(DataRow row) { _row = row; } public string GetString(string fieldName, bool required = false) { var str = _colMap.TryGetValue(fieldName, out var colIndex) ? _row[colIndex]?.ToString()?.Trim() : null; if (required && string.IsNullOrWhiteSpace(str)) { throw new ServiceException($"{fieldName} 必须填写"); } return str; } public double? GetDoubleOrPercent(string fieldName, bool required, bool percent) { var str = GetString(fieldName, required); if (!required && string.IsNullOrWhiteSpace(str)) { return null; } if (percent && (percent = str.EndsWith("%"))) { str = str.TrimEnd('%'); } return double.TryParse(str, out var num) ? (percent ? num / 100 : num) : throw new ServiceException($"{fieldName} 填写错误:{str}"); } public double? GetDouble(string fieldName, bool required = false) { var str = GetString(fieldName, required); if (!required && string.IsNullOrWhiteSpace(str)) { return null; } return double.TryParse(str, out var num) ? num : throw new ServiceException($"{fieldName} 填写错误:{str}"); } //为了兼容模板修改导致的字段名称改变问题 public double? GetDouble(string fieldName, string fieldName2, bool required = false) { var str = GetString(fieldName, false) ?? GetString(fieldName2, false); if (string.IsNullOrWhiteSpace(str)) { return required ? throw new ServiceException($"{fieldName} 必须填写") : (double?)null; } return double.TryParse(str, out var num) ? num : throw new ServiceException($"{fieldName} 填写错误:{str}"); } public double? GetPercent(string fieldName, bool required = false) { var str = GetString(fieldName, required); if (!required && string.IsNullOrWhiteSpace(str)) { return null; } var percent = str.EndsWith("%"); if (percent) { str = str.TrimEnd('%'); } return double.TryParse(str, out var num) ? (percent ? num / 100 : num) : throw new ServiceException($"{fieldName} 填写错误:{str}"); } /// /// 获取日期(不包括时间) /// public DateTime? GetDate(string fieldName, bool required = false) { var str = GetString(fieldName, required); if (!required && string.IsNullOrWhiteSpace(str)) { return null; } if (str.Length == 8 && Regex.IsMatch(str, @"^\d+$")) { return DateTime.TryParseExact(str, "yyyyMMdd", CultureInfo.InvariantCulture, DateTimeStyles.None, out var dt2) ? dt2 : throw new ServiceException($"{fieldName} 填写错误:{str}"); } return DateTime.TryParse(str, out var dt) ? dt.Date : throw new ServiceException($"{fieldName} 填写错误:{str}"); } /// /// /// public int? GetInt32(string fieldName, bool required = false) { var str = GetString(fieldName, required); if (!required && string.IsNullOrWhiteSpace(str)) { return null; } return int.TryParse(str, out var num) ? num : throw new ServiceException($"{fieldName} 填写错误:{str}"); } } #endregion } }