def main(): # if np_output is True, the output will be np.ndarray, otherwise pd.DataFrame np_output = False # True t = "30-04-2021" r = 0.10 S = 14661 sigma = 0.2375 # sigma = 0.23 K = 14600 T = "06-05-2021" # default market environment market_env = MarketEnvironment(t, r, S, sigma) # print(market_env) # define option style and type opt_style = "plain_vanilla" # "digital" # "plain_vanilla" opt_type = "put" # "put" option = option_factory(market_env, opt_style, opt_type, K, T) # print(option) # CalcualtePricesForRange(S, option) # print("Metrics:") # print("Payoff:", option.payoff()) # print("Price upper limit:", option.price_upper_limit()) # print("Price lower limit:", option.price_lower_limit()) print("Price:", option.price()) print("P&L:", option.PnL()) print("Delta:", option.delta()) print("Theta:", option.theta()) print("Gamma:", option.gamma()) print("Vega:", option.vega()) print("Rho:", option.rho())
def main(): # numeric greeks example # default market environment market_env = MarketEnvironment() print(market_env) # define option style and type opt_style = "plain_vanilla" # "digital" opt_type = "call" # "call" option = option_factory(market_env, opt_style, opt_type) print(option) # numeric greeks instance NumGreeks = NumericGreeks(option) # underlying range at which compute greeks S_range = np.linspace(50, 150, 2000) # 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) # select greek for greek_type in ["delta", "theta", "gamma", "vega", "rho"]: # # greek Vs Underlying level S # # numeric greek calculation 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") # plot title plot_title_S = greeks_title_factory(option, greek_type) # plot plot(x=S_range, f=greek_numeric_Vs_S, x_label=r"$S$", f_label=label_numeric_S, title=plot_title_S) # # greek Vs residual time to maturity tau # # numeric greek calculation 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") # plot title plot_title_tau = greeks_title_factory(option, greek_type, underlying=r"\tau") # plot plot(x=tau_range, f=greek_numeric_Vs_tau, x_label=r"$\tau$", f_label=label_numeric_tau, title=plot_title_tau)
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))
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'] is 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)
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) # 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"]))
def CreateExpectedSpotLists(OptionType, currSymbol="Sheet1"): data = pd.read_excel(OptionsConstants.Location + "\\" + OptionsConstants.TradeDate + "\\" + OptionType + "_" + OptionsConstants.FileSuffix + ".xlsx", sheet_name=currSymbol) OutputList = [] for index, row in data.iterrows(): t = OptionsConstants.TradeDate r = 0.1 S = row['underlyingValue'] sigma = float((row['impliedVolatility']) / 100) K = row['strikePrice'] T = (datetime.datetime.strptime(row['expiryDate'], '%d-%b-%Y')).strftime('%d-%m-%Y') # default market environment market_env = MarketEnvironment(t, r, S, sigma) # define option style and type opt_style = "plain_vanilla" # "digital" # "plain_vanilla" opt_type = OptionType option = option_factory(market_env, opt_style, opt_type, K, T) ProjectedPriceList = CalcualtePricesForRange(S, option) OutputList.append({ 'OptionType': OptionType, 'StrikePrice': row['strikePrice'], 'Underlying': row['underlyingValue'], 'LastPrice': row['lastPrice'], 'ExpiryDate': row['expiryDate'], 'ProjectedSpot': ProjectedPriceList }) newCalldf = pd.DataFrame(OutputList).dropna() filemode = 'w' if (os.path.exists(OptionsConstants.Location + "\\" + OptionsConstants.TradeDate + "\\" + OptionType + "Projected_" + OptionsConstants.FileSuffix + ".xlsx")): filemode = 'a' with pd.ExcelWriter(OptionsConstants.Location + "\\" + OptionsConstants.TradeDate + "\\" + OptionType + "Projected_" + OptionsConstants.FileSuffix + ".xlsx", engine='openpyxl', mode=filemode) as writer: newCalldf.to_excel(writer, sheet_name=currSymbol, index=False) return (OutputList)
def setPortfolio(): mktEnv = MarketEnvironment() # strikes kl = 90 ks = 110 print(mktEnv) option_spread_ptf = Portfolio(name="Option Spread") print(option_spread_ptf) # 90-call vcl = PlainVanillaOption(mktEnv, K=kl, T='31-12-2021') print(vcl) vcs = PlainVanillaOption(mktEnv, K=ks, T='31-12-2021') print(vcs) # creation of bull-spread portfolio strategy option_spread_ptf.add_instrument(vcl, 1) option_spread_ptf.add_instrument(vcs, -1) print(option_spread_ptf)
def setUp(self) -> None: warnings.filterwarnings("ignore") # common market environment mkt_env = MarketEnvironment(t="01-06-2020") # underlying values to test S_vector = [60, 90, 120] # options maturities T_call = "31-12-2020" T_put = "30-06-2021" # time parameter t_range = pd.date_range(start=mkt_env.get_t(), end=T_call, periods=3) # pricing parameters self.params = {"S": S_vector, "t": t_range, "np_output": False} # options strikes K_put = 80 K_call = 110 # portfolio options positions self.call_pos = 2 self.put_pos = -5 # empty portfolio initialized self.ptf = Portfolio() # adding 2 long plain-vanilla call contracts self.call_opt = PlainVanillaOption(mkt_env, K=K_call, T=T_call) # adding 5 short plain-vanilla put contracts self.put_opt = PlainVanillaOption(mkt_env, option_type="put", K=K_put, T=T_put) # adding contracts to portfolio self.ptf.add_instrument(self.call_opt, self.call_pos) self.ptf.add_instrument(self.put_opt, self.put_pos)
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))
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"]))
def main(): # output format: pd.DataFrame np_output = False # choose whether to plot expected IV or reconstructed one (takes longer) plot_expected_iv = True # 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 = np.linspace(50, 150, 100) # 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) expected_IV.rename_axis('K', axis='columns', inplace=True) expected_IV.rename_axis('t', axis='rows', inplace=True) print("\nExpected Kxt Implied volatility Surface: \n", expected_IV) if plot_expected_iv: IV_plot = expected_IV else: # 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 # 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 - Least-Squares constrained method - Metrics (NaN excluded): RMSE={:.1E}, " "RMSRE={:.1E}:\n".format(RMSE_ls, RMSRE_ls), ls_IV) IV_plot = ls_IV # option plotter instance plotter = OptionPlotter(option) plotter.plot(plot_metrics="implied_volatility", IV=IV_plot)
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" # options strikes are the same: single-strike portfolio can be evaluated # at different strike-price too 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))
def test_ReadURL(self): # url = "https://www.nseindia.com/api/option-chain-indices?symbol=NIFTY" # # url = "https://www.nseindia.com/get-quotes/derivatives?symbol=NIFTY&identifier=OPTIDXNIFTY" # headers = { # 'User-agent': 'Mozilla/5.0' # } # t = requests.get(url,headers=headers) # # print(t.text) # test = t.json() # # path="100%.data.expiryDate" # # for expiryDate in test.values(): # # try: # # print(expiryDate) # # except KeyError: # # temp="dummy" # # print(test["records"]["data"]) with open('C:\\Users\\srepswal\\Desktop\\test.json') as f: data = json.load(f) df = pd.DataFrame(list(data["records"]["data"][0:]),columns=['PE','CE']).dropna() df2 = pd.DataFrame(df['PE'].values.tolist()) df2 = df2[(df2['openInterest']>2000) & (df2['impliedVolatility']>0 )& (df2['totalTradedVolume']>2000 )] df3 = pd.DataFrame(df['CE'].values.tolist()) df3 = df3[(df3['openInterest'] > 2000) & (df3['impliedVolatility']>0) & (df3['totalTradedVolume']>2000 )] # print(data["records"]["data"][0]["PE"]["openInterest"]) with pd.ExcelWriter("C:\\Users\\srepswal\\PycharmProjects\\EquityModelling\\Main\\DriverObject\\Trading\\Data\\Option\\02Apr2021\\temp.xlsx", engine='xlsxwriter') as writer: df2.to_excel(writer, index=False) with pd.ExcelWriter( "C:\\Users\\srepswal\\PycharmProjects\\EquityModelling\\Main\\DriverObject\\Trading\\Data\\Option\\02Apr2021\\call.xlsx", engine='xlsxwriter') as writer: df3.to_excel(writer, index=False) callList = [] for index, row in df3.iterrows(): print(row['strikePrice'], row['lastPrice'],row['impliedVolatility'],row['expiryDate']) t = "26-03-2021" r = 0.03 S = row['underlyingValue'] sigma = row['impliedVolatility']/100 K = row['strikePrice'] T =(datetime.datetime.strptime(row['expiryDate'], '%d-%b-%Y')).strftime('%d-%m-%Y') # default market environment market_env = MarketEnvironment(t, r, S, sigma) # 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, K, T) ProjectedPriceList =CalcualtePricesForRange(S, option) callList.append( {'OptionType': 'Call', 'StrikePrice': row['strikePrice'], 'Underlying': row['underlyingValue'], 'LastPrice': row['lastPrice'], 'ExpiryDate': row['expiryDate'], 'ProjectedSpot': ProjectedPriceList}) newCalldf= pd.DataFrame(callList).dropna() with pd.ExcelWriter( "C:\\Users\\srepswal\\PycharmProjects\\EquityModelling\\Main\\DriverObject\\Trading\\Data\\Option\\02Apr2021\\CallProjected.xlsx", engine='xlsxwriter') as writer: newCalldf.to_excel(writer, index=False) putList = [] for index, row in df2.iterrows(): print(row['strikePrice'], row['lastPrice'], row['impliedVolatility'], row['expiryDate']) t = "01-04-2021" r = 0.03 S = row['underlyingValue'] sigma = row['impliedVolatility'] / 100 K = row['strikePrice'] T = (datetime.datetime.strptime(row['expiryDate'], '%d-%b-%Y')).strftime('%d-%m-%Y') # default market environment market_env = MarketEnvironment(t, r, S, sigma) # print(market_env) # define option style and type opt_style = "plain_vanilla" # "digital" # "plain_vanilla" opt_type = "put" # "put" option = option_factory(market_env, opt_style, opt_type, K, T) ProjectedPriceList = CalcualtePricesForRange(S, option) putList.append( {'OptionType': 'Put', 'StrikePrice': row['strikePrice'], 'Underlying': row['underlyingValue'], 'LastPrice': row['lastPrice'], 'ExpiryDate': row['expiryDate'], 'ProjectedSpot': ProjectedPriceList}) newPutdf = pd.DataFrame(putList).dropna() with pd.ExcelWriter( "C:\\Users\\srepswal\\PycharmProjects\\EquityModelling\\Main\\DriverObject\\Trading\\Data\\Option\\02Apr2021\\PutProjected.xlsx", engine='xlsxwriter') as writer: newPutdf.to_excel(writer, index=False) # CalculateMaxLossAndMinProfit(callList,putList) CalculateLossAndProfit(callList, putList)
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" # "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'] is False) not_r_axis = ('r_axis' not in param_dict) or (param_dict['r_axis'] is 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)))
def CreateSpotListsWithGreeks(OptionType, currSymbol="Sheet1"): data = pd.read_excel(OptionsConstants.Location + "\\" + OptionsConstants.TradeDate + "\\" + OptionType + "_" + OptionsConstants.FileSuffix + ".xlsx", sheet_name=currSymbol) OutputList = [] # OutputList[OptionType+'_Delta']=0.000000 # OutputList[OptionType + '_Theta'] = 0.000000 # OutputList[OptionType + '_Gamma'] = 0.000000 # OutputList[OptionType + '_Vega'] = 0.000000 # OutputList[OptionType + '_Rho'] = 0.000000 for index, row in data.iterrows(): t = OptionsConstants.TradeDate r = 0.1 S = row['underlyingValue'] sigma = float((row['impliedVolatility']) / 100) K = row['strikePrice'] T = (datetime.datetime.strptime(row['expiryDate'], '%d-%b-%Y')).strftime('%d-%m-%Y') # default market environment market_env = MarketEnvironment(t, r, S, sigma) # define option style and type opt_style = "plain_vanilla" # "digital" # "plain_vanilla" opt_type = OptionType option = option_factory(market_env, opt_style, opt_type, K, T) Delta = option.delta() Theta = option.theta() Gamma = option.gamma() Vega = option.vega() Rho = option.rho() OutputList.append({ 'OptionType': OptionType, 'StrikePrice': row['strikePrice'], 'Underlying': row['underlyingValue'], 'LastPrice': row['lastPrice'], 'ExpiryDate': row['expiryDate'], OptionType + '_Delta': '%.4f' % float(option.delta()[0]), OptionType + '_Theta': '%.4f' % float(option.theta()[0]), OptionType + '_Gamma': '%.4f' % float(option.gamma()[0]), OptionType + '_Vega': '%.4f' % float(option.vega()[0]), OptionType + '_Rho': '%.4f' % float(option.rho()[0]) }) newCalldf = pd.DataFrame(OutputList).dropna() filemode = 'w' if (os.path.exists(OptionsConstants.Location + "\\" + OptionsConstants.TradeDate + "\\" + OptionType + "Greeks" + OptionsConstants.FileSuffix + ".xlsx")): filemode = 'a' with pd.ExcelWriter(OptionsConstants.Location + "\\" + OptionsConstants.TradeDate + "\\" + OptionType + "Greeks" + OptionsConstants.FileSuffix + ".xlsx", engine='openpyxl', mode=filemode) as writer: newCalldf.to_excel(writer, sheet_name=currSymbol, index=False) return (OutputList)
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) expected_IV.rename_axis('K', axis='columns', inplace=True) expected_IV.rename_axis('t', axis='rows', inplace=True) print("\nExpected Kxt Implied volatility 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 param_dict["minimization_method"] = "Newton" 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 - Least-Squares constrained 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 # newton method param_dict["minimization_method"] = "Newton" 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 - Least-Squares constrained method - Metrics (NaN excluded): RMSE={:.1E}, RMSRE={:.1E}:\n" .format(RMSE_ls, RMSRE_ls), ls_IV)