def get_delta(symbol: str, percent_move: float, expiry: str): s = Stock(symbol) up_px = s.price * (1 + percent_move / 100) down_px = s.price * (1 - percent_move / 100) call = Call(symbol, d=int(expiry[0:2]), m=int(expiry[3:5]), y=int(expiry[6:10])) up_delta_dict = get_strike_bracket(call.strikes, up_px) call.set_strike(up_delta_dict['lower_strike']) delta1 = call.delta() * up_delta_dict['lower_weight'] call.set_strike(up_delta_dict['higher_strike']) delta2 = call.delta() * (1 - up_delta_dict['lower_weight']) delta_up_move = delta1 + delta2 put = Put(symbol, d=int(expiry[0:2]), m=int(expiry[3:5]), y=int(expiry[6:10])) down_delta_dict = get_strike_bracket(put.strikes, down_px) put.set_strike(down_delta_dict['lower_strike']) delta1 = -put.delta() * down_delta_dict['lower_weight'] put.set_strike(down_delta_dict['higher_strike']) delta2 = -put.delta() * (1 - down_delta_dict['lower_weight']) delta_down_move = delta1 + delta2 return {'delta_up': delta_up_move, 'delta_down': delta_down_move}
def get_delta(symbol: str, percent_move: float, expiry: str): symbol = symbol.upper() if is_cache_good(f'{symbol}|getdelta|{percent_move:.2f}|{expiry}'): return ast.literal_eval( r.hget(f'{symbol}|getdelta|{percent_move:.2f}|{expiry}', 'value')) s = Stock(symbol) up_px = s.price * (1 + percent_move / 100) down_px = s.price * (1 - percent_move / 100) call = Call(symbol, d=int(expiry[0:2]), m=int(expiry[3:5]), y=int(expiry[6:10])) up_delta_dict = get_strike_bracket(call.strikes, up_px) call.set_strike(up_delta_dict['lower_strike']) delta1 = call.delta() * up_delta_dict['lower_weight'] call.set_strike(up_delta_dict['higher_strike']) delta2 = call.delta() * (1 - up_delta_dict['lower_weight']) delta_up_move = delta1 + delta2 put = Put(symbol, d=int(expiry[0:2]), m=int(expiry[3:5]), y=int(expiry[6:10])) down_delta_dict = get_strike_bracket(put.strikes, down_px) put.set_strike(down_delta_dict['lower_strike']) delta1 = -put.delta() * down_delta_dict['lower_weight'] put.set_strike(down_delta_dict['higher_strike']) delta2 = -put.delta() * (1 - down_delta_dict['lower_weight']) delta_down_move = delta1 + delta2 return_dict = {'delta_up': delta_up_move, 'delta_down': delta_down_move} r.hset(f'{symbol}|getdelta|{percent_move:.2f}|{expiry}', 'time', datetime.utcnow().strftime('%s')) r.hset(f'{symbol}|getdelta|{percent_move:.2f}|{expiry}', 'value', str(return_dict)) return return_dict
def get_atm_ivol(s, ndays=30): #Need to fix for divs, borrow etc to find atm symbol = s.ticker expiry_dict = get_expiries_bracket(symbol, ndays) #First Shorter One x = expiry_dict['shorter_expiry'] shorter_call = Call(symbol, d=int(x[0:2]), m=int(x[3:5]), y=int(x[6:10])) strike_dict = get_strike_bracket(shorter_call.strikes, s.price) shorter_call.set_strike(strike_dict['lower_strike']) lower_vol = shorter_call.implied_volatility() shorter_call.set_strike(strike_dict['higher_strike']) higher_vol = shorter_call.implied_volatility() shorter_ivol = lower_vol * strike_dict['lower_weight'] + higher_vol * ( 1 - strike_dict['lower_weight']) #Now longer One x = expiry_dict['longer_expiry'] longer_call = Call(symbol, d=int(x[0:2]), m=int(x[3:5]), y=int(x[6:10])) strike_dict = get_strike_bracket(longer_call.strikes, s.price) longer_call.set_strike(strike_dict['lower_strike']) lower_vol = longer_call.implied_volatility() longer_call.set_strike(strike_dict['higher_strike']) higher_vol = longer_call.implied_volatility() longer_ivol = lower_vol * strike_dict['lower_weight'] + higher_vol * ( 1 - strike_dict['lower_weight']) implied_ivol = shorter_ivol * expiry_dict[ 'shorter_weight'] + longer_ivol * (1 - expiry_dict['shorter_weight']) one_sigma_move_ndays_day = implied_ivol * math.sqrt(ndays / 365) return (implied_ivol, one_sigma_move_ndays_day)
def implied_forward(symbol, n_days): s = Stock(symbol) c = Call(symbol) curr_date = str(datetime.date(datetime.now())) expiries = c.expirations expiry_to_use = expiries[0] my_n_days = 0 for i in expiries: days_to_exp = abs( datetime.strptime(i, '%d-%m-%Y') - datetime.strptime(curr_date, '%Y-%m-%d')).days expiry_to_use = i my_n_days = days_to_exp if days_to_exp >= n_days: break call = Call(symbol, d=int(expiry_to_use[0:2]), m=int(expiry_to_use[3:5]), y=int(expiry_to_use[6:10])) put = Put(symbol, d=int(expiry_to_use[0:2]), m=int(expiry_to_use[3:5]), y=int(expiry_to_use[6:10])) bracket_dict = get_strike_bracket(call.strikes, s.price) forward = s.price if bracket_dict['lower_weight'] > 0.5: call.set_strike(bracket_dict['lower_strike']) put.set_strike(bracket_dict['lower_strike']) forward = bracket_dict['lower_strike'] - put.price + call.price else: call.set_strike(bracket_dict['higher_strike']) put.set_strike(bracket_dict['higher_strike']) forward = bracket_dict['higher_strike'] - put.price + call.price return { "symbol": symbol, "forward_price": forward, "current_price": s.price, "expiry": expiry_to_use }
def get_options(sym, strike_date): put = Put(sym, d=strike_date.day, m=strike_date.month, y=strike_date.year, strict=True, source='yahoo') call = Call(sym, d=strike_date.day, m=strike_date.month, y=strike_date.year, strict=True, source='yahoo') stock = Stock(sym) price = get_closest(stock.price, put.strikes) put.set_strike(price) call.set_strike(price) return [ stock.price, price, put.price, put.volume, call.price, call.volume, format_date(put.expiration), format_date(call.expiration) ]
def get_atm_ivol(s, ndays=30): #Need to fix for divs, borrow etc to find atm symbol = s.ticker symbol = symbol.upper() if is_cache_good(f'{symbol}|getatmivol|{ndays}'): return ast.literal_eval(r.hget(f'{symbol}|getatmivol|{ndays}', 'value')) expiry_dict = get_expiries_bracket(symbol, ndays) #First Shorter One x = expiry_dict['shorter_expiry'] shorter_call = Call(symbol, d=int(x[0:2]), m=int(x[3:5]), y=int(x[6:10])) strike_dict = get_strike_bracket(shorter_call.strikes, s.price) shorter_call.set_strike(strike_dict['lower_strike']) lower_vol = shorter_call.implied_volatility() shorter_call.set_strike(strike_dict['higher_strike']) higher_vol = shorter_call.implied_volatility() shorter_ivol = lower_vol * strike_dict['lower_weight'] + higher_vol * ( 1 - strike_dict['lower_weight']) #Now longer One x = expiry_dict['longer_expiry'] longer_call = Call(symbol, d=int(x[0:2]), m=int(x[3:5]), y=int(x[6:10])) strike_dict = get_strike_bracket(longer_call.strikes, s.price) longer_call.set_strike(strike_dict['lower_strike']) lower_vol = longer_call.implied_volatility() longer_call.set_strike(strike_dict['higher_strike']) higher_vol = longer_call.implied_volatility() longer_ivol = lower_vol * strike_dict['lower_weight'] + higher_vol * ( 1 - strike_dict['lower_weight']) implied_ivol = shorter_ivol * expiry_dict[ 'shorter_weight'] + longer_ivol * (1 - expiry_dict['shorter_weight']) one_sigma_move_ndays_day = implied_ivol * math.sqrt(ndays / 365) return_dict = (implied_ivol, one_sigma_move_ndays_day) r.hset(f'{symbol}|getatmivol|{ndays}', 'time', datetime.utcnow().strftime('%s')) r.hset(f'{symbol}|getatmivol|{ndays}', 'value', str(return_dict)) return return_dict
def best_call_trades(symbol, num_of_days): symbol = symbol.upper() if is_cache_good(f'{symbol}|calltrade|{num_of_days}'): return ast.literal_eval( r.hget(f'{symbol}|calltrade|{num_of_days}', 'value')) return_dict = {"error": "no options"} try: c = Call(symbol) range_dict = range_data_from_symbol(symbol, num_of_days) curr_date = str(datetime.date(datetime.now())) expiries = c.expirations expiry_to_use = expiries[0] for i in expiries: days_to_exp = abs( datetime.strptime(i, '%d-%m-%Y') - datetime.strptime(curr_date, '%Y-%m-%d')).days expiry_to_use = i if days_to_exp >= num_of_days: break c = Call(symbol, d=int(expiry_to_use[0:2]), m=int(expiry_to_use[3:5]), y=int(expiry_to_use[6:10])) counter = 0 spread_list = [] strikes = c.strikes for i in strikes: if i >= range_dict["high_range"] and counter < 10: counter = counter + 1 c.set_strike(i) spread_list.append({ 'strike': i, 'bid': c.bid, 'ask': c.ask, 'last': c.price, 'using_last': 'false', 'delta': c.delta() }) max_amt = 0 max_call_amt = 0 best_spread = {} best_call_written = {} for i in spread_list: #for call prob_winning_call = 1 - i['delta'] # Not expiring in the money i['using_last'] = 'false' if i['bid'] == 0 and i['ask'] == 0: i['bid'] = i['last'] i['ask'] = i['last'] i['using_last'] = 'true' premium_call = i['bid'] call_win_amt = premium_call * prob_winning_call if call_win_amt > max_call_amt: max_call_amt = call_win_amt best_call_written = i for j in spread_list: if i['strike'] < j['strike']: #for spread premium_per_dollar = (i['bid'] - j['ask']) / (j['strike'] - i['strike']) spread_using_last = 'false' if i['using_last'] == 'true' or j[ 'using_last'] == 'true': #If any leg uses last mark spread as last spread_using_last = 'true' prob_winning_spread = 1 - j['delta'] win_amt = premium_per_dollar * prob_winning_spread if win_amt > max_amt: max_amt = win_amt if spread_using_last == 'true': best_spread = { 'strike_to_sell': i['strike'], 'strike_to_buy': j['strike'], 'premium_received': i['last'], 'premium_paid': j['last'], 'expiry': expiry_to_use, 'spread_using_last': spread_using_last } else: best_spread = { 'strike_to_sell': i['strike'], 'strike_to_buy': j['strike'], 'premium_received': i['bid'], 'premium_paid': j['ask'], 'expiry': expiry_to_use, 'spread_using_last': spread_using_last } best_call_written['expiry'] = expiry_to_use return_dict = { "symbol": symbol, 'best_spread': best_spread, 'best_call': best_call_written } if best_spread and best_call_written: r.hset(f'{symbol}|calltrade|{num_of_days}', 'time', datetime.utcnow().strftime('%s')) r.hset(f'{symbol}|calltrade|{num_of_days}', 'value', str(return_dict)) return return_dict except: return return_dict
def main(): parser = argparse.ArgumentParser( description="Find best trading strategies") group = parser.add_mutually_exclusive_group() parser.add_argument("ticker", type=str, help="stock ticker") # group.add_argument("-t", "--ticker", action="store_true") group.add_argument("-d", "--date", action="store_true") parser.add_argument("-s", "--strategy", help="the strategy") # parser.add_argument("y", type=int, help="the exponent") args = parser.parse_args() ticker = yf.Ticker(args.ticker) # get stock info print('****** Info **********') print(ticker.info) # input("Press Enter to continue...") # get historical market data print('****** History **********') hist = ticker.history(period="max") print(hist) # input("Press Enter to continue...") print('****** Actions **********') # show actions (dividends, splits) print(ticker.actions) # input("Press Enter to continue...") print('****** dividends **********') # show dividends print(ticker.dividends) # input("Press Enter to continue...") # show splits ticker.splits # show financials print('****** financials **********') print(ticker.financials) print(ticker.quarterly_financials) # input("Press Enter to continue...") # show major holders print(ticker.major_holders) # show institutional holders print(ticker.institutional_holders) # input("Press Enter to continue...") # show balance heet print(ticker.balance_sheet) print(ticker.quarterly_balance_sheet) # show cashflow ticker.cashflow ticker.quarterly_cashflow # show earnings print(ticker.earnings) print(ticker.quarterly_earnings) # show sustainability print(ticker.sustainability) # show analysts recommendations print(ticker.recommendations) # show next event (earnings, etc) print('****** calendars **********') print(ticker.calendar) # input("Press Enter to continue...") # show ISIN code - *experimental* # ISIN = International Securities Identification Number print(ticker.isin) # show options expirations print('****** calendars **********') print(ticker.options) # input("Press Enter to continue...") # get option chain for specific expiration opt = ticker.option_chain(ticker.options[0]) # data available via: opt.calls, opt.puts print(opt.calls) # input("Press Enter to continue...") print(opt.puts) # input("Press Enter to continue...") history = ticker.history() last_quote = (history.tail(1)['Close'].iloc[0]) last_price = int(last_quote) # calls for opt in ticker.options: try: data = [] dt = datetime.fromisoformat(opt) option = Call(args.ticker ) # d=dt.day, m=dt.month, y=dt.year, strike=ticker.) for strike in option.strikes: if strike < last_price - 40 or strike > last_price + 25: continue print(f'strike = {strike}') option.set_strike(strike) item = {} item['strike'] = strike item['price'] = option.price item['iv'] = option.implied_volatility() item['delta'] = option.delta() item['vega'] = option.vega() item['gamma'] = option.gamma() # print(f'theta = {option.theta()}') # print(f'vega = {option.vega()}') data.append(item) dataframe = pd.DataFrame(data) dataframe.to_csv(f'call-{args.ticker}-{dt}') print(dataframe.to_csv()) except Exception as e: print(f'{type(e)}: {str(e)} ') continue # put for opt in ticker.options: try: data = [] dt = datetime.fromisoformat(opt) option = Put( args.ticker ) # d=dt.day, m=dt.month, y=dt.year, strike=ticker.) for strike in option.strikes: if strike < last_price - 40 or strike > last_price + 25: continue print(f'strike = {strike}') option.set_strike(strike) item = {} item['strike'] = strike item['price'] = option.price item['iv'] = option.implied_volatility() item['delta'] = option.delta() item['vega'] = option.vega() item['gamma'] = option.gamma() # print(f'Rho = {option.rho()}') # print(f'type = {option.Option_type}') # print(f'theta = {option.theta()}') # print(f'vega = {option.vega()}') data.append(item) dataframe = pd.DataFrame(data) dataframe.to_csv(f'put-{args.ticker}-{dt}') print(dataframe.to_csv()) except Exception as e: print(f'{type(e)}: {str(e)} ') continue
o = None # This is our option object. if is_call: o = Call(symbol, d=expdate.day, m=expdate.month, y=expdate.year) print("CALLS") else: o = Put(symbol, d=expdate.day, m=expdate.month, y=expdate.year) print("PUTS") if len(o.strikes) > 0: print("Strikes", o.strikes) strikes = get_strikes(price, o.strikes, is_call, num_options) for i, strik in enumerate(strikes): strike = Decimal(strik) o.set_strike(strike) row = f'r{i+1}' price = Decimal(o.price) window[row + 'c1'].update(o.strike) window[row + 'c2'].update(o.price) if target1 > 0: gain = strike - target1 - price if is_call: gain = target1 - strike - price window[row + 'c3'].update(f'{gain:.2f}') pctgain = gain * 100 / price window[row + 'c4'].update(f'{pctgain:.2f}%') if target2 > 0: gain = strike - target2 - price if is_call: gain = target2 - strike - price
#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ Wallstreet package can be found in the following link https://pypi.python.org/pypi/wallstreet/0.1.5 @author: chenkai """ from wallstreet import Stock, Call, Put import pandas as pd import numpy as np import matplotlib.pyplot as plt g = Call('SPX', d=20, m=7, y=2018, source='yahoo') x = g.strikes y = np.zeros(len(x)) for i in range(len(x)): g.set_strike(x[i]) y[i] = g.implied_volatility() plt.plot(x, y) plt.scatter(x, y)