示例#1
0
    def resolve_performances(self, info, provider_id, account_id=None, **kwargs):
        provider = info.context.user.service_providers.get(id=provider_id)
        account = info.context.user.accounts.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:
            raise AttributeError(
                'Account Key not provided. ' +
                'Either specify accountId argument or configure a default accountKey on the provider.'
            )

        etrade = get_provider_instance(provider)
        transactions = etrade.get_transactions(account_key) or []

        symbol_map = {}
        for tran in transactions:
            brokerage = tran.get("brokerage")
            product = brokerage.get("product")
            transaction_type = tran.get("transactionType")
            transaction_date = tran.get("transactionDate")
            symbol = product.get("symbol")
            quantity = brokerage.get("quantity")
            amount = tran.get("amount")
            if transaction_type not in ('Bought', 'Sold'):
                continue
            if symbol not in symbol_map:
                performance = {
                    'symbol': symbol,
                    'amount': Decimal(amount),
                    'date': datetime.datetime.fromtimestamp(transaction_date/1000),
                    'bought': int(quantity) if transaction_type == 'Bought' else 0,
                    'sold': int(quantity) * -1 if transaction_type == 'Sold' else 0
                }
                symbol_map[symbol] = performance
            else:
                performace = symbol_map[symbol]
                performace['date'] = datetime.datetime.fromtimestamp(
                    transaction_date/1000)
                performace['amount'] = performace['amount'] + \
                    Decimal(amount)
                if transaction_type == 'Bought':
                    performace['bought'] = performace['bought'] + \
                        int(quantity)
                else:
                    performace['sold'] = performace['sold'] + \
                        int(quantity) * -1

        performances = [val for val in symbol_map.values()
                        if val['bought'] == val['sold']]
        performances.sort(key=lambda val: val['date'], reverse=True)

        return performances
示例#2
0
    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()
示例#3
0
    def resolve_session_status(self, *args, **kwargs):
        session = ProviderSession.objects.filter(provider=self).first()
        if not session:
            return ProviderSession.CLOSED

        etrade = get_provider_instance(self)
        if self.session and not etrade.is_session_active():
            self.session.delete()
            self.session = None
            self.save()
            return ProviderSession.CLOSED

        return self.session.status
示例#4
0
    def resolve_transactions(self, info, provider_id, account_id=None, **kwargs):
        provider = info.context.user.service_providers.get(id=provider_id)
        account = info.context.user.accounts.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:
            raise AttributeError(
                'Account Key not provided. ' +
                'Either specify accountId argument or configure a default accountKey on the provider.'
            )

        etrade = get_provider_instance(provider)
        return etrade.get_transactions(account_key) or []
示例#5
0
    def mutate_and_get_payload(cls, root, info, provider_id):
        provider = info.context.user.service_providers.filter(
            id=provider_id).first()

        if not provider:
            return ConnectProvider(
                error=ConnectProviderError.PROVIDER_NOT_FOUND,
                error_message=
                "Sorry! the provider you're trying to connect to was not found."
            )

        etrade = get_provider_instance(provider)
        authorize_url = etrade.get_authorize_url()

        return ConnectProvider(service_provider=provider,
                               authorize_url=authorize_url,
                               callback_enabled=provider.callback_configured)
示例#6
0
    def resolve_quote(self, info, symbol):
        etrade = get_provider_instance(self)
        quote_data = etrade.get_quote(symbol)

        if not quote_data:
            return None

        return QuoteType(
            volume=get_volume(quote_data),
            last=get_last(quote_data),
            bid=get_bid(quote_data),
            ask=get_ask(quote_data),
            last_trade_direction=Decimal(
                str(quote_data.get('All').get('dirLast'))),
            market_cap=Decimal(str(quote_data.get('All').get('marketCap'))),
            shares_outstanding=quote_data.get('All').get('sharesOutstanding'),
            primary_exchange=quote_data.get('All').get('primaryExchange'),
            company_name=quote_data.get('All').get('companyName'),
        )
示例#7
0
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               oauth_verifier,
                               oauth_token=None,
                               provider_id=None):
        if not oauth_token and not provider_id:
            return AuthorizeConnection(
                error=AuthorizeConnectionError.MISSING_REQUIRED_FIELD,
                error_message="Provide oath_token or provider_id")

        if oauth_token:
            provider = info.context.user.service_providers \
                .filter(session__request_token=oauth_token) \
                .select_related('session') \
                .first()
        else:
            provider = info.context.user.service_providers \
                .filter(id=provider_id) \
                .select_related('session') \
                .first()

        if not provider:
            return AuthorizeConnection(
                error=AuthorizeConnectionError.SESSION_NOT_FOUND,
                error_message=
                "Pending session not found. Try starting a new connection.")

        if provider.session.status != ProviderSession.REQUESTING:
            return AuthorizeConnection(
                error=AuthorizeConnectionError.INCOMPATIBLE_STATE,
                error_message=
                "Session state is not compatible. Try starting a new connection."
            )

        etrade = get_provider_instance(provider)
        provider = etrade.authorize(oauth_verifier)

        return AuthorizeConnection(service_provider=provider)
示例#8
0
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               order_id,
                               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 CancelOrder(
                error=CancelOrderError.ACCOUNT_NOT_PROVIDED,
                error_message=
                'Either specify an accountId that has a valid accountKey ' +
                'or configure a default accountKey on the provider.')

        etrade = get_provider_instance(provider)
        etrade.cancel_order(account_key=account_key, order_id=order_id)

        return CancelOrder()
示例#9
0
    def mutate_and_get_payload(cls, root, info, provider_id):
        provider = info.context.user.service_providers \
            .filter(id=provider_id) \
            .select_related('session') \
            .first()

        if not provider:
            return AuthorizeConnection(
                error=SyncAccounts.PROVIDER_NOT_FOUND,
                error_message=
                "Pending session not found. Try starting a new connection.")

        etrade = get_provider_instance(provider)
        etrade.sync_accounts()

        default_account = Account.objects.filter(
            institution_type='BROKERAGE').first()

        if not provider.account_key:
            provider.account_key = default_account.account_key
            provider.save()

        return SyncAccounts(broker=provider.broker)
示例#10
0
def oauth1_verify(request: Request):
    data = request.data
    oauth_token = data.get("oauthToken", None)
    oauth_verifier = data.get("oauthVerifier", None)

    if not oauth_token:
        return Response({
            "error": f'oauthToken required'
        })

    provider = ServiceProvider.objects \
        .filter(session__request_token=oauth_token) \
        .select_related('session', 'broker', 'user__auth_token') \
        .first()

    if not provider:
        return Response({
            "error": f'no session found for provided oauthToken'
        })

    etrade = get_provider_instance(provider)
    try:
        provider = etrade.authorize(oauth_verifier)
    except KeyError as e:
        if f'Token {oauth_token} is invalid, or has expired' in str(e):
            return Response({
                "error": f'Token expired.'
            })
        else:
            raise

    return Response({
        "accessToken": provider.user.auth_token.key,
        "brokerSlug": provider.broker.slug,
        "providerSlug": provider.slug,
    })
示例#11
0
    def mutate_and_get_payload(cls,
                               root,
                               info,
                               symbol,
                               strategy_id=None,
                               provider_id=None,
                               account_id=None,
                               modifier=None):
        user = info.context.user

        strategy = user.trading_strategies.get(
            id=strategy_id) if strategy_id else cls.get_default_strategy(info)
        if not strategy:
            return AutoPilotON(
                error=AutoPilotONError.STRATEGY_REQUIRED,
                error_message=
                'Either set the strategy_id param or configure a default.')

        provider = user.service_providers.get(
            id=provider_id) if provider_id else cls.get_default_privider(info)
        if not provider:
            return AutoPilotON(
                error=AutoPilotONError.PROVIDER_REQUIRED,
                error_message=
                'Either set the provider_id param or configure a default.')

        account = user.accounts.get(
            id=account_id) if account_id else cls.get_default_account(info)
        if not account:
            return AutoPilotON(
                error=AutoPilotONError.ACCOUNT_REQUIRED,
                error_message=
                'Either set the account_id param or configure a default.')

        if AutoPilotTask.objects.filter(symbol=symbol,
                                        status=AutoPilotTask.RUNNING).exists():
            return AutoPilotON(
                error=AutoPilotONError.ALREADY_EXISTS,
                error_message=f'Autopilot for {symbol} already exists.')

        if modifier is None:
            modifier = cls.get_default_modifier(user)

        discord_webhook = cls.get_discord_webhook(info)

        etrade = get_provider_instance(provider)
        quantity, entry_price = etrade.get_position(account.account_key,
                                                    symbol)
        if not quantity or not entry_price:
            return AutoPilotON(
                error=AutoPilotONError.NO_POSITION_FOR_SYMBOL,
                error_message=
                f'No position found for {symbol}. Position: {quantity}@{entry_price}'
            )

        quote = etrade.get_quote(symbol)
        is_otc = etrade.is_otc(quote)

        task = AutoPilotTask(user=user,
                             strategy=strategy,
                             provider=provider,
                             account=account,
                             is_otc=is_otc,
                             symbol=symbol,
                             quantity=quantity,
                             entry_price=entry_price,
                             base_price=entry_price,
                             loss_ref_price=entry_price,
                             profit_ref_price=entry_price,
                             ref_time=timezone.now(),
                             modifier=modifier,
                             discord_webhook=discord_webhook)

        task.save()
        return AutoPilotON()
示例#12
0
    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()
示例#13
0
    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()
示例#14
0
    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()