def covered_stock(chain, **params): """ A covered call is an options strategy whereby an investor holds a long position n an asset and writes (sells) call options on that same asset in an attempt to generate increased income from the asset. Writing covered puts is a bearish options trading strategy involving the writing of put options while shorting the obligated shares of the underlying stock. :param chain: dataframe of option chain data :param params: params used to build the covered stock strategy :return: A new dataframe containing all covered stock created from dataframe """ if 'option_type' not in params: raise ValueError("Must provide option_type for covered stock") # set the attributes for this option strategy OptionStrategies.covered_stock.option_config = { 'stock': 100, 'option': 1 } out_col = OptionStrategies.base_out_col chains = OptionQuery(chain).option_type(params['option_type']) chains = chains.lte( 'expiration', params['DTE']).fetch() if 'DTE' in params else chains.fetch() side = -1 * params['option_type'].value[1] chains['spread_mark'] = (side * (chains['bid'] + chains['ask']) / 2) + chains['underlying_price'] prefix = "-." if params['option_type'] == OptionType.CALL else "." chains['spread_symbol'] = prefix + chains['symbol'] + "+100*" + chains[ 'underlying_symbol'] return OptionSeries(chains[out_col + ['strike']])
def calendar(chain, **params): """ A calendar spread is a strategy involving buying longer term options and selling equal number of shorter term options of the same underlying stock or index with the same strike price. Calendar spreads can be done with calls or with puts, which are virtually equivalent if using same strikes and expirations. :param chain: Filtered Dataframe to vertical spreads with. :param option_type: The option type for this spread :param depth: The period to represent the difference between the expiration dates of the two options :return: A new dataframe containing all covered stock created from dataframe """ if 'option_type' not in params: raise ValueError("Must provide option_type for calendar spread") elif 'depth' not in params: raise ValueError("Must provide period depth for calender spread") # set the attributes for this option strategy OptionStrategies.calendar.option_config = {'option': 2} out_col = OptionStrategies.base_out_col shift = Period.ONE_WEEK if 'depth' not in params else params['depth'] chains = OptionQuery(chain).option_type(params['option_type']) chains = chains.lte( 'expiration', params['DTE']).fetch() if 'DTE' in params else chains.fetch() # create column with expiration shifted by depth chains['expiration_key'] = chains['expiration'] + timedelta( days=shift.value) left_keys = ['quote_date', 'expiration_key', 'option_type', 'strike'] right_keys = ['quote_date', 'expiration', 'option_type', 'strike'] chains = chains.merge(chains, left_on=left_keys, right_on=right_keys, suffixes=('', '_shifted')) if chains.empty: raise ValueError( "Cannot construct calendar spreads. Check expirations exists for specified depth." ) # calculate the spread's bid and ask prices for c, f in OptionStrategies.shift_col: # handle bid ask special case if c == 'bid': chains['spread_' + c] = f(chains[c], chains['ask_shifted']) elif c == 'ask': chains['spread_' + c] = f(chains[c], chains['bid_shifted']) else: if f is not None: chains['spread_' + c] = f(chains[c], chains[c + '_shifted']) chains['spread_mark'] = (chains['spread_bid'] + chains['spread_ask']) / 2 chains['spread_symbol'] = "." + chains[ 'symbol_shifted'] + "-." + chains['symbol'] # assign the strategy name to this dataframe's name attribute chains.name = OptionStrategies.single.__name__ return OptionSeries(chains[out_col + ['strike', 'expiration_shifted']])