using YLErp.BLL;
using YLErp.Commons;
using YLErp.DBModels.Helpers;
using YLErp.QdpModule;
using static iTextSharp.text.pdf.AcroFields;
namespace YLErp.Modules.TradeModule
{
///
/// 交易扩展通用服务
///
public class TradeExtendService : YLBaseService
{
public TradeExtendService(OptUserInfo optUser, YLContext dbContext) : base(optUser, dbContext)
{
}
public TradeExtendService(YLBaseService baseService) : base(baseService)
{
}
public TradeExtendService(OptUserInfo userInfo) : base(userInfo)
{
}
///
/// 设置奇异要素
///
public void SetTradeExtendWithCnKey(IEnumerable otcTrades, bool setMetaData = false, DateTime? dateTime = null)
{
if (otcTrades is null || !otcTrades.Any())
{
return;
}
Dictionary getTradeEx(IEnumerable tids) where T : TradeExtendBase
{
return DbContext.Set().AsNoTracking().Where(n => tids.Contains(n.TradeId)).ToDictionary(n => n.TradeId);
}
var extGroups = otcTrades.GroupBy(n => n.IsGroup == 1 && n.StructureType == "气囊结构" ? "气囊结构" : n.TradeType).ToArray();
foreach (var g in extGroups)
{
var tids = g.Select(n => n.id).ToHashSet();
switch (g.Key)
{
case "亚式期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
if (dic.TryGetValue(td.id, out var ext))
{
extDic["亚式_均价起算日"] = ext.AveragingPeriodStartDate.OtcFormatDate();
extDic["亚式_均价计算"] = TradeHelper.GetAsianPayoffTypeCn(ext.PayoffType);
if (ext.PayoffTypeCn.Contains("增强"))
{
extDic["亚式_结算类型"] = ext.SettleMode == "AtEnd" ? "递延" : "立即";
}
else
{
extDic["亚式_结算类型"] = "";
}
extDic["亚式_行权价类型"] = TradeHelper.GetAsianStrikeTypeCn(ext.StrikeType);
extDic["亚式_杠杆率"] = ext.StrikeGearingFactor.OtcFormatPercent();
if (td.TradeType == "亚式期权" && ext.PayoffType == "EnhancedArithmeticAverage" && ext.StrikeType != "Floating")
{
if (td.IsMoneynessOptionData)
{
extDic["增强价格"] = ext.EnhancedPrice.OtcFormatPercent();
}
else
{
extDic["增强价格"] = ext.EnhancedPrice.OtcFormatUmPrice();
}
}
else
{
extDic["增强价格"] = "";
}
}
}
}
break;
case "障碍期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["障碍_障碍类型"] = ext.BarrierType;
extDic["障碍_障碍价格"] = ext.BarrierPrice.OtcFormatUmPrice(isMoneyness);
extDic["障碍_高障碍价格"] = ext.UpperBarrierPrice.OtcFormatUmPrice(isMoneyness);
extDic["障碍_补偿支付"] = TradeHelper.GetRebateTypeCn(ext.RebateType);
extDic["障碍_补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateRate, ext.Rebate);
extDic["障碍_高障碍补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateHighRate, ext.RebateHigh);
extDic["障碍_障碍偏移"] = NumberHelper.Format(ext.BarrierShift, "F2");
extDic["障碍_观察方式"] = ext.Discrete;
extDic["障碍_敲入敲出状态"] = ext.KnockInOutStatusCn;
extDic["障碍_敲入敲出日期"] = ext.KnockInOutDate.OtcFormatDate();
extDic["障碍_补偿按敲出日年化"] = ext.RebateAnnualizedAtKO ? "是" : "否";
extDic["障碍_补偿计息规则"] = ext.RebateDayCount;
}
}
}
break;
case "双鲨期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["双鲨_低障碍价格"] = ext.BarrierLow.OtcFormatUmPrice(isMoneyness);
extDic["双鲨_高障碍价格"] = ext.BarrierHigh.OtcFormatUmPrice(isMoneyness);
extDic["双鲨_低行权价"] = td.Strike.OtcFormatUmPrice(isMoneyness);
extDic["双鲨_高行权价"] = ext.StrikeHigh.OtcFormatUmPrice(isMoneyness);
extDic["双鲨_补偿支付"] = TradeHelper.GetRebateTypeCn(ext.RebateType);
extDic["双鲨_补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateRate, ext.Rebate);
extDic["双鲨_高障碍补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateHighRate, ext.RebateHigh);
extDic["双鲨_观察方式"] = ext.Discrete;
extDic["双鲨_高参与率"] = ext.CallParticipationRate.OtcFormatPercent();
extDic["双鲨_低参与率"] = ext.PutParticipationRate.OtcFormatPercent();
extDic["双鲨_敲入敲出日期"] = ext.KnockInOutDate.OtcFormatDate();
extDic["双鲨_敲入敲出状态"] = ext.KnockInOutStatusCn;
}
}
}
break;
case "二元期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["二元_二元类型"] = ext.PayoffType;
extDic["二元_高障碍价格"] = ext.UpperBarrier.OtcFormatUmPrice(isMoneyness);
extDic["二元_补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.CashOrNothingAmountRate, ext.CashOrNothingAmount);
extDic["二元_高障碍补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.CashOrNothingAmountHighRate, ext.CashOrNothingAmountHigh);
extDic["二元_观察方式"] = ext.MonitorType;
extDic["二元_补偿支付"] = TradeHelper.GetRebateTypeCn(ext.RebateType);
extDic["二元_一级收益率"] = (td.IsUsePremiumRate == true ? (td.PremiumRate > 0 ? (ext.CashOrNothingAmountRate ?? 0) / td.PremiumRate.Value : 0) : (td.TradeSinglePrice > 0 ? (ext.CashOrNothingAmount ?? 0) / td.TradeSinglePrice.Value : 0)).OtcFormat(OtcFormatFlag.percent);
extDic["二元_保底收益率"] = (td.PrincipalRate ?? 0).OtcFormat(OtcFormatFlag.percent);
extDic["二元_补偿按敲出日年化"] = ext.RebateAnnualizedAtKO ? "是" : "否";
extDic["二元_补偿计息规则"] = ext.RebateDayCount;
}
}
}
break;
case "区间累积期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["区间累积_区间下限"] = ext.LowerRange.OtcFormatUmPrice(isMoneyness);
extDic["区间累积_区间上限"] = ext.UpperRange.OtcFormatUmPrice(isMoneyness);
extDic["区间累积_观察日期"] = string.IsNullOrEmpty(ext.ObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : ext.ObservationDates;
extDic["区间累积_区间收益"] = ext.BonusRate.OtcFormatPercent(4);
}
}
}
break;
case "气囊结构":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["气囊_障碍价格"] = ext.Barrier.OtcFormatUmPrice(isMoneyness);
extDic["气囊_是否离散观察"] = ext.IsDiscreteMonitored ? "是" : "否";
extDic["气囊_未敲入参与率"] = ext.NotKIParticipationRate.OtcFormatPercent();
extDic["气囊_敲入参与率"] = ext.KIParticipationRate.OtcFormatPercent();
extDic["气囊_收益封顶"] = ext.HasPayoffLimit ? "是" : "否";
extDic["气囊_收益封顶价格"] = ext.HasPayoffLimit ? ext.HighStrike.OtcFormatUmPrice(isMoneyness) : "";
extDic["气囊_敲入敲出状态"] = ext.KnockInOutStatusCn;
extDic["气囊_敲入敲出日期"] = ext.KnockInOutDate.OtcFormatDate();
}
}
}
break;
case "收益增强结构":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
if (dic.TryGetValue(td.id, out var ext))
{
td.MetaDic["收益增强_年化增强收益"] = ext.AnnualizedEnhanceRate.OtcFormatPercent(4);
}
}
}
break;
case "凤凰期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["凤凰_票息年化"] = ext.IsFixedCoupon ? "否" : "是";
extDic["凤凰_票息率"] = GetCoupon(ext.IsFixedCoupon, ext.CouponDayCount, ext.Coupon).OtcFormat(OtcFormatFlag.premiumRateP);
extDic["凤凰_票息日历规则"] = ext.CouponDayCount;
extDic["凤凰_票息包含首日"] = ext.CouponIncludeStartDate == true ? "是" : "否";
extDic["凤凰_使用支付日计息"] = ext.CouponUsePaymentDate == true ? "是" : "否";
extDic["凤凰_票息障碍价格"] = ext.CouponBarrier.OtcFormatUmPrice(isMoneyness);
extDic["凤凰_票息结算方式"] = ext.CouponPayTypeDesc();
extDic["凤凰_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
extDic["凤凰_敲入障碍价格"] = ext.KIBarrier.OtcFormatUmPrice(isMoneyness);
extDic["凤凰_敲入到期是否支付票息"] = ext.IncludeCouponAfterKI ? "是" : "否";
extDic["凤凰_敲入到期支付类别"] = ext.KIPayoffTypeDesc();
extDic["凤凰_敲入行权价1"] = ext.SpreadStrike1.OtcFormatUmPrice(isMoneyness);
extDic["凤凰_敲入行权价2"] = ext.SpreadStrike.OtcFormatUmPrice(isMoneyness);
var KOObservationDates = ext.KOObservationDates ?? string.Empty;
var CouponObservation = string.Empty;
if (!string.IsNullOrWhiteSpace(KOObservationDates) && KOObservationDates.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Any())
{
var koInfo = TradeObservationHelper.GetAutocallKOObservationAndCoupon(ext.KOObservationDates, ext.CouponBarrier);
var koObInfo = koInfo.Item2;
var customizedResults = koObInfo.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (customizedResults != null && customizedResults.Any())
{
var koObservationDates = customizedResults[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var customizedKOBarriers = customizedResults[1].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
//|| customizedCoupons != null && customizedCoupons.Distinct().Count() >= 2
if (customizedKOBarriers != null && customizedKOBarriers.Distinct().Count() >= 2)
{
KOObservationDates = string.Empty;
var index = 0;
foreach (var date in koObservationDates)
{
KOObservationDates += date.ToString() + "," + Convert.ToDouble(customizedKOBarriers[index]).OtcFormatUmPrice(isMoneyness) + ";";
index++;
}
}
else if (koObservationDates != null)
{
KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString()));
}
}
else
{
KOObservationDates = "";
}
var coInfo = koInfo.Item1;
if (coInfo != null)
{
var coResults = coInfo.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
var coObservationDates = coResults[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var coBarriers = coResults[1].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
var coCoupons = coResults[2].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
if (coCoupons != null && coCoupons.Distinct().Count() >= 2)
{
var index = 0;
foreach (var date in coObservationDates)
{
CouponObservation += date.ToString() + "," + Convert.ToDouble(coBarriers[index]).OtcFormatUmPrice(isMoneyness) + "," + Convert.ToDouble(coCoupons[index]).OtcFormatUmPrice(isMoneyness) + ";";
index++;
}
}
else if (coObservationDates != null)
{
CouponObservation = string.Join(";", coObservationDates.Select(O => O.ToString()));
}
}
}
extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : KOObservationDates;
extDic["票息观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : CouponObservation;
extDic["敲入观察频率"] = string.IsNullOrEmpty(ext.ObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : ext.ObservationDates;
extDic["期权年化"] = ext.IsAnnualized2 ? "是" : "否";
extDic["凤凰_敲入敲出状态"] = ext.KnockInOutStatusCn;
}
}
}
break;
case "收益互换":
//{
// var dic = getTradeEx(tids);
// foreach (var td in g)
// {
// var extDic = td.MetaDic;
// var isMoneyness = td.IsMoneynessOption == "是";
// if (dic.TryGetValue(td.id, out var ext))
// {
// var PaySwapTimeAndRate = ext.PaySwapTimeAndRate == null ? "" : ext.PaySwapTimeAndRate.Split(';')[1];
// var GetSwapTimeAndRate = ext.GetSwapTimeAndRate == null ? "" : ext.GetSwapTimeAndRate.Split(';')[1];
// var GetSwapTime = ext.GetSwapTimeAndRate == null ? "" : ext.GetSwapTimeAndRate.Substring(0, ext.GetSwapTimeAndRate.IndexOf(";"));
// var PaySwapTime = ext.PaySwapTimeAndRate == null ? "" : ext.PaySwapTimeAndRate.Substring(0, ext.PaySwapTimeAndRate.IndexOf(";"));
// var GetUnderlyingAssetName = DataCacheProvider.GetUnderlyingDataSource().GetData(ext.GetUnderlyingCode)?.UnderlyingName;
// var PayUnderlyingAssetName = DataCacheProvider.GetUnderlyingDataSource().GetData(ext.PayUnderlyingCode)?.UnderlyingName;
// var PaySingleFeeToString = "";
// var GetSingleFeeToString = "";
// #region 单位交易费用导出逻辑
// if (ext.IsGetFloatingProfit == false && ext.GetUnAnnualRate < 1 && ext.GetUnAnnualRate > 0)
// {
// GetSingleFeeToString = ext.GetUnAnnualRate.OtcFormatPercent(4);
// }
// else
// {
// GetSingleFeeToString = ext.GetSingleFee.OtcFormatUmPrice();
// }
// if (ext.IsPayFloatingProfit == false && ext.PayUnAnnualRate < 1 && ext.PayUnAnnualRate > 0)
// {
// PaySingleFeeToString = ext.PayUnAnnualRate.OtcFormatPercent(4);
// }
// else
// {
// PaySingleFeeToString = ext.PaySingleFee.OtcFormatUmPrice();
// }
// #endregion
// extDic["互换_支付方互换利率"] = PaySwapTimeAndRate;
// extDic["互换_支付方标的代码"] = ext.PayUnderlyingCode;
// extDic["互换_支付方标的名称"] = PayUnderlyingAssetName;
// extDic["互换_支付方期初标的价格"] = ext.PaySpotPrice.OtcFormatUmPrice();
// extDic["互换_支付方交易数量"] = ext.PayTradeAmount.OtcFormatNotional();
// extDic["互换_支付方到期标的价格"] = ext.PayFinalPrice.OtcFormatUmPrice();
// extDic["互换_支付方固定收益"] = ext.PayFixedProfit.OtcFormat(OtcFormatFlag.tradePrice);
// extDic["互换_支付方单位交易费用"] = PaySingleFeeToString;
// extDic["互换_支付方初始预付金"] = ext.PayMarginRate.OtcFormatPercent();
// extDic["互换_支付方交易费用"] = ext.PayTradePrice.OtcFormat(OtcFormatFlag.tradePrice);
// extDic["互换_支付方多空方向"] = ext.PayLongShort;
// extDic["互换_收取方单位交易费用"] = GetSingleFeeToString;
// extDic["互换_收取方互换利率"] = GetSwapTimeAndRate;
// extDic["互换_收取方固定收益"] = ext.GetFixedProfit.OtcFormat(OtcFormatFlag.tradePrice);
// extDic["互换_收取方初始预付金"] = ext.GetMarginRate.OtcFormatPercent();
// extDic["互换_收取方交易费用"] = ext.GetTradePrice.OtcFormat(OtcFormatFlag.tradePrice);
// extDic["互换_收取方标的代码"] = ext.GetUnderlyingCode;
// extDic["互换_收取方标的名称"] = GetUnderlyingAssetName;
// extDic["互换_收取方多空方向"] = ext.GetLongShort;
// extDic["互换_收取方期初标的价格"] = ext.GetSpotPrice.OtcFormatUmPrice();
// extDic["互换_收取方交易数量"] = ext.GetTradeAmount.OtcFormatNotional();
// extDic["互换_收取方到期标的价格"] = ext.GetFinalPrice.OtcFormatUmPrice();
// extDic["互换_互换日期"] = GetSwapTime ?? PaySwapTime;
// extDic["年化天数"] = ext.AnnualDays.ToString();
// }
// }
//}
break;
case "掉期":
case "远期":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
if (dic.TryGetValue(td.id, out var ext))
{
extDic["手数"] = td.Lots.OtcFormatMoney();
extDic["挂钩标的"] = td.BasisUnderlyingCode;
extDic["基差"] = td.BasisGap.OtcFormatNotional();
extDic["远期价值"] = ext.ForwardValue.OtcFormatMoney();
extDic["开仓费用"] = (ext.OpenCommission * -1).OtcFormatMoney();
extDic["开仓总费用"] = (td.TradePrice * -1).OtcFormatMoney();
extDic["年化预付金成本"] = ext.AnnualMarginRate.OtcFormatPercent();
extDic["年化仓储成本"] = ext.AnnualStoragePrice.OtcFormatMoney();
extDic["均价计算日期"] = ext.ObservationDates;
}
}
}
break;
case "雪球期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
var KOObservationDates = ext.KOObservationDates ?? string.Empty;
if (!string.IsNullOrWhiteSpace(KOObservationDates))
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ext.KOObservationDates);
var koObservationDates = customizedResults.Item1;
var customizedKOBarriers = customizedResults.Item2;
var customizedCoupons = customizedResults.Item3;
if (customizedKOBarriers != null && customizedKOBarriers.Distinct().Count() >= 2 || customizedCoupons != null && customizedCoupons.Distinct().Count() >= 2)
{
KOObservationDates = string.Empty;
var index = 0;
foreach (var date in koObservationDates)
{
KOObservationDates += date.ToString() + "," + customizedKOBarriers[index].OtcFormatUmPrice(isMoneyness) + "," + customizedCoupons[index].OtcFormat(OtcFormatFlag.premiumRateP) + ";";
index++;
}
}
else
{
KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString()));
}
}
extDic["雪球_红利票息"] = ext.Coupon./*OtcFormatPercent()*/OtcFormatFlex(2, percent: true);
extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : KOObservationDates;
extDic["敲入观察频率"] = ext.IsInitialKnockedIn ? "" : (string.IsNullOrEmpty(ext.ObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : ext.ObservationDates);
extDic["期权年化"] = ext.IsAnnualized2 ? "是" : "否";
extDic["雪球_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
extDic["雪球_敲入敲出状态"] = ext.KnockInOutStatusCn;
switch (ext.KOPayoffType)
{
case KOPayoffTypeEnum.Rebate:
extDic["雪球_敲出赔付类别"] = "票息补偿";
extDic["雪球_票息年化"] = ext.IsFixedCoupon ? "否" : "是";
extDic["雪球_票息率"] = ext.KORebate.OtcFormat(OtcFormatFlag.premiumRateP);
extDic["雪球_票息日历规则"] = ext.CouponDayCount;
extDic["雪球_票息包含首日"] = ext.CouponIncludeStartDate == true ? "是" : "否";
extDic["雪球_使用支付日计息"] = ext.CouponUsePaymentDate == true ? "是" : "否";
extDic["雪球_年化期权费率"] = ext.AnnualizedPremiumRate.OtcFormat(OtcFormatFlag.premiumRateP);
if (!string.IsNullOrWhiteSpace(ext.KOObservationSettleDates))
{
extDic["雪球_票息支付日期"] = ext.KOObservationSettleDates;
}
else
{
extDic["雪球_票息支付日期"] = extDic["敲出观察频率"];
}
break;
case KOPayoffTypeEnum.ToOption:
extDic["雪球_敲出赔付类别"] = KOPayoffTypeEnumHelper.GetDesc(KOPayoffTypeEnum.ToOption, td.CallPut);
extDic["雪球_敲出行权价1"] = ext.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness);
break;
case KOPayoffTypeEnum.ToSpreadOption:
extDic["雪球_敲出赔付类别"] = KOPayoffTypeEnumHelper.GetDesc(KOPayoffTypeEnum.ToSpreadOption, td.CallPut);
extDic["雪球_敲出行权价2"] = ext.SpreadStrikeAtKO.OtcFormatUmPrice(isMoneyness);
extDic["雪球_敲出行权价1"] = ext.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness);
break;
default:
extDic["雪球_敲出赔付类别"] = ext.KOPayoffType.ToString();
break;
}
extDic["雪球_敲出支付方式"] = RebateTypeEnumHelper.GetDesc(ext.KORebateType);
extDic["雪球_初始敲入"] = ext.IsInitialKnockedIn ? "是" : "否";
extDic["雪球_敲入障碍价格"] = ext.IsInitialKnockedIn ? "" : ext.KIBarrier.OtcFormatUmPrice(isMoneyness);
switch (ext.KIPayoffType)
{
case KIPayoffTypeEnum.None:
extDic["雪球_敲入到期支付类别"] = "无";
break;
case KIPayoffTypeEnum.ToPutOption:
extDic["雪球_敲入到期支付类别"] = "敲入转看跌";
extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToPutSpreadOption:
extDic["雪球_敲入到期支付类别"] = "敲入转熊市价差";
extDic["雪球_封顶/封底"] = extDic["雪球_敲入行权价2"] = ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness);
extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToCallOption:
extDic["雪球_敲入到期支付类别"] = "敲入转看涨";
extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
case KIPayoffTypeEnum.ToCallSpreadOption:
extDic["雪球_敲入到期支付类别"] = "敲入转牛市价差";
extDic["雪球_封顶/封底"] = extDic["雪球_敲入行权价2"] = ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness);
extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness);
break;
default:
extDic["雪球_敲入到期支付类别"] = ext.KIPayoffType.ToString();
break;
}
if (PS.Config.IsGuoJun)
{
var instrumentTypeArr = ConsGlobal.InstrumentType.EquityTypes();
if (!instrumentTypeArr.Contains(DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode).UnderlyingInstrumentType))
{
if (td.OptionType == "看涨")
{
extDic["雪球_敲入行权价1"] = (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || ext.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption ? ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness) : "");
extDic["雪球_敲入行权价2"] = (ext.KIPayoffType != KIPayoffTypeEnum.None ? ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness) : "");
}
else
{
extDic["雪球_敲入行权价1"] = (ext.KIPayoffType != KIPayoffTypeEnum.None ? ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness) : "");
extDic["雪球_敲入行权价2"] = (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || ext.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption ? ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness) : "");
}
}
else
{
extDic["雪球_敲入行权价1"] = (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || ext.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption ? ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness) : "");
extDic["雪球_敲入行权价2"] = (ext.KIPayoffType != KIPayoffTypeEnum.None ? ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness) : "");
}
}
}
}
}
break;
case "现金流交易":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
if (dic.TryGetValue(td.id, out var ext))
{
extDic["利率"] = ext.ProfitRate.OtcFormatPercent();
extDic["利率类型"] = ext.RateType.ToString();
extDic["计息日历规则"] = ext.ProfitDayCount;
extDic["预付返还比例"] = ext.PrepayRatio.OtcFormatPercent();
}
}
}
break;
case "累计期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["累计期权_结构类型"] = ext.AccumulatorStructureType.ToString();
if (ext.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented)
{
//获取 trade ,valuedate
extDic["累计三段式_行权价2"] = ext.Strike2.OtcFormatUmPrice(isMoneyness);
extDic["累计三段式_行权价3"] = ext.Strike3.OtcFormatUmPrice(isMoneyness);
extDic["累计三段式_乘数1"] = ext.Multiplier.OtcFormatUmPrice();
extDic["累计三段式_乘数2"] = ext.Multiplier2.OtcFormatUmPrice();
extDic["累计三段式_乘数3"] = ext.Multiplier3.OtcFormatUmPrice();
if (dateTime != null)
{
var td_db = DbContext.trade.FirstOrDefault(l => l.id == td.id);
bool Isexist = new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(td_db, Convert.ToDateTime(dateTime));
if (Isexist)
extDic["累计三段式_敲出障碍价格"] = td_db.trade_accumulator_option.KOBarrier.OtcFormatUmPrice(isMoneyness);
else
extDic["累计三段式_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
}
else
{
extDic["累计三段式_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
}
extDic["累计三段式_上端收益类型"] = ext.PayoffType;
extDic["累计三段式_累计类型"] = ext.AccumuType;
if (ext.PayoffType == "固定")
{
extDic["累计三段式_票息1"] = ext.Coupon.OtcFormat(ext.CouponPercent ? OtcFormatFlag.premiumRateP : OtcFormatFlag.umprice);
extDic["累计三段式_票息2"] = ext.Coupon2.OtcFormat(ext.CouponPercent ? OtcFormatFlag.premiumRateP : OtcFormatFlag.umprice);
extDic["累计三段式_票息日历规则"] = ext.CouponDayCount;
extDic["累计三段式_票息年化"] = ext.IsFixedCoupon ? "否" : "是";
}
extDic["累计三段式_敲出是否终止"] = ext.EarlyTerminate ? "是" : "否";
if (string.IsNullOrEmpty(ext.KOObservationDates))
{
extDic["累计三段式_观察日期"] = "起始日至到期日(含)间每一交易日";
}
else
{
extDic["累计三段式_观察日期"] = ext.KOObservationDates;
}
extDic["累计三段式_结算方式1"] = ext.SettlementMode == "现金结算" ? "现金结算(当日)" : ext.SettlementMode;
//判断结算方式是否为实物交割
if (ext.SettlementMode != "实物交割"&& ext.SettlementMode!= "现金实物合并结算")
{
extDic["累计三段式_远期期初价类型1"] = null;
extDic["累计三段式_远期到期日类型1"] = null;
}
else
{
extDic["累计三段式_远期期初价类型1"] = ext.ForwardPriceType;
extDic["累计三段式_远期到期日类型1"] = ext.ForwardDateType;
}
extDic["累计三段式_结算方式2"] = ext.SettlementMode2 == "现金结算" ? "现金结算(当日)" : ext.SettlementMode2;
//判断结算方式是否为实物交割
if (ext.SettlementMode2 != "实物交割"&& ext.SettlementMode2 != "现金实物合并结算")
{
extDic["累计三段式_远期期初价类型2"] = null;
extDic["累计三段式_远期到期日类型2"] = null;
}
else
{
extDic["累计三段式_远期期初价类型2"] = ext.ForwardPriceType2;
extDic["累计三段式_远期到期日类型2"] = ext.ForwardDateType2;
}
extDic["累计三段式_结算方式3"] = ext.SettlementMode3 == "现金结算" ? "现金结算(当日)" : ext.SettlementMode3;
//判断结算方式是否为实物交割
if (ext.SettlementMode3 != "实物交割" && ext.SettlementMode3 != "现金实物合并结算")
{
extDic["累计三段式_远期期初价类型3"] = null;
extDic["累计三段式_远期到期日类型3"] = null;
}
else
{
extDic["累计三段式_远期期初价类型3"] = ext.ForwardPriceType3;
extDic["累计三段式_远期到期日类型3"] = ext.ForwardDateType3;
}
extDic["累计三段式_沽购数量"] = ext.OriginalAccumuTradeAmount.OtcFormatUmPrice();
var KOObservationDates = ext.KOObservationDates ?? string.Empty;
if (!string.IsNullOrWhiteSpace(KOObservationDates))
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ext.KOObservationDates);
var koObservationDates = customizedResults.Item1;
KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString()));
}
extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日至到期日(含)间每一交易日" : KOObservationDates;
}
else
{
//获取 trade ,valuedate
if (dateTime != null)
{
var td_db = DbContext.trade.FirstOrDefault(l => l.id == td.id);
bool Isexist = new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(td_db, Convert.ToDateTime(dateTime));
if (Isexist)
extDic["累计_敲出障碍价格"] = td_db.trade_accumulator_option.KOBarrier.OtcFormatUmPrice(isMoneyness);
else
extDic["累计_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
}
else
{
extDic["累计_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness);
}
extDic["累计_上端收益类型"] = ext.PayoffType;
extDic["累计_累计类型"] = ext.AccumuType;
if (ext.PayoffType == "固定")
{
extDic["累计_票息"] = ext.Coupon.OtcFormat(ext.CouponPercent ? OtcFormatFlag.premiumRateP : OtcFormatFlag.umprice);
extDic["累计_票息日历规则"] = ext.CouponDayCount;
extDic["累计_票息年化"] = ext.IsFixedCoupon ? "否" : "是";
}
extDic["累计_看涨乘数"] = ext.CallMultiplier.OtcFormatUmPrice();
extDic["累计_看跌乘数"] = ext.PutMultiplier.OtcFormatUmPrice();
extDic["累计_杠杆倍数"] = ConsGlobal.CallPut.IsCall(td.CallPut) ? extDic["累计_看跌乘数"] : extDic["累计_看涨乘数"];
extDic["累计_敲出是否终止"] = ext.EarlyTerminate ? "是" : "否";
extDic["累计_结算方式"] = ext.GetSettlementModeDesc();
if (string.IsNullOrEmpty(ext.KOObservationDates))
{
extDic["累计_观察日期"] = "起始日至到期日(含)间每一交易日";
}
else
{
extDic["累计_观察日期"] = ext.KOObservationDates;
}
//判断结算方式是否为实物交割
if (ext.GetSettlementModeDesc() != "实物交割"&& ext.GetSettlementModeDesc() != "现金实物合并结算")
{
extDic["累计_远期期初价类型"] = null;
extDic["累计_远期到期日类型"] = null;
}
else
{
extDic["累计_远期期初价类型"] = ext.ForwardPriceType;
extDic["累计_远期到期日类型"] = ext.ForwardDateType;
}
extDic["累计_沽购数量"] = ext.OriginalAccumuTradeAmount.OtcFormatUmPrice();
var KOObservationDates = ext.KOObservationDates ?? string.Empty;
if (!string.IsNullOrWhiteSpace(KOObservationDates))
{
var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ext.KOObservationDates);
var koObservationDates = customizedResults.Item1;
KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString()));
}
extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日至到期日(含)间每一交易日" : KOObservationDates;
}
}
}
}
break;
case "自定义交易":
{
var otherTrades = otcTrades.Where(x => x.ExtendInfo != null).ToList();
otherTrades.ForEach(x =>
{
if (x.Propertys != null)
{
foreach (var item in x.Propertys)
{
var extDic = x.MetaDic;
extDic["自定义_" + item.name] = item.value;
}
}
});
}
break;
case "Risky期权":
{
var dic = getTradeEx(tids);
foreach (var td in g)
{
var extDic = td.MetaDic;
var isMoneyness = td.IsMoneynessOption == "是";
if (dic.TryGetValue(td.id, out var ext))
{
extDic["Risky_执行价格1"] = ext.Strike1.OtcFormatUmPrice(isMoneyness);
extDic["Risky_执行价格2"] = ext.Strike2.OtcFormatUmPrice(isMoneyness);
extDic["Risky_执行价格3"] = ext.Strike3.OtcFormatUmPrice(isMoneyness);
extDic["Risky_参与率1"] = ext.ParticipationRate1.OtcFormat(OtcFormatFlag.premiumRateP);
extDic["Risky_参与率2"] = ext.ParticipationRate2.OtcFormat(OtcFormatFlag.premiumRateP);
extDic["Risky_参与率3"] = ext.ParticipationRate3.OtcFormat(OtcFormatFlag.premiumRateP);
}
};
}
break;
}
}
if (setMetaData)
{
SetTradeMeta(otcTrades);
}
}
///
/// 转化票息率
///
/// 是否年化 false 是 true 否
/// 票息日历规则
/// 票息率
///
private double GetCoupon(bool isFixedCoupon, string couponDayCount, double coupon)
{
//if (PS.Config.Company == Configuration.CompanyEnum.国泰君安)
//{
// if (isFixedCoupon)
// {
// switch (couponDayCount)
// {
// case "Monthly":
// return coupon * 12;
// default:
// return coupon;
// }
// }
//}
return coupon;
}
///
/// 设置奇异要素
///
public void SetTradeExtend(IEnumerable otcTrades, bool setMetaData = false)
{
if (otcTrades is null || !otcTrades.Any())
{
return;
}
void setTradeEx(IEnumerable tds) where T : TradeExtendBase
{
var tids = tds.Select(n => n.id).ToHashSet();
var dic = DbContext.Set().Where(n => tids.Contains(n.TradeId)).ToDictionary(n => n.TradeId);
foreach (var td in tds)
{
if (dic.TryGetValue(td.id, out var ext))
{
YLAutoMapper.Map(ext, td);
}
}
}
var extGroups = otcTrades.GroupBy(n => n.IsGroup == 1 && n.StructureType == "气囊结构" ? "气囊结构" : n.TradeType).ToArray();
foreach (var g in extGroups)
{
switch (g.Key)
{
case "亚式期权":
setTradeEx(g); break;
case "障碍期权":
setTradeEx(g); break;
case "双鲨期权":
setTradeEx(g); break;
case "二元期权":
setTradeEx(g); break;
case "区间累积期权":
setTradeEx(g); break;
case "气囊结构":
setTradeEx(g); break;
case "收益增强结构":
setTradeEx(g); break;
case "凤凰期权":
setTradeEx(g); break;
case "雪球期权":
setTradeEx(g); break;
case "累计期权":
setTradeEx(g); break;
case "现金流交易":
setTradeEx(g); break;
case "自定义交易":
setTradeEx(g); break;
case "Risky期权":
setTradeEx(g); break;
}
}
if (setMetaData)
{
SetTradeMeta(otcTrades);
}
}
public void SetTradeExtend(OtcOptionTradeFull otcTrade, trade input)
{
if (otcTrade == null || input == null)
{
return;
}
switch (otcTrade.TradeType)
{
case "亚式期权":
setTradeEx(input.trade_asian_option); break;
case "障碍期权":
setTradeEx(input.trade_barrier_option); break;
case "双鲨期权":
setTradeEx(input.trade_double_sharkfin_option); break;
case "二元期权":
setTradeEx(input.trade_binary_option); break;
case "区间累积期权":
setTradeEx(input.trade_rangeaccrual); break;
case "气囊结构":
setTradeEx(input.trade_airbag); break;
case "收益增强结构":
setTradeEx(input.trade_underlying_enhance); break;
case "凤凰期权":
setTradeEx(input.trade_autocall); break;
case "雪球期权":
setTradeEx(input.trade_snowball); break;
case "累计期权":
setTradeEx(input.trade_accumulator_option);
otcTrade.StrikeGearingFactor = ConsGlobal.CallPut.IsCall(input.OptionType) ? otcTrade.PutMultiplier : otcTrade.CallMultiplier;
break;
case "现金流交易":
setTradeEx(input.trade_cashflow); break;
case "自定义交易":
setTradeEx(input.trade_custom); break;
}
void setTradeEx(T extend) where T : TradeExtendBase
{
YLAutoMapper.Map(extend, otcTrade);
}
}
///
/// 设置奇异要素
///
public void SetTradeExtend(IEnumerable tradeList, bool setMetaData = false, bool tracking = false)
{
if (tradeList is null || !tradeList.Any())
{
return;
}
void InnerSetExt(IEnumerable tds, Func getter, Action setter) where T : TradeExtendBase
{
var tids = tds.Where(n =>
{
var obj = getter(n);
return obj == null || obj.TradeId != n.id;
}).Select(n => n.id).ToHashSet();
var dic = (tracking ? DbContext.Set() : DbContext.Set().AsNoTracking()).Where(n => tids.Contains(n.TradeId)).ToDictionary(n => n.TradeId);
foreach (var td in tds)
{
if (dic.TryGetValue(td.id, out var ext))
{
setter(td, ext);
}
}
}
void InnerSetExt2(IEnumerable tds, Func> getter, Action> setter) where T : TradeExtendBase
{
var tids = tds.Where(n =>
{
var obj = getter(n);
return obj == null || obj.Count == 0 || obj.FirstOrDefault()?.TradeId != n.id;
}).Select(n => n.id).ToHashSet();
var dic = (tracking ? DbContext.Set() : DbContext.Set().AsNoTracking()).Where(n => tids.Contains(n.TradeId))
.AsEnumerable().GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.ToList());
foreach (var td in tds)
{
if (dic.TryGetValue(td.id, out var ext))
{
setter(td, ext);
}
}
}
var extGroups = tradeList.Where(n => n.id > 0).GroupBy(n => n.IsGroup == 1 && n.StructureType == "气囊结构" ? "气囊结构" : n.TradeType).ToArray();
foreach (var g in extGroups)
{
var tids = g.Select(n => n.id).ToHashSet();
switch (g.Key)
{
case "亚式期权":
InnerSetExt(g, t => t.trade_asian_option, (t, ext) => t.trade_asian_option = ext);
break;
case "障碍期权":
InnerSetExt(g, t => t.trade_barrier_option, (t, ext) => t.trade_barrier_option = ext);
break;
case "Risky期权":
InnerSetExt(g, t => t.trade_risky_option, (t, ext) => t.trade_risky_option = ext);
break;
case "双鲨期权":
InnerSetExt(g, t => t.trade_double_sharkfin_option, (t, ext) => t.trade_double_sharkfin_option = ext);
break;
case "二元期权":
InnerSetExt(g, t => t.trade_binary_option, (t, ext) => t.trade_binary_option = ext);
break;
case "区间累积期权":
InnerSetExt(g, t => t.trade_rangeaccrual, (t, ext) => t.trade_rangeaccrual = ext);
break;
case "气囊结构":
InnerSetExt(g, t => t.trade_airbag, (t, ext) => t.trade_airbag = ext);
break;
case "收益增强结构":
InnerSetExt(g, t => t.trade_underlying_enhance, (t, ext) => t.trade_underlying_enhance = ext);
break;
case "凤凰期权":
InnerSetExt(g, t => t.trade_autocall, (t, ext) => t.trade_autocall = ext);
break;
case "雪球期权":
InnerSetExt(g, t => t.trade_snowball, (t, ext) => t.trade_snowball = ext);
break;
case "彩虹期权":
InnerSetExt(g, t => t.trade_rainbow_option, (t, ext) => t.trade_rainbow_option = ext);
break;
case "价差期权":
InnerSetExt(g, t => t.trade_spread_option, (t, ext) => t.trade_spread_option = ext);
break;
case "收益互换":
//InnerSetExt(g, t => t.trade_swap, (t, ext) => t.trade_swap = ext);
//InnerSetExt2(g, t => t.get_trade_swap_details, (t, ext) => t.get_trade_swap_details = ext.Where(O => O.IsForGet && O.ValidState != "InValid").ToList());
//InnerSetExt2(g, t => t.pay_trade_swap_details, (t, ext) => t.pay_trade_swap_details = ext.Where(O => !O.IsForGet && O.ValidState != "InValid").ToList());
break;
case "合成价差期权":
//香草期权和合成价差期权都没有奇异要素扩展字段
break;
case "远期":
InnerSetExt(g, t => t.trade_forward, (t, ext) => t.trade_forward = ext);
break;
case "现金流交易":
InnerSetExt(g, t => t.trade_cashflow, (t, ext) => t.trade_cashflow = ext);
break;
case "自定义交易":
InnerSetExt(g, t => t.trade_custom, (t, ext) => t.trade_custom = ext);
break;
case "累计期权":
InnerSetExt(g, t => t.trade_accumulator_option, (t, ext) => t.trade_accumulator_option = ext);
break;
}
}
if (setMetaData)
{
SetTradeMeta(tradeList);
}
}
///
/// 设置元数据
///
public void SetTradeMeta(IEnumerable otcTrades)
{
if (otcTrades is null || !otcTrades.Any())
{
return;
}
var set = new HashSet();//应该没有重复的数据但也防止下意外情况的发生
var tradDic = otcTrades.Where(n => set.Add(n.id)).ToDictionary(n => n.id);
//为前端下载所有数据优化
for (var i = 0; i < set.Count; i += 1000)
{
var ids = set.Skip(i).Take(1000).ToArray();
var metaDatas = DbContext.TradeMeta.Where(n => ids.Contains(n.TradeId))
.Select(n => new { n.TradeId, n.MetaKey, n.MetaValue }).ToArray();
foreach (var meta in metaDatas)
{
if (tradDic.TryGetValue(meta.TradeId, out var td))
{
td.MetaDic[meta.MetaKey] = meta.MetaValue;
}
}
}
}
}
}