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
{
///
/// 亚式期权计算测试
///
[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(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 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(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);
}
}
}