public void Test()
{
// Tests HW1 dynamics comparing the price of a call option on a bond
// calculated through simulation and the theoretical one.
Engine.MultiThread = true;
Document doc = new Document();
ProjectROV rov = new ProjectROV(doc);
doc.Part.Add(rov);
doc.DefaultProject.NMethods.m_UseAntiteticPaths = true;
int n_sim = 20000;
int n_steps = 1024;
double a = 0.2;
double DR = 0.02;
double r0 = 0.015;
double a1 = 0.02;
double sigma1 = 0.01;
double maturityOpt = 5.0;
double strike = 0.98192;
double tau = 1.0;
ModelParameter PT = new ModelParameter(maturityOpt, "TT");
PT.VarName = "TT";
rov.Symbols.Add(PT);
ModelParameter Ptau = new ModelParameter(tau, "tau");
Ptau.VarName = "tau";
rov.Symbols.Add(Ptau);
ModelParameter Pa = new ModelParameter(a, "a");
Pa.VarName = "a";
rov.Symbols.Add(Pa);
ModelParameter PDR = new ModelParameter(DR, "PDR");
PDR.VarName = "DR";
rov.Symbols.Add(PDR);
ModelParameter Pr0 = new ModelParameter(r0, "r0");
Pr0.VarName = "r0";
rov.Symbols.Add(Pr0);
ModelParameter Pstrike = new ModelParameter(strike, "strike");
Pstrike.VarName = "strike";
rov.Symbols.Add(Pstrike);
AFunction zerorate = new AFunction(rov);
zerorate.VarName = "zr";
zerorate.m_IndependentVariables = 1;
zerorate.m_Value = (RightValue)("(1-exp(-a*x1))*DR + r0");
rov.Symbols.Add(zerorate);
HW1 process = new HW1(a1, sigma1, "@zr");
StochasticProcessExtendible s = new StochasticProcessExtendible(rov, process);
rov.Processes.AddProcess(s);
// Set the discounting.
RiskFreeInfo rfi = rov.GetDiscountingModel() as RiskFreeInfo;
rfi.ActualizationType = EActualizationType.Stochastic;
rfi.m_deterministicRF = (ModelParameter)"@V1";
OptionTree op = new OptionTree(rov);
op.PayoffInfo.PayoffExpression = "Max(bond(TT;TT+tau;@v1)-strike;0)";
op.PayoffInfo.Timing.EndingTime.m_Value = (RightValue)maturityOpt;
op.PayoffInfo.European = true;
rov.Map.Root = op;
rov.NMethods.Technology = ETechType.T_SIMULATION;
rov.NMethods.PathsNumber = n_sim;
rov.NMethods.SimulationSteps = n_steps;
ROVSolver solver = new ROVSolver();
solver.BindToProject(rov);
solver.DoValuation(-1);
if (rov.HasErrors)
{
Console.WriteLine(rov.m_RuntimeErrorList[0]);
}
Assert.IsFalse(rov.HasErrors);
ResultItem price = rov.m_ResultList[0] as ResultItem;
double samplePrice = price.value;
double sampleDevSt = price.stdDev / Math.Sqrt((double)n_sim);
// Calculation of the theoretical value of the call.
CapHW1 cap = new CapHW1(zerorate);
double d1 = cap.D1(a1, sigma1, maturityOpt, maturityOpt + tau, strike);
double d2 = cap.D2(a1, sigma1, maturityOpt, maturityOpt + tau, strike);
double theoreticalPrice = ZCB(zerorate, maturityOpt + tau) * SpecialFunctions.NormCdf(d1) - strike * ZCB(zerorate, maturityOpt) * SpecialFunctions.NormCdf(d2);
Console.WriteLine("Theoretical Price = " + theoreticalPrice.ToString());
Console.WriteLine("Monte Carlo Price = " + samplePrice);
Console.WriteLine("Standard Deviation = " + sampleDevSt.ToString());
double tol = 4.0 * sampleDevSt;
Assert.Less(Math.Abs(theoreticalPrice - samplePrice), tol);
}