using Newtonsoft.Json.Linq; using YLErp.Core.Helpers; using YLErp.DBModels; using YLErp.DBModels.Consts; using YLErp.DBModels.Enums; using YLErp.Models; using YLErp.Plugins.TradeDocGenerator; using YLErp.Plugins.TradeDocGenerator.Abstracts; using YLErp.QdpModule; namespace YLErp.Plugins.GuoLian.DocumentGenerator { /// /// 国联证券结算单生成器 /// internal class TradeSettleBillGenerator : BaseSettleBillGenerator, ITradeSettleBillGenerator { protected override string GetContractNo(out string contractIndex) { var contractNo = Context.GenerateContractNo(out contractIndex); return contractNo; } protected override void PrepareViewData(Dictionary dic) { var client = Context.GetClient(); var flowEvents = Context.GetFlowEvents(); var allFlowEvents = Context.GetAllFlowEvents(); var swapPositions = Context.GetSwapPositions(); var trades = Context.Trades; var tradeIds = trades.Select(t => t.id).ToList(); var tradeExtends = Context.GetTrade_Extends(tradeIds); List table = new List(); SwapEndConfirmModel outPut = new SwapEndConfirmModel(); foreach (var flowEventGroup in flowEvents) { var tradeId = flowEventGroup.SwapTradeId; var positions = swapPositions.Where(x => x.SwapTradeId == tradeId && x.IsInitial).ToList(); var posi = positions.FirstOrDefault(f => f.id == flowEventGroup.PositionId); var unwindFlowEvents = allFlowEvents.Where(x => x.EventId == flowEventGroup.EventId); var trade = trades.FirstOrDefault(x => x.id == tradeId); var preSettleDate = flowEventGroup.UnwindDate.Value.AddDays(-1); var swapEodPositions = Context.GetEodPositions(tradeId, preSettleDate); var tradeExtend = tradeExtends.FirstOrDefault(x => x.TradeId == tradeId); var ratio = posi.PositionType == (int)PositionTypeFlag.Long ? 1 : -1; ExcelReportModel row = new ExcelReportModel(); var confirmNo = Context.Gettrade_contract_r(tradeId, ContractTypeEnum.Trade); if (string.IsNullOrEmpty(confirmNo)) { throw new ServiceException($"{trade.TradeNumber}未生成交易确认书"); } row.TradeNumber = confirmNo; row.ClientName = client.Name; row.UnderlyingCode = flowEventGroup.UnderlyingCode; row.StartDate = trade.StartDate.Value.ToString("yyyy-MM-dd"); var eventDate = flowEventGroup.UnwindDate.Value; row.EventDate = eventDate.ToString("yyyy-MM-dd"); var payDate = flowEventGroup.PayDate; var sr = tradeExtend == null ? 0 : tradeExtend.ExtendObj.SettlementRules; if (!payDate.HasValue) { payDate = QdpCalendarHelper.GetNonHoliday(flowEventGroup.EventDate.AddDays(sr)); } row.PayDate = payDate.Value.ToString("yyyy-MM-dd"); row.ClosePrice = ((flowEventGroup.TradingAmountAvg) * 100).ToString("0.00000000"); decimal interestRate = unwindFlowEvents.Where(x => ConsTrade.InterestModels.Contains(x.InterestMode)).Sum(s => s.InterestRate); row.InterestRate = interestRate.ToString("0.00%"); var PosiNotionalValue = flowEventGroup.Quantity * flowEventGroup.ContractSize * posi.PosiGrossPrice; if (flowEventGroup.EventId.HasValue) { var swapEvent = Context.GetEvent(flowEventGroup.EventId.Value); if (swapEvent != null) { swapEvent.unwindData = JsonHelper.Deserialize(swapEvent.EventData); PosiNotionalValue = swapEvent.unwindData.CloseNotionalValue; } } row.Quantity = flowEventGroup.Quantity.ToString("0.00"); row.PosiNotionalValue = PosiNotionalValue.ToString("0.00"); row.PosiNetPrice = (posi.PosiGrossPrice * 100).ToString("0.00000000"); //var tradingFee = (flowEventGroup.TradingAmountFeeAvg- posi.PosiNetPrice- flowEventGroup.TradingAmountAvg+ posi.PosiGrossPrice)* PosiNotionalValue* ratio; var tradingFee = flowEventGroup.TradingFee + flowEventGroup.TradingFeePending; row.Fee = (-tradingFee).ToString("0.00"); var RateDays = (eventDate - trade.StartDate.Value).Days; RateDays = RateDays < 0 ? 0 : RateDays; row.RateDays = RateDays.ToString(); var MarginAmout = positions.Where(x => x.InterestMode == (int)InterestModeEnum.初始预付金).Sum(s => s.InterestPrincipalFix * (s.InterestDirection == (int)SwapDirectionEnum.收取 ? 1 : -1)); row.MarginAmout = Math.Abs(MarginAmout).ToString("0.00"); var MarginRebateRate = positions.Where(x => x.InterestMode == (int)InterestModeEnum.初始预付金).Sum(s => s.InterestRateDefault); row.MarginRebateRate = MarginRebateRate.ToString("0.00%"); var MarginInterestAmount = unwindFlowEvents.Where(x => ConsTrade.InterestMarginModels.Contains(x.InterestMode)).Sum(s => s.InterestClosePnL); row.MarginInterestAmount = (-MarginInterestAmount).ToString("0.00"); var InterestAmount = unwindFlowEvents.Where(x => ConsTrade.InterestModels.Contains(x.InterestMode)).Sum(s => s.InterestClosePnL) * -1; row.InterestAmount = InterestAmount.ToString("0.00"); //var lastInterestAmount= swapEodPositions.Where(x => ConsTrade.InterestModels.Contains(x.InterestMode)).Sum(s => s.InterestIncomeSum); //var lastPosiNotionalValue = swapEodPositions.Sum(s=>s.PosiNotionalValue); //var InterestAmount = lastPosiNotionalValue==0?0: - lastInterestAmount* PosiNotionalValue/ lastPosiNotionalValue; //row.InterestAmount = InterestAmount.ToString("0.00"); //var lastMarginAmount = swapEodPositions.Where(x => ConsTrade.InterestMarginModels.Contains(x.InterestMode)).Sum(s => s.InterestIncomeSum); //var MarginInterestAmount = lastMarginAmount == 0 ? 0 : -lastMarginAmount * PosiNotionalValue / lastMarginAmount; //row.MarginInterestAmount = MarginInterestAmount.ToString("0.00"); var FloatRate = PosiNotionalValue == 0 ? 0 : InterestAmount / PosiNotionalValue; row.FloatRate = FloatRate.ToString("0.0000%"); var PosiPnl = -flowEventGroup.MarkClosePnl; row.PosiPnl = PosiPnl.ToString("0.00"); var markClosePnl = -flowEventGroup.FloatPnlSum; row.MarkClosePnl = markClosePnl.ToString("0.00"); row.DividendIn = (-flowEventGroup.DividendIn).ToString("0.00"); var marginBackAmount = unwindFlowEvents.Where(x => ConsTrade.InterestMarginModels.Contains(x.InterestMode)).Sum(s => s.InterestPrincipal); var NetSettleAmout = unwindFlowEvents.Sum(x => x.InterestClosePnL) * -1 + flowEventGroup.FloatPnlSum * -1 + marginBackAmount; row.NetSettleAmout = NetSettleAmout.ToString("0.00"); table.Add(row); } outPut.table = table; dic["TRS结算单"] = outPut; } protected override void PrepareViewData(Dictionary dic) { var client = Context.GetClient(); if (string.IsNullOrEmpty(client.SettleFileNumber)) { throw new ServiceException($"{client.Name}未设置定义文件编号"); } var flowEvents = Context.GetFlowEvents(); var allFlowEvents = Context.GetAllFlowEvents(); var swapPositions = Context.GetSwapPositions(); var trades = Context.Trades; var eventDate = flowEvents.First().UnwindDate; var td = trades.First(); var realPositions = swapPositions.Where(x => x.PosiQuantity > 0 && !x.IsInitial).ToList(); var posiNationalValue = realPositions.Sum(x => x.PosiNotionalValue); var metaDic = Context.GetTradeMetas(td.id); dic["主协议编号"] = metaDic[ConsTradeMetaKey.MainProtocolCode]; dic["文件编号"] = client.SettleFileNumber; dic["乙方"] = client.Name; dic["管理人名称"] = client.Manager; var confirmNo = Context.Gettrade_contract_r(td.id, ContractTypeEnum.Trade); if (string.IsNullOrEmpty(confirmNo)) { throw new ServiceException($"{td.TradeNumber}未生成交易确认书"); } FormatToDict("平仓日期", eventDate, dic); JArray table = new JArray(); JArray table2 = new JArray(); foreach (var flowEvent in flowEvents) { var tradeId = flowEvent.SwapTradeId; var positions = swapPositions.Where(x => x.SwapTradeId == tradeId).ToList(); var posi = positions.FirstOrDefault(f => f.PositionId == flowEvent.PositionId); JObject row = new JObject(); row["交易确认书编号"] = confirmNo; var ratio = flowEvent.PositionType == (int)PositionTypeFlag.Long ? 1 : -1; row["多空方向"] = flowEvent.PositionType == (int)PositionTypeFlag.Long ? "多" : "空"; FormatToDict("平仓日期", eventDate, row); underlying_manager underlying = Context.GetTradeUnderlying(flowEvent.UnderlyingCode); row["标的代码"] = flowEvent.UnderlyingCode; row["标的名称"] = underlying?.UnderlyingName; var preQty = flowEvent.Quantity + flowEvent.PositionQty ?? 0; FormatToDict("平仓前数量", Convert.ToDouble(preQty) * ratio, row); FormatToDict("平仓数量", Convert.ToDouble(flowEvent.Quantity), row); FormatToDict("平仓后数量", Convert.ToDouble(flowEvent.PositionQty ?? 0) * ratio, row); FormatToDict("平仓成交金额", Convert.ToDouble(flowEvent.Quantity * posi.PosiNetPrice * flowEvent.ContractSize), row); table.Add(row); } JObject row2 = new JObject(); row2["交易确认书编号"] = confirmNo; FormatToDict("平仓日期", eventDate, row2); FormatToDict("平仓后名义本金", Convert.ToDouble(posiNationalValue), row2); table2.Add(row2); dic["table"] = table; dic["table2"] = table2; } protected override string GetTemplateFilePath() { var trades = Context.Trades; var templatePath = string.Empty; if (trades.Any(s => s.StructureType == "多空组合" || s.StructureType == "定义文件型债券收益互换")) { templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs/settlement_template/dma_01.docx"); return templatePath; } templatePath = MosPathHelper.Combine(GlobalConfig.PluginFolder, "App_Docs/settlement_template/nodma_01.xlsx"); return templatePath; } protected override string GetOutputFileName(string contractNo, string contractIndex) { var trades = Context.Trades; var client = Context.GetClient(); var flowEvents = Context.GetFlowEvents(); var eventDate = flowEvents.FirstOrDefault().UnwindDate.Value; var valueDate = eventDate.ToString("yyyy-MM-dd"); var count = Context.GetDMASelttementCount(client.id, eventDate); var countStr = count == 0 ? "" : "-" + (count + 1).ToString(); var FullName = $"结算单-{client.Name}-{valueDate}{countStr}"; if (trades.Any(s => s.StructureType == "多空组合" || s.StructureType == "定义文件型债券收益互换")) { FullName = $"{client.Name}-结算确认书-{valueDate}-交易平仓{countStr}"; return $"{FullName}.docx"; } return $"{FullName}.xlsx"; } } }