Files
zszq-trs/YLErpDAL/Modules/EodModule/GLMSGreeksHandleService.cs
T

385 lines
16 KiB
C#

using Dapper;
using Org.BouncyCastle.Asn1.Mozilla;
using Org.BouncyCastle.Ocsp;
using Qdp.Foundation.Implementations;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using YLErp.Abstract.DataProviders;
using YLErp.DBModels;
using YLErp.Model;
using YLErp.Modules.CalculationModule;
using YLErp.Modules.DataProviderModule;
using YLErp.Modules.MarketRiskMoudule.Dto;
namespace YLErp.Modules.EodModule
{
/// <summary>
/// 国联民生 希腊字母计算
/// </summary>
public class GLMSGreeksHandleService
{
private readonly List<string> calcInstrumentTypes = new List<string>() { ConsGlobal.InstrumentType.TBonds, ConsGlobal.InstrumentType.CreditBonds, ConsGlobal.InstrumentType.OtherBonds,
ConsGlobal.InstrumentType.RateYield,ConsGlobal.InstrumentType.BondIndex,ConsGlobal.InstrumentType.TBFutures };
private readonly List<string> instrumentBondsTypes = new List<string>() { ConsGlobal.InstrumentType.TBonds, ConsGlobal.InstrumentType.CreditBonds, ConsGlobal.InstrumentType.OtherBonds };
Dictionary<string, double?> _pDic = new Dictionary<string, double?>();
Dictionary<string, double?> _dDic = new Dictionary<string, double?>();
Dictionary<string, double?> _cDic = new Dictionary<string, double?>();
Dictionary<string, double?> _ytmDic = new Dictionary<string, double?>();
Dictionary<string, double?> _cfDic = new Dictionary<string, double?>();
//期货对应的债券代码
Dictionary<string, string> _TFeaturesBondCodeDic = new Dictionary<string, string>();
public void InitData(DateTime valueDate,List<string> underlyingCodes)
{
var umDatas = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().Where(p => underlyingCodes.Contains(p.UnderlyingCode) && calcInstrumentTypes.Contains(p.UnderlyingInstrumentType)).ToList();
if (umDatas == null || umDatas.Count == 0)
{
return;
}
var eodPriceProvier = new EodPriceProvider(valueDate);
eodPriceProvier.Initialize(underlyingCodes);
underlyingCodes.ForEach(e => {
_pDic.Add(e, eodPriceProvier.GetPrice(e, SettlementTypeEnum.ClosePrice));
});
using var db = DbContextFactory.GetYLDbContext();
var conn = db.Database.GetDbConnection();
var bondsUmCodes = umDatas.Where(p => instrumentBondsTypes.Contains(p.UnderlyingInstrumentType)).Select(p => p.UnderlyingCode).Distinct().ToList();
if (bondsUmCodes == null)
{
bondsUmCodes = new List<string>();
}
var bondIndexUmInnerCodes = umDatas.Where(p => ConsGlobal.InstrumentType.BondIndex.Equals(p.UnderlyingInstrumentType)).Select(p => p.InnerCode??0).Distinct().ToList();
if (bondIndexUmInnerCodes != null && bondIndexUmInnerCodes.Count > 0)
{
var querySql = "SELECT InnerCode,Duration1,Convexity1,YTM FROM bond_chinabondindexquote WHERE TradingDay = @ValueDate AND InnerCode IN @InnerCodes";
var bondIndexQuoteDatas = conn.Query<ChinaBondIndexQuoteQueryDto>(querySql, new
{
ValueDate = valueDate,
InnerCodes = bondIndexUmInnerCodes
}, commandTimeout: 1800).ToList();
if (bondIndexQuoteDatas != null && bondIndexQuoteDatas.Count > 0)
{
foreach (var item in bondIndexQuoteDatas)
{
var umCode = umDatas.First(d => d.InnerCode == item.InnerCode).UnderlyingCode;
_dDic.Add(umCode, item.Duration1 != null ? (double)item.Duration1 : null);
_cDic.Add(umCode, item.Convexity1 != null ? (double)item.Convexity1 : null);
_ytmDic.Add(umCode, item.YTM != null ? (double)item.YTM : null);
}
}
}
var bondFeatureUmCodes = umDatas.Where(p => ConsGlobal.InstrumentType.TBFutures.Equals(p.UnderlyingInstrumentType)).Select(p => p.UnderlyingCode).Distinct().ToList();
if (bondFeatureUmCodes != null && bondFeatureUmCodes.Count > 0)
{
var tFeatureBondInnerCodeDic = GetTFeatureBondInnerCode(bondFeatureUmCodes, valueDate, conn);
if (tFeatureBondInnerCodeDic != null && tFeatureBondInnerCodeDic.Count > 0)
{
var contractInnerCodeBondInnerCodeDic = new Dictionary<long, long>();
foreach (var item in tFeatureBondInnerCodeDic)
{
var bondUm = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().FirstOrDefault(p => p.InnerCode == item.Value);
if (bondUm != null)
{
_TFeaturesBondCodeDic.Add(item.Key, bondUm.UnderlyingCode);
bondsUmCodes.Add(bondUm.UnderlyingCode);
}
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(item.Key);
if (um.InnerCode != null)
{
contractInnerCodeBondInnerCodeDic.Add(um.InnerCode ?? 0, item.Value);
}
}
if (contractInnerCodeBondInnerCodeDic.Count > 0)
{
var cfDatas = GetCFDatas(contractInnerCodeBondInnerCodeDic, conn);
if (cfDatas != null && cfDatas.Count > 0)
{
foreach (var item in cfDatas)
{
var um = DataCacheProvider.GetUnderlyingDataSource().AsQueryable().FirstOrDefault(p => p.InnerCode == item.Key);
if (um != null)
{
_cfDic.Add(um.UnderlyingCode, item.Value);
}
}
}
}
}
}
if (bondsUmCodes != null && bondsUmCodes.Count > 0)
{
bondsUmCodes = bondsUmCodes.Distinct().ToList();
var datas = db.china_bond_valuation.AsNoTracking().Where(p => p.valuation_date == valueDate && bondsUmCodes.Contains(p.bond_id)).Select(p => new
{
p.bond_id,
p.modi_dura,
p.convexity,
p.yield
}).ToList();
if (datas != null && datas.Count > 0)
{
foreach (var item in datas)
{
_dDic.Add(item.bond_id, item.modi_dura != null ? (double)item.modi_dura : null);
_cDic.Add(item.bond_id, item.convexity != null ? (double)item.convexity : null);
_ytmDic.Add(item.bond_id, item.yield != null ? (double)item.yield : null);
}
}
}
}
public void Handle(EodPositionRisksDTO dto,underlying_manager um)
{
var calcDto = new GreeksCalcDto
{
Delta = dto.Delta,
Gamma = dto.Gamma,
Vega = dto.Vega,
};
handle(calcDto, um);
dto.Delta_r = calcDto.Delta_r;
dto.Gamma_r = calcDto.Gamma_r;
dto.Vega_r = calcDto.Vega_r;
dto.Delta_r_1bp = calcDto.Delta_r_1bp;
dto.Dv01 = calcDto.Dv01;
dto.Gamma_r_1bp = calcDto.Gamma_r_1bp;
dto.Vega_r_1bp = calcDto.Vega_r_1bp;
}
public void Handle(trade td,TradeValueResult calRes, underlying_manager um)
{
var calcDto = new GreeksCalcDto
{
Delta = calRes.Delta,
Gamma = calRes.Gamma,
Vega = calRes.Vega,
};
handle(calcDto, um);
calRes.Delta_r = calcDto.Delta_r;
calRes.Gamma_r = calcDto.Gamma_r;
calRes.Vega_r = calcDto.Vega_r;
calRes.Delta_r_1bp = calcDto.Delta_r_1bp;
calRes.Dv01 = calcDto.Dv01;
calRes.Gamma_r_1bp = calcDto.Gamma_r_1bp;
calRes.Vega_r_1bp = calcDto.Vega_r_1bp;
}
private Dictionary<string,long> GetTFeatureBondInnerCode(List<string> underlyingCodes,DateTime valueDate,DbConnection conn)
{
var sql = "SELECT contractcode,deliverableinnercode,spread FROM fut_cgbderiv WHERE TradingDay = @ValueDate AND pricetype = 3 AND (contractcode,irr) IN (SELECT contractcode,MAX(irr) FROM fut_cgbderiv WHERE TradingDay = @ValueDate AND contractcode IN (@UmCodes) AND pricetype = 3 GROUP BY contractcode);";
var datas = conn.Query<TFeatureBondInnerCodeQueryDto>(sql, new
{
ValueDate = valueDate,
UmCodes = underlyingCodes
}, commandTimeout: 1800).ToList();
var res = new Dictionary<string,long>();
if (datas != null && datas.Count > 0)
{
res = datas.GroupBy(p => p.contractcode).ToDictionary(p => p.Key, p => p.OrderBy(d => d.spread).First().deliverableinnercode);
}
return res;
}
private GLMSGreeksCalcArgs GetCalcArgs(string underlyingCode, string underlyingInstrumentType)
{
var res = new GLMSGreeksCalcArgs();
if (ConsGlobal.InstrumentType.RateYield.Equals(underlyingInstrumentType))
{
return res;
}
if (ConsGlobal.InstrumentType.TBFutures.Equals(underlyingInstrumentType))
{
var bondUnderlyingCode = _TFeaturesBondCodeDic.GetValueOrDefault(underlyingCode, null);
if (!string.IsNullOrEmpty(bondUnderlyingCode))
{
res.P = _pDic.GetValueOrDefault(bondUnderlyingCode, null);
res.D = _dDic.GetValueOrDefault(bondUnderlyingCode, null);
res.C = _cDic.GetValueOrDefault(bondUnderlyingCode, null);
res.Ytm = _ytmDic.GetValueOrDefault(bondUnderlyingCode, null);
}
res.CF = _cfDic.GetValueOrDefault(underlyingCode, null);
}
else
{
res.P = _pDic.GetValueOrDefault(underlyingCode, null);
res.D = _dDic.GetValueOrDefault(underlyingCode, null);
res.C = _cDic.GetValueOrDefault(underlyingCode, null);
res.Ytm = _ytmDic.GetValueOrDefault(underlyingCode, null);
}
//
return res;
}
private Dictionary<long, double?> GetCFDatas(Dictionary<long, long> contractInnerCodeBondInnerCodeDic, DbConnection conn)
{
if (contractInnerCodeBondInnerCodeDic == null || contractInnerCodeBondInnerCodeDic.Count == 0)
return new Dictionary<long, double?>();
var parameters = new DynamicParameters();
var tupleList = new List<string>();
int idx = 0;
foreach (var kvp in contractInnerCodeBondInnerCodeDic)
{
var cp = $"@C{idx}";
var bp = $"@B{idx}";
tupleList.Add($"({cp},{bp})");
parameters.Add(cp, kvp.Key);
parameters.Add(bp, kvp.Value);
idx++;
}
var sql = $@"SELECT infopubldate, contractinnercode, ibmarketinnercode, conversionfactors
FROM fut_conversionfactors
WHERE (contractinnercode, ibmarketinnercode) IN ({string.Join(",", tupleList)})";
var datas = conn.Query<CFQueryDto>(sql, parameters, commandTimeout: 1800).ToList();
return datas.GroupBy(p => p.contractinnercode).ToDictionary(d => d.Key, d =>
{
var res = d.OrderByDescending(p => p.infopubldate).First().conversionfactors;
return res != null ? (double)res : (double?)null;
});
}
private void handle(GreeksCalcDto dto, underlying_manager um)
{
if (!calcInstrumentTypes.Contains(um.UnderlyingInstrumentType))
{
return;
}
var calcArgs = GetCalcArgs(um.UnderlyingCode, um.UnderlyingInstrumentType);
if (ConsGlobal.InstrumentType.RateYield.Equals(um.UnderlyingInstrumentType))
{
//利率收益率
dto.Delta_r = dto.Delta * -1;
dto.Gamma_r = dto.Gamma;
dto.Vega_r = dto.Vega;
}
else if (instrumentBondsTypes.Contains(um.UnderlyingInstrumentType))
{
//利率债、信用债、其它债券
dto.Delta_r = dto.Delta * calcArgs.P * calcArgs.D;
dto.Gamma_r = dto.Delta * calcArgs.P * calcArgs.C + (calcArgs.P * calcArgs.D) * (calcArgs.P * calcArgs.D) * dto.Gamma;
dto.Vega_r = dto.Vega * calcArgs.D * calcArgs.Ytm;
}
else if (ConsGlobal.InstrumentType.BondIndex.Equals(um.UnderlyingInstrumentType))
{
//债券指数
dto.Delta_r = dto.Delta * calcArgs.P * calcArgs.D;
dto.Gamma_r = dto.Delta * calcArgs.P * calcArgs.C + (calcArgs.P * calcArgs.D) * (calcArgs.P * calcArgs.D) * dto.Gamma;
dto.Vega_r = dto.Vega * calcArgs.D * calcArgs.Ytm;
}
else if (ConsGlobal.InstrumentType.TBFutures.Equals(um.UnderlyingInstrumentType))
{
//国债期货
dto.Delta_r = dto.Delta * calcArgs.P * calcArgs.D / calcArgs.CF;
dto.Gamma_r = dto.Delta * calcArgs.P * calcArgs.C / calcArgs.CF + (calcArgs.P * calcArgs.D / calcArgs.CF) * (calcArgs.P * calcArgs.D / calcArgs.CF) * dto.Gamma;
dto.Vega_r = dto.Vega * calcArgs.D * calcArgs.Ytm;
}
dto.Delta_r_1bp = dto.Delta_r * 0.0001;
dto.Dv01 = dto.Delta_r_1bp;
dto.Gamma_r_1bp = dto.Gamma_r * 0.0001 * 0.0001;
dto.Vega_r_1bp = dto.Vega_r * 0.0001;
}
}
public class GLMSGreeksCalcArgs
{
//计算日的全价
public double? P { get; set; }
public double? D { get; set; }
public double? CF { get; set; }
public double? C { get; set; }
public double? Ytm { get; set; }
}
public class GreeksCalcDto
{
public double? Delta { get; set; }
public double? Gamma { get; set; }
public double? Vega { get; set; }
/// <summary>
/// Delta_R
/// </summary>
public double? Delta_r { get; set; }
public double? Delta_r_1bp { get; set; }
public double? Dv01 { get; set; }
public double? Gamma_r { get; set; }
public double? Gamma_r_1bp { get; set; }
public double? Vega_r { get; set; }
public double? Vega_r_1bp { get; set; }
}
public class ChinaBondIndexQuoteQueryDto
{
public long InnerCode { get; set; }
public decimal? Duration1 { get; set; }
public decimal? Convexity1 { get; set; }
public decimal? YTM { get; set; }
}
public class TFeatureBondInnerCodeQueryDto
{
public string contractcode { get; set; }
public long deliverableinnercode { get; set; }
public decimal? spread { get; set; }
}
public class CFQueryDto
{
public DateTime infopubldate { get; set; }
public long contractinnercode { get; set; }
public long ibmarketinnercode { get; set; }
public decimal? conversionfactors { get; set; }
}
}