Files
zszq-trs/UnitTestProject/Modules/CalcModules/AutocalllOptionCalcTest.cs
T
2024-05-09 14:06:26 +08:00

151 lines
5.9 KiB
C#

using Qdp.Foundation.Implementations;
using Qdp.Pricing.Base.Enums;
using Qdp.Pricing.Base.Implementations;
using Qdp.Pricing.Base.Interfaces;
using Qdp.Pricing.Library.Options.MonteCarlo;
using Qdp.Pricing.Library.Options.Products.Autocall.Phoenix;
using Qdp.Pricing.Library.Options.Products.Autocall.Phoenix.Numerical;
using YLErp.Modules.CalculationModule;
using YLErp.QdpModule;
namespace YLErp.Modules.CalcModules
{
/// <summary>
/// 凤凰期权计算测试
/// </summary>
[TestClass]
public class AutocalllOptionCalcTest : UnitTestBase
{
[TestMethod("看跌凤凰")]
public void SnowballOptionCalcTest1()
{
var ValueDate = new Date(2019, 11, 26);
var maturityDate = new Date(2020, 2, 24);
const double SPOT = 3899;
const double NOTIONAL = 1000000.0 / SPOT;
var tradeId = Guid.NewGuid().ToString();
var tdParam = new AutocallOptionTradeParam
{
annualizedFactor = 1,
annualizedOptionPayoff = false,
barrierStatus = null,
buysell = null,
callput = OptionType.Put,
coupon = 0.05,
couponBarrier = 1.05,
couponDayCount = "Act365",
couponPayAtMaturity = false,
dividendRate = 0.01,
dividends = null,
endDate = maturityDate,
exerciseDate = maturityDate,
exerciseType = "European",
happenedObservations = null,
hasNightMarket = false,
//includeCouponAfterKI = true,
initialSpotPrice = SPOT,
isAnnualized = false,
isFixedCoupon = false,
isForwardTrade = false,
isMoneynessOption = true,
kiBarrier = 1.05,
kiOptionType = "Call",
koBarrier = 0.8,
koObservationDateStr = "",
notional = NOTIONAL,
observationDateStr = "",
participationRate = 1,
preciseTimeMode = false,
principalRate = 0,
riskFreeRate = 0.05,
settlementDate = maturityDate,
strike = 1,
startDate = ValueDate,
timeToMaturityDays = double.NaN,
tradeDate = ValueDate,
tradeId = tradeId,
underlyingInstrumentType = ConsGlobal.InstrumentType.Stock,
underlyingTickers = new[] { "AAA9999" },
volSurfaceNames = new[] { tradeId }
};
using var market = new MarketProxy(ValueDate, 0.05);
market.SetStockPrice("AAA9999", SPOT);
market.SetVolSurface(tradeId, 0.2);
var val = TradeRiskCalcUtil.GetAutocallOptionValue(market, new OptionCalcParam<AutocallOptionTradeParam>(tdParam)
{
CalcDeltaT1 = false,
calcScenario = Enums.CalcScenarioEnum.Pricing,
engineName = null,
pricingRequest = PricingRequest.Pv,
quadratureFastMode = false,
spotPrices = new[] { SPOT }
});
//Assert.IsTrue(Math.Abs(val.Pv / -32652.810546875 - 1) < 0.01);
Assert.AreEqual((-32785 / val.Pv) - 1, 0, 1e-3);
}
[TestMethod("看跌凤凰")]
public void TestPhoenixPriceOfDownAndOut()
{
var ValueDate = new Date(2019, 11, 26);
var maturityDate = new Date(2020, 2, 24);
var Calendar = CalendarImpl.Get("chn");
IDayCount DayCount = new Bus252();
var InstrumentType = Qdp.Pricing.Base.Enums.InstrumentType.Stock;
const double VOL = 0.2;
const double SPOT = 3899;
const double RISK_FREE_RATE = 0.05;
const double DIVIDEND_RATE = 0.01;
const double NOTIONAL = 1000000.0 / SPOT;
var market = QdpTestHelper.CreateMarket(ValueDate, VOL, SPOT, RISK_FREE_RATE, DIVIDEND_RATE);
var newEngine = new QuadAutoCallEngine();
var mcEngine = new GbmMonteCarloEngine(1000000, 1e-3, 1e-6, 1);
var option2 = new AutoCall(
startDate: ValueDate,
maturityDate: maturityDate,
koBarrier: 0.8,
kiBarrier: 1.05,
couponBarrier: 1.05,
coupon: 0.05,
couponPayAtMaturity: false,
includeCouponAfterKI: true,
optionParticipationRate: 1.0,
koObsDates: QdpTestHelper.GenerateObservationDates(Calendar, ValueDate, maturityDate, new Term("1M"), BusinessDayConvention.Following),
kiObsDates: null,
observationDates: QdpTestHelper.GenerateObservationDates(Calendar, ValueDate, maturityDate),
notional: NOTIONAL,
initialSpotPrice: SPOT,
underlyingType: InstrumentType,
calendar: Calendar,
dayCount: DayCount,
payoffCcy: CurrencyCode.CNY,
settlementCcy: CurrencyCode.CNY,
exerciseDates: new Date[] { maturityDate },
exercise: OptionExercise.European,
optionType: OptionType.Put,
barrierType: BarrierType.DownAndOut,
strike: 1.0,
spreadStrike: 1.1,
annualizedOptionPayoff: false,
isMoneynessOption: true,
kiOptionType: OptionType.Call);
var json = Newtonsoft.Json.JsonConvert.SerializeObject(option2);
var mcPv2 = mcEngine.Calculate(option2, market, PricingRequest.Pv).Pv;
Assert.IsTrue(Math.Abs((mcPv2 / -32652.810546875) - 1) < 0.01);
var newPv2 = newEngine.Calculate(option2, market, PricingRequest.Pv).Pv;
Assert.AreEqual((-32737.653776411829 / newPv2) - 1, 0, 1e-3);
}
}
}