예제 #1
0
    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)
예제 #2
0
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)
예제 #3
0
 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()
예제 #4
0
    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)
예제 #5
0
    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)
예제 #6
0
 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
예제 #7
0
 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)
예제 #8
0
    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)
예제 #9
0
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)
예제 #10
0
    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)
예제 #11
0
 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
예제 #12
0
    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)
예제 #13
0
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)
예제 #14
0
    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])
예제 #15
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)
예제 #16
0
    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)
예제 #17
0
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
예제 #18
0
    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)
예제 #19
0
    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',
예제 #21
0
    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)
예제 #22
0
    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)
예제 #23
0
    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)
예제 #24
0
 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)))