Exemple #1
0
    def test_current__closed_end__none(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_CLOSED_END
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current()

        assert current is None
Exemple #2
0
    def test_current__market_end__regular(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_MARKET_END
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current()

        assert current is MarketSession.REGULAR
Exemple #3
0
    def test_current__otc_market_start__regular(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_MARKET_START
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current(otc=True)

        assert current is MarketSession.REGULAR
Exemple #4
0
    def test_current__otc_weekend_closed_start__none(self, mock_datetime):
        mock_datetime.now.return_value = SUNDAY_CLOSED_START
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current(otc=True)

        assert current is None
Exemple #5
0
    def test_current__dst_premarket_end__extended(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_PREMARKET_END_DST
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current()

        assert current is MarketSession.EXTENDED
Exemple #6
0
    def test_current__otc_weekend_afterhours_end__none(self, mock_datetime):
        mock_datetime.now.return_value = SUNDAY_AFTERHOURS_END
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current(otc=True)

        assert current is None
Exemple #7
0
    def test_current__otc_weekend_market_start__none(self, mock_datetime):
        mock_datetime.now.return_value = SATURDAY_MARKET_START
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current(otc=True)

        assert current is None
Exemple #8
0
    def test_current__otc_afterhours_start__none(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_AFTERHOURS_START
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current(otc=True)

        assert current is None
Exemple #9
0
    def test_current__weekend_premarket_end__none(self, mock_datetime):
        mock_datetime.now.return_value = SATURDAY_PREMARKET_END
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current()

        assert current is None
Exemple #10
0
    def test_current__afterhours_end__extended(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_AFTERHOURS_END
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current()

        assert current is MarketSession.EXTENDED
async def place_sell_order(passenger: AutoPilotTask, sell_price: Decimal,
                           etrade: AsyncEtrade):
    try:
        limit_price = get_limit_price(OrderAction.SELL,
                                      sell_price,
                                      margin=passenger.strategy.price_margin)
        order_params = {
            'account_key': passenger.account.account_key,
            'market_session': MarketSession.current().value,
            'action': OrderAction.SELL.value,
            'symbol': passenger.symbol,
            'price_type': PriceType.LIMIT.value,
            'quantity': passenger.quantity,
            'limit_price': limit_price
        }

        preview_ids = await etrade.preview_order(
            order_client_id=get_random_string(length=20), **order_params)
        order_id = await etrade.place_order(
            order_client_id=get_random_string(length=20),
            preview_ids=preview_ids,
            **order_params)
    except ServiceError:
        logger.error("place_sell_order: params %s", order_params)
        raise

    return order_id
Exemple #12
0
    def test_current__otc_premarket_end__none(self, mock_datetime):
        mock_datetime.now.return_value = FRIDAY_PREMARKET_END
        mock_datetime.side_effect = create_datetime

        current = MarketSession.current(otc=True)

        assert current is None
async def green_light(pilot_name: str, passenger: AutoPilotTask,
                      etrade: AsyncEtrade) -> bool:
    # handle override signal
    if passenger.signal == AutoPilotTask.MANUAL_OVERRIDE:
        logger.info("%s %s received signal MANUAL_OVERRIDE.", PREFIX,
                    pilot_name)
        logger.info("%s %s releasing control...", PREFIX, pilot_name)
        passenger.status = AutoPilotTask.DONE
        return False

    # if no market session, sleep until market opens
    if MarketSession.current(passenger.is_otc) is None:
        logger.debug("%s %s market is closed. sleeping 1h", PREFIX, pilot_name)
        time_till_open = time_till_market_open(passenger.is_otc)
        await asyncio.sleep(time_till_open)
        return False

    # if no access token, sleep 1s (repeat until valid access)
    if not etrade.is_session_active():
        logger.debug("%s %s waiting for valid %s session...", PREFIX,
                     pilot_name, etrade.name)
        await asyncio.sleep(1)
        return False

    return True
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               symbol,
                               provider_id,
                               account_id=None):
        account = Account.objects.get(id=account_id) if account_id else None
        provider = ServiceProvider.objects.select_related('session') \
            .get(id=provider_id)
        account_key = account.account_key.strip() if account \
            else provider.account_key.strip()

        if not account_key:
            return StopLoss(
                error=StopLossError.ACCOUNT_NOT_PROVIDED,
                error_message=
                'Either specify an accountId that has a valid accountKey ' +
                'or configure a default accountKey on the provider.')

        autopilot = get_autopilot(info.context.user.id, symbol)
        if autopilot:
            return StopLoss(error=StopLossError.NOT_ALLOWED_ON_AUTOPILOT,
                            error_message='You must turn off autopilot first.')

        etrade = get_provider_instance(provider)
        position_quantity = etrade.get_position_quantity(account_key, symbol)
        quote = etrade.get_quote(symbol)
        last_price = get_bid(quote)
        stop_price = get_round_price(last_price -
                                     (last_price * Decimal('0.02')))
        limit_price = get_limit_price(OrderAction.SELL,
                                      stop_price,
                                      margin=Decimal('0.02'))

        order_params = {
            'account_key': account_key,
            'market_session': MarketSession.current().value,
            'action': OrderAction.SELL.value,
            'symbol': symbol,
            'price_type': PriceType.STOP_LIMIT.value,
            'quantity': position_quantity,
            'stop_price': stop_price,
            'limit_price': limit_price
        }

        preview_ids = etrade.preview_order(
            order_client_id=get_random_string(length=20), **order_params)
        etrade.place_order(order_client_id=get_random_string(length=20),
                           preview_ids=preview_ids,
                           **order_params)

        return StopLoss()
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               symbol,
                               provider_id,
                               strategy_id=None,
                               account_id=None):
        account = Account.objects.get(id=account_id) if account_id else None
        provider = ServiceProvider.objects.select_related('session') \
            .get(id=provider_id)

        strategy = None
        if strategy_id:
            strategy = info.context.user.trading_strategies.filter(
                id=strategy_id).first()
            if not strategy:
                return StopProfit(
                    error=StopProfitError.STRATEGY_NOT_FOUND,
                    error_message=
                    f'TradingStrategy with id {strategy_id} not found.')

        account_key = account.account_key.strip() if account \
            else provider.account_key.strip()

        if not account_key:
            return StopProfit(
                error=StopProfitError.ACCOUNT_NOT_PROVIDED,
                error_message=
                'Either specify an accountId that has a valid accountKey ' +
                'or configure a default accountKey on the provider.')

        autopilot = get_autopilot(info.context.user.id, symbol)
        if autopilot:
            return StopProfit(
                error=StopProfitError.NOT_ALLOWED_ON_AUTOPILOT,
                error_message='You must turn off autopilot first.')

        etrade = get_provider_instance(provider)
        position_quantity, entry_price = etrade.get_position(
            account_key, symbol)

        if strategy:
            profit_amount = entry_price * (strategy.profit_percent / 100)
            stop_price = get_round_price(entry_price + profit_amount)
        else:
            quote = etrade.get_quote(symbol)
            last_price = get_ask(quote)
            profit_amount = last_price * Decimal('0.02')
            stop_price = get_round_price(last_price + profit_amount)

        limit_price = get_limit_price(OrderAction.SELL,
                                      stop_price,
                                      margin=Decimal('0.01'))

        order_params = {
            'account_key': account_key,
            'market_session': MarketSession.current().value,
            'action': OrderAction.SELL.value,
            'symbol': symbol,
            'price_type': PriceType.STOP_LIMIT.value,
            'quantity': position_quantity,
            'stop_price': stop_price,
            'limit_price': limit_price
        }

        preview_ids = etrade.preview_order(
            order_client_id=get_random_string(length=20), **order_params)
        etrade.place_order(order_client_id=get_random_string(length=20),
                           preview_ids=preview_ids,
                           **order_params)

        return StopProfit()
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               symbol,
                               provider_id,
                               margin='0.00',
                               price='0.0000',
                               quantity=0,
                               account_id=None):
        account = Account.objects.get(id=account_id) if account_id else None
        provider = ServiceProvider.objects.select_related('session') \
            .get(id=provider_id)
        account_key = account.account_key.strip() if account \
            else provider.account_key.strip()

        if not account_key:
            return SellStock(
                error=SellStockError.ACCOUNT_NOT_PROVIDED,
                error_message=
                'Either specify an accountId that has a valid accountKey ' +
                'or configure a default accountKey on the provider.')

        # turn_off_autopilot(info.context.user.id, symbol)
        autopilot = get_autopilot(info.context.user.id, symbol)

        if autopilot:
            autopilot.signal = AutoPilotTask.SELL
            autopilot.save()
            return SellStock()

        etrade = get_provider_instance(provider)

        if Decimal(price):
            limit_price = Decimal(price).quantize(Decimal('0.0001'))
        else:
            quantized_margin = Decimal(margin).quantize(Decimal('0.001'))
            print(f'margin: {Decimal(quantized_margin)}')
            quote = etrade.get_quote(symbol)
            limit_price = get_limit_price(OrderAction.SELL,
                                          get_ask(quote),
                                          margin=Decimal(quantized_margin)
                                          or Decimal('0.1'))

        if not quantity:
            quantity = etrade.get_position_quantity(account_key, symbol)

        order_params = {
            'account_key': account_key,
            'market_session': MarketSession.current().value,
            'action': OrderAction.SELL.value,
            'symbol': symbol,
            'price_type': PriceType.LIMIT.value,
            'quantity': quantity,
            'limit_price': limit_price
        }

        preview_ids = etrade.preview_order(
            order_client_id=get_random_string(length=20), **order_params)
        etrade.place_order(order_client_id=get_random_string(length=20),
                           preview_ids=preview_ids,
                           **order_params)

        return SellStock()
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               symbol,
                               strategy_id,
                               provider_id,
                               margin='0.00',
                               price='0.0000',
                               quantity=0,
                               account_id=None,
                               autopilot=False):
        strategy = TradingStrategy.objects.get(id=strategy_id)
        provider = ServiceProvider.objects.select_related('session') \
            .get(id=provider_id)
        account = Account.objects.get(id=account_id) if account_id else None
        account_key = account.account_key.strip() if account \
            else provider.account_key.strip()

        if not account_key:
            return BuyStock(
                error=BuyStockError.ACCOUNT_NOT_PROVIDED,
                error_message=
                'Either specify an accountId that has a valid accountKey ' +
                'or configure a default accountKey on the provider.')

        if not account:
            account = Account.objects.get(account_key=account_key)

        if not strategy.funded(account):
            return BuyStock(
                error=BuyStockError.INSUFFICIENT_FUNDS,
                error_message='Insufficient funds. Strategy selected ' +
                'requires more cash available for investment.')

        etrade = get_provider_instance(provider)

        if autopilot:
            quote = etrade.get_quote(symbol)
            is_otc = etrade.is_otc(quote)
            user = info.context.user
            settings = Settings.objects.filter(user_id=user.id).first()
            default_modifier = settings.default_autopilot_modifier if settings else None
            discord_webhook = settings.discord_webhook if settings else None
            task = AutoPilotTask(signal=AutoPilotTask.BUY,
                                 user=info.context.user,
                                 strategy=strategy,
                                 provider=provider,
                                 account=account,
                                 is_otc=is_otc,
                                 symbol=symbol,
                                 quantity=quantity,
                                 entry_price=price,
                                 base_price=price,
                                 loss_ref_price=price,
                                 profit_ref_price=price,
                                 ref_time=timezone.now(),
                                 modifier=default_modifier,
                                 discord_webhook=discord_webhook)
            task.save()
            return BuyStock()

        if Decimal(price):
            limit_price = Decimal(price).quantize(Decimal('0.0001'))
        else:
            quantized_margin = Decimal(margin).quantize(Decimal('0.001'))
            quote = etrade.get_quote(symbol)
            limit_price = get_limit_price(
                OrderAction.BUY, get_bid(quote),
                Decimal(quantized_margin) or strategy.price_margin)

        if not quantity:
            quantity = strategy.get_quantity_for(
                buying_power=account.real_value, price_per_share=limit_price)

        order_params = {
            'account_key': account_key,
            'market_session': MarketSession.current().value,
            'action': OrderAction.BUY.value,
            'symbol': symbol,
            'price_type': PriceType.LIMIT.value,
            'quantity': quantity,
            'limit_price': limit_price
        }

        preview_ids = etrade.preview_order(
            order_client_id=get_random_string(length=20), **order_params)
        etrade.place_order(order_client_id=get_random_string(length=20),
                           preview_ids=preview_ids,
                           **order_params)

        # TODO: HANDLE Code: 1527. Message: Opening orders for this security cannot be accepted online at this time. For assistance with placing this order, please contact Customer Service at 1-800-ETRADE-1 (1-800-387-2331).

        return BuyStock()