731 lines
41 KiB
C#
731 lines
41 KiB
C#
using BaseOUDAL;
|
|
using YLErp.BLL;
|
|
using YLErp.Commons;
|
|
using YLErp.Configuration;
|
|
using YLErp.DBModels.Consts;
|
|
using YLErp.Helpers;
|
|
using YLErp.Model;
|
|
using YLErp.Modules.ClientModule;
|
|
using YLErp.Modules.SuperviseReportModule.CFMMC.Model;
|
|
using YLErp.Modules.TradeModule;
|
|
using YLErp.QdpModule;
|
|
using static YLErp.ConsGlobal;
|
|
|
|
namespace YLErp.Modules.SuperviseReportModule.CFMMC.Service
|
|
{
|
|
public class SuperviseReportPositionService : SuperviseReportBaseService
|
|
{
|
|
private string _volType { get; set; }
|
|
public SuperviseReportPositionService(SuperviseReportReq req, OptUserInfo userInfo) : base(req, userInfo)
|
|
{
|
|
var arr = req.DataSource?.Split(',') ?? new string[2];
|
|
_volType = arr[0];
|
|
req.DataSource = arr[1];
|
|
}
|
|
|
|
private SearchListResult<SuperviseReportPositionModel> ReportQuery(SuperviseReportReq req)
|
|
{
|
|
var commodityList = new List<string> { InstrumentType.CommodityFutures, InstrumentType.CommoditySpot };
|
|
var umQuery = DbContext.underlying_manager.AsQueryable();
|
|
switch (req.DataSource)
|
|
{
|
|
case "权益":
|
|
umQuery = umQuery.Where(O => !commodityList.Contains(O.UnderlyingInstrumentType));
|
|
break;
|
|
case "商品":
|
|
umQuery = umQuery.Where(O => commodityList.Contains(O.UnderlyingInstrumentType));
|
|
break;
|
|
case "全量":
|
|
default:
|
|
break;
|
|
}
|
|
|
|
var insidedClientIds = DataCacheProvider.GetClientDataSource().AsQueryable().Where(O => O.IsInsided == 1).Select(O => O.id).ToList();
|
|
var tId = DbContext.eod_trade_position.Where(O => !insidedClientIds.Contains(O.ClientId) && O.ValueDate == req.ValueDate && (O.TradeType.EndsWith("期权") || O.TradeType == "远期" || O.TradeType == "收益互换" || O.TradeType == "自定义交易" || O.TradeType == "气囊结构") && O.TradeType != "场内期权" && O.TradeId != 0).Select(O => O.TradeId);
|
|
var query = from eodTrade in DbContext.eod_trade
|
|
join trade in DbContext.trade on eodTrade.TradeId equals trade.id
|
|
join um in umQuery on trade.UnderlyingCode equals um.UnderlyingCode
|
|
where eodTrade.ValueDate == req.ValueDate && (tId.Contains(eodTrade.TradeId) || trade.IsGroup == 1) && trade.IsGroup != 2 && trade.TradeType != "现金流交易" && eodTrade.ClientId != 0 && ConsTrade.LiveTradeStatusList.Contains(eodTrade.TradeStatus)
|
|
select new SuperviseReportPositionModel
|
|
{
|
|
PositionDate = eodTrade.ValueDate,
|
|
TradeId = eodTrade.TradeId,
|
|
ClientId = eodTrade.ClientId,
|
|
UnderlyingCode = eodTrade.UnderlyingCode,
|
|
ParentTradeId = eodTrade.ParentTradeId,
|
|
TradeStatus = eodTrade.TradeStatus,
|
|
OriginalTradeNumber = eodTrade.TradeNumber,
|
|
TradeJson = eodTrade.TradeJson,
|
|
ValuationMethod = "O",
|
|
UnwindPercentRate = 0,
|
|
QuoteCurrency = "CNY",
|
|
ForeignCurrencyRate = null,
|
|
IsAnnualTrade = "N",
|
|
PriceSymbol = 1,
|
|
ParticipateRate = 1,
|
|
IsGroup = trade.IsGroup
|
|
};
|
|
|
|
var clientcontext = new ClientDBContext();
|
|
var clientids = query.Select(x => x.ClientId).Distinct().ToArray();
|
|
var clients = clientcontext.client.Where(x => clientids.Contains(x.id) && x.IsInsided != 1).Select(x => x.id).ToArray();
|
|
|
|
query = query.Where(x => clients.Contains(x.ClientId)).OrderBy(O => O.OriginalTradeNumber);
|
|
var retListResult = query.ToSearchList(req, false);
|
|
return retListResult;
|
|
}
|
|
|
|
public SearchListResult<SuperviseReportPositionModel> SearchReportList()
|
|
{
|
|
SearchListResult<SuperviseReportPositionModel> retListResult = null;
|
|
using (var basedb = new ErpBaseContext())
|
|
{
|
|
IQueryable<EodTradeRisk> etr = null;
|
|
IQueryable<EodTradePosition> etp = null;
|
|
switch (_volType)
|
|
{
|
|
case "开仓":
|
|
etr = DbContext.eod_trade_risk_openvol.Where(O => O.ValueDate == _req.ValueDate);
|
|
etp = DbContext.eod_trade_position_openvol.Where(O => O.ValueDate == _req.ValueDate);
|
|
break;
|
|
case "持仓":
|
|
default:
|
|
etr = DbContext.eod_trade_risk.Where(O => O.ValueDate == _req.ValueDate);
|
|
etp = DbContext.eod_trade_position.Where(O => O.ValueDate == _req.ValueDate);
|
|
break;
|
|
}
|
|
if (!etp.Any())
|
|
{
|
|
throw new ServiceException("数据不存在");
|
|
}
|
|
retListResult = ReportQuery(_req);
|
|
var ignoreTradeTypes = new List<string>()
|
|
{
|
|
"远期",
|
|
"收益互换",
|
|
"掉期",
|
|
};
|
|
|
|
var varietyTypeList = (from i in basedb.DictionaryItems join d in basedb.Dictionaries on i.DictId equals d.Id where d.Name == "品种类型" select i).ToList();
|
|
var assetTypeList = (from i in basedb.DictionaryItems join d in basedb.Dictionaries on i.DictId equals d.Id where d.Name == "资产类型" select i).ToList();
|
|
var varietySuffixList = (from i in basedb.DictionaryItems join d in basedb.Dictionaries on i.DictId equals d.Id where d.Name == "标的资产后缀" select i).ToList();
|
|
var varietyCodeList = (from i in basedb.DictionaryItems join d in basedb.Dictionaries on i.DictId equals d.Id where d.Name == "标的对应资产品种" select i).ToList();
|
|
try
|
|
{
|
|
var config = DbContext.valuedate.FirstOrDefault(x => x.State == valuedate.当前使用);
|
|
var tIdArr = retListResult.rows.Select(O => O.TradeId);
|
|
Dictionary<int, EodTradePosition> ePnlInfos = null;
|
|
Dictionary<int, EodTradeRisk> eRiskInfos = null;
|
|
var func = new Func<EodTradeRisk, EodTradeRisk>(O => new EodTradeRisk
|
|
{
|
|
TradeId = O.TradeId,
|
|
Delta = O.Delta,
|
|
DeltaCash = O.DeltaCash,
|
|
GammaCash = O.GammaCash,
|
|
Theta = O.Theta,
|
|
Gamma = O.Gamma,
|
|
Rho = O.Rho,
|
|
Vega = O.Vega,
|
|
Vol = O.Vol,
|
|
OtherRisks = O.OtherRisks
|
|
});
|
|
ePnlInfos = etp.Where(O => tIdArr.Contains(O.TradeId)).Select(O => new EodTradePosition { TradeId = O.TradeId, Pv = O.Pv, Margin = O.Margin }).ToDictionary(K => K.TradeId, V => V);
|
|
eRiskInfos = etr.Where(O => tIdArr.Contains(O.TradeId)).Select(func).AsEnumerable().GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.First());
|
|
|
|
var clientIdArr = retListResult.rows.Select(O => O.ClientId);
|
|
//var clientInfos = DbContext.client.Where(O => clientIdArr.Contains(O.id)).Select(O => new { O.id, O.Name, O.LicenseCode }).ToDictionary(K => K.id, V => V);
|
|
var ptIdArr = retListResult.rows.Where(O => O.ParentTradeId != null).Select(O => O.ParentTradeId).ToHashSet();
|
|
var ptInfos = DbContext.trade.Where(O => ptIdArr.Contains(O.id)).Select(O => new { O.id, O.TradeType, O.StructureType, O.TradeNumber }).ToDictionary(K => K.id, V => V);
|
|
var tcRInfos = new Dictionary<int, string>();
|
|
var tmInfos = new Dictionary<int, string>();
|
|
switch (PS.Config.Company)
|
|
{
|
|
case Configuration.CompanyEnum.长江:
|
|
tcRInfos = DbContext.trade_contract_r.Where(O => (tIdArr.Contains(O.TradeId) || ptIdArr.Contains(O.TradeId)) && O.Type == ContractTypeEnum.Trade && O.IsValid).Select(O => new { O.TradeId, O.ContractCode }).AsEnumerable().GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.FirstOrDefault().ContractCode);
|
|
tmInfos = DbContext.TradeMeta.Where(O => (tIdArr.Contains(O.TradeId) || ptIdArr.Contains(O.TradeId)) && O.MetaKey == ConsTradeMetaKey.ContractCode).ToDictionary(K => K.TradeId, V => V.MetaValue);
|
|
break;
|
|
case Configuration.CompanyEnum.浙期:
|
|
tmInfos = DbContext.TradeMeta.Where(O => (tIdArr.Contains(O.TradeId) || ptIdArr.Contains(O.TradeId)) && O.MetaKey == ConsTradeMetaKey.ContractCode).ToDictionary(K => K.TradeId, V => V.MetaValue);
|
|
break;
|
|
}
|
|
var dbTradeMeta = DbContext.TradeMeta.Where(O => (tIdArr.Contains(O.TradeId) || ptIdArr.Contains(O.TradeId))).ToList();
|
|
var obsvitionInfos = dbTradeMeta.Where(O => (O.MetaKey == ConsTradeMetaKey.ObservationRemark1 || O.MetaKey == ConsTradeMetaKey.ObservationRemark2)).ToList();
|
|
var tbInfos = DbContext.trade_binary_option.Where(O => tIdArr.Contains(O.TradeId)).Select(O => new { O.TradeId, O.PayoffType }).ToDictionary(K => K.TradeId, V => V.PayoffType);
|
|
var clientMetaQuery = DbContextFactory.GetClientDbContext(UserInfo).ClientMeta.Where(O => clientIdArr.Contains(O.ClientId));
|
|
var clientReportInfo = clientMetaQuery.Where(O => O.MetaKey == "ReportName").ToDictionary(K => K.ClientId, V => V.MetaValue);
|
|
foreach (var item in retListResult.rows)
|
|
{
|
|
|
|
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(item.UnderlyingCode);
|
|
var variety = DataCacheProvider.GetVarietyDataSource().GetData(um.UnderlyingTypeId);
|
|
//clientInfos.TryGetValue(item.ClientId, out var client);
|
|
var client = ClientDataQueryService.GetClient(item.ClientId);
|
|
ptInfos.TryGetValue(item.ParentTradeId ?? 0, out var parentTrade);
|
|
tbInfos.TryGetValue(item.TradeId, out var payoffType);
|
|
ePnlInfos.TryGetValue(item.TradeId, out var positionInfo);
|
|
_priceProvider.TryGetPrice(item.UnderlyingCode, out var price);
|
|
eRiskInfos.TryGetValue(item.TradeId, out var eRisk);
|
|
|
|
var metaModel = dbTradeMeta.Where(m => m.TradeId == item.TradeId && m.MetaKey == "ExchangeRate").OrderByDescending(m => m.CreateTime).FirstOrDefault();
|
|
if (!string.IsNullOrEmpty(variety.QuoteCurrency) && variety.QuoteCurrency != "CNY")
|
|
{
|
|
item.QuoteCurrency = variety.QuoteCurrency;
|
|
item.ForeignCurrencyRate = double.TryParse(metaModel?.MetaValue, out double meta) ? meta : item.ForeignCurrencyRate;
|
|
}
|
|
|
|
item.OriginalVarietyCode = variety.VarietyCode;
|
|
item.MainName = config.SuperviseMainName;
|
|
item.MainCode = config.SuperviseMainCode;
|
|
item.ClientName = clientReportInfo.TryGetValue(client.id, out var reportName) && !string.IsNullOrWhiteSpace(reportName) ? reportName : client.Name;
|
|
item.ClientLicenseCode = client?.LicenseCode;
|
|
item.PositionDate = _req.ValueDate;
|
|
item.TradeType = parentTrade?.TradeType ?? item.trade.TradeType;
|
|
item.StructureType = parentTrade?.StructureType ?? item.trade.StructureType;
|
|
item.PayoffType = payoffType ?? "";
|
|
if (item.TradeType == "远期" || item.TradeType == "收益互换")
|
|
{
|
|
item.ValuationMethod = "M";
|
|
}
|
|
switch (PS.Config.Company)
|
|
{
|
|
case Configuration.CompanyEnum.长江:
|
|
tcRInfos.TryGetValue(item.ParentTradeId ?? 0, out var pTcR);
|
|
tcRInfos.TryGetValue(item.TradeId, out var tcR);
|
|
tmInfos.TryGetValue(item.TradeId, out var tmValue);
|
|
tmInfos.TryGetValue(item.ParentTradeId ?? 0, out var ptmValue);
|
|
item.ContractCode = pTcR ?? tcR ?? ptmValue ?? tmValue ?? "";
|
|
break;
|
|
case Configuration.CompanyEnum.浙期:
|
|
tmInfos.TryGetValue(item.TradeId, out tmValue);
|
|
tmInfos.TryGetValue(item.ParentTradeId ?? 0, out ptmValue);
|
|
item.ContractCode = ptmValue ?? tmValue ?? parentTrade?.TradeNumber ?? item.OriginalTradeNumber;
|
|
item.OriginalTradeNumber = tmValue ?? item.OriginalTradeNumber;
|
|
|
|
|
|
|
|
|
|
|
|
var actualExerciseDate = DbContext.TradeMeta.Where(a => a.TradeId == item.TradeId && a.MetaKey == "ActualExerciseDate").FirstOrDefault()?.MetaValue;
|
|
if (!string.IsNullOrEmpty(actualExerciseDate) && DateTime.TryParse(actualExerciseDate,out DateTime newActualExerciseDate))
|
|
{
|
|
item.ExerciseDate = newActualExerciseDate;
|
|
}
|
|
|
|
|
|
|
|
break;
|
|
default:
|
|
item.ContractCode = parentTrade?.TradeNumber ?? item.OriginalTradeNumber;
|
|
break;
|
|
}
|
|
item.InitialSpotPrice = price.ToString();
|
|
item.Pv = (double)(positionInfo?.Pv ?? 0);
|
|
item.Vol = eRisk?.Vol ?? 0;
|
|
if (item.TradeType == "凤凰期权")
|
|
{
|
|
var autocall = item.trade.trade_autocall;
|
|
if (autocall.ObservationDates != null)
|
|
{
|
|
var ko = TradeObservationHelper.GetAutocallKOObservationAndCoupon(autocall.KOObservationDates, autocall.CouponBarrier);
|
|
var koarr = ko.Item2.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
|
|
item.KOObservationDates = koarr[0];
|
|
item.KOBarrier = koarr[1];
|
|
}
|
|
}
|
|
if (item.TradeType == "雪球期权")
|
|
{
|
|
item.SpotPrice = item.trade.SpotPrice ?? 0;
|
|
var snowball = item.trade.trade_snowball;
|
|
var koObservationList = QdpHelper.ParseAutocallCustomizedInfo(snowball.KOObservationDates);
|
|
var index = koObservationList.Item1?.Where(O => O.DateTime <= _req.ValueDate).Count() ?? 0;
|
|
if (koObservationList.Item1 != null)
|
|
{ index = koObservationList.Item1 == null || index < koObservationList.Item1.Length ? index : koObservationList.Item1.Length - 1; }
|
|
|
|
double[] koBarrier;
|
|
//国投 敲入观察价格,执行价格,敲出价格 处理两位小数
|
|
if (!item.trade.IsMoneynessOptionData && (PS.Config.Company == Configuration.CompanyEnum.国投 || PS.Config.Company == Configuration.CompanyEnum.浙期))
|
|
{
|
|
koBarrier = koObservationList.Item2?.Select(O => OtcFormatHelper.FormatValue(O, 2)).ToArray() ?? new double[0];
|
|
}
|
|
else
|
|
{
|
|
koBarrier = koObservationList.Item2?.Select(O => OtcFormatHelper.FormatValue(O, 6)).ToArray() ?? new double[0];
|
|
}
|
|
var kiBarrier = snowball.KIBarrier;
|
|
if (item.trade.IsMoneynessOptionData)
|
|
{
|
|
if (PS.Config.Company == Configuration.CompanyEnum.国投 || PS.Config.Company == Configuration.CompanyEnum.浙期)
|
|
{
|
|
koBarrier = koBarrier.Select(O => OtcFormatHelper.FormatValue(O * (item.trade.SpotPrice ?? 0), 2)).ToArray();
|
|
}
|
|
else
|
|
{
|
|
koBarrier = koBarrier.Select(O => OtcFormatHelper.FormatValue(O * (item.trade.SpotPrice ?? 0), 6)).ToArray();
|
|
}
|
|
kiBarrier *= item.trade.SpotPrice ?? 0;
|
|
}
|
|
|
|
item.SnowStatus = formatSnowStatus(snowball.KnockInOutStatus, koBarrier.Length > 0 ? koBarrier[index] : double.NaN, price);
|
|
item.SnowStructureInfo = formatSnowStructureType(item.SnowType, snowball.KIPayoffType, koObservationList.Item2 ?? new double[0]);
|
|
item.ClientType = formatClientType(client.id);
|
|
if (koObservationList.Item1?.Length > 0)
|
|
{
|
|
var remark = obsvitionInfos.Where(O => O.TradeId == item.trade.id && O.MetaKey == ConsTradeMetaKey.ObservationRemark2).FirstOrDefault();
|
|
if (remark == null || remark.MetaValue.IsNullOrWhiteSpace())
|
|
{
|
|
item.KOObservationDates = string.Join(";", koObservationList.Item1.Select(O => O.DateTime.ToString("yyyy-MM-dd")));
|
|
}
|
|
else
|
|
{
|
|
item.KOObservationDates = remark.MetaValue;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
item.KOObservationDates = "逐日";
|
|
}
|
|
item.KOBarrier = string.Join(";", koBarrier);
|
|
if (PS.Config.Company == CompanyEnum.国投)
|
|
{
|
|
item.KOBarrier = string.Join(";", koBarrier.Select(l => l.ToString("#.00")).ToArray());
|
|
}
|
|
if (snowball.KIPayoffType != KIPayoffTypeEnum.None && !snowball.IsInitialKnockedIn)
|
|
{
|
|
if (snowball.ObservationDates.IsNullOrWhiteSpace())
|
|
{
|
|
item.KIObservationDates = "逐日";
|
|
}
|
|
else
|
|
{
|
|
var remark = obsvitionInfos.Where(O => O.TradeId == item.trade.id && O.MetaKey == ConsTradeMetaKey.ObservationRemark1).FirstOrDefault();
|
|
if (remark == null || remark.MetaValue.IsNullOrWhiteSpace())
|
|
{
|
|
item.KIObservationDates = snowball.ObservationDates.Replace(",", ";");
|
|
}
|
|
else
|
|
{
|
|
item.KIObservationDates = remark.MetaValue;
|
|
}
|
|
}
|
|
if (PS.Config.Company == Configuration.CompanyEnum.浙期)
|
|
{
|
|
item.KIBarrier = OtcFormatHelper.FormatValue(kiBarrier, 2);
|
|
}
|
|
else
|
|
{
|
|
item.KIBarrier = kiBarrier;
|
|
}
|
|
}
|
|
|
|
item.PremiumRate = snowball.AnnualizedPremiumRate.HasValue ? snowball.AnnualizedPremiumRate?.ToString("0.######%") : item.trade.PremiumRate.HasValue ? item.trade.PremiumRate?.ToString("0.######%") : (item.trade.TradePrice / item.trade.OriginalStockEqvNotional)?.ToString("0.######%");
|
|
item.SnowType = formatSnowType2(item.trade, koObservationList.Item2);
|
|
|
|
if (snowball.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption || snowball.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
|
|
{
|
|
var strikeLow = Math.Abs((snowball.SpreadStrikeAtMaturity1 ?? 0) - (snowball.SpreadStrikeAtMaturity ?? 0));
|
|
if (PS.Config.Is浙期)
|
|
{
|
|
strikeLow = snowball.SpreadStrikeAtMaturity ?? 0;
|
|
item.PrincipalRate = ((item.trade.IsMoneynessOptionData ? strikeLow : strikeLow / item.trade.SpotPrice) ?? 0).ToString("0.######%");
|
|
}
|
|
else
|
|
{
|
|
item.PrincipalRate = ((1 - (item.trade.IsMoneynessOptionData ? strikeLow : strikeLow / item.trade.SpotPrice)) ?? 0).ToString("0.######%");
|
|
}
|
|
|
|
}
|
|
|
|
if (item.PrincipalRate == "0%")
|
|
{
|
|
item.PrincipalRate = null;
|
|
}
|
|
item.InitialMargin = formatInitCastClientPayable(item.trade);
|
|
item.PositionMargin = positionInfo?.Margin ?? 0;
|
|
item.RiskYield = (item.trade.NoRiskRate - item.trade.DividendRate).ToString();
|
|
item.Coupon = item.trade.trade_snowball.Coupon;
|
|
item.KOCoupon = item.trade.trade_snowball.KORebate;
|
|
item.KIPayoffType = formatKIPayoffType(item.trade.trade_snowball.KIPayoffType);
|
|
}
|
|
|
|
if (item.IsGroup == 1)
|
|
{
|
|
var childIds = DbContext.trade.Where(x => x.ParentTradeId == item.TradeId).Select(x => x.id);
|
|
var riskChilds = DbContext.eod_trade_risk.Where(x => childIds.Contains(x.TradeId) && x.ValueDate == _req.ValueDate).ToList();
|
|
item.Pv = riskChilds.Sum(x => x.Pv);
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.Delta = riskChilds.Sum(x => x.Delta / um.ContractSize).OtcFormat(OtcFormatFlag.greek);
|
|
}
|
|
else
|
|
{
|
|
item.Delta = riskChilds.Sum(x => x.Delta).OtcFormat(OtcFormatFlag.greek);
|
|
}
|
|
item.Vega = riskChilds.Sum(x => x.Vega);
|
|
item.Theta = riskChilds.Sum(x => x.Theta);
|
|
item.Rho = riskChilds.Sum(x => x.Rho) * 100;
|
|
item.DeltaCash = riskChilds.Sum(x => x.DeltaCash).OtcFormat(OtcFormatFlag.greek);
|
|
item.GammaCash = riskChilds.Sum(x => x.GammaCash);
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.InnerGamma = riskChilds.Sum(x => x.Gamma / um.ContractSize);
|
|
}
|
|
else
|
|
{
|
|
item.InnerGamma = riskChilds.Sum(x => x.Gamma);
|
|
}
|
|
}
|
|
else if (!ignoreTradeTypes.Contains(item.TradeType))
|
|
{
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.Delta = ((double)(eRisk?.Delta ?? 0) / um.ContractSize).OtcFormat(OtcFormatFlag.greek);
|
|
}
|
|
else
|
|
{
|
|
item.Delta = ((double)(eRisk?.Delta ?? 0)).OtcFormat(OtcFormatFlag.greek);
|
|
}
|
|
item.Vega = eRisk?.Vega ?? 0;
|
|
item.Theta = eRisk?.Theta ?? 0;
|
|
item.Rho = (eRisk?.Rho ?? 0) * 100;
|
|
item.DeltaCash = (eRisk?.DeltaCash ?? 0).OtcFormat(OtcFormatFlag.greek);
|
|
item.GammaCash = eRisk?.GammaCash ?? 0;
|
|
var otherRisks = JsonHelper.Parse<OtherRisks>(eRisk?.OtherRisks);
|
|
if (otherRisks == null || string.IsNullOrWhiteSpace(otherRisks.CrossGamma))
|
|
{
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.InnerGamma = (double)(eRisk?.Gamma / um.ContractSize ?? 0); ;
|
|
}
|
|
else
|
|
{
|
|
item.InnerGamma = (double)(eRisk?.Gamma ?? 0);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.CrossGamma = double.TryParse(otherRisks.CrossGamma, out var temp) ? (temp / um.ContractSize).OtcFormat(OtcFormatFlag.greek) : "";
|
|
}
|
|
else
|
|
{
|
|
item.CrossGamma = otherRisks.CrossGamma;
|
|
}
|
|
|
|
}
|
|
if (PS.Config.Company == Configuration.CompanyEnum.浙期 && item.SnowType != "2")
|
|
{
|
|
item.PrincipalRate = null;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.Delta = ((double)(eRisk?.Delta ?? 0) / um.ContractSize).OtcFormat(OtcFormatFlag.greek);
|
|
}
|
|
else
|
|
{
|
|
item.Delta = ((double)(eRisk?.Delta ?? 0)).OtcFormat(OtcFormatFlag.greek);
|
|
}
|
|
item.DeltaCash = (eRisk?.DeltaCash ?? 0).OtcFormat(OtcFormatFlag.greek);
|
|
item.GammaCash = eRisk?.GammaCash ?? 0;
|
|
if (PS.Config.Company == Configuration.CompanyEnum.浙期 && !string.IsNullOrWhiteSpace(item.trade.BasisUnderlyingCode))
|
|
{
|
|
if (item.SnowType != "2")
|
|
{
|
|
item.PrincipalRate = "";
|
|
}
|
|
item.Delta += "," + item.Delta;
|
|
item.DeltaCash += "," + item.DeltaCash;
|
|
item.GammaCash = 0;
|
|
}
|
|
if (_req.DataSource == "权益")
|
|
{
|
|
item.InnerGamma = (double)(eRisk?.Gamma / um.ContractSize ?? 0); ;
|
|
}
|
|
else
|
|
{
|
|
item.InnerGamma = (double)(eRisk?.Gamma ?? 0);
|
|
}
|
|
}
|
|
if (PS.Config.Is国投)
|
|
{
|
|
item.SpotPrice = item.trade.SpotPrice ?? 0;
|
|
}
|
|
FormatModel(item, varietyTypeList, assetTypeList, varietySuffixList, varietyCodeList, out _);
|
|
}
|
|
}
|
|
catch (ServiceException ex)
|
|
{
|
|
LogFactory.GetLogger("SuperviseReportPositionService").Error(ex, "已知错误");
|
|
throw ex;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
LogFactory.GetLogger("SuperviseReportPositionService").Error(ex, "未知错误");
|
|
throw;
|
|
}
|
|
}
|
|
return retListResult;
|
|
}
|
|
|
|
/// <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 override void FormatModel(SuperviseReportBaseModel model, List<DictionaryItem> varietyTypes, List<DictionaryItem> assetTypes, List<DictionaryItem> varietySuffixs, List<DictionaryItem> varietyCodeList, out SyntheticPriceModel syntheticPrice)
|
|
{
|
|
var obj = (SuperviseReportPositionModel)model;
|
|
base.FormatModel(obj, varietyTypes, assetTypes, varietySuffixs, varietyCodeList, out syntheticPrice);
|
|
|
|
obj.TradeDate = obj.trade.TradeDate;
|
|
obj.ExerciseDate = obj.ExerciseDate == null ? obj.trade.ExerciseDate : obj.ExerciseDate;
|
|
//var annualizeFactor = obj.trade.IsAnnualized ? obj.trade.AnnualizeFactor : 1;
|
|
double endEqv, eqv;
|
|
if (syntheticPrice != null && syntheticPrice.SuList.Count() > 0)
|
|
{
|
|
var underlyingPrices = syntheticPrice.SuList.ToArray();
|
|
var arrSEN = new string[underlyingPrices.Length];
|
|
var arrEndSEN = new string[underlyingPrices.Length];
|
|
var arrAmount = new string[underlyingPrices.Length];
|
|
var arrEndAmount = new string[underlyingPrices.Length];
|
|
var arrSpotPrice = new string[underlyingPrices.Length];
|
|
for (var i = 0; i < underlyingPrices.Length; i++)
|
|
{
|
|
var originalStockEqvNotional = (underlyingPrices[i].Price * obj.trade.OriginalNotional / obj.trade.AnnualizeFactor / obj.trade.ParticipationRate * underlyingPrices[i].Coefficient) ?? 0;
|
|
////var stockEqvNotional = underlyingPrices[i].Price * obj.trade.Notional * underlyingPrices[i].Coefficient;
|
|
//if (obj.trade.TradeType == "凤凰期权" && (obj.trade.trade_autocall?.IsAnnualized2).GetValueOrDefault())
|
|
//{
|
|
// originalStockEqvNotional = originalStockEqvNotional * (obj.trade.trade_autocall.AnnualizeFactor2 ?? 1);
|
|
// //stockEqvNotional = stockEqvNotional * (obj.trade.trade_autocall.AnnualizeFactor2 ?? 1);
|
|
//}
|
|
//else if (obj.trade.TradeType == "雪球期权" && (obj.trade.trade_snowball?.IsAnnualized2).GetValueOrDefault())
|
|
//{
|
|
// originalStockEqvNotional = originalStockEqvNotional * (obj.trade.trade_snowball.AnnualizeFactor2 ?? 1);
|
|
// //stockEqvNotional = stockEqvNotional * (obj.trade.trade_snowball.AnnualizeFactor2 ?? 1);
|
|
//}
|
|
eqv = formatEndStockEqvNotionalReal(originalStockEqvNotional, 1);
|
|
endEqv = formatEndStockEqvNotionalReal(eqv, (1 - (obj.trade.Notional / obj.trade.OriginalNotional ?? 1)));
|
|
if (obj.ForeignCurrencyRate != null)
|
|
{
|
|
arrSEN[i] = (eqv * obj.ForeignCurrencyRate).ToString();
|
|
arrEndSEN[i] = (endEqv * obj.ForeignCurrencyRate).ToString();
|
|
}
|
|
else
|
|
{
|
|
arrSEN[i] = eqv.ToString();
|
|
arrEndSEN[i] = endEqv.ToString();
|
|
}
|
|
|
|
arrAmount[i] = formatTradeAmount(eqv / underlyingPrices[i].Price, (underlyingPrices[i].Coefficient > 0 ? 1 : -1));
|
|
arrEndAmount[i] = formatTradeAmount(endEqv / underlyingPrices[i].Price, (underlyingPrices[i].Coefficient > 0 ? 1 : -1));
|
|
arrSpotPrice[i] = _priceProvider.GetPrice(underlyingPrices[i].UnderlyingCode).ToString();
|
|
}
|
|
obj.StockEqvNotional = string.Join(base._separator, arrSEN);
|
|
obj.EndStockEqvNotional = string.Join(base._separator, arrEndSEN);
|
|
obj.TradeAmount = string.Join(base._separator, arrAmount);
|
|
obj.EndTradeAmount = string.Join(base._separator, arrEndAmount);
|
|
obj.InitialSpotPrice = string.Join(base._separator, arrSpotPrice);//只有多标的时才采用期初价格,单标的时会采用最新价格;
|
|
}
|
|
else
|
|
{
|
|
var originalStockEqvNotional = (obj.trade.OriginalStockEqvNotional == 0 ? (obj.trade.SpotPrice * obj.trade.OriginalNotional / obj.trade.AnnualizeFactor / obj.trade.ParticipationRate) : obj.trade.OriginalStockEqvNotional) ?? 0;
|
|
//if (obj.trade.TradeType == "凤凰期权" && (obj.trade.trade_autocall?.IsAnnualized2).GetValueOrDefault())
|
|
//{
|
|
// originalStockEqvNotional = originalStockEqvNotional * (obj.trade.trade_autocall.AnnualizeFactor2 ?? 1);
|
|
//}
|
|
//else if (obj.trade.TradeType == "雪球期权" && (obj.trade.trade_snowball?.IsAnnualized2).GetValueOrDefault())
|
|
//{
|
|
// originalStockEqvNotional = originalStockEqvNotional * (obj.trade.trade_snowball.AnnualizeFactor2 ?? 1);
|
|
//}
|
|
eqv = formatEndStockEqvNotionalReal(originalStockEqvNotional, 1);
|
|
endEqv = formatEndStockEqvNotionalReal(eqv, (1 - (obj.trade.Notional / (obj.trade.OriginalNotional ?? 1))));
|
|
if (obj.ForeignCurrencyRate != null)
|
|
{
|
|
obj.StockEqvNotional = (eqv * obj.ForeignCurrencyRate).ToString();
|
|
obj.EndStockEqvNotional = (endEqv * obj.ForeignCurrencyRate).ToString();
|
|
}
|
|
else
|
|
{
|
|
obj.StockEqvNotional = eqv.ToString();
|
|
obj.EndStockEqvNotional = endEqv.ToString();
|
|
}
|
|
obj.TradeAmount = formatTradeAmount(eqv / obj.trade.SpotPrice);
|
|
obj.EndTradeAmount = formatTradeAmount(endEqv / obj.trade.SpotPrice);
|
|
//obj.SpotPrice = OtcFormatHelper.FormatValue(obj.trade.SpotPrice ?? 0, 6).ToString();
|
|
}
|
|
|
|
obj.NoRiskRate = obj.trade.NoRiskRate ?? (valuedateBLL.RiskFreeRate * 0.01);
|
|
obj.DiscountRate = obj.trade.NoRiskRate ?? (valuedateBLL.RiskFreeRate * 0.01);
|
|
|
|
//obj.Delta /= um.ContractSize;
|
|
//obj.InnerGamma /= um.ContractSize;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 格式化敲入期权类型
|
|
/// </summary>
|
|
/// <param name="kiPayoffType">敲入期权类型</param>
|
|
/// <returns></returns>
|
|
private string formatKIPayoffType(KIPayoffTypeEnum kiPayoffType)
|
|
{
|
|
var result = "";
|
|
switch (kiPayoffType)
|
|
{
|
|
case KIPayoffTypeEnum.ToPutOption:
|
|
result = "1";
|
|
break;
|
|
case KIPayoffTypeEnum.ToPutSpreadOption:
|
|
result = "3";
|
|
break;
|
|
case KIPayoffTypeEnum.ToCallOption:
|
|
result = "2";
|
|
break;
|
|
case KIPayoffTypeEnum.ToCallSpreadOption:
|
|
result = "4";
|
|
break;
|
|
case KIPayoffTypeEnum.None:
|
|
default:
|
|
result = "9";
|
|
break;
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 格式化雪球期权状态
|
|
/// </summary>
|
|
/// <param name="knockInOutStatus">期权观察状态</param>
|
|
/// <param name="koBarrier">敲出障碍价格</param>
|
|
/// <param name="price">现价</param>
|
|
/// <returns></returns>
|
|
private string formatSnowStatus(string knockInOutStatus, double koBarrier, double price)
|
|
{
|
|
if (knockInOutStatus == "KnockedIn")
|
|
{
|
|
return koBarrier > price ? "3" : "2";//2:敲入过且现价大于等于敲出价;3:敲入过且现价小于敲出价;
|
|
}
|
|
else if (knockInOutStatus != "KnockedOut")
|
|
{
|
|
return "1";// "未敲入过";
|
|
}
|
|
else
|
|
{
|
|
return "";
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// 格式化客户类型
|
|
/// </summary>
|
|
/// <param name="clientId">客户Id</param>
|
|
/// <returns></returns>
|
|
private string formatClientType(int clientId)
|
|
{
|
|
var result = "";
|
|
var clientInfo = DataCacheProvider.GetClientDataSource().GetData(clientId);
|
|
if (clientInfo.ClientType == "产品")
|
|
{
|
|
result = "1";//产品
|
|
}
|
|
else
|
|
{
|
|
if (clientInfo.BusinessType == null)
|
|
{
|
|
result = "9";//其他
|
|
}
|
|
else if (clientInfo.BusinessType.Contains("券商"))
|
|
{
|
|
result = "2";//券商
|
|
}
|
|
else if (clientInfo.BusinessType.Contains("银行"))
|
|
{
|
|
result = "3";//银行
|
|
}
|
|
else if (clientInfo.BusinessType.Contains("期货"))
|
|
{
|
|
result = "4";//期货公司风险管理子公司
|
|
}
|
|
else
|
|
{
|
|
result = "9";//其他
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private string formatSnowType2(trade t, double[] koObservationPrice)
|
|
{
|
|
var result = "9";//其他
|
|
var snowball = t.trade_snowball;
|
|
if (snowball.KORebate != 0)
|
|
{
|
|
if ((snowball.KIPayoffType == KIPayoffTypeEnum.ToPutOption || snowball.KIPayoffType == KIPayoffTypeEnum.ToCallOption) && koObservationPrice != null && koObservationPrice.ToHashSet().Count() > 1)
|
|
{
|
|
if (t.PrincipalRate.GetValueOrDefault() == 0)
|
|
{
|
|
result = "3";//阶梯价雪球
|
|
}
|
|
else
|
|
{
|
|
result = "9";//其他
|
|
}
|
|
}
|
|
else if (snowball.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || snowball.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption)
|
|
{
|
|
result = "2";//保底雪球
|
|
}
|
|
else if (snowball.KIPayoffType == KIPayoffTypeEnum.ToPutOption || snowball.KIPayoffType == KIPayoffTypeEnum.ToCallOption)
|
|
{
|
|
result = "1";//传统雪球和带敲出观察空窗的传统雪球
|
|
}
|
|
else if (snowball.KIPayoffType == KIPayoffTypeEnum.None)
|
|
{
|
|
result = "4";//小雪球
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 格式化雪球结构要素
|
|
/// </summary>
|
|
/// <param name="snowType">雪球类型</param>
|
|
/// <param name="kiPayoffType">敲入支付方式</param>
|
|
/// <param name="koObservationPrice">敲出价格列表</param>
|
|
/// <returns></returns>
|
|
private string formatSnowStructureType(string snowType, KIPayoffTypeEnum kiPayoffType, double[] koObservationPrice)
|
|
{
|
|
var result = new List<string>();
|
|
if (kiPayoffType == KIPayoffTypeEnum.ToPutOption)
|
|
{
|
|
result.Add("1");//普通
|
|
}
|
|
if (koObservationPrice.ToHashSet().Count() > 1)
|
|
{
|
|
//由于现阶段敲入观察价格不支持多个,所以只要是阶梯价雪球,一定是敲出要素变化
|
|
result.Add("3");//敲出要素变化
|
|
}
|
|
if (kiPayoffType == KIPayoffTypeEnum.ToCallSpreadOption)
|
|
{
|
|
result.Add("4");//敲入转牛市价差
|
|
}
|
|
if (kiPayoffType == KIPayoffTypeEnum.ToPutSpreadOption)
|
|
{
|
|
result.Add("5");//敲入转熊市价差
|
|
}
|
|
if (snowType == "4" || result.Count == 0)
|
|
{
|
|
result.Add("9");//其他
|
|
}
|
|
return string.Join(";", result);
|
|
}
|
|
}
|
|
}
|