def test_prices(self): while self.tdi.has_next(): row = self.tdi.next_row() S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[ 'v'] self.assertAlmostEqual(black_scholes('c', S, K, t, r, sigma), row['bs_call'], delta=0.000001) self.assertAlmostEqual(black_scholes('p', S, K, t, r, sigma), row['bs_put'], delta=0.000001)
def bs_option_price(connector, underlying, expiration, option_type, strike, current_date, include_riskfree=True): price = None while price is None: current_quote = connector.query_midprice_underlying( underlying, current_date) if current_quote is None: current_date = current_date - timedelta(1) continue expiration_time = datetime.combine(expiration, time(16)) remaining_time_in_years = remaining_time(current_date, expiration_time) rf = interest if include_riskfree: rf = get_riskfree_libor(current_date, remaining_time_in_years) price = black_scholes.black_scholes(option_type, current_quote, strike, remaining_time_in_years, rf, 0.151) return float(price)
def generate_limit_order(self, asset_code, measured_price, volatility, best_ask, best_bid, min_spread=MIN_SPREAD): bs_price = bs.black_scholes(asset_code[0].lower(), self.underlying_price, self.asset_codes[asset_code]["strike"], self.get_time_to_exp(), 0, volatility) # spread, base_price = self.get_spread(bs_price, measured_price, best_ask, best_bid, method="scaled") # spread, base_price = (self.get_spread(volatility, measured_price, method="logistic"), measured_price) # can switch to stoikov easily base_price = measured_price curr_best_spread = best_ask - best_bid spread = _get_spread_logistic(self.asset_codes[asset_code]["vol"], curr_best_spread) # spread = curr_best_spread + 0.02 if spread < min_spread: return # print(spread - curr_best_spread) qty = min(get_qty(spread, abs(base_price - bs_price)), 5) + 1 self.send_order(asset_code, qty, base_price, spread, self.tick) try: self.asset_codes[asset_code][ "vol"] = bs.implied_volatility.implied_volatility( measured_price, self.underlying_price, self.asset_codes[asset_code]["strike"], self.get_time_to_exp(), 0, asset_code[0].lower()) except: pass
def test_implied_volatility(self): while self.tdi.has_next(): row = self.tdi.next_row() S, K, t, r, sigma = row['S'], row['K'], row['t'], row['R'], row[ 'v'] C, P = black_scholes('c', S, K, t, r, sigma), black_scholes('p', S, K, t, r, sigma) try: iv = implied_volatility(C, S, K, t, r, 'c') self.assertAlmostEqual(sigma, iv, delta=0.0001) except: print('could not calculate iv for ', C, S, K, t, r, 'c') iv = implied_volatility(P, S, K, t, r, 'p') self.assertTrue( iv == 0.0) if iv == 0.0 else self.assertAlmostEqual( sigma, iv, delta=0.001)
def generate_limit_order(self, asset_code, measured_price, volatility, best_ask, best_bid, min_spread=MIN_SPREAD): HIST = 4 bs_price = bs.black_scholes(asset_code[0].lower(), self.underlying_price, self.asset_codes[asset_code]["strike"], self.get_time_to_exp(), 0, volatility) # spread, base_price = self.get_spread(bs_price, measured_price, best_ask, best_bid, method="scaled") spread, base_price = (self.get_spread(volatility, measured_price, method="logistic"), measured_price) # can switch to stoikov easily # print(asset_code, spread) if spread < min_spread: return self.send_order(asset_code, get_qty(spread, abs(base_price - bs_price)), base_price, spread, self.tick) self.asset_codes[asset_code][ "vol"] = bs.implied_volatility.implied_volatility( measured_price, self.underlying_price, self.asset_codes[asset_code]["strike"], self.get_time_to_exp(), 0, asset_code[0].lower())
def get_price(row): try: return round( black_scholes('c', row.Price, row.Excercise, row.Date / 360, risk_free, get_volatility(row.Symbol, price_df)), 3) except: return np.nan
def getLowerBreakpointGroup(group, current_date, expiration): expiration_time = datetime.combine(expiration, time(16, 00)) remaining_time_in_years = util.remaining_time(current_date, expiration_time) lowest = group.getLowest().lowerlongposition.option.strike highest = group.getHighest().upperlongposition.option.strike quote = lowest while quote < highest: sum_guv = 0 combos = group.getButterflies() for combo in combos: positions = combo.getPositions() for position in positions: value = black_scholes.black_scholes(position.option.type, quote, position.option.strike, remaining_time_in_years, util.interest, 0) guv = ((value - position.entry_price) * util.ratio * position.amount) sum_guv += guv if (sum_guv > 0): return quote quote += 0.1
def getLowerBreakpoint(combo, current_date, include_riskfree=True): lowest = combo.lowerlongposition.option.strike highest = combo.upperlongposition.option.strike quote = lowest while quote < highest: sum_guv = 0 positions = combo.getPositions() for position in positions: expiration_time = datetime.combine(position.option.expiration, time(16)) remaining_time_in_years = remaining_time(current_date, expiration_time) rf = interest if include_riskfree: rf = get_riskfree_libor(current_date, remaining_time_in_years) value = black_scholes.black_scholes(position.option.type, float(quote), position.option.strike, remaining_time_in_years, rf, 0) guv = ((value - position.entry_price) * ratio * position.amount) sum_guv += guv if (sum_guv > 0): return quote quote += 1
def get_price(attrs): ul_price = attrs['ul_price'] dte = attrs['dte'] strike = attrs['strike'] flag = attrs['flag'] iv = attrs['iv'] price = black_scholes(flag, ul_price, strike, dte/365, interest, iv) return price
def __init_asset_codes(self): asset_codes = {} for code in self.codes: asset_codes[code] = {} asset_codes[code]["strike"] = int(code[1:-3]) asset_codes[code]["vol"] = 8. * abs( math.log(100. / asset_codes[code]["strike"])) asset_codes[code]["price"] = bs.black_scholes( code[0].lower(), 100, asset_codes[code]["strike"], 0.25, 0, asset_codes[code]["vol"]) return asset_codes
def pd_apply(N): from py_vollib.black_scholes.implied_volatility import implied_volatility from py_vollib.black_scholes import black_scholes tt = big_test_df.iloc[:N] tt["price"] = tt.apply(lambda row: black_scholes(row["flag"], row[ "S"], row["K"], row["t"], row["R"], row["v"]), axis=1) tt.apply(lambda row: implied_volatility(row["price"], row["S"], row["K"], row["t"], row["R"], row["flag"]), axis=1)
def test_vs_py_vollib(self): for sigma, r, s0, tm, sk, call in itertools.product( self.sigmas, self.rates, self.spots, self.maturities, self.strikes, self.call): with self.subTest(): np.testing.assert_almost_equal( BlackScholes._option_price(sigma, r, s0, tm, sk, call), black_scholes(flag='c' if call else 'p', S=s0, K=sk, t=tm, r=r, sigma=sigma))
def getUpperExpiration(combo): upper_expiration_line = 0 positions = combo.getPositions() for position in positions: upper_value = black_scholes.black_scholes(position.option.type, upper_ul, position.option.strike, 0, interest, 0) upper_expiration = ((upper_value - position.entry_price) * ratio * position.amount) upper_expiration_line += upper_expiration return upper_expiration_line
def iterrows(N): from py_vollib.black_scholes.implied_volatility import implied_volatility from py_vollib.black_scholes import black_scholes tt = big_test_df.iloc[:N] prices = [] for _, row in tt.iterrows(): prices.append( black_scholes(row["flag"], row["S"], row["K"], row["t"], row["R"], row["v"])) tt["price"] = prices ivs = [] for _, row in tt.iterrows(): ivs.append( implied_volatility(row["price"], row["S"], row["K"], row["t"], row["R"], row["flag"]))
def listcomp(N): from py_vollib.black_scholes.implied_volatility import implied_volatility from py_vollib.black_scholes import black_scholes tt = big_test_df.iloc[:N] prices = [ black_scholes(tt.iloc[i]["flag"], tt.iloc[i]["S"], tt.iloc[i]["K"], tt.iloc[i]["t"], tt.iloc[i]["R"], tt.iloc[i]["v"]) for i in range(len(tt)) ] tt["price"] = prices ivs = [ implied_volatility(tt.iloc[i]["price"], tt.iloc[i]["S"], tt.iloc[i]["K"], tt.iloc[i]["t"], tt.iloc[i]["R"], tt.iloc[i]["flag"]) for i in range(len(tt)) ]
def getUpperExpiration(combo, include_riskfree = True): upper_expiration_line = 0 positions = combo.getPositions() for position in positions: if (position is None) or (position.entry_price is None): return None rf = interest if include_riskfree: rf = get_riskfree_libor(position.option.expiration, 0) upper_value = black_scholes.black_scholes(position.option.type, upper_ul, position.option.strike, 0, rf, 0) upper_expiration = ((upper_value - position.entry_price) * ratio * position.amount) upper_expiration_line += upper_expiration return upper_expiration_line
def for_loop(N): from py_vollib.black_scholes.implied_volatility import implied_volatility from py_vollib.black_scholes import black_scholes tt = big_test_df.iloc[:N] prices = [] for i in range(len(tt)): prices.append( black_scholes(tt.iloc[i]["flag"], tt.iloc[i]["S"], tt.iloc[i]["K"], tt.iloc[i]["t"], tt.iloc[i]["R"], tt.iloc[i]["v"])) tt["price"] = prices ivs = [] for i in range(len(tt)): ivs.append( implied_volatility(tt.iloc[i]["price"], tt.iloc[i]["S"], tt.iloc[i]["K"], tt.iloc[i]["t"], tt.iloc[i]["R"], tt.iloc[i]["flag"]))
def on_update(msg, order): now = time.time() global tick ms = msg['market_state'] tck = ms['ticker'] last_price = msg['market_state']['last_price'] tickers[tck]['price'].append(last_price) tick += 1 if tck == fut: return S = tickers[fut]['price'][-1] if len(tickers[fut]['price']) > 0 else None K = int(tck[1:4]) if len(tck) == 5 else int(tck[1:3]) t = (450 - tick) / 450 * 1 / 12 flag = 'c' if tck[-1] == 'C' else 'p' if S is not None: try: iv = implied_volatility.implied_volatility(last_price, S, K, t, r, flag) theo_p = black_scholes.black_scholes(flag, S, K, t, r, iv) delta = analytical.delta(flag, S, K, t, r, iv) gamma = analytical.gamma(flag, S, K, t, r, iv) # vega = analytical.vega(flag,S,K,t,r,iv) tickers[tck]['vol'].append(vol) tickers[tck]['delta'].append(delta) tickers[tck]['gamma'].append(gamma) # tickers[tck]['vega'].append(vega) if len(tickers[tck]['vol']) > 5: vol_sma = np.mean(np.array(ticker[tck]['vol'][-6:-1])) if abs(iv - vol_sma) / vol_sma > .015: if iv > vol_sma: order.addSell(tck, 10, last_price + dx) else: order.addBuy(tck, 10, last_price - dx) except: print(S, K, last_price, flag)
def getExpiration(combo, underlying_value, include_riskfree=True): expiration_line = 0 positions = combo.getPositions() for position in positions: if (position is None) or (position.entry_price is None): return None rf = interest if include_riskfree: rf = get_riskfree_libor(position.option.expiration, 0) value = black_scholes.black_scholes(position.option.type, underlying_value, position.option.strike, 0, rf, 0) expiration = ( (value - position.entry_price) * ratio * position.amount - (commissions * (abs(position.amount)))) expiration_line += expiration return expiration_line
def precompute(table, computedate, underlying, include_riskfree): db = psycopg2.connect(host="localhost", user=settings.db_username, password=settings.db_password, database="optiondata") cur2 = db.cursor() underlying_fragment = "" if (underlying != "*"): underlying_fragment = "underlying_symbol = '" + underlying + "' AND " date_fragment = "" if (computedate != "*"): date_fragment = "quote_date = '" + str(computedate) + "' AND " query = "SELECT id, quote_date, underlying_mid_1545, mid_1545, expiration, strike, option_type FROM " + \ table + " WHERE " + underlying_fragment + date_fragment + "iv IS NULL" cur2.execute(query) result = cur2.fetchall() print( str(computedate) + " " + str(underlying) + ": " + str(len(result)) + " results") bulkrows = [] if (len(result) > 0): for row in result: rowid = row[0] quote_date = row[1] underlying_mid_1545 = float(row[2]) mid_1545 = float(row[3]) expiration = row[4] strike = float(row[5]) option_type = row[6] expiration_time = datetime.datetime.combine( expiration, datetime.time(16, 0)) remaining_time_in_years = util.remaining_time( quote_date, expiration_time) rf = util.interest if include_riskfree: rf = util.get_riskfree_libor(quote_date, remaining_time_in_years) try: iv = implied_volatility.implied_volatility( mid_1545, underlying_mid_1545, int(strike), remaining_time_in_years, rf, option_type) except: iv = 0.001 try: bs_price_bid_ask = black_scholes(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) except: bs_price_bid_ask = 0.001 try: delta = analytical.delta(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: delta = 0.001 try: theta = analytical.theta(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: theta = 0.001 try: vega = analytical.vega(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) * 100 except: vega = 0.001 bulkrows.append({ 'iv': iv, 'bs_price_bid_ask': bs_price_bid_ask, 'delta': delta, 'theta': theta, 'vega': vega, 'rowid': rowid }) psycopg2.extras.execute_batch( cur2, """UPDATE """ + table + """ SET iv=%(iv)s, bs_price_bid_ask=%(bs_price_bid_ask)s, delta=%(delta)s, theta=%(theta)s, vega=%(vega)s WHERE id=%(rowid)s""", bulkrows, page_size=100) db.commit() db.close()
def getExpectedValue(connector, underlying, combo, current_date, expiration): current_quote = connector.query_midprice_underlying( underlying, current_date) expiration_time = datetime.combine(expiration, time(16)) remaining_time_in_years = util.remaining_time(current_date, expiration_time) ul_for_ew = [] sum_legs = [] prob_touch = [] if (current_quote % 10) < 5: atm_strike = int(current_quote / 10) * 10 else: atm_strike = int((current_quote + 10) / 10) * 10 try: atm_option = util.Option(connector, current_date, underlying, atm_strike, expiration, "p") except ValueError: return "missing data" midprice = connector.query_midprice(current_date, atm_option) try: atm_iv = implied_volatility.implied_volatility( midprice, current_quote, atm_strike, remaining_time_in_years, util.interest, atm_option.type) except pyex.BelowIntrinsicException: atm_iv = 0.01 if (atm_iv == 0): atm_iv = 0.01 # print atm_iv one_sd = (atm_iv / math.sqrt( util.yeartradingdays / (remaining_time_in_years * util.yeartradingdays))) * current_quote lower_ul = current_quote - e_spanne * one_sd upper_ul = current_quote + e_spanne * one_sd step = (upper_ul - lower_ul) / 24 # war 1000 for i in range(25): # war 1001 ul_for_ew.insert(i, lower_ul + (i * step)) sum_legs_i = 0 positions = combo.getPositions() for position in positions: # param sigma: annualized standard deviation, or volatility # https://www.etfreplay.com/etf/iwm.aspx value = black_scholes.black_scholes(position.option.type, ul_for_ew[i], position.option.strike, remaining_time_in_years, util.interest, 0) guv = (value - position.entry_price) * ratio * position.amount sum_legs_i += guv sum_legs.insert(i, sum_legs_i) prob = util.prob_hit(current_quote, ul_for_ew[i], remaining_time_in_years, 0, atm_iv) prob_touch.insert(i, prob) sumproduct = sum([a * b for a, b in zip(sum_legs, prob_touch)]) expected_value = round((sumproduct / sum(prob_touch)), 2) return expected_value
def precompute(table, computedate, underlying, include_riskfree): # start = time.time() db = psycopg2.connect(host="localhost", user=settings.db_username, password=settings.db_password, database="optiondata") cur2 = db.cursor() underlying_fragment = "" if (underlying != "*"): underlying_fragment = "underlying_symbol = '" + underlying + "' AND " date_fragment = "" if (computedate != "*"): date_fragment = "quote_date = '" + str(computedate) + "' AND " query = "SELECT id, quote_date, underlying_mid_1545, mid_1545, expiration, strike, option_type FROM " + table + " WHERE " + underlying_fragment + date_fragment + "bs_price_bid_ask IS NULL" cur2.execute(query) result = cur2.fetchall() print (str(computedate) + " " + str(underlying) + ": " + str(len(result)) + " results") bulkrows = [] if (len(result) > 0): for row in result: rowid = row[0] quote_date = row[1] underlying_mid_1545 = float(row[2]) mid_1545 = float(row[3]) expiration = row[4] strike = float(row[5]) option_type = row[6] expiration_time = datetime.datetime.combine(expiration, datetime.time(16, 0)) remaining_time_in_years = util.remaining_time(quote_date, expiration_time) rf = util.interest if include_riskfree: rf = util.get_riskfree_libor(quote_date, remaining_time_in_years) try: iv = implied_volatility.implied_volatility(mid_1545, underlying_mid_1545, int(strike), remaining_time_in_years, rf, option_type) except: iv = 0.001 if underlying_mid_1545 == 0: underlying_mid_1545 = 0.01 bs_price_bid_ask = black_scholes(option_type, underlying_mid_1545, strike, remaining_time_in_years, rf, iv) # print (bs_price_bid_ask) bulkrows.append({'bs_price_bid_ask': bs_price_bid_ask, 'rowid': rowid}) try: psycopg2.extras.execute_batch(cur2, """UPDATE """ + table + """ SET bs_price_bid_ask=%(bs_price_bid_ask)s WHERE id=%(rowid)s""", bulkrows, page_size=100) db.commit() except Exception as e: print("an exception occurred") print(e) print (query) # end = time.time() # print (end - start) print () db.close()
def getExpectedValue(underlying, combo, current_date, expiration, use_precomputed=True, include_riskfree=True): current_quote_original = util.connector.query_midprice_underlying( underlying, current_date) if (current_quote_original is None): return None current_quote = float(current_quote_original) if (current_quote == 0.0): return None expiration_time = datetime.combine(expiration, time(16)) remaining_time_in_years = util.remaining_time(current_date, expiration_time) ul_for_ew = [] sum_legs = [] prob_touch = [] if (current_quote % 10) < 5: atm_strike = int(current_quote / 10) * 10 else: atm_strike = int((current_quote + 10) / 10) * 10 if use_precomputed: try: atm_iv = float( util.connector.select_iv(current_date, underlying, expiration, "p", atm_strike)) except: atm_iv = 0.01 else: try: atm_option = util.Option(current_date, underlying, atm_strike, expiration, "p") except ValueError: return None midprice = util.connector.query_midprice(current_date, atm_option) rf = util.interest if include_riskfree: rf = util.get_riskfree_libor(current_date, remaining_time_in_years) try: atm_iv = float( implied_volatility.implied_volatility(midprice, current_quote, atm_strike, remaining_time_in_years, rf, atm_option.type)) except: atm_iv = 0.01 if (atm_iv == 0): atm_iv = 0.01 one_sd = (atm_iv / math.sqrt( util.yeartradingdays / (remaining_time_in_years * util.yeartradingdays))) * current_quote lower_ul = current_quote - e_spanne * one_sd upper_ul = current_quote + e_spanne * one_sd step = (upper_ul - lower_ul) / 24 # war 1000 for i in range(25): # war 1001 ul_for_ew.insert(i, lower_ul + (i * step)) sum_legs_i = 0 positions = combo.getPositions() for position in positions: # param sigma: annualized standard deviation, or volatility # https://www.etfreplay.com/etf/iwm.aspx rf = util.interest if include_riskfree: rf = util.get_riskfree_libor(current_date, remaining_time_in_years) value = black_scholes.black_scholes(position.option.type, ul_for_ew[i], position.option.strike, remaining_time_in_years, rf, 0) guv = (value - position.entry_price) * ratio * position.amount sum_legs_i += guv sum_legs.insert(i, sum_legs_i) prob = util.prob_hit(current_quote, ul_for_ew[i], remaining_time_in_years, 0, atm_iv) prob_touch.insert(i, prob) sumproduct = sum([a * b for a, b in zip(sum_legs, prob_touch)]) expected_value = round((sumproduct / sum(prob_touch)), 2) return expected_value
def plot_risk_graph(options_data, S, r, save_png=False): ''' Creates a risk graph for the combination of options provided in the input list of options for the different times to expiration provided inputs: options_data -> options data composing the strategy. It is important to provide this list ordered by near-term expiries first S -> current underlying price r -> interest rate on a 3-month U.S. Treasury bill or similar save_png -> determines if the plot is saved as a PNG file (default False) returns: list of tuples (x, (datetime, y)) ''' # Get the list of options from options_data options_list = options_data['options'] # First get the graph bounds, 10% apart from the min and max strikes min_strike = None max_strike = None for opt in options_list: if (min_strike is None) or (opt['strike'] < min_strike): min_strike = opt['strike'] if (max_strike is None) or (opt['strike'] > max_strike): max_strike = opt['strike'] # Make sure current underlying price is into the range if min_strike > S: min_strike = S if max_strike < S: max_strike = S # Determine front expiration date front_expiration = None back_expiration = None for opt in options_list: aux_date = datetime.strptime(opt['expiration_date'], '%d/%m/%Y') if (front_expiration is None) or (aux_date < front_expiration): front_expiration = aux_date if (back_expiration is None) or (aux_date > back_expiration): back_expiration = aux_date # Prices vector strike_spread = max_strike - min_strike x_vector = np.linspace(min_strike - strike_spread * 0.1, max_strike + strike_spread * 0.1, 500) # Now plot the risk graph for the different time values provided return_values = [] y = [] for t in [datetime.today(), front_expiration, back_expiration]: y_vector = np.zeros(len(x_vector)) y_vector.fill(options_data['meta']['amount'] * options_data['meta']['multiplier'] * options_data['meta']['premium'] - options_data['meta']['commisions']) y.append(y_vector) # Create the discrete values of P/L to plot against xrange for opt in options_list: # Get time to expiration in years days_to_expire = ( datetime.strptime(opt['expiration_date'], '%d/%m/%Y') - t).days t_exp = days_to_expire / 365. if t_exp >= 0: # Calculate IV from latest option price iv = bsiv.implied_volatility(opt['last_price'], S, opt['strike'], t_exp, r, opt['right'].lower()) # Calculate option price using black-scholes given that IV y[-1] += np.array([ options_data['meta']['amount'] * options_data['meta']['multiplier'] * opt['amount'] * bs.black_scholes(opt['right'].lower(), x, opt['strike'], t_exp, r, iv) for x in x_vector ]) # Get the number of days to expiration from today for plot's legend plt.plot(x_vector, y[-1], label='t: ' + str(days_to_expire)) return_values.append((t, y[-1])) # Plot a vertical line where the underlying is currently trading at plt.axvline(S, color='r') # Plot zero horizontal line plt.axhline(0, color='k', linestyle='dashed') plt.legend() plt.xlabel('Price') plt.ylabel('P/L') # Save the plot as a PNG if required, or show plot in a window if save_png: plt.savefig(datetime.today().strftime(options_data.meta.ticker + '_%d%b%y.png')) else: # Show the plot plt.show() # Return the values calculated TODO for what? to calculate breakevens? return (x_vector, return_values)
from py_vollib.black_scholes.greeks.analytical import * from py_vollib.black_scholes import black_scholes import datetime import pandas as pd tday = datetime.date.today() expiry = datetime.date(2020, 9, 18) output = [] multiplier = 1000 for t in range(1, (expiry - tday).days): for S in range(200, 351): delta_calc = delta("c", S, 280, t / 365, 0.05, 0.3) * multiplier gamma_calc = gamma("c", S, 280, t / 365, 0.05, 0.3) * multiplier theta_calc = theta("c", S, 280, t / 365, 0.05, 0.3) * multiplier vega_calc = vega("c", S, 280, t / 365, 0.05, 0.3) * multiplier value = black_scholes("c", S, 280, t / 365, 0.05, 0.3) * multiplier output.append((delta_calc, gamma_calc, theta_calc, vega_calc, value, expiry - datetime.timedelta(days=t), S)) output = pd.DataFrame( output, columns=['delta', 'gamma', 'theta', 'vega', 'value', 't', 'spot']) output.index = [output['t'], output['spot']] output = output.stack().reset_index() output.columns = ['date', 'spot', 'plot_type', 'value'] output.to_csv("spx_test.csv")
from py_vollib.black_scholes import black_scholes from py_vollib.helpers.numerical_greeks import delta as numerical_delta from py_vollib.helpers.numerical_greeks import vega as numerical_vega from py_vollib.helpers.numerical_greeks import theta as numerical_theta from py_vollib.helpers.numerical_greeks import rho as numerical_rho from py_vollib.helpers.numerical_greeks import gamma as numerical_gamma from py_vollib.black_scholes.greeks.analytical import gamma as agamma from py_vollib.black_scholes.greeks.analytical import delta as adelta from py_vollib.black_scholes.greeks.analytical import vega as avega from py_vollib.black_scholes.greeks.analytical import rho as arho from py_vollib.black_scholes.greeks.analytical import theta as atheta # ----------------------------------------------------------------------------- # FUNCTIONS - NUMERICAL GREEK CALCULATION f = lambda flag, S, K, t, r, sigma, b: black_scholes(flag, S, K, t, r, sigma) def delta(flag, S, K, t, r, sigma): """Return Black-Scholes delta of an option. :param S: underlying asset price :type S: float :param K: strike price :type K: float :param sigma: annualized standard deviation, or volatility :type sigma: float :param t: time to expiration in years :type t: float :param r: risk-free interest rate :type r: float