Closed andrzimin72 closed 2 months ago
Thanks for posting! It might take a while before we look at your issue, so don't worry if there seems to be no feedback. We'll get to it.
I'm kind of guessing since I don't know how you initialized the various variables, but
model.calibrate(swaptions, optimization_method, end_criteria)
might work. The operator()
you're calling is for internal use of the model. I'm not sure it should be exposed to Python.
Thank you very much for your good advices. May be you a right. But I have read very interesting article about this topic: “The Levenberg-Marquardt Method and its Implementation in Python” submitted by Marius Kaltenbach (Konstanzer Online-Publikations-System (KOPS) URL: http://nbn-resolving.de/urn:nbn:de:bsz:352-2-1ofyba49ud2jr5). So far I have no complaints about this argument ‘statState’. I think the input parameters of this argument are: -maximum iterations: restrict the maximum number of solver iterations; -minimum stationary state iterations: give a minimum number of iterations at stationary point (for both, function value stationarity and root stationarity). I suppose that not all of the end criteria are needed in each optimizer. I haven’t found any argument 3 of type 'Size &' which checks for the optimization. Furthermore, the argument which leads to a stopping of the algorithm is returned. May be it should be checked that this criteria is not of type EndCriteria::None. But I don't know how to calculate argument 3 of type 'Size &' in method 'EndCriteria_call'. And I don't know how to change it.
You don't have to call the method 'EndCriteriacall'. That method is internal and shouldn't be exposed to Python.
You have already passed the input parameters to the EndCriteria
constructor and built end_criteria
. You can pass it to the calibrate
method by saying model.calibrate(swaptions, optimization_method, end_criteria)
.
Thank you very much for your good advices. I corrected the error in the script, so it shouldn't happen again. Apparently there is another problem with the code. model.calibrate(swaptions, optimization_method, end_criteria) File "/pandas1/lib/python3.10/site-packages/QuantLib/QuantLib.py", line 16672, in calibrate return _QuantLib.CalibratedModel_calibrate(self, *args) RuntimeError: wrong argument type I suppose in general there is now be another possibilities to find out where exactly in the code it goes wrong. I have read the instructions https://www.implementingquantlib.com/2013/08/chapter-5-part-4-of-5-models-and.html, https://rkapl123.github.io/QLAnnotatedSource/d7/db6/class_quant_lib_1_1_calibrated_model.html. May be I am again a bit confused here.
Hard to say what's wrong without seeing the rest of the code. Can you post a script that we can run to reproduce the problem?
But you're a busy man. Therefore, if I’m already in a difficult situation, I should not waste your time on unnecessary thoughts or waiting for a miracle, which simply can not be. For a long time I assumed that this error was due purely to my own personal bumbling, and not a problem with the method. Anyway I'm trying to answer the question, to articulate my ask. vasicek_calib.zip
No problem, it took all of 5 minutes once I had code to run. The code below runs the calibration. You were nearly there. The needed changes were:
BlackCallableFixedRateBondEngine
can't work with swaptions. The JamshidianSwaptionEngine
you tried and then commented out works.CalibrationData(0, 1, 0.1)
(a swaption can't have 0 time to exercise) and replaced with another item because we need at least 4 of them; I picked time to exercise = 2.EndCriteria__call__
.import numpy as np
import QuantLib as ql
from collections import namedtuple
import math
def create_swaption_helpers(data_, index_, term_structure_, engine_):
swaptions_ = []
fixed_leg_tenor = ql.Period(1, ql.Years)
fixed_leg_daycounter = ql.Actual360()
floating_leg_daycounter = ql.Actual360()
for d in data_:
vol_handle = ql.QuoteHandle(ql.SimpleQuote(d.volatility))
helper = ql.SwaptionHelper(ql.Period(d.start, ql.Months),
ql.Period(d.length, ql.Months),
vol_handle,
index_,
fixed_leg_tenor,
fixed_leg_daycounter,
floating_leg_daycounter,
term_structure_,
ql.BlackCalibrationHelper.RelativePriceError,
ql.nullDouble(),
1.,
ql.Normal,
0.
)
helper.setPricingEngine(engine_)
swaptions_.append(helper)
return swaptions_
def calibration_report(swaptions_, data_):
print("-" * 82)
print("%15s %15s %15s %15s %15s" % \
("Model Price", "Market Price", "Implied Vol", "Market Vol", "Rel Error"))
print("-" * 82)
cum_err = 0.0
for i, s in enumerate(swaptions_):
model_price = s.modelValue()
market_vol = data_[i].volatility
black_price = s.blackPrice(market_vol)
rel_error = model_price / black_price - 1.0
implied_vol = s.impliedVolatility(model_price,
1e-6, 500, 0.0, 0.50)
rel_error2 = implied_vol / market_vol - 1.0
cum_err += rel_error2 * rel_error2
print("%15.5f %15.5f %15.5f %15.5f %15.5f" % \
(model_price, black_price, implied_vol, market_vol, rel_error))
print("-" * 82)
print("Cumulative Error : %15.5f" % math.sqrt(cum_err))
today = ql.Date().todaysDate()
# ql.Settings.instance().evaluationDate = today
# crv = ql.ZeroCurve([today, settlement], [0.05, 0.05], ql.Actual365Fixed())
crv = ql.FlatForward(today, 0.05, ql.Actual365Fixed())
yts = ql.YieldTermStructureHandle(crv)
vol = ql.QuoteHandle(ql.SimpleQuote(0.1))
model = ql.Vasicek(r0=0.05, a=0.2, b=0.05, sigma=0.1)
# engine = ql.BlackCallableFixedRateBondEngine(vol, yts)
engine = ql.JamshidianSwaptionEngine(model, yts)
index = ql.Euribor1Y(yts)
CalibrationData = namedtuple("CalibrationData",
"start, length, volatility")
data = [
# CalibrationData(0, 1, 0.1),
CalibrationData(1, 1, 0.1),
CalibrationData(2, 1, 0.1),
CalibrationData(3, 1, 0.1),
CalibrationData(4, 1, 0.1)
]
swaptions = create_swaption_helpers(data, index, yts, engine)
optimization_method = ql.LevenbergMarquardt(1.0e-8, 1.0e-8, 1.0e-8)
end_criteria = ql.EndCriteria(10000, 100, 1e-6, 1e-8, 1e-8)
model.calibrate(swaptions, optimization_method, end_criteria)
calibration_report(swaptions, data)
a, b, sigma, lam = model.params()
print('%6.5f' % a, '%6.5f' % b, '%6.5f' % sigma, '%6.5f' % lam)
It's amazing incredible! Excellent attention, you have solved the problem. I’m grateful for your help and support. Also, I am grateful for the good fortune to learn at you, to communicate with the great minds, I'm not afraid of this word, experts in programming and machine learning. May be interest to the independent decision of a problem is the stimulus, driving force of process of knowledge. I hope this information proves helpful to someone in the future. Regards!
This issue was automatically marked as stale because it has been open 60 days with no activity. Remove stale label or comment, or this will be closed in two weeks.
I cordially salute the participants of the QuantLib conference. As for me one of the most important tools, in particular in calibration procedures, is an optimizer of a function. For example, my typical problem is: find a model parameter set such that some cost function is minimized. The available optimizers in QuantLib are Levenberg Marquardt methods. To setup up an optimizer, I need to define the end criteria which lead to a successful optimization. They are summarized in the EndCriteria class whose constructor os EndCriteria (StationaryStateIterations). I wrote a small piece of code to сonsider the Vasicek model for standard Brownian motion. With a little bit of bad advice, I find myself facing a much bigger challenge.
model.calibrate(swaptions, optimization_method, end_criteria(10000, 100, 1e-6, 1e-8, 1e-8, 1.0e-8, 1.0e-8, 1.0e-8)) File "pandas1/lib/python3.10/site-packages/QuantLib/QuantLib.py", line 7508, in callreturn _QuantLib.EndCriteria_call_(self, iteration, statState, positiveOptimization, fold, normgold, fnew, normgnewx, ecType) TypeError: in method 'EndCriteriacall__', argument 3 of type 'Size &'
I am new in this field, could you please guide me about this error. And how should I write this argument ‘statState’ of type 'Size &'?