forked from amaggiulli/QLNet
-
Notifications
You must be signed in to change notification settings - Fork 0
/
T_BlackFormula.cs
120 lines (108 loc) · 5.38 KB
/
T_BlackFormula.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
/*
Copyright (C) 2008-2014 Andrea Maggiulli ([email protected])
This file is part of QLNet Project https://github.com/amaggiulli/qlnet
QLNet is free software: you can redistribute it and/or modify it
under the terms of the QLNet license. You should have received a
copy of the license along with this program; if not, license is
available at <https://github.com/amaggiulli/QLNet/blob/develop/LICENSE>.
QLNet is a based on QuantLib, a free-software/open-source library
for financial quantitative analysts and developers - http://quantlib.org/
The QuantLib license is available online at http://quantlib.org/license.shtml.
This program is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the license for more details.
*/
using System;
using Xunit;
using QLNet;
namespace TestSuite
{
[Collection("QLNet CI Tests")]
public class T_BlackFormula
{
[Fact]
public void testBachelierImpliedVol()
{
// Testing Bachelier implied vol...
double forward = 1.0;
double bpvol = 0.01;
double tte = 10.0;
double stdDev = bpvol * Math.Sqrt(tte);
Option.Type optionType = Option.Type.Call;
double discount = 0.95;
double[] d = {-3.0, -2.0, -1.0, -0.5, 0.0, 0.5, 1.0, 2.0, 3.0};
for (int i = 0; i < d.Length; ++i)
{
double strike = forward - d[i] * bpvol * Math.Sqrt(tte);
double callPrem = Utils.bachelierBlackFormula(optionType, strike, forward, stdDev, discount);
double impliedBpVol = Utils.bachelierBlackFormulaImpliedVol(optionType, strike, forward, tte, callPrem, discount);
if (Math.Abs(bpvol - impliedBpVol) > 1.0e-12)
{
QAssert.Fail("Failed, expected " + bpvol + " realised " + impliedBpVol);
}
}
return;
}
[Fact]
public void testChambersImpliedVol()
{
// Testing Chambers-Nawalkha implied vol approximation
Option.Type[] types = {Option.Type.Call, Option.Type.Put};
double[] displacements = {0.0000, 0.0010, 0.0050, 0.0100, 0.0200};
double[] forwards = {-0.0010, 0.0000, 0.0050, 0.0100, 0.0200, 0.0500};
double[] strikes = {-0.0100, -0.0050, -0.0010, 0.0000, 0.0010, 0.0050, 0.0100, 0.0200, 0.0500, 0.1000};
double[] stdDevs = {0.10, 0.15, 0.20, 0.30, 0.50, 0.60, 0.70, 0.80, 1.00, 1.50, 2.00};
double[] discounts = {1.00, 0.95, 0.80, 1.10};
double tol = 5.0E-4;
for (int i1 = 0; i1 < types.Length; ++i1)
{
for (int i2 = 0; i2 < displacements.Length; ++i2)
{
for (int i3 = 0; i3 < forwards.Length; ++i3)
{
for (int i4 = 0; i4 < strikes.Length; ++i4)
{
for (int i5 = 0; i5 < stdDevs.Length; ++i5)
{
for (int i6 = 0; i6 < discounts.Length; ++i6)
{
if (forwards[i3] + displacements[i2] > 0.0 &&
strikes[i4] + displacements[i2] > 0.0)
{
double premium = Utils.blackFormula(
types[i1], strikes[i4], forwards[i3],
stdDevs[i5], discounts[i6],
displacements[i2]);
double atmPremium = Utils.blackFormula(
types[i1], forwards[i3], forwards[i3],
stdDevs[i5], discounts[i6],
displacements[i2]);
double iStdDev = Utils.blackFormulaImpliedStdDevChambers(
types[i1], strikes[i4], forwards[i3],
premium, atmPremium, discounts[i6],
displacements[i2]);
double moneyness = (strikes[i4] + displacements[i2]) /
(forwards[i3] + displacements[i2]);
if (moneyness > 1.0)
moneyness = 1.0 / moneyness;
double error = (iStdDev - stdDevs[i5]) / stdDevs[i5] * moneyness;
if (error > tol)
QAssert.Fail("Failed to verify Chambers-Nawalkha approximation for "
+ types[i1]
+ " displacement=" + displacements[i2]
+ " forward=" + forwards[i3]
+ " strike=" + strikes[i4]
+ " discount=" + discounts[i6]
+ " stddev=" + stdDevs[i5]
+ " result=" + iStdDev
+ " exceeds maximum error tolerance");
}
}
}
}
}
}
}
}
}
}