From 4dea9e69976812a0d1e0a0ea03c1b2b50d0689d0 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Thu, 14 Aug 2025 11:31:15 -0400 Subject: [PATCH 1/3] follow upstream hierarchy --- quantlib/{instruments => }/_exercise.pxd | 0 quantlib/_option.pxd | 11 ++ quantlib/{instruments => }/_payoffs.pxd | 0 quantlib/{instruments => }/exercise.pxd | 2 +- quantlib/{instruments => }/exercise.pyx | 0 quantlib/instruments/_asian_options.pxd | 6 +- quantlib/instruments/_europeanoption.pxd | 12 ++ quantlib/instruments/_oneassetoption.pxd | 27 ++++ quantlib/instruments/_option.pxd | 76 ---------- quantlib/instruments/_swaption.pxd | 4 +- quantlib/instruments/_vanillaoption.pxd | 33 +++++ quantlib/instruments/api.py | 8 +- quantlib/instruments/asian_options.pxd | 2 +- quantlib/instruments/asian_options.pyx | 8 +- .../dividendschedule.pxd} | 2 +- .../dividendschedule.pyx} | 2 +- quantlib/instruments/europeanoption.pxd | 5 + quantlib/instruments/europeanoption.pyx | 17 +++ quantlib/instruments/oneassetoption.pxd | 5 + quantlib/instruments/oneassetoption.pyx | 48 +++++++ quantlib/instruments/option.pyx | 132 ------------------ quantlib/instruments/swaption.pxd | 2 +- quantlib/instruments/swaption.pyx | 2 +- quantlib/instruments/vanillaoption.pxd | 4 + quantlib/instruments/vanillaoption.pyx | 37 +++++ quantlib/mlab/option_pricing.py | 7 +- quantlib/models/_model.pxd | 2 +- quantlib/models/shortrate/onefactor_model.pyx | 2 +- .../onefactormodels/_gaussian1dmodel.pxd | 2 +- .../shortrate/onefactormodels/_hullwhite.pxd | 2 +- quantlib/{instruments => }/option.pxd | 4 - quantlib/option.pyx | 32 +++++ quantlib/{instruments => }/payoffs.pxd | 0 quantlib/{instruments => }/payoffs.pyx | 7 +- quantlib/pricingengines/_blackformula.pxd | 2 +- quantlib/pricingengines/blackformula.pyx | 4 +- .../vanilla/_fdblackscholesvanillaengine.pxd | 2 +- .../vanilla/fdblackscholesvanillaengine.pyx | 2 +- quantlib/pricingengines/vanilla/vanilla.pyx | 2 +- .../volatility/_smilesection.pxd | 2 +- .../volatility/smilesection.pyx | 2 +- quantlib/util/options.py | 8 +- 42 files changed, 272 insertions(+), 255 deletions(-) rename quantlib/{instruments => }/_exercise.pxd (100%) create mode 100644 quantlib/_option.pxd rename quantlib/{instruments => }/_payoffs.pxd (100%) rename quantlib/{instruments => }/exercise.pxd (83%) rename quantlib/{instruments => }/exercise.pyx (100%) create mode 100644 quantlib/instruments/_europeanoption.pxd create mode 100644 quantlib/instruments/_oneassetoption.pxd delete mode 100644 quantlib/instruments/_option.pxd create mode 100644 quantlib/instruments/_vanillaoption.pxd rename quantlib/{cashflows/dividend.pxd => instruments/dividendschedule.pxd} (74%) rename quantlib/{cashflows/dividend.pyx => instruments/dividendschedule.pyx} (90%) create mode 100644 quantlib/instruments/europeanoption.pxd create mode 100644 quantlib/instruments/europeanoption.pyx create mode 100644 quantlib/instruments/oneassetoption.pxd create mode 100644 quantlib/instruments/oneassetoption.pyx delete mode 100644 quantlib/instruments/option.pyx create mode 100644 quantlib/instruments/vanillaoption.pxd create mode 100644 quantlib/instruments/vanillaoption.pyx rename quantlib/{instruments => }/option.pxd (66%) create mode 100644 quantlib/option.pyx rename quantlib/{instruments => }/payoffs.pxd (100%) rename quantlib/{instruments => }/payoffs.pyx (93%) diff --git a/quantlib/instruments/_exercise.pxd b/quantlib/_exercise.pxd similarity index 100% rename from quantlib/instruments/_exercise.pxd rename to quantlib/_exercise.pxd diff --git a/quantlib/_option.pxd b/quantlib/_option.pxd new file mode 100644 index 000000000..3aee447a5 --- /dev/null +++ b/quantlib/_option.pxd @@ -0,0 +1,11 @@ +from ._instrument cimport Instrument +from ._exercise cimport Exercise +from ._payoffs cimport Payoff +from quantlib.handle cimport shared_ptr + + +cdef extern from 'ql/option.hpp' namespace 'QuantLib' nogil: + + cdef cppclass Option(Instrument): + shared_ptr[Payoff] payoff() + shared_ptr[Exercise] exercise() diff --git a/quantlib/instruments/_payoffs.pxd b/quantlib/_payoffs.pxd similarity index 100% rename from quantlib/instruments/_payoffs.pxd rename to quantlib/_payoffs.pxd diff --git a/quantlib/instruments/exercise.pxd b/quantlib/exercise.pxd similarity index 83% rename from quantlib/instruments/exercise.pxd rename to quantlib/exercise.pxd index 676ab339a..ed00cbf90 100644 --- a/quantlib/instruments/exercise.pxd +++ b/quantlib/exercise.pxd @@ -1,5 +1,5 @@ from quantlib.handle cimport shared_ptr -cimport quantlib.instruments._exercise as _exercise +from . cimport _exercise cdef extern from 'ql/exercise.hpp' namespace 'QuantLib::Exercise' nogil: cpdef enum class Type: diff --git a/quantlib/instruments/exercise.pyx b/quantlib/exercise.pyx similarity index 100% rename from quantlib/instruments/exercise.pyx rename to quantlib/exercise.pyx diff --git a/quantlib/instruments/_asian_options.pxd b/quantlib/instruments/_asian_options.pxd index 4570d65e7..0eedb2199 100644 --- a/quantlib/instruments/_asian_options.pxd +++ b/quantlib/instruments/_asian_options.pxd @@ -4,9 +4,9 @@ from libcpp.vector cimport vector from quantlib.handle cimport shared_ptr from quantlib.time._date cimport Date -from quantlib.instruments._exercise cimport Exercise -from quantlib.instruments._option cimport OneAssetOption -from quantlib.instruments._payoffs cimport StrikedTypePayoff +from quantlib._exercise cimport Exercise +from ._oneassetoption cimport OneAssetOption +from quantlib._payoffs cimport StrikedTypePayoff from .asian_options cimport AverageType diff --git a/quantlib/instruments/_europeanoption.pxd b/quantlib/instruments/_europeanoption.pxd new file mode 100644 index 000000000..3decf83e8 --- /dev/null +++ b/quantlib/instruments/_europeanoption.pxd @@ -0,0 +1,12 @@ +from .._payoffs cimport Payoff, StrikedTypePayoff +from ._vanillaoption cimport VanillaOption +from .._exercise cimport Exercise +from quantlib.handle cimport shared_ptr + +cdef extern from 'ql/instruments/europeanoption.hpp' namespace 'QuantLib' nogil: + + cdef cppclass EuropeanOption(VanillaOption): + EuropeanOption( + shared_ptr[StrikedTypePayoff]& payoff, + shared_ptr[Exercise]& exercise + ) diff --git a/quantlib/instruments/_oneassetoption.pxd b/quantlib/instruments/_oneassetoption.pxd new file mode 100644 index 000000000..11190192b --- /dev/null +++ b/quantlib/instruments/_oneassetoption.pxd @@ -0,0 +1,27 @@ +from quantlib.types cimport Real +from .._option cimport Option +from quantlib.handle cimport shared_ptr +from .._exercise cimport Exercise +from .._payoffs cimport StrikedTypePayoff +from quantlib.pricingengines._pricing_engine cimport PricingEngine + +cdef extern from 'ql/instruments/oneassetoption.hpp' namespace 'QuantLib' nogil: + + cdef cppclass OneAssetOption(Option): + cppclass engine(PricingEngine): + pass + OneAssetOption( + shared_ptr[StrikedTypePayoff]& payoff, + shared_ptr[Exercise]& exercise + ) + Real delta() except + + Real deltaForward() except + + Real elasticity() except + + Real gamma() except + + Real theta() except + + Real thetaPerDay() except + + Real vega() except + + Real rho() except + + Real dividendRho() except + + Real strikeSensitivity() except + + Real itmCashProbability() except + diff --git a/quantlib/instruments/_option.pxd b/quantlib/instruments/_option.pxd deleted file mode 100644 index 47daad70f..000000000 --- a/quantlib/instruments/_option.pxd +++ /dev/null @@ -1,76 +0,0 @@ -from quantlib.types cimport Real, Size, Volatility -from libcpp cimport bool -from libcpp.vector cimport vector - -from .._instrument cimport Instrument -from ._dividendschedule cimport DividendSchedule -from ._payoffs cimport Payoff, StrikedTypePayoff -from ._exercise cimport Exercise -from quantlib.handle cimport shared_ptr -from quantlib.time._date cimport Date -from quantlib.processes._black_scholes_process cimport GeneralizedBlackScholesProcess -from quantlib.pricingengines._pricing_engine cimport PricingEngine - - -cdef extern from 'ql/option.hpp' namespace 'QuantLib' nogil: - - cdef cppclass Option(Instrument): - shared_ptr[Payoff] payoff() - shared_ptr[Exercise] exercise() - -cdef extern from 'ql/instruments/oneassetoption.hpp' namespace 'QuantLib' nogil: - - cdef cppclass OneAssetOption(Option): - cppclass engine(PricingEngine): - pass - OneAssetOption( - shared_ptr[StrikedTypePayoff]& payoff, - shared_ptr[Exercise]& exercise - ) - bool isExpired() - Real delta() except + - Real deltaForward() except + - Real elasticity() except + - Real gamma() except + - Real theta() except + - Real thetaPerDay() except + - Real vega() except + - Real rho() except + - Real dividendRho() except + - Real strikeSensitivity() except + - Real itmCashProbability() except + - - -cdef extern from 'ql/instruments/vanillaoption.hpp' namespace 'QuantLib' nogil: - - cdef cppclass VanillaOption(OneAssetOption): - VanillaOption( - shared_ptr[StrikedTypePayoff]& payoff, - shared_ptr[Exercise]& exercise - ) - Volatility impliedVolatility( - Real price, - shared_ptr[GeneralizedBlackScholesProcess]& process, - Real accuracy, - Size maxEvaluations, - Volatility minVol, - Volatility maxVol - ) except + - Volatility impliedVolatility( - Real price, - shared_ptr[GeneralizedBlackScholesProcess]& process, - DividendSchedule dividens, - Real accuracy, # 1.0e-4 - Size maxEvaluations, #100 - Volatility minVol, # 1.0e-7 - Volatility maxVol # 4.0 - ) except + - - -cdef extern from 'ql/instruments/europeanoption.hpp' namespace 'QuantLib' nogil: - - cdef cppclass EuropeanOption(VanillaOption): - EuropeanOption( - shared_ptr[StrikedTypePayoff]& payoff, - shared_ptr[Exercise]& exercise - ) diff --git a/quantlib/instruments/_swaption.pxd b/quantlib/instruments/_swaption.pxd index 0826e9c36..4c9f9e56d 100644 --- a/quantlib/instruments/_swaption.pxd +++ b/quantlib/instruments/_swaption.pxd @@ -2,8 +2,8 @@ include '../types.pxi' from quantlib.handle cimport shared_ptr, optional from ._fixedvsfloatingswap cimport FixedVsFloatingSwap from ._overnightindexedswap cimport OvernightIndexedSwap -from ._option cimport Option -from ._exercise cimport Exercise +from .._option cimport Option +from .._exercise cimport Exercise from .swap cimport Type as SwapType from quantlib.termstructures._yield_term_structure cimport YieldTermStructure from quantlib.termstructures.volatility.volatilitytype cimport VolatilityType diff --git a/quantlib/instruments/_vanillaoption.pxd b/quantlib/instruments/_vanillaoption.pxd new file mode 100644 index 000000000..426907c6c --- /dev/null +++ b/quantlib/instruments/_vanillaoption.pxd @@ -0,0 +1,33 @@ +from quantlib.types cimport Real, Size, Volatility +from ._oneassetoption cimport OneAssetOption +from ._dividendschedule cimport DividendSchedule +from .._payoffs cimport StrikedTypePayoff +from .._exercise cimport Exercise + +from quantlib.processes._black_scholes_process cimport GeneralizedBlackScholesProcess +from quantlib.handle cimport shared_ptr + +cdef extern from 'ql/instruments/vanillaoption.hpp' namespace 'QuantLib' nogil: + + cdef cppclass VanillaOption(OneAssetOption): + VanillaOption( + shared_ptr[StrikedTypePayoff]& payoff, + shared_ptr[Exercise]& exercise + ) + Volatility impliedVolatility( + Real price, + shared_ptr[GeneralizedBlackScholesProcess]& process, + Real accuracy, # 1.0e-4 + Size maxEvaluations, #100 + Volatility minVol, # 1.0e-7 + Volatility maxVol # 4.0 + ) except + + Volatility impliedVolatility( + Real price, + shared_ptr[GeneralizedBlackScholesProcess]& process, + DividendSchedule dividends, + Real accuracy, # 1.0e-4 + Size maxEvaluations, #100 + Volatility minVol, # 1.0e-7 + Volatility maxVol # 4.0 + ) except + diff --git a/quantlib/instruments/api.py b/quantlib/instruments/api.py index c4d226d1d..3643b82fd 100644 --- a/quantlib/instruments/api.py +++ b/quantlib/instruments/api.py @@ -2,9 +2,11 @@ from .bondforward import BondForward from .credit_default_swap import CreditDefaultSwap, PricingModel from ..default import Protection -from .exercise import EuropeanExercise, AmericanExercise -from .option import VanillaOption, EuropeanOption, OptionType -from .payoffs import PlainVanillaPayoff +from ..exercise import EuropeanExercise, AmericanExercise +from ..option import OptionType +from .vanillaoption import VanillaOption +from .europeanoption import EuropeanOption +from ..payoffs import PlainVanillaPayoff from .swap import Swap from .vanillaswap import VanillaSwap from .make_vanilla_swap import MakeVanillaSwap diff --git a/quantlib/instruments/asian_options.pxd b/quantlib/instruments/asian_options.pxd index 31e12b849..86dde71ef 100644 --- a/quantlib/instruments/asian_options.pxd +++ b/quantlib/instruments/asian_options.pxd @@ -1,4 +1,4 @@ -from quantlib.instruments.option cimport OneAssetOption +from .oneassetoption cimport OneAssetOption cdef extern from 'ql/instruments/averagetype.hpp' namespace 'QuantLib::Average': cpdef enum class AverageType "QuantLib::Average::Type": diff --git a/quantlib/instruments/asian_options.pyx b/quantlib/instruments/asian_options.pyx index 43412b57b..da1df2635 100644 --- a/quantlib/instruments/asian_options.pyx +++ b/quantlib/instruments/asian_options.pyx @@ -5,11 +5,11 @@ from libcpp.vector cimport vector from quantlib.handle cimport shared_ptr, static_pointer_cast cimport quantlib.time._date as _date from quantlib.time.date cimport Date -from quantlib.instruments.payoffs cimport StrikedTypePayoff +from quantlib.payoffs cimport StrikedTypePayoff -from .option cimport OneAssetOption -from .exercise cimport Exercise -from . cimport _payoffs +from .oneassetoption cimport OneAssetOption +from ..exercise cimport Exercise +from .. cimport _payoffs from .._instrument cimport Instrument as _Instrument from ._asian_options cimport ( ContinuousAveragingAsianOption as _ContinuousAveragingAsianOption, diff --git a/quantlib/cashflows/dividend.pxd b/quantlib/instruments/dividendschedule.pxd similarity index 74% rename from quantlib/cashflows/dividend.pxd rename to quantlib/instruments/dividendschedule.pxd index 098fdfe71..ea8865d45 100644 --- a/quantlib/cashflows/dividend.pxd +++ b/quantlib/instruments/dividendschedule.pxd @@ -1,5 +1,5 @@ from libcpp.vector cimport vector -from ._dividend cimport Dividend +from quantlib.cashflows._dividend cimport Dividend from quantlib.handle cimport shared_ptr cdef class DividendSchedule: diff --git a/quantlib/cashflows/dividend.pyx b/quantlib/instruments/dividendschedule.pyx similarity index 90% rename from quantlib/cashflows/dividend.pyx rename to quantlib/instruments/dividendschedule.pyx index 83d92b708..99f01c743 100644 --- a/quantlib/cashflows/dividend.pyx +++ b/quantlib/instruments/dividendschedule.pyx @@ -1,7 +1,7 @@ from quantlib.time.date cimport _qldate_from_pydate, _pydate_from_qldate from quantlib.time._date cimport Date from quantlib.types cimport Real -from ._dividend cimport DividendVector, Dividend +from quantlib.cashflows._dividend cimport DividendVector, Dividend cdef class DividendSchedule: def __init__(self, list dividend_dates, vector[Real] dividends): diff --git a/quantlib/instruments/europeanoption.pxd b/quantlib/instruments/europeanoption.pxd new file mode 100644 index 000000000..f5111861f --- /dev/null +++ b/quantlib/instruments/europeanoption.pxd @@ -0,0 +1,5 @@ +"""European option on a single asset""" +from .vanillaoption cimport VanillaOption + +cdef class EuropeanOption(VanillaOption): + pass diff --git a/quantlib/instruments/europeanoption.pyx b/quantlib/instruments/europeanoption.pyx new file mode 100644 index 000000000..75b8ae384 --- /dev/null +++ b/quantlib/instruments/europeanoption.pyx @@ -0,0 +1,17 @@ +from . cimport _europeanoption as _eo +from ..payoffs cimport StrikedTypePayoff +from ..exercise cimport Exercise +from .. cimport _payoffs +from quantlib.handle cimport shared_ptr, static_pointer_cast + +cdef class EuropeanOption(VanillaOption): + """European option on a single asset""" + def __init__(self, StrikedTypePayoff payoff not None, Exercise exercise not None): + + cdef shared_ptr[_payoffs.StrikedTypePayoff] payoff_ptr = \ + static_pointer_cast[_payoffs.StrikedTypePayoff]( + payoff._thisptr) + + self._thisptr.reset( + new _eo.EuropeanOption(payoff_ptr, exercise._thisptr) + ) diff --git a/quantlib/instruments/oneassetoption.pxd b/quantlib/instruments/oneassetoption.pxd new file mode 100644 index 000000000..b276ee6a2 --- /dev/null +++ b/quantlib/instruments/oneassetoption.pxd @@ -0,0 +1,5 @@ +from ..option cimport Option +from . cimport _oneassetoption as _oa + +cdef class OneAssetOption(Option): + cdef inline _oa.OneAssetOption* as_ptr(self) noexcept nogil diff --git a/quantlib/instruments/oneassetoption.pyx b/quantlib/instruments/oneassetoption.pyx new file mode 100644 index 000000000..b93ea1488 --- /dev/null +++ b/quantlib/instruments/oneassetoption.pyx @@ -0,0 +1,48 @@ +cdef class OneAssetOption(Option): + + cdef inline _oa.OneAssetOption* as_ptr(self) noexcept nogil: + return <_oa.OneAssetOption*>self._thisptr.get() + + @property + def delta(self): + return self.as_ptr().delta() + + @property + def delta_forward(self): + return self.as_ptr().deltaForward() + + @property + def elasticity(self): + return self.as_ptr().elasticity() + + @property + def gamma(self): + return self.as_ptr().gamma() + + @property + def theta(self): + return self.as_ptr().theta() + + @property + def theta_per_day(self): + return self.as_ptr().thetaPerDay() + + @property + def vega(self): + return self.as_ptr().vega() + + @property + def rho(self): + return self.as_ptr().rho() + + @property + def dividend_rho(self): + return self.as_ptr().dividendRho() + + @property + def strike_sensitivity(self): + return self.as_ptr().strikeSensitivity() + + @property + def itm_cash_probability(self): + return self.as_ptr().itmCashProbability() diff --git a/quantlib/instruments/option.pyx b/quantlib/instruments/option.pyx deleted file mode 100644 index 7a364da1d..000000000 --- a/quantlib/instruments/option.pyx +++ /dev/null @@ -1,132 +0,0 @@ -include '../types.pxi' - -# Cython imports -from libcpp cimport bool - -from . cimport _option -from . cimport _payoffs -from .exercise cimport Exercise -from quantlib.cashflows.dividend cimport DividendSchedule -cimport quantlib._instrument as _instrument -cimport quantlib.time._date as _date -cimport quantlib.pricingengines._pricing_engine as _pe -cimport quantlib.processes._black_scholes_process as _bsp - -from quantlib.handle cimport shared_ptr, static_pointer_cast -from quantlib.instruments.payoffs cimport Payoff, StrikedTypePayoff -from quantlib.pricingengines.engine cimport PricingEngine -from quantlib.processes.black_scholes_process cimport GeneralizedBlackScholesProcess - -cdef class Option(Instrument): - def __init__(self): - raise NotImplementedError( - 'Cannot implement this abstract class. Use child like the ' - 'VanillaOption' - ) - - def __str__(self): - return '%s %s %s' % ( - type(self).__name__, str(self.exercise), str(self.payoff) - ) - - @property - def exercise(self): - cdef Exercise ex = Exercise.__new__(Exercise) - ex._thisptr = (<_option.Option*>self._thisptr.get()).exercise() - return ex - - @property - def payoff(self): - cdef Payoff po = Payoff.__new__(Payoff) - po._thisptr = (<_option.Option*>self._thisptr.get()).payoff() - return po - -cdef class OneAssetOption(Option): - - cdef inline _option.OneAssetOption* as_ptr(self) nogil: - return <_option.OneAssetOption*>self._thisptr.get() - - @property - def delta(self): - return self.as_ptr().delta() - - @property - def delta_forward(self): - return self.as_ptr().deltaForward() - - @property - def elasticity(self): - return self.as_ptr().elasticity() - - property gamma: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).gamma() - - property theta: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).theta() - - property theta_per_day: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).thetaPerDay() - - property vega: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).vega() - - property rho: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).rho() - - property dividend_rho: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).dividendRho() - - property strike_sensitivity: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).strikeSensitivity() - - property itm_cash_probability: - def __get__(self): - return (<_option.OneAssetOption *> self._thisptr.get()).itmCashProbability() - - -cdef class VanillaOption(OneAssetOption): - - def __init__(self, StrikedTypePayoff payoff not None, Exercise exercise not None): - - self._thisptr = shared_ptr[_instrument.Instrument]( \ - new _option.VanillaOption( - static_pointer_cast[_payoffs.StrikedTypePayoff](payoff._thisptr), - exercise._thisptr) - ) - - - def implied_volatility(self, Real price, - GeneralizedBlackScholesProcess process, - DividendSchedule dividends=None, - Real accuracy=1e-4, - Size max_evaluations=100, - Volatility min_vol=1e-7, Volatility max_vol=4.0): - - cdef shared_ptr[_bsp.GeneralizedBlackScholesProcess] process_ptr = \ - static_pointer_cast[_bsp.GeneralizedBlackScholesProcess](process._thisptr) - if dividends is None: - return (<_option.VanillaOption *>self._thisptr.get()).impliedVolatility( - price, process_ptr, accuracy, max_evaluations, min_vol, max_vol) - else: - return (<_option.VanillaOption *>self._thisptr.get()).impliedVolatility( - price, process_ptr, dividends.schedule, accuracy, max_evaluations, min_vol, max_vol) - - -cdef class EuropeanOption(VanillaOption): - - def __init__(self, StrikedTypePayoff payoff not None, Exercise exercise not None): - - cdef shared_ptr[_payoffs.StrikedTypePayoff] payoff_ptr = \ - static_pointer_cast[_payoffs.StrikedTypePayoff]( - payoff._thisptr) - - self._thisptr = shared_ptr[_instrument.Instrument]( \ - new _option.EuropeanOption(payoff_ptr, exercise._thisptr) - ) diff --git a/quantlib/instruments/swaption.pxd b/quantlib/instruments/swaption.pxd index 82462da91..febbe1f91 100644 --- a/quantlib/instruments/swaption.pxd +++ b/quantlib/instruments/swaption.pxd @@ -1,5 +1,5 @@ from . cimport _swaption -from .option cimport Option +from ..option cimport Option cdef extern from "ql/instruments/swaption.hpp" namespace "QuantLib::Settlement": cpdef enum class Method "QuantLib::Settlement::Method": diff --git a/quantlib/instruments/swaption.pyx b/quantlib/instruments/swaption.pyx index 0895ef71f..fb33f5556 100644 --- a/quantlib/instruments/swaption.pyx +++ b/quantlib/instruments/swaption.pyx @@ -5,7 +5,7 @@ from quantlib.termstructures.volatility.volatilitytype cimport ( VolatilityType, ShiftedLognormal ) from quantlib.termstructures.yield_term_structure cimport YieldTermStructure from quantlib.termstructures cimport _yield_term_structure as _yts -from .exercise cimport Exercise +from ..exercise cimport Exercise from .swap cimport Type as SwapType from .fixedvsfloatingswap cimport FixedVsFloatingSwap from . cimport _fixedvsfloatingswap diff --git a/quantlib/instruments/vanillaoption.pxd b/quantlib/instruments/vanillaoption.pxd new file mode 100644 index 000000000..beadc42b7 --- /dev/null +++ b/quantlib/instruments/vanillaoption.pxd @@ -0,0 +1,4 @@ +from .oneassetoption cimport OneAssetOption + +cdef class VanillaOption(OneAssetOption): + pass diff --git a/quantlib/instruments/vanillaoption.pyx b/quantlib/instruments/vanillaoption.pyx new file mode 100644 index 000000000..8521e8861 --- /dev/null +++ b/quantlib/instruments/vanillaoption.pyx @@ -0,0 +1,37 @@ +from quantlib.handle cimport shared_ptr, static_pointer_cast +from quantlib.types cimport Real, Size, Volatility +from quantlib.processes.black_scholes_process cimport GeneralizedBlackScholesProcess +from quantlib.processes cimport _black_scholes_process as _bsp +from .dividendschedule cimport DividendSchedule +from ..exercise cimport Exercise +from ..payoffs cimport StrikedTypePayoff +from .. cimport _payoffs + +from . cimport _vanillaoption as _va + +cdef class VanillaOption(OneAssetOption): + + def __init__(self, StrikedTypePayoff payoff not None, Exercise exercise not None): + + self._thisptr.reset( + new _va.VanillaOption( + static_pointer_cast[_payoffs.StrikedTypePayoff](payoff._thisptr), + exercise._thisptr + ) + ) + + def implied_volatility(self, Real price, + GeneralizedBlackScholesProcess process, + DividendSchedule dividends=None, + Real accuracy=1e-4, + Size max_evaluations=100, + Volatility min_vol=1e-7, Volatility max_vol=4.0): + + cdef shared_ptr[_bsp.GeneralizedBlackScholesProcess] process_ptr = \ + static_pointer_cast[_bsp.GeneralizedBlackScholesProcess](process._thisptr) + if dividends is None: + return (<_va.VanillaOption *>self._thisptr.get()).impliedVolatility( + price, process_ptr, accuracy, max_evaluations, min_vol, max_vol) + else: + return (<_va.VanillaOption *>self._thisptr.get()).impliedVolatility( + price, process_ptr, dividends.schedule, accuracy, max_evaluations, min_vol, max_vol) diff --git a/quantlib/mlab/option_pricing.py b/quantlib/mlab/option_pricing.py index 85408bb2b..ac9c303c0 100644 --- a/quantlib/mlab/option_pricing.py +++ b/quantlib/mlab/option_pricing.py @@ -10,9 +10,10 @@ import numpy as np import quantlib.reference.names as nm -from quantlib.instruments.option import VanillaOption, OptionType -from quantlib.instruments.exercise import EuropeanExercise -from quantlib.instruments.payoffs import PlainVanillaPayoff +from quantlib.option import OptionType +from quantlib.instruments.vanillaoption import VanillaOption +from quantlib.exercise import EuropeanExercise +from quantlib.payoffs import PlainVanillaPayoff from quantlib.models.equity.heston_model import HestonModel from quantlib.processes.heston_process import HestonProcess from quantlib.quotes import SimpleQuote diff --git a/quantlib/models/_model.pxd b/quantlib/models/_model.pxd index 1205549e8..3fc5be03e 100644 --- a/quantlib/models/_model.pxd +++ b/quantlib/models/_model.pxd @@ -4,7 +4,7 @@ from quantlib.types cimport DiscountFactor, Real, Size, Time from quantlib.handle cimport shared_ptr, Handle from quantlib.termstructures._yield_term_structure cimport YieldTermStructure -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType from quantlib._numericalmethod cimport Lattice from quantlib._time_grid cimport TimeGrid from quantlib.math._optimization cimport Constraint, EndCriteria, OptimizationMethod diff --git a/quantlib/models/shortrate/onefactor_model.pyx b/quantlib/models/shortrate/onefactor_model.pyx index da539899c..135b38def 100644 --- a/quantlib/models/shortrate/onefactor_model.pyx +++ b/quantlib/models/shortrate/onefactor_model.pyx @@ -9,7 +9,7 @@ from quantlib.types cimport Rate, Real, Time from quantlib.handle cimport static_pointer_cast -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType cimport quantlib.models.shortrate._onefactor_model as _ofm cimport quantlib._stochastic_process as _sp from quantlib.stochastic_process cimport StochasticProcess1D diff --git a/quantlib/models/shortrate/onefactormodels/_gaussian1dmodel.pxd b/quantlib/models/shortrate/onefactormodels/_gaussian1dmodel.pxd index 26e4616e8..0c32725bc 100644 --- a/quantlib/models/shortrate/onefactormodels/_gaussian1dmodel.pxd +++ b/quantlib/models/shortrate/onefactormodels/_gaussian1dmodel.pxd @@ -3,7 +3,7 @@ from quantlib.time._date cimport Date from quantlib.types cimport Rate, Real, SizeTime from quantlib.handle cimport Handle, shared_ptr from quantlib.termstructures._yield_term_structure cimport YieldTermStructure -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType from ..._model cimport TermStructureConsistentModel cdef extern from 'ql/models/shortrate/onefactormodels/gaussian1dmodel.hpp' namespace 'QuantLib' nogil: diff --git a/quantlib/models/shortrate/onefactormodels/_hullwhite.pxd b/quantlib/models/shortrate/onefactormodels/_hullwhite.pxd index f56debcda..3aa098223 100644 --- a/quantlib/models/shortrate/onefactormodels/_hullwhite.pxd +++ b/quantlib/models/shortrate/onefactormodels/_hullwhite.pxd @@ -8,7 +8,7 @@ from quantlib.types cimport Rate, Real, Time from quantlib.handle cimport Handle from quantlib.termstructures._yield_term_structure cimport YieldTermStructure -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType from ._vasicek cimport Vasicek from ..._model cimport TermStructureConsistentModel diff --git a/quantlib/instruments/option.pxd b/quantlib/option.pxd similarity index 66% rename from quantlib/instruments/option.pxd rename to quantlib/option.pxd index fcbd9994f..583ab2f53 100644 --- a/quantlib/instruments/option.pxd +++ b/quantlib/option.pxd @@ -1,5 +1,4 @@ from quantlib.instrument cimport Instrument -from . cimport _option cdef extern from 'ql/option.hpp' namespace 'QuantLib::Option': cpdef enum class OptionType "QuantLib::Option::Type": @@ -10,6 +9,3 @@ cdef extern from 'ql/option.hpp' namespace 'QuantLib::Option': cdef class Option(Instrument): pass - -cdef class OneAssetOption(Option): - cdef inline _option.OneAssetOption* as_ptr(self) nogil diff --git a/quantlib/option.pyx b/quantlib/option.pyx new file mode 100644 index 000000000..64584082e --- /dev/null +++ b/quantlib/option.pyx @@ -0,0 +1,32 @@ +# Cython imports +from . cimport _option +from .exercise cimport Exercise +from .payoffs cimport Payoff + +cdef class Option(Instrument): + """base option class""" + def __init__(self): + raise NotImplementedError( + 'Cannot implement this abstract class. Use child like the ' + 'VanillaOption' + ) + + Put = OptionType.Put + Call = OptionType.Call + + def __str__(self): + return '%s %s %s' % ( + type(self).__name__, str(self.exercise), str(self.payoff) + ) + + @property + def exercise(self) -> Exercise: + cdef Exercise ex = Exercise.__new__(Exercise) + ex._thisptr = (<_option.Option*>self._thisptr.get()).exercise() + return ex + + @property + def payoff(self) -> Payoff: + cdef Payoff po = Payoff.__new__(Payoff) + po._thisptr = (<_option.Option*>self._thisptr.get()).payoff() + return po diff --git a/quantlib/instruments/payoffs.pxd b/quantlib/payoffs.pxd similarity index 100% rename from quantlib/instruments/payoffs.pxd rename to quantlib/payoffs.pxd diff --git a/quantlib/instruments/payoffs.pyx b/quantlib/payoffs.pyx similarity index 93% rename from quantlib/instruments/payoffs.pyx rename to quantlib/payoffs.pyx index 38990ea49..a813558a2 100644 --- a/quantlib/instruments/payoffs.pyx +++ b/quantlib/payoffs.pyx @@ -1,4 +1,4 @@ -include '../types.pxi' +include 'types.pxi' from cython.operator import dereference as deref # cython imports @@ -28,7 +28,6 @@ cdef class StrikedTypePayoff(Payoff): cdef class PlainVanillaPayoff(StrikedTypePayoff): - """ Plain vanilla payoff. Parameters @@ -39,10 +38,6 @@ cdef class PlainVanillaPayoff(StrikedTypePayoff): strike: double The strike value - Properties - ---------- - option_type: Call or Put - strike: float """ def __init__(self, OptionType option_type, double strike): diff --git a/quantlib/pricingengines/_blackformula.pxd b/quantlib/pricingengines/_blackformula.pxd index 646c5b2b0..cf8b1e279 100644 --- a/quantlib/pricingengines/_blackformula.pxd +++ b/quantlib/pricingengines/_blackformula.pxd @@ -1,5 +1,5 @@ include '../types.pxi' -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType cdef extern from 'ql/pricingengines/blackformula.hpp' namespace 'QuantLib': diff --git a/quantlib/pricingengines/blackformula.pyx b/quantlib/pricingengines/blackformula.pyx index 1a7c09bb8..546f8937c 100644 --- a/quantlib/pricingengines/blackformula.pyx +++ b/quantlib/pricingengines/blackformula.pyx @@ -1,9 +1,9 @@ include '../types.pxi' from . cimport _blackformula as _bf -cimport quantlib.instruments._option as _opt +cimport quantlib._option as _opt -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType from math import sqrt, log diff --git a/quantlib/pricingengines/vanilla/_fdblackscholesvanillaengine.pxd b/quantlib/pricingengines/vanilla/_fdblackscholesvanillaengine.pxd index 245d1b4dc..3ccd828f7 100644 --- a/quantlib/pricingengines/vanilla/_fdblackscholesvanillaengine.pxd +++ b/quantlib/pricingengines/vanilla/_fdblackscholesvanillaengine.pxd @@ -1,7 +1,7 @@ from libcpp cimport bool from quantlib.handle cimport shared_ptr from quantlib.types cimport Size, Real -from quantlib.instruments._option cimport VanillaOption +from quantlib.instruments._vanillaoption cimport VanillaOption from quantlib.instruments._dividendschedule cimport DividendSchedule from quantlib.processes._black_scholes_process cimport GeneralizedBlackScholesProcess from quantlib.methods.finitedifferences.solvers._fdmbackwardsolver cimport FdmSchemeDesc diff --git a/quantlib/pricingengines/vanilla/fdblackscholesvanillaengine.pyx b/quantlib/pricingengines/vanilla/fdblackscholesvanillaengine.pyx index 6bf6c3124..c19686d47 100644 --- a/quantlib/pricingengines/vanilla/fdblackscholesvanillaengine.pyx +++ b/quantlib/pricingengines/vanilla/fdblackscholesvanillaengine.pyx @@ -2,7 +2,7 @@ from libcpp cimport bool from cython.operator cimport dereference as deref from quantlib.utilities.null cimport Null -from quantlib.cashflows.dividend cimport DividendSchedule +from quantlib.instruments.dividendschedule cimport DividendSchedule from quantlib.handle cimport static_pointer_cast, shared_ptr from quantlib.types cimport Size, Real from quantlib.pricingengines._pricing_engine cimport PricingEngine as QlPricingEngine diff --git a/quantlib/pricingengines/vanilla/vanilla.pyx b/quantlib/pricingengines/vanilla/vanilla.pyx index 922d10817..66697f7f2 100644 --- a/quantlib/pricingengines/vanilla/vanilla.pyx +++ b/quantlib/pricingengines/vanilla/vanilla.pyx @@ -4,7 +4,7 @@ from libcpp.vector cimport vector from libcpp cimport bool from cython.operator cimport dereference as deref -from quantlib.cashflows.dividend cimport DividendSchedule +from quantlib.instruments.dividendschedule cimport DividendSchedule from quantlib.handle cimport shared_ptr, static_pointer_cast cimport quantlib.processes._black_scholes_process as _bsp cimport quantlib.models.equity._bates_model as _bm diff --git a/quantlib/termstructures/volatility/_smilesection.pxd b/quantlib/termstructures/volatility/_smilesection.pxd index 847004d23..1e126bb85 100644 --- a/quantlib/termstructures/volatility/_smilesection.pxd +++ b/quantlib/termstructures/volatility/_smilesection.pxd @@ -1,5 +1,5 @@ include "../../types.pxi" -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType from quantlib.time._daycounter cimport DayCounter from quantlib.time._date cimport Date from .volatilitytype cimport VolatilityType diff --git a/quantlib/termstructures/volatility/smilesection.pyx b/quantlib/termstructures/volatility/smilesection.pyx index f685a64c5..bbc756948 100644 --- a/quantlib/termstructures/volatility/smilesection.pyx +++ b/quantlib/termstructures/volatility/smilesection.pyx @@ -3,7 +3,7 @@ include "../../types.pxi" cimport quantlib.time._daycounter as _dc from quantlib.time.date cimport date_from_qldate from quantlib.time.daycounter cimport DayCounter -from quantlib.instruments.option cimport OptionType +from quantlib.option cimport OptionType cdef class SmileSection: @property diff --git a/quantlib/util/options.py b/quantlib/util/options.py index 7ae29f690..6b3fe9f8b 100644 --- a/quantlib/util/options.py +++ b/quantlib/util/options.py @@ -12,10 +12,10 @@ import quantlib.reference.data_structures as ds from pandas import DataFrame -from quantlib.instruments.option import VanillaOption -from quantlib.instruments.exercise import EuropeanExercise -from quantlib.instruments.payoffs import PlainVanillaPayoff -from quantlib.instruments.option import OptionType +from quantlib.instruments.vanillaoption import VanillaOption +from quantlib.exercise import EuropeanExercise +from quantlib.payoffs import PlainVanillaPayoff +from quantlib.option import OptionType from quantlib.models.equity.heston_model import HestonModel from quantlib.processes.heston_process import HestonProcess from quantlib.quotes import SimpleQuote From fd0bac490908d3acb63e9a9185b22b224f0a41c7 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Thu, 14 Aug 2025 11:31:40 -0400 Subject: [PATCH 2/3] fix tests --- examples/option_valuation.py | 9 +++++---- examples/traits_example.py | 9 +++++---- test/test_asian.py | 6 +++--- test/test_bermudan_swaption.py | 2 +- test/test_heston_model.py | 12 ++++++------ test/test_hybridhestonhullwhite_process.py | 9 ++++----- test/test_mlab.py | 2 +- test/test_notebooks.py | 2 +- test/test_payoff.py | 4 ++-- test/test_vanilla_option.py | 10 +++++----- test/test_variance_swap.py | 4 ++-- 11 files changed, 35 insertions(+), 34 deletions(-) diff --git a/examples/option_valuation.py b/examples/option_valuation.py index 318e2e4a5..62d316469 100644 --- a/examples/option_valuation.py +++ b/examples/option_valuation.py @@ -22,13 +22,14 @@ """ from quantlib.settings import Settings from quantlib.compounding import Simple -from quantlib.cashflows.dividend import DividendSchedule +from quantlib.instruments.dividendschedule import DividendSchedule from quantlib.currency.api import USDCurrency from quantlib.indexes.api import Libor from quantlib.indexes.swap_index import SwapIndex -from quantlib.instruments.exercise import EuropeanExercise, AmericanExercise -from quantlib.instruments.option import VanillaOption, VanillaOption, OptionType -from quantlib.instruments.payoffs import PlainVanillaPayoff +from quantlib.exercise import EuropeanExercise, AmericanExercise +from quantlib.instruments.vanillaoption import VanillaOption +from quantlib.option import OptionType +from quantlib.payoffs import PlainVanillaPayoff from quantlib.math.interpolation import Linear from quantlib.pricingengines.api import AnalyticDividendEuropeanEngine from quantlib.pricingengines.api import FdBlackScholesVanillaEngine diff --git a/examples/traits_example.py b/examples/traits_example.py index 7ddad08e8..06b136204 100644 --- a/examples/traits_example.py +++ b/examples/traits_example.py @@ -4,10 +4,11 @@ from traits.api import HasTraits, Enum, Float, Date, Property, Range from traitsui.api import View, Item, HGroup, EnumEditor -from quantlib.instruments.option import Put, Call, EuropeanExercise -from quantlib.instruments.payoffs import PlainVanillaPayoff -from quantlib.instruments.option import VanillaOption -from quantlib.pricingengines.vanilla import AnalyticEuropeanEngine +from quantlib.option import OptionType +from quantlib.exercise import EuropeanExercise +from quantlib.payoffs import PlainVanillaPayoff +from quantlib.instruments.vanillaoption import VanillaOption +from quantlib.pricingengines.api import AnalyticEuropeanEngine from quantlib.processes.black_scholes_process import BlackScholesMertonProcess from quantlib.quotes import SimpleQuote from quantlib.settings import Settings diff --git a/test/test_asian.py b/test/test_asian.py index 6b03adeba..78ed69e5a 100644 --- a/test/test_asian.py +++ b/test/test_asian.py @@ -1,9 +1,9 @@ from itertools import product -from quantlib.instruments.exercise import EuropeanExercise +from quantlib.exercise import EuropeanExercise -from quantlib.instruments.payoffs import PlainVanillaPayoff -from quantlib.instruments.option import OptionType +from quantlib.payoffs import PlainVanillaPayoff +from quantlib.option import OptionType from quantlib.instruments.asian_options import ( ContinuousAveragingAsianOption, DiscreteAveragingAsianOption, AverageType ) diff --git a/test/test_bermudan_swaption.py b/test/test_bermudan_swaption.py index d52f04382..9041f019a 100644 --- a/test/test_bermudan_swaption.py +++ b/test/test_bermudan_swaption.py @@ -11,7 +11,7 @@ from quantlib.models.api import HullWhite from quantlib.settings import Settings from quantlib.pricingengines.api import DiscountingSwapEngine, TreeSwaptionEngine -from quantlib.instruments.exercise import BermudanExercise +from quantlib.exercise import BermudanExercise from .utilities import flat_rate diff --git a/test/test_heston_model.py b/test/test_heston_model.py index 390cc3277..f43a2fc9d 100644 --- a/test/test_heston_model.py +++ b/test/test_heston_model.py @@ -4,9 +4,9 @@ import unittest -from quantlib.instruments.exercise import EuropeanExercise -from quantlib.instruments.option import VanillaOption, OptionType -from quantlib.instruments.payoffs import PlainVanillaPayoff +from quantlib.exercise import EuropeanExercise +from quantlib.instruments.vanillaoption import VanillaOption +from quantlib.payoffs import PlainVanillaPayoff from quantlib.models.calibration_helper import ImpliedVolError from quantlib.models.equity.heston_model import ( HestonModelHelper, HestonModel @@ -238,7 +238,7 @@ def test_analytic_versus_black(self): exercise_date = settlement_date + Period(6, Months) - payoff = PlainVanillaPayoff(OptionType.Put, 30) + payoff = PlainVanillaPayoff(VanillaOption.Put, 30) exercise = EuropeanExercise(exercise_date) @@ -295,7 +295,7 @@ def test_bates_det_jump(self): exercise_date = settlement_date + Period(6, Months) - payoff = PlainVanillaPayoff(OptionType.Put, 1290) + payoff = PlainVanillaPayoff(VanillaOption.Put, 1290) exercise = EuropeanExercise(exercise_date) option = VanillaOption(payoff, exercise) @@ -363,7 +363,7 @@ def test_smith(self): exercise_date = settlement_date + timeToMaturity * 365 - c_payoff = PlainVanillaPayoff(OptionType.Call, 100) + c_payoff = PlainVanillaPayoff(VanillaOption.Call, 100) exercise = EuropeanExercise(exercise_date) diff --git a/test/test_hybridhestonhullwhite_process.py b/test/test_hybridhestonhullwhite_process.py index d1725bcc2..b1aadb49c 100644 --- a/test/test_hybridhestonhullwhite_process.py +++ b/test/test_hybridhestonhullwhite_process.py @@ -7,12 +7,12 @@ from quantlib.settings import Settings -from quantlib.instruments.option import OptionType -from quantlib.instruments.exercise import EuropeanExercise +from quantlib.option import OptionType +from quantlib.exercise import EuropeanExercise from quantlib.models.shortrate.onefactormodels.hullwhite import HullWhite -from quantlib.instruments.option import VanillaOption +from quantlib.instruments.vanillaoption import VanillaOption from quantlib.time.api import (today, Years, Actual365Fixed, Period, May, Date, @@ -37,8 +37,7 @@ from quantlib.quotes import SimpleQuote -from quantlib.instruments.payoffs import ( - PlainVanillaPayoff) +from quantlib.payoffs import PlainVanillaPayoff from quantlib.methods.finitedifferences.solvers.fdmbackwardsolver import FdmSchemeDesc diff --git a/test/test_mlab.py b/test/test_mlab.py index afb2504b5..80c90e024 100644 --- a/test/test_mlab.py +++ b/test/test_mlab.py @@ -4,7 +4,7 @@ from quantlib.mlab.option_pricing import heston_pricer, blsprice, blsimpv from quantlib.mlab.fixed_income import bndprice, cfamounts from quantlib.mlab.term_structure import zbt_libor_yield -from quantlib.instruments.option import OptionType +from quantlib.option import OptionType from quantlib.util.rates import make_rate_helper, zero_rate import quantlib.reference.names as nm diff --git a/test/test_notebooks.py b/test/test_notebooks.py index c6769c931..de53c60b5 100644 --- a/test/test_notebooks.py +++ b/test/test_notebooks.py @@ -5,7 +5,7 @@ import quantlib.reference.names as nm from quantlib.pricingengines.blackformula import blackFormulaImpliedStdDev -from quantlib.instruments.option import OptionType +from quantlib.option import OptionType def Compute_IV(optionDataFrame, tMin=0, nMin=0, QDMin=0, QDMax=1, keepOTMData=True): diff --git a/test/test_payoff.py b/test/test_payoff.py index e0b1a3107..669f452de 100644 --- a/test/test_payoff.py +++ b/test/test_payoff.py @@ -1,7 +1,7 @@ import unittest -from quantlib.instruments.payoffs import PlainVanillaPayoff -from quantlib.instruments.option import OptionType +from quantlib.payoffs import PlainVanillaPayoff +from quantlib.option import OptionType class PayoffTestCase(unittest.TestCase): diff --git a/test/test_vanilla_option.py b/test/test_vanilla_option.py index d3a65f736..05b751c2c 100644 --- a/test/test_vanilla_option.py +++ b/test/test_vanilla_option.py @@ -1,12 +1,12 @@ import unittest import datetime -from quantlib.instruments.exercise import ( +from quantlib.exercise import ( EuropeanExercise, AmericanExercise) -from quantlib.cashflows.dividend import DividendSchedule +from quantlib.instruments.dividendschedule import DividendSchedule -from quantlib.instruments.payoffs import PlainVanillaPayoff -from quantlib.instruments.option import VanillaOption, OptionType +from quantlib.payoffs import PlainVanillaPayoff +from quantlib.instruments.vanillaoption import VanillaOption from quantlib.pricingengines.vanilla.vanilla import ( AnalyticEuropeanEngine, BaroneAdesiWhaleyApproximationEngine) from quantlib.pricingengines.vanilla.fdblackscholesvanillaengine import ( @@ -43,7 +43,7 @@ def setUp(self): self.settings.evaluation_date = self.todays_date # options parameters - self.option_type = OptionType.Put + self.option_type = VanillaOption.Put self.underlying = 36 self.strike = 40 self.dividend_yield = 0.00 diff --git a/test/test_variance_swap.py b/test/test_variance_swap.py index a5299d12f..9c5b5d9d2 100644 --- a/test/test_variance_swap.py +++ b/test/test_variance_swap.py @@ -4,8 +4,8 @@ import numpy as np from quantlib.settings import Settings -from quantlib.instruments.exercise import EuropeanExercise -from quantlib.instruments.option import OptionType +from quantlib.exercise import EuropeanExercise +from quantlib.option import OptionType from quantlib.instruments.variance_swap import VarianceSwap, SwapType from quantlib.math.matrix import Matrix from quantlib.pricingengines.forward.replicating_variance_swap_engine import ReplicatingVarianceSwapEngine From a756c5fdeb9466da32247179e65c134522cb2dd1 Mon Sep 17 00:00:00 2001 From: Guillaume Horel Date: Thu, 14 Aug 2025 14:11:07 -0400 Subject: [PATCH 3/3] better docstrings --- quantlib/exercise.pxd | 8 +++++ quantlib/exercise.pyx | 48 ++++++++++++++++++------- quantlib/instruments/europeanoption.pxd | 1 - quantlib/instruments/europeanoption.pyx | 1 + quantlib/instruments/futures.pxd | 16 +++++++++ quantlib/instruments/oneassetoption.pyx | 3 +- quantlib/instruments/vanillaoption.pyx | 23 ++++++++++++ quantlib/payoffs.pyx | 4 +-- 8 files changed, 87 insertions(+), 17 deletions(-) diff --git a/quantlib/exercise.pxd b/quantlib/exercise.pxd index ed00cbf90..24b63f6af 100644 --- a/quantlib/exercise.pxd +++ b/quantlib/exercise.pxd @@ -3,6 +3,14 @@ from . cimport _exercise cdef extern from 'ql/exercise.hpp' namespace 'QuantLib::Exercise' nogil: cpdef enum class Type: + """Exercise types + + Attributes + ---------- + American + Bermudan + European + """ American Bermudan European diff --git a/quantlib/exercise.pyx b/quantlib/exercise.pyx index e2a41af89..6f4c81977 100644 --- a/quantlib/exercise.pyx +++ b/quantlib/exercise.pyx @@ -6,6 +6,15 @@ from quantlib.time.date cimport Date, _pydate_from_qldate from quantlib.time._date cimport Date as QlDate cdef class Exercise: + """Base exercise class + + Attributes + ---------- + American + Bermudan + European + """ + American = Type.American Bermudan = Type.Bermudan @@ -19,6 +28,7 @@ cdef class Exercise: return _pydate_from_qldate(self._thisptr.get().lastDate()) def dates(self): + """ all exercise dates""" cdef vector[QlDate].const_iterator it = self._thisptr.get().dates().const_begin() cdef list r = [] while it != self._thisptr.get().dates().end(): @@ -30,6 +40,10 @@ cdef class Exercise: return self._thisptr.get().type() cdef class EuropeanExercise(Exercise): + """European exercise + + A European option can only be exercised at one (expiry) date. + """ def __init__(self, Date exercise_date not None): self._thisptr.reset( @@ -39,14 +53,21 @@ cdef class EuropeanExercise(Exercise): ) cdef class AmericanExercise(Exercise): + """American exercise - def __init__(self, Date latest_exercise_date, Date earliest_exercise_date=None): - """ Creates an AmericanExercise. + An American option can be exercised at any time between to + predefined dates; the first date might be amitted, in which + case the option can be exercied at any time before the expiry. - :param latest_exercise_date: Latest exercise date for the option - :param earliest_exercise_date: Earliest exercise date for the option (default to None) + Parameters + ---------- + latest_exercise_date : :class:`~quantlib.time.date.Date` + Latest exercise date for the option + earliest_exercise_date : :class:`~quantlib.time.date.Date` | None + Earliest exercise date for the option + """ - """ + def __init__(self, Date latest_exercise_date, Date earliest_exercise_date=None): if earliest_exercise_date is not None: self._thisptr = shared_ptr[_exercise.Exercise]( \ new _exercise.AmericanExercise( @@ -63,16 +84,17 @@ cdef class AmericanExercise(Exercise): cdef class BermudanExercise(Exercise): - def __init__(self, list dates, bool payoff_at_expiry=False): - """ Bermudan exercise + """ Bermudan exercise - A Bermudan option can only be exercised at a set of fixed dates. + A Bermudan option can only be exercised at a set of fixed dates. - Parameters - ---------- - dates : list of exercise dates - payoff_at_expiry : bool - """ + Parameters + ---------- + dates : list of exercise dates + payoff_at_expiry : bool + """ + + def __init__(self, list dates, bool payoff_at_expiry=False): cdef vector[QlDate] c_dates for d in dates: c_dates.push_back((d)._thisptr) diff --git a/quantlib/instruments/europeanoption.pxd b/quantlib/instruments/europeanoption.pxd index f5111861f..ee4af6849 100644 --- a/quantlib/instruments/europeanoption.pxd +++ b/quantlib/instruments/europeanoption.pxd @@ -1,4 +1,3 @@ -"""European option on a single asset""" from .vanillaoption cimport VanillaOption cdef class EuropeanOption(VanillaOption): diff --git a/quantlib/instruments/europeanoption.pyx b/quantlib/instruments/europeanoption.pyx index 75b8ae384..ddad03852 100644 --- a/quantlib/instruments/europeanoption.pyx +++ b/quantlib/instruments/europeanoption.pyx @@ -1,3 +1,4 @@ +""" European option on a single asset """ from . cimport _europeanoption as _eo from ..payoffs cimport StrikedTypePayoff from ..exercise cimport Exercise diff --git a/quantlib/instruments/futures.pxd b/quantlib/instruments/futures.pxd index f54d35969..00a701445 100644 --- a/quantlib/instruments/futures.pxd +++ b/quantlib/instruments/futures.pxd @@ -1,4 +1,20 @@ cdef extern from 'ql/instruments/futures.hpp' namespace 'QuantLib::Futures': cpdef enum FuturesType "QuantLib::Futures::Type": + """Futures types enumeration + + These conventions specify the kind of futures types + + Attributes + ---------- IMM + Chicago Mercantile International Money Market, i.e + third Wednesday of March, June, September, December ASX + Australian Security Exchange, i.e. second Friday + of March, June, September, December + Custom + Other rules + """ + IMM + ASX + Custom diff --git a/quantlib/instruments/oneassetoption.pyx b/quantlib/instruments/oneassetoption.pyx index b93ea1488..fc5118ce8 100644 --- a/quantlib/instruments/oneassetoption.pyx +++ b/quantlib/instruments/oneassetoption.pyx @@ -1,5 +1,6 @@ +"""Option on a single asset""" cdef class OneAssetOption(Option): - + """Base class for option on a single asset""" cdef inline _oa.OneAssetOption* as_ptr(self) noexcept nogil: return <_oa.OneAssetOption*>self._thisptr.get() diff --git a/quantlib/instruments/vanillaoption.pyx b/quantlib/instruments/vanillaoption.pyx index 8521e8861..11ea8a76a 100644 --- a/quantlib/instruments/vanillaoption.pyx +++ b/quantlib/instruments/vanillaoption.pyx @@ -1,3 +1,4 @@ +"""Vanilla option on a single asset""" from quantlib.handle cimport shared_ptr, static_pointer_cast from quantlib.types cimport Real, Size, Volatility from quantlib.processes.black_scholes_process cimport GeneralizedBlackScholesProcess @@ -10,6 +11,28 @@ from .. cimport _payoffs from . cimport _vanillaoption as _va cdef class VanillaOption(OneAssetOption): + """Vanilla option (no discrete dividends, no barriers) on a single asset + + Parameters + ---------- + payoff : :class:`~quantlib.payoffs.StrikedTypePayoff` + exercise : :class:`~quantlib.exercise.Exercise` + + Warnings + -------- + Currently, this method returns the Black-Scholes + implied volatility using analytic formulas for + European options and a finite-difference method + for American and Bermudan options. It will give + unconsistent results if the pricing was performed + with any other methods (such as jump-diffusion models.) + + Options with a gamma that changes sign (e.g., binary options) have values that are **not** + monotonic in the volatility. In these cases, the calculation can fail and + the result (if any) is almost meaningless. Another possible source of + failure is to have a target value that is not attainable with any volatility, e.g., a target + value lower than the intrinsic value in the case of American options. + """ def __init__(self, StrikedTypePayoff payoff not None, Exercise exercise not None): diff --git a/quantlib/payoffs.pyx b/quantlib/payoffs.pyx index a813558a2..3a4c9a9ff 100644 --- a/quantlib/payoffs.pyx +++ b/quantlib/payoffs.pyx @@ -33,8 +33,8 @@ cdef class PlainVanillaPayoff(StrikedTypePayoff): Parameters ---------- - option_type: int - The type of option, can be either Call or Put + option_type: :class:`~quantlib.option.OptionType` + The type of option, can be either `Call` or `Put` strike: double The strike value