I am following this example and trying to adapt it to my needs.
In the section of code:
implied_vols[i][j] = data[j][i]
implied_vols = ql.Matrix(len(strikes), len(expiration_dates))
for i in range(implied_vols.rows()):
for j in range(implied_vols.columns()):
implied_vols[i][j] = data[j][i]
[1]: http://gouthamanbalaraman.com/blog/volatility-smile-heston-model-calibration-quantlib-python.html
This assumes the IV
matrix
has all corresponding strikes
for a given expiry. In fact, the [mass] quote
is often stored in a dictionary
instead of an array
exactly for this reason.
For example in the SPX
, we have different strike
increments at different expiration
. So some strikes
are empty for one expiry but not another. I realize I can force the situation by making the matrix
cell always have numerical value, but I am assuming that inserting a 0 at a given strike/expiry
is a bad idea. Alternatively, forcing all expiry
to the least common denominator of strikes
between the expiry
throws out lots of data.
What happens if the volatility
quotes you have are not square and you don't want to throw out data when building a ql.Matrix
to hand to BlackVarianceSurface
?
Unfortunately, there's no ready-made solution. As you say filling the missing cells with 0 is a bad idea; but filling them by interpolating manually the missing values should work. The way to do it probably depends on how sparse your data is...