diff --git a/quantlib/_index.pxd b/quantlib/_index.pxd index e4e1b161a..6abd91122 100644 --- a/quantlib/_index.pxd +++ b/quantlib/_index.pxd @@ -30,3 +30,4 @@ cdef extern from 'ql/index.hpp' namespace 'QuantLib' nogil: void addFixings(vector[Date].iterator dBegin, vector[Date].iterator dEnd, vector[Real].iterator vBegin, bool forceOverwrite) except + TimeSeries[Real] timeSeries() void clearFixings() + bool hasHistoricalFixing(const Date& fixingDate) diff --git a/quantlib/compounding.pxd b/quantlib/compounding.pxd index 4f2a9b5f3..91f784e2e 100644 --- a/quantlib/compounding.pxd +++ b/quantlib/compounding.pxd @@ -1,4 +1,4 @@ -cdef extern from "ql/compounding.hpp" namespace "QuantLib": +cdef extern from "ql/compounding.hpp" namespace "QuantLib" nogil: cpdef enum Compounding: Simple = 0 Continuous = 1 diff --git a/quantlib/compounding.pyx b/quantlib/compounding.pyx index e69de29bb..acbc5fb20 100644 --- a/quantlib/compounding.pyx +++ b/quantlib/compounding.pyx @@ -0,0 +1 @@ +globals().update(getattr(Compounding, "__members__")) diff --git a/quantlib/experimental/risk/__init__.py b/quantlib/experimental/risk/__init__.py deleted file mode 100644 index e69de29bb..000000000 diff --git a/quantlib/experimental/risk/_sensitivityanalysis.pxd b/quantlib/experimental/risk/_sensitivityanalysis.pxd deleted file mode 100644 index db50d17ae..000000000 --- a/quantlib/experimental/risk/_sensitivityanalysis.pxd +++ /dev/null @@ -1,36 +0,0 @@ -include '../../types.pxi' - -from quantlib.handle cimport shared_ptr, Handle -from quantlib._instrument cimport Instrument -from quantlib.quotes._simplequote cimport SimpleQuote -from libcpp.vector cimport vector -from libcpp.pair cimport pair - - -cdef extern from 'ql/experimental/risk/sensitivityanalysis.hpp' namespace 'QuantLib': - cdef enum SensitivityAnalysis: - OneSided - Centered - -cdef extern from 'ql/experimental/risk/sensitivityanalysis.hpp' namespace 'QuantLib': - pair[vector[vector[Real]], vector[vector[Real]]] bucketAnalysis( - vector[vector[Handle[SimpleQuote]]]& quotes, - vector[shared_ptr[Instrument]]& instr, - vector[Real]& quant, - Real shift, - SensitivityAnalysis type) except + - # rename the function otherwise cython can't distinguish between the two - pair[vector[Real], vector[Real]] bucketAnalysis1 "bucketAnalysis"( - vector[Handle[SimpleQuote]]& quotes, - vector[shared_ptr[Instrument]]& instr, - vector[Real]& quant, - Real shift, - SensitivityAnalysis type) except + - - pair[Real, Real] parallelAnalysis( - const vector[Handle[SimpleQuote]]&, - const vector[shared_ptr[Instrument]]&, - vector[Real]& quantities, - Real shift, # =0.0001, - SensitivityAnalysis type, #= Centered, - Real reference_npv)# = Null() diff --git a/quantlib/experimental/risk/sensitivityanalysis.pyx b/quantlib/experimental/risk/sensitivityanalysis.pyx deleted file mode 100644 index 21413428c..000000000 --- a/quantlib/experimental/risk/sensitivityanalysis.pyx +++ /dev/null @@ -1,110 +0,0 @@ -include '../../types.pxi' - -from cython.operator cimport dereference as deref -from quantlib.handle cimport shared_ptr, Handle, static_pointer_cast -from quantlib.utilities.null cimport Null -cimport quantlib.quotes._simplequote as _sq -from . cimport _sensitivityanalysis as _sa -cimport quantlib._instrument as _it -from libcpp.vector cimport vector -from libcpp.pair cimport pair -from quantlib.quotes.simplequote cimport SimpleQuote -from quantlib.instrument cimport Instrument - -cpdef enum SensitivityAnalysis: - OneSide - Centered - -def parallel_analysis(list quotes not None, list instruments not None, - vector[Real] quantities=[], - Real shift=0.0001, SensitivityAnalysis type=Centered, - Real reference_npv=Null[Real]()): - """ - Parallel shift PV01 sensitivity analysis for a SimpleQuote vector - - Returns a pair of first and second derivative values. Second derivative - is not available if type is OneSide. - - Empty quantities vector is considered as unit vector. The same if the - vector is just one single element equal to one. - - Parameters - ---------- - quotes : list[SimpleQuote] - instrument : list[Instrument] - quantities : list[Real] - shift : Real - type : SensitivityAnalysis - """ - cdef vector[Handle[_sq.SimpleQuote]] _quotes - cdef vector[shared_ptr[_it.Instrument]] _instruments - cdef shared_ptr[_sq.SimpleQuote] q_ptr - cdef Instrument inst - cdef SimpleQuote q - - for q in quotes: - q_ptr = static_pointer_cast[_sq.SimpleQuote](q._thisptr) - _quotes.push_back(Handle[_sq.SimpleQuote](q_ptr)) - - for inst in instruments: - _instruments.push_back(inst._thisptr) - - return _sa.parallelAnalysis(_quotes, - _instruments, - quantities, - shift, - <_sa.SensitivityAnalysis>(type), - reference_npv) - - -def bucket_analysis(list quotes not None, list instruments not None, - vector[Real] quantities=[], Real shift=0.0001, - SensitivityAnalysis type=Centered): - - """ - Parameters - ---------- - 1) quotes : list[SimpleQuote] or list[list[SimpleQuote]] - list or list of list of quotes to be tweaked by a certain shift, - usually passed from ratehelpers - 2) instruments : List of instruments - list of instruments to be analyzed. - 3) quantity : Quantity of instrument - A multiplier for the resulting buckets, Usually 1 or lower. - 4) shift : Amount of shift for analysis. - Tends to be 0.0001 (1 bp). Can be larger as well as positive or negative. - 5) type : Sensitivity Analysis Type - Will be either OneSide or Centered - """ - - #C++ Inputs - cdef vector[vector[Handle[_sq.SimpleQuote]]] _Quotes - cdef vector[shared_ptr[_it.Instrument]] _instruments - - #intermediary temps - cdef vector[Handle[_sq.SimpleQuote]] _quotes - cdef shared_ptr[_sq.SimpleQuote] q_ptr - cdef Handle[_sq.SimpleQuote] quote_handle - cdef list quotes_list - cdef SimpleQuote q - cdef Instrument inst - - for inst in instruments: - _instruments.push_back(inst._thisptr) - - if isinstance(quotes[0], list): - for quotes_list in quotes: - _Quotes.push_back(vector[Handle[_sq.SimpleQuote]]()) - for q in quotes_list: - q_ptr = static_pointer_cast[_sq.SimpleQuote](q._thisptr) - _Quotes.back().push_back(Handle[_sq.SimpleQuote](q_ptr)) - return _sa.bucketAnalysis(_Quotes, _instruments, quantities, shift, - <_sa.SensitivityAnalysis>(type)) - elif isinstance(quotes[0], SimpleQuote): - for q in quotes: - q_ptr = static_pointer_cast[_sq.SimpleQuote](q._thisptr) - _quotes.push_back(Handle[_sq.SimpleQuote](q_ptr)) - return _sa.bucketAnalysis1(_quotes, _instruments, quantities, shift, - <_sa.SensitivityAnalysis>(type)) - else: - raise RuntimeError("quotes need to be either a list or list of lists of SimpleQuote") diff --git a/quantlib/index.pyx b/quantlib/index.pyx index f68ad46e0..9725d851d 100644 --- a/quantlib/index.pyx +++ b/quantlib/index.pyx @@ -5,8 +5,7 @@ # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the license for more details. """Abstract base class for indices""" -include 'types.pxi' - +from quantlib.types cimport Real from cpython.datetime cimport PyDate_Check, date_year, date_month, date_day, import_datetime from libcpp cimport bool from libcpp.vector cimport vector @@ -92,3 +91,6 @@ cdef class Index: def clear_fixings(self): self._thisptr.get().clearFixings() + + def has_historical_fixing(self, Date d): + return self._thisptr.get().hasHistoricalFixing(d._thisptr) diff --git a/quantlib/indexes/_inflation_index.pxd b/quantlib/indexes/_inflation_index.pxd index eb29db537..342ef4feb 100644 --- a/quantlib/indexes/_inflation_index.pxd +++ b/quantlib/indexes/_inflation_index.pxd @@ -7,7 +7,6 @@ FOR A PARTICULAR PURPOSE. See the license for more details. """ -include '../types.pxi' from libcpp cimport bool from libcpp.string cimport string @@ -58,7 +57,6 @@ cdef extern from 'ql/indexes/inflationindex.hpp' namespace 'QuantLib' nogil: YoYInflationIndex(const string& familyName, const Region& region, bool revised, - bool ratio, # is this one a genuine index or a ratio? Frequency frequency, const Period& availabilityLag, const Currency& currency, diff --git a/quantlib/indexes/index_manager.pyx b/quantlib/indexes/index_manager.pyx index d7946700c..c75464c06 100644 --- a/quantlib/indexes/index_manager.pyx +++ b/quantlib/indexes/index_manager.pyx @@ -1,32 +1,8 @@ # cython: c_string_type=unicode, c_string_encoding=ascii -include '../types.pxi' -from libcpp.string cimport string cimport quantlib.indexes._index_manager as _im -from quantlib.time_series cimport TimeSeries -cimport quantlib._time_series as _ts cdef class IndexManager: - cdef has_history(self, string name): - _im.IndexManager.instance().hasHistory(name) @staticmethod def histories(): return _im.IndexManager.instance().histories() - - @staticmethod - def get_history(string name): - cdef TimeSeries ts = TimeSeries.__new__(TimeSeries) - ts._thisptr = _im.IndexManager.instance().getHistory(name) - return ts - - @staticmethod - def set_history(string name, TimeSeries ts not None): - _im.IndexManager.instance().setHistory(name, ts._thisptr) - - @staticmethod - def clear_history(string name): - _im.IndexManager.instance().clearHistory(name) - - @staticmethod - def clear_histories(): - _im.IndexManager.instance().clearHistories() diff --git a/quantlib/indexes/inflation/_euhicp.pxd b/quantlib/indexes/inflation/_euhicp.pxd index 5931b4e93..355fc1427 100644 --- a/quantlib/indexes/inflation/_euhicp.pxd +++ b/quantlib/indexes/inflation/_euhicp.pxd @@ -11,9 +11,7 @@ cdef extern from 'ql/indexes/inflation/euhicp.hpp' namespace 'QuantLib' nogil: EUHICPXT(const Handle[ZeroInflationTermStructure]& ts) cdef cppclass YYEUHICP(YoYInflationIndex): - YYEUHICP(bool interpolated, - const Handle[YoYInflationTermStructure]& ts) + YYEUHICP(const Handle[YoYInflationTermStructure]& ts) cdef cppclass YYEUHICPXT(YoYInflationIndex): - YYEUHICPXT(bool interpolated, - const Handle[YoYInflationTermStructure]& ts) + YYEUHICPXT(const Handle[YoYInflationTermStructure]& ts) diff --git a/quantlib/indexes/inflation/euhicp.pyx b/quantlib/indexes/inflation/euhicp.pyx index ba7d9924b..8c8eb10d0 100644 --- a/quantlib/indexes/inflation/euhicp.pyx +++ b/quantlib/indexes/inflation/euhicp.pyx @@ -13,9 +13,9 @@ cdef class EUHICPXT(ZeroInflationIndex): self._thisptr.reset(new _euhicp.EUHICPXT(ts._handle)) cdef class YYEUHICP(YoYInflationIndex): - def __init__(self, bool interpolated, YoYInflationTermStructure ts=YoYInflationTermStructure()): - self._thisptr.reset(new _euhicp.YYEUHICP(interpolated, ts._handle)) + def __init__(self, YoYInflationTermStructure ts=YoYInflationTermStructure()): + self._thisptr.reset(new _euhicp.YYEUHICP(ts._handle)) cdef class YYEUHICPXT(YoYInflationIndex): - def __init__(self, bool interpolated, YoYInflationTermStructure ts=YoYInflationTermStructure()): - self._thisptr.reset(new _euhicp.YYEUHICPXT(interpolated, ts._handle)) + def __init__(self, YoYInflationTermStructure ts=YoYInflationTermStructure()): + self._thisptr.reset(new _euhicp.YYEUHICPXT(ts._handle)) diff --git a/quantlib/indexes/inflation_index.pyx b/quantlib/indexes/inflation_index.pyx index ec3c51616..b677ef034 100644 --- a/quantlib/indexes/inflation_index.pyx +++ b/quantlib/indexes/inflation_index.pyx @@ -106,7 +106,7 @@ cdef class ZeroInflationIndex(InflationIndex): cdef class YoYInflationIndex(ZeroInflationIndex): def __init__(self, family_name, Region region, bool revised, - bool ratio, Frequency frequency, + Frequency frequency, Period availability_lag, Currency currency, YoYInflationTermStructure ts=YoYInflationTermStructure()): @@ -115,6 +115,6 @@ cdef class YoYInflationIndex(ZeroInflationIndex): self._thisptr = shared_ptr[_in.Index]( new _ii.YoYInflationIndex( c_family_name, deref(region._thisptr), revised, - ratio, frequency, + frequency, deref(availability_lag._thisptr), deref(currency._thisptr), ts._handle)) diff --git a/quantlib/instruments/_swaption.pxd b/quantlib/instruments/_swaption.pxd index b3569d083..0826e9c36 100644 --- a/quantlib/instruments/_swaption.pxd +++ b/quantlib/instruments/_swaption.pxd @@ -29,4 +29,4 @@ cdef extern from 'ql/instruments/swaption.hpp' namespace 'QuantLib': VolatilityType type,# = ShiftedLognormal, Real displacement)# = 0.0) SwapType type() const - const shared_ptr[FixedVsFloatingSwap]& underlyingSwap() + const shared_ptr[FixedVsFloatingSwap]& underlying() diff --git a/quantlib/instruments/swaption.pyx b/quantlib/instruments/swaption.pyx index 42b7ac4cb..0895ef71f 100644 --- a/quantlib/instruments/swaption.pyx +++ b/quantlib/instruments/swaption.pyx @@ -71,9 +71,9 @@ cdef class Swaption(Option): def type(self): return (self.get_swaption().type()) - def underlying_swap(self): + def underlying(self): cdef FixedVsFloatingSwap instance = FixedVsFloatingSwap.__new__(FixedVsFloatingSwap) - cdef shared_ptr[_fixedvsfloatingswap.FixedVsFloatingSwap] swap = self.get_swaption().underlyingSwap() + cdef shared_ptr[_fixedvsfloatingswap.FixedVsFloatingSwap] swap = self.get_swaption().underlying() instance._thisptr = static_pointer_cast[_instrument.Instrument](swap) return instance diff --git a/quantlib/mlab/fixed_income.py b/quantlib/mlab/fixed_income.py index da3353d06..3a1191d5a 100644 --- a/quantlib/mlab/fixed_income.py +++ b/quantlib/mlab/fixed_income.py @@ -12,10 +12,10 @@ FixedRateBond ) -from quantlib.compounding import Compounded +from quantlib.compounding import Compounding from quantlib.pricingengines.bond import DiscountingBondEngine -from quantlib.time.businessdayconvention import ( +from quantlib.time.api import ( Unadjusted, ModifiedFollowing, Following) from quantlib.time.calendars.null_calendar import NullCalendar @@ -144,7 +144,7 @@ def _bndprice(bond_yield, coupon_rate, pricing_date, maturity_date, forward=bond_yield, calendar=NullCalendar(), daycounter=cnt_yield, - compounding=Compounded, + compounding=Compounding.Compounded, frequency=period) discounting_term_structure.link_to(flat_term_structure) diff --git a/quantlib/mlab/option_pricing.py b/quantlib/mlab/option_pricing.py index 4dcd66b50..85408bb2b 100644 --- a/quantlib/mlab/option_pricing.py +++ b/quantlib/mlab/option_pricing.py @@ -25,7 +25,7 @@ from quantlib.processes.api import BlackScholesMertonProcess from quantlib.termstructures.yields.api import FlatForward, HandleYieldTermStructure from quantlib.termstructures.volatility.api import BlackConstantVol -from quantlib.time.api import today, NullCalendar, ActualActual, ISMA +from quantlib.time.api import today, NullCalendar, ActualActual from quantlib.time.date import (Period, Days) from quantlib.mlab.util import common_shape, array_call @@ -104,7 +104,7 @@ def _blsprice(spot, strike, risk_free_rate, time, volatility, """ _spot = SimpleQuote(spot) - daycounter = ActualActual(ISMA) + daycounter = ActualActual(ActualActual.ISMA) risk_free_ts = HandleYieldTermStructure(FlatForward(today(), risk_free_rate, daycounter)) dividend_ts = HandleYieldTermStructure(FlatForward(today(), dividend, daycounter)) volatility_ts = BlackConstantVol(today(), NullCalendar(), @@ -162,7 +162,7 @@ def _blsimpv(price, spot, strike, risk_free_rate, time, option_type, dividend): spot = SimpleQuote(spot) - daycounter = ActualActual(ISMA) + daycounter = ActualActual(ActualActual.ISMA) risk_free_ts = HandleYieldTermStructure(FlatForward(today(), risk_free_rate, daycounter)) dividend_ts = HandleYieldTermStructure(FlatForward(today(), dividend, daycounter)) volatility_ts = BlackConstantVol(today(), NullCalendar(), diff --git a/quantlib/models/calibration_helper.pyx b/quantlib/models/calibration_helper.pyx index d9df4863a..1e3900faf 100644 --- a/quantlib/models/calibration_helper.pyx +++ b/quantlib/models/calibration_helper.pyx @@ -11,7 +11,7 @@ from quantlib.types cimport Real, Size, Volatility from quantlib.handle cimport shared_ptr from quantlib.pricingengines.engine cimport PricingEngine - +globals().update(getattr(CalibrationErrorType, "__members__")) cdef class BlackCalibrationHelper: diff --git a/quantlib/models/shortrate/calibrationhelpers/_swaption_helper.pxd b/quantlib/models/shortrate/calibrationhelpers/_swaption_helper.pxd index 5db8cff36..2de1eebbb 100644 --- a/quantlib/models/shortrate/calibrationhelpers/_swaption_helper.pxd +++ b/quantlib/models/shortrate/calibrationhelpers/_swaption_helper.pxd @@ -38,7 +38,7 @@ cdef extern from 'ql/models/shortrate/calibrationhelpers/swaptionhelper.hpp' nam VolatilityType type, # = ShiftedLognormal, Real shift # = 0.0 ) except + - shared_ptr[FixedVsFloatingSwap] underlyingSwap() + shared_ptr[FixedVsFloatingSwap] underlying() shared_ptr[Swaption] swaption() # this should really be a constructor but cython can't disambiguate the diff --git a/quantlib/models/shortrate/calibrationhelpers/swaption_helper.pyx b/quantlib/models/shortrate/calibrationhelpers/swaption_helper.pyx index 54e5ae285..518608d03 100644 --- a/quantlib/models/shortrate/calibrationhelpers/swaption_helper.pyx +++ b/quantlib/models/shortrate/calibrationhelpers/swaption_helper.pyx @@ -19,7 +19,6 @@ from quantlib.instruments.fixedvsfloatingswap cimport FixedVsFloatingSwap from quantlib.instruments.swaption cimport Swaption from quantlib.time.date cimport Period, Date from quantlib.quote cimport Quote -from quantlib.models.calibration_helper import RelativePriceError from quantlib.utilities.null cimport Null cimport quantlib._quote as _qt @@ -42,7 +41,7 @@ cdef class SwaptionHelper(BlackCalibrationHelper): DayCounter fixed_leg_daycounter not None, DayCounter floating_leg_daycounter not None, HandleYieldTermStructure ts not None, - CalibrationErrorType error_type=RelativePriceError, + CalibrationErrorType error_type=CalibrationErrorType.RelativePriceError, Real strike=Null[Real](), Real nominal=1.0, VolatilityType vol_type=VolatilityType.ShiftedLognormal, @@ -103,9 +102,9 @@ cdef class SwaptionHelper(BlackCalibrationHelper): ) ) - def underlying_swap(self): + def underlying(self): cdef FixedVsFloatingSwap swap = FixedVsFloatingSwap.__new__(FixedVsFloatingSwap) - swap._thisptr = (<_sh.SwaptionHelper*>self._thisptr.get()).underlyingSwap() + swap._thisptr = (<_sh.SwaptionHelper*>self._thisptr.get()).underlying() return swap def underlying_swaption(self): diff --git a/quantlib/processes/_heston_process.pxd b/quantlib/processes/_heston_process.pxd index e97a5f743..b94a769a4 100644 --- a/quantlib/processes/_heston_process.pxd +++ b/quantlib/processes/_heston_process.pxd @@ -7,28 +7,19 @@ FOR A PARTICULAR PURPOSE. See the license for more details. """ -include '../types.pxi' - from quantlib.handle cimport Handle, shared_ptr from quantlib.termstructures.yields._flat_forward cimport YieldTermStructure +from quantlib.types cimport Real, Size cimport quantlib._quote as _qt from quantlib._stochastic_process cimport StochasticProcess -cdef extern from 'ql/processes/hestonprocess.hpp' namespace 'QuantLib': +cdef extern from 'ql/processes/hestonprocess.hpp' namespace 'QuantLib' nogil: cdef cppclass HestonProcess(StochasticProcess): HestonProcess() # fake empty constructor for Cython # fixme: implement the discrization version of the constructor enum Discretization: - PartialTruncation - FullTruncation - Reflection - NonCentralChiSquareVariance - QuadraticExponential - QuadraticExponentialMartingale - BroadieKayaExactSchemeLobatto - BroadieKayaExactSchemeLaguerre - BroadieKayaExactSchemeTrapezoidal + pass HestonProcess( Handle[YieldTermStructure]& riskFreeRate, Handle[YieldTermStructure]& dividendYield, @@ -48,7 +39,7 @@ cdef extern from 'ql/processes/hestonprocess.hpp' namespace 'QuantLib': Handle[YieldTermStructure] riskeFreeRate() -cdef extern from 'ql/processes/batesprocess.hpp' namespace 'QuantLib': +cdef extern from 'ql/processes/batesprocess.hpp' namespace 'QuantLib' nogil: cdef cppclass BatesProcess(HestonProcess): BatesProcess( @@ -62,4 +53,3 @@ cdef extern from 'ql/processes/batesprocess.hpp' namespace 'QuantLib': Real Lambda 'lambda'() except + Real nu() except + Real delta() except + - diff --git a/quantlib/processes/heston_process.pxd b/quantlib/processes/heston_process.pxd index db36181ba..ef481ff25 100644 --- a/quantlib/processes/heston_process.pxd +++ b/quantlib/processes/heston_process.pxd @@ -1,16 +1,17 @@ from quantlib.stochastic_process cimport StochasticProcess from ._heston_process cimport HestonProcess as QlHestonProcess -cpdef enum Discretization: - PartialTruncation - FullTruncation - Reflection - NonCentralChiSquareVariance - QuadraticExponential - QuadraticExponentialMartingale - BroadieKayaExactSchemeLobatto - BroadieKayaExactSchemeLaguerre - BroadieKayaExactSchemeTrapezoidal +cdef extern from "ql/processes/hestonprocess.hpp" namespace "QuantLib::HestonProcess" nogil: + cpdef enum Discretization: + PartialTruncation + FullTruncation + Reflection + NonCentralChiSquareVariance + QuadraticExponential + QuadraticExponentialMartingale + BroadieKayaExactSchemeLobatto + BroadieKayaExactSchemeLaguerre + BroadieKayaExactSchemeTrapezoidal cdef class HestonProcess(StochasticProcess): pass diff --git a/quantlib/processes/heston_process.pyx b/quantlib/processes/heston_process.pyx index 5412ed58a..4624912fb 100644 --- a/quantlib/processes/heston_process.pyx +++ b/quantlib/processes/heston_process.pyx @@ -1,5 +1,4 @@ -include '../types.pxi' - +from quantlib.types cimport Real from .heston_process cimport PartialTruncation cimport quantlib._stochastic_process as _sp @@ -17,11 +16,20 @@ cdef class HestonProcess(StochasticProcess): .. math:: - dS_t =& (r-d) S_t dt + \sqrt{V_t} S_t dW^s_t \\ + dS_t =& (r-d) S_t dt + \sqrt{V_t} S_t dW/^s_t \\ dV_t =& \kappa (\theta - V_t) dt + \varepsilon \sqrt{V_t} dW^\upsilon_t \\ dW^s_t dW^\upsilon_t =& \rho dt """ + PartialTruncation = Discretization.PartialTruncation + FullTruncation = Discretization.FullTruncation + Reflection = Discretization.Reflection + NonCentralChiSquareVariance = Discretization.NonCentralChiSquareVariance + QuadraticExponential = Discretization.QuadraticExponential + QuadraticExponentialMartingale = Discretization.QuadraticExponentialMartingale + BroadieKayaExactSchemeLobatto = Discretization.BroadieKayaExactSchemeLobatto + BroadieKayaExactSchemeLaguerre = Discretization.BroadieKayaExactSchemeLaguerre + BroadieKayaExactSchemeTrapezoidal = Discretization.BroadieKayaExactSchemeTrapezoidal def __init__(self, HandleYieldTermStructure risk_free_rate_ts=HandleYieldTermStructure(), diff --git a/quantlib/termstructures/_inflation_term_structure.pxd b/quantlib/termstructures/_inflation_term_structure.pxd index 067adbbe9..bccca5d10 100644 --- a/quantlib/termstructures/_inflation_term_structure.pxd +++ b/quantlib/termstructures/_inflation_term_structure.pxd @@ -28,7 +28,6 @@ cdef extern from 'ql/termstructures/inflationtermstructure.hpp' namespace 'Quant Date& referenceDate() Date& maxDate() Date& baseDate() - Period observationLag() Rate baseRate() diff --git a/quantlib/termstructures/inflation/_inflation_helpers.pxd b/quantlib/termstructures/inflation/_inflation_helpers.pxd index 105648178..8aa1a81e2 100644 --- a/quantlib/termstructures/inflation/_inflation_helpers.pxd +++ b/quantlib/termstructures/inflation/_inflation_helpers.pxd @@ -1,6 +1,3 @@ - -include '../../types.pxi' - from quantlib._quote cimport Quote from quantlib.handle cimport shared_ptr, Handle from quantlib.time.businessdayconvention cimport BusinessDayConvention @@ -17,7 +14,7 @@ from quantlib.termstructures.inflation.inflation_traits cimport ( cimport quantlib.termstructures._inflation_term_structure as _its cimport quantlib.termstructures._yield_term_structure as _yts -cdef extern from 'ql/termstructures/inflation/inflationhelpers.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/inflation/inflationhelpers.hpp' namespace 'QuantLib' nogil: cdef cppclass ZeroCouponInflationSwapHelper(ZeroInflationTraits.helper): ZeroCouponInflationSwapHelper( const Handle[Quote]& quote, @@ -40,4 +37,5 @@ cdef extern from 'ql/termstructures/inflation/inflationhelpers.hpp' namespace 'Q BusinessDayConvention payment_convention, const DayCounter& day_counter, const shared_ptr[YoYInflationIndex]& yii, + CPI.InterpolationType interpolation, const Handle[_yts.YieldTermStructure]& nominal_term_structure) except + diff --git a/quantlib/termstructures/inflation/inflation_helpers.pyx b/quantlib/termstructures/inflation/inflation_helpers.pyx index f0da09241..f68a2de07 100644 --- a/quantlib/termstructures/inflation/inflation_helpers.pyx +++ b/quantlib/termstructures/inflation/inflation_helpers.pyx @@ -56,6 +56,7 @@ cdef class YearOnYearInflationSwapHelper: BusinessDayConvention payment_convention, DayCounter day_counter not None, YoYInflationIndex yii not None, + InterpolationType interpolation, HandleYieldTermStructure nominal_term_structure not None): self._thisptr = shared_ptr[YoYInflationTraits.helper]( new _ih.YearOnYearInflationSwapHelper( @@ -65,6 +66,7 @@ cdef class YearOnYearInflationSwapHelper: calendar._thisptr, payment_convention, deref(day_counter._thisptr), static_pointer_cast[_ii.YoYInflationIndex](yii._thisptr), + interpolation, nominal_term_structure.handle) ) diff --git a/quantlib/termstructures/inflation_term_structure.pyx b/quantlib/termstructures/inflation_term_structure.pyx index 04e629364..87e88c92c 100644 --- a/quantlib/termstructures/inflation_term_structure.pyx +++ b/quantlib/termstructures/inflation_term_structure.pyx @@ -54,10 +54,6 @@ cdef class InflationTermStructure: def base_rate(self): return self._thisptr.get().baseRate() - @property - def observation_lag(self): - return period_from_qlperiod(self._thisptr.get().observationLag()) - cdef class ZeroInflationTermStructure(InflationTermStructure): def __cinit__(self): diff --git a/quantlib/termstructures/yields/_bootstraptraits.pxd b/quantlib/termstructures/yields/_bootstraptraits.pxd index 3e49c0066..c9bb49d6c 100644 --- a/quantlib/termstructures/yields/_bootstraptraits.pxd +++ b/quantlib/termstructures/yields/_bootstraptraits.pxd @@ -1,4 +1,4 @@ -cdef extern from 'ql/termstructures/yield/bootstraptraits.hpp' namespace 'QuantLib': +cdef extern from 'ql/termstructures/yield/bootstraptraits.hpp' namespace 'QuantLib' nogil: cdef cppclass Discount: pass diff --git a/quantlib/termstructures/yields/_ois_rate_helper.pxd b/quantlib/termstructures/yields/_ois_rate_helper.pxd index 43e8a3006..c19cb2d85 100644 --- a/quantlib/termstructures/yields/_ois_rate_helper.pxd +++ b/quantlib/termstructures/yields/_ois_rate_helper.pxd @@ -42,15 +42,40 @@ cdef extern from 'ql/termstructures/yield/oisratehelper.hpp' namespace 'QuantLib bool applyObservationShift,# = false, #shared_ptr[FloatingRateCouponPricer] pricer ) except + # = 0.0 - - cdef cppclass DatedOISRateHelper(RateHelper): - DatedOISRateHelper( - Date& startDate, - Date& endDate, +cdef extern from 'ql/termstructures/yield/oisratehelper.hpp' namespace 'QuantLib': + OISRateHelper* OISRateHelper_ "new QuantLib::OISRateHelper" ( + Date startDate, + Date endDate, Handle[Quote]& fixedRate, shared_ptr[OvernightIndex]& overnightIndex, # exogenous discounting curve - Handle[YieldTermStructure] discountingCurve,# = Handle(), - bool telescopicValueDates, #= false, - RateAveraging averagingMethod #= RateAveraging::Compound) - ) except + + Handle[YieldTermStructure]& discountingCurve, # = Handle() + bool telescopicValueDates, # False) + Integer paymentLag, # = 0 + BusinessDayConvention paymentConvention, # = Following + Frequency paymentFrequency, # = Annual + Calendar& paymentCalendar, # = Calendar() + Spread overnightSpread, + Pillar pillar, # = Pillar::LastRelevantDate, + Date customPillarDate, # = Date(), + RateAveraging averagingMethod,# = RateAveraging::Compound, + optional[bool] endOfMonth, # = boost::none + optional[Frequency] fixedPaymentFrequency, # = ext::nullopt, + Calendar fixedCalendar, # = Calendar(), + Natural lookbackDays, # = Null(), + Natural lockoutDays, # = 0, + bool applyObservationShift,# = false, + #shared_ptr[FloatingRateCouponPricer] pricer + ) except + # = 0.0 + + # cdef cppclass DatedOISRateHelper(RateHelper): + # DatedOISRateHelper( + # Date& startDate, + # Date& endDate, + # Handle[Quote]& fixedRate, + # shared_ptr[OvernightIndex]& overnightIndex, + # # exogenous discounting curve + # Handle[YieldTermStructure] discountingCurve,# = Handle(), + # bool telescopicValueDates, #= false, + # RateAveraging averagingMethod #= RateAveraging::Compound) + # ) except + diff --git a/quantlib/termstructures/yields/bootstraptraits.pyx b/quantlib/termstructures/yields/bootstraptraits.pyx index e69de29bb..010875401 100644 --- a/quantlib/termstructures/yields/bootstraptraits.pyx +++ b/quantlib/termstructures/yields/bootstraptraits.pyx @@ -0,0 +1 @@ +globals().update(getattr(BootstrapTrait, "__members__")) diff --git a/quantlib/termstructures/yields/ois_rate_helper.pyx b/quantlib/termstructures/yields/ois_rate_helper.pyx index 6ad30c468..aeb16f422 100644 --- a/quantlib/termstructures/yields/ois_rate_helper.pyx +++ b/quantlib/termstructures/yields/ois_rate_helper.pyx @@ -83,27 +83,83 @@ cdef class OISRateHelper(RelativeDateRateHelper): #pricer._thisptr ) ) - -cdef class DatedOISRateHelper(RateHelper): - - def __init__(self, - Date start_date not None, + @classmethod + def from_dates(cls, Date start_date not None, Date end_date not None, Quote fixed_rate not None, OvernightIndex overnight_index not None, # exogenous discounting curve HandleYieldTermStructure discounting_curve not None=HandleYieldTermStructure(), bool telescopic_value_dates = False, + Integer payment_lag=0, + BusinessDayConvention payment_convention = Following, + Frequency payment_frequency = Frequency.Annual, + Calendar payment_calendar = Calendar(), + Spread overnight_spread = 0.0, + Pillar pillar=Pillar.LastRelevantDate, + Date custom_pillar_date=Date(), RateAveraging averaging_method=RateAveraging.Compound, - ): - self._thisptr = shared_ptr[_rh.RateHelper]( - new _orh.DatedOISRateHelper( + end_of_month=None, + fixed_payment_frequency=None, + Calendar fixed_calendar=Calendar(), + Natural lookback_days=Null[Natural](), + Natural lockout_days=0, + bool apply_observation_shift=False): + cdef OISRateHelper instance = OISRateHelper.__new__(OISRateHelper) + cdef: + optional[bool] end_of_month_opt + optional[Frequency] fixed_payment_frequency_opt + if end_of_month is not None: + end_of_month_opt = end_of_month + if fixed_payment_frequency is not None: + fixed_payment_frequency_opt = fixed_payment_frequency + instance._thisptr.reset( + _orh.OISRateHelper_( start_date._thisptr, end_date._thisptr, fixed_rate.handle(), static_pointer_cast[_ib.OvernightIndex](overnight_index._thisptr), discounting_curve.handle, telescopic_value_dates, - averaging_method + payment_lag, + <_rh.BusinessDayConvention> payment_convention, + payment_frequency, + payment_calendar._thisptr, + overnight_spread, + pillar, + custom_pillar_date._thisptr, + averaging_method, + end_of_month_opt, + fixed_payment_frequency_opt, + fixed_calendar._thisptr, + lookback_days, + lockout_days, + apply_observation_shift, + #pricer._thisptr ) ) + return instance + +# cdef class DatedOISRateHelper(RateHelper): + +# def __init__(self, +# Date start_date not None, +# Date end_date not None, +# Quote fixed_rate not None, +# OvernightIndex overnight_index not None, +# # exogenous discounting curve +# HandleYieldTermStructure discounting_curve not None=HandleYieldTermStructure(), +# bool telescopic_value_dates = False, +# RateAveraging averaging_method=RateAveraging.Compound, +# ): +# self._thisptr = shared_ptr[_rh.RateHelper]( +# new _orh.DatedOISRateHelper( +# start_date._thisptr, +# end_date._thisptr, +# fixed_rate.handle(), +# static_pointer_cast[_ib.OvernightIndex](overnight_index._thisptr), +# discounting_curve.handle, +# telescopic_value_dates, +# averaging_method +# ) +# ) diff --git a/quantlib/time/_date.pxd b/quantlib/time/_date.pxd index be4e921a2..1f4ae88c6 100644 --- a/quantlib/time/_date.pxd +++ b/quantlib/time/_date.pxd @@ -1,6 +1,6 @@ from quantlib.types cimport * -cdef extern from 'ql/time/date.hpp' namespace 'QuantLib': +cdef extern from 'ql/time/date.hpp' namespace 'QuantLib' nogil: ctypedef int Year ctypedef int Day ctypedef int Hour @@ -18,25 +18,12 @@ cdef extern from "ostream" namespace "std": cdef cppclass ostream: pass -cdef extern from 'ql/time/weekday.hpp' namespace "QuantLib": +cdef extern from 'ql/time/weekday.hpp' namespace "QuantLib" nogil: cdef enum Weekday: - Sunday = 1 - Monday = 2 - Tuesday = 3 - Wednesday = 4 - Thursday = 5 - Friday = 6 - Saturday = 7 - Sun = 1 - Mon = 2 - Tue = 3 - Wed = 4 - Thu = 5 - Fri = 6 - Sat = 7 - -cdef extern from "ql/time/date.hpp" namespace "QuantLib::Date": + pass + +cdef extern from "ql/time/date.hpp" namespace "QuantLib::Date" nogil: ctypedef int_fast32_t serial_type cdef Date todaysDate() cdef Date minDate() @@ -50,35 +37,14 @@ cdef extern from "ql/time/date.hpp" namespace "QuantLib::Date": cdef Date localDateTime() cdef Date universalDateTime() -cdef extern from "ql/time/date.hpp" namespace "QuantLib": + +cdef extern from "ql/time/date.hpp" namespace "QuantLib" nogil: cdef enum Month: - January = 1 - February = 2 - March = 3 - April = 4 - May = 5 - June = 6 - July = 7 - August = 8 - September = 9 - October = 10 - November = 11 - December = 12 - Jan = 1 - Feb = 2 - Mar = 3 - Apr = 4 - Jun = 6 - Jul = 7 - Aug = 8 - Sep = 9 - Oct = 10 - Nov = 11 - Dec = 12 + pass cdef cppclass Date: - Date() except + + Date() Date(serial_type serialnumber) except + Date(const Date&) Date(Day d, Month m, Year y) except + @@ -134,13 +100,13 @@ cdef extern from "ql/time/date.hpp" namespace "QuantLib::detail": cdef cppclass formatted_date_holder: pass -cdef extern from "ql/time/date.hpp" namespace "QuantLib::io": +cdef extern from "ql/time/date.hpp" namespace "QuantLib::io" nogil: cdef short_date_holder short_date(const Date&) cdef iso_date_holder iso_date(const Date&) cdef iso_datetime_holder iso_datetime(const Date&) cdef formatted_date_holder formatted_date(const Date&, const string& fmt) -cdef extern from "" namespace "std": +cdef extern from "" namespace "std" nogil: cdef cppclass stringstream: stringstream& operator<<(iso_date_holder) stringstream& operator<<(short_date_holder) @@ -149,6 +115,6 @@ cdef extern from "" namespace "std": stringstream& operator<<(formatted_date_holder) string str() -cdef extern from 'ql/utilities/dataparsers.hpp' namespace "QuantLib::DateParser": +cdef extern from 'ql/utilities/dataparsers.hpp' namespace "QuantLib::DateParser" nogil: Date parseISO(const string& str) except + Date parseFormatted(const string&, const string&) except + diff --git a/quantlib/time/api.py b/quantlib/time/api.py index d3adca9e1..44ad49564 100644 --- a/quantlib/time/api.py +++ b/quantlib/time/api.py @@ -28,8 +28,7 @@ from .daycounter import DayCounter from .daycounters.simple import Actual360, Actual365Fixed from .daycounters.thirty360 import Thirty360 -from .daycounters.actual_actual import (ActualActual, ISMA, ISDA, Bond, - Historical, Actual365, AFB, Euro) +from .daycounters.actual_actual import ActualActual from .date import ( diff --git a/quantlib/time/businessdayconvention.pxd b/quantlib/time/businessdayconvention.pxd index 0f70cfd02..f504e7e38 100644 --- a/quantlib/time/businessdayconvention.pxd +++ b/quantlib/time/businessdayconvention.pxd @@ -1,4 +1,4 @@ -cdef extern from "ql/time/businessdayconvention.hpp" namespace "QuantLib": +cdef extern from "ql/time/businessdayconvention.hpp" namespace "QuantLib" nogil: cpdef enum BusinessDayConvention: Following ModifiedFollowing diff --git a/quantlib/time/businessdayconvention.pyx b/quantlib/time/businessdayconvention.pyx index e69de29bb..c010a5b9b 100644 --- a/quantlib/time/businessdayconvention.pyx +++ b/quantlib/time/businessdayconvention.pyx @@ -0,0 +1 @@ +globals().update(getattr(BusinessDayConvention, "__members__")) diff --git a/quantlib/time/calendar_registry.py b/quantlib/time/calendar_registry.py index 1b1b8dcf6..6f38f7c9f 100644 --- a/quantlib/time/calendar_registry.py +++ b/quantlib/time/calendar_registry.py @@ -1,7 +1,7 @@ from quantlib.time.calendars.null_calendar import NullCalendar from quantlib.time.calendars.weekends_only import WeekendsOnly -import quantlib.time.calendars.germany as ger -import quantlib.time.calendars.united_states as us +from quantlib.time.calendars.germany import Germany +from quantlib.time.calendars.united_states import UnitedStates import quantlib.time.calendars.united_kingdom as uk import quantlib.time.calendars.japan as jp import quantlib.time.calendars.switzerland as sw @@ -14,18 +14,18 @@ 'TARGET': TARGET(), 'NULL': NullCalendar(), 'WO': WeekendsOnly(), - 'DEU': ger.Germany(), - 'EUREX': ger.Germany(ger.Eurex), - 'FSE': ger.Germany(ger.FrankfurtStockExchange), - 'EUWAX': ger.Germany(ger.Euwax), - 'XETRA': ger.Germany(ger.Xetra), + 'DEU': Germany(), + 'EUREX': Germany(Germany.Eurex), + 'FSE': Germany(Germany.FrankfurtStockExchange), + 'EUWAX': Germany(Germany.Euwax), + 'XETRA': Germany(Germany.Xetra), 'GBR': uk.UnitedKingdom(), 'LSE': uk.UnitedKingdom(uk.Market.Exchange), 'LME': uk.UnitedKingdom(uk.Market.Metals), - 'USA': us.UnitedStates(), - 'USA-GVT-BONDS': us.UnitedStates(us.Market.GovernmentBond), - 'NYSE': us.UnitedStates(us.Market.NYSE), - 'NERC': us.UnitedStates(us.Market.NERC), + 'USA': UnitedStates(), + 'USA-GVT-BONDS': UnitedStates(UnitedStates.GovernmentBond), + 'NYSE': UnitedStates(UnitedStates.NYSE), + 'NERC': UnitedStates(UnitedStates.NERC), 'JPN': jp.Japan(), 'CHE': sw.Switzerland(), 'CAN': ca.Canada(), diff --git a/quantlib/time/calendars/_germany.pxd b/quantlib/time/calendars/_germany.pxd index a59d96453..d45de9945 100644 --- a/quantlib/time/calendars/_germany.pxd +++ b/quantlib/time/calendars/_germany.pxd @@ -1,16 +1,8 @@ from quantlib.time._calendar cimport Calendar -cdef extern from 'ql/time/calendars/germany.hpp' namespace 'QuantLib::Germany': - - cdef enum Market: - Settlement - FrankfurtStockExchange - Xetra - Eurex - Euwax - - -cdef extern from 'ql/time/calendars/germany.hpp' namespace 'QuantLib': +cdef extern from 'ql/time/calendars/germany.hpp' namespace 'QuantLib' nogil: cdef cppclass Germany(Calendar): + enum Market: + pass Germany(Market mkt) diff --git a/quantlib/time/calendars/_jointcalendar.pxd b/quantlib/time/calendars/_jointcalendar.pxd index 207a5c1ef..b92f13d09 100644 --- a/quantlib/time/calendars/_jointcalendar.pxd +++ b/quantlib/time/calendars/_jointcalendar.pxd @@ -1,17 +1,9 @@ from libcpp.string cimport string from quantlib.time._calendar cimport Calendar +from .jointcalendar cimport JointCalendarRule - -cdef extern from 'ql/time/calendars/jointcalendar.hpp' namespace 'QuantLib': - - cdef enum JointCalendarRule: - JoinHolidays # A date is a holiday for the joint calendar - # if it is a holiday for any of the given calendars - JoinBusinessDays # A date is a business day for the joint calendar - # if it is a business day for any of the given calendars - -cdef extern from 'ql/time/calendars/jointcalendar.hpp' namespace 'QuantLib': +cdef extern from 'ql/time/calendars/jointcalendar.hpp' namespace 'QuantLib' nogil: cdef cppclass JointCalendar(Calendar): JointCalendar(Calendar& c1, Calendar& c2, diff --git a/quantlib/time/calendars/germany.pxd b/quantlib/time/calendars/germany.pxd new file mode 100644 index 000000000..9080e4f66 --- /dev/null +++ b/quantlib/time/calendars/germany.pxd @@ -0,0 +1,8 @@ +cdef extern from "ql/time/calendars/germany.hpp" namespace "QuantLib::Germany" nogil: + cpdef enum class Market: + """Germany calendar""" + Settlement + FrankfurtStockExchange + Xetra + Eurex + Euwax diff --git a/quantlib/time/calendars/germany.pyx b/quantlib/time/calendars/germany.pyx index eefa468e1..da244ce5b 100644 --- a/quantlib/time/calendars/germany.pyx +++ b/quantlib/time/calendars/germany.pyx @@ -1,18 +1,15 @@ -cimport quantlib.time._calendar as _calendar cimport quantlib.time.calendars._germany as _gm from quantlib.time.calendar cimport Calendar -cpdef enum Market: - Settlement = _gm.Settlement - FrankfurtStockExchange = _gm.FrankfurtStockExchange # Frankfurt stock-exchange - Xetra = _gm.Xetra # Xetra - Eurex = _gm.Eurex # Eurex - Euwax = _gm.Euwax # Euwax - cdef class Germany(Calendar): ''' Germany calendars. ''' + Settlement = Market.Settlement + FrankfurtStockExchange = Market.FrankfurtStockExchange + Xetra = Market.Xetra + Eurex = Market.Eurex + Euwax = Market.Euwax def __cinit__(self, Market market=Market.Settlement): - self._thisptr = _gm.Germany(<_gm.Market>market) + self._thisptr = _gm.Germany(market) diff --git a/quantlib/time/calendars/jointcalendar.pxd b/quantlib/time/calendars/jointcalendar.pxd index bc2369514..283a6bfc8 100644 --- a/quantlib/time/calendars/jointcalendar.pxd +++ b/quantlib/time/calendars/jointcalendar.pxd @@ -1,5 +1,13 @@ from quantlib.time.calendar cimport Calendar +cdef extern from 'ql/time/calendars/jointcalendar.hpp' namespace 'QuantLib' nogil: + + cpdef enum JointCalendarRule: + JoinHolidays # A date is a holiday for the joint calendar + # if it is a holiday for any of the given calendars + JoinBusinessDays # A date is a business day for the joint calendar + # if it is a business day for any of the given calendars + cdef class JointCalendar(Calendar): pass diff --git a/quantlib/time/calendars/jointcalendar.pyx b/quantlib/time/calendars/jointcalendar.pyx index 5fbe85eee..4d763c039 100644 --- a/quantlib/time/calendars/jointcalendar.pyx +++ b/quantlib/time/calendars/jointcalendar.pyx @@ -4,10 +4,6 @@ cimport quantlib.time.calendars._jointcalendar as _jc cimport quantlib.time._calendar as _cal from quantlib.time.calendar cimport Calendar -cpdef enum JointCalendarRule: - JOINHOLIDAYS = _jc.JoinHolidays - JOINBUSINESSDAYS = _jc.JoinBusinessDays - cdef class JointCalendar(Calendar): ''' Joint calendar @@ -17,7 +13,7 @@ cdef class JointCalendar(Calendar): ''' @cython.cpp_locals(True) - def __cinit__(self, Calendar c1, Calendar c2, int jc = JOINHOLIDAYS): + def __cinit__(self, Calendar c1, Calendar c2, JointCalendarRule jc = JointCalendarRule.JoinHolidays): self._thisptr = _jc.JointCalendar(c1._thisptr, c2._thisptr, - <_jc.JointCalendarRule> jc) + jc) diff --git a/quantlib/time/calendars/united_states.pxd b/quantlib/time/calendars/united_states.pxd index cf000d502..bfedfc306 100644 --- a/quantlib/time/calendars/united_states.pxd +++ b/quantlib/time/calendars/united_states.pxd @@ -9,3 +9,4 @@ cdef extern from 'ql/time/calendars/unitedstates.hpp' namespace \ NERC # off-peak days for NERC LiborImpact # Libor impact calendar FederalReserve # Federal Reserve Bankwire System + SOFR # SOFR fixing calendar diff --git a/quantlib/time/calendars/united_states.pyx b/quantlib/time/calendars/united_states.pyx index 6dc4bc80a..34d4f3725 100644 --- a/quantlib/time/calendars/united_states.pyx +++ b/quantlib/time/calendars/united_states.pyx @@ -76,5 +76,13 @@ cdef class UnitedStates(Calendar): * Christmas, December 25th (moved to Monday if Sunday) ''' + Settlement = Market.Settlement # generic settlement calendar + NYSE = Market.NYSE # New York stock exchange calendar + GovernmentBond = Market.GovernmentBond # government-bond calendar + NERC = Market.NERC # off-peak days for NERC + LiborImpact = Market.LiborImpact # Libor impact + FederalReserve = Market.FederalReserve # Federal Reserve Bankwire System + SOFR = Market.SOFR # SOFR fixing calendar + def __cinit__(self, Market market=Market.Settlement): self._thisptr = _us.UnitedStates(market) diff --git a/quantlib/time/date.pxd b/quantlib/time/date.pxd index bb589c3c9..52d8b8a8f 100644 --- a/quantlib/time/date.pxd +++ b/quantlib/time/date.pxd @@ -1,25 +1,71 @@ -""" - Copyright (C) 2011, Enthought Inc - Copyright (C) 2011, Patrick Henaff +# Copyright (C) 2011, Enthought Inc +# Copyright (C) 2011, Patrick Henaff + +# 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. - 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. -""" from libcpp cimport bool -cimport quantlib.time._date as _date +from ._date cimport Date as QlDate + cimport quantlib.time._period as _period from quantlib.handle cimport shared_ptr +cdef extern from 'ql/time/weekday.hpp' namespace "QuantLib" nogil: + + cpdef enum Weekday: + Sunday = 1 + Monday = 2 + Tuesday = 3 + Wednesday = 4 + Thursday = 5 + Friday = 6 + Saturday = 7 + Sun = 1 + Mon = 2 + Tue = 3 + Wed = 4 + Thu = 5 + Fri = 6 + Sat = 7 + +cdef extern from "ql/time/date.hpp" namespace "QuantLib" nogil: + + cpdef enum Month: + January = 1 + February = 2 + March = 3 + April = 4 + May = 5 + June = 6 + July = 7 + August = 8 + September = 9 + October = 10 + November = 11 + December = 12 + Jan = 1 + Feb = 2 + Mar = 3 + Apr = 4 + Jun = 6 + Jul = 7 + Aug = 8 + Sep = 9 + Oct = 10 + Nov = 11 + Dec = 12 + + cdef class Period: cdef shared_ptr[_period.Period] _thisptr cdef class Date: - cdef _date.Date _thisptr + cdef QlDate _thisptr -cdef Date date_from_qldate(const _date.Date& date) +cdef Date date_from_qldate(const QlDate& date) cdef Period period_from_qlperiod(const _period.Period& period) -cdef object _pydate_from_qldate(_date.Date qdate) -cdef _date.Date _qldate_from_pydate(object date) +cdef object _pydate_from_qldate(QlDate qdate) +cdef QlDate _qldate_from_pydate(object date) diff --git a/quantlib/time/date.pyx b/quantlib/time/date.pyx index 95ac90ca8..96027d288 100644 --- a/quantlib/time/date.pyx +++ b/quantlib/time/date.pyx @@ -11,58 +11,17 @@ from . cimport frequency from ._date cimport ( Date as QlDate, todaysDate, nextWeekday, endOfMonth, isEndOfMonth, - minDate, maxDate, Year, Day, Month as QlMonth, Hour, Minute, Second, Millisecond, + minDate, maxDate, Year, Day, Hour, Minute, Second, Millisecond, Microsecond, isLeap, Size, nthWeekday, serial_type, Integer ) from ._period cimport Period as QlPeriod, parse, unary_minus from enum import IntEnum - +globals().update(getattr(Weekday, "__members__")) +globals().update(getattr(Month, "__members__")) # Python imports import_datetime() import six -cpdef enum Month: - January = _date.January - February = _date.February - March = _date.March - April = _date.April - May = _date.May - June = _date.June - July = _date.July - August = _date.August - September = _date.September - October = _date.October - November = _date.November - December = _date.December - Jan = _date.Jan - Feb = _date.Feb - Mar = _date.Mar - Apr = _date.Apr - Jun = _date.Jun - Jul = _date.Jul - Aug = _date.Aug - Sep = _date.Sep - Oct = _date.Oct - Nov = _date.Nov - Dec = _date.Dec - -cpdef enum Weekday: - Sunday = _date.Sunday - Monday = _date.Monday - Tuesday = _date.Tuesday - Wednesday = _date.Wednesday - Thursday = _date.Thursday - Friday = _date.Friday - Saturday = _date.Saturday - Sun = _date.Sun - Mon = _date.Mon - Tue = _date.Tue - Wed = _date.Wed - Thu = _date.Thu - Fri = _date.Fri - Sat = _date.Sat - - class TimeUnit(IntEnum): Days = _period.Days #: Days = 0 Weeks = _period.Weeks #: Weeks = 1 @@ -270,9 +229,9 @@ cdef class Date: if day is None and month is None and year is None: self._thisptr = QlDate() elif day is not None and month is not None and year is not None: - self._thisptr = QlDate(day, month, year) + self._thisptr = QlDate(day, month, year) elif hours is not None and minutes is not None and seconds is not None: - self._thisptr = QlDate(day, month, year, hours, minutes, seconds, millisec, microsec) + self._thisptr = QlDate(day, month, year, hours, minutes, seconds, millisec, microsec) else: raise ValueError("Invalid constructor") diff --git a/quantlib/time/daycounters/thirty360.pxd b/quantlib/time/daycounters/thirty360.pxd index 868f231b8..5d3613f25 100644 --- a/quantlib/time/daycounters/thirty360.pxd +++ b/quantlib/time/daycounters/thirty360.pxd @@ -3,7 +3,7 @@ from quantlib.time.daycounter cimport DayCounter cdef class Thirty360(DayCounter): pass -cdef extern from 'ql/time/daycounters/thirty360.hpp' namespace 'QuantLib::Thirty360': +cdef extern from 'ql/time/daycounters/thirty360.hpp' namespace 'QuantLib::Thirty360' nogil: cpdef enum Convention: USA BondBasis diff --git a/quantlib/time/daycounters/thirty360.pyx b/quantlib/time/daycounters/thirty360.pyx index 2417b91f4..892c0b977 100644 --- a/quantlib/time/daycounters/thirty360.pyx +++ b/quantlib/time/daycounters/thirty360.pyx @@ -59,6 +59,15 @@ cdef class Thirty360(DayCounter): * ISDA * NASD """ + USA = Convention.USA + BondBasis = Convention.BondBasis + European = Convention.European + EurobondBasis = Convention.EurobondBasis + Italian = Convention.Italian + German = Convention.German + ISMA = Convention.ISMA + ISDA = Convention.ISDA + NASD = Convention.NASD def __cinit__(self, Convention convention=Convention.BondBasis, Date termination_date=Date()): self._thisptr = new _th.Thirty360(convention, termination_date._thisptr) diff --git a/quantlib/time/frequency.pyx b/quantlib/time/frequency.pyx index e69de29bb..a22d14e51 100644 --- a/quantlib/time/frequency.pyx +++ b/quantlib/time/frequency.pyx @@ -0,0 +1 @@ +globals().update(getattr(Frequency, "__members__")) diff --git a/quantlib/util/rates.py b/quantlib/util/rates.py index 2816636b2..0c172b71c 100644 --- a/quantlib/util/rates.py +++ b/quantlib/util/rates.py @@ -6,7 +6,6 @@ ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the license for more details. """ -from __future__ import division # Utility functions for handling interest rates # --------------------------------------------- @@ -26,7 +25,7 @@ from quantlib.math.interpolation import LogLinear from quantlib.time.api import ( TARGET, Period, Months, Years, Days, ModifiedFollowing, Unadjusted, - Actual360, Thirty360, Annual, ActualActual, ISDA, JointCalendar, + Actual360, Thirty360, Annual, ActualActual, JointCalendar, UnitedStates, UnitedKingdom, NullCalendar, Date ) from quantlib.util.converter import pydate_to_qldate, qldate_to_pydate @@ -122,7 +121,7 @@ def make_term_structure(rates, dt_obs): h = make_rate_helper(label, r, settlement_date) rate_helpers.append(h) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date( settlement_date, rate_helpers, ts_day_counter, accuracy=tolerance diff --git a/setup.py b/setup.py index c7fd33fc0..5cbad0ad4 100644 --- a/setup.py +++ b/setup.py @@ -142,11 +142,6 @@ def collect_extensions(): 'libraries':[QL_LIBRARY] } - test_extension = Extension('test.test_cython_bug', - ['test/test_cython_bug.pyx'], - **kwargs - ) - multipath_extension = Extension( name='quantlib.sim.simulate', sources=[ @@ -168,7 +163,6 @@ def collect_extensions(): manual_extensions = [ multipath_extension, hestonhw_constraint_extension, - test_extension, ] # remove all the manual extensions from the collected ones diff --git a/test/test_bondfunctions.py b/test/test_bondfunctions.py index 8baee4ee0..8a3d58c45 100644 --- a/test/test_bondfunctions.py +++ b/test/test_bondfunctions.py @@ -14,10 +14,9 @@ from quantlib.time.date import ( Date, Days, Years, January, August, Period, April ) -from quantlib.time.api import (TARGET, Months, ISDA, +from quantlib.time.api import (TARGET, Months, ModifiedFollowing, Unadjusted, Actual360, Thirty360, ActualActual, Actual365Fixed, Annual, Months, Actual365Fixed, Annual, Semiannual) -from quantlib.time.daycounters.actual_actual import Bond from quantlib.time.schedule import Schedule from quantlib.time.dategeneration import DateGeneration from quantlib.settings import Settings @@ -89,7 +88,7 @@ def setUp(self): face_amount, fixed_bond_schedule, [coupon_rate], - ActualActual(Bond), + ActualActual(ActualActual.Bond), Unadjusted, redemption, issue_date @@ -143,25 +142,25 @@ def test_display(self): rate_helpers.append(helper) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date( self.settlement_date, rate_helpers, ts_day_counter, accuracy=tolerance) - pyc_zspd=bf.zSpread(self.bond, Price(102.0), ts, ActualActual(ISDA), + pyc_zspd=bf.zSpread(self.bond, Price(102.0), ts, ActualActual(ActualActual.ISDA), Compounded, Semiannual, Date(1, April, 2015), 1e-6, 100, 0.05) - pyc_zspd_disco=bf.zSpread(self.bond, Price(95.0), ts, ActualActual(ISDA), + pyc_zspd_disco=bf.zSpread(self.bond, Price(95.0), ts, ActualActual(ActualActual.ISDA), Compounded, Semiannual, self.settlement_date, 1e-6, 100, 0.05) - yld = bf.bond_yield(self.bond, Price(102.0), ActualActual(ISDA), Compounded, Semiannual, self.settlement_date, 1e-6, 100, 0.05) - dur = bf.duration(self.bond, yld, ActualActual(ISDA), Compounded, Semiannual, settlement_date=self.settlement_date) + yld = bf.bond_yield(self.bond, Price(102.0), ActualActual(ActualActual.ISDA), Compounded, Semiannual, self.settlement_date, 1e-6, 100, 0.05) + dur = bf.duration(self.bond, yld, ActualActual(ActualActual.ISDA), Compounded, Semiannual, settlement_date=self.settlement_date) - yld_disco = bf.bond_yield(self.bond, Price(95.0), ActualActual(ISDA), Compounded, Semiannual, self.settlement_date, 1e-6, 100, 0.05) - dur_disco = bf.duration(self.bond, yld_disco, ActualActual(ISDA), Compounded, Semiannual, settlement_date=self.settlement_date) + yld_disco = bf.bond_yield(self.bond, Price(95.0), ActualActual(ActualActual.ISDA), Compounded, Semiannual, self.settlement_date, 1e-6, 100, 0.05) + dur_disco = bf.duration(self.bond, yld_disco, ActualActual(ActualActual.ISDA), Compounded, Semiannual, settlement_date=self.settlement_date) self.assertAlmostEqual(zspd, 0.001281, 6) self.assertAlmostEqual(pyc_zspd, -0.0264, 4) diff --git a/test/test_bonds.py b/test/test_bonds.py index 5556e3305..08625bf70 100644 --- a/test/test_bonds.py +++ b/test/test_bonds.py @@ -16,7 +16,7 @@ Jul, Years ) from quantlib.time.daycounters.simple import Actual365Fixed, Actual360 -from quantlib.time.daycounters.actual_actual import ActualActual, Bond, ISMA +from quantlib.time.daycounters.actual_actual import ActualActual from quantlib.time.schedule import Schedule from quantlib.time.dategeneration import DateGeneration from quantlib.settings import Settings @@ -90,7 +90,7 @@ def test_pricing_bond(self): face_amount, fixed_bond_schedule, [coupon_rate], - ActualActual(Bond), + ActualActual(ActualActual.Bond), Unadjusted, redemption, issue_date @@ -162,7 +162,7 @@ def test_excel_example_with_fixed_rate_bond(self): face_amount, fixed_bond_schedule, [coupon_rate], - ActualActual(ISMA), + ActualActual(ActualActual.ISMA), Following, redemption, issue_date diff --git a/test/test_calendar.py b/test/test_calendar.py index 9eb2473f8..a6e42cc71 100644 --- a/test/test_calendar.py +++ b/test/test_calendar.py @@ -16,7 +16,7 @@ Date, May, March, June, Jan, August, Months,November, Period, Days, Apr, Jul, Sep, Oct, Dec, Nov) from quantlib.time.calendars.jointcalendar import ( - JointCalendar, JOINHOLIDAYS, JOINBUSINESSDAYS + JointCalendar, JointCalendarRule ) from quantlib.util.version import QUANTLIB_VERSION @@ -71,12 +71,12 @@ def test_joint(self): bank_holiday_date = Date(3, May, 2010) #Early May Bank Holiday thanksgiving_holiday_date = Date(22, Nov, 2012) - jtcal = JointCalendar(ukcal, uscal, JOINHOLIDAYS) + jtcal = JointCalendar(ukcal, uscal, JointCalendarRule.JoinHolidays) self.assertFalse(jtcal.is_business_day(bank_holiday_date)) self.assertFalse(jtcal.is_business_day(thanksgiving_holiday_date)) - jtcal = JointCalendar(ukcal, uscal, JOINBUSINESSDAYS) + jtcal = JointCalendar(ukcal, uscal, JointCalendarRule.JoinBusinessDays) self.assertTrue(jtcal.is_business_day(bank_holiday_date)) self.assertTrue(jtcal.is_business_day(thanksgiving_holiday_date)) diff --git a/test/test_cython_bug.pyx b/test/test_cython_bug.pyx deleted file mode 100644 index e002fa122..000000000 --- a/test/test_cython_bug.pyx +++ /dev/null @@ -1,123 +0,0 @@ -from quantlib.types cimport Integer, Natural, Rate, Real -from cython.operator cimport dereference as deref -from libcpp.vector cimport vector - -from quantlib.instruments.bonds._fixedratebond cimport FixedRateBond -from quantlib.time._date cimport ( - Date as QlDate, todaysDate, Jul, August, September, endOfMonth -) -from quantlib.time._period cimport Years, Period, Days -from quantlib.time.frequency cimport Annual -from quantlib.time._calendar cimport Calendar -from quantlib.time.businessdayconvention cimport ( - Unadjusted, ModifiedFollowing, Following -) -from quantlib.time.calendars._target cimport TARGET -from quantlib.time._schedule cimport Schedule -from quantlib.time.dategeneration cimport DateGeneration -from quantlib.time.date cimport date_from_qldate, Date -from quantlib.time._daycounter cimport DayCounter -from quantlib.time.daycounters._actual_actual cimport ActualActual -from quantlib.time.daycounters.actual_actual cimport Convention - -from quantlib._settings cimport Settings - -def test_bond_schedule_today_cython(): - cdef QlDate today = todaysDate() - cdef Calendar calendar = TARGET() - - cdef FixedRateBond* bond = get_bond_for_evaluation_date(today) - - cdef QlDate s_date = calendar.advance(today, 3, Days, Following, - False) - cdef QlDate b_date = bond.settlementDate(QlDate()) - - cdef Date s1 = date_from_qldate(s_date) - cdef Date s2 = date_from_qldate(b_date) - - return s1, s2 - - -cdef FixedRateBond* get_bond_for_evaluation_date(QlDate& in_date): - - Settings.instance().evaluationDate().assign_date(in_date) - - # debugged evaluation date - cdef QlDate evaluation_date = Settings.instance().evaluationDate() - cdef Date cython_evaluation_date = date_from_qldate(evaluation_date) - print('Current evaluation date', cython_evaluation_date) - - - - cdef Calendar calendar = TARGET() - cdef QlDate effective_date = QlDate(10, Jul, 2006) - - cdef QlDate termination_date = calendar.advance( - effective_date, 10, Years, Unadjusted, False - ) - - cdef Natural settlement_days = 3 - cdef Real face_amount = 100.0 - cdef Real coupon_rate = 0.05 - cdef Real redemption = 100.0 - - cdef Schedule fixed_bond_schedule = Schedule( - effective_date, - termination_date, - Period(Annual), - calendar, - ModifiedFollowing, - ModifiedFollowing, - DateGeneration.Backward, - False, - QlDate(), - QlDate() - ) - - cdef QlDate issue_date = QlDate(10, Jul, 2006) - - cdef vector[Rate] coupons - coupons.push_back(coupon_rate) - - cdef FixedRateBond* bond = new FixedRateBond( - settlement_days, - face_amount, - fixed_bond_schedule, - coupons, - ActualActual(Convention.ISMA), - Following, - redemption, - issue_date, - Calendar(), - Period(), - Calendar(), - Unadjusted, - False, - DayCounter() - ) - - return bond - -def test_bond_schedule_anotherday_cython(): - - cdef QlDate last_month = QlDate(30, August, 2011) - cdef QlDate today = endOfMonth(last_month) - - cdef FixedRateBond* bond = get_bond_for_evaluation_date(today) - - cdef Calendar calendar = TARGET() - cdef QlDate s_date = calendar.advance(today, 3, Days, Following, - False) - cdef QlDate b_date = bond.settlementDate(QlDate()) - - cdef QlDate e_date = Settings.instance().evaluationDate() - - print(s_date.serialNumber()) - print(b_date.serialNumber()) - - cdef Date s1 = date_from_qldate(s_date) - cdef Date s2 = date_from_qldate(b_date) - cdef Date s3 = date_from_qldate(e_date) - print(s3) - - return s1, s2 diff --git a/test/test_daycounter.py b/test/test_daycounter.py index 6136bc96a..0d72dd28e 100644 --- a/test/test_daycounter.py +++ b/test/test_daycounter.py @@ -6,12 +6,10 @@ Actual360, SimpleDayCounter ) -from quantlib.time.daycounters.actual_actual import ( - ActualActual, ISDA, ISMA, AFB -) +from quantlib.time.daycounters.actual_actual import ActualActual from quantlib.time.daycounters.thirty360 import ( - Thirty360, Convention, EurobondBasis + Thirty360, Convention ) from quantlib.time.date import ( Date, November, May, February, July, January, Period, @@ -87,7 +85,7 @@ def setUp(self): def test_first_example_isda(self): - day_counter = ActualActual(ISDA) + day_counter = ActualActual(ActualActual.ISDA) self.assertAlmostEqual( 0.497724380567, @@ -95,7 +93,7 @@ def test_first_example_isda(self): ) def test_first_example_isma(self): - day_counter = ActualActual(ISMA) + day_counter = ActualActual(ActualActual.ISMA) self.assertAlmostEqual( 0.5, @@ -104,7 +102,7 @@ def test_first_example_isma(self): ) def test_first_example_afb(self): - day_counter = ActualActual(AFB) + day_counter = ActualActual(ActualActual.AFB) self.assertAlmostEqual( 0.497267759563, @@ -113,7 +111,7 @@ def test_first_example_afb(self): def test_short_calculation_first_period_isda(self): - day_counter = ActualActual(ISDA) + day_counter = ActualActual(ActualActual.ISDA) from_date = Date(1, February, 1999) to_date = Date(1, July, 1999) @@ -125,7 +123,7 @@ def test_short_calculation_first_period_isda(self): ) def test_short_calculation_first_period_isma(self): - day_counter = ActualActual(ISMA) + day_counter = ActualActual(ActualActual.ISMA) from_date = Date(1, February, 1999) to_date = Date(1, July, 1999) ref_start = Date(1,July,1998) @@ -138,7 +136,7 @@ def test_short_calculation_first_period_isma(self): ) def test_short_calculation_first_period_afb(self): - day_counter = ActualActual(AFB) + day_counter = ActualActual(ActualActual.AFB) from_date = Date(1, February, 1999) to_date = Date(1, July, 1999) @@ -150,7 +148,7 @@ def test_short_calculation_first_period_afb(self): ) def test_short_calculation_second_period_isda(self): - day_counter = ActualActual(ISDA) + day_counter = ActualActual(ActualActual.ISDA) from_date = Date(1, July, 1999) to_date = Date(1, July, 2000) @@ -162,7 +160,7 @@ def test_short_calculation_second_period_isda(self): ) def test_short_calculation_second_period_isma(self): - day_counter = ActualActual(ISMA) + day_counter = ActualActual(ActualActual.ISMA) from_date = Date(1, July, 1999) to_date = Date(1, July, 2000) ref_start = Date(1, July, 1999) @@ -178,7 +176,7 @@ def test_short_calculation_second_period_isma(self): def test_short_calculation_second_period_afb(self): - day_counter = ActualActual(AFB) + day_counter = ActualActual(ActualActual.AFB) from_date = Date(1, July, 1999) to_date = Date(1, July, 2000) @@ -207,7 +205,7 @@ def test_simple(self): def test_thirty360(self): - day_counter = Thirty360(EurobondBasis) + day_counter = Thirty360(Thirty360.EurobondBasis) from_date = Date(1, July, 1999) to_date = Date(1, July, 2000) @@ -221,12 +219,12 @@ def test_thirty360(self): def test_equality_method(self): - day_counter = Thirty360(EurobondBasis) + day_counter = Thirty360(Thirty360.EurobondBasis) a = Thirty360() self.assertNotEqual(day_counter, a) self.assertNotEqual(day_counter, Thirty360()) - self.assertEqual(day_counter, Thirty360(EurobondBasis)) + self.assertEqual(day_counter, Thirty360(Thirty360.EurobondBasis)) def test_thirty360_from_name(self): for c in Convention: diff --git a/test/test_heston_model.py b/test/test_heston_model.py index b5860046e..390cc3277 100644 --- a/test/test_heston_model.py +++ b/test/test_heston_model.py @@ -19,7 +19,6 @@ from quantlib.pricingengines.blackformula import blackFormula from quantlib.pricingengines.vanilla.vanilla import BatesDetJumpEngine from quantlib.pricingengines.vanilla.analytic_heston_engine import AnalyticHestonEngine, Integration -from quantlib.processes.heston_process import QuadraticExponential from quantlib.math.optimization import LevenbergMarquardt, EndCriteria from quantlib.settings import Settings from quantlib.time.api import ( @@ -385,7 +384,7 @@ def test_smith(self): process = HestonProcess( risk_free_ts, dividend_ts, s0, v0, kappa, theta, - sigma, rho, QuadraticExponential) + sigma, rho, HestonProcess.QuadraticExponential) model = HestonModel(process) diff --git a/test/test_indexes.py b/test/test_indexes.py index a618ccd94..c527f985e 100644 --- a/test/test_indexes.py +++ b/test/test_indexes.py @@ -155,11 +155,11 @@ class IndexManagerTestCase(unittest.TestCase): def test_index_manager_methods(self): self.assertIn(self.index.name, IndexManager.histories()) - ts = IndexManager.get_history(self.index.name) + ts = self.index.time_series self.assertEqual(ts[Date(5, 2, 2018)], 1.79345) self.assertEqual(ts[Date(2, 2, 2018)], 1.78902) - IndexManager.clear_histories() - self.assertFalse(IndexManager.get_history(self.index.name)) + self.index.clear_fixings() + self.assertFalse(self.index.has_historical_fixing(Date(5, 2, 2018))) if __name__ == '__main__': unittest.main() diff --git a/test/test_interest_rate.py b/test/test_interest_rate.py index 95b1af0ce..faef301fb 100644 --- a/test/test_interest_rate.py +++ b/test/test_interest_rate.py @@ -4,7 +4,7 @@ from quantlib.compounding import Continuous, Compounded from quantlib.time.api import Actual360, Monthly, NoFrequency, Once, Thirty360 -from quantlib.time.daycounters.thirty360 import Thirty360, Italian +from quantlib.time.daycounters.thirty360 import Thirty360 class InterestRateTestCase(unittest.TestCase): @@ -55,7 +55,7 @@ def test_create_interest_rate_compounded_error(self): def test_create_intereste_rate_with_daycounter_convention(self): rate = 0.05 - counter = Thirty360(Italian) + counter = Thirty360(Thirty360.Italian) compounding = Compounded frequency = Monthly interest_rate = InterestRate(rate, counter, compounding, frequency) diff --git a/test/test_mlab.py b/test/test_mlab.py index 8ff27b19b..afb2504b5 100644 --- a/test/test_mlab.py +++ b/test/test_mlab.py @@ -13,7 +13,7 @@ from quantlib.termstructures.yields.api import ( PiecewiseYieldCurve, BootstrapTrait ) from quantlib.math.interpolation import LogLinear -from quantlib.time.api import ActualActual, ISDA, Frequency +from quantlib.time.api import ActualActual, Frequency from quantlib.util.converter import pydate_to_qldate @@ -91,7 +91,7 @@ def test_yield(self): h = make_rate_helper(label, rate, settlement_date) rate_helpers.append(h) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date( diff --git a/test/test_piecewise_yield_curve.py b/test/test_piecewise_yield_curve.py index f27d599bc..985158431 100644 --- a/test/test_piecewise_yield_curve.py +++ b/test/test_piecewise_yield_curve.py @@ -19,7 +19,7 @@ PiecewiseYieldCurve ) from quantlib.time.api import Date, TARGET, Period, Months, Years, Days -from quantlib.time.api import September, ISDA, today, Mar +from quantlib.time.api import September, today, Mar from quantlib.time.api import ModifiedFollowing, Unadjusted, Actual360 from quantlib.time.api import Thirty360, ActualActual, Actual365Fixed from quantlib.time.api import Annual, UnitedStates @@ -67,7 +67,7 @@ def test_creation(self): rate_helpers.append(helper) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 @@ -107,7 +107,7 @@ def test_relative_yieldcurve(self): quote, Period(month, Months), fixing_days, calendar, convention, end_of_month, deposit_day_counter) for quote, month in zip(quotes, tenors)] - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 @@ -148,7 +148,7 @@ def test_bump_yieldcurve(self): quote, Period(month, Months), fixing_days, calendar, convention, end_of_month, deposit_day_counter) for quote, month in zip(quotes, tenors)] - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 @@ -182,7 +182,7 @@ def test_discount_curve(self): quote, Period(month, Months), fixing_days, calendar, convention, end_of_month, deposit_day_counter) for quote, month in zip(quotes, tenors)] - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 @@ -309,7 +309,7 @@ def test_deposit_swap(self): rate_helpers.append(helper) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-15 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date( diff --git a/test/test_sensitivity_analysis.py b/test/test_sensitivity_analysis.py deleted file mode 100644 index 803bf70fd..000000000 --- a/test/test_sensitivity_analysis.py +++ /dev/null @@ -1,237 +0,0 @@ -import unittest - -from quantlib.instruments.api import MakeVanillaSwap, FixedRateBond -from quantlib.pricingengines.bond import DiscountingBondEngine -from quantlib.time.calendars.target import TARGET -from quantlib.time.calendars.united_states import UnitedStates, Market -from quantlib.instruments.option import VanillaOption, OptionType -from quantlib.instruments.exercise import EuropeanExercise -from quantlib.time.date import ( - Date, Days, January, - Period, May, Years) -from quantlib.time.api import (Months, ISDA, - ModifiedFollowing, Unadjusted, Actual360, - Thirty360, ActualActual, - Actual365Fixed, Semiannual, Annual) -from quantlib.time.daycounters.actual_actual import Bond -from quantlib.time.schedule import Schedule -from quantlib.time.dategeneration import DateGeneration -from quantlib.settings import Settings -from quantlib.indexes.ibor.usdlibor import USDLibor -from quantlib.termstructures.yields.rate_helpers import ( - DepositRateHelper, SwapRateHelper) -from quantlib.termstructures.yields.piecewise_yield_curve \ - import PiecewiseYieldCurve -from quantlib.termstructures.yields.api import ( - FlatForward, BootstrapTrait, HandleYieldTermStructure) -from quantlib.math.interpolation import LogLinear -from quantlib.quotes import SimpleQuote -from quantlib.termstructures.volatility.equityfx.black_constant_vol \ - import BlackConstantVol -from quantlib.processes.black_scholes_process import BlackScholesMertonProcess -from quantlib.pricingengines.vanilla.vanilla import ( - AnalyticEuropeanEngine -) -from quantlib.instruments.payoffs import PlainVanillaPayoff -import quantlib.pricingengines.bond.bondfunctions as bf -from quantlib.experimental.risk.sensitivityanalysis import ( - bucket_analysis, parallel_analysis, Centered) -from numpy.testing import assert_allclose - -class SensitivityTestCase(unittest.TestCase): - - def setUp(self): - self.calendar = TARGET() - self.settlement_days = 1 - settlement_date = self.calendar.adjust(Date(28, January, 2011)) - todays_date = self.calendar.advance( - settlement_date, -self.settlement_days, Days - ) - Settings().evaluation_date = todays_date - - depositData = [[ 1, Months, 4.581 ], - [ 2, Months, 4.573 ], - [ 3, Months, 4.557 ], - [ 6, Months, 4.496 ], - [ 9, Months, 4.490 ]] - - swapData = [[ 1, Years, 4.54 ], - [ 5, Years, 4.99 ], - [ 10, Years, 5.47 ], - [ 20, Years, 5.89 ], - [ 30, Years, 5.96 ]] - - self.rate_helpers = [] - self.quotes = [] - - end_of_month = True - for m, period, rate in depositData: - tenor = Period(m, Months) - q = SimpleQuote(rate / 100) - helper = DepositRateHelper(q, - tenor, - self.settlement_days, - self.calendar, - ModifiedFollowing, - end_of_month, - Actual360()) - self.quotes.append(q) - self.rate_helpers.append(helper) - - liborIndex = USDLibor(Period(6, Months)) - - for m, period, rate in swapData: - sq_rate = SimpleQuote(rate/100) - helper = SwapRateHelper.from_tenor( - sq_rate, Period(m, Years), self.calendar, Annual, Unadjusted, - Thirty360(), liborIndex - ) - self.quotes.append(sq_rate) - self.rate_helpers.append(helper) - - ts_day_counter = ActualActual(ISDA) - tolerance = 1.0e-15 - - self.ts = HandleYieldTermStructure( - PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear]( - self.settlement_days, - self.calendar, self.rate_helpers, ts_day_counter, accuracy=tolerance) - ) - - def test_bucketanalysis_bond(self): - - face_amount = 100.0 - redemption = 100.0 - issue_date = Date(27, January, 2011) - maturity_date = Date(1, January, 2021) - coupon_rate = 0.055 - - fixed_bond_schedule = Schedule.from_rule( - issue_date, - maturity_date, - Period(Semiannual), - UnitedStates(market=Market.GovernmentBond), - Unadjusted, - Unadjusted, - DateGeneration.Backward, - False) - - bond = FixedRateBond( - self.settlement_days, - face_amount, - fixed_bond_schedule, - [coupon_rate], - ActualActual(Bond), - Unadjusted, - redemption, - issue_date - ) - - pricing_engine = DiscountingBondEngine(self.ts) - bond.set_pricing_engine(pricing_engine) - - self.assertAlmostEqual(bond.npv, 100.82127876105724) - delta, gamma = bucket_analysis(self.quotes, [bond]) - self.assertEqual(len(self.quotes), len(delta)) - old_values = [q.value for q in self.quotes] - delta_manual = [] - gamma_manual = [] - pv = bond.npv - shift = 1e-4 - for v, q in zip(old_values, self.quotes): - q.value = v + shift - pv_plus = bond.npv - q.value = v - shift - pv_minus = bond.npv - delta_manual.append((pv_plus - pv_minus) * 0.5 / shift) - gamma_manual.append((pv_plus - 2 * pv + pv_minus) / shift ** 2) - q.value = v - assert_allclose(delta, delta_manual) - assert_allclose(gamma, gamma_manual, atol=1e-4) - - def test_bucket_analysis_option(self): - - settings = Settings() - - calendar = TARGET() - - todays_date = Date(15, May, 1998) - settlement_date = Date(17, May, 1998) - - settings.evaluation_date = todays_date - - option_type = OptionType.Put - underlying = 40 - strike = 40 - dividend_yield = 0.00 - risk_free_rate = 0.001 - volatility = SimpleQuote(0.20) - maturity = Date(17, May, 1999) - daycounter = Actual365Fixed() - - underlyingH = SimpleQuote(underlying) - - payoff = PlainVanillaPayoff(option_type, strike) - - - flat_term_structure = HandleYieldTermStructure(FlatForward( - reference_date = settlement_date, - forward = risk_free_rate, - daycounter = daycounter - )) - flat_dividend_ts = HandleYieldTermStructure(FlatForward( - reference_date = settlement_date, - forward = dividend_yield, - daycounter = daycounter - )) - - flat_vol_ts = BlackConstantVol( - settlement_date, - calendar, - volatility, - daycounter - ) - - black_scholes_merton_process = BlackScholesMertonProcess( - underlyingH, - flat_dividend_ts, - flat_term_structure, - flat_vol_ts - ) - - european_exercise = EuropeanExercise(maturity) - european_option = VanillaOption(payoff, european_exercise) - analytic_european_engine = AnalyticEuropeanEngine( - black_scholes_merton_process - ) - - european_option.set_pricing_engine(analytic_european_engine) - - - delta, gamma = bucket_analysis( - [underlyingH, volatility], [european_option], shift=1e-4, - type=Centered) - self.assertAlmostEqual(delta[0], european_option.delta) - self.assertAlmostEqual(delta[1], european_option.vega) - self.assertAlmostEqual(gamma[0], european_option.gamma, 5) - - def test_parallel_analysis(self): - index = USDLibor(Period(3, Months), self.ts) - swap = MakeVanillaSwap(Period(10, Years), - index)() - old_values = [q.value for q in self.quotes] - dv01, _ = parallel_analysis(self.quotes, [swap]) - shift = 1e-4 - - for v, q in zip(old_values, self.quotes): - q.value = v + shift - pv_plus = swap.npv - - for v, q in zip(old_values, self.quotes): - q.value = v - shift - pv_minus = swap.npv - - self.assertAlmostEqual((pv_plus - pv_minus) * 0.5 / shift, dv01) - -if __name__ == '__main__': - unittest.main() diff --git a/test/test_settings.py b/test/test_settings.py index e679e2c0f..4348a526c 100644 --- a/test/test_settings.py +++ b/test/test_settings.py @@ -2,7 +2,7 @@ from quantlib.instruments.bonds import FixedRateBond from quantlib.time.api import ( Date, Days, August, Period, Jul, Annual, today, Years, TARGET, - Unadjusted, Schedule, ModifiedFollowing, DateGeneration, ActualActual, ISMA, + Unadjusted, Schedule, ModifiedFollowing, DateGeneration, ActualActual, Following ) @@ -85,7 +85,7 @@ def test_bond_schedule_today(self): face_amount, fixed_bond_schedule, [coupon_rate], - ActualActual(ISMA), + ActualActual(ActualActual.ISMA), Following, redemption, issue_date @@ -134,7 +134,7 @@ def test_bond_schedule_anotherday(self): face_amount, fixed_bond_schedule, [coupon_rate], - ActualActual(ISMA), + ActualActual(ActualActual.ISMA), Following, redemption, issue_date @@ -143,15 +143,5 @@ def test_bond_schedule_anotherday(self): self.assertEqual( calendar.advance(todays_date, 3, Days), bond.settlement_date()) - def test_bond_schedule_anotherday_bug_cython_implementation(self): - - from . import test_cython_bug as tcb - - date1, date2 = tcb.test_bond_schedule_today_cython() - self.assertEqual(date1, date2) - - date1, date2 = tcb.test_bond_schedule_anotherday_cython() - self.assertEqual(date1, date2) - if __name__ == "__main__": unittest.main() diff --git a/test/test_simulate.py b/test/test_simulate.py index ca8b300af..0d48b8f2d 100644 --- a/test/test_simulate.py +++ b/test/test_simulate.py @@ -16,8 +16,6 @@ from quantlib.sim.simulate import simulate_process from quantlib.time_grid import TimeGrid -from quantlib.processes.heston_process import PartialTruncation - from .utilities import flat_rate @@ -49,7 +47,7 @@ def setUp(self): self.heston_process = HestonProcess(self.risk_free_ts, self.dividend_ts, s0, v0, kappa, theta, sigma, rho, - PartialTruncation) + HestonProcess.PartialTruncation) v0 = 0.05 ival = {'v0': v0, 'kappa': 3.7, 'theta': v0, diff --git a/test/test_swaption.py b/test/test_swaption.py index f0adf9fb1..55b27b0e5 100644 --- a/test/test_swaption.py +++ b/test/test_swaption.py @@ -28,7 +28,7 @@ def test_make_swaption(self): swaption = self.factory() self.assertEqual(swaption.settlement_type, Settlement.Cash) self.assertEqual(swaption.settlement_method, Settlement.ParYieldCurve) - swap = swaption.underlying_swap() + swap = swaption.underlying() self.assertEqual(swap.type, Swap.Receiver) self.assertEqual(swaption.type, Swap.Receiver) exercise_date = self.index.fixing_calendar.advance( diff --git a/test/test_zero_coupon.py b/test/test_zero_coupon.py index afad15626..89ff9f4af 100644 --- a/test/test_zero_coupon.py +++ b/test/test_zero_coupon.py @@ -14,7 +14,7 @@ from quantlib.time.api import ( Period, Months, Date, Days, TARGET, ModifiedFollowing, Years, Actual360, Semiannual, - Thirty360, ActualActual, ISDA + Thirty360, ActualActual ) from datetime import date @@ -92,7 +92,7 @@ def test_extrapolation(self): print('dt Obs: %s\ndt Eval: %s\ndt Settle: %s' % (dtObs, eval_date, settlement_date)) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-2 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date( @@ -125,7 +125,7 @@ def test_zero_curve(self): # must be a business day settlement_date = calendar.adjust(settlement_date) - ts_day_counter = ActualActual(ISDA) + ts_day_counter = ActualActual(ActualActual.ISDA) tolerance = 1.0e-2 ts = PiecewiseYieldCurve[BootstrapTrait.Discount, LogLinear].from_reference_date(