Esempio n. 1
0
def test_nearest_column_round_down(one_day_data, value):
    # here we test for mid-point, values returned should round down.
    chain = OptionQuery.nearest(one_day_data, value[0], value[1], 'rounddown')
    values = chain[value[0]].unique()

    assert len(values) == 1
    assert values[0] == value[2]
Esempio n. 2
0
    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']])
Esempio n. 3
0
def test_invalid_column_values(one_day_data, value):
    with pytest.raises(ValueError):
        OptionQuery._check_inputs(one_day_data, value[0], value[1])
Esempio n. 4
0
def test_underlying_price(one_day_data):
    chain = OptionQuery().underlying_price(one_day_data)
    assert chain == 40.55
Esempio n. 5
0
def test_option_type(one_day_data, option_type):
    chain = OptionQuery.opt_type(one_day_data,
                                 option_type).option_type.unique()
    assert len(chain) == 1
    assert chain[0] == option_type.value[0]
Esempio n. 6
0
def test_invalid_option_type(one_day_data, option_type):
    with pytest.raises(ValueError):
        OptionQuery.opt_type(one_day_data, option_type)
Esempio n. 7
0
def test_puts(one_day_data):
    puts = OptionQuery.puts(one_day_data).option_type.unique()
    assert len(puts) == 1
    assert puts[0] == 'p'
Esempio n. 8
0
def test_calls(one_day_data):
    calls = OptionQuery.calls(one_day_data).option_type.unique()
    assert len(calls) == 1
    assert calls[0] == 'c'
Esempio n. 9
0
    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']])