1013 lines
37 KiB
C#
1013 lines
37 KiB
C#
using Qdp.Pricing.Base.Implementations;
|
|
using YLErp.BLL.Calculation.V2;
|
|
using YLErp.BLL.Calculation.V2.Parameter;
|
|
using YLErp.QdpModule;
|
|
|
|
namespace YLErp.Modules.CalcModules
|
|
{
|
|
/// <summary>
|
|
/// 中银国际的POC测试,TradeDayCount和CurveDayCount请使用Act365测试
|
|
/// </summary>
|
|
[TestClass]
|
|
public class BocInternationalTest
|
|
{
|
|
private readonly DateTime ValueDate = new(2019, 11, 26);
|
|
private readonly DateTime MaturityDate = new(2019, 12, 26);
|
|
private readonly string UnderlyingTicker = "000300";
|
|
private readonly underlying_manager Underlying = new()
|
|
{
|
|
QuotationDate = new DateTime(2019, 11, 26),
|
|
UnderlyingCode = "000300",
|
|
UnderlyingInstrumentType = "Stock"
|
|
};
|
|
private readonly string userId = Guid.NewGuid().ToString();
|
|
|
|
private const double SPOT = 3899.0;
|
|
private const double VOL = 0.2;
|
|
private const double RISKFREE_RATE = 0.05;
|
|
private const double DIVIDEND_RATE = 0.01;
|
|
private const double NOTIONAL = 1000000.0 / 3899.0;
|
|
|
|
[TestMethod]
|
|
public void EuropeanVanillaTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var call = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
var put = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.97,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
var parameter = new VanillaOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var callResult = ValueCalculator.CalculateTradeValue(
|
|
userId,
|
|
call,
|
|
Underlying,
|
|
parameter,
|
|
PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(12246.342761701024, callResult.Pv, 1e-8);
|
|
|
|
var putResult = ValueCalculator.CalculateTradeValue(
|
|
userId,
|
|
put,
|
|
Underlying,
|
|
parameter,
|
|
PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(9677.6310645714639, putResult.Pv, 1e-8);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void VanillaStrategyTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
// 牛市价差
|
|
var leg1 = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.98,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
var leg2 = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
var parameter = new VanillaOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, leg1, Underlying, parameter, PricingRequest.Pv);
|
|
var result2 = ValueCalculator.CalculateTradeValue(userId, leg2, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(23808.69577353201, result1.Pv - result2.Pv, 1e-8);
|
|
|
|
// 熊市价差
|
|
leg1 = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.98,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
leg2 = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
result1 = ValueCalculator.CalculateTradeValue(userId, leg1, Underlying, parameter, PricingRequest.Pv);
|
|
result2 = ValueCalculator.CalculateTradeValue(userId, leg2, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(25986.246414678219, result2.Pv - result1.Pv, 1e-8);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void EuropeanBinaryTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var call = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "CashOrNothing",
|
|
CashOrNothingAmount = SPOT * 0.05,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var put = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.97,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "CashOrNothing",
|
|
CashOrNothingAmount = SPOT * 0.05,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var parameter = new BinaryOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var callResult = ValueCalculator.CalculateTradeValue(userId, call, Underlying, parameter, PricingRequest.Pv);
|
|
var putResult = ValueCalculator.CalculateTradeValue(userId, put, Underlying, parameter, PricingRequest.Pv);
|
|
Assert.AreEqual(15594.939923929795, callResult.Pv, 1e-8);
|
|
Assert.AreEqual(14329.866102278227, putResult.Pv, 1e-8);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void AmericanVanillaTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var call = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
var put = new trade()
|
|
{
|
|
TradeType = "香草期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.97,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
};
|
|
|
|
var parameter = new VanillaOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var callResult = ValueCalculator.CalculateTradeValue(userId, call, Underlying, parameter, PricingRequest.Pv);
|
|
var putResult = ValueCalculator.CalculateTradeValue(userId, put, Underlying, parameter, PricingRequest.Pv);
|
|
Assert.AreEqual(12282.946028031403, callResult.Pv, 1e-8);
|
|
Assert.AreEqual(9763.3711407456285, putResult.Pv, 1e-8);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void AsianTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var call = new trade()
|
|
{
|
|
TradeType = "亚式期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
trade_asian_option = new trade_asian_option()
|
|
{
|
|
StrikeType = "Fixed",
|
|
PayoffType = "ArithmeticAverage",
|
|
AveragingPeriodStartDate = ValueDate
|
|
}
|
|
};
|
|
|
|
var put = new trade()
|
|
{
|
|
TradeType = "亚式期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.97,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
trade_asian_option = new trade_asian_option()
|
|
{
|
|
StrikeType = "Fixed",
|
|
PayoffType = "ArithmeticAverage",
|
|
AveragingPeriodStartDate = ValueDate
|
|
}
|
|
};
|
|
|
|
var parameter = new AsianOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE,
|
|
Fixings = null
|
|
};
|
|
|
|
var callResult = ValueCalculator.CalculateTradeValue(userId, call, Underlying, parameter, PricingRequest.Pv);
|
|
var putResult = ValueCalculator.CalculateTradeValue(userId, put, Underlying, parameter, PricingRequest.Pv);
|
|
Assert.AreEqual(3427.8986213282096, callResult.Pv, 1e-8);
|
|
Assert.AreEqual(2618.116861274927, putResult.Pv, 1e-3);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void RangeAccrualTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var option = new trade()
|
|
{
|
|
TradeType = "区间累积期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_rangeaccrual = new trade_rangeaccrual()
|
|
{
|
|
LowerRange = 0.975,
|
|
UpperRange = 1.025,
|
|
BonusRate = 0.06
|
|
}
|
|
};
|
|
|
|
var parameter = new RangeAccrualParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE,
|
|
Fixings = null
|
|
};
|
|
|
|
var result = ValueCalculator.CalculateTradeValue(userId, option, Underlying, parameter, PricingRequest.Pv);
|
|
Assert.AreEqual(29620.042479889609, result.Pv, 1e-8);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void AmericanBinaryTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var option1 = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "UpOneTouch",
|
|
CashOrNothingAmount = SPOT * 0.05,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var option2 = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.03,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "UpOneTouch",
|
|
CashOrNothingAmount = SPOT * 0.05,
|
|
RebateType = "AtEnd"
|
|
}
|
|
};
|
|
|
|
var option3 = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.97,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "DownOneTouch",
|
|
CashOrNothingAmount = SPOT * 0.05,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var option4 = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.97,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "DownOneTouch",
|
|
CashOrNothingAmount = SPOT * 0.05,
|
|
RebateType = "AtEnd"
|
|
}
|
|
};
|
|
|
|
var parameter = new BinaryOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, option1, Underlying, parameter, PricingRequest.Pv);
|
|
var result2 = ValueCalculator.CalculateTradeValue(userId, option2, Underlying, parameter, PricingRequest.Pv);
|
|
var result3 = ValueCalculator.CalculateTradeValue(userId, option3, Underlying, parameter, PricingRequest.Pv);
|
|
var result4 = ValueCalculator.CalculateTradeValue(userId, option4, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(30715.28279692346, result1.Pv, 1e-10);
|
|
Assert.AreEqual(30630.600069456796, result2.Pv, 1e-10);
|
|
Assert.AreEqual(29268.976807251885, result3.Pv, 1e-10);
|
|
Assert.AreEqual(29189.216364369575, result4.Pv, 1e-10);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void AmericanBinaryDoubleTouchTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var option1 = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.9,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "DoubleOneTouch",
|
|
UpperBarrier = 1.1,
|
|
CashOrNothingAmount = SPOT * 0.1,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var option2 = new trade()
|
|
{
|
|
TradeType = "二元期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "American",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.9,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_binary_option = new trade_binary_option()
|
|
{
|
|
PayoffType = "DoubleNoTouch",
|
|
UpperBarrier = 1.1,
|
|
CashOrNothingAmount = SPOT * 0.1,
|
|
RebateType = "AtEnd"
|
|
}
|
|
};
|
|
|
|
var parameter = new BinaryOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, option1, Underlying, parameter, PricingRequest.Pv);
|
|
var result2 = ValueCalculator.CalculateTradeValue(userId, option2, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(16339.046613388811, result1.Pv, 1e-10);
|
|
Assert.AreEqual(83270.814664408739, result2.Pv, 1e-10);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void BarrierTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var option1 = new trade()
|
|
{
|
|
TradeType = "障碍期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.05,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_barrier_option = new trade_barrier_option()
|
|
{
|
|
BarrierType = "UpAndOut",
|
|
BarrierPrice = 1.1,
|
|
Discrete = "离散",
|
|
Rebate = SPOT * 0.05,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var option2 = new trade()
|
|
{
|
|
TradeType = "障碍期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.05,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_barrier_option = new trade_barrier_option()
|
|
{
|
|
BarrierType = "UpAndOut",
|
|
BarrierPrice = 1.1,
|
|
Discrete = "离散",
|
|
Rebate = SPOT * 0.05,
|
|
RebateType = "AtEnd"
|
|
}
|
|
};
|
|
|
|
var option3 = new trade()
|
|
{
|
|
TradeType = "障碍期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.95,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_barrier_option = new trade_barrier_option()
|
|
{
|
|
BarrierType = "DownAndOut",
|
|
BarrierPrice = 0.9,
|
|
Discrete = "离散",
|
|
Rebate = SPOT * 0.05,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var option4 = new trade()
|
|
{
|
|
TradeType = "障碍期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.95,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_barrier_option = new trade_barrier_option()
|
|
{
|
|
BarrierType = "DownAndOut",
|
|
BarrierPrice = 0.9,
|
|
Discrete = "离散",
|
|
Rebate = SPOT * 0.05,
|
|
RebateType = "AtEnd"
|
|
}
|
|
};
|
|
|
|
var parameter = new BarrierOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, option1, Underlying, parameter, PricingRequest.Pv);
|
|
var result2 = ValueCalculator.CalculateTradeValue(userId, option2, Underlying, parameter, PricingRequest.Pv);
|
|
var result3 = ValueCalculator.CalculateTradeValue(userId, option3, Underlying, parameter, PricingRequest.Pv);
|
|
var result4 = ValueCalculator.CalculateTradeValue(userId, option4, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(6434.9341859467013, result1.Pv, 1e-10);
|
|
Assert.AreEqual(6430.1233648704419, result2.Pv, 1e-10);
|
|
Assert.AreEqual(4836.0864487604222, result3.Pv, 1e-10);
|
|
Assert.AreEqual(4833.45426819408, result4.Pv, 1e-10);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void DoubleSharkFinTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
|
|
var option1 = new trade()
|
|
{
|
|
TradeType = "双鲨期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.95,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_double_sharkfin_option = new trade_double_sharkfin_option()
|
|
{
|
|
StrikeHigh = 1.05,
|
|
StrikeLow = 0.95,
|
|
BarrierHigh = 1.1,
|
|
BarrierLow = 0.9,
|
|
Rebate = SPOT * 0.04,
|
|
RebateHigh = SPOT * 0.06,
|
|
RebateType = "AtHit"
|
|
}
|
|
};
|
|
|
|
var option2 = new trade()
|
|
{
|
|
TradeType = "双鲨期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = MaturityDate,
|
|
ExerciseDate = MaturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.95,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
|
|
trade_double_sharkfin_option = new trade_double_sharkfin_option()
|
|
{
|
|
StrikeHigh = 1.05,
|
|
StrikeLow = 0.95,
|
|
BarrierHigh = 1.1,
|
|
BarrierLow = 0.9,
|
|
Rebate = SPOT * 0.04,
|
|
RebateHigh = SPOT * 0.06,
|
|
RebateType = "AtEnd"
|
|
}
|
|
};
|
|
|
|
var parameter = new DoubleSharkFinOptionParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, option1, Underlying, parameter, PricingRequest.Pv);
|
|
var result2 = ValueCalculator.CalculateTradeValue(userId, option2, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(12366.591429397329, result1.Pv, 1e-8);
|
|
Assert.AreEqual(12356.036818992074, result2.Pv, 1e-8);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void SnowballTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
var maturityDate = new DateTime(2020, 2, 24);
|
|
var option1 = new trade()
|
|
{
|
|
TradeType = "雪球期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = maturityDate,
|
|
ExerciseDate = maturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.0,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
ParticipationRate = 1,
|
|
|
|
trade_snowball = new trade_snowball()
|
|
{
|
|
KOBarrier = 1.03,
|
|
KIBarrier = 1.0,
|
|
Coupon = 0.0,
|
|
KORebate = 0.1,
|
|
//KOBarrierAdjustStep = 0.0,
|
|
//UseOptionPayoffAtMaturity = false,
|
|
KOObservationDates = QdpObservationHelper.GetObservationDateString(ValueDate, maturityDate, "1W")
|
|
}
|
|
};
|
|
|
|
var option2 = new trade()
|
|
{
|
|
TradeType = "雪球期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = maturityDate,
|
|
ExerciseDate = maturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.0,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
ParticipationRate = 1.0,
|
|
|
|
trade_snowball = new trade_snowball()
|
|
{
|
|
KOBarrier = 1.03,
|
|
KIBarrier = 1.0,
|
|
Coupon = 0.0,
|
|
KORebate = 0.1,
|
|
//KOBarrierAdjustStep = -0.01,
|
|
//UseOptionPayoffAtMaturity = false,
|
|
KOObservationDates = QdpObservationHelper.GetObservationDateString(ValueDate, maturityDate, "1W")
|
|
}
|
|
};
|
|
|
|
var option3 = new trade()
|
|
{
|
|
TradeType = "雪球期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = maturityDate,
|
|
ExerciseDate = maturityDate,
|
|
OptionType = "看涨",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 0.98,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
ParticipationRate = 1.0,
|
|
|
|
trade_snowball = new trade_snowball()
|
|
{
|
|
KOBarrier = 1.03,
|
|
KIBarrier = 1.0,
|
|
Coupon = 0.0,
|
|
KORebate = 0.1,
|
|
//KOBarrierAdjustStep = 0.0,
|
|
//UseOptionPayoffAtMaturity = true,
|
|
KOObservationDates = QdpObservationHelper.GetObservationDateString(ValueDate, maturityDate, "1W")
|
|
}
|
|
};
|
|
|
|
var parameter = new SnowballParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, option1, Underlying, parameter, PricingRequest.Pv);
|
|
var result2 = ValueCalculator.CalculateTradeValue(userId, option2, Underlying, parameter, PricingRequest.Pv);
|
|
var result3 = ValueCalculator.CalculateTradeValue(userId, option3, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(256.05315398303719, result1.Pv, 1.0);
|
|
Assert.AreEqual(257.09573597682572, result2.Pv, 1.0);
|
|
Assert.AreEqual(256.11164110697115, result3.Pv, 1.0);
|
|
}
|
|
|
|
[TestMethod]
|
|
public void PhoenixAutocallTest()
|
|
{
|
|
PS.ResetConfig("{\"SkewMapVolConstruction\":\"false\"}");
|
|
var maturityDate = new DateTime(2020, 2, 24);
|
|
var option1 = new trade()
|
|
{
|
|
TradeType = "凤凰期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = maturityDate,
|
|
ExerciseDate = maturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.0,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
ParticipationRate = 1,
|
|
|
|
trade_autocall = new trade_autocall()
|
|
{
|
|
KOBarrier = 1.03,
|
|
KIBarrier = 0.8,
|
|
CouponBarrier = 0.8,
|
|
Coupon = 0.05,
|
|
CouponPayType = CouponPayTypeEnum.AtCreated,
|
|
IncludeCouponAfterKI = false,
|
|
KOObservationDates = QdpObservationHelper.GetObservationDateString(ValueDate, maturityDate, "1M")
|
|
}
|
|
};
|
|
|
|
var option2 = new trade()
|
|
{
|
|
TradeType = "凤凰期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = maturityDate,
|
|
ExerciseDate = maturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.0,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
ParticipationRate = 1,
|
|
|
|
trade_autocall = new trade_autocall()
|
|
{
|
|
KOBarrier = 1.03,
|
|
KIBarrier = 0.8,
|
|
CouponBarrier = 1.03,
|
|
Coupon = 0.05,
|
|
CouponPayType = CouponPayTypeEnum.AtCreated,
|
|
IncludeCouponAfterKI = false,
|
|
KOObservationDates = QdpObservationHelper.GetObservationDateString(ValueDate, maturityDate, "1M")
|
|
}
|
|
};
|
|
|
|
//ki to put spread
|
|
var option4 = new trade()
|
|
{
|
|
TradeType = "凤凰期权",
|
|
TradeDate = ValueDate,
|
|
MaturityDate = maturityDate,
|
|
ExerciseDate = maturityDate,
|
|
OptionType = "看跌",
|
|
ExerciseMode = "European",
|
|
BuySell = "Buy",
|
|
UnderlyingInstrumentType = "Stock",
|
|
Strike = 1.0,
|
|
Notional = NOTIONAL,
|
|
IsMoneynessOption = "是",
|
|
SpotPrice = SPOT,
|
|
ParticipationRate = 1,
|
|
|
|
trade_autocall = new trade_autocall()
|
|
{
|
|
KOBarrier = 1.03,
|
|
KIBarrier = 0.8,
|
|
CouponBarrier = 0.8,
|
|
Coupon = 0.05,
|
|
CouponPayType = CouponPayTypeEnum.AtCreated,
|
|
IncludeCouponAfterKI = false,
|
|
SpreadStrike = 0.8,
|
|
KOObservationDates = QdpObservationHelper.GetObservationDateString(ValueDate, maturityDate, "1M")
|
|
}
|
|
};
|
|
|
|
var parameter = new AutocallParameter()
|
|
{
|
|
ValueDate = ValueDate,
|
|
Volatility = VOL,
|
|
SpotPrices = new Dictionary<string, double>() { { UnderlyingTicker, SPOT } },
|
|
RiskFreeRate = RISKFREE_RATE,
|
|
DividendRate = DIVIDEND_RATE
|
|
};
|
|
|
|
var result1 = ValueCalculator.CalculateTradeValue(userId, option1, Underlying, parameter, PricingRequest.Pv);
|
|
//var result2 = ValueCalculator.CalculateTradeValue(userId, option2, Underlying, parameter, PricingRequest.Pv);
|
|
var result4 = ValueCalculator.CalculateTradeValue(userId, option4, Underlying, parameter, PricingRequest.Pv);
|
|
|
|
Assert.AreEqual(3250, result1.Pv, 10);
|
|
//Assert.AreEqual(2328.39, result2.Pv, 10);
|
|
Assert.AreEqual(3519, result4.Pv, 10);
|
|
}
|
|
}
|
|
}
|