def main():

    # if np_output is True, the output will be np.ndarray, otherwise pd.DataFrame    
    np_output = False # True
    
    # default market environment
    market_env = MarketEnvironment()
    print(market_env)
    
    # define option style and type
    opt_style = "plain_vanilla" # "digital"
    opt_type = "call" # "put"   
    option = option_factory(market_env, opt_style, opt_type)
    print(option)
    
    for case in ['All_scalar', \
                 'S', 'S.sigma_distributed', 'S.r_distributed', 'S.sigma_and_r_distributed', \
                 'K', 'K.sigma_distributed', 'K.r_distributed', 'K.sigma_and_r_distributed', \
                 't', 't.sigma_distributed', 't.r_distributed', 't.sigma_and_r_distributed', \
                 'S.t', 'S.t.sigma_distributed_as_Sxt_grid', 'S.t.r_distributed_as_Sxt_grid', 'S.t.sigma_and_r_distributed_as_Sxt_grid', \
                 'K.t', 'K.t.sigma_distributed_as_Kxt_grid', 'K.t.r_distributed_as_Kxt_grid', 'K.t.sigma_and_r_distributed_as_Kxt_grid', \
                 't.sigma_axis', 't.r_axis']:
    
        # get parameters dictionary for case considered
        param_dict, case_info = get_param_dict(option, np_output, case)
    
        print("\n--------------------------------------------\n")
        print("\n" + case_info + "\n")
        
        print("Parameters:")
        print("S: {}".format(param_dict["S"]))
        print("K: {}".format(param_dict["K"]))
        print("t: {}".format(param_dict["t"]))
        print("sigma: {}".format(param_dict["sigma"]))
        print("r: {}\n".format(param_dict["r"]))
        
        print("Metrics:")
        print("Payoff:\n", option.payoff(**param_dict))
        print("\nPrice upper limit:\n", option.price_upper_limit(**param_dict))
        print("\nPrice lower limit:\n", option.price_lower_limit(**param_dict))
        print("\nPrice:\n", option.price(**param_dict))
        print("\nP&L:\n", option.PnL(**param_dict))
        print("\nDelta:\n", option.delta(**param_dict))
        print("\nTheta:\n", option.theta(**param_dict))
        print("\nGamma:\n", option.gamma(**param_dict))
        print("\nVega:\n", option.vega(**param_dict))
        print("\nRho:\n", option.rho(**param_dict))

        # Implied volatility calculation is not implemented for x-axis 
        # (columns) spanned by sigma
        if ('sigma_axis' not in param_dict) or (param_dict['sigma_axis'] == False):
            
            print("\nExpected Implied Volatility: \n{}\n".format(param_dict["sigma"]))

            print("\nImplied Volatility - Newton method:\n{}\n"\
                  .format(option.implied_volatility(**param_dict)))
            
            param_dict["minimization_method"] = "Least-Squares"
            print("\nImplied Volatility - Least-Squares constrained method:\n{}\n"\
                  .format(option.implied_volatility(**param_dict)))
def main():

    # vanilla call implementation example

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # define option style and type
    opt_style = "plain_vanilla"  # "digital"
    opt_type = "call"  # "put"
    option = option_factory(market_env, opt_style, opt_type)
    print(option)

    # option plotter instance
    plotter = OptionPlotter(option)

    # valuation date of the option
    emission_date = option.get_t()
    print(emission_date)

    # select dependency to plot as x-axis of the plot
    for dependency_type in ["S", "K", "sigma", "r"]:

        # keyboard parameter and corresponding range to test
        x_axis_dict = options_x_axis_parameters_factory(
            option, dependency_type)

        # select metrics to plot
        for plot_metrics in [
                "price", "PnL", "delta", "theta", "gamma", "vega", "rho"
        ]:

            plot_details_flag = True if plot_metrics == "price" else False

            # Plot at t
            plotter.plot(**x_axis_dict,
                         t=[emission_date],
                         plot_metrics=plot_metrics,
                         plot_details=plot_details_flag)

            # Plot at another date-string date
            plotter.plot(**x_axis_dict,
                         t="01-06-2020",
                         plot_metrics=plot_metrics,
                         plot_details=plot_details_flag)

            for time_kind in ['date', 'tau']:

                # set time-parameter to plot
                multiple_valuation_dates = get_time_parameter(option,
                                                              kind=time_kind)
                print(multiple_valuation_dates)

                # Plot at multiple dates
                plotter.plot(**x_axis_dict,
                             t=multiple_valuation_dates,
                             plot_metrics=plot_metrics)
Beispiel #3
0
def main():

    # vanilla call implementation example

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # define option style and type
    opt_style = "plain_vanilla"  # "digital"
    opt_type = "call"  # "put"
    option = option_factory(market_env, opt_style, opt_type)
    print(option)

    # option plotter instance
    plotter = OptionPlotter(option)

    # valuation date of the option
    emission_date = option.get_t()
    print(emission_date)

    # select metrics to plot
    for plot_metrics in ["implied_volatility"]:

        plot_details_flag = True if plot_metrics == "price" else False

        # Plot at t
        plotter.plot(t=[emission_date],
                     plot_metrics=plot_metrics,
                     plot_details=plot_details_flag)

        # Plot at another date-string date
        plotter.plot(t="01-06-2020",
                     plot_metrics=plot_metrics,
                     plot_details=plot_details_flag)

        for time_kind in ['date', 'tau']:

            # set time-parameter to plot
            multiple_valuation_dates = get_time_parameter(option,
                                                          kind=time_kind)
            print(multiple_valuation_dates)

            # Plot at multiple dates
            plotter.plot(t=multiple_valuation_dates, plot_metrics=plot_metrics)
Beispiel #4
0
def main():

    # Bull-Spread implementation example

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # options strikes
    K_long = 80
    K_short = 110

    # bull-spread portfolio initialized (as empty portfolio)
    bull_spread_ptf = Portfolio(name="Bull Spread Strategy")
    print(bull_spread_ptf)

    # 80-call
    Vanilla_Call_long = PlainVanillaOption(market_env,
                                           K=K_long,
                                           T='31-12-2021')
    print(Vanilla_Call_long)

    # 110-call
    Vanilla_Call_short = PlainVanillaOption(market_env,
                                            K=K_short,
                                            T='31-12-2021')
    print(Vanilla_Call_short)

    # creation of bull-spread portfolio strategy
    bull_spread_ptf.add_instrument(Vanilla_Call_long, 1)
    bull_spread_ptf.add_instrument(Vanilla_Call_short, -1)
    print(bull_spread_ptf)

    # portfolio plotter instance
    bull_spread_ptf_plotter = PortfolioPlotter(bull_spread_ptf)

    # select dependency to plot as x-axis of the plot
    # (strike 'K' is skipped because a bull-spread is a multi-strike portfolio)
    for dependency_type in ["S", "sigma", "r"]:

        # keyboard parameter and corresponding range to test
        x_axis_dict = options_x_axis_parameters_factory(
            bull_spread_ptf, dependency_type)

        # appropriate azimut angle for best viewing
        azimut_angle = get_azimut_angle(dependency_type)

        # select metrics to plot
        for plot_metrics in [
                "price", "PnL", "delta", "theta", "gamma", "vega", "rho"
        ]:

            plot_details_flag = True if plot_metrics == "price" else False

            # Bull-Spread price plot
            bull_spread_ptf_plotter.plot(**x_axis_dict,
                                         t='01-06-2020',
                                         plot_metrics=plot_metrics,
                                         plot_details=plot_details_flag)

            for time_kind in ['date', 'tau']:

                # set time-parameter to plot
                multiple_valuation_dates = get_time_parameter(bull_spread_ptf,
                                                              kind=time_kind)
                print(multiple_valuation_dates)

                # Plot at multiple dates
                bull_spread_ptf_plotter.plot(**x_axis_dict,
                                             t=multiple_valuation_dates,
                                             plot_metrics=plot_metrics)

                # Surface plot
                bull_spread_ptf_plotter.plot(**x_axis_dict,
                                             t=multiple_valuation_dates,
                                             plot_metrics=plot_metrics,
                                             surf_plot=True)

                # Surface plot (rotate) - x-axis side
                bull_spread_ptf_plotter.plot(**x_axis_dict,
                                             t=multiple_valuation_dates,
                                             plot_metrics=plot_metrics,
                                             surf_plot=True,
                                             view=(
                                                 0,
                                                 azimut_angle["x-axis side"]))

                # Price surface plot (rotate) - Date side
                bull_spread_ptf_plotter.plot(**x_axis_dict,
                                             t=multiple_valuation_dates,
                                             plot_metrics=plot_metrics,
                                             surf_plot=True,
                                             view=(0,
                                                   azimut_angle["Date side"]))
Beispiel #5
0
def main():

    #
    # portfolio instantiation example
    #

    # if np_output is True, the output will be np.ndarray, otherwise pd.DataFrame
    np_output = False  # True

    # default market environment
    market_env = MarketEnvironment(t="01-06-2020")
    print(market_env)

    # underlying values to test
    S_vector = [60, 90, 120]
    print("S_vector: {}\n".format(S_vector))

    # options maturities
    T_call = "31-12-2020"
    T_put = "30-06-2021"

    # options strikes are the same
    K = 90
    K_put = K
    K_call = K

    # portfolio options positions
    call_pos = 2
    put_pos = -5

    #
    # Step 0: empty portfolio initialized
    #

    ptf = Portfolio()
    print(ptf)

    #
    # Step 1: adding 2 long plain-vanilla call contracts
    #

    # plain-vanilla call option
    opt1_style = "plain_vanilla"  # "digital"
    opt1_type = "call"  # "put"
    call = option_factory(market_env,
                          opt1_style,
                          opt1_type,
                          K=K_call,
                          T=T_call)
    print(call)

    # adding contract to portfolio
    ptf.add_instrument(call, call_pos)
    print(ptf)

    #
    # Step 2: adding 5 short plain-vanilla put contracts
    #

    # plain-vanilla put option
    opt2_style = "plain_vanilla"  # "digital"
    opt2_type = "put"  # "call"
    put = option_factory(market_env, opt2_style, opt2_type, K=K_put, T=T_put)
    print(put)

    # plain-vanilla put option
    put = PlainVanillaOption(market_env, option_type="put", K=K_put, T=T_put)
    print(put)

    # adding contract to portfolio
    ptf.add_instrument(put, put_pos)
    print(ptf)

    #
    # Step 3: portfolio evaluation
    #

    for case in ['All_scalar', \
                 'S', 'S.sigma_distributed', 'S.r_distributed', 'S.sigma_and_r_distributed', \
                 'K', 'K.sigma_distributed', 'K.r_distributed', 'K.sigma_and_r_distributed', \
                 't', 't.sigma_distributed', 't.r_distributed', 't.sigma_and_r_distributed', \
                 'S.t', 'S.t.sigma_distributed_as_Sxt_grid', 'S.t.r_distributed_as_Sxt_grid', 'S.t.sigma_and_r_distributed_as_Sxt_grid', \
                 'K.t', 'K.t.sigma_distributed_as_Kxt_grid', 'K.t.r_distributed_as_Kxt_grid', 'K.t.sigma_and_r_distributed_as_Kxt_grid', \
                 't.sigma_axis', 't.r_axis']:

        # get parameters dictionary for case considered
        param_dict, case_info = get_param_dict_single_K_ptf(
            ptf,
            np_output,
            case,
            T=min(T_call, T_put, key=date_string_to_datetime_obj))

        print("\n--------------------------------------------\n")
        print("\n" + case_info + "\n")

        print("Parameters:")
        print("S: {}".format(param_dict["S"]))
        print("K: {}".format(param_dict["K"]))
        print("t: {}".format(param_dict["t"]))
        print("sigma: {}".format(param_dict["sigma"]))
        print("r: {}\n".format(param_dict["r"]))

        print("Metrics:")

        # metrics to compare
        for metrics in [
                "price", "PnL", "delta", "theta", "gamma", "vega", "rho"
        ]:

            # portfolio metrics
            ptf_metrics = getattr(ptf, metrics)(**param_dict)
            print("\nPortfolio {}:\n{}".format(metrics, ptf_metrics))

            # verification with benchmark metrics
            call_metrics = getattr(call, metrics)(**param_dict)
            put_metrics = getattr(put, metrics)(**param_dict)
            benchmark_metrics = call_pos * call_metrics + put_pos * put_metrics
            print("\nBenchmark {}:\n{}".format(metrics, benchmark_metrics))

            # check effective match
            diff = (ptf_metrics - benchmark_metrics).astype('float')
            num_nonzero_diff = np.count_nonzero(diff) - np.isnan(
                diff).sum().sum()
            exact_match = True if num_nonzero_diff == 0 else False
            print("\nIs replication exact (NaN excluded)? {}\n".format(
                exact_match))
Beispiel #6
0
def main():

    # numeric Vs analytic greeks example
            
    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # define option style and type
    opt_style = "plain_vanilla" # "digital"
    opt_type = "call" # "put"  
    option = option_factory(market_env, opt_style, opt_type)
    print(option)
    
    # select greek
    for greek_type in ["delta", "theta", "gamma", "vega", "rho"]:
        
        # numeric greeks instance
        NumGreeks = NumericGreeks(option)
    
        #
        # greek Vs Underlying level S
        # 
        
        # underlying range at which compute greeks
        S_range = np.linspace(50, 150, 2000)
        
        # analytic greek
        greek_analytic_Vs_S = greeks_factory(option, greek_type)(S=S_range)
        
        # numeric greek
        greek_numeric_Vs_S = greeks_factory(NumGreeks, greek_type)(S=S_range)
        
        # labels
        label_numeric_S = greeks_label_factory(greek_type, opt_type, kind="num")
        label_analytic_S = greeks_label_factory(greek_type, opt_type, kind="exact")
            
        # plot title
        plot_title_S = greeks_title_factory(option, greek_type)
        
        # comparison
        plot_compare(S_range, f=greek_numeric_Vs_S, f_ref=greek_analytic_Vs_S, 
                     f_label=label_numeric_S, f_ref_label=label_analytic_S,
                     x_label="S",f_test_name="Numeric " + greek_type,
                     f_ref_name="Exact " + greek_type, title=plot_title_S)
        
        #
        # greek Vs residual time to maturity tau
        # 
        
        # time-to-maturity range at which compute greeks
        tau_range = np.linspace(1e-4,1.0,1000)
        tau_range = homogenize(tau_range, reverse_order=True)
        
        # analytic greek
        greek_analytic_Vs_tau = greeks_factory(option, greek_type)(tau=tau_range)
    
        # numeric greek
        greek_numeric_Vs_tau = greeks_factory(NumGreeks, greek_type)(tau=tau_range)
        
        # labels
        label_numeric_tau = greeks_label_factory(greek_type, opt_type, 
                                                 kind="num", underlying=r"\tau")
        label_analytic_tau = greeks_label_factory(greek_type, opt_type, 
                                                  kind="exact", underlying=r"\tau")
            
        # plot title
        plot_title_tau = greeks_title_factory(option, greek_type, underlying=r"\tau")
        
        # comparison
        plot_compare(tau_range, f=greek_numeric_Vs_tau, f_ref=greek_analytic_Vs_tau, 
                     f_label=label_numeric_tau, f_ref_label=label_analytic_tau,
                     x_label=r"\tau", f_test_name="Numeric " + greek_type,
                     f_ref_name="Exact " + greek_type, title=plot_title_tau)
Beispiel #7
0
def main():

    # Bull-Spread implementation example

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # options strikes
    K_long = 80
    K_short = 110

    # bull-spread portfolio initialized (as empty portfolio)
    bull_spread_ptf = Portfolio(name="Bull Spread Strategy")
    print(bull_spread_ptf)

    # 80-call
    Vanilla_Call_long = PlainVanillaOption(market_env,
                                           K=K_long,
                                           T='31-12-2021')
    print(Vanilla_Call_long)

    # 110-call
    Vanilla_Call_short = PlainVanillaOption(market_env,
                                            K=K_short,
                                            T='31-12-2021')
    print(Vanilla_Call_short)

    # creation of bull-spread portfolio strategy
    bull_spread_ptf.add_instrument(Vanilla_Call_long, 1)
    bull_spread_ptf.add_instrument(Vanilla_Call_short, -1)
    print(bull_spread_ptf)

    # portfolio plotter instance
    bull_spread_ptf_plotter = PortfolioPlotter(bull_spread_ptf)

    # select metrics to plot
    for plot_metrics in [
            "price", "PnL", "delta", "theta", "gamma", "vega", "rho"
    ]:

        plot_details_flag = True if plot_metrics == "price" else False

        # Bull-Spread price plot
        bull_spread_ptf_plotter.plot(t='01-06-2020',
                                     plot_metrics=plot_metrics,
                                     plot_details=plot_details_flag)

        for time_kind in ['date', 'tau']:

            # set time-parameter to plot
            multiple_valuation_dates = get_time_parameter(bull_spread_ptf,
                                                          kind=time_kind)
            print(multiple_valuation_dates)

            # Plot at multiple dates
            bull_spread_ptf_plotter.plot(t=multiple_valuation_dates,
                                         plot_metrics=plot_metrics)

            # Surface plot
            bull_spread_ptf_plotter.plot(t=multiple_valuation_dates,
                                         plot_metrics=plot_metrics,
                                         surf_plot=True)

            # Surface plot (rotate) - Underlying value side
            bull_spread_ptf_plotter.plot(t=multiple_valuation_dates,
                                         plot_metrics=plot_metrics,
                                         surf_plot=True,
                                         view=(0, 180))

            # Price surface plot (rotate) - Date side
            bull_spread_ptf_plotter.plot(t=multiple_valuation_dates,
                                         plot_metrics=plot_metrics,
                                         surf_plot=True,
                                         view=(0, -90))
Beispiel #8
0
def main():
    
    # Calendar-Spread implementation example
            
    # default market environment
    market_env = MarketEnvironment()
    print(market_env)
    
    # options expirations
    T_short = "31-05-2020"
    T_long = "30-08-2020"
    
    # current underlying level
    S_t = market_env.get_S()

    # calendar-spread portfolio initialized (as empty portfolio)   
    calendar_spread_ptf = Portfolio(name="Calendar Spread Strategy")
    print(calendar_spread_ptf)
    
    # T_long-call
    Vanilla_Call_long = PlainVanillaOption(market_env, T=T_long, K=S_t)
    print(Vanilla_Call_long)

    # T_short-call
    Vanilla_Call_short = PlainVanillaOption(market_env, T=T_short, K=S_t)
    print(Vanilla_Call_short)

    # creation of Calendar-Spread portfolio strategy   
    calendar_spread_ptf.add_instrument(Vanilla_Call_long, 1)
    calendar_spread_ptf.add_instrument(Vanilla_Call_short, -1)    
    print(calendar_spread_ptf)
    
    # portfolio plotter instance
    calendar_spread_ptf_plotter = PortfolioPlotter(calendar_spread_ptf)
    
    # valuation date of the portfolio
    valuation_date = calendar_spread_ptf.get_t()
    print(valuation_date)
        
    # select dependency to plot as x-axis of the plot 
    for dependency_type in ["S", "K", "sigma", "r"]:
    
        # keyboard parameter and corresponding range to test
        x_axis_dict = options_x_axis_parameters_factory(calendar_spread_ptf, dependency_type)    

        # appropriate azimut angle for best viewing
        azimut_angle = get_azimut_angle(dependency_type)

        # select metrics to plot
        for plot_metrics in ["price", "PnL", "delta", "theta", "gamma", "vega", "rho"]:
            
            plot_details_flag = True if plot_metrics == "price" else False
    
            # time-parameter as a date-range of 5 valuation dates between t and T_short
            last_date = T_short if plot_metrics in ["price", "PnL"] else date_string_to_datetime_obj(T_short) - pd.Timedelta(days=1)
            multiple_valuation_dates = pd.date_range(start=valuation_date, 
                                                     end=last_date, 
                                                     periods=5)
            print(multiple_valuation_dates)
    
            # Bull-Spread price plot
            calendar_spread_ptf_plotter.plot(**x_axis_dict, t=last_date, plot_metrics=plot_metrics, 
                                             plot_details=plot_details_flag)
                
            # Plot at multiple dates
            calendar_spread_ptf_plotter.plot(**x_axis_dict, t=multiple_valuation_dates, plot_metrics=plot_metrics)
        
            # Surface plot
            calendar_spread_ptf_plotter.plot(**x_axis_dict, t=multiple_valuation_dates, 
                                             plot_metrics=plot_metrics, surf_plot=True)
        
            # Surface plot (rotate) - Underlying value side
            calendar_spread_ptf_plotter.plot(**x_axis_dict, t=multiple_valuation_dates, 
                                             plot_metrics=plot_metrics, surf_plot=True, 
                                             view=(0,azimut_angle["x-axis side"]))
        
            # Price surface plot (rotate) - Date side
            calendar_spread_ptf_plotter.plot(**x_axis_dict, t=multiple_valuation_dates, 
                                             plot_metrics=plot_metrics, surf_plot=True, 
                                             view=(0,azimut_angle["Date side"]))
Beispiel #9
0
def main():

    #
    # Black-Scholes implied volatility calculation with user-defined 'sigma'
    # parameter surface, used to evaluate the quality of the implied volatility
    # calculation.
    #

    # output format: pd.DataFrame
    np_output = False

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # define option style and type
    opt_style = "plain_vanilla"  # "digital"
    opt_type = "call"  # "call" # "put"
    option = option_factory(market_env, opt_style, opt_type)
    print(option)

    # K
    K_vector = [50, 75, 100, 125, 150]

    # tau: a date-range of 5 valuation dates between t and T-10d
    n = 6
    valuation_date = option.get_t()
    expiration_date = option.get_T()
    t_vector = pd.date_range(start=valuation_date,
                             end=expiration_date - pd.Timedelta(days=25),
                             periods=n)

    # sigma (qualitatively reproducing the smile)
    k, tau = np.meshgrid(K_vector, option.time_to_maturity(t=t_vector))
    sigma_grid_K = 0.01 + ((k - 100)**2) / (100 * k * tau)

    # pricing parameters
    param_dict = {
        "S": 100,
        "K": K_vector,
        "t": t_vector,
        "sigma": sigma_grid_K,
        "r": 0.01,
        "np_output": np_output
    }

    print("Parameters:")
    print("S: {}".format(param_dict["S"]))
    print("K: {}".format(param_dict["K"]))
    print("t: {}".format(param_dict["t"]))
    print("sigma: \n{}".format(param_dict["sigma"]))
    print("r: {}\n".format(param_dict["r"]))

    # expected implied volatility: is the 'sigma' parameter with which the
    # target price has been generated
    expected_IV = pd.DataFrame(data=param_dict["sigma"],
                               columns=K_vector,
                               index=t_vector)
    print("\nExpected Kxt Implied volatiltiy Surface: \n", expected_IV)

    #
    # Without target_price in input: param_dict['sigma'] parameter is
    # used to construct target price, used in minimization
    #

    print("\n--- WITHOUT target_price in input ---\n")

    # newton method
    newton_IV = option.implied_volatility(**param_dict)
    RMSE_newton = np.sqrt(np.nanmean((newton_IV - expected_IV)**2))
    RMSRE_newton = np.sqrt(
        np.nanmean(((newton_IV - expected_IV) / expected_IV)**2))
    print("\nImplied Volatility - Newton method - Metrics (NaN excluded): RMSE={:.1E}, RMSRE={:.1E}:\n"\
          .format(RMSE_newton, RMSRE_newton), newton_IV)

    # Least=Squares method
    param_dict["minimization_method"] = "Least-Squares"
    ls_IV = option.implied_volatility(**param_dict)
    RMSE_ls = np.sqrt(np.nanmean((ls_IV - expected_IV)**2))
    RMSRE_ls = np.sqrt(np.nanmean(((ls_IV - expected_IV) / expected_IV)**2))

    print("\nImplied Volatility - Newton method - Metrics (NaN excluded): RMSE={:.1E}, RMSRE={:.1E}:\n"\
          .format(RMSE_ls, RMSRE_ls), ls_IV)

    #
    # With target_price in input: target_price, but no param_dict['sigma'],
    # is used in minimization.
    #

    print("\n--- WITH target_price in input ---\n")

    # compute target price
    target_price = option.price(**param_dict)
    print("\nTarget Price in input: \n", target_price)

    # Add target_price to parameters dictionary:
    param_dict['target_price'] = target_price

    # Remove from implied volatility parameters in input the 'sigma' parameter
    # it's not necessary, but this way for sure the .implied_volatility() method
    # is agnostic of the expected implied volatility
    del param_dict['sigma']

    # newton method
    newton_IV = option.implied_volatility(**param_dict)
    RMSE_newton = np.sqrt(np.nanmean((newton_IV - expected_IV)**2))
    RMSRE_newton = np.sqrt(
        np.nanmean(((newton_IV - expected_IV) / expected_IV)**2))
    print("\nImplied Volatility - Newton method - Metrics (NaN excluded): RMSE={:.1E}, RMSRE={:.1E}:\n"\
          .format(RMSE_newton, RMSRE_newton), newton_IV)

    # Least=Squares method
    param_dict["minimization_method"] = "Least-Squares"
    ls_IV = option.implied_volatility(**param_dict)
    RMSE_ls = np.sqrt(np.nanmean((ls_IV - expected_IV)**2))
    RMSRE_ls = np.sqrt(np.nanmean(((ls_IV - expected_IV) / expected_IV)**2))

    print("\nImplied Volatility - Newton method - Metrics (NaN excluded): RMSE={:.1E}, RMSRE={:.1E}:\n"\
          .format(RMSE_ls, RMSRE_ls), ls_IV)
def main():
    
    # Calendar-Spread implementation example
            
    # default market environment
    market_env = MarketEnvironment()
    print(market_env)
    
    # options expirations
    T_short = "31-05-2020"
    T_long = "30-08-2020"
    
    # current underlying level
    S_t = market_env.get_S()

    # calendar-spread portfolio initialized (as empty portfolio)   
    calendar_spread_ptf = Portfolio(name="Calendar Spread Strategy")
    print(calendar_spread_ptf)
    
    # T_long-call
    Vanilla_Call_long = PlainVanillaOption(market_env, T=T_long, K=S_t)
    print(Vanilla_Call_long)

    # T_short-call
    Vanilla_Call_short = PlainVanillaOption(market_env, T=T_short, K=S_t)
    print(Vanilla_Call_short)

    # creation of Calendar-Spread portfolio strategy   
    calendar_spread_ptf.add_instrument(Vanilla_Call_long, 1)
    calendar_spread_ptf.add_instrument(Vanilla_Call_short, -1)    
    print(calendar_spread_ptf)
    
    # portfolio plotter instance
    calendar_spread_ptf_plotter = PortfolioPlotter(calendar_spread_ptf)
    
    # valuation date of the portfolio
    valuation_date = calendar_spread_ptf.get_t()
    print(valuation_date)
        
    # select metrics to plot
    for plot_metrics in ["price", "PnL", "delta", "theta", "gamma", "vega", "rho"]:
        
        plot_details_flag = True if plot_metrics == "price" else False

        # time-parameter as a date-range of 5 valuation dates between t and T_short
        # being the Calendar-Spread a multi-horizon portfolio, time-to-maturity
        # time parameters are not allowed.
        last_date = T_short if plot_metrics in ["price", "PnL"] else date_string_to_datetime_obj(T_short) - pd.Timedelta(days=1)
        multiple_valuation_dates = pd.date_range(start=valuation_date, 
                                                 end=last_date, 
                                                 periods=5)
        print(multiple_valuation_dates)

        # Bull-Spread price plot
        calendar_spread_ptf_plotter.plot(t=last_date, plot_metrics=plot_metrics, 
                                         plot_details=plot_details_flag)
            
        # Plot at multiple dates
        calendar_spread_ptf_plotter.plot(t=multiple_valuation_dates, plot_metrics=plot_metrics)
    
        # Surface plot
        calendar_spread_ptf_plotter.plot(t=multiple_valuation_dates, plot_metrics=plot_metrics, 
                                         surf_plot=True)
    
        # Surface plot (rotate) - Underlying value side
        calendar_spread_ptf_plotter.plot(t=multiple_valuation_dates, plot_metrics=plot_metrics, 
                                         surf_plot=True, view=(0,180))
    
        # Price surface plot (rotate) - Date side
        calendar_spread_ptf_plotter.plot(t=multiple_valuation_dates, plot_metrics=plot_metrics, 
                                         surf_plot=True, view=(0,-90))
def main():

    #
    # portfolio instantiation example
    #

    # if np_output is True, the output will be np.ndarray, otherwise pd.DataFrame
    np_output = False  # True

    # default market environment
    market_env = MarketEnvironment(t="01-06-2020")
    print(market_env)

    # underlying values to test
    S_vector = [60, 90, 120]
    print("S_vector: {}\n".format(S_vector))

    # options maturities
    T_call = "31-12-2020"
    T_put = "30-06-2021"  # T_call

    # choose the kind of time-parameter to use: either a date ('date') or a
    # time-to-maturity ('ttm'). Time-to-maturity time parameter is not allowed
    # for multi-horizon portfolios.
    time_parameter = 'date'  # 'ttm'

    # get time parameter
    t_range = get_time_parameter(market_env,
                                 end_date=min(T_call,
                                              T_put,
                                              key=date_string_to_datetime_obj),
                                 periods=5,
                                 kind=time_parameter,
                                 multi_horizon_ptf=T_call != T_put)

    # options strikes
    K_put = 80
    K_call = 110

    # portfolio options positions
    call_pos = 2
    put_pos = -5

    #
    # Step 0: empty portfolio initialized
    #

    ptf = Portfolio()
    print(ptf)

    #
    # Step 1: adding 2 long plain-vanilla call contracts
    #

    # plain-vanilla call option
    call = PlainVanillaOption(market_env, K=K_call, T=T_call)
    print(call)

    # adding contract to portfolio
    ptf.add_instrument(call, call_pos)
    print(ptf)

    # metrics to compare
    for metrics in ["price", "PnL", "delta", "theta", "gamma", "vega", "rho"]:

        # portfolio metrics
        ptf_metrics = getattr(ptf, metrics)(S=S_vector,
                                            t=t_range,
                                            np_output=np_output)
        print("\nPortfolio {}:\n{}".format(metrics, ptf_metrics))

        # verification with benchmark metrics
        call_metrics = getattr(call, metrics)(S=S_vector,
                                              t=t_range,
                                              np_output=np_output)
        benchmark_metrics = call_pos * call_metrics
        print("\nBenchmark {}:\n{}".format(metrics, benchmark_metrics))

        # check effective match
        diff = (ptf_metrics - benchmark_metrics).astype('float')
        num_nonzero_diff = np.count_nonzero(diff) - np.isnan(diff).sum().sum()
        exact_match = True if num_nonzero_diff == 0 else False
        print(
            "\nIs replication exact (NaN excluded)? {}\n".format(exact_match))

    #
    # Step 2: adding 5 short plain-vanilla put contracts
    #

    # plain-vanilla put option
    put = PlainVanillaOption(market_env, option_type="put", K=K_put, T=T_put)
    print(put)

    # adding contract to portfolio
    ptf.add_instrument(put, put_pos)
    print(ptf)

    # metrics to compare
    for metrics in ["price", "PnL", "delta", "theta", "gamma", "vega", "rho"]:

        # portfolio metrics
        ptf_metrics = getattr(ptf, metrics)(S=S_vector,
                                            t=t_range,
                                            np_output=np_output)
        print("\nPortfolio {}:\n{}".format(metrics, ptf_metrics))

        # verification with benchmark metrics
        call_metrics = getattr(call, metrics)(S=S_vector,
                                              t=t_range,
                                              np_output=np_output)
        put_metrics = getattr(put, metrics)(S=S_vector,
                                            t=t_range,
                                            np_output=np_output)
        benchmark_metrics = call_pos * call_metrics + put_pos * put_metrics
        print("\nBenchmark {}:\n{}".format(metrics, benchmark_metrics))

        # check effective match
        diff = (ptf_metrics - benchmark_metrics).astype('float')
        num_nonzero_diff = np.count_nonzero(diff) - np.isnan(diff).sum().sum()
        exact_match = True if num_nonzero_diff == 0 else False
        print(
            "\nIs replication exact (NaN excluded)? {}\n".format(exact_match))
Beispiel #12
0
def main():

    # vanilla call implementation example

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # define option style and type
    opt_style = "plain_vanilla"  # "digital"
    opt_type = "call"  # "put"
    option = option_factory(market_env, opt_style, opt_type)
    print(option)

    # option plotter instance
    plotter = OptionPlotter(option)

    # valuation date of the option
    emission_date = option.get_t()

    # select dependency to plot as x-axis of the plot
    for dependency_type in ["S", "K", "sigma", "r"]:

        # keyboard parameter and corresponding range to test
        x_axis_dict = options_x_axis_parameters_factory(
            option, dependency_type)

        # appropriate azimut angle for best viewing
        azimut_angle = get_azimut_angle(dependency_type)

        # select metrics to plot
        for plot_metrics in [
                "price", "PnL", "delta", "theta", "gamma", "vega", "rho"
        ]:

            for time_kind in ['date', 'tau']:

                # set time-parameter to plot
                multiple_valuation_dates = get_time_parameter(option,
                                                              kind=time_kind)
                print(multiple_valuation_dates)

                # Surface plot
                plotter.plot(**x_axis_dict,
                             t=multiple_valuation_dates,
                             plot_metrics=plot_metrics,
                             surf_plot=True)

                # Surface plot (rotate) - x-axis side
                plotter.plot(**x_axis_dict,
                             t=multiple_valuation_dates,
                             plot_metrics=plot_metrics,
                             surf_plot=True,
                             view=(0, azimut_angle["x-axis side"]))

                # Price surface plot (rotate) - Date side
                plotter.plot(**x_axis_dict,
                             t=multiple_valuation_dates,
                             plot_metrics=plot_metrics,
                             surf_plot=True,
                             view=(0, azimut_angle["Date side"]))
Beispiel #13
0
def main():

    #
    # option (underlying, time-parameter) instantiation example
    #

    # if np_output is True, the output will be np.ndarray, otherwise pd.DataFrame
    np_output = False  # True

    # default market environment
    market_env = MarketEnvironment()
    print(market_env)

    # define option style and type
    opt_style = "plain_vanilla"  # "digital" # "plain_vanilla"
    opt_type = "call"  # "put"
    option = option_factory(market_env, opt_style, opt_type)
    print(option)

    # loop over different cases:
    for case in ["S_scalar_default.t_scalar_default", \
                 "S_scalar.t_scalar_dt", \
                 "S_scalar.t_scalar_str", \
                 "S_scalar.tau_scalar", \
                 "S_vector.t_scalar_default", \
                 "S_scalar_default.t_date_range", \
                 "S_vector.t_date_range", \
                 "S_vector.t_str_list", \
                 "S_vector.tau_list", \
                 "S_scalar_default.t_scalar_default.sigma_axis", \
                 "S_scalar_default.t_scalar_default.r_axis"]:

        # get parameters dictionary for case considered
        param_dict, case_info = get_param_dict(option, np_output, case)

        not_sigma_axis = ('sigma_axis'
                          not in param_dict) or (param_dict['sigma_axis']
                                                 == False)
        not_r_axis = ('r_axis' not in param_dict) or (param_dict['r_axis']
                                                      == False)

        print("\n--------------------------------------------\n")
        print("\n" + case_info + "\n")

        print("Parameters:")
        print(
            "S: {}".format(param_dict["S"] if "S" in
                           param_dict else str(option.get_S()) + " (default)"))
        print(
            "K: {}".format(param_dict["K"] if "K" in
                           param_dict else str(option.get_K()) + " (default)"))
        print("t: {}".format(param_dict["t"] if "t" in
                             param_dict else str(option.get_tau()) +
                             " (default)"))
        print("sigma: {}".format(param_dict["sigma"] if "sigma" in
                                 param_dict else str(option.get_sigma()) +
                                 " (default)"))
        print("r: {}\n".format(param_dict["r"] if "r" in
                               param_dict else str(option.get_r()) +
                               " (default)"))

        print("Metrics:")
        print("Payoff:\n", option.payoff(**param_dict))
        print("\nPrice upper limit:\n", option.price_upper_limit(**param_dict))
        print("\nPrice lower limit:\n", option.price_lower_limit(**param_dict))
        print("\nPrice:\n", option.price(**param_dict))
        print("\nP&L:\n", option.PnL(**param_dict))
        print("\nDelta:\n", option.delta(**param_dict))
        print("\nTheta:\n", option.theta(**param_dict))
        print("\nGamma:\n", option.gamma(**param_dict))
        print("\nVega:\n", option.vega(**param_dict))
        print("\nRho:\n", option.rho(**param_dict))

        # Implied volatility calculation is not implemented for x-axis (columns)
        # spanned by parameters different from S or K (like sigma or r)
        if not_sigma_axis and not_r_axis:
            print("\nExpected Implied Volatility: \n{}\n"\
                  .format(option.get_sigma()))
            print("\nImplied Volatility - Newton method:\n{}\n"\
                  .format(option.implied_volatility(**param_dict)))
            param_dict["minimization_method"] = "Least-Squares"
            print("\nImplied Volatility - Least-Squares constrained method:\n{}\n"\
                  .format(option.implied_volatility(**param_dict)))