コード例 #1
0
def correlated_defaults_scatter(lambda_1, lambda_2, rhos, size):

    tau_2 = [0] * len(rhos)

    sns = np.random.standard_normal(2 * size)

    x = [sns[k] for k in range(size)]
    tau_1 = [
        dist.exponential_inverse_cdf(lambda_1, dist.standard_normal_cdf(x1))
        for x1 in x
    ]

    index = 0
    for rho in rhos:
        y = [
            rho * sns[k] + np.sqrt(1 - rho * rho) * sns[k + size]
            for k in range(size)
        ]
        tau_2[index] = [
            dist.exponential_inverse_cdf(lambda_2,
                                         dist.standard_normal_cdf(y1))
            for y1 in y
        ]
        index = index + 1

    ### scatter plot of the simulated defaults
    colors = ['blue', 'green', 'orange', 'red', 'yellow']

    mp = pu.PlotUtilities('Default Times with Correlations={0}'.format(rhos),
                          'x', 'y')

    mp.scatterPlot(tau_1, tau_2, rhos, colors)
コード例 #2
0
def plot_bachelier_digital_option(_time, _timestep, _strike):

    #######
    ## call helper function to generate sufficient symmetric binomials
    #######

    size = int(_time / _timestep)

    sample = np.random.normal(0, np.sqrt(_timestep), size)

    path_bm = [sum(sample[0:n]) for n in range(size)]

    x = [_timestep * k for k in range(size)]
    remaining_time = [np.sqrt(_time - x_i) for x_i in x]

    ## theoretical option value over time on a single path
    path_digital_option = [
        1 - dist.standard_normal_cdf((_strike - bm) / rt)
        for (bm, rt) in zip(path_bm, remaining_time)
    ]

    hedge_proportion = [0] * (size)
    path_digital_option_hedge = [0] * (size)

    ####
    ## plot the trajectory of the process
    ####
    _t_remain = remaining_time[0]
    path_digital_option_hedge[0] = path_digital_option[0]
    hedge_proportion[0] = dist.standard_normal_pdf(
        (_strike - path_bm[0]) / _t_remain) / _t_remain

    for j in range(1, size):
        _t_remain = remaining_time[j]
        hedge_proportion[j] = dist.standard_normal_pdf(
            (_strike - path_bm[j - 1]) / _t_remain) / _t_remain
        path_digital_option_hedge[j] = path_digital_option_hedge[
            j - 1] + sample[j] * hedge_proportion[j]

    mp = pu.PlotUtilities("Paths of Digital Option Value", 'Time',
                          "Option Value")

    trackHedgeOnly = True
    if (trackHedgeOnly):
        mp.multiPlot(x, [path_digital_option, path_digital_option_hedge])
    else:
        arg = [
            'Option Value', 'Hedge Proportion', 'Underlying Brownian Motion'
        ]
        colors = ['green', 'red', 'blue']
        mp = pu.PlotUtilities("Paths of Digital Option Value", 'Time',
                              "Option Value")
        mp.subPlots(x, [path_digital_option, hedge_proportion, path_bm], arg,
                    colors)
コード例 #3
0
def plot_maximising_goal_probability(_time, _timestep, _initial_capital,
                                     _target, _b, _r, _sigma):

    #######
    ## call helper function to generate sufficient symmetric binomials
    #######

    size = int(_time / _timestep) - 1

    sample = np.random.normal(0, np.sqrt(_timestep), size)

    path_underlying = [1.] * (size)
    path_wealth = [_initial_capital] * (size)
    path_portfolio = [0] * (size)

    x = [_timestep * k for k in range(size)]

    _theta = (_b - _r) / _sigma

    _y0 = np.sqrt(_time) * dist.standard_normal_inverse_cdf(
        _initial_capital * np.exp(_r * _time) / _target)

    ####
    ## create the various paths for plotting
    ####

    bm = 0
    _y = path_wealth[0] * np.exp(_r * _time) / _target
    path_portfolio[0] = dist.standard_normal_pdf(
        dist.standard_normal_inverse_cdf(_y)) / (_y * _sigma * np.sqrt(_time))
    for j in range(1, size):
        _t_remain = _time - x[j]
        _t_sq_remain = np.sqrt(_t_remain)
        path_underlying[j] = path_underlying[j - 1] * (1. + _b * _timestep +
                                                       _sigma * sample[j])
        bm = bm + sample[j] + _theta * _timestep
        path_wealth[j] = _target * np.exp( - _r * _t_remain ) * \
                                dist.standard_normal_cdf((bm + _y0) / _t_sq_remain)

        _y = path_wealth[j] * np.exp(_r * _t_remain) / _target
        path_portfolio[j] = dist.standard_normal_pdf(
            dist.standard_normal_inverse_cdf(_y)) / (_y * _sigma *
                                                     _t_sq_remain)

    mp = pu.PlotUtilities("Maximising Probability of Reaching a Goal", 'Time',
                          "None")

    labels = ['Stock Price', 'Wealth Process', 'Portfolio Value']
    mp.subPlots(x, [path_underlying, path_wealth, path_portfolio], labels,
                ['red', 'blue', 'green'])
コード例 #4
0
def variance_normal_digital(strike):

    x_label = 'shift'
    y_label = 'Variance'
    chart_title = 'Sample Variance Under Exponential Tilting (Normal)'
    min_val = strike - 2.
    max_val = strike + 2.
    steps = 1000
    step = (max_val - min_val) / steps
    x_ax = [min_val + step * k for k in range(steps)]
    y_ax = [
        np.exp(x * x) * dist.standard_normal_cdf(-strike - x) for x in x_ax
    ]

    mp = pu.PlotUtilities(chart_title, x_label, y_label)
    mp.multiPlot(x_ax, [y_ax])
コード例 #5
0
def excess_probability_payoff(_strike, _mean, _variance):
    return 1 - dist.standard_normal_cdf((_strike - _mean) / np.sqrt(_variance))
コード例 #6
0
def expected_positive_exposure(_mean, _variance):
    y = _mean / np.sqrt(_variance)
    return _mean * dist.standard_normal_cdf(y) + np.sqrt(_variance) * dist.standard_normal_pdf(y)
コード例 #7
0
def malliavin_greeks(start, vol, strike, digitalPayout = False):

    ## we calculate the option value of a call option $(X-K)^+$ where the underlying is of the form $X = x_0 + sigma W$ with $W$ standard normal
    ## the aim is to calculate the sensitivities of the option price with respect to the x_0 both in bump and reval and with logarithmic Malliavin weights

    nd = dist.NormalDistribution(start, vol * vol)
    y = (start - strike) / vol
    if (digitalPayout):
        theo_option_price = nd.cdf(y)
        act_delta = dist.standard_normal_pdf(y) / vol
        act_gamma = - y * dist.standard_normal_pdf(y) / vol / vol
    else:
        theo_option_price = nd.call_option(strike)
        act_delta = dist.standard_normal_cdf(y)
        act_gamma = dist.standard_normal_pdf(y) / vol

    perturbation = 1.e-08

    # print (str("Theoretical Price: ") + str(theo_option_price))
    # print (str("Theoretical Delta: ") + str(act_delta))
    # print (str("Theoretical Gamma: ") + str(act_gamma))

    repeats = 500

    sample_delta = [0.] * 2
    sample_delta[0] = [0] * repeats  # this is the sample for the delta with B&R approach
    sample_delta[1] = [0] * repeats  # this is the sample for the delta with Malliavin logarithmic trick

    sample_gamma = [0.] * 2
    sample_gamma[0] = [0] * repeats # this is the sample for the gamma with B&R approach
    sample_gamma[1] = [0] * repeats # this is the sample for the gamma with Malliavin logarithmic

    sz = 5000
    total_sz = sz * repeats

    normal_sample = np.random.normal(0, 1, total_sz)

    for z in range(repeats):

        thisNormalSample = normal_sample[z * sz : (z+1) * sz]

        if (digitalPayout):
            option_value = sum([(0 if start + vol * ns < strike else 1.) for ns in thisNormalSample])

            malliavin_delta = sum([(0 if start + vol * ns < strike else 1.) * ns / vol for ns in thisNormalSample])
            malliavin_gamma = sum([(0 if start + vol * ns < strike else 1.) * (ns * ns - 1) / (vol * vol) for ns in thisNormalSample])

            option_value_pert = sum([(0 if start + perturbation + vol * ns < strike else 1.) for ns in thisNormalSample])
            option_value_pert_down = sum([(0 if start - perturbation + vol * ns < strike else 1.) for ns in thisNormalSample])
        else:
            option_value = sum([max(start + vol * ns - strike, 0.) for ns in thisNormalSample])

            malliavin_delta = sum([max(start + vol * ns - strike, 0.) * (ns) / (vol) for ns in thisNormalSample])
            malliavin_gamma = sum([max(start + vol * ns - strike, 0.) * (ns * ns - 1) / (vol * vol) for ns in thisNormalSample])

            option_value_pert = sum([max(start + perturbation + vol * ns - strike, 0.) for ns in thisNormalSample])
            option_value_pert_down = sum([max(start - perturbation + vol * ns - strike, 0.) for ns in thisNormalSample])


        sample_delta[0][z] = (option_value_pert - option_value) / sz / perturbation
        sample_delta[1][z] = malliavin_delta / sz
        sample_gamma[0][z] = (
                             option_value_pert - 2 * option_value + option_value_pert_down) / sz / perturbation / perturbation

        sample_gamma[1][z] = malliavin_gamma / sz

    #######
    ### prepare and show plot
    ###
    num_bins = 25

    print (np.var(sample_delta[0]))
    print (np.var(sample_delta[1]))


    plotGamma = False

    totalPlots = (2 if plotGamma else 1)

    ### Subplot for Delta Calculation
    plt.subplot(totalPlots, 1, 1)

    plt.xlabel('Outcome')
    plt.ylabel('Rel. Occurrence')
    plt.title("B + R vs Malliavin Delta (Value={0})".format(act_delta))

    n, bins, _hist = plt.hist(sample_delta[0], num_bins, normed=True, facecolor='orange', alpha=0.5)
    n, bins, _hist = plt.hist(sample_delta[1], num_bins, normed=True, facecolor='blue', alpha=0.75)

    ### Subplot for Gamma Calculation
    if (plotGamma):
        plt.subplot(totalPlots, 1, 2)

        plt.xlabel('Outcome')
        plt.ylabel('Rel. Occurrence')
        plt.title("B + R vs Malliavin Gamma (Value={0})".format(act_gamma))

        n, bins, _hist = plt.hist(sample_gamma[0], num_bins, normed=True, facecolor='orange', alpha=0.55)
        n, bins, _hist = plt.hist(sample_gamma[1], num_bins, normed=True, facecolor='blue', alpha=0.75)

    plt.show()