Example #1
0
 def setUp(self):
     self.test_option = Option(ticker='AKS',
                               quantity=1,
                               expiry=date(2018, 8, 10),
                               strike=Decimal('3.5'),
                               option_type=OptionType.CALL,
                               underlying_type=UnderlyingType.EQUITY)
Example #2
0
    def parse(cls, ticker: str, response: dict):
        """
        Parses a response from tasty session into a dict[str, Option]

        Args:
            ticker (str): Ticker symbol of the option chain
            response (dict): Response from tasty session

        Returns:
            dict[str,Option]: dict mapping all option symbols to Option structures
        """

        chain = {}
        for expiry, strikes in response.items():
            for strike, opts in strikes.items():
                chain[opts['call']] = Option(
                    ticker=ticker,
                    expiry=datetime.date(expiry),
                    strike=strike,
                    option_type=OptionType.CALL,
                    underlying_type=OptionUnderlyingType.
                    EQUITY,  #todo pass underlying                                        
                )

                chain[opts['put']] = Option(
                    ticker=ticker,
                    expiry=datetime.date(expiry),
                    strike=strike,
                    option_type=OptionType.PUT,
                    underlying_type=OptionUnderlyingType.
                    EQUITY,  #todo pass underlying                                        
                )

        return chain
Example #3
0
 def get_option_obj(self):
     exp_date = datetime.strptime(self.symbol[6:12], '%y%m%d').date()
     option_type = OptionType(self.symbol[12:13])
     strike = Decimal(self.symbol[13:]) / 1000
     return Option(ticker=self.underlying_symbol,
                   quantity=self.quantity,
                   expiry=exp_date,
                   strike=strike,
                   option_type=option_type,
                   underlying_type=UnderlyingType.EQUITY)
async def EnterTrade(ticker, price: Decimal, expiry, strike: Decimal, opt_type: OptionType, quantity = 1):
    sub_values = {"Quote": ["/ES"]}
    if Settings.EnterWithMarketOrder:
        details = OrderDetails(type=OrderType.MARKET, price=None, price_effect=OrderPriceEffect.DEBIT)
    else:
        details = OrderDetails(type=OrderType.LIMIT, price=price, price_effect=OrderPriceEffect.DEBIT)
    new_order = Order(details)
    opt = Option(ticker=ticker, quantity=quantity, expiry=expiry, strike=strike, option_type=opt_type, underlying_type=UnderlyingType.EQUITY)
    new_order.add_leg(opt)
    return await tasty_acct.execute_order(new_order, tasty_client, dry_run=False)
Example #5
0
 def get_equity_leg_from_dict(self, input_dict: dict):
     exp_date = datetime.strptime(input_dict['symbol'][6:12],
                                  '%y%m%d').date()
     option_type = OptionType(input_dict['symbol'][12:13])
     strike = Decimal(input_dict['symbol'][13:]) / 1000
     return Option(ticker=self.details.ticker,
                   quantity=input_dict['quantity'],
                   expiry=exp_date,
                   strike=strike,
                   option_type=option_type,
                   underlying_type=UnderlyingType.EQUITY)
Example #6
0
async def main_loop(session: TastyAPISession, streamer: DataStreamer):
    # sub_values = {
    #     "Greeks": [
    #         ".VIX180718C21",
    #         ".YUM180518C95"
    #     ]
    # }
    sub_values = {
        "Quote": ["/ES"]
    }

    accounts = await TradingAccount.get_remote_accounts(session)
    acct = accounts[0]
    LOGGER.info('Accounts available: %s', accounts)

    orders = await Order.get_remote_orders(session, acct)
    LOGGER.info('Number of active orders: %s', len(orders))

    # Execute an order

    details = OrderDetails(
        type=OrderType.LIMIT,
        price=400,
        price_effect=OrderPriceEffect.CREDIT)
    new_order = Order(details)

    opt = Option(
        ticker='AKS',
        quantity=1,
        expiry=date(2018, 10, 19),
        strike=3.0,
        option_type=OptionType.CALL,
        underlying_type=UnderlyingType.EQUITY
    )
    new_order.add_leg(opt)

    res = await acct.execute_order(new_order, session, dry_run=True)
    LOGGER.info('Order executed successfully: %s', res)

    # Get an options chain
    undl = underlying.Underlying('AKS')

    chain = await option_chain.get_option_chain(session, undl)
    LOGGER.info('Chain strikes: %s', chain.get_all_strikes())

    await streamer.add_data_sub(sub_values)

    async for item in streamer.listen():
        LOGGER.info('Received item: %s' % item.data)
Example #7
0
class TestOptionModel(unittest.TestCase):
    def setUp(self):
        self.test_option = Option(
            ticker='AKS',
            quantity=1,
            expiry=date(2018, 8, 10),
            strike=3.5,
            option_type=OptionType.CALL,
            underlying_type=OptionUnderlyingType.EQUITY
        )

    def test_occ2010_integer_strike(self):
        self.test_option.strike = 3
        expected_result = 'AKS   180810C00003000'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_occ2010_fraction_strike(self):
        self.test_option.strike = 3.45
        expected_result = 'AKS   180810C00003450'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

        self.test_option.strike = 3.5
        expected_result = 'AKS   180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_occ2010_ticker_padding(self):
        self.test_option.ticker = 'BOB123'
        expected_result = 'BOB123180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

        self.test_option.ticker = 'BOB'
        expected_result = 'BOB   180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_occ2010_ticker_trimming(self):
        self.test_option.ticker = 'BOB123456'
        expected_result = 'BOB123180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)
Example #8
0
async def get_option_chain(session, underlying: Underlying, expiration: date = None) -> List[Option]:
    LOGGER.debug('Getting options chain for ticker: %s', underlying.ticker)
    data = await _get_tasty_option_chain_data(session, underlying)
    res = []

    for exp in data['expirations']:
        exp_date = datetime.strptime(exp['expiration-date'], '%Y-%m-%d').date()

        if expiration and expiration != exp_date:
            continue

        for strike in exp['strikes']:
            strike_val = float(strike['strike-price'])
            for option_types in OptionType:
                new_option = Option(
                    ticker=underlying.ticker,
                    expiry=exp_date,
                    strike=strike_val,
                    option_type=option_types,
                    underlying_type=UnderlyingType.EQUITY
                )
                res.append(new_option)
    return OptionChain(res)
Example #9
0
class TestOptionModel(unittest.TestCase):
    def setUp(self):
        self.test_option = Option(ticker='AKS',
                                  quantity=1,
                                  expiry=date(2018, 8, 10),
                                  strike=Decimal('3.5'),
                                  option_type=OptionType.CALL,
                                  underlying_type=UnderlyingType.EQUITY)

    def test_occ2010_integer_strike(self):
        self.test_option.strike = 3
        expected_result = 'AKS   180810C00003000'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_occ2010_fraction_strike(self):
        self.test_option.strike = 3.45
        expected_result = 'AKS   180810C00003450'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

        self.test_option.strike = 3.5
        expected_result = 'AKS   180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_occ2010_ticker_padding(self):
        self.test_option.ticker = 'BOB123'
        expected_result = 'BOB123180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

        self.test_option.ticker = 'BOB'
        expected_result = 'BOB   180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_occ2010_ticker_trimming(self):
        self.test_option.ticker = 'BOB123456'
        expected_result = 'BOB123180810C00003500'

        res = self.test_option.get_occ2010_symbol()
        self.assertEqual(expected_result, res)

    def test_get_dxfeed_symbol(self):
        expected_result = '.AKS180810C3.5'
        result = self.test_option.get_dxfeed_symbol()
        self.assertEqual(result, expected_result)

    def test_no_option_chains_on_option(self):
        with self.assertRaises(Exception):
            self.test_option.get_option_chain()

    def test_get_underlying_type_string(self):
        res = self.test_option._get_underlying_type_string(
            UnderlyingType.EQUITY)
        self.assertEqual(res, 'Equity Option')

    def test_to_tasty_json(self):
        res = self.test_option.to_tasty_json()
        expected_result = {
            'instrument-type': 'Equity Option',
            'symbol': 'AKS   180810C00003500',
            'quantity': 1
        }
        self.assertDictEqual(res, expected_result)
Example #10
0
async def call(underlying: str,
               quantity: int,
               strike: Optional[int] = None,
               all_expirations: Optional[bool] = False,
               delta: Optional[int] = None):
    if strike is not None and delta is not None:
        raise TastyworksCLIError(
            'Must specify either delta or strike, but not both.')
    elif not strike and not delta:
        raise TastyworksCLIError(
            'Please specify either delta or strike for the option.')
    elif abs(delta) > 100:
        raise TastyworksCLIError(
            'Delta value is too high, -100 <= delta <= 100')

    sesh = await RenewableTastyAPISession.create()
    undl = Underlying(underlying)
    expiration = await choose_expiration(sesh, undl, all_expirations)
    streamer = await DataStreamer.create(sesh)

    if not strike:
        chain = await get_option_chain(sesh, undl, expiration)
        dxfeeds = [
            option.symbol_dxf for option in chain.options
            if option.option_type == OptionType.CALL
        ]
        greeks = await streamer.stream('Greeks', dxfeeds)

        lowest = abs(greeks[0]['delta'] * 100.0 - delta)
        index = 0
        for i in range(1, len(greeks)):
            diff = abs(greeks[i]['delta'] * 100.0 - delta)
            if diff < lowest:
                index = i
                lowest = diff
        for option in chain.options:
            if option.symbol_dxf == greeks[index]['eventSymbol']:
                strike = option.strike
                break

    option = Option(ticker=underlying,
                    quantity=abs(quantity),
                    expiry=expiration,
                    strike=strike,
                    option_type=OptionType.CALL,
                    underlying_type=UnderlyingType.EQUITY)
    quote = await streamer.stream('Quote', [option.symbol_dxf])
    bid = quote[0]['bidPrice']
    ask = quote[0]['askPrice']
    mid = (bid + ask) / 2

    await streamer.close()

    console = Console()
    table = Table(show_header=True,
                  header_style='bold',
                  title_style='bold',
                  title=f'Quote for {underlying} {strike}C {expiration}')
    table.add_column('Bid', style='green', width=8, justify='center')
    table.add_column('Mid', width=8, justify='center')
    table.add_column('Ask', style='red', width=8, justify='center')
    table.add_row(f'{bid:.2f}', f'{mid:.2f}', f'{ask:.2f}')
    console.print(table)

    price = input(
        'Please enter a limit price for the entire order (default mid): ')
    if not price:
        price = round(mid * abs(quantity), 2)
    price = Decimal(price)

    details = OrderDetails(type=OrderType.LIMIT,
                           price=price,
                           price_effect=OrderPriceEffect.CREDIT
                           if quantity < 0 else OrderPriceEffect.DEBIT)
    order = Order(details)
    order.add_leg(option)

    acct = await get_account(sesh)
    details = await acct.get_balance(sesh)
    nl = Decimal(details['net-liquidating-value'])

    data = await acct.execute_order(order, sesh, dry_run=True)
    bp = Decimal(data['buying-power-effect']['change-in-buying-power'])
    percent = bp / nl * Decimal(100)
    # bp_effect = data['buying-power-effect']['change-in-buying-power-effect']
    fees = Decimal(data['fee-calculation']['total-fees'])

    table = Table(show_header=True,
                  header_style='bold',
                  title_style='bold',
                  title='Order Review')
    table.add_column('Quantity', width=8, justify='center')
    table.add_column('Symbol', width=8, justify='center')
    table.add_column('Strike', width=8, justify='center')
    table.add_column('Type', width=8, justify='center')
    table.add_column('Expiration', width=10, justify='center')
    table.add_column('Price', width=8, justify='center')
    table.add_column('BP', width=8, justify='center')
    table.add_column('% of NL', width=8, justify='center')
    table.add_column('Fees', width=8, justify='center')
    table.add_row(f'{quantity}', underlying, f'{strike:.2f}', 'CALL',
                  f'{expiration}', f'${price:.2f}', f'${bp:.2f}',
                  f'{percent:.2f}%', f'${fees}')
    console.print(table)

    if data['warnings']:
        console.print('[bold orange]Warnings:[/bold orange]')
        for warning in data['warnings']:
            console.print(f'[i gray]{warning}[/i gray]')
    if get_confirmation('Send order? Y/n '):
        await acct.execute_order(order, sesh, dry_run=False)