def objective_shape(self, predictive_model, date, nb_samples_x=100, nb_samples_y=100): df = du.from_hdf5(self.key_model, du.h5file) self.set_date(date) params_predict = predictive_model.predict((self.values, self._ircurve.values)) params_predict = params_predict.reshape((params_predict.shape[1],)) self.model.setParams(ql.Array(params_predict.tolist())) print("Predict value = %f" % self.model.value(self.model.params(), self.helpers)) orig_objective = df.ix[date, 'OrigObjective'] hist_objective = df.ix[date, 'HistObjective'] if orig_objective < hist_objective: name = 'OrigParam' else: name = 'HistParam' params_calib = np.array([df.ix[date, name + '0'], df.ix[date, name + '1'], df.ix[date, name + '2'], df.ix[date, name + '3'], df.ix[date, name + '4']]) self.model.setParams(ql.Array(params_calib.tolist())) print("Calib value = %f" % self.model.value(self.model.params(), self.helpers)) params_optim = np.array(self._default_params) self.model.setParams(self._default_params) print("Optim value = %f" % self.model.value(self.model.params(), self.helpers)) #The intention is to sample the plane that joins the three points: #params_predict, params_calib, and params_optim #A point on that plane can be described by Q(alpha, beta) #Q(alpha, beta) = params_predict+(alpha-beta(A*B)/(A*A))A+beta B #with A = params_calib - params_predict # and B = params_optim - params_predict Aa = np.sqrt(np.dot(A, A)) Ba = np.dot(A, B)/Aa lim_alpha = np.array([np.min((Ba, 0)), np.max((Ba/Aa, 1))]) da = lim_alpha[1] - lim_alpha[0] lim_alpha += np.array([-1.0, 1.0])*da/10 lim_beta = np.array([-0.1, 1.1]) ls_alpha = np.linspace(lim_alpha[0], lim_alpha[1], nb_samples_x) ls_beta = np.linspace(lim_beta[0], lim_beta[1], nb_samples_y) xv, xy = np.meshgrid(ls_alpha, ls_beta) sh = xv.shape samples = [params_predict + (alpha-beta*Ba/Aa)*A+beta*B for alpha, beta in zip(xv.reshape((-1,)), xy.reshape((-1,)))] objectives = np.empty((len(samples), )) for i, params in enumerate(samples): try: self.model.setParams(ql.Array(params.tolist())) objectives[i] = self.model.value(self.model.params(), self.helpers) except RuntimeError: objectives[i] = np.nan return (objectives.reshape(sh), lim_alpha, lim_beta)
def g2_method_local(): method = ql.LevenbergMarquardt() criteria = ql.EndCriteria(250, 200, 1e-7, 1e-7, 1e-7) lower = ql.Array(5, 1e-9) upper = ql.Array(5, 1.0) lower[4] = -1.0 constraint = ql.NonhomogeneousBoundaryConstraint(lower, upper) return (method, criteria, constraint)
def evaluate(self, params, irValues, date): self.refdate = ql.Date(date.day, date.month, date.year) _, curve = self._ircurve.build(self.refdate, irValues) self._term_structure.linkTo(curve) qlParams = ql.Array(params.tolist()) self.model.setParams(qlParams) return self.__errors()
def testSparseLinearMatrixSolver(self): """Testing sparse linear matrix solver""" A = ql.Matrix([[1.0, 0.0, 1.0], [0.0, 1.0, 0.5], [1.0, 0.5, 1.0]]) b = ql.Array([1.0, 0.2, 0.5]) expected = ql.inverse(A) * b def foo(x): return A * x calculated = ql.BiCGstab(ql.MatrixMultiplicationProxy(foo), 100, 1e-6).solve(b) for i in range(3): self.assertAlmostEqual(expected[i], calculated[i], 4) calculated = ql.GMRES(ql.MatrixMultiplicationProxy(foo), 100, 1e-6).solve(b) for i in range(3): self.assertAlmostEqual(expected[i], calculated[i], 4) def preconditioner(x): return ql.inverse(A) * x calculated = ql.BiCGstab( ql.MatrixMultiplicationProxy(foo), 100, 1e-6, ql.MatrixMultiplicationProxy(preconditioner)).solve(b) for i in range(3): self.assertAlmostEqual(expected[i], calculated[i], 4)
def train_history(self, *kwargs): #Retrieves training data from history if 'history_start' in kwargs: history_start = kwargs['history_start'] history_end = kwargs['history_end'] history_part = None else: history_start = None history_end = None if 'history_part' in kwargs: history_part = kwargs['history_part'] else: history_part = 0.4 if 'save' in kwargs and kwargs['save']: if 'file_name' in kwargs: file_name = kwargs['file_name'] else: file_name = sample_file_name(self, 0, True, history_start, history_end, history_part) print('Saving to file %s' % file_name) (dates, y, swo_error) = \ self.__history(history_start, history_end, history_part, True) x_ir = self._ircurve.to_matrix(dates) #Calculate volatilities according to different conditions nb_instruments = len(self.helpers) nb_dates = len(dates) x_swo = np.zeros((nb_dates, nb_instruments), float_type) for row in range(nb_dates): #Set term structure self.set_date(dates[row]) self.model.setParams(ql.Array(y[row, :].tolist())) for swaption in range(nb_instruments): try: NPV = self.helpers[swaption].modelValue() vola = self.helpers[swaption].impliedVolatility(NPV, 1.0e-6, 1000, 0.0001, 2.50) x_swo[row, swaption] = np.clip(vola - swo_error[row, swaption], 0., np.inf) except RuntimeError as e: print('Exception (%s) for (sample, maturity, length): (%s, %s, %s)' % (e, row, self._maturities[swaption], self._lengths[swaption])) if 'save' in kwargs and kwargs['save']: if 'append' in kwargs and kwargs['append']: try: x_swo_l = np.load(file_name + '_x_swo.npy') x_ir_l = np.load(file_name + '_x_ir.npy') y_l = np.load(file_name + '_y.npy') x_swo = np.concatenate((x_swo_l, x_swo), axis=0) x_ir = np.concatenate((x_ir_l, x_ir), axis=0) y = np.concatenate((y_l, y), axis=0) except Exception as e: print(e) np.save(file_name + '_x_swo', x_swo) np.save(file_name + '_x_ir', x_ir) np.save(file_name + '_y', y) return (x_swo, x_ir, y)
def cost_function(params): params_ = ql.Array(list(params)) model.setParams(params_) error = [h.calibrationError() for h in helpers] if norm: return np.sqrt(np.sum(np.abs(error))) else: return error
def errors(self, predictive_model, date): df_error = du.from_hdf5(self.key_error, du.h5file) orig_errors = df_error.loc[date] self.refdate = ql.Date(1, 1, 1901) self.set_date(date) params = predictive_model.predict((self.values, self._ircurve.values)) self.model.setParams(ql.Array(params.tolist()[0])) _, errors = self.__errors() return (orig_errors, errors)
def compare_history(self, predictive_model, dates=None, plot_results=False): store = pd.get_store(du.h5file) df = store[self.key_model] store.close() self.refdate = ql.Date(1, 1, 1901) vals = np.zeros((len(df.index), 2)) values = np.zeros((len(df.index), 6)) if dates is None: dates = self._dates for i in xrange(len(self._dates)): date = self._dates[i] self.set_date(date) params = predictive_model.predict( (self.values, self._ircurve.values)) self.model.setParams(ql.Array(params.tolist()[0])) meanErrorPrior, _ = self.__errors() objectivePrior = self.model.value(self.model.params(), self.helpers) origMeanError = df.ix[date, 'OrigMeanError'] histMeanError = df.ix[date, 'HistMeanError'] origObjective = df.ix[date, 'OrigObjective'] histObjective = df.ix[date, 'HistObjective'] values[i, 0] = origMeanError values[i, 1] = histMeanError values[i, 2] = meanErrorPrior values[i, 3] = origObjective values[i, 4] = histObjective values[i, 5] = objectivePrior print('Date=%s' % date) print('Vola: Orig=%s Hist=%s Model=%s' % (origMeanError, histMeanError, meanErrorPrior)) print('NPV: Orig=%s Hist=%s Model=%s' % (origObjective, histObjective, objectivePrior)) vals[i, 0] = (meanErrorPrior - origMeanError) / origMeanError * 100.0 vals[i, 1] = (meanErrorPrior - histMeanError) / histMeanError * 100.0 print(' impO=%s impH=%s' % (vals[i, 0], vals[i, 1])) if plot_results: r = range(vals.shape[0]) fig = plt.figure(figsize=(16, 16)) f1 = fig.add_subplot(211) f1.plot(r, vals[:, 0]) f2 = fig.add_subplot(212) f2.plot(r, vals[:, 1]) return (dates, values)
def g2_method(): n = 5 lower = ql.Array(n, 1e-9); upper = ql.Array(n, 1.0); lower[n-1] = -1.0; upper[n-1] = 1.0; constraint = ql.NonhomogeneousBoundaryConstraint(lower, upper); maxSteps = 5000; staticSteps = 600; initialTemp = 50.0; finalTemp = 0.001; sampler = ql.SamplerMirrorGaussian(lower, upper, seed); probability = ql.ProbabilityBoltzmannDownhill(seed); temperature = ql.TemperatureExponential(initialTemp, n); method = ql.MirrorGaussianSimulatedAnnealing(sampler, probability, temperature, ql.ReannealingTrivial(), initialTemp, finalTemp) criteria = ql.EndCriteria(maxSteps, staticSteps, 1.0e-8, 1.0e-8, 1.0e-8); return (method, criteria, constraint)
def errors(self, predictive_model, date): with pd.get_store(du.h5file) as store: df_error = store[self.key_error] orig_errors = df_error.loc[date] store.close() self.refdate = ql.Date(1, 1, 1901) self.set_date(date) params = predictive_model.predict((self.values, self._ircurve.values)) self.model.setParams(ql.Array(params.tolist()[0])) _, errors = self.__errors() return (orig_errors, errors)
def history_heatmap(self, predictive_model, dates=None): self.refdate = ql.Date(1, 1, 1901) if dates is None: dates = self._dates errors_mat = np.zeros((len(dates), len(self.helpers))) for i, date in enumerate(dates): date = self._dates[i] self.set_date(date) params = predictive_model.predict((self.values, self._ircurve.values)) self.model.setParams(ql.Array(params.tolist()[0])) _, errors_mat[i, :] = self.__errors() return errors_mat
def objective_values(self, predictive_model, date_start, date_end): dates = self._dates[date_start:date_end] objective_predict = np.empty((len(dates), )) volas_predict = np.empty((len(dates), )) for i, date in enumerate(dates): self.set_date(date) params = predictive_model.predict((self.values, self._ircurve.values)) self.model.setParams(ql.Array(params.tolist()[0])) volas_predict[i], _ = self.__errors() try: objective_predict[i] = self.model.value(self.model.params(), self.helpers) except RuntimeError: objective_predict[i] = np.nan return (objective_predict, volas_predict)
def plot4(): swo = inst.get_swaptiongen(inst.hullwhite_analytic) df = pd.get_store(du.h5file)[swo.key_model] d1 = df.loc['2015-06-01'] d2 = df.loc['2015-06-02'] x1_orig = d1.loc['OrigParam0'] x1_hist = d1.loc['HistParam0'] x2_orig = d2.loc['OrigParam0'] x2_hist = d2.loc['HistParam0'] y1_orig = d1.loc['OrigParam1'] y1_hist = d1.loc['HistParam1'] y2_orig = d2.loc['OrigParam1'] y2_hist = d2.loc['HistParam1'] x_default = 0.1 y_default = 0.01 xmin = min(x_default, x1_orig, x2_orig, x1_hist, x2_hist) xmax = max(x_default, x1_orig, x2_orig, x1_hist, x2_hist) ymin = min(y_default, y1_orig, y2_orig, y1_hist, y2_hist) ymax = max(y_default, y1_orig, y2_orig, y1_hist, y2_hist) (X, Y, Z) = inst.local_hw_map(swo, '2015-06-02', [xmin, ymin], [xmax, ymax], nb_points=20) fig = plt.figure(figsize=(20, 20)) ax = fig.add_subplot(111, projection='3d') ax.plot_surface(X, Y, Z, alpha=0.3, cstride=1, rstride=1, linewidth=0, antialiased=True) xpoints = np.array([x1_orig, x2_orig, x2_hist, x_default]) ypoints = np.array([y1_orig, y2_orig, y2_hist, y_default]) zpoints = np.zeros(xpoints.shape) for x, y, rank in zip(xpoints, ypoints, range(len(xpoints))): swo.model.setParams(ql.Array([x, y])) zpoints[rank] = swo.model.value(swo.model.params(), swo.helpers) ax.scatter(xpoints, ypoints, zpoints) plt.savefig('../data/surf.eps', bbox_inches="tight") xpoints.shape = (4, 1) ypoints.shape = (4, 1) zpoints.shape = (4, 1) print np.concatenate((xpoints, ypoints, zpoints), axis=1) return (X, Y, Z)
def testFdmStepConditionCallBack(self): """Testing step condition call back function""" class Foo: @classmethod def applyTo(self, a, t): for i in range(5): a[i] = t + 1.0 m = ql.FdmStepConditionProxy(Foo()) x = ql.Array(5) m.applyTo(x, 2.0) self.assertEqual(len(x), 5) self.assertEqual(list(x), [3.0, 3.0, 3.0, 3.0, 3.0])
def local_hw_map(swo, date, pointA, pointB, off_x=0.1, off_y=0.1, low_x=1e-8, low_y=1e-8, nb_points=20): assert (len(pointA) == 2 and len(pointB) == 2) if pointA[0] > pointB[0]: max_x = pointA[0] min_x = pointB[0] else: min_x = pointA[0] max_x = pointB[0] if pointA[1] > pointB[1]: max_y = pointA[1] min_y = pointB[1] else: min_y = pointA[1] max_y = pointB[1] off_x = (max_x - min_x) * off_x off_y = (max_y - min_y) * off_y max_x += off_x min_x -= off_x max_y += off_y min_y -= off_y if min_x <= low_x: min_x = low_x if min_y <= low_y: min_y = low_y assert (min_x <= max_x and min_y <= max_y) rx = np.linspace(min_x, max_x, nb_points) ry = np.linspace(min_y, max_y, nb_points) xx, yy = np.meshgrid(rx, ry) result = np.empty(xx.shape) result.fill(np.nan) swo.set_date(date) for i, x in enumerate(rx): for j, y in enumerate(ry): swo.model.setParams(ql.Array([x, y])) result[i, j] = swo.model.value(swo.model.params(), swo.helpers) return (xx, yy, result)
def testFdmBoundaryCondition(self): """Testing Dirichlet Boundary conditions""" m = ql.FdmMesherComposite(ql.Uniform1dMesher(0.0, 1.0, 5)) b = ql.FdmDirichletBoundary(m, math.pi, 0, ql.FdmBoundaryCondition.Upper) x = ql.Array(len(m.locations(0)), 0.0) b.applyAfterApplying(x) self.assertEqual(list(x), [0, 0, 0, 0, math.pi]) s = ql.FdmBoundaryConditionSet() s.push_back(b) self.assertEqual(len(s), 1)
print("knotCubic:\t") for v in knotCubic: print('{0:.6f}'.format(v)) print() print("termstrc knots:\t") for v in termstrcKnotes: print('{0:.6f}'.format(v)) print() print("knotQuadratic:\t") for v in knotQuadratic: print('{0:.6f}'.format(v)) csf = ql.CubicSplinesFitting(knotCubic, ql.Array(), optMethod) qsf = ql.QuadraticSplinesFitting(knotQuadratic, ql.Array(), optMethod) tsCubicSplines = ql.FittedBondDiscountCurve(bondSettlementDate, instruments, dayCounter, csf, tolerance, max) tsQuadraticSplines = ql.FittedBondDiscountCurve(bondSettlementDate, instruments, dayCounter, qsf, tolerance, max) weightsCubic = tsCubicSplines.fitResults().solution() weightsQuadratic = tsQuadraticSplines.fitResults().solution() termstrcWeights = ql.Array(7) termstrcWeights[0] = 1.9320e-02 termstrcWeights[1] = -8.4936e-05 termstrcWeights[2] = -3.2009e-04 termstrcWeights[3] = -3.7101e-04
def training_data(self, nb_samples, with_error=True, **kwargs): #Prepares nb_samples by sampling from the model parameters and generating #a term structure with the use of PCA, and then evaluates the set of #swaptions to produce volatilities #The sample is of the form (x_swo, x_ir,y), where x_swo and x_ir are the #future input for the supervised machine learning algorithm, and y is #the desired output #Draw random model parameters and IR curves if 'seed' in kwargs: np.random.seed(kwargs['seed']) else: np.random.seed(0) if 'history_start' in kwargs: history_start = kwargs['history_start'] history_end = kwargs['history_end'] history_part = None else: history_start = None history_end = None if 'history_part' in kwargs: history_part = kwargs['history_part'] else: history_part = 0.4 if 'save' in kwargs and kwargs['save']: if 'file_name' in kwargs: file_name = kwargs['file_name'] else: file_name = sample_file_name(self, nb_samples, with_error, history_start, history_end, history_part) print('Saving to file %s' % file_name) (y, ir_draw, error_draw, dates) = self.__random_draw(nb_samples, with_error=with_error, history_start=history_start, history_end=history_end, history_part=history_part) #Draw random dates date_index = np.random.randint(0, len(dates), nb_samples) dates = dates[date_index] #Calculate volatilities according to different conditions nb_instruments = len(self.helpers) x_swo = np.zeros((nb_samples, nb_instruments), float_type) x_ir = np.zeros((nb_samples, len(self._ircurve.axis(0))), float_type) if 'plot' in kwargs and kwargs['plot']: plot_ir = True else: plot_ir = False if 'threshold' in kwargs: threshold = kwargs['threshold'] else: threshold = nb_instruments + 1 indices = np.ones((nb_samples, ), dtype=bool) for row in range(nb_samples): if row % 1000 == 0: print('Processing sample %s' % row) #Set term structure try: (x_ir[row, :], curve) = self._ircurve.rebuild(dates[row], ir_draw[row, :]) if plot_ir: du.plot_data(self._ircurve.axis(0).values, x_ir[row, :]) self._term_structure.linkTo(curve) self.model.setParams(ql.Array(y[row, :].tolist())) nb_nan_swo = 0 for swaption in range(nb_instruments): try: NPV = self.helpers[swaption].modelValue() vola = self.helpers[swaption].impliedVolatility(NPV, 1.0e-6, 1000, 0.0001, 2.50) x_swo[row, swaption] = np.clip(vola - error_draw[row, swaption], 0., np.inf) except RuntimeError as e: print('Exception (%s) for (sample, maturity, length): (%s, %s, %s)' % (e, row, self._maturities[swaption], self._lengths[swaption])) nb_nan_swo = nb_nan_swo + 1 if nb_nan_swo > threshold: print('Throwing out sample %s' % row) indices[row] = False break; except RuntimeError as e: print('Throwing out sample %s. Exception: %s' % (row, e)) if ~np.any(indices): raise RuntimeError('All samples were thrown out') if np.any(~indices): #Remove rows with too many nans x_swo = x_swo[indices, :] x_ir = x_ir[indices, :] y = y[indices, :] print('%s samples had too many nans' % np.sum(~indices)) if 'save' in kwargs and kwargs['save']: if 'append' in kwargs and kwargs['append']: try: x_swo_l = np.load(file_name + '_x_swo.npy') x_ir_l = np.load(file_name + '_x_ir.npy') y_l = np.load(file_name + '_y.npy') x_swo = np.concatenate((x_swo_l, x_swo), axis=0) x_ir = np.concatenate((x_ir_l, x_ir), axis=0) y = np.concatenate((y_l, y), axis=0) except Exception as e: print(e) np.save(file_name + '_x_swo', x_swo) np.save(file_name + '_x_ir', x_ir) np.save(file_name + '_y', y) return (x_swo, x_ir, y)
method = ql.MirrorGaussianSimulatedAnnealing(sampler, probability, temperature, ql.ReannealingTrivial(), initialTemp, finalTemp) criteria = ql.EndCriteria(maxSteps, staticSteps, 1.0e-8, 1.0e-8, 1.0e-8); return (method, criteria, constraint) def g2_method_local(): method = ql.LevenbergMarquardt() criteria = ql.EndCriteria(250, 200, 1e-7, 1e-7, 1e-7) lower = ql.Array(5, 1e-9) upper = ql.Array(5, 1.0) lower[4] = -1.0 constraint = ql.NonhomogeneousBoundaryConstraint(lower, upper) return (method, criteria, constraint) g2_lower = ql.Array(5, 1e-9) g2_upper = ql.Array(5, 1.0) g2_lower[4] = -1.0 g2_constraint = ql.NonhomogeneousBoundaryConstraint(g2_lower, g2_upper) g2 = {'name' : 'G2++', 'model' : ql.G2, 'engine' : lambda model, _: ql.G2SwaptionEngine(model, 6.0, 16), 'transformation' : g2_transformation, 'inverse_transformation' : g2_inverse_transformation, 'method': g2_method(), 'sampler': random_normal_draw, 'constraint': g2_constraint} g2_local = {'name' : 'G2++_local', 'model' : ql.G2,
caldt = CRSPData.CALDT.as_matrix() bond_rates = CRSPData.TCOUPRT.as_matrix() bond_prices = CRSPData.TDNOMPRC.as_matrix() cusips = CRSPData.TCUSIP.as_matrix() unique_dates_np = pd.to_datetime(unique_dates).as_matrix() cal_date = CRSPData.CALDT.astype('category') bond_tdatdt = CRSPData.TDATDT.as_matrix() # Stack everything into a single ndarray for speed. Stacking datetime64 together with other types doesn't work. npdata = np.stack([bond_maturities, itype, bond_rates, bond_prices, cusips], axis=1) ##### TESTING # Best so far apr_03_best_params = ql.Array([ 5.7502795124539426e-12, 4.922549407660499, 4.787747793861142, 19.42439599101258, 0.5003770453206803, 0.07538988176046008 ]) apr_05_best_params = ql.Array( [-443.158, 448.276, 160.167, 1103.64, 0.197248, 0.0527979]) jul_10_best_params = ql.Array( [0.324442, 4.21542, 6.00256, 14.3762, 1.44664, 0.186048]) jul_21_best_params = ql.Array( [2.41441, 2.39558, 3.15241, 8.46661, 1.17268, 0.172212]) # Get data bad_days = [ '1996-04-05', # Meh, whatever '1998-07-10', '1998-07-21', '1998-10-07', '1999-01-28',
def testAmericanOptionPricing(self): """Testing Black-Scholes and Heston American Option pricing""" xSteps = 100 tSteps = 25 dampingSteps = 0 todaysDate = ql.Date(15, ql.January, 2020) ql.Settings.instance().evaluationDate = todaysDate dc = ql.Actual365Fixed() riskFreeRate = ql.YieldTermStructureHandle( ql.FlatForward(todaysDate, 0.06, dc)) dividendYield = ql.YieldTermStructureHandle( ql.FlatForward(todaysDate, 0.02, dc)) strike = 110.0 payoff = ql.PlainVanillaPayoff(ql.Option.Put, strike) maturityDate = todaysDate + ql.Period(1, ql.Years) maturity = dc.yearFraction(todaysDate, maturityDate) exercise = ql.AmericanExercise(todaysDate, maturityDate) spot = ql.QuoteHandle(ql.SimpleQuote(100.0)) volatility = ql.BlackConstantVol(todaysDate, ql.TARGET(), 0.20, dc) process = ql.BlackScholesMertonProcess( spot, dividendYield, riskFreeRate, ql.BlackVolTermStructureHandle(volatility)) option = ql.VanillaOption(payoff, exercise) option.setPricingEngine( ql.FdBlackScholesVanillaEngine.make(process, xGrid=xSteps, tGrid=tSteps, dampingSteps=dampingSteps)) expected = option.NPV() equityMesher = ql.FdmBlackScholesMesher(xSteps, process, maturity, strike, cPoint=(strike, 0.1)) mesher = ql.FdmMesherComposite(equityMesher) op = ql.FdmBlackScholesOp(mesher, process, strike) innerValueCalculator = ql.FdmLogInnerValue(payoff, mesher, 0) x = [] rhs = [] layout = mesher.layout() opIter = layout.begin() while (opIter.notEqual(layout.end())): x.append(mesher.location(opIter, 0)) rhs.append(innerValueCalculator.avgInnerValue(opIter, maturity)) opIter.increment() rhs = ql.Array(rhs) bcSet = ql.FdmBoundaryConditionSet() stepCondition = ql.FdmStepConditionComposite.vanillaComposite( ql.DividendSchedule(), exercise, mesher, innerValueCalculator, todaysDate, dc) # only to test an Operator defined in python class OperatorProxy: def __init__(self, op): self.op = op def size(self): return self.op.size() def setTime(self, t1, t2): return self.op.setTime(t1, t2) def apply(self, r): return self.op.apply(r) def apply_direction(self, i, r): return self.op.apply_direction(i, r) def solve_splitting(self, i, r, s): return self.op.solve_splitting(i, r, s) proxyOp = ql.FdmLinearOpCompositeProxy(OperatorProxy(op)) solver = ql.FdmBackwardSolver(proxyOp, bcSet, stepCondition, ql.FdmSchemeDesc.Douglas()) solver.rollback(rhs, maturity, 0.0, tSteps, dampingSteps) spline = ql.CubicNaturalSpline(x, rhs) logS = math.log(spot.value()) calculated = spline(logS) self.assertAlmostEqual(calculated, expected, 1) solverDesc = ql.FdmSolverDesc(mesher, bcSet, stepCondition, innerValueCalculator, maturity, tSteps, dampingSteps) calculated = ql.Fdm1DimSolver(solverDesc, ql.FdmSchemeDesc.Douglas(), op).interpolateAt(logS) self.assertAlmostEqual(calculated, expected, 2) v0 = 0.4 * 0.4 kappa = 1.0 theta = v0 sigma = 1e-4 rho = 0.0 hestonProcess = ql.HestonProcess(riskFreeRate, dividendYield, spot, v0, kappa, theta, sigma, rho) leverageFct = ql.LocalVolSurface( ql.BlackVolTermStructureHandle( ql.BlackConstantVol(todaysDate, ql.TARGET(), 0.50, dc)), riskFreeRate, dividendYield, spot.value()) vSteps = 3 vMesher = ql.FdmHestonLocalVolatilityVarianceMesher( vSteps, hestonProcess, leverageFct, maturity) avgVolaEstimate = vMesher.volaEstimate() self.assertAlmostEqual(avgVolaEstimate, 0.2, 5) mesher = ql.FdmMesherComposite(equityMesher, vMesher) innerValueCalculator = ql.FdmLogInnerValue(payoff, mesher, 0) stepCondition = ql.FdmStepConditionComposite.vanillaComposite( ql.DividendSchedule(), exercise, mesher, innerValueCalculator, todaysDate, dc) solverDesc = ql.FdmSolverDesc(mesher, bcSet, stepCondition, innerValueCalculator, maturity, tSteps, dampingSteps) calculated = ql.FdmHestonSolver(hestonProcess, solverDesc, leverageFct=leverageFct).valueAt( spot.value(), 0.16) self.assertAlmostEqual(calculated, expected, 1)
def testFdmLinearOpComposite(self): """Testing linear operator composites""" class Foo: t1 = 0.0 t2 = 0.0 @classmethod def size(self): return 42 def setTime(self, t1, t2): self.t1 = t1 self.t2 = t2 @classmethod def apply(self, r): return 2 * r @classmethod def apply_mixed(self, r): return 3 * r @classmethod def apply_direction(self, direction, r): return direction * r @classmethod def solve_splitting(self, direction, r, s): return direction * s * r @classmethod def preconditioner(self, r, s): return s * r foo = Foo() c = ql.FdmLinearOpCompositeProxy(foo) self.assertEqual(c.size(), foo.size()) c.setTime(1.0, 2.0) self.assertAlmostEqual(foo.t1, 1.0, 14) self.assertAlmostEqual(foo.t2, 2.0, 14) r = ql.Array([1, 2, 3, 4]) self.assertEqual(list(c.apply(r)), list(2 * r)) self.assertEqual(list(c.apply_mixed(r)), list(3 * r)) self.assertEqual(list(c.apply_direction(7, r)), list(7 * r)) s = list(c.solve_splitting(7, r, 0.5)) self.assertEqual(len(s), len(r)) for i, x in enumerate(s): self.assertAlmostEqual(x, 3.5 * r[i], 14) self.assertEqual(list(c.preconditioner(r, 4)), list(4 * r)) class Bar: @classmethod def apply(self, r): return 1 def apply_mixed(self, r): pass with self.assertRaises(RuntimeError): ql.FdmLinearOpCompositeProxy(Bar()).apply(r) with self.assertRaises(RuntimeError): ql.FdmLinearOpCompositeProxy(Bar()).apply_mixed(r)
def compare_history(self, predictive_model, dates=None, plot_results=False): df = du.from_hdf5(self.key_model, du.h5file) self.refdate = ql.Date(1, 1, 1901) vals = np.zeros((len(df.index),4)) values = np.zeros((len(df.index),13)) if dates is None: dates = self._dates method = ql.LevenbergMarquardt() end_criteria = ql.EndCriteria(250, 200, 1e-7, 1e-7, 1e-7) if 'constraint' in self._model_dict: constraint = self._model_dict['constraint'] else: constraint = ql.NoConstraint() for i, date in enumerate(dates): self.set_date(date) params = predictive_model.predict((self.values, self._ircurve.values)) self.model.setParams(ql.Array(params.tolist()[0])) meanErrorPrior, _ = self.__errors() try: objectivePrior = self.model.value(self.model.params(), self.helpers) except RuntimeError: objectivePrior = np.nan self.model.calibrate(self.helpers, method, end_criteria, constraint) meanErrorAfter, _ = self.__errors() paramsC = self.model.params() try: objectiveAfter = self.model.value(self.model.params(), self.helpers) except RuntimeError: objectiveAfter = np.nan orig_mean_error = df.ix[date, 'OrigMeanError'] hist_mean_error = df.ix[date, 'HistMeanError'] orig_objective = df.ix[date, 'OrigObjective'] hist_objective = df.ix[date, 'HistObjective'] values[i, 0] = orig_mean_error values[i, 1] = hist_mean_error values[i, 2] = meanErrorPrior values[i, 3] = orig_objective values[i, 4] = hist_objective values[i, 5] = objectivePrior values[i, 6] = meanErrorAfter values[i, 7] = objectiveAfter if orig_objective < hist_objective: values[i, 8] = df.ix[date, 'OrigParam0'] values[i, 9] = df.ix[date, 'OrigParam1'] values[i, 10] = df.ix[date, 'OrigParam2'] values[i, 11] = df.ix[date, 'OrigParam3'] values[i, 12] = df.ix[date, 'OrigParam4'] else: values[i, 8] = df.ix[date, 'HistParam0'] values[i, 9] = df.ix[date, 'HistParam1'] values[i, 10] = df.ix[date, 'HistParam2'] values[i, 11] = df.ix[date, 'HistParam3'] values[i, 12] = df.ix[date, 'HistParam4'] print('Date=%s' % date) print('Vola: Orig=%s Hist=%s ModelPrior=%s ModelAfter=%s' % (orig_mean_error, hist_mean_error, meanErrorPrior, meanErrorAfter)) print('NPV: Orig=%s Hist=%s Model=%s ModelAfter=%s' % (orig_objective, hist_objective, objectivePrior, objectiveAfter)) print('Param0: Cal:%s , Model:%s, Cal-Mod:%s' % (values[i, 8], params[0][0], paramsC[0])) print('Param1: Cal:%s , Model:%s, Cal-Mod:%s' % (values[i, 9], params[0][1], paramsC[1])) print('Param2: Cal:%s , Model:%s, Cal-Mod:%s' % (values[i, 10], params[0][2], paramsC[2])) print('Param3: Cal:%s , Model:%s, Cal-Mod:%s' % (values[i, 11], params[0][3], paramsC[3])) print('Param4: Cal:%s , Model:%s, Cal-Mod:%s' % (values[i, 12], params[0][4], paramsC[4])) vals[i, 0] = (meanErrorPrior - orig_mean_error)/orig_mean_error*100.0 vals[i, 1] = (meanErrorPrior - hist_mean_error)/hist_mean_error*100.0 vals[i, 2] = (meanErrorAfter - orig_mean_error)/orig_mean_error*100.0 vals[i, 3] = (meanErrorAfter - hist_mean_error)/hist_mean_error*100.0 print(' impO=%s impH=%s impAfterO=%s impAfterH=%s' % (vals[i, 0], vals[i, 1], vals[i,2], vals[i, 3])) if plot_results: r = range(vals.shape[0]) fig = plt.figure(figsize=(16, 16)) f1 = fig.add_subplot(211) f1.plot(r, vals[:, 0]) f2 = fig.add_subplot(212) f2.plot(r, vals[:, 1]) return (dates, values)
def CostFunction(x): parameters = ql.Array(list(x)) model.setParams(parameters) error = [helper.calibrationError() for helper in helpers] return np.sqrt(np.sum(np.abs(error)))