Beispiel #1
0
def normal_histogram(mu, var, sz):

    nd = dist.NormalDistribution(mu, var)
    #######
    ### transform the uniform sample
    #######
    sample = [nd.inverse_cdf(u) for u in getUniformSample(sz)]
    num_bins = 60

    hp = pu.PlotUtilities(
        "Histogram of Normal Sample with Mean={0}, Variance={1}".format(
            mu, var), 'Outcome', 'Rel. Occurrence')
    hp.plotHistogram(sample, num_bins)
def plot_bachelier_option_price(start, vol):

    lower_bound = start - 10.
    upper_bound = start + 10.
    step = 0.01
    n_steps = int((upper_bound - lower_bound) / step)

    nd = dist.NormalDistribution(0., 1.)

    knock_out = 5

    x_ax = [lower_bound + k * step for k in range(n_steps)]
    y_ax = [ vol * nd.pdf( (max(x,knock_out) - start) / vol ) - (x - start) * nd.cdf( (start - max(x, knock_out)) / vol ) for x in x_ax]  # poisson distribution

    mp = pu.PlotUtilities("Bachelier Option Value as Function of Strike", "Option Strike", "Option Value")
    mp.multiPlot(x_ax, [y_ax], '-')
Beispiel #3
0
def lognormal_histogram(mu, var, sz):

    uniform_sample = getUniformSample(sz)

    nd = dist.NormalDistribution(0, var)
    #######
    ### transform the uniform sample
    #######
    ###
    strike = 70.
    sample = [''] * 2
    sample[0] = [
        mu * np.exp(nd.inverse_cdf(u) - 0.5 * var) for u in uniform_sample
    ]
    sample[1] = [max(s - strike, 0.) for s in sample[0]]
    num_bins = 75

    hp = pu.PlotUtilities(
        "Histogram of Lognormal Sample with Mean={0}, Variance={1}".format(
            mu, var), 'Outcome', 'Rel. Occurrence')
    hp.plotHistogram([sample[0]], num_bins)
def moment_matching(p, sz_basket):

    #####
    ## create a basket with random weights of size sz_basket
    #####

    lower_bound = 0.
    upper_bound = 1.

    weights = np.random.uniform(lower_bound, upper_bound, sz_basket)

    ## calculate mean and variance of the basket

    expectation = 0
    variance = 0

    for k in range(sz_basket):
        expectation = expectation + weights[k]
        variance = variance + weights[k] * weights[k]

    expectation = expectation * dist.symmetric_binomial_expectation(p)
    variance = variance * dist.symmetric_binomial_variance(p)

    simulation = 50000

    outcome = [0] * simulation

    for k in range(simulation):

        uni_sample = np.random.uniform(lower_bound, upper_bound, sz_basket)

        #######
        ### transform the uniform sample
        #######
        sample = range(sz_basket)
        for j in range(sz_basket):
            sample[j] = dist.symmetric_binomial_inverse_cdf(p, uni_sample[j])

        for m in range(sz_basket):
            outcome[k] = outcome[k] + weights[m] * sample[m]

    num_bins = 50


    plt.subplot(2,1,1)

    plt.title("Moment Matching of Binomial Basket of Size={0}".format(sz_basket))

    # the histogram of the data
    n, bins, _hist = plt.hist(outcome, num_bins, normed=True, facecolor='blue', alpha=0.75)

    pdf_approx = [0.] * (num_bins+1)
    call_option_sampled = [0.] * (num_bins+1)
    call_option_approx = [0.] * (num_bins+1)

    nd = dist.NormalDistribution(expectation, variance)

    ###### overlay the moment matched pdf
    for i in range(0,num_bins+1):
        pdf_approx[i] = nd.pdf(bins[i])
        call_option_approx[i] = nd.call_option(bins[i])
        call_option_sampled[i] = 0.
        for k in range(simulation):
            if (outcome[k] >= bins[i]):
                call_option_sampled[i] = call_option_sampled[i] + (outcome[k] - bins[i]) / float(simulation)

    plt.xlabel('Outcome')
    plt.ylabel('Rel. Occurrence')

    plt.plot(bins, pdf_approx, 'r*')

    plt.subplot(2,1,2)

    plt.xlabel('Call Option Strike')
    plt.ylabel('Call Option Price')

    plt.plot(bins, call_option_sampled, 'b-')
    plt.plot(bins, call_option_approx, 'r*')

    plt.show()
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()
def conditional_default_prob(rho, p, z):

    nd = dist.NormalDistribution(0., 1.)
    y = (nd.inverse_cdf(p) - np.sqrt(rho) * z) / np.sqrt(1 - rho)
    return nd.cdf(y)
        mp = pu.PlotUtilities('Probability Density Functions', 'x', 'PDF Value')
        mp.multiPlot(x_ax, y_ax)

if __name__ == '__main__':

    m = 5
    d = [0.] * m

    version = 1

    if (version == 1):
        ### example of normal distributions with different $\sigma$ and $\mu = 0$.
        min_val = -5.
        max_val = 5.
        for k in range(m):
            d[k] = dist.NormalDistribution(0., 1. * (1. + float(k)) )
    if (version == 2):
        min_val = -5.
        max_val = 5.
        ### example of normal distributions with different $\mu$ and $\sigma = 1$.
        for k in range(m):
            d[k] = dist.NormalDistribution(-2. + float(k), 1.)
    if (version == 3):
        ## example of Exponential distributions
        min_val = 0.
        max_val = 4.
        for k in range(m):
            d[k] = dist.ExponentialDistribution(0.5 * (1. + float(k)))

    plotMultiDistributions(d, min_val, max_val, 100)
def vasicek_large_portfolio_cdf(rho, p, x):

    nd = dist.NormalDistribution(0., 1.)
    y = (nd.inverse_cdf(x) * np.sqrt(1 - rho) -
         nd.inverse_cdf(p)) / np.sqrt(rho)
    return nd.cdf(y)
Beispiel #9
0
 def u(self, _t, _x):
     nd = dist.NormalDistribution(_x, _t)
     return nd.excess_probability(self._strike)
Beispiel #10
0
 def u(self, _t, _x):
     mean = (self.a - 0.5 * self.b * self.b) * _t
     variance = self.b * self.b * _t
     nd = dist.NormalDistribution(mean, variance)
     strk = np.log(self.strike / _x)
     return 1 - nd.cdf(strk)
Beispiel #11
0
 def u(self, _t, _x):
     nd = dist.NormalDistribution(_x, _t)
     return nd.second_moment()
Beispiel #12
0
 def u(self, _t, _x):
     nd = dist.NormalDistribution(_x, _t)
     return nd.expected_positive_exposure()
Beispiel #13
0
 def u(self, _t, _x):
     nd = dist.NormalDistribution(_x, _t)
     return nd.pdf(self._start)
def moment_matching(p, sz_basket):

    #####
    ## create a basket with random weights of size sz_basket
    #####

    lower_bound = 0.
    upper_bound = 1.

    weights = np.random.uniform(lower_bound, upper_bound, sz_basket)

    ## calculate mean and variance of the basket

    expectation = sum(weights) * dist.symmetric_binomial_expectation(p)
    variance = sum([w * w
                    for w in weights]) * dist.symmetric_binomial_variance(p)

    simulation = 50000

    outcome = [0] * simulation

    for k in range(simulation):

        #######
        ### sample the basket constituents and determine the outcome for each trial
        #######
        uni_sample = np.random.uniform(lower_bound, upper_bound, sz_basket)
        sample = [
            dist.symmetric_binomial_inverse_cdf(p, u) for u in uni_sample
        ]
        outcome[k] = sum([w * s for w, s in zip(weights, sample)])

    num_bins = 50

    plt.subplot(2, 1, 1)

    plt.title(
        "Moment Matching of Binomial Basket of Size={0}".format(sz_basket))

    # the histogram of the data
    n, bins, _hist = plt.hist(outcome,
                              num_bins,
                              normed=True,
                              facecolor='blue',
                              alpha=0.75)

    nd = dist.NormalDistribution(expectation, variance)

    mc_weight = 1. / float(simulation)
    pdf_approx = [nd.pdf(b) for b in bins]
    call_option_approx = [nd.call_option(b) for b in bins]
    call_option_sampled = [
        mc_weight * sum([max(oc - b, 0.) for oc in outcome]) for b in bins
    ]

    plt.xlabel('Outcome')
    plt.ylabel('Rel. Occurrence')

    plt.plot(bins, pdf_approx, 'r*')

    plt.subplot(2, 1, 2)

    plt.xlabel('Call Option Strike')
    plt.ylabel('Call Option Price')

    plt.plot(bins, call_option_sampled, 'b-')
    plt.plot(bins, call_option_approx, 'r*')

    plt.show()
if __name__ == '__main__':

    n_plots = 5

    versions = [k for k in range(1, 5)]

    plotCDF = True

    for version in versions:
        title = ''
        if (version == 1):
            ### example of normal distributions with different $\sigma$ and $\mu = 0$.
            min_val = -5.
            max_val = 5.
            title = 'Normal Distribution with fixed $\mu$'
            d = [dist.NormalDistribution(0., 1. * (1. + float(k))) for k in range(n_plots)]
        elif (version == 2):
            ### example of normal distributions with different $\mu$ and $\sigma = 1$.
            min_val = -5.
            max_val = 5.
            title = 'Normal Distribution with fixed $\sigma$'
            d = [dist.NormalDistribution(-2. + float(k), 1.) for k in range(n_plots)]
        elif (version == 3):
            ## example of Exponential distributions
            min_val = 0.
            max_val = 10.
            title = 'Exponential Distribution'
            d = [dist.ExponentialDistribution(0.5 * (1. + float(k))) for k in range(n_plots)]
        elif (version == 4):
            min_val = -1.
            max_val = n_plots + 1