using YLErp.BLL; using YLErp.BLL.Eod; using YLErp.Configuration; using YLErp.Modules.CalculationModule; namespace YLErp.Modules.TradeModule.OrderModule { /// /// 不要再合并3.9 /// public class TradeTerminationAbstractService { /// /// /// public static string GetAbstractInfoText(trade_cash tc, trade td, bool isUnwind, bool useHeader = false, bool derive = false) { var items = isUnwind ? GetUnwindAbstractInfoItems(tc, td).ToList() : GetExerciseAbstractInfoItems(tc, td).ToList(); var bodyIndent = string.Empty; if (items.Any()) { //var maxLen = items.Max(n => n.text.Length); //bodyIndent = new string(' ', maxLen + 1); //items = items.Select(n => (n.text == "#" ? bodyIndent : n.text.PadLeft(maxLen, ' '), n.value)).ToList(); items = items.Select(n => (n.text == "#" ? new string(' ', 5) : n.text, n.value)).ToList(); } var headIndent = bodyIndent.Length > 3 ? bodyIndent.Substring(0, bodyIndent.Length - 3) : string.Empty; var list = new List<(string text, string value)>(); if (derive == true) { list = new List<(string text, string value)>() { (headIndent, PS.Config.CompanyName), (headIndent, "【场外了结记录摘要】"), (string.Empty, "####") }; } else { list = new List<(string text, string value)>(); } list.AddRange(items); return string.Join("\r\n", list.Select( n => string.IsNullOrEmpty(n.text) ? n.value : n.text.EndsWith(" ") ? n.text + n.value : n.text + ":" + n.value)); } /// /// 生成平仓摘要 /// public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems(trade_cash tc, trade td) { if (td.TradeType == "远期") { return GetUnwindAbstractInfoItems_Forward(tc, td); } if (td.TradeType == "雪球期权") { return GetUnwindAbstractInfoItems_snowball(tc, td, true); } if (td.TradeType == "现金流交易") { return GetUnwindAbstractInfoItems_cashflow(tc, td); } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString); var IsUsePremiumRate = td.IsUsePremiumRate == true; var SpotPrice = underlying.UnderlyingInstrumentType == "CommodityFutures" ? td.SpotPrice : td.InitialSpotPrice; var strikeFmt = new Func(d => d.OtcFormatUmPrice(td.IsMoneynessOption == "是")); var premiumFmt = IsUsePremiumRate ? new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP)) : new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice)); var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock" ? " 股" : " " + td.QuoteUnitSingle); var tradeType = GetTradeType(td); var istrade_barrier = td.TradeType == "障碍期权"; //如果是组合标的 if (underlying.UnderlyingType == "组合标的") { if (!string.IsNullOrWhiteSpace(td.SyntheticUnderlyingTipsInfo)) { td.UnderlyingCode = td.SyntheticUnderlyingTipsInfo; } else { td.UnderlyingCode = synthetic_underlyingBLL.GetUnderlyingTipsInfo(td.UnderlyingCode); } } var list = new List<(string, string)>(); if (PS.Config.Is厦门象屿) { list.Add(("平仓信息", "")); } list.AddRange(new[]{ ("交易编号", td.TradeNumber), ("开仓日期", td.TradeDate.OtcFormatDate()), ("开仓方向", td.ClientName), ("#", td.BuySell == "买入" ? "卖出" : "买入"), ("期权类型",(PS.Config.Is光大光子 && td.TradeType=="自定义交易")?td.StructureIntroduction : tradeType), ("标的代码",td.UnderlyingCode), }); if (istrade_barrier) { list.Add(("观察频率", td.trade_barrier_option.ObservationDates ?? "每日观察")); list.Add(("报价单位", QuoteUnitString)); list.Add(("障碍水平", strikeFmt(td.trade_barrier_option.BarrierPrice))); } var actualExerciseDate = td.ExerciseDate; if (td.MetaDic == null || td.MetaDic.Count == 0) { var exerciseDate = new TradeMetaService(OptUserInfo.SystemUser).GetTradeMeta(td.id, "ActualExerciseDate"); if (!string.IsNullOrWhiteSpace(exerciseDate) && DateTime.TryParse(exerciseDate, out var tempDate)) { actualExerciseDate = tempDate; } } list.Add(("执行价格", strikeFmt(td.Strike))); list.Add(("到期日期", actualExerciseDate.OtcFormatDate())); if (istrade_barrier) { list.Add(("补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateRate) : strikeFmt(td.trade_barrier_option.Rebate))); list.Add(("高障碍补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateHighRate) : strikeFmt(td.trade_barrier_option.RebateHigh))); list.Add(("补偿支付", td.trade_barrier_option.RebateTypeCn)); } list.Add(("平仓日期", tc.ValueDate.OtcFormatDate())); bool ActualHasMinusValueOptions = valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? ConsTrade.HasMinusValueOptions.Contains(td.TradeType) : !ConsTrade.HasMinusValueOptions.Contains(td.TradeType); if (IsUsePremiumRate) { list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + " (开仓)")); list.Add((new string(' ', 5), tc.FinalPrice.OtcFormatUmPrice() + " (平仓)")); var premiumRate = td.PremiumRate * (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? EodOperationBase.GetSign(td.BuySell) : 1); list.Add(("期权费率", premiumFmt(premiumRate) + " (开仓) ")); //计算出交易员角度的值 var unwindPricePercentRate = tc.UnwindPricePercentRate * (ActualHasMinusValueOptions ? 1 : EodOperationBase.GetSign(td.BuySell)); //结算视角需要客户视角 unwindPricePercentRate *= (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? -1 : 1); list.Add((new string(' ', 5), premiumFmt(unwindPricePercentRate) + "(平仓)")); } else { using (var db = DbContextFactory.GetYLDbContext()) { list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + " (开仓)")); list.Add((new string(' ', 5), tc.FinalPrice.OtcFormatUmPrice() + " (平仓)")); var openPrice = td.TradeSinglePrice * (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? EodOperationBase.GetSign(td.BuySell) : 1); list.Add((" 权利金", premiumFmt(openPrice) + " (开仓) ")); //计算出交易员角度的值 var unwindPrice = tc.UnwindPrice * (ActualHasMinusValueOptions ? 1 : EodOperationBase.GetSign(td.BuySell)); //结算视角需要客户视角 unwindPrice *= (valuedateBLL.SystemDate.UnwindSinglePriceAngle == 1 ? -1 : 1); list.Add((new string(' ', 5), premiumFmt(unwindPrice) + "(平仓)")); } } var amount = tc.Amount * (valuedateBLL.SystemDate.UnwindAmountAngle == 1 ? -1 : EodOperationBase.GetSign(td.BuySell)); if (IsUsePremiumRate) { list.AddRange(new[] { ("平仓比例", tc.UnwindPercentRate.OtcFormatPercent()), ("平仓总额", (amount).OtcFormatMoney()+"元"), ("实现盈亏",(-TradeCalcHelper.CalcChildTradeSumWinLoss(td,tc,IsUsePremiumRate,underlying.CountRatio)).OtcFormatMoney()+" 元") }); } else { list.AddRange(new[] { ("平仓数量",(td.UnderlyingInstrumentType=="Stock"?tc.UnwindNotional.OtcFormatNotional()+"股": tc.UnwindTradeAmount.OtcFormatNotional(underlying.CountRatio,PS.Config.IsUseDisplayNotional)+ " " +(td.QuoteUnitSingle == "吨" &&PS.Config.IsUseDisplayNotional&& underlying.UnderlyingType == "鸡蛋" ? "半吨":td.QuoteUnitSingle) )), ("平仓总额", (amount).OtcFormatMoney()+"元"), ("实现盈亏",(-TradeCalcHelper.CalcChildTradeSumWinLoss(td,tc,IsUsePremiumRate,underlying.CountRatio)).OtcFormatMoney()+" 元") }); } return list; } /// /// 生成行权摘要 /// public static IEnumerable<(string text, string value)> GetExerciseAbstractInfoItems(trade_cash tc, trade td) { if (td.TradeType == "雪球期权") { return GetUnwindAbstractInfoItems_snowball(tc, td, false); } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var IsUsePremiumRate = td.IsUsePremiumRate == true; var QuoteUnitString = ""; if (underlying != null) { QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString); var SpotPrice = underlying.UnderlyingInstrumentType == "CommodityFutures" ? td.SpotPrice : td.InitialSpotPrice; } ///行权价格式 var strikeFmt = new Func(d => d.OtcFormatUmPrice(td.IsMoneynessOption == "是")); var premiumFmt = IsUsePremiumRate ? new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP)) : new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice)); var single = new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice)); var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock" ? " 股" : " " + td.QuoteUnitSingle); var istrade_barrier = td.TradeType == "障碍期权"; var actionName = "行权"; //如果是组合标的 if (underlying != null) { if (underlying.UnderlyingType == "组合标的") { if (!string.IsNullOrWhiteSpace(td.SyntheticUnderlyingTipsInfo)) { td.UnderlyingCode = td.SyntheticUnderlyingTipsInfo; } else { td.UnderlyingCode = synthetic_underlyingBLL.GetUnderlyingTipsInfo(td.UnderlyingCode); } } } var list = new List<(string, string)>(); if (PS.Config.Is厦门象屿) { list.Add(("行权信息", "")); } list.AddRange(new[] { ("交易编号", td.TradeNumber), ("开仓日期", td.TradeDate.OtcFormatDate()), ("开仓方向", td.ClientName), ("#", td.BuySell == "买入" ? "卖出" : "买入"), ("期权类型", td.StructureType!=null?td.StructureType: GetTradeType(td)), ("标的代码",td.UnderlyingCode), }); if (istrade_barrier) { list.Add(("观察频率", td.trade_barrier_option.ObservationDates ?? "每日观察")); list.Add(("报价单位", QuoteUnitString)); list.Add(("障碍水平", strikeFmt(td.trade_barrier_option.BarrierPrice))); } if (td.TradeType != "雪球期权" && td.TradeType != "凤凰期权") { list.Add(("执行价格", strikeFmt(td.Strike))); } list.Add(("到期日期", td.ExerciseDate.OtcFormatDate())); if (istrade_barrier) { tradeBLL.SetFieldsByTradeType(td); list.Add(("补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateRate) : premiumFmt(td.trade_barrier_option.Rebate))); list.Add(("高障碍补偿金额", IsUsePremiumRate ? premiumFmt(td.trade_barrier_option.RebateHighRate) : strikeFmt(td.trade_barrier_option.RebateHigh))); list.Add(("补偿支付", td.trade_barrier_option.RebateTypeCn)); } if (IsUsePremiumRate) { list.Add(("期权费率", premiumFmt(td.PremiumRate) + " (开仓) ")); } else { list.Add((" 权利金", premiumFmt(td.TradeSinglePrice ?? 0) + " (开仓) ")); } list.Add(($"{actionName}日期", tc.ValueDate.ToString("yyyy-MM-dd"))); if (td.UnderlyingInstrumentType == "CommodityFutures") { list.Add(("标的价格", td.SpotPrice.OtcFormatUmPrice() + " (开仓)")); list.Add((new string(' ', 5), (tc.FinalPrice ?? 0).OtcFormatUmPrice() + (PS.Config.Is厦门象屿 ? "(到期)" : "(行权)"))); } else { list.Add(("标的价格", td.InitialSpotPrice.OtcFormatUmPrice() + " (开仓)")); list.Add((new string(' ', 5), tc.FinalPrice.OtcFormatUmPrice() + $" ({actionName})")); } var UnwindPrice = 0.00; if (tc.UnwindPrice == null) { UnwindPrice = 0.00; } else { UnwindPrice = Math.Abs(tc.UnwindPrice.Value); } if (underlying != null) { list.AddRange(new[] { ($"{actionName}收益",single(UnwindPrice)+ " 元"), ($"{actionName}数量",(tc.IsLastAction? tc.Notional / underlying.CountRatio: (tc.UnwindTradeAmount!=null?tc.UnwindTradeAmount:0.0000)).OtcFormatNotional(underlying.CountRatio,PS.Config.IsUseDisplayNotional)+ " " +(PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString)), ($"{actionName}总额",(-tc.Amount).OtcFormatMoney()+ " 元"), }); } list.Add(("实现盈亏", (-TradeCalcHelper.CalcChildTradeSumWinLoss(td, tc)).OtcFormatMoney() + " 元")); return list; } private static string GetTradeType(trade td) { var result = ""; switch (td.StructureType ?? td.TradeType) { case "远期": case "掉期": result = (td.StructureType.TrimToNull() ?? td.TradeType) + (td.OptionType == "看涨" || td.OptionType == "多头" ? "多头" : "空头"); break; case "二元期权": result = td.ExerciseMode == "American" ? td.ExerciseModeCn + td.TradeType.Replace("期权", "") + "期权" : td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权"; break; case "雪球期权": result = "雪球 " + td.OptionType; break; case "双鲨期权": result = td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权"; break; case "亚式期权": case "香草期权": case "障碍期权": case "合成价差期权": case "累计期权": if (td.ParentTradeId == 0) { result = PS.Config.Is瑞达 && td.TradeType == "香草期权" ? td.ExerciseModeCn + td.OptionType + "期权" : td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权"; } else { var tradelists = DbContextFactory.GetYLDbContext().trade.Where(x => x.id == td.ParentTradeId).FirstOrDefault(); result = tradelists?.StructureType ?? tradelists?.TradeType ?? td.StructureType ?? td.TradeType; } break; case "现金流交易": result = td.TradeType; break; default: result = td.TradeType; switch (td.TradeType) { case "结构化交易": result = td.StructureType; break; case "凤凰期权": case ConsGlobal.TradeType.CashFlow: case ConsGlobal.TradeType.Forward: case ConsGlobal.TradeType.PayoffSwap: break; case "自定义交易": result = td.StructureIntroduction.TrimToNull() ?? td.StructureType.TrimToNull() ?? td.TradeType; break; case "气囊结构": case "区间累积期权": case "收益增强结构": result = td.ExerciseModeCn + td.TradeType; break; default: result = td.ExerciseModeCn + td.TradeType.Replace("期权", "") + td.OptionType + "期权"; break; } break; } return result; } /// /// 雪球期权生成交易摘要 /// public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems_snowball(trade_cash tc, trade td, bool isUnwind) { var snowball = td.trade_snowball; if (snowball == null) { throw new ServiceException("雪球期权扩展信息不存在,无法生成交易摘要"); } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString); var IsUsePremiumRate = td.IsUsePremiumRate == true; var SpotPrice = underlying.UnderlyingInstrumentType == "CommodityFutures" ? td.SpotPrice : td.InitialSpotPrice; var strikeFmt = td.IsMoneynessOption == "是" ? new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.percent)) : new Func(d => OtcFormatExtensions.OtcFormatFlex(d, 2, 4)); var premiumFmt = IsUsePremiumRate ? new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP)) : new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice)); var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock" ? " 股" : " " + td.QuoteUnitSingle); var list = new List<(string, string)>(); var action = tc.Action.Substring(5, 2); if (PS.Config.Is厦门象屿) { list.Add(($"{action}信息", "")); } list.AddRange(new[] { ("交易编号", td.TradeNumber), ("开仓日期", td.TradeDate.OtcFormatDate()), ("开仓方向", td.ClientName), ("#", td.BuySell == "买入" ? "卖出" : "买入"), ("期权类型", GetTradeType(td)), ("标的名称",td.UnderlyingAssetName), ("标的代码",td.UnderlyingCode), ("名义本金",OtcFormatExtensions.OtcFormat(td.StockEqvNotionalToShow, OtcFormatFlag.StockEqvNotional)) }); if (snowball.KORebate > 0) { list.Add(("  票息", snowball.KORebate.OtcFormatPercent())); } //var suffix = isUnwind ? " (平仓)" : "(行权)"; var action_2 = $"({action})"; list.Add(("期初价格", td.SpotPrice.OtcFormatUmPrice())); if (!snowball.IsInitialKnockedIn) { list.Add(("敲入价格", strikeFmt(snowball.KIBarrier))); } else { list.Add(("初始敲入", "是")); } list.Add(("敲出价格", strikeFmt(snowball.KOBarrier))); list.Add(("执行价格", strikeFmt(td.Strike))); list.Add(("到期日期", td.ExerciseDate.OtcFormatDate())); list.Add(("终止价格", tc.FinalPrice.OtcFormatUmPrice() + action_2)); list.Add(("终止日期", tc.ValueDate.OtcFormatDate())); var amount = tc.Amount * (valuedateBLL.SystemDate.UnwindAmountAngle == 1 ? -1 : EodOperationBase.GetSign(td.BuySell)); list.Add(("结算金额", (amount).OtcFormatMoney() + "元")); return list; } /// /// 远期平仓摘要 /// public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems_Forward(trade_cash tc, trade td) { var snowball = td.trade_forward; if (snowball == null) { throw new ServiceException("远期扩展信息不存在,无法生成交易摘要"); } var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode); var QuoteUnitString = " 元/" + (PS.Config.IsUseDisplayNotional ? underlying.QuoteUnitString : underlying.TradeUnitString); var IsUsePremiumRate = td.IsUsePremiumRate == true; var strikeFmt = new Func(d => d.OtcFormatUmPrice(td.IsMoneynessOption == "是")); var premiumFmt = IsUsePremiumRate ? new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.premiumRateP)) : new Func(d => OtcFormatExtensions.OtcFormat(d, OtcFormatFlag.tradeSinglePrice)); var tradeAmount = td.TradeAmount.OtcFormatNotional() + (td.UnderlyingInstrumentType == "Stock" ? " 股" : " " + td.QuoteUnitSingle); var winloss = TradeCalcHelper.CalcWinLoss(tradeType: td.TradeType, buySell: td.BuySell, tradePrice: td.TradePrice ?? 0, tcUnwindPercent: tc.UnwindPercentRate ?? (tc.UnwindNotional / td.OriginalNotional) ?? 0, tcAmount: tc.Amount); var list = new List<(string, string)>(); if (PS.Config.Is厦门象屿) { list.Add(("平仓信息", "")); } var actualExerciseDate = td.ExerciseDate; if (td.MetaDic == null || td.MetaDic.Count == 0) { var exerciseDate = new TradeMetaService(OptUserInfo.SystemUser).GetTradeMeta(td.id, "ActualExerciseDate"); if (!string.IsNullOrWhiteSpace(exerciseDate) && DateTime.TryParse(exerciseDate, out var tempDate)) { actualExerciseDate = tempDate; } } list.AddRange(new[] { ("交易编号", td.TradeNumber), ("开仓日期", td.TradeDate.OtcFormatDate()), ("开仓方向", td.ClientName), ("#", td.BuySell == "买入" ? "卖出" : "买入"), ("结构类型", (td.StructureType.TrimToNull()??td.TradeType) + (td.OptionType == "看涨" ? "多头" : "空头")), ("标的代码",td.UnderlyingCode), ("执行价格",td.Strike.OtcFormatUmPrice(td.IsMoneynessOption == "是")), ("到期日期", actualExerciseDate.OtcFormatDate()), ("平仓日期", tc.ValueDate.OtcFormatDate()), ("标的价格", td.SpotPrice.OtcFormatUmPrice()), (new string(' ', 5),tc.FinalPrice.OtcFormatUmPrice() + "(平仓)"), ("平仓数量",td.UnderlyingInstrumentType=="Stock"?tc.UnwindNotional.OtcFormatNotional()+"股": tc.UnwindTradeAmount.OtcFormatNotional(underlying.CountRatio,PS.Config.IsUseDisplayNotional)+ " " +(td.QuoteUnitSingle == "吨" && underlying.UnderlyingType == "鸡蛋" ? "半吨":td.QuoteUnitSingle)), ("平仓总额", (-tc.Amount).OtcFormatMoney() + "元"), //客户角度,故为相反金额 ("实现盈亏",(-winloss).OtcFormatMoney() + " 元") }); return list; } /// /// 现金流平仓摘要 /// public static IEnumerable<(string text, string value)> GetUnwindAbstractInfoItems_cashflow(trade_cash tc, trade td) { var cashflow = td.trade_cashflow; if (cashflow == null) { throw new ServiceException("现金流扩展信息不存在,无法生成交易摘要"); } var list = new List<(string, string)>(); if (PS.Config.Is厦门象屿) { list.Add(("平仓信息", "")); } //客户角度,故为相反金额 var amount = tc.Amount * (valuedateBLL.SystemDate.UnwindAmountAngle == 1 ? -1 : EodOperationBase.GetSign(td.BuySell)); list.AddRange(new[] { ("交易编号", td.TradeNumber), ("开仓日期", td.TradeDate.OtcFormatDate()), ("开仓方向", td.ClientName), ("#", td.BuySell == "买入" ? "卖出" : "买入"), ("平仓日期", tc.ValueDate.OtcFormatDate()), ("名义本金",(tc.UnwindPercentRate * td.OriginalStockEqvNotional).OtcFormatNotional() + "元"), ("平仓总额", (amount).OtcFormatMoney() + "元"), }); return list; } } }