Files
zszq-trs/YLErpDAL/Modules/SuperviseReportModule/CFMMC2022/Service/SuperviseReportBaseService.cs
T
2024-05-09 14:06:26 +08:00

2165 lines
88 KiB
C#

using BaseOUDAL;
using Qdp.Foundation.Implementations;
using System.Text.RegularExpressions;
using YLErp.Abstract.DataProviders;
using YLErp.Commons;
using YLErp.DBModels.Consts;
using YLErp.Model;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.SuperviseReportModule.CFMMC2022.Model;
using YLErp.Modules.TradeModule;
using YLErp.QdpModule;
using static YLErp.Modules.SuperviseReportModule.CFMMC2022.Model.SuperviseReportBaseModel;
namespace YLErp.Modules.SuperviseReportModule.CFMMC2022.Service
{
public abstract class SuperviseReportBaseService : YLBaseService
{
protected SuperviseReportReq _req { get; set; }
/// <summary>
/// 分隔符
/// <para>分号</para>
/// </summary>
protected string _separator => ";";
protected IEodPriceProviderWrap _priceProvider;
protected SuperviseReportBaseService(SuperviseReportReq req, OptUserInfo userInfo) : base(userInfo)
{
_req = req ?? throw new ArgumentNullException(nameof(req));
_priceProvider = new EodPriceProvider(_req.ValueDate).GetPriceProvider(SettlementTypeEnum.ClosePrice);
}
private readonly List<string> ignoreTradeTypes = new List<string>() { "区间累积期权" };
/// <summary>
/// 了结交易类型代码集合
/// </summary>
private readonly List<string> tradeTypes = new List<string>() { "PU", "FU", "ED" };
/// <summary>
///
/// </summary>
/// <param name="model"></param>
/// <param name="varietyTypes">标的资产类型</param>
/// <param name="assetTypes">资产类型</param>
/// <param name="varietySuffixs">标的资产品种后缀和标的资产对应合约后缀</param>
/// <param name="syntheticPrice">组合标的价格</param>
/// <exception cref="ServiceException">EodTrade不存在时抛出</exception>
protected virtual void FormatModel(SuperviseReportBaseModel model, List<DictionaryItem> assetTypes, List<DictionaryItem> varietySuffixs, List<DictionaryItem> varietyCodeList, out SyntheticPriceModel syntheticPrice)
{
if (model.trade == null)
{
throw new ServiceException($"日终Trade不存在,交易编号:{model.OriginalTradeNumber}");
}
//工具类型
model.ToolType = formatToolType(model.trade.TradeType, model.StructureType);
//当“工具类型”为OP或FW时,该字段只能填报B或S
if (model.ToolType == "OP")
{
model.ClientDirection = model.trade.BuySell == "买入" ? "B" : "S";
}
else if (model.ToolType == "FW")
{
model.ClientDirection =
(model.trade.BuySell == "买入" && model.trade.OptionType == "看涨") ||
(model.trade.BuySell == "卖出" && model.trade.OptionType == "看跌")
? "B" : "S";
}
//当“工具类型“为SW时,该字段只能填报P或R
else if (model.ToolType == "SW")
{
model.ClientDirection = model.trade.trade_swap.IsGetFloatingProfit ? "P" : "R";
}
//期初价格
model.UnderlyingInitialPrice = model.trade.SpotPrice.OtcFormatFlex(2); //formatTradeAmount(model.trade.SpotPrice);
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(model.trade.UnderlyingCode);
if (um.IsSynthetic() || !string.IsNullOrWhiteSpace(model.trade.BasisUnderlyingCode))
{
var marketNoDict = new Dictionary<string, string>();
var query = DbContext.TradeMeta.Where(O => O.TradeId == model.trade.id && O.MetaValue.Length > 5);
if (um.IsSynthetic())
{
query = query.Where(O => O.MetaKey.StartsWith(ConsTradeMetaKey.SyntheticUnderlying));
var tradeMeta = query.FirstOrDefault();
if (string.IsNullOrWhiteSpace(tradeMeta?.MetaValue))
{
throw new ServiceException($"组合标的期初价格信息不完整,交易编号:{model.OriginalTradeNumber}");
}
syntheticPrice = JsonHelper.Deserialize<SyntheticPriceModel>(tradeMeta.MetaValue);
if (syntheticPrice.SuList == null)
{
throw new ServiceException($"组合标的价格缺失,交易编号:{model.trade.TradeNumber}");
}
}
else
{
query = query.Where(O => O.MetaKey == ConsTradeMetaKey.SpotInfos);
var tradeMeta = query.FirstOrDefault();
string[] arrPrice = null;
if (string.IsNullOrWhiteSpace(tradeMeta?.MetaValue))
{
arrPrice = new[] { model.trade.SpotPrice?.ToString() };
}
else
{
arrPrice = JsonHelper.Deserialize<string[]>(tradeMeta.MetaValue);
if (arrPrice == null || arrPrice.Length == 0)
{
throw new ServiceException($"期初价格缺失,交易编号:{model.trade.TradeNumber}");
}
}
var prides = new UnderlyingPriceModel[arrPrice.Length];
for (var i = 0; i < arrPrice.Length; i++)
{
prides[i] = new UnderlyingPriceModel
{
Price = double.TryParse(arrPrice[i], out var p) ? p : 0,
Coefficient = i == 0 ? 1 : -1,
UnderlyingCode = i == 0 ? model.trade.UnderlyingCode : model.trade.BasisUnderlyingCode
};
}
syntheticPrice = new SyntheticPriceModel
{
SuList = prides
};
}
var underlyingCodes = syntheticPrice.SuList.Select(O => O).ToArray();
var arrCode = new string[underlyingCodes.Length];
var arrUnitZh = new string[underlyingCodes.Length];
var arrUnitEn = new string[underlyingCodes.Length];
var arrVarietyType = new string[underlyingCodes.Length];
var arrUnderlyingPlate = new string[underlyingCodes.Length];
var arrDeltaCash = new string[underlyingCodes.Length];
//多表的资产类型
var vTypeIsOther = false;
var vTypeStr = "";
//多标的数量单位
var vUnitEnIsOther = false;
var vUnitEnStr = "";
for (var i = 0; i < underlyingCodes.Length; i++)
{
if (underlyingCodes[i] == null || string.IsNullOrWhiteSpace(underlyingCodes[i].UnderlyingCode))
{
arrCode[i] = null;
arrUnitZh[i] = null;
arrUnitEn[i] = null;
arrVarietyType[i] = null;
continue;
}
var variety = UnderlyingDataProvider.GetVariety(underlyingCodes[i].UnderlyingCode);
if (variety == null) { throw new ServiceException($"未找到品种数据: {underlyingCodes[i].UnderlyingCode}"); }
var um1 = UnderlyingDataProvider.GetUnderlying(underlyingCodes[i].UnderlyingCode);
var varietySuffix = formatDictItem(varietySuffixs, um1?.MarketCode, um1?.MarketCode);
marketNoDict[underlyingCodes[i].UnderlyingCode] = varietySuffix;
arrCode[i] = formatVarietyCode(underlyingCodes[i].UnderlyingCode, variety, varietyCodeList, varietySuffix);
arrUnitZh[i] = um?.QuoteUnit;//variety.QuoteUnitSingleOriginal;
//arrUnitEn[i] = formatQuoteUnit(arrUnitZh[i]);
//arrVarietyType[i] = formatVariety(variety.MainCategory);
arrUnderlyingPlate[i] = formatUnderlyingPlate(variety.AssetType);
arrDeltaCash[i] = OtcFormatHelper.FormatValue((model._delta * underlyingCodes[i].Price), 4).ToString();
//多标的数量单位,如果不同的数量单位,就报其他(O)
if (string.IsNullOrEmpty(vUnitEnStr))
{
vUnitEnStr = arrUnderlyingPlate[i] == "IN" ? "元/指数点" : formatQuoteUnit(arrUnitZh[i]);
}
else
{
if (vUnitEnStr != (arrUnderlyingPlate[i] == "IN" ? "元/指数点" : formatQuoteUnit(arrUnitZh[i])))
{
vUnitEnIsOther = true;
}
}
//多标的资产类型,如果不同的资产类型,就报其他(O)
if (string.IsNullOrEmpty(vTypeStr))
{
vTypeStr = formatVariety(variety.MainCategory);
}
else
{
if (vTypeStr != formatVariety(variety.MainCategory))
{
vTypeIsOther = true;
}
}
}
model.UnderlyingCode = formatSyntheticUnderlying(syntheticPrice, marketNoDict);
model.VarietyCode = JoinArr(arrCode);
//model.QuoteUnitEn = JoinArr(arrUnitEn);
model.QuoteUnitEn = vUnitEnIsOther ? "Other" : vUnitEnStr;
//model.VarietyType = JoinArr(arrVarietyType);
model.VarietyType = vTypeIsOther ? "O" : vTypeStr;
model.UnderlyingPlate = JoinArr(arrUnderlyingPlate);
model.DeltaCash = JoinArr(arrDeltaCash);
}
else
{
var variety = UnderlyingDataProvider.GetVariety(model.trade.UnderlyingCode);
if (variety == null) { throw new ServiceException($"未找到品种数据: {model.trade.UnderlyingCode}"); }
var varietySuffix = formatDictItem(varietySuffixs, um?.MarketCode, um?.MarketCode);
model.UnderlyingCode = formatUnderlyingCode(model.trade.UnderlyingCode, varietySuffix);
model.VarietyCode = formatVarietyCode(model.trade.UnderlyingCode, variety, varietyCodeList, varietySuffix);
model.VarietyType = formatVariety(variety.MainCategory);
model.UnderlyingPlate = formatUnderlyingPlate(variety.AssetType);
model.QuoteUnitEn = model.UnderlyingPlate == "IN" ? "元/指数点" : formatQuoteUnit(um?.QuoteUnit);
model.DeltaCash = OtcFormatHelper.FormatValue((model._delta * model._price ?? model.trade.SpotPrice), 4).ToString();
syntheticPrice = null;
}
if (um?.UnderlyingInstrumentType == "Stock")
{
model.IsStock = true;
}
model.UnderlyingInitialPriceSymbol = formatPriceSymbol(model.UnderlyingPlate);
if (model.UnderlyingInitialPriceSymbol == "1")
{
model.UnderlyingInitialPriceCurrency = "CNY";
}
//期权行权时间类型
model.ExerciseMode = IsOption(model.trade) && model.trade.TradeType != "自定义交易" ? (model.trade.ExerciseMode == "European" ? "EU" : "US") : "O";
//国投特殊处理
model.ExerciseMode = PS.Config.Company == Configuration.CompanyEnum.国投 && model.trade.TradeType == "雪球期权" ? "O" : model.ExerciseMode;
model.OptionType = ignoreTradeTypes.Contains(model.trade.TradeType) ? "9" : IsOption(model.trade) ? (model.trade.OptionType == "看涨" ? "2" : "1") : "9";
if (model.ToolType == "FW" || model.ToolType == "SW")
{
model.ExerciseMode = null;
model.OptionType = null;
}
//看跌是1,看涨是2,价差是9
if (model.trade.TradeType == "凤凰期权")
{
if (model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToPutOption || model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
{
model.OptionType = "1";
}
else if (model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToCallOption || model.trade.trade_autocall.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption)
{
model.OptionType = "2";
}
else
{
model.OptionType = "9";
}
}
else if (model.trade.TradeType == "雪球期权")
{
if (model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToPutOption || model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
{
model.OptionType = "1";
}
else if (model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToCallOption || model.trade.trade_snowball.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption)
{
model.OptionType = "2";
}
else
{
model.OptionType = "9";
}
}
//多腿编号
model.MoreLegCode = formatTradeNumber(model);
//期权产品结构
model.OptionProductStructure = formatOptionProductStructure(model);
//获取执行价格
formatStrike(model);
//观察类型、观察起始日、观察截止日、观察周期、观察周期乘数
formatObserveType(model);
//收益计算方式
formatRevenueCalculationMethod(model);
//保底收益
model.GuaranteedIncome = model.trade.OriginalPrincipalSum * (model.trade.Notional / model.trade.OriginalNotional);
model.GuaranteedIncomeSymbol = "1";
model.GuaranteedIncomeCurrency = "CNY";
//保底收益率
if (model.trade.IsUsePremiumRate == true)
{
model.GuaranteedIncome = model.trade.PrincipalRateWrite;
model.GuaranteedIncomeCurrency = null;
model.GuaranteedIncomeSymbol = "2";
}
//参与率
model.ParticipateRate = model.trade.ParticipationRate ?? 1;
//是否为年化名义金额
model.IsAnnualizedNominalAmount = model.trade.IsAnnualized ? "Y" : "N";
//凤凰、雪球
if (model.OptionProductStructure == "PA")
{
model.IsAnnualizedNominalAmount = model.trade.trade_autocall.IsAnnualized2 ? "Y" : "N";
}
else if (model.OptionProductStructure == "SA" || model.OptionProductStructure == "GSA")
{
model.IsAnnualizedNominalAmount = model.trade.trade_snowball.IsAnnualized2 ? "Y" : "N";
//小雪球的时候,红利票息赋值给保底收益
if (model.OptionProductStructure == "GSA")
{
model.GuaranteedIncome = model.trade.trade_snowball.Coupon;
model.GuaranteedIncomeCurrency = null;
model.GuaranteedIncomeSymbol = "2";
}
}
//特定字段赋值
switch (model.ToolType)
{
case "OP":
setOptionlFields(model);
break;
case "FW":
setForwardFields(model);
break;
case "SW":
setSwapFields(model);
break;
}
//自定义字段结构不为空时,处理自定义字段报送
if (!string.IsNullOrEmpty(model.ExtendInfo))
{
formatExtendInfo(model);
}
}
/// <summary>
/// 获取资产类型
/// </summary>
/// <param name="inputVal"></param>
/// <returns></returns>
private string formatVariety(string inputVal)
{
var varietyType = "";
switch (inputVal)
{
case "Equity":
varietyType = "EQ";
break;
case "BulkCommodity":
varietyType = "CO";
break;
case "InterestRate":
varietyType = "IR";
break;
case "Credit":
varietyType = "CR";
break;
case "ExchangeRate":
varietyType = "FX";
break;
default: varietyType = "CO"; break;
}
return varietyType;
}
/// <summary>
/// 获取价格符号
/// </summary>
/// <param name="underlyingPlate"></param>
/// <returns></returns>
private string formatPriceSymbol(string underlyingPlate)
{
switch (underlyingPlate)
{
case "IN": return "3";
case "LIBOR":
case "LPR":
case "GBOND":
case "TBOND":
case "PolicyBBOND":
case "CBOND":
case "FBOND":
return "2";
default: return "1";
}
}
protected double formatInitCastClientPayable(trade t)
{
double result = 0;
if (t != null)
{
result = (t.InitialMargin * (t.Notional / t.OriginalNotional)) ?? 0;
}
return Math.Max(0, result);
}
protected string formatTradeAmount(double? notional, double coefficient = 1)
{
var value = notional * coefficient;
return OtcFormatHelper.FormatValue(value, 4).ToString();
}
/// <summary>
/// 获取工具类型
/// </summary>
/// <param name="tradeType"></param>
/// <param name="structureType"></param>
/// <returns></returns>
private string formatToolType(string tradeType, string structureType)
{
var toolType = "O";
switch (tradeType)
{
case "收益互换":
toolType = "SW";
break;
case "远期":
toolType = "FW";
if (structureType == "掉期")
{
toolType = "SW";
}
break;
default:
toolType = "OP";
break;
}
return toolType;
}
protected string formatDictItem(List<DictionaryItem> dictItemMap, string name, string defaultValue = "")
{
if (name == null || dictItemMap == null) { return defaultValue; }
var obj = dictItemMap.FirstOrDefault(O => O.Name == name);
return obj == null ? defaultValue : obj.ShortName;
}
private string formatSyntheticUnderlying(SyntheticPriceModel underlying, Dictionary<string, string> exchangeNo)
{
Func<double, string, string> formatCode = (_coefficient, _underlyingCode) =>
{
var code = formatUnderlyingCode(_underlyingCode, exchangeNo[_underlyingCode]);
var coef = Math.Abs(_coefficient).ToString();
return $"{(coef == "1" ? null : coef)}{code}";
};
var tipsInfo = "";
foreach (var item in underlying.SuList)
{
if (!string.IsNullOrEmpty(tipsInfo) || item.Coefficient < 0)
{
tipsInfo += (item.Coefficient >= 0 ? "+" : "-");
}
tipsInfo += formatCode(item.Coefficient, item.UnderlyingCode);
}
return tipsInfo;
}
/// <summary>
/// 获取标的代码
/// </summary>
/// <param name="underlyingCode"></param>
/// <param name="exchangeNo"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private string formatUnderlyingCode(string underlyingCode, string exchangeNo)
{
if (string.IsNullOrWhiteSpace(underlyingCode))
{
throw new ArgumentException("标的代码不存在", nameof(underlyingCode));
}
var superviseUndelrying = DbContext.supervise_undelrying.FirstOrDefault(n => n.undelrying == underlyingCode);
if (superviseUndelrying != null && !string.IsNullOrEmpty(superviseUndelrying.undelrying_CFMMC))
{
return superviseUndelrying.undelrying_CFMMC;
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
if (underlying == null)
{
throw new ArgumentException("标的信息不存在:" + underlyingCode);
}
if (underlying.UnderlyingInstrumentType == ConsGlobal.InstrumentType.CommoditySpot)
{
return underlying.UnderlyingName;
}
else if (underlyingCode.Contains("."))
{
return underlyingCode;
}
return $"{underlyingCode}.{exchangeNo}";
}
/// <summary>
/// 获取标的资产所属板块
/// </summary>
/// <param name="inputVal"></param>
/// <returns></returns>
private string formatUnderlyingPlate(string inputVal)
{
switch (inputVal)
{
case "贵金属":
case "有色及贵金属":
return "Pmetal";
case "黑色": return "Ferrous";
case "能化":
case "能源化工":
return "ECH";
case "农产品": return "AGP";
case "有色": return "NonFerrous";
case "商品ETF": return "COETF";
case "个股": return "SK";
case "股指":
case "指数":
return "IN";
case "基金": return "FD";
case "LIBOR": return "LIBOR";
case "LPR": return "LPR";
case "地方政府债": return "GBOND";
case "国股银票转贴现": return "BAEX_1";
case "国债": return "TBOND";
case "政策性金融债": return "PolicyBBOND";
case "美元兑人民币": return "USDRMB";
case "公司债": return "CBOND";
case "金融债": return "FBOND";
default: return null;
}
}
/// <summary>
/// 多腿编号
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
private string formatTradeNumber(SuperviseReportBaseModel model)
{
var tradeNum = "";
if (model.ParentTradeId > 0)
{
if (PS.Config.Company == Configuration.CompanyEnum.浙期)
{
if (!int.TryParse(Regex.Match(model.OriginalTradeNumber ?? "", @"(?<=X)\d+$").Value, out var tradeNum2))
{
return null;
}
tradeNum = tradeNum2.ToString();
}
else if (PS.Config.Is物产中大 && model.ParentTradeId > 0)
{
tradeNum = (DbContext.trade.Where(l=>l.id<model.TradeId && l.ParentTradeId ==model.ParentTradeId && l.ValidState!= "InValid").Count()+1).ToString();
}
else if (model.OriginalTradeNumber.IndexOf('-') > 0)
{
var arrOTNum = model.OriginalTradeNumber.Split('-');
tradeNum = arrOTNum[arrOTNum.Length - 1];
}
}
else
{
tradeNum = null;
}
return tradeNum;
}
/// <summary>
/// 获取期权产品结构
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
private string formatOptionProductStructure(SuperviseReportBaseModel model)
{
var tradeTypeEn = "O";
switch (model.OptionProductStructure)
{
case "香草期权":
tradeTypeEn = "VA";
break;
case "亚式期权":
tradeTypeEn = "AS";
break;
case "二元期权":
tradeTypeEn = "DI";
break;
case "区间累计期权":
case "区间累积期权":
tradeTypeEn = "RA";
break;
case "障碍期权":
if (model.trade.trade_barrier_option.BarrierType.StartsWith("双障碍"))
{
tradeTypeEn = "DSF";
}
else if (model.trade.trade_barrier_option.BarrierType.EndsWith("敲入"))
{
tradeTypeEn = "SKI";
}
else if (model.trade.trade_barrier_option.BarrierType.EndsWith("敲出"))
{
tradeTypeEn = "SF";
}
break;
case "双鲨期权":
tradeTypeEn = "DSF";
break;
case "累计期权":
tradeTypeEn = "AC";
break;
case "雪球期权":
if (model.trade.trade_snowball.KIPayoffType == 0)
{
tradeTypeEn = "GSA";
}
else
{
tradeTypeEn = "SA";
}
break;
case "凤凰期权":
tradeTypeEn = "PA";
break;
case "自定义交易":
tradeTypeEn = "O";
if (!string.IsNullOrEmpty(model.trade.StructureType))
{
var customTradeInfo = DbContext.Structure_Info.FirstOrDefault(n => n.StructureName == model.trade.StructureType);
if (customTradeInfo != null)
{
if (!string.IsNullOrEmpty(customTradeInfo.StructureTypeSm))
{
tradeTypeEn = customTradeInfo.StructureTypeSm;
}
}
}
break;
default:
tradeTypeEn = "O";
break;
}
return tradeTypeEn;
}
/// <summary>
/// 获取标的资产品种
/// </summary>
/// <param name="underlyingCode"></param>
/// <param name="variety"></param>
/// <param name="varietyCodeList"></param>
/// <param name="marketExchangeNo"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
private string formatVarietyCode(string underlyingCode, Variety variety, List<DictionaryItem> varietyCodeList, string marketExchangeNo)
{
if (string.IsNullOrWhiteSpace(underlyingCode))
{
throw new ArgumentException("标的代码不存在", nameof(underlyingCode));
}
var code = varietyCodeList.Where(O => O.Name.ToLower() == underlyingCode.ToLower()).Select(O => O.ShortName).FirstOrDefault();
if (!string.IsNullOrEmpty(code))
{
return code;
}
var underlying = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
if (underlying == null)
{
throw new ArgumentException("标的信息不存在:" + underlyingCode);
}
var assetVariety = $"{{0}}.{marketExchangeNo}";
switch (underlying.UnderlyingInstrumentType)
{
case ConsGlobal.InstrumentType.StockIndex:
case ConsGlobal.InstrumentType.StockIF:
assetVariety = variety.VarietyName;
break;
case ConsGlobal.InstrumentType.CommodityFutures:
assetVariety = string.Format(assetVariety, variety.VarietyCode);
break;
case ConsGlobal.InstrumentType.CommoditySpot:
if (marketExchangeNo == "SGE")
{
assetVariety = string.Format(assetVariety, underlyingCode);
}
else
{
assetVariety = variety.VarietyName;
}
break;
case ConsGlobal.InstrumentType.Stock:
//assetVariety = string.Format(assetVariety, getStockVarietyCode(underlyingCode));
assetVariety = getStockVarietyCode(underlyingCode);
break;
default:
assetVariety = underlyingCode;
break;
}
return assetVariety;
}
private string getStockVarietyCode(string code)
{
var assetVariety = "";
if (code.StartsWith("60") || code.StartsWith("000"))
{ //主板
assetVariety = "ZB";
}
else if (code.StartsWith("002"))
{//中小板
//assetVariety = "ZXB";
assetVariety = "ZB";
}
else if (code.StartsWith("300"))
{//创业板
assetVariety = "CYB";
}
else if (code.StartsWith("688"))
{//科创版
assetVariety = "KCB";
}
else
{
assetVariety = "";
}
return assetVariety;
}
/// <summary>
/// 获取数量单位
/// </summary>
/// <param name="quoteUnit"></param>
/// <returns></returns>
private string formatQuoteUnit(string quoteUnit)
{
switch (quoteUnit)
{
case "吨":
return "t";
case "桶":
return "barrel";
case "克":
return "g";
case "千克":
return "kg";
case "500千克":
return "500kg";
case "股":
case "股(份)":
return "share";
case "磅":
return "lb";
case "点":
//if (PS.Config.Company == Configuration.CompanyEnum.国投)
//{
// return "bp";
//}
//return "point";
case "基点":
//return "bp";
case "units":
//return "units";
return "Other";
case "指数":
case "元/指数点":
return "元/指数点";
default:
return "Other";
}
//return quoteUnit;
}
protected double formatEndStockEqvNotionalReal(double? stockEqvNotional, double percentRate)
{
var result = stockEqvNotional * percentRate;
return Math.Abs(OtcFormatHelper.FormatValue((result ?? 0), 4));
}
protected string JoinArr(string[] arr)
{
var singleArr = new HashSet<string>(arr);
singleArr.Remove("");
return string.Join(";", singleArr);
}
/// <summary>
/// 是否为期权
/// </summary>
/// <param name="t"></param>
/// <returns></returns>
private bool IsOption(trade t)
{
return t.IsOption() || t.TradeType == "自定义交易";
}
/// <summary>
/// 获取执行价格1、2、3
/// </summary>
/// <param name="model"></param>
/// <returns></returns>
private void formatStrike(SuperviseReportBaseModel model)
{
//执行价格符号
model.StrikeSymbol = formatPriceSymbol(model.UnderlyingPlate);
if (model.StrikeSymbol == "1")
{
//执行价格货币
model.StrikeCurrency = "CNY";
}
var trade = model.trade;
//当期权产品结构为 AS(亚式期权),且执行价为观察期内标的价格的均值,则此处无需填写执行价格
if (model.OptionProductStructure == "AS" && trade.trade_asian_option.StrikeType == "Floating")
{
return;
}
//执行价1
model.Strike = trade.Strike ?? 0; //trade.IsMoneynessOption == "是" ? ((trade.Strike * trade.SpotPrice) ?? 0) :
if (trade.IsMoneynessOption == "是")
{
model.Strike = ((trade.Strike * trade.SpotPrice) ?? 0);
}
//执行价2
if (model.OptionProductStructure == "SA" || model.OptionProductStructure == "GSA")
{
model.Strike2 = trade.trade_snowball.SpreadStrikeAtMaturity;
if (trade.IsMoneynessOption == "是")
{
model.Strike2 = (trade.trade_snowball.SpreadStrikeAtMaturity * trade.SpotPrice);
}
}
else if (model.OptionProductStructure == "PA")
{
model.Strike2 = trade.trade_autocall.SpreadStrike;
if (trade.IsMoneynessOption == "是")
{
model.Strike2 = (trade.trade_autocall.SpreadStrike * trade.SpotPrice);
}
}
else if (model.OptionProductStructure == "DI" && trade.trade_binary_option.PayoffType.StartsWith("Double"))
{
model.Strike2 = trade.trade_binary_option.UpperBarrier;
if (trade.IsMoneynessOption == "是")
{
model.Strike2 = (trade.trade_binary_option.UpperBarrier * trade.SpotPrice);
}
}
else if (model.OptionProductStructure == "O" && trade.trade_risky_option != null)
{
model.Strike2 = trade.trade_risky_option.Strike2;
model.Strike3 = trade.trade_risky_option.Strike3;
if (trade.IsMoneynessOption == "是")
{
model.Strike2 = (trade.trade_risky_option.Strike2 * trade.SpotPrice);
model.Strike3 = (trade.trade_risky_option.Strike3 * trade.SpotPrice);
}
}
else if (model.OptionProductStructure == "AC" && trade.trade_accumulator_option != null && trade.trade_accumulator_option.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented)
{
model.Strike2 = trade.trade_accumulator_option.Strike2;
model.Strike3 = trade.trade_accumulator_option.Strike3;
if (trade.IsMoneynessOption == "是")
{
model.Strike2 = (trade.trade_accumulator_option.Strike2 * trade.SpotPrice);
model.Strike3 = (trade.trade_accumulator_option.Strike3 * trade.SpotPrice);
}
}
if (model.Strike > model.Strike2 && model.Strike2 > 0)
{
var tempVal = model.Strike2 ?? 0;
model.Strike2 = model.Strike;
model.Strike = tempVal;
}
}
/// <summary>
/// 获取观察方式、观察开始时间、观察结束时间、观察周期
/// </summary>
/// <param name="observType"></param>
/// <returns></returns>
private void formatObserveType(SuperviseReportBaseModel model)
{
string getObType(string input)
{
switch (input)
{
case "离散": return "DISCRETE";
case "连续": return "CONTINUOUS";
case "到期": return "TERMINAL";
default: return "DISCRETE";
}
}
DateTime getObSDate(string observationDates, out DateTime inputDateTime)
{
var observations = observationDates.Split(',');
var observeStartData = DateTime.Parse(observations[0]);
inputDateTime = DateTime.Parse(observations[(observations.Count() - 1)]);
return observeStartData;
}
var trade = model.trade;
DateTime oSd;
DateTime observeEndDate;
switch (model.OptionProductStructure)
{
case "AS":
model.ObserveType = getObType("离散");
model.ObserveStartDate = trade.trade_asian_option?.AveragingPeriodStartDate;
model.ObserveEndDate = model.EndDate;
break;
case "DI":
model.ObserveType = getObType((trade.ExerciseModeCn == "欧式" || trade.ExerciseMode == "European") ? "到期" : trade.trade_binary_option.MonitorType);
if (!string.IsNullOrEmpty(trade.trade_binary_option.ObservationDates))
{
model.ObserveStartDate = getObSDate(trade.trade_binary_option.ObservationDates, out observeEndDate);
model.ObserveEndDate = observeEndDate;
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
break;
case "RA":
model.ObserveType = getObType("离散");//trade_rangeaccrual
if (!string.IsNullOrEmpty(trade.trade_rangeaccrual.ObservationDates))
{
model.ObserveStartDate = getObSDate(trade.trade_rangeaccrual.ObservationDates, out observeEndDate);
model.ObserveEndDate = observeEndDate;
if (isTerminal(trade.trade_rangeaccrual.ObservationDates, model.EndDate.Value))
{
model.ObserveType = "TERMINAL";
}
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
break;
case "SF":
case "SKI":
model.ObserveType = getObType(trade.trade_barrier_option.Discrete);
if (!string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates))
{
model.ObserveStartDate = getObSDate(trade.trade_barrier_option.ObservationDates, out observeEndDate);
model.ObserveEndDate = observeEndDate;
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
break;
case "DSF":
if (model.ProductType == "双鲨期权")
{
model.ObserveType = getObType(trade.trade_double_sharkfin_option.Discrete);
if (!string.IsNullOrEmpty(trade.trade_double_sharkfin_option.ObservationDates))
{
model.ObserveStartDate = getObSDate(trade.trade_double_sharkfin_option.ObservationDates, out observeEndDate);
model.ObserveEndDate = observeEndDate;
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
}
else
{
model.ObserveType = getObType(trade.trade_barrier_option.Discrete);
if (!string.IsNullOrEmpty(trade.trade_barrier_option.ObservationDates))
{
model.ObserveStartDate = getObSDate(trade.trade_barrier_option.ObservationDates, out observeEndDate);
model.ObserveEndDate = observeEndDate;
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
}
break;
case "AC":
model.ObserveType = getObType("离散");//trade_accumulator_option
if (!string.IsNullOrEmpty(trade.trade_accumulator_option.KOObservationDates))
{
var KOObservationDatesArr = trade.trade_accumulator_option.KOObservationDates.Split(';');
if (KOObservationDatesArr.Length > 0)
{
model.ObserveStartDate = getObSDate(KOObservationDatesArr[0], out observeEndDate);
model.ObserveEndDate = observeEndDate;
if (isTerminal(KOObservationDatesArr[0], model.EndDate.Value))
{
model.ObserveType = "TERMINAL";
}
}
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
break;
case "SA":
case "GSA":
model.ObserveType = getObType("离散");//trade_snowball
if (!string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates))
{
var KOObservationDatesArr = trade.trade_snowball.KOObservationDates.Split(';');
if (KOObservationDatesArr.Length > 0)
{
model.ObserveStartDate = getObSDate(KOObservationDatesArr[0], out observeEndDate);
model.ObserveEndDate = observeEndDate;
if (isTerminal(KOObservationDatesArr[0], model.EndDate.Value))
{
model.ObserveType = "TERMINAL";
}
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
}
break;
case "PA":
model.ObserveType = getObType("离散");//trade_autocall
if (!string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates))
{
var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(trade.trade_autocall.KOObservationDates, trade.trade_autocall.CouponBarrier);
var KOObservationDatesArr = ko.Item2.Split(';');
if (KOObservationDatesArr.Length > 0)
{
model.ObserveStartDate = getObSDate(KOObservationDatesArr[0], out observeEndDate);
model.ObserveEndDate = observeEndDate;
if (isTerminal(KOObservationDatesArr[0], model.EndDate.Value))
{
model.ObserveType = "TERMINAL";
}
}
}
else
{
oSd = model.StartDate.Value.AddDays(1);
model.ObserveStartDate = oSd;
model.ObserveEndDate = model.EndDate;
}
break;
}
}
/// <summary>
/// 是否是到期观察
/// </summary>
/// <param name="observationDates"></param>
/// <param name="endDate"></param>
/// <returns></returns>
public bool isTerminal(string observationDates, DateTime endDate)
{
var isTerminal = false;
var observations = observationDates.Split(',');
if (observations.Length == 1)
{
var observeStartData = DateTime.Parse(observations[0]);
if (observeStartData == endDate)
{
isTerminal = true;
}
}
return isTerminal;
}
/// <summary>
/// 获取收益计算方式
/// </summary>
/// <param name="model"></param>
private void formatRevenueCalculationMethod(SuperviseReportBaseModel model)
{
var trade = model.trade;
switch (model.OptionProductStructure)
{
case "AS":
break;
case "DI":
model.RevenueCalculationMethod = trade.trade_binary_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT";
break;
case "RA":
break;
case "SF":
case "SKI":
model.RevenueCalculationMethod = trade.trade_barrier_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT";
break;
case "DSF":
if (model.ProductType == "双鲨期权")
{
model.RevenueCalculationMethod = trade.trade_double_sharkfin_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT";
}
else
{
model.RevenueCalculationMethod = trade.trade_barrier_option.RebateType == "AtEnd" ? "EXPIRY" : "HIT";
}
break;
case "AC":
break;
case "SA":
case "GSA":
model.RevenueCalculationMethod = trade.trade_snowball.KORebateType == 0 ? "HIT" : "EXPIRY";
break;
case "PA":
model.RevenueCalculationMethod = trade.trade_autocall.CouponPayType == 0 ? "HIT" : "EXPIRY";
break;
}
}
/// <summary>
/// 设置特定期权结构的字段 需要大改
/// </summary>
/// <param name="model"></param>
private void setOptionlFields(SuperviseReportBaseModel model)
{
var trade = model.trade;
switch (model.OptionProductStructure)
{
case "DI"://二元
if (trade.trade_binary_option != null)
{
model.ExerciseBenefitsSymbol = "1";
if (trade.IsUsePremiumRate == true)
{
model.ExerciseBenefitsSymbol = "2";
model.ExerciseBenefits = trade.trade_binary_option.CashOrNothingAmountRate + (model.GuaranteedIncome ?? 0);
if (model.Strike2 > 0)
{
model.ExerciseBenefits2 = trade.trade_binary_option.CashOrNothingAmountHighRate + (model.GuaranteedIncome ?? 0);
}
}
else
{
model.ExerciseBenefitsCurrency = "CNY";
model.ExerciseBenefits = trade.trade_binary_option.CashOrNothingAmount + (model.GuaranteedIncome ?? 0);
if (model.Strike2 > 0)
{
model.ExerciseBenefits2 = trade.trade_binary_option.CashOrNothingAmountHigh + (model.GuaranteedIncome ?? 0);
}
}
}
break;
case "RA":
if (trade.trade_rangeaccrual != null)
{
model.ExerciseBenefitsSymbol = "2";
model.ExerciseBenefits = trade.trade_rangeaccrual.BonusRate + (trade.PrincipalRateWrite ?? 0);
}
break;
case "SKI":
case "SF":
if (trade.trade_barrier_option != null)
{
model.BarriersPrice = trade.trade_barrier_option.BarrierPrice;
if (!string.IsNullOrEmpty(trade.trade_barrier_option.BarrierType))
{
if (trade.trade_barrier_option.BarrierType.StartsWith("上"))
{
model.BarriersPriceTouchDirection = "Up";
}
else if (trade.trade_barrier_option.BarrierType.StartsWith("下"))
{
model.BarriersPriceTouchDirection = "Down";
}
if (trade.trade_barrier_option.BarrierType.EndsWith("敲入"))
{
model.BarriersPriceType = "In";
}
else if (trade.trade_barrier_option.BarrierType.EndsWith("敲出"))
{
model.BarriersPriceType = "Out";
}
}
if (model.trade.IsMoneynessOption == "是")
{
model.BarriersPrice = trade.trade_barrier_option.BarrierPrice * trade.SpotPrice;
}
model.CompensationIncomeCurrency = "CNY";
if (trade.IsUsePremiumRate == true)
{
model.CompensationIncomeSymbol = "2";
model.CompensationIncome = trade.trade_barrier_option.RebateRate ?? 0;
model.CompensationIncomeCurrency = null;
}
else
{
model.CompensationIncomeSymbol = "1";
model.CompensationIncome = trade.trade_barrier_option.Rebate ?? 0;
}
}
break;
case "DSF":
model.CompensationIncomeCurrency = "CNY";
if (model.ProductType == "双鲨期权")
{
if (trade.trade_double_sharkfin_option != null)
{
model.BarriersPrice = trade.trade_double_sharkfin_option.BarrierLow;
model.BarriersPrice2 = trade.trade_double_sharkfin_option.BarrierHigh;
if (model.trade.IsMoneynessOption == "是")
{
model.BarriersPrice = trade.trade_double_sharkfin_option.BarrierLow * trade.SpotPrice;
model.BarriersPrice2 = trade.trade_double_sharkfin_option.BarrierHigh * trade.SpotPrice;
}
model.BarriersPriceTouchDirection = "Down";
model.BarriersPrice2TouchDirection = "Up";
model.BarriersPriceType = "Out";
model.BarriersPrice2Type = "Out";
if (trade.IsUsePremiumRate == true)
{
model.CompensationIncome = trade.trade_double_sharkfin_option.RebateRate ?? 0;
model.CompensationIncome2 = trade.trade_double_sharkfin_option.RebateHighRate ?? 0;
model.CompensationIncomeSymbol = "2";
model.CompensationIncomeCurrency = null;
}
else
{
model.CompensationIncome = trade.trade_double_sharkfin_option.Rebate ?? 0;
model.CompensationIncome2 = trade.trade_double_sharkfin_option.RebateHigh ?? 0;
model.CompensationIncomeSymbol = "1";
}
}
}
else
{
if (trade.trade_barrier_option != null)
{
model.BarriersPrice = trade.trade_barrier_option.BarrierPrice;
model.BarriersPrice2 = trade.trade_barrier_option.UpperBarrierPrice;
if (model.trade.IsMoneynessOption == "是")
{
model.BarriersPrice = trade.trade_barrier_option.BarrierPrice * trade.SpotPrice;
model.BarriersPrice2 = trade.trade_barrier_option.UpperBarrierPrice * trade.SpotPrice;
}
model.BarriersPriceTouchDirection = "Down";
if (!string.IsNullOrEmpty(trade.trade_barrier_option.BarrierType))
{
if (trade.trade_barrier_option.BarrierType.EndsWith("敲入"))
{
model.BarriersPriceType = "In";
if (model.BarriersPrice2 > 0)
{
model.BarriersPrice2Type = "In";
model.BarriersPrice2TouchDirection = "Up";
}
}
else if (trade.trade_barrier_option.BarrierType.EndsWith("敲出"))
{
model.BarriersPriceType = "Out";
if (model.BarriersPrice2 > 0)
{
model.BarriersPrice2Type = "Out";
model.BarriersPrice2TouchDirection = "Up";
}
}
}
if (trade.IsUsePremiumRate == true)
{
model.CompensationIncome = trade.trade_barrier_option.RebateRate ?? 0;
model.CompensationIncome2 = trade.trade_barrier_option.RebateHighRate ?? 0;
model.CompensationIncomeSymbol = "2";
model.CompensationIncomeCurrency = null;
}
else
{
model.CompensationIncome = trade.trade_barrier_option.Rebate ?? 0;
model.CompensationIncome2 = trade.trade_barrier_option.RebateHigh ?? 0;
model.CompensationIncomeSymbol = "1";
}
}
}
break;
case "SA":
case "GSA":
if (trade.trade_snowball != null)
{
double? saKOPrice, saKIPrice;
saKOPrice = trade.trade_snowball.KOBarrier;
//敲出障碍价
if (!string.IsNullOrEmpty(trade.trade_snowball.KOObservationDates))
{
var saKoResult = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.KOObservationDates);
if (saKoResult.Item2 != null)
{
var latestKOObservationDate = saKoResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault();
saKOPrice = saKoResult.Item2[GetDateIndex(saKoResult.Item1, latestKOObservationDate)];
}
}
//敲入障碍价
saKIPrice = trade.trade_snowball.KIBarrier;
if (!string.IsNullOrEmpty(trade.trade_snowball.ObservationDates))
{
var saKiResult = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_snowball.ObservationDates);
if (saKiResult.Item2 != null)
{
var latestKIObservationDate = saKiResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault();
saKIPrice = saKiResult.Item2[GetDateIndex(saKiResult.Item1, latestKIObservationDate)];
}
}
if (trade.trade_snowball.KIPayoffType != 0)
{
model.KnockInBarrierPrice = saKIPrice;
if (model.trade.IsMoneynessOption == "是")
{
model.KnockInBarrierPrice = saKIPrice * trade.SpotPrice;
}
}
model.KnockOutBarrierPrice = saKOPrice;
if (model.trade.IsMoneynessOption == "是")
{
model.KnockOutBarrierPrice = saKOPrice * trade.SpotPrice;
}
if (model.GuaranteedIncomeSymbol == "2")
{
model.CouponAnnualRate = trade.trade_snowball.KORebate + (model.GuaranteedIncome ?? 0);
}
else
{
model.CouponAnnualRate = trade.trade_snowball.KORebate + ((trade.OriginalPrincipalSum ?? 0) / trade.StockEqvNotional);
}
//雪球敲出时,判断敲出日期是否小杨到期日,是的话,提前终止日期需赋值
if (!string.IsNullOrEmpty(trade.trade_snowball.KnockInOutStatus) && (trade.trade_snowball.KnockInOutStatusCn.Contains("敲出") || trade.trade_snowball.KnockInOutStatus.ToLower().Contains("out")))
{
if (trade.trade_snowball.KnockInOutDate < model.EndDate)
{
model.UnWindDate = trade.trade_snowball.KnockInOutDate;
}
}
}
break;
case "PA":
if (trade.trade_autocall != null)
{
double? paKOPrice, paKIPrice, paCoupon, couponRate;
paKOPrice = trade.trade_autocall.KOBarrier;
paCoupon = trade.trade_autocall.CouponBarrier;
couponRate = trade.trade_autocall.Coupon;
//敲出障碍价、Coupon障碍价
if (!string.IsNullOrEmpty(trade.trade_autocall.KOObservationDates))
{
var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(trade.trade_autocall.KOObservationDates, trade.trade_autocall.CouponBarrier);
var paKoResult = QdpHelper.ParseAutocallCustomizedInfoV3(ko.Item2);
//敲出观察频率
if (paKoResult.Item2 != null)
{
var latestKOObservationDate = paKoResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault();
paKOPrice = paKoResult.Item2[GetDateIndex(paKoResult.Item1, latestKOObservationDate)];
}
//票息观察频率
var CouponKoResult = QdpHelper.ParseAutocallCustomizedInfo(ko.Item1);
if (CouponKoResult.Item3 != null)
{
var latestKOObservationDate = CouponKoResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault();
couponRate = CouponKoResult.Item3[GetDateIndex(CouponKoResult.Item1, latestKOObservationDate)];
}
}
//敲入障碍价
paKIPrice = trade.trade_autocall.KIBarrier;
if (!string.IsNullOrEmpty(trade.trade_autocall.ObservationDates))
{
var paKiResult = QdpHelper.ParseAutocallCustomizedInfo(trade.trade_autocall.ObservationDates);
if (paKiResult.Item2 != null)
{
var latestKIObservationDate = paKiResult.Item1.Where(x => x.DateTime >= model.ValueDate).OrderBy(x => x.DateTime).FirstOrDefault();
paKIPrice = paKiResult.Item2[GetDateIndex(paKiResult.Item1, latestKIObservationDate)];
}
}
model.KnockInBarrierPrice = paKIPrice;
model.KnockOutBarrierPrice = paKOPrice;
model.CouponBarrierPrice = paCoupon;
if (model.trade.IsMoneynessOption == "是")
{
model.KnockInBarrierPrice = paKIPrice * trade.SpotPrice;
model.KnockOutBarrierPrice = paKOPrice * trade.SpotPrice;
model.CouponBarrierPrice = paCoupon * trade.SpotPrice;
}
if (model.GuaranteedIncomeSymbol == "2")
{
model.CouponAnnualRate = couponRate + (model.GuaranteedIncome ?? 0);
}
else
{
model.CouponAnnualRate = couponRate + (trade.OriginalPrincipalSum / trade.SpotPrice);
}
//凤凰敲出时,判断敲出日期是否小杨到期日,是的话,提前终止日期需赋值
if (!string.IsNullOrEmpty(trade.trade_autocall.KnockInOutStatus) && (trade.trade_autocall.KnockInOutStatusCn.Contains("敲出") || trade.trade_autocall.KnockInOutStatus.ToLower().Contains("out")))
{
if (trade.trade_autocall.KnockInOutDate < model.EndDate)
{
model.UnWindDate = trade.trade_autocall.KnockInOutDate;
}
}
}
break;
}
}
/// <summary>
/// 设置远期结构的字段
/// </summary>
/// <param name="model"></param>
private void setForwardFields(SuperviseReportBaseModel model)
{
var trade = model.trade;
model.ForwardPrice = trade.Strike;
model.ForwardPriceCurrency = "CNY";
model.ForwardPriceSymbol = "1";
//保底收益
if (model.GuaranteedIncome == null)
{
model.GuaranteedIncome = 0;
model.GuaranteedIncomeSymbol = "1";
model.GuaranteedIncomeCurrency = "CNY";
}
}
/// <summary>
/// 设置互换结构的字段
/// </summary>
/// <param name="model"></param>
private void setSwapFields(SuperviseReportBaseModel model)
{
var trade = model.trade;
var tSwap = trade.trade_swap;
model.FixedIncomeCurrency = "CNY";
if (tSwap.IsGetFloatingProfit)
{
if (tSwap.GetLongShort == "多头")
{
model.FloatingDirection = "1";
}
else
{
model.FloatingDirection = "2";
}
}
else
{
model.FixedIncome = tSwap.GetSwapRate;
model.FixedIncomeSymbol = "2";
model.FixedIncomeCurrency = null;
}
if (tSwap.IsPayFloatingProfit)
{
if (tSwap.PayLongShort == "多头")
{
model.FloatingDirection = "1";
}
else
{
model.FloatingDirection = "2";
}
}
else
{
model.FixedIncome = tSwap.PaySwapRate;
model.FixedIncomeSymbol = "2";
model.FixedIncomeCurrency = null;
}
//互换交易,设置了互换利率的话,固定收益又没设置,就读取互换利率的最后一个
if (model.FixedIncome <= 0)
{
if (!string.IsNullOrEmpty(tSwap.GetSwapTimeAndRate))
{
var swapTiamAndRateArr = tSwap.GetSwapTimeAndRate.Split(';');
if (swapTiamAndRateArr.Length >= 1)
{
var swapRateArr = swapTiamAndRateArr[1]?.Split(',');
model.FixedIncome = double.Parse(swapRateArr[swapRateArr.Length - 1]);
model.FixedIncomeSymbol = "2";
}
}
}
}
/// <summary>
/// 自定义字段结构不为空时,处理自定义字段报送
/// </summary>
/// <param name="item"></param>
private void formatExtendInfo(SuperviseReportBaseModel item)
{
var stInfo = DbContext.Structure_Info.FirstOrDefault(n => n.StructureName == item.StructureType);
if (stInfo == null)
{
return;
}
item.OptionProductStructure = string.IsNullOrWhiteSpace(stInfo.StructureTypeSm) ? "O" : stInfo.StructureTypeSm;
var stDetail = DbContext.Structure_Details.Where(n => n.StructureId == stInfo.id).ToList();
if (stDetail.Count == 0)
{
return;
}
formatCustomProductStructure(item, stInfo, stDetail);
}
/// <summary>
/// 自定义结构初始化
/// </summary>
/// <param name="item"></param>
/// <param name="structure"></param>
/// <param name="structureDetail"></param>
private void formatCustomProductStructure(SuperviseReportBaseModel model, Structure_Info structure, List<Structure_Details> structureDetail)
{
var sdInfoList = JsonHelper.Deserialize<List<StructureDetailInfo>>(model.ExtendInfo);
string v1, v2, v3, v4, v5, v6, v7, v8, v9, v10;
switch (structure.StructureTypeSm)
{
case "DI":
case "RA":
case "AC":
v1 = GetCustomVal(structureDetail, sdInfoList, "行权收益1");
v2 = GetCustomVal(structureDetail, sdInfoList, "行权收益2");
v3 = GetCustomVal(structureDetail, sdInfoList, "行权收益3");
v4 = GetCustomVal(structureDetail, sdInfoList, "行权收益货币");
v5 = GetCustomVal(structureDetail, sdInfoList, "行权收益符号");
if (!string.IsNullOrEmpty(v1))
{
model.ExerciseBenefits = NumericalProcessing(v1, out var isPercentage);
}
if (!string.IsNullOrEmpty(v2))
{
model.ExerciseBenefits2 = NumericalProcessing(v2, out var isPercentage);
}
if (!string.IsNullOrEmpty(v3))
{
model.ExerciseBenefits3 = NumericalProcessing(v3, out var isPercentage);
}
if (!string.IsNullOrEmpty(v4))
{
model.ExerciseBenefitsCurrency = v4;
}
if (!string.IsNullOrEmpty(v5))
{
model.ExerciseBenefitsSymbol = v5;
}
break;
case "DSF":
case "SKI":
case "SF":
v1 = GetCustomVal(structureDetail, sdInfoList, "障碍价1");
v2 = GetCustomVal(structureDetail, sdInfoList, "障碍价1触碰方向");
v3 = GetCustomVal(structureDetail, sdInfoList, "障碍价1类型");
v4 = GetCustomVal(structureDetail, sdInfoList, "障碍价2");
v5 = GetCustomVal(structureDetail, sdInfoList, "障碍价2触碰方向");
v6 = GetCustomVal(structureDetail, sdInfoList, "障碍价2类型");
v7 = GetCustomVal(structureDetail, sdInfoList, "补偿收益1");
v8 = GetCustomVal(structureDetail, sdInfoList, "补偿收益2");
v9 = GetCustomVal(structureDetail, sdInfoList, "补偿收益货币");
v10 = GetCustomVal(structureDetail, sdInfoList, "补偿收益符号");
if (!string.IsNullOrEmpty(v1))
{
model.BarriersPrice = NumericalProcessing(v1, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.BarriersPrice = model.BarriersPrice * model.trade.OriginalStockEqvNotional;
}
}
else
{
model.BarriersPrice = null;
}
if (!string.IsNullOrEmpty(v2))
{
model.BarriersPriceTouchDirection = getCustomBarriersFiled(v2);
}
if (!string.IsNullOrEmpty(v3))
{
model.BarriersPriceType = getCustomBarriersFiled(v3);
}
if (!string.IsNullOrEmpty(v4))
{
model.BarriersPrice2 = NumericalProcessing(v4, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.BarriersPrice2 = model.BarriersPrice2 * model.trade.OriginalStockEqvNotional;
}
}
else
{
model.BarriersPrice2 = null;
}
if (!string.IsNullOrEmpty(v5))
{
model.BarriersPrice2TouchDirection = getCustomBarriersFiled(v5);
}
if (!string.IsNullOrEmpty(v6))
{
model.BarriersPrice2Type = getCustomBarriersFiled(v6);
}
if (!string.IsNullOrEmpty(v7))
{
model.CompensationIncome = NumericalProcessing(v7, out var isPercentage);
}
else
{
model.CompensationIncome = null;
}
if (!string.IsNullOrEmpty(v8))
{
model.CompensationIncome2 = NumericalProcessing(v8, out var isPercentage);
}
else
{
model.CompensationIncome2 = null;
}
if (!string.IsNullOrEmpty(v9))
{
model.CompensationIncomeCurrency = v9;
}
if (!string.IsNullOrEmpty(v10))
{
model.CompensationIncomeSymbol = v10;
}
break;
case "SA":
case "GSA":
case "PA":
v1 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-敲入障碍价");
v2 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-敲入观察期");
v3 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-敲出障碍价");
v4 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-Coupon障碍价");
v5 = GetCustomVal(structureDetail, sdInfoList, "SA&PA-Coupon年化收益率");
if (!string.IsNullOrEmpty(v1))
{
model.KnockInBarrierPrice = NumericalProcessing(v1, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.KnockInBarrierPrice = model.KnockInBarrierPrice * model.trade.OriginalStockEqvNotional;
}
}
else
{
model.KnockInBarrierPrice = null;
}
if (!string.IsNullOrEmpty(v2))
{
model.KnockInObservationPeriod = v2;
}
if (!string.IsNullOrEmpty(v3))
{
model.KnockOutBarrierPrice = NumericalProcessing(v3, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.KnockOutBarrierPrice = model.KnockOutBarrierPrice * model.trade.OriginalStockEqvNotional;
}
}
else
{
model.KnockOutBarrierPrice = null;
}
if (!string.IsNullOrEmpty(v4))
{
model.CouponBarrierPrice = NumericalProcessing(v4, out var isPercentage);
}
else
{
model.CouponBarrierPrice = null;
}
if (!string.IsNullOrEmpty(v5))
{
model.CouponAnnualRate = NumericalProcessing(v5, out var isPercentage);
}
else
{
model.CouponAnnualRate = null;
}
break;
}
#region 黑箱自定义基础字段
string customObserveType, customObserveStartDate, customObserveEndDate,
customObservationPeriod, customObservePeriodMultiplier, customRevenueCalculationMethod,
customGuaranteedIncome, customGuaranteedIncomeCurrency, customGuaranteedIncomeSymbol,
customStrike1, customStrike2, customStrike3, customStrikeCurrency, customStrikeSymbol,
customExerciseMode, customOptionType, customExerciseDate, customValidDays;
customExerciseMode = GetCustomVal(structureDetail, sdInfoList, "期权行权时间类型");
customOptionType = GetCustomVal(structureDetail, sdInfoList, "期权权利类型");
customExerciseDate = GetCustomVal(structureDetail, sdInfoList, "行权日");
customStrike1 = GetCustomVal(structureDetail, sdInfoList, "执行价格1");
customStrike2 = GetCustomVal(structureDetail, sdInfoList, "执行价格2");
customStrike3 = GetCustomVal(structureDetail, sdInfoList, "执行价格3");
customStrikeCurrency = GetCustomVal(structureDetail, sdInfoList, "执行价格货币");
customStrikeSymbol = GetCustomVal(structureDetail, sdInfoList, "执行价格符号");
customObserveType = GetCustomVal(structureDetail, sdInfoList, "观察类型");
customObserveStartDate = GetCustomVal(structureDetail, sdInfoList, "观察起始日");
customObserveEndDate = GetCustomVal(structureDetail, sdInfoList, "观察结束日");
customObservationPeriod = GetCustomVal(structureDetail, sdInfoList, "观察周期");
customObservePeriodMultiplier = GetCustomVal(structureDetail, sdInfoList, "观察周期乘数");
customRevenueCalculationMethod = GetCustomVal(structureDetail, sdInfoList, "收益计算方式");
customGuaranteedIncome = GetCustomVal(structureDetail, sdInfoList, "保底收益");
customGuaranteedIncomeCurrency = GetCustomVal(structureDetail, sdInfoList, "保底收益货币");
customGuaranteedIncomeSymbol = GetCustomVal(structureDetail, sdInfoList, "保底收益符号");
customValidDays = GetCustomVal(structureDetail, sdInfoList, "一年有效天数");
if (!string.IsNullOrEmpty(customValidDays))
{
model.ValidDaysStr = customValidDays;
}
if (!string.IsNullOrEmpty(customExerciseMode))
{
model.ExerciseMode = getCustomExerciseMode(customExerciseMode);
}
else
{
model.ExerciseMode = null;
}
if (!string.IsNullOrEmpty(customOptionType))
{
model.OptionType = getCustomOptionType(customOptionType);
}
else
{
model.OptionType = null;
}
if (!string.IsNullOrEmpty(customExerciseDate))
{
model.ExerciseDate = DateTime.Parse(customExerciseDate);
}
else
{
model.ExerciseDate = null;
}
if (!string.IsNullOrEmpty(customStrike1))
{
model.Strike = NumericalProcessing(customStrike1, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.Strike = ((model.Strike * model.trade.SpotPrice) ?? 0);
}
}
else
{
model.Strike = null;
}
if (!string.IsNullOrEmpty(customStrike2))
{
model.Strike2 = NumericalProcessing(customStrike2, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.Strike2 = ((model.Strike2 * model.trade.SpotPrice) ?? 0);
}
}
else
{
model.Strike2 = null;
}
if (!string.IsNullOrEmpty(customStrike3))
{
model.Strike3 = NumericalProcessing(customStrike3, out var isPercentage);
if (model.trade.IsMoneynessOption == "是" && isPercentage)
{
model.Strike3 = ((model.Strike3 * model.trade.SpotPrice) ?? 0);
}
}
else
{
model.Strike3 = null;
}
if (!string.IsNullOrEmpty(customStrikeCurrency))
{
model.StrikeCurrency = customStrikeCurrency;
}
else if (model.Strike != null)
{
if (model.UnderlyingInitialPriceSymbol == "1")
{
model.StrikeCurrency = "CNY";
}
}
else
{
model.StrikeCurrency = null;
}
if (!string.IsNullOrEmpty(customStrikeSymbol))
{
model.StrikeSymbol = customStrikeSymbol;
}
else if (model.Strike != null)
{
model.StrikeSymbol = model.UnderlyingInitialPriceSymbol;
}
else
{
model.StrikeSymbol = null;
}
if (!string.IsNullOrEmpty(customObserveType))
{
model.ObserveType = getCustomObType(customObserveType).ToUpper();
}
if (!string.IsNullOrEmpty(customObserveStartDate))
{
model.ObserveStartDate = DateTime.Parse(customObserveStartDate);
}
if (!string.IsNullOrEmpty(customObserveEndDate))
{
model.ObserveEndDate = DateTime.Parse(customObserveEndDate);
}
if (!string.IsNullOrEmpty(customObservationPeriod))
{
model.ObservationPeriod = getCustomOBPeriod(customObservationPeriod).ToUpper();
}
if (!string.IsNullOrEmpty(customObservePeriodMultiplier))
{
model.ObservePeriodMultiplier = NumericalProcessing(customObservePeriodMultiplier, out var isPercentage);
}
else
{
model.ObservePeriodMultiplier = null;
}
if (!string.IsNullOrEmpty(customRevenueCalculationMethod))
{
model.RevenueCalculationMethod = getCustomRCMethod(customRevenueCalculationMethod).ToUpper();
}
if (!string.IsNullOrEmpty(customGuaranteedIncome))
{
model.GuaranteedIncome = NumericalProcessing(customGuaranteedIncome, out _);
}
else
{
model.GuaranteedIncome = null;
}
if (!string.IsNullOrEmpty(customGuaranteedIncomeSymbol))
{
model.GuaranteedIncomeSymbol = customGuaranteedIncomeSymbol;
}
else if (model.GuaranteedIncome != null)
{
model.GuaranteedIncomeSymbol = "1";
}
else
{
model.GuaranteedIncomeSymbol = null;
}
if (!string.IsNullOrEmpty(customGuaranteedIncomeCurrency))
{
model.GuaranteedIncomeCurrency = customGuaranteedIncomeCurrency;
}
else if (!string.IsNullOrWhiteSpace(model.GuaranteedIncomeSymbol) && model.GuaranteedIncomeSymbol == "1")
{
model.GuaranteedIncomeCurrency = "CNY";
}
else
{
model.GuaranteedIncomeCurrency = null;
}
#endregion
}
/// <summary>
/// 关联获取数据
/// </summary>
/// <param name="structureDetail"></param>
/// <param name="sdInfoList"></param>
/// <param name="FieldNameSm"></param>
/// <returns></returns>
private string GetCustomVal(List<Structure_Details> structureDetail, List<StructureDetailInfo> sdInfoList, string FieldNameSm)
{
var query = (from sd in sdInfoList
join std in structureDetail on sd.name.ToLower() equals std.ColumnName.ToLower()
where (!string.IsNullOrWhiteSpace(std.FieldNameSm) && std.FieldNameSm == FieldNameSm) || (string.IsNullOrWhiteSpace(std.FieldNameSm) && std.ColumnName == FieldNameSm)
select sd).FirstOrDefault();
return query == null ? "" : query.value;
}
/// <summary>
/// 数值处理
/// </summary>
/// <param name="inpVal"></param>
/// <returns></returns>
private double NumericalProcessing(string inpVal, out bool isPercentage)
{
double resultVal = 0;
isPercentage = false;
if (inpVal.IndexOf(',') >= 0)
{
inpVal = inpVal.Replace(",", "");
}
if (inpVal.EndsWith("%"))
{
isPercentage = true;
inpVal = inpVal.Replace("%", "");
}
resultVal = Convert.ToDouble(inpVal);
if (isPercentage)
{
resultVal = resultVal / 100;
}
return resultVal;
}
private string getCustomObType(string input)
{
switch (input)
{
case "离散":
case "离散观察":
return "DISCRETE";
case "连续":
case "连续观察":
return "CONTINUOUS";
case "到期":
case "到期观察":
return "TERMINAL";
default: return input;
}
}
private string getCustomOBPeriod(string inputVal)
{
switch (inputVal)
{
case "日度":
case "D":
case "d":
return "DAIL";
case "周度":
case "W":
case "w":
return "WEEK";
case "月度":
case "M":
case "m":
return "MNTH";
case "年度":
case "Y":
case "y":
return "YEAR";
default: return inputVal;
}
}
private string getCustomRCMethod(string input)
{
switch (input)
{
case "递延至期末支付":
return "EXPIRY";
case "即期计算":
case "立即支付":
return "HIT";
default: return input;
}
}
private string getCustomBarriersFiled(string input)
{
switch (input)
{
case "向上":
return "Up";
case "向下":
return "Down";
case "敲入":
return "In";
case "敲出":
return "Out";
default: return input;
}
}
/// <summary>
/// 黑箱自定义期权行权时间类型
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private string getCustomExerciseMode(string input)
{
switch (input)
{
case "欧式":
return "EU";
case "美式":
return "US";
case "百慕大":
return "BD";
case "其他":
return "O";
default: return input;
}
}
/// <summary>
/// 黑箱自定义期权权利类型
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
private string getCustomOptionType(string input)
{
switch (input.ToLower())
{
case "put":
case "看跌":
return "1";
case "call":
case "看涨":
return "2";
case "chooser":
return "3";
case "其他":
case "价差":
return "9";
default: return input;
}
}
private int GetDateIndex(Date[] source, Date value)
{
var index = 0;
foreach (var item in source)
{
if (item.DateTime == value.DateTime)
{
return index;
}
index++;
}
return -1;
}
}
}