Ejemplo n.º 1
0
async def create_closing_order(session: TastyAPISession,
                               acct: TradingAccount,
                               order: OrderChangeAccountObject,
                               close_order_type: OrderType,
                               limit_price_delta: float = None,
                               stop_order_trigger: float = None):

    LOGGER.warning(f"Creating Closing Order: {AUTOCLOSE_ORDER_TYPE.name}")

    #Market Orders don't have price effect, assumes we're Buying first
    flipped_ope = (OrderPriceEffect.CREDIT if
                   (not (getattr(order, 'price_effect_enum', None))
                    or OrderPriceEffect.DEBIT == order.price_effect_enum.DEBIT)
                   else OrderPriceEffect.DEBIT)

    details = OrderDetails(
        type=close_order_type,
        price=((order.price +
                limit_price_delta) if close_order_type.is_limit() else None),
        stop_trigger=(stop_order_trigger
                      if close_order_type.is_stop() else None),
        price_effect=flipped_ope,
        is_open_order=False)
    new_order = Order(details)

    for leg in order.legs:
        opt = CompleteOption(instrument_type=leg.instrument_type,
                             symbol_complete=leg.symbol,
                             quantity=leg.quantity)
        new_order.add_leg(opt)

    res = await acct.execute_order(new_order, session, dry_run=False)
    LOGGER.info(f"Closing Order opened?: {bool(res)}")
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)
Ejemplo n.º 3
0
 def get_closing_order_object(self,
                              price: Decimal,
                              stop_trigger: Decimal = None,
                              order_type: OrderType = OrderType.LIMIT):
     closing_order_price_effect = self.get_closing_order_price_effect()
     details = OrderDetails(type=order_type,
                            price=price,
                            price_effect=closing_order_price_effect,
                            stop_trigger=stop_trigger)
     new_order = Order(details)
     opt = self.get_option_obj()
     new_order.add_leg(opt)
     return new_order
Ejemplo n.º 4
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)
Ejemplo n.º 5
0
    async def execute_order(self, order: Order, session, dry_run=True):
        """
        Execute an order. If doing a dry run, the order isn't placed but simulated (server-side).

        Args:
            order (Order): The order object to execute.
            session (TastyAPISession): The tastyworks session onto which to execute the order.
            dry_run (bool): Whether to do a test (dry) run.

        Returns:
            bool: Whether the order was successful.
        """
        if not order.check_is_order_executable():
            raise Exception('Order is not executable, most likely due to missing data')

        if not session.is_active():
            raise Exception('The supplied session is not active and valid')

        url = '{}/accounts/{}/orders'.format(
            session.API_url,
            self.account_number
        )
        if dry_run:
            url = f'{url}/dry-run'

        body = _get_execute_order_json(order)

        async with aiohttp.request('POST', url, headers=session.get_request_headers(), json=body) as resp:
            if resp.status == 201:
                return True
            elif resp.status == 400:
                raise Exception('Order execution failed, message: {}'.format(await resp.text()))
            else:
                raise Exception('Unknown remote error, status code: {}, message: {}'.format(resp.status, await resp.text()))
Ejemplo n.º 6
0
    async def execute_order(self, order: Order, session, dry_run=True):
        """
        Execute an order. If doing a dry run, the order isn't placed but simulated (server-side).

        Args:
            order (Order): The order object to execute.
            dry_run (bool): Whether to do a test (dry) run.

        Returns:
            bool: Whether the order was successful.
        """
        if not order.check_is_order_executable():
            raise Exception(
                'Order is not executable, most likely due to missing data')

        if not session.is_active():
            raise Exception('The supplied session is not active and valid')

        url = '{}/accounts/{}/orders'.format(session.API_url,
                                             self.account_number)
        if dry_run:
            url = f'{url}/dry-run'

        body = {
            'source': order.details.source,
            'order-type': order.details.type.value,
            'price': str(order.details.price),
            'price-effect': order.details.price_effect.value,
            'time-in-force': order.details.time_in_force,
            'legs': self._get_legs_request_data(order)
        }

        async with aiohttp.request('POST',
                                   url,
                                   headers=session.get_request_headers(),
                                   json=body) as resp:
            if resp.status == 201:
                return True
            elif resp.status == 400:
                raise Exception('Order execution failed, message: {}'.format(
                    await resp.text()))
            else:
                raise Exception(
                    'Unknown remote error, status code: {}, message: {}'.
                    format(resp.status, await resp.text()))
Ejemplo n.º 7
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)