33
34
35
37 "CarrMadanMarginalProbability: shift (" <<
shift_ <<
") must be non-negative");
38
40 <<
strikes_.size() <<
") inconsistent to callPrices ("
42
43 QL_REQUIRE(!
strikes_.empty(),
"CarrMadanMarginalProbability: input moneyness is empty");
44
45
46
47 std::vector<Size> perm(
strikes.size());
48 std::iota(perm.begin(), perm.end(), 0);
49 std::sort(perm.begin(), perm.end(), [this](Size a, Size b) { return strikes_[a] < strikes_[b]; });
50
51
52
53 for (Size i = 1; i <
strikes_.size(); ++i) {
55 "CarrMadanMarginalProbability: duplicate strikes at "
56 << perm[i - 1] <<
", " << perm[i] <<
": " <<
strikes[perm[i - 1]] <<
", " <<
strikes[perm[i]]);
57 }
58
60 "CarrMadanMarginalProbability: all input strikes (" <<
strikes_[perm[0]] <<
") plus shift (" <<
shift
61 << ") must be positive or zero, got "
63
64
65
66 bool minusShiftStrikeAdded = false;
71 perm.insert(perm.begin(),
strikes_.size() - 1);
72 minusShiftStrikeAdded = true;
73 } else {
75 "CarrMadanMarginalProbability: call price ("
76 <<
callPrices_.front() <<
") for strike -shift (" << -
shift_ <<
") should match forward ("
78 }
79 }
80
81
82
84 "CarrMadanMarginalProbability: at least two strikes levels required (after adding -shift)");
85
86
87
88 std::vector<Real> Q(
strikes_.size() - 1);
89 for (Size i = 1; i <
strikes_.size(); ++i) {
91 }
92
93
94
95 std::vector<Real> BS(
strikes_.size() - 2);
96 for (Size i = 1; i <
strikes_.size() - 1; ++i) {
102 }
103
104
105
109
110
111
112 for (Size i = 0; i < Q.size(); ++i) {
113 if (Q[i] < -1.0E-10 || Q[i] > 1.0 + 1.0E-10) {
117 }
118 }
119
120
121
122 for (Size i = 0; i < BS.size(); ++i) {
123 if (BS[i] < -1.0E-10) {
128 }
129 }
130
131
132
134 q_[perm[0]] = 1.0 - Q.front();
135 for (Size i = 0; i < Q.size() - 1; ++i) {
136 q_[perm[i + 1]] = Q[i] - Q[i + 1];
137 }
138 q_[perm.back()] = Q.back();
139
140
141
142 if (minusShiftStrikeAdded) {
147 q_.erase(std::next(
q_.begin(), perm.front()));
148 }
149}
std::vector< Real > callPrices_
std::vector< bool > callSpreadArbitrage_
std::vector< Real > strikes_
const std::vector< Real > & strikes() const
std::vector< bool > butterflyArbitrage_
bool smileIsArbitrageFree_
const std::vector< Real > & callPrices() const
Filter close_enough(const RandomVariable &x, const RandomVariable &y)