using Qdp.Pricing.Base.Implementations; using YLErp.Modules.CalculationModule; using YLErp.Modules.EodModule.SettlementModule; using YLErp.QdpModule; namespace YLErp.Modules.EodModule { [TestClass] public class EodSettlementTest : UnitTestBase { [TestMethod("收盘估值计算")] public void TestCalcPv() { var settleDate = new DateTime(2021, 4, 27); var predicate = PredicateBuilder.Create(t => t.TradeNumber == "CW20210016E0002"); var otcTrades = new EodSettleDataQueryService(GetOptUser()) .GetOtcTrades(settleDate, predicate, out var tradeCashProvider); var td = otcTrades.FirstOrDefault(); if (td == null) { Console.WriteLine("没有找到交易"); return; } var eodpriceProvider = new YLErp.Modules.DataProviderModule.EodPriceProvider(settleDate); var spotPrice = eodpriceProvider.GetPrice(td.UnderlyingCode, SettlementTypeEnum.ClosePrice); var req = new OptionValueCalcRequest(td.NoRiskRate ?? 0) { correlations = null,//不计算彩虹等多标的期权暂时不需要 engineName = null, preciseTimeMode = false, //日终一定是false pricingRequest = QdpPricingRequest.BASIC_GREEKS, spotPrices = new[] { spotPrice } }; if (td.TradeType != ConsGlobal.TradeType.CashFlow) { var volProvider = EodVolProviderFactory.GetEodVolProvider(settleDate, "持仓"); var vol = volProvider.GetVol(td, spotPrice) ?? ConsGlobal.DefaultVol; req.vols = new[] { vol }; } var option = OptionCalculatorV2.GetOptionValueResult(settleDate, td, req, out var underlyings); Console.WriteLine($"[{td.TradeType},{td.TradeNumber},{td.id}] pv:{option.Pv}, delta:{option.Delta}"); } [TestMethod("测试盈亏分解--当天新开仓的交易")] public void TestCalcPnlExplainV2_NewOtcTradeDeal() { var db = DbContextFactory.GetYLDbContext(); var td = db.trade.FirstOrDefault(n => n.TradeNumber == "CW20210016C0001"); YLErp.BLL.tradeBLL.SetFieldsByTradeType(td); var pnl = new EodPnl(); double spot0 = 5910, spot1 = 5911, pv1 = 53796.37; var pS0V1Q1T1 = CalcPnlExplainV2(td, new CalcField { spot = spot0, vol = 0.28, dividendRate = 0, riskFreeRate = 0.03, date = new DateTime(2021, 4, 27) }, PricingRequest.Pv | PricingRequest.Delta, x => { }); if (pS0V1Q1T1 != null) { pnl.PnLVega += NumberHelper.Normalize(pS0V1Q1T1.Pv - ((td.TradeSinglePrice ?? 0) * td.Notional)); pnl.PnLDelta += NumberHelper.Normalize(pS0V1Q1T1.Delta * (spot1 - spot0)); pnl.PnLGamma += NumberHelper.Normalize(pv1 - pS0V1Q1T1.Pv - pnl.PnLDelta); Console.WriteLine($"pS0V1Q1T1 pv:{pS0V1Q1T1.Pv}, delta:{pS0V1Q1T1.Delta}"); } Console.WriteLine("计算失败"); } //计算pv和delta private static TradeValueResult CalcPnlExplainV2(trade td, CalcField f, PricingRequest pricingRequest , Action paramOverride = null) { td.NoRiskRate = f.riskFreeRate; td.DividendRate = f.dividendRate; var req = new OptionValueCalcRequest(f.riskFreeRate) { correlations = null,//不计算彩虹等多标的期权暂时不需要 engineName = null, preciseTimeMode = false, //日终一定是false pricingRequest = pricingRequest, spotPrices = new[] { f.spot }, vols = new[] { f.vol }, ParamOverride = paramOverride }; return OptionCalculatorV2.GetOptionValueResult(f.date, td, req, out _); } class CalcField { //public double pv; public DateTime date; public double vol; public double dividendRate; public double spot; public double riskFreeRate; } } }