Skip to content

Commit fd39138

Browse files
committed
Add optional forward parameter to SmileSection pricing methods
1 parent 68f4edf commit fd39138

File tree

11 files changed

+136
-35
lines changed

11 files changed

+136
-35
lines changed

ql/experimental/volatility/noarbsabrsmilesection.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -57,19 +57,19 @@ void NoArbSabrSmileSection::init() {
5757
}
5858

5959
Real NoArbSabrSmileSection::optionPrice(Rate strike, Option::Type type,
60-
Real discount) const {
60+
Real discount, Real) const {
6161
Real call = model_->optionPrice(strike);
6262
return discount *
6363
(type == Option::Call ? call : call - (forward_ - strike));
6464
}
6565

6666
Real NoArbSabrSmileSection::digitalOptionPrice(Rate strike, Option::Type type,
67-
Real discount, Real) const {
67+
Real discount, Real, Real) const {
6868
Real call = model_->digitalOptionPrice(strike);
6969
return discount * (type == Option::Call ? call : 1.0 - call);
7070
}
7171

72-
Real NoArbSabrSmileSection::density(Rate strike, Real discount, Real) const {
72+
Real NoArbSabrSmileSection::density(Rate strike, Real discount, Real, Real) const {
7373
return discount * model_->density(strike);
7474
}
7575

ql/experimental/volatility/noarbsabrsmilesection.hpp

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -49,12 +49,15 @@ class NoArbSabrSmileSection : public SmileSection {
4949
Real maxStrike() const override { return QL_MAX_REAL; }
5050
Real atmLevel() const override { return forward_; }
5151
Real
52-
optionPrice(Rate strike, Option::Type type = Option::Call, Real discount = 1.0) const override;
52+
optionPrice(Rate strike, Option::Type type = Option::Call, Real discount = 1.0,
53+
Real forward = Null<Real>()) const override;
5354
Real digitalOptionPrice(Rate strike,
5455
Option::Type type = Option::Call,
5556
Real discount = 1.0,
56-
Real gap = 1.0e-5) const override;
57-
Real density(Rate strike, Real discount = 1.0, Real gap = 1.0E-4) const override;
57+
Real gap = 1.0e-5,
58+
Real forward = Null<Real>()) const override;
59+
Real density(Rate strike, Real discount = 1.0, Real gap = 1.0E-4,
60+
Real forward = Null<Real>()) const override;
5861

5962
ext::shared_ptr<NoArbSabrModel> model() { return model_; }
6063

ql/termstructures/volatility/atmadjustedsmilesection.hpp

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -48,24 +48,28 @@ namespace QuantLib {
4848

4949
Real optionPrice(Rate strike,
5050
Option::Type type = Option::Call,
51-
Real discount = 1.0) const override {
52-
return source_->optionPrice(adjustedStrike(strike), type, discount);
51+
Real discount = 1.0,
52+
Real forward = Null<Real>()) const override {
53+
return source_->optionPrice(adjustedStrike(strike), type, discount, forward);
5354
}
5455

5556
Real digitalOptionPrice(Rate strike,
5657
Option::Type type = Option::Call,
5758
Real discount = 1.0,
58-
Real gap = 1.0e-5) const override {
59+
Real gap = 1.0e-5,
60+
Real forward = Null<Real>()) const override {
5961
return source_->digitalOptionPrice(adjustedStrike(strike), type,
60-
discount, gap);
62+
discount, gap, forward);
6163
}
6264

63-
Real vega(Rate strike, Real discount = 1.0) const override {
64-
return source_->vega(adjustedStrike(strike), discount);
65+
Real vega(Rate strike, Real discount = 1.0,
66+
Real forward = Null<Real>()) const override {
67+
return source_->vega(adjustedStrike(strike), discount, forward);
6568
}
6669

67-
Real density(Rate strike, Real discount = 1.0, Real gap = 1.0E-4) const override {
68-
return source_->density(adjustedStrike(strike), discount, gap);
70+
Real density(Rate strike, Real discount = 1.0, Real gap = 1.0E-4,
71+
Real forward = Null<Real>()) const override {
72+
return source_->density(adjustedStrike(strike), discount, gap, forward);
6973
}
7074

7175
protected:

ql/termstructures/volatility/gaussian1dsmilesection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ namespace QuantLib {
7373
Real Gaussian1dSmileSection::atmLevel() const { return atm_; }
7474

7575
Real Gaussian1dSmileSection::optionPrice(Rate strike, Option::Type type,
76-
Real discount) const {
76+
Real discount, Real) const {
7777

7878
if (swapIndex_ != nullptr) {
7979
Swaption s = MakeSwaption(swapIndex_, fixingDate_, strike)

ql/termstructures/volatility/gaussian1dsmilesection.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,8 @@ class Gaussian1dSmileSection : public SmileSection {
5959
Real maxStrike() const override { return QL_MAX_REAL; }
6060

6161
Real atmLevel() const override;
62-
Real optionPrice(Rate strike, Option::Type = Option::Call, Real discount = 1.0) const override;
62+
Real optionPrice(Rate strike, Option::Type = Option::Call, Real discount = 1.0,
63+
Real forward = Null<Real>()) const override;
6364

6465
protected:
6566
Real volatilityImpl(Rate strike) const override;

ql/termstructures/volatility/kahalesmilesection.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,7 @@ namespace QuantLib {
224224
}
225225

226226
Real KahaleSmileSection::optionPrice(Rate strike, Option::Type type,
227-
Real discount) const {
227+
Real discount, Real) const {
228228
// option prices are directly available, so implement this function
229229
// rather than use smileSection
230230
// standard implementation

ql/termstructures/volatility/kahalesmilesection.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,8 @@ namespace QuantLib {
156156

157157
Real optionPrice(Rate strike,
158158
Option::Type type = Option::Call,
159-
Real discount = 1.0) const override;
159+
Real discount = 1.0,
160+
Real forward = Null<Real>()) const override;
160161

161162
protected:
162163
Volatility volatilityImpl(Rate strike) const override;

ql/termstructures/volatility/smilesection.cpp

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/*
44
Copyright (C) 2006 Mario Pucci
55
Copyright (C) 2013, 2015 Peter Caspers
6+
Copyright (C) 2026 Yassine Idyiahia
67
78
This file is part of QuantLib, a free-software/open-source library
89
for financial quantitative analysts and developers - http://quantlib.org/
@@ -71,10 +72,12 @@ namespace QuantLib {
7172

7273
Real SmileSection::optionPrice(Rate strike,
7374
Option::Type type,
74-
Real discount) const {
75-
Real atm = atmLevel();
75+
Real discount,
76+
Real forward) const {
77+
Real atm = forward != Null<Real>() ? forward : atmLevel();
7678
QL_REQUIRE(atm != Null<Real>(),
77-
"smile section must provide atm level to compute option price");
79+
"smile section must provide atm level "
80+
"or forward must be passed to compute option price");
7881
// if lognormal or shifted lognormal,
7982
// for strike at -shift, return option price even if outside
8083
// minstrike, maxstrike interval
@@ -88,28 +91,32 @@ namespace QuantLib {
8891
Real SmileSection::digitalOptionPrice(Rate strike,
8992
Option::Type type,
9093
Real discount,
91-
Real gap) const {
94+
Real gap,
95+
Real forward) const {
9296
Real m = volatilityType() == ShiftedLognormal ? Real(-shift()) : -QL_MAX_REAL;
9397
Real kl = std::max(strike-gap/2.0,m);
9498
Real kr = kl+gap;
9599
return (type==Option::Call ? 1.0 : -1.0) *
96-
(optionPrice(kl,type,discount)-optionPrice(kr,type,discount)) / gap;
100+
(optionPrice(kl,type,discount,forward)-optionPrice(kr,type,discount,forward)) / gap;
97101
}
98102

99-
Real SmileSection::density(Rate strike, Real discount, Real gap) const {
103+
Real SmileSection::density(Rate strike, Real discount, Real gap,
104+
Real forward) const {
100105
Real m = volatilityType() == ShiftedLognormal ? Real(-shift()) : -QL_MAX_REAL;
101106
Real kl = std::max(strike-gap/2.0,m);
102107
Real kr = kl+gap;
103-
return (digitalOptionPrice(kl,Option::Call,discount,gap) -
104-
digitalOptionPrice(kr,Option::Call,discount,gap)) / gap;
108+
return (digitalOptionPrice(kl,Option::Call,discount,gap,forward) -
109+
digitalOptionPrice(kr,Option::Call,discount,gap,forward)) / gap;
105110
}
106111

107-
Real SmileSection::vega(Rate strike, Real discount) const {
108-
Real atm = atmLevel();
112+
Real SmileSection::vega(Rate strike, Real discount,
113+
Real forward) const {
114+
Real atm = forward != Null<Real>() ? forward : atmLevel();
109115
QL_REQUIRE(atm != Null<Real>(),
110-
"smile section must provide atm level to compute option vega");
116+
"smile section must provide atm level "
117+
"or forward must be passed to compute option vega");
111118
if (volatilityType() == ShiftedLognormal)
112-
return blackFormulaVolDerivative(strike,atmLevel(),
119+
return blackFormulaVolDerivative(strike,atm,
113120
sqrt(variance(strike)),
114121
exerciseTime(),discount,shift())*0.01;
115122
else

ql/termstructures/volatility/smilesection.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
/*
44
Copyright (C) 2006 Mario Pucci
55
Copyright (C) 2013, 2015 Peter Caspers
6+
Copyright (C) 2026 Yassine Idyiahia
67
78
This file is part of QuantLib, a free-software/open-source library
89
for financial quantitative analysts and developers - http://quantlib.org/
@@ -67,16 +68,20 @@ namespace QuantLib {
6768
virtual const DayCounter& dayCounter() const { return dc_; }
6869
virtual Real optionPrice(Rate strike,
6970
Option::Type type = Option::Call,
70-
Real discount=1.0) const;
71+
Real discount=1.0,
72+
Real forward=Null<Real>()) const;
7173
virtual Real digitalOptionPrice(Rate strike,
7274
Option::Type type = Option::Call,
7375
Real discount=1.0,
74-
Real gap=1.0e-5) const;
76+
Real gap=1.0e-5,
77+
Real forward=Null<Real>()) const;
7578
virtual Real vega(Rate strike,
76-
Real discount=1.0) const;
79+
Real discount=1.0,
80+
Real forward=Null<Real>()) const;
7781
virtual Real density(Rate strike,
7882
Real discount=1.0,
79-
Real gap=1.0E-4) const;
83+
Real gap=1.0E-4,
84+
Real forward=Null<Real>()) const;
8085
Volatility volatility(Rate strike, VolatilityType type, Real shift=0.0) const;
8186
protected:
8287
virtual void initializeExerciseTime() const;

ql/termstructures/volatility/zabrsmilesection.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,8 @@ template <typename Evaluation> class ZabrSmileSection : public SmileSection {
6262
Real maxStrike() const override { return QL_MAX_REAL; }
6363
Real atmLevel() const override { return model_->forward(); }
6464
Real
65-
optionPrice(Rate strike, Option::Type type = Option::Call, Real discount = 1.0) const override {
65+
optionPrice(Rate strike, Option::Type type = Option::Call, Real discount = 1.0,
66+
Real forward = Null<Real>()) const override {
6667
return optionPrice(strike, type, discount, Evaluation());
6768
}
6869

0 commit comments

Comments
 (0)