255 lines
11 KiB
C#
255 lines
11 KiB
C#
using Qdp.ComputeService.Data.CommonModels.ValuationParams.Equity;
|
|
using Qdp.ComputeServiceV2.Data.CommonModels.TradeInfos.Options;
|
|
using Qdp.Pricing.Base.Enums;
|
|
using Qdp.Pricing.Base.Implementations;
|
|
using Qdp.Pricing.Base.Interfaces;
|
|
using Qdp.Pricing.Library.Options.Products.Asian;
|
|
using YLErp.BLL.Calculation.Engine;
|
|
using YLErp.Modules.CalculationModule;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.CalcModules
|
|
{
|
|
/// <summary>
|
|
/// 亚式期权计算测试
|
|
/// </summary>
|
|
[TestClass]
|
|
public class AisanOptionCalcTest : UnitTestBase
|
|
{
|
|
[TestMethod("亚式期权计算测试")]
|
|
public void AisianOptionCalcTest1()
|
|
{
|
|
var param = new AsianOptionTradeParam
|
|
{
|
|
annualizedFactor = 1,
|
|
averagingPeriodStartDate = new Qdp.Foundation.Implementations.Date(2022, 2, 28),
|
|
buysell = "买入",
|
|
callput = OptionType.Put,
|
|
dividendRate = 0.03,
|
|
dividends = null,
|
|
endDate = new Qdp.Foundation.Implementations.Date(2022, 3, 28),
|
|
exerciseDate = new Qdp.Foundation.Implementations.Date(2022, 3, 28),
|
|
exerciseType = "European",
|
|
fixings = "2022-02-28,17690.0;2022-03-01,17535.0;2022-03-02,17565.0;2022-03-03,17470.0;2022-03-04,17465.0;2022-03-07,17765.0;2022-03-08,17580.0;2022-03-09,17770.0;2022-03-10,18000.0;2022-03-11,17735.0;2022-03-14,17460.0;2022-03-15,16910.0",
|
|
hasNightMarket = false,
|
|
initialSpotPrice = 17375,
|
|
isAnnualized = false,
|
|
isForwardTrade = false,
|
|
isMoneynessOption = false,
|
|
notional = 50,
|
|
observationDateStr = null,
|
|
optionType = OptionType.Put,
|
|
participationRate = 1,
|
|
payoffType = "EnhancedArithmeticAverage",
|
|
preciseTimeMode = false,
|
|
principalRate = 0,
|
|
riskFreeRate = 0.03,
|
|
settlementDate = new Qdp.Foundation.Implementations.Date(2022, 3, 28),
|
|
startDate = new Qdp.Foundation.Implementations.Date(2022, 2, 28),
|
|
strike = 21610,
|
|
strikeGearingFactor = 1,
|
|
strikeStyle = "Fixed",
|
|
timeToMaturityDays = double.NaN,
|
|
tradeDate = new Qdp.Foundation.Implementations.Date(2022, 2, 28),
|
|
tradeId = "11111",
|
|
underlyingInstrumentType = ConsGlobal.InstrumentType.CommodityFutures,
|
|
underlyingTickers = new[] { "ceshi_biaodi" },
|
|
volSurfaceNames = new[] { "ceshi_bodonglv" }
|
|
};
|
|
|
|
var calcParam = new OptionCalcParam<AsianOptionTradeParam>(param)
|
|
{
|
|
pricingRequest = PricingRequest.Pv | PricingRequest.Delta,
|
|
calcScenario = Enums.CalcScenarioEnum.RealtimeRisk,
|
|
spotPrices = new[] { 16910d }
|
|
};
|
|
|
|
using var m = new MarketProxy(new DateTime(2022, 3, 15), 0.03);
|
|
m.SetStockPrice("ceshi_biaodi", 16910d);
|
|
var volatility = QdpVolHelper.GetDefaultVolatility(0.45);
|
|
m.SetVolSurface("ceshi_bodonglv", volatility);
|
|
var result = GetAsianOptionValue(m, calcParam, out var optionTrade1);
|
|
Console.WriteLine($"{result.Pv} -- {result.Delta}");
|
|
|
|
m.SetStockPrice("ceshi_biaodi", 16900d);
|
|
var result2 = GetAsianOptionValue(m, calcParam, out var optionTrade2);
|
|
Console.WriteLine($"{result2.Pv} -- {result2.Delta}");
|
|
Assert.AreEqual(Math.Abs(result2.Pv - result.Pv), Math.Abs(result.Delta) * 10, 0.01);
|
|
|
|
param.fixings = "2022-02-28,17690.0;2022-03-01,17535.0;2022-03-02,17565.0;2022-03-03,17470.0;2022-03-04,17465.0;2022-03-07,17765.0;2022-03-08,17580.0;2022-03-09,17770.0;2022-03-10,18000.0;2022-03-11,17735.0;2022-03-14,17460.0;2022-03-15,16900.0";//
|
|
|
|
var result3 = GetAsianOptionValue(m, calcParam, out var optionTrade3);
|
|
|
|
Console.WriteLine($"{result3.Pv} -- {result3.Delta}");
|
|
|
|
Assert.AreEqual(Math.Abs(result3.Pv - result.Pv), Math.Abs(result.Delta) * 10, 0.01);
|
|
}
|
|
|
|
public static IPricingResult GetAsianOptionValue(MarketProxy marketProxy
|
|
, OptionCalcParam<AsianOptionTradeParam> calcParam
|
|
, out AsianOptionTrade optionTrade)
|
|
{
|
|
optionTrade = QdpTradeBuilder.GetAsianOptionTrade(calcParam.TradeParam);
|
|
|
|
var parameters = new OptionValuationParameters(marketProxy.DiscountCurveName ?? MarketProxy.ConstantZeroCurve,
|
|
MarketProxy.ConstantZeroCurve, calcParam.volSurfaceNames[0], calcParam.underlyingTickers[0]);
|
|
|
|
var option = optionTrade.Instrument as AsianOption;
|
|
var factory = OptionEngineFactory.GetEngineFactory("AsianOption");
|
|
var engine = factory.GetEngine(calcParam.engineName, option.Exercise, calcParam.TradeParam.payoffType, option, calcParam.TradeParam.strikeStyle);
|
|
var pricingRequest = calcParam.pricingRequest;
|
|
if (option.AsianType == AsianType.EnhancedArithmeticAverage)
|
|
{
|
|
pricingRequest = QdpPricingRequest.UnionBaiscGreeks(calcParam.pricingRequest);
|
|
}
|
|
|
|
return optionTrade.CalculateRisks(marketProxy.QdpMarket, pricingRequest, engine, parameters);
|
|
}
|
|
|
|
[TestMethod("亚式期权计算测试2")]
|
|
public void AisianOptionCalcTest2()
|
|
{
|
|
var startDate = new DateTime(2019, 7, 22);
|
|
var endDate = startDate.AddMonths(9);
|
|
var observationDateStr = new StringBuilder(3000);
|
|
for (var dt = startDate; dt <= endDate; dt = dt.AddDays(1))
|
|
{
|
|
observationDateStr.Append(dt.ToString("yyyy-MM-dd")).Append(',');
|
|
}
|
|
observationDateStr.Remove(observationDateStr.Length - 1, 1);
|
|
var param = new AsianOptionTradeParam
|
|
{
|
|
annualizedFactor = 1,
|
|
averagingPeriodStartDate = startDate,
|
|
buysell = "买入",
|
|
callput = OptionType.Call,
|
|
dividendRate = 0.05,
|
|
dividends = null,
|
|
endDate = endDate,
|
|
exerciseDate = endDate,
|
|
exerciseType = "European",
|
|
fixings = "2019-07-22,100",
|
|
hasNightMarket = false,
|
|
initialSpotPrice = 100,
|
|
isAnnualized = false,
|
|
isForwardTrade = false,
|
|
isMoneynessOption = false,
|
|
notional = 1,
|
|
observationDateStr = null,//observationDateStr.ToString(),
|
|
optionType = OptionType.Call,
|
|
participationRate = 1,
|
|
payoffType = "ArithmeticAverage",
|
|
preciseTimeMode = false,
|
|
principalRate = 0,
|
|
riskFreeRate = 0.1,
|
|
settlementDate = null,
|
|
startDate = startDate,
|
|
strike = 100,
|
|
strikeGearingFactor = 1,
|
|
strikeStyle = "Fixed",
|
|
timeToMaturityDays = double.NaN,
|
|
tradeDate = startDate,
|
|
tradeId = "11111",
|
|
underlyingInstrumentType = ConsGlobal.InstrumentType.Stock,
|
|
underlyingTickers = new[] { "ceshi_biaodi" },
|
|
volSurfaceNames = new[] { "ceshi_bodonglv" }
|
|
};
|
|
|
|
var calcParam = new OptionCalcParam<AsianOptionTradeParam>(param)
|
|
{
|
|
pricingRequest = PricingRequest.Pv,
|
|
calcScenario = Enums.CalcScenarioEnum.RealtimeRisk,
|
|
spotPrices = new[] { 100d }
|
|
};
|
|
|
|
using var m = new MarketProxy(startDate, 0.1);
|
|
m.SetStockPrice("ceshi_biaodi", 100d);
|
|
var volatility = QdpVolHelper.GetDefaultVolatility(0.15);
|
|
m.SetVolSurface("ceshi_bodonglv", volatility);
|
|
var result = GetAsianOptionValue(m, calcParam, out var optionTrade1);
|
|
Console.WriteLine($"{result.Pv}");
|
|
}
|
|
|
|
//国信金阳:API是 9.53
|
|
[TestMethod("(国信金阳)亚式期权计算测试")]
|
|
public void AisianOptionCalcTestGuoXin()
|
|
{
|
|
var startDate = new Qdp.Foundation.Implementations.Date(2022, 8, 31);
|
|
var exerciseDate = new Qdp.Foundation.Implementations.Date(2022, 9, 30);
|
|
|
|
var valueDate = new DateTime(2022, 9, 6);
|
|
|
|
var td = new trade
|
|
{
|
|
BuySell = "买入",
|
|
AnnualizeFactor = 1,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
|
|
StartDate = startDate,
|
|
TradeDate = startDate,
|
|
|
|
ExerciseDate = exerciseDate,
|
|
SettlementDate = exerciseDate,
|
|
|
|
Notional = 1,
|
|
InitialSpotPrice = 23190,
|
|
Strike = 23380,
|
|
|
|
NoRiskRate = 0,
|
|
DividendRate = 0,
|
|
|
|
IsAnnualized = false,
|
|
IsMoneynessOption = null,
|
|
|
|
UnderlyingCode = "LH2301",
|
|
UnderlyingInstrumentType = ConsGlobal.InstrumentType.CommodityFutures,
|
|
|
|
TradeType = "亚式期权",
|
|
trade_asian_option = new trade_asian_option
|
|
{
|
|
AveragingPeriodStartDate = new DateTime(2022, 9, 1),
|
|
StrikeType = "Fixed",
|
|
PayoffType = "EnhancedArithmeticAverage",
|
|
Fixings = "2022-09-01,23285.0;2022-09-02,23025;2022-09-05,23380.0",
|
|
StrikeGearingFactor = 1,
|
|
ObservationDates = null,
|
|
}
|
|
};
|
|
|
|
var creq = new OptionValueCalcRequest(0)
|
|
{
|
|
calcDeltaT1 = false,
|
|
calcScenario = Enums.CalcScenarioEnum.RealtimeRisk,
|
|
correlations = null,
|
|
engineName = null,
|
|
fixings = td.trade_asian_option.Fixings,
|
|
isEodCalc = false,
|
|
maturityShift = 0,
|
|
preciseTimeMode = false,
|
|
quadratureFastMode = false,
|
|
pricingRequest = PricingRequest.Pv | PricingRequest.Delta,
|
|
spotPrices = new[] { 23190d },
|
|
timeToMaturityDays = double.NaN,
|
|
vols = new[] { 0.25 }
|
|
};
|
|
|
|
void outputResult(TradeValueResult mr)
|
|
{
|
|
var dlots = mr.Delta * 312 / 16;
|
|
var tdays = mr.PricingT * 244;
|
|
Console.WriteLine($"{tdays} -- {mr.Pv} -- {mr.Delta} -- {dlots}");
|
|
}
|
|
|
|
var resultA1 = OptionCalculatorV2.GetOptionValueResult(valueDate, td, creq, out _);
|
|
outputResult(resultA1);
|
|
|
|
creq.timeToMaturityDays = 18;
|
|
var result = OptionCalculatorV2.GetOptionValueResult(valueDate, td, creq, out _);
|
|
outputResult(result);
|
|
|
|
Assert.AreEqual(resultA1.Delta, result.Delta, 1e-4);
|
|
}
|
|
}
|
|
}
|