Files
zszq-trs/YLErpDAL/Modules/TradeModule/TradeExtendService.cs
T
2024-05-09 14:06:26 +08:00

1034 lines
66 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using YLErp.BLL;
using YLErp.Commons;
using YLErp.DBModels.Helpers;
using YLErp.QdpModule;
using static iTextSharp.text.pdf.AcroFields;
namespace YLErp.Modules.TradeModule
{
/// <summary>
/// 交易扩展通用服务
/// </summary>
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)
{
}
/// <summary>
/// 设置奇异要素
/// </summary>
public void SetTradeExtendWithCnKey(IEnumerable<OtcTradeBase> otcTrades, bool setMetaData = false, DateTime? dateTime = null)
{
if (otcTrades is null || !otcTrades.Any())
{
return;
}
Dictionary<int, T> getTradeEx<T>(IEnumerable<int> tids) where T : TradeExtendBase
{
return DbContext.Set<T>().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<trade_asian_option>(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<trade_barrier_option>(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<trade_double_sharkfin_option>(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<trade_binary_option>(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<trade_rangeaccrual>(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<trade_airbag>(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<trade_underlying_enhance>(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<trade_autocall>(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<trade_swap>(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<trade_forward>(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<trade_snowball>(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<trade_cashflow>(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<trade_accumulator_option>(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<trade_risky_option>(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);
}
}
/// <summary>
/// 转化票息率
/// </summary>
/// <param name="isFixedCoupon">是否年化 false 是 true 否</param>
/// <param name="couponDayCount">票息日历规则</param>
/// <param name="coupon">票息率</param>
/// <returns></returns>
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;
}
/// <summary>
/// 设置奇异要素
/// </summary>
public void SetTradeExtend(IEnumerable<OtcOptionTradeFull> otcTrades, bool setMetaData = false)
{
if (otcTrades is null || !otcTrades.Any())
{
return;
}
void setTradeEx<T>(IEnumerable<OtcOptionTradeFull> tds) where T : TradeExtendBase
{
var tids = tds.Select(n => n.id).ToHashSet();
var dic = DbContext.Set<T>().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<trade_asian_option>(g); break;
case "障碍期权":
setTradeEx<trade_barrier_option>(g); break;
case "双鲨期权":
setTradeEx<trade_double_sharkfin_option>(g); break;
case "二元期权":
setTradeEx<trade_binary_option>(g); break;
case "区间累积期权":
setTradeEx<trade_rangeaccrual>(g); break;
case "气囊结构":
setTradeEx<trade_airbag>(g); break;
case "收益增强结构":
setTradeEx<trade_underlying_enhance>(g); break;
case "凤凰期权":
setTradeEx<trade_autocall>(g); break;
case "雪球期权":
setTradeEx<trade_snowball>(g); break;
case "累计期权":
setTradeEx<trade_accumulator_option>(g); break;
case "现金流交易":
setTradeEx<trade_cashflow>(g); break;
case "自定义交易":
setTradeEx<trade_custom>(g); break;
case "Risky期权":
setTradeEx<trade_risky_option>(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>(T extend) where T : TradeExtendBase
{
YLAutoMapper.Map(extend, otcTrade);
}
}
/// <summary>
/// 设置奇异要素
/// </summary>
public void SetTradeExtend(IEnumerable<trade> tradeList, bool setMetaData = false, bool tracking = false)
{
if (tradeList is null || !tradeList.Any())
{
return;
}
void InnerSetExt<T>(IEnumerable<trade> tds, Func<trade, T> getter, Action<trade, T> 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<T>() : DbContext.Set<T>().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<T>(IEnumerable<trade> tds, Func<trade, List<T>> getter, Action<trade, List<T>> 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<T>() : DbContext.Set<T>().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);
}
}
/// <summary>
/// 设置元数据
/// </summary>
public void SetTradeMeta(IEnumerable<OtcTradeBase> otcTrades)
{
if (otcTrades is null || !otcTrades.Any())
{
return;
}
var set = new HashSet<int>();//应该没有重复的数据但也防止下意外情况的发生
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;
}
}
}
}
}
}