Option Pricing Techniques¶

As with other option pricing techniques Monte Carlo methods are used to price options using what is essentially a three step process.

  • Step 1: Simulate potential price paths of the underlying asset.
  • Step 2: Calculate the option payoff for each of these price paths.
  • Step 3: Average the payoff and discount back to today to determine the option price.

Applying Euler discretization of SDE, we get

$$ S_{t+\delta t} = S_t * \left(1+r\delta t + \sigma \sqrt{\delta t} w_t \right) $$

In [ ]:
# Import Required Libraries
import pandas as pd
from numpy import *
import scipy.stats as ss

# Set max row to 300
pd.set_option('display.max_rows', 300)


# Libraries for plotting
import matplotlib.pyplot as plt
import cufflinks as cf
cf.set_config_file(offline=True)


# Ignore warnings
import warnings
warnings.filterwarnings('ignore')

# line color and style for plots
dash_styles = ['solid', 'dash']*5
color_styles = sorted(['black', 'brightblue', 'brightred',  'green', 'darkviolet'] * 2)
In [ ]:
# define simulation function
def simulate_path(s0, mu, sigma, horizon, timesteps, n_sims):
    
    # set the seed
    random.seed(2023)
    
    # read the params
    S0 = s0
    r = mu

    T = horizon
    t = timesteps
    n = n_sims
    # define dt
    dt = T/t
    
    # Simulating 'n' asset price paths with 't' timesteps
    S = zeros((t+1, n))
    S[0] = S0
    
    for i in range(1, t+1):
        z = random.standard_normal(n)     # psuedo random numbers
        
        S[i]=S[i-1]+r*S[i-1]*dt+sigma * sqrt(dt)*S[i-1]*z #  Euler-Maruyama scheme
        
    return S
In [ ]:
# Assign simulated price path to dataframe for analysis and plotting
price_path = pd.DataFrame(simulate_path(100,0.05,0.2,1,252,100000))

# Verify the generated price paths
price_path.head()
Out[ ]:
0 1 2 3 4 5 6 7 8 9 ... 99990 99991 99992 99993 99994 99995 99996 99997 99998 99999
0 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 ... 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000
1 100.916466 99.611029 98.757603 100.317489 99.891132 98.581948 103.364080 101.834833 100.144446 96.087080 ... 100.526533 98.860239 98.837148 100.039456 98.913105 99.580159 99.246204 99.383916 98.362717 100.002582
2 101.102047 99.252871 98.060186 100.326270 98.603518 100.717457 104.176433 100.222994 101.468809 95.026936 ... 101.555214 97.144692 99.130006 100.251700 97.617909 99.474348 98.328044 100.179019 98.775283 99.668132
3 100.572272 100.383399 98.151705 100.305081 100.957863 101.003838 105.040394 96.817626 100.584172 93.812262 ... 100.687368 95.671818 98.864215 100.339384 98.261258 101.356891 97.348343 100.076692 98.885967 98.173543
4 100.103597 100.482743 99.225147 100.341161 100.908313 100.437038 104.973611 96.873934 99.199344 92.857468 ... 103.588192 96.954031 100.491272 99.724911 98.236881 100.712394 97.737062 99.770981 97.046760 97.968690

5 rows × 100000 columns

In [ ]:
# Plot the histogram of the simulated price path at maturity
price_path.iloc[-1].hist(bins=100)
plt.ylabel('frequency')
plt.xlabel('Asset price at maturity')
plt.title('Histogram of the simulated price path at maturity')
plt.xlim(0, 400)
plt.show()
No description has been provided for this image
In [ ]:
# Plot simulated price paths,1-20th
price_path.iloc[:,:20].iplot(title='Simulated Underlying Asset Price Paths', xTitle='Time Steps', yTitle='Price')

A call option gives the holder of the option the right to buy the asset at a pre-defined price. A call buyer makes money if the price of the asset at maturity, denoted by ST , is above the strike price K, otherwise it’s worth nothing.

$ C_T = max(0,S_T −K) $

The price of an option using a Monte Carlo simulation is the expected value of its future payoff. So at any date before maturity, denoted by t, the option’s value is the present value of the expectation of its payoff at maturity, T.

$ C = PV (E[max(0,S_T −K)]) $

Under the risk-neutral framework, we assume the asset is going to earn, on average, the risk-free interest rate. Hence, the option value at time t would simply be the discounted value of the expected payoff.

$ C = e^{-r(T-t)} * (E[max(0, S_T - K)]) $

Asian and Look back options are path-dependent options. The discounted value of the expected pay off will be

$C = e^{-r(T-t)}(E[max(0,S_{\text{Avg}} −K)])$ for Asian options

$C = e^{-r(T-t)}(E[max(0,S_{\text{max}} −K)])$ for Lookback options or

$C = e^{-r(T-t)}(E[max(0,S_{\text{min}} −K)])$ for Lookback options

I will be using $max$ for pricing Lookback options here.

In [ ]:
def caculate_exotic_price(S_path,sampling_period,E,r,horizon):  
    
    S=S_path   #simulated price path data
    sp=sampling_period  #sampling_period refers the days  sampling once

    T=horizon
    final_price=S.iloc[-1] #final price at maturity
    path_mean=S.iloc[sp::sp].mean(axis=0)  #  MEAN related to sample period
    path_max=S.iloc[sp::sp].max(axis=0)    # MAX related to sample period
    path_min=S.iloc[sp::sp].min(axis=0)   #  MIN related to sample period

    # Calculate the discounted value of the expeced payoff
    #vanilla
    C0 = exp(-r*T) * mean(maximum(final_price - E, 0))
    P0 = exp(-r*T) * mean(maximum(E - final_price, 0))
    
    #fixed Asian
    fix_Asian_C = exp(-r*T) * mean(maximum(path_mean - E, 0))
    fix_Asian_P = exp(-r*T) * mean(maximum(E - path_mean, 0))
    
    # floating Asisn
    float_Asian_C = exp(-r*T) * mean(maximum(path_mean - final_price, 0))
    float_Asian_P = exp(-r*T) * mean(maximum(final_price - path_mean, 0))
    
    # fixed look
    fix_Lookback_C = exp(-r*T) * mean(maximum(path_max - E, 0))
    fix_Lookback_P = exp(-r*T) * mean(maximum(E - path_min, 0))

    # floating Lookback
    float_Lookback_C = exp(-r*T) * mean(maximum(path_max - final_price, 0))
    float_Lookback_P = exp(-r*T) * mean(maximum(final_price - path_min, 0))
    
    # the calculated results are returned as a list
    return [C0,P0, \
            fix_Asian_C,fix_Asian_P, \
            float_Asian_C,float_Asian_P,\
            fix_Lookback_C,fix_Lookback_P,\
            float_Lookback_C,float_Lookback_P]
In [ ]:
# Assign simulated price path to dataframe for analysis and plotting
price_path = pd.DataFrame(simulate_path(100, 0.05, 0.20, 1, 252, 100000)) # timesteps=252 meaning simulating by days
# Verify the generated price paths
price_path.tail()
Out[ ]:
0 1 2 3 4 5 6 7 8 9 ... 99990 99991 99992 99993 99994 99995 99996 99997 99998 99999
248 83.625902 75.827722 96.600573 103.596788 106.015185 147.020837 108.247054 86.245161 146.001810 98.963360 ... 104.219166 96.538980 104.257557 129.044406 83.385164 164.666929 83.411607 89.556030 61.695214 137.059986
249 82.015420 76.972786 96.294851 103.555391 106.868361 150.234926 107.513052 85.295482 148.012494 99.377709 ... 105.629601 96.199775 102.848104 128.312085 84.227749 164.295674 84.452631 89.853093 61.860018 138.444789
250 80.642913 76.783025 95.154389 105.616379 107.497258 149.945284 107.222721 86.734576 148.618368 98.820653 ... 107.406821 94.912560 102.935111 125.641846 83.604510 163.470033 83.007683 91.172556 61.333441 136.355664
251 80.782976 76.713537 94.691231 103.588088 108.632172 151.506379 107.393998 85.837756 147.199309 100.592983 ... 107.665608 96.874877 102.839756 122.933012 83.634889 163.939416 81.774788 91.142776 62.203926 137.327203
252 79.896474 76.152872 96.269968 102.360518 106.431434 153.371441 107.719045 86.611925 147.370448 98.748978 ... 107.623348 97.718515 102.937203 123.649104 85.340604 166.349697 80.660933 91.513198 63.571316 137.789066

5 rows × 100000 columns

In [ ]:
variable_range=[1,5,21,63,126,252] #Sampling by 1 Day,1 Week,1 Month,1 quarter,semi-year,1 year


option_prices=[]# set a list to save data
for d in variable_range:
    result_list=caculate_exotic_price(price_path,d,100,0.05,1) # for different sampling periods caculate extotic price
    option_prices.append(result_list)# put caculate reslut into the list
    

df=pd.DataFrame(option_prices)# to dataframe
df.columns=["European Call", "European Put", \
            "Fixed Asian Call", "Fixed Asian put",\
            "Floating Asian Call","Floating Asian Put",\
            "Fixed Lookback Call","Fixed Lookback Put",\
            "Floating Lookback Call","Floating Lookback Put"]
df.index=variable_range
df.index.name="Sampling Period"

##################################### visualize ####################################################
df.iplot(title='Option price with change in sampling time', xTitle='Sampling Period in days', yTitle='Price',colors=color_styles, width=3, dash=dash_styles)


round(df, 2)# keep 4 decimals
Out[ ]:
European Call European Put Fixed Asian Call Fixed Asian put Floating Asian Call Floating Asian Put Fixed Lookback Call Fixed Lookback Put Floating Lookback Call Floating Lookback Put
Sampling Period
1 10.5 5.58 5.82 3.38 3.38 5.85 18.39 11.76 13.45 16.63
5 10.5 5.58 5.86 3.40 3.37 5.82 17.34 11.01 12.42 15.79
21 10.5 5.58 6.19 3.56 3.20 5.48 15.81 9.81 10.38 13.93
63 10.5 5.58 6.98 3.93 2.81 4.68 13.81 8.26 7.39 10.73
126 10.5 5.58 8.16 4.49 2.20 3.44 12.23 7.00 4.40 6.88
252 10.5 5.58 10.50 5.58 0.00 0.00 10.50 5.58 0.00 0.00
In [ ]:
variable_range=range(60,155,5)

option_prices=[]
for s0 in variable_range:
    price_path = pd.DataFrame(simulate_path(s0, 0.05, 0.20, 1, 252, 100000)) # timesteps=252 meaning simulating by days
    result_list=caculate_exotic_price(price_path,21,100,0.05,1)
    option_prices.append(result_list)
    
##################################### make table ####################################################

df=pd.DataFrame(option_prices)
df.columns=["European Call", "European Put", \
            "Fixed Asian Call", "Fixed Asian put",\
            "Floating Asian Call","Floating Asian Put",\
            "Fixed Lookback Call","Fixed Lookback Put",\
            "Floating Lookback Call","Floating Lookback Put"]
df.index=variable_range
df.index.name="S0"

##################################### visualize ####################################################
df.iplot(title='Option price with change in S0', xTitle='S0', yTitle='Price',colors=color_styles, width=3, dash=dash_styles)
round(df, 2)
Out[ ]:
European Call European Put Fixed Asian Call Fixed Asian put Floating Asian Call Floating Asian Put Fixed Lookback Call Fixed Lookback Put Floating Lookback Call Floating Lookback Put
S0
60 0.06 35.16 0.00 36.47 1.92 3.29 0.07 43.46 6.23 8.36
65 0.18 30.28 0.00 31.58 2.08 3.56 0.23 39.16 6.75 9.06
70 0.45 25.55 0.01 26.71 2.24 3.83 0.61 34.85 7.26 9.75
75 0.99 21.08 0.08 21.88 2.40 4.11 1.36 30.55 7.78 10.45
80 1.89 16.98 0.28 17.20 2.56 4.38 2.66 26.24 8.30 11.15
85 3.25 13.34 0.79 12.82 2.72 4.66 4.67 21.94 8.82 11.84
90 5.13 10.22 1.84 8.99 2.88 4.93 7.52 17.65 9.34 12.54
95 7.56 7.64 3.62 5.87 3.04 5.20 11.25 13.51 9.86 13.24
100 10.50 5.58 6.19 3.56 3.20 5.48 15.81 9.81 10.38 13.93
105 13.91 3.99 9.52 2.00 3.36 5.75 20.94 6.85 10.90 14.63
110 17.71 2.80 13.45 1.04 3.52 6.03 26.36 4.67 11.42 15.33
115 21.84 1.92 17.80 0.50 3.68 6.30 31.86 3.13 11.93 16.02
120 26.22 1.30 22.41 0.23 3.84 6.57 37.37 2.07 12.45 16.72
125 30.78 0.86 27.17 0.10 4.00 6.85 42.90 1.34 12.97 17.42
130 35.49 0.56 32.00 0.04 4.16 7.12 48.42 0.86 13.49 18.11
135 40.29 0.37 36.86 0.01 4.32 7.39 53.94 0.55 14.01 18.81
140 45.16 0.24 41.74 0.01 4.48 7.67 59.46 0.34 14.53 19.51
145 50.08 0.15 46.63 0.00 4.64 7.94 64.98 0.21 15.05 20.20
150 55.03 0.09 51.51 0.00 4.80 8.22 70.50 0.13 15.57 20.90
In [ ]:
price_path = pd.DataFrame(simulate_path(100, 0.05, 0.20, 1, 252, 100000)) # reset
variable_range=range(50,155,5)

option_prices=[]
for E in variable_range:
    result_list=caculate_exotic_price(price_path,21,E,0.05,1)
    option_prices.append(result_list)
    
##################################### make table ####################################################

df=pd.DataFrame(option_prices)
df.columns=["European Call", "European Put", \
            "Fixed Asian Call", "Fixed Asian put",\
            "Floating Asian Call","Floating Asian Put",\
            "Fixed Lookback Call","Fixed Lookback Put",\
            "Floating Lookback Call","Floating Lookback Put"]
df.index=variable_range
df.index.name="E"

##################################### visualize ####################################################
names=["European Call","European Put","Fixed Asian Call","Fixed Asian put","Fixed Lookback Call","Fixed Lookback Put"]
df=df[names]
df.iplot(title='Option price with change in E', xTitle='E', yTitle='Price',colors=color_styles, width=3, dash=['solid', 'dash','solid', 'dash','solid', 'dash'])
round(df, 2)
Out[ ]:
European Call European Put Fixed Asian Call Fixed Asian put Fixed Lookback Call Fixed Lookback Put
E
50 52.48 0.00 50.19 0.00 62.85 0.00
55 47.72 0.00 45.44 0.00 58.10 0.00
60 42.97 0.01 40.68 0.00 53.34 0.02
65 38.25 0.04 35.93 0.00 48.58 0.06
70 33.58 0.13 31.17 0.00 43.83 0.18
75 29.01 0.32 26.43 0.02 39.07 0.48
80 24.63 0.69 21.73 0.08 34.32 1.07
85 20.51 1.33 17.19 0.28 29.56 2.14
90 16.74 2.32 12.95 0.80 24.82 3.85
95 13.39 3.72 9.23 1.84 20.16 6.38
100 10.50 5.58 6.19 3.56 15.81 9.81
105 8.07 7.91 3.91 6.03 12.03 13.99
110 6.09 10.69 2.32 9.20 8.95 18.57
115 4.51 13.87 1.30 12.93 6.54 23.29
120 3.29 17.40 0.69 17.08 4.69 28.05
125 2.36 21.22 0.35 21.50 3.32 32.80
130 1.67 25.29 0.17 26.07 2.32 37.56
135 1.16 29.54 0.08 30.74 1.60 42.31
140 0.80 33.94 0.03 35.45 1.09 47.07
145 0.55 38.44 0.01 40.19 0.74 51.83
150 0.37 43.02 0.01 44.93 0.49 56.58
In [ ]:
variable_range=arange(0.05,0.40,0.01)

option_prices=[]
for Sig in variable_range:
    price_path = pd.DataFrame(simulate_path(100, 0.05, Sig, 1, 252, 100000)) # timesteps=252 meaning simulating by days
    result_list=caculate_exotic_price(price_path,21,100,0.05,1)
    option_prices.append(result_list)
    
##################################### make table ####################################################
df=pd.DataFrame(option_prices)
df.columns=["European Call", "European Put", \
            "Fixed Asian Call", "Fixed Asian put",\
            "Floating Asian Call","Floating Asian Put",\
            "Fixed Lookback Call","Fixed Lookback Put",\
            "Floating Lookback Call","Floating Lookback Put"]
df.index=variable_range
df.index.name="sigma"

##################################### visualize ####################################################
df.iplot(title='Option price with change in Volatility ', xTitle='Vol', yTitle='Price',colors=color_styles, width=3, dash=dash_styles)

Heston model for stochastic volatility¶

The Heston process is described by the SDE:

$$ \begin{cases} dS_t = \mu S_t dt + \sqrt{v_t} S_t dW^1_t \\ dv_t = \kappa (\theta - v_t) dt + \sigma \sqrt{v_t} dW^2_t \end{cases}$$

The stock price follows a "geometric Brownian motion" with a stochastic volatility.

The parameters are:

  • $\mu$ drift of the stock process
  • $\kappa$ mean reversion coefficient of the variance process
  • $\theta$ long term mean of the variance process
  • $\sigma$ volatility coefficient of the variance process
  • $\rho$ correlation between $W^1$ and $W^2$ i.e. $$ dW^1_t dW^2_t = \rho dt $$

We will also require that $2\kappa \theta > \sigma^2$ (Feller condition).

The Euler method can be obtained by using Ito's lemma $ln S_t$ $$ v_{t+dt} = v_t + \kappa(\theta - v_t)dt + \sigma\sqrt(v_t dt) Z_v \\ S_{t+dt} = S_t * exp((r - \frac{1}{2} v_t)dt + \sqrt(v_t dt) Z_s) $$

To generate $Z_v$ and $Z_S$ with correlation $\rho$ we generate two independent standard normal variable $Z_1$ and $Z_2$, and we set $Z_v = Z1$ and $Z_S = \rho Z_1 + \sqrt(1-\rho)^2 Z_2$.

To avoid negative variances we must apply the full truncation scheme by replacing $v_t$ everywhere with $|v_t|$.

In [ ]:
# define simulation function for stochastic volatility
def simulate_path_sv(s0, mu, horizon, timesteps, n_sims, volvol, kappa, rho):
    
    # set the seed
    random.seed(2023)
    
    # read the params
    S0 = s0
    r = mu

    T = horizon
    t = timesteps
    n = n_sims
    # define dt
    dt = T/t
    
    #rho = 0.6  # correlation coefficient
    #kappa = 2  # mean reversion coefficient
    theta = 0.04  # long-term variance
    
    # simulate path
    S = zeros((t+1,n))
    S[0] = S0
    
    v = zeros((t+1,n))
    v[0] = 0.04
    

    for i in range(1, t+1):
        # Generate random Brownian Motion
        z1 = random.standard_normal(n) # psuedo random numbers
        z2 = random.standard_normal(n) # psuedo random numbers
        
        W_v = z1 
        W_S = rho*z1 + sqrt(1 - rho*rho) * z2 
        
        # Euler discretization of v_t
        v[i] = maximum( zeros(n), v[i-1] + kappa*(theta - v[i-1]) * dt + volvol * sqrt(v[i-1] * dt) * W_v)
        
        # Euler discretization of SDE
        S[i] = S[i-1] * exp( (r - 0.5*v[i-1])*dt + sqrt(v[i-1]*dt) * W_S)
        
    return S
In [ ]:
# Assign simulated price path to dataframe for analysis and plotting
price_path = pd.DataFrame(simulate_path_sv(100,0.05,1,252,100000, 0.4, 2, 0.6))

# Verify the generated price paths
price_path.head()
Out[ ]:
0 1 2 3 4 5 6 7 8 9 ... 99990 99991 99992 99993 99994 99995 99996 99997 99998 99999
0 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 ... 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000 100.000000
1 100.683448 99.464538 98.682492 100.181788 98.893757 100.870041 102.666231 99.818953 101.135151 96.805848 ... 101.124961 97.933658 99.524592 100.177686 98.299079 99.647838 98.799013 100.254826 99.339495 99.718520
2 99.945981 100.195158 99.531965 100.181610 100.256683 100.597858 103.173847 97.661437 99.479355 95.614572 ... 102.982239 98.070345 100.597226 99.724128 98.634632 100.245476 98.521237 99.944258 98.046813 98.645791
3 99.683888 99.338538 98.095665 101.008841 96.855748 100.345477 105.495043 97.603989 98.047109 95.489134 ... 103.794795 98.220274 101.982000 99.122856 100.905605 100.589018 97.021455 101.100073 96.274585 96.454135
4 99.194870 98.447574 97.498160 98.997072 97.945392 100.191981 108.018307 97.304107 99.697690 95.448173 ... 103.380656 98.186150 101.988699 100.195150 100.468666 98.715772 94.380848 103.317409 96.351390 96.440158

5 rows × 100000 columns

In [ ]:
# Plot the histogram of the simulated price path at maturity
price_path.iloc[-1].hist(bins=100)
plt.ylabel('frequency')
plt.xlabel('Asset price at maturity with stochatic volatility model')
plt.title('Histogram of the simulated price path at maturity')
plt.xlim(0, 400)
plt.show()
No description has been provided for this image
In [ ]:
price_path.iloc[:,:20].iplot(title='Simulated Underlying Asset Price Paths with stochastic volatility assumption', xTitle='Time Steps', yTitle='Price')
In [ ]:
variable_range=arange(0.00,1,0.1)

option_prices=[]
for v in variable_range:
    SV_price_path = pd.DataFrame(simulate_path_sv(s0=100, mu=0.05, horizon=1, timesteps=252, n_sims=100000, volvol=v, kappa=2, rho=0.6 ))
    result_path=caculate_exotic_price(SV_price_path,21,100,0.05,1)
    option_prices.append(result_path)
    
##################################### make table ####################################################
df=pd.DataFrame(option_prices)
df.columns=["European Call", "European Put", \
            "Fixed Asian Call", "Fixed Asian put",\
            "Floating Asian Call","Floating Asian Put",\
            "Fixed Lookback Call","Fixed Lookback Put",\
            "Floating Lookback Call","Floating Lookback Put"]

df.index=variable_range
df.index.name="vol of vol"
##################################### visualize ####################################################
df.iplot(title='Option price with change in vol of vol', xTitle='vol of vol', yTitle='Price',colors=color_styles, width=3, dash=dash_styles)
In [ ]:
round(df, 2)
Out[ ]:
European Call European Put Fixed Asian Call Fixed Asian put Floating Asian Call Floating Asian Put Fixed Lookback Call Fixed Lookback Put Floating Lookback Call Floating Lookback Put
vol of vol
0.0 10.45 5.58 6.18 3.55 3.21 5.45 15.75 9.80 10.36 13.88
0.1 10.38 5.51 6.15 3.51 3.18 5.42 15.96 9.54 10.57 13.65
0.2 10.26 5.38 6.10 3.45 3.11 5.35 16.07 9.20 10.66 13.32
0.3 10.11 5.22 6.03 3.37 3.01 5.24 16.08 8.79 10.65 12.91
0.4 9.92 5.03 5.94 3.28 2.88 5.11 15.99 8.35 10.53 12.48
0.5 9.76 4.85 5.85 3.18 2.76 5.00 15.86 7.96 10.39 12.10
0.6 9.64 4.72 5.77 3.09 2.69 4.93 15.78 7.67 10.29 11.81
0.7 9.58 4.65 5.71 3.02 2.65 4.90 15.78 7.48 10.27 11.63
0.8 9.57 4.64 5.67 2.98 2.66 4.91 15.85 7.39 10.35 11.54
0.9 9.60 4.66 5.65 2.96 2.69 4.94 16.00 7.36 10.49 11.52
In [ ]:
variable_range=arange(-1,1.1,0.1)

option_prices=[]
for p in variable_range:
    SV_price_path = pd.DataFrame(simulate_path_sv(s0=100, mu=0.05, horizon=1, timesteps=252, n_sims=100000, volvol=0.4, kappa=2, rho=p ))
    result_path=caculate_exotic_price(SV_price_path,21,100,0.05,1)
    option_prices.append(result_path)
    
##################################### make table ####################################################
df=pd.DataFrame(option_prices)
df.columns=["European Call", "European Put", \
            "Fixed Asian Call", "Fixed Asian put",\
            "Floating Asian Call","Floating Asian Put",\
            "Fixed Lookback Call","Fixed Lookback Put",\
            "Floating Lookback Call","Floating Lookback Put"]

df.index=variable_range.round(1)
df.index.name="rho"

##################################### visualize ####################################################
df.iplot(title='Option price with change in Correlation Coefficient', xTitle='Correlation Coefficient', yTitle='Prices',colors=color_styles, width=3, dash=dash_styles)
round(df, 2)
Out[ ]:
European Call European Put Fixed Asian Call Fixed Asian put Floating Asian Call Floating Asian Put Fixed Lookback Call Fixed Lookback Put Floating Lookback Call Floating Lookback Put
rho
-1.0 10.34 5.38 6.13 3.48 2.96 5.27 13.62 10.29 8.19 14.23
-0.9 10.35 5.37 6.14 3.47 2.96 5.27 13.76 10.18 8.31 14.15
-0.8 10.35 5.37 6.13 3.46 2.96 5.27 13.89 10.08 8.44 14.07
-0.7 10.35 5.36 6.13 3.45 2.97 5.27 14.03 9.98 8.57 13.98
-0.6 10.34 5.36 6.12 3.44 2.97 5.27 14.17 9.87 8.71 13.88
-0.5 10.32 5.34 6.11 3.43 2.96 5.26 14.31 9.76 8.85 13.79
-0.4 10.30 5.33 6.10 3.42 2.96 5.26 14.46 9.65 8.99 13.69
-0.3 10.29 5.31 6.09 3.41 2.96 5.25 14.61 9.53 9.13 13.58
-0.2 10.26 5.30 6.08 3.40 2.96 5.24 14.76 9.42 9.28 13.48
-0.1 10.24 5.28 6.07 3.39 2.95 5.23 14.91 9.30 9.43 13.37
-0.0 10.21 5.25 6.05 3.37 2.94 5.22 15.06 9.18 9.58 13.26
0.1 10.18 5.23 6.04 3.36 2.94 5.21 15.21 9.05 9.73 13.14
0.2 10.14 5.20 6.02 3.35 2.93 5.19 15.36 8.92 9.88 13.02
0.3 10.10 5.17 6.01 3.33 2.92 5.17 15.52 8.79 10.04 12.90
0.4 10.05 5.13 5.98 3.31 2.91 5.16 15.67 8.65 10.20 12.77
0.5 9.99 5.08 5.96 3.30 2.89 5.14 15.83 8.51 10.36 12.63
0.6 9.92 5.03 5.94 3.28 2.88 5.11 15.99 8.35 10.53 12.48
0.7 9.85 4.97 5.91 3.25 2.86 5.09 16.15 8.18 10.70 12.32
0.8 9.77 4.91 5.87 3.23 2.85 5.06 16.31 8.00 10.88 12.15
0.9 9.67 4.84 5.83 3.20 2.84 5.04 16.47 7.81 11.05 11.96
1.0 9.54 4.76 5.77 3.17 2.84 5.01 16.60 7.62 11.23 11.74