def test_marketBuyInvalidAmount():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    with pytest.raises(ValueError) as execinfo:
        exchange.marketBuy('XXX-YYY', 0)
    assert str(execinfo.value) == 'Trade amount is too small (>= 10).'
def test_marketBuyInvalidMarket():
    filename = 'config.json'

    with open(filename) as config_file:
        config = json.load(config_file)

        api_key = ''
        api_secret = ''
        api_passphrase = ''
        api_url = ''
        if 'api_key' in config and 'api_secret' in config and 'api_pass' in config and 'api_url' in config:
            api_key = config['api_key']
            api_secret = config['api_secret']
            api_passphrase = config['api_pass']
            api_url = config['api_url']

        elif 'api_key' in config['coinbasepro'] and 'api_secret' in config[
                'coinbasepro'] and 'api_passphrase' in config[
                    'coinbasepro'] and 'api_url' in config['coinbasepro']:
            api_key = config['coinbasepro']['api_key']
            api_secret = config['coinbasepro']['api_secret']
            api_passphrase = config['coinbasepro']['api_passphrase']
            api_url = config['coinbasepro']['api_url']

    exchange = AuthAPI(api_key, api_secret, api_passphrase, api_url)
    assert type(exchange) is AuthAPI

    with pytest.raises(ValueError) as execinfo:
        exchange.marketBuy('ERROR', -1)
    assert str(execinfo.value) == 'Coinbase Pro market is invalid.'
Esempio n. 3
0
    def marketBuy(self, market, quote_currency, buy_percent=100):
        if self.is_live == 1:
            if isinstance(buy_percent, int):
                if buy_percent > 0 and buy_percent < 100:
                    quote_currency = (buy_percent / 100) * quote_currency

            if self.exchange == 'coinbasepro':
                api = CBAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIPassphrase(), self.getAPIURL())
                return api.marketBuy(market, self.truncate(quote_currency, 2))
            elif self.exchange == 'binance':
                api = BAuthAPI(self.getAPIKey(), self.getAPISecret(), self.getAPIURL())
                return api.marketBuy(market, quote_currency)
            else:
                return None
Esempio n. 4
0
    def buy(self,
            cryptoMarket,
            fiatMarket,
            fiatAmount=0,
            manualPrice=0.00000000):
        """Places a buy order either live or simulation

        Parameters
        ----------
        cryptoMarket: str
            Crypto market you wish to purchase
        fiatMarket, str
            QUOTE market funding the purchase
        fiatAmount, float
            QUOTE amount of crypto currency to purchase
        manualPrice, float
            Used for simulations specifying the live price to purchase
        """

        # fiat funding amount must be an integer or float
        if not isinstance(fiatAmount, float) and not isinstance(
                fiatAmount, int):
            raise TypeError('QUOTE amount not numeric.')

        # fiat funding amount must be positive
        if fiatAmount <= 0:
            raise Exception('Invalid QUOTE amount.')

        if self.app.getExchange() == 'binance':
            # validate crypto market is syntactically correct
            p = re.compile(r"^[A-Z]{3,8}$")
            if not p.match(cryptoMarket):
                raise TypeError('Binance crypto market is invalid.')

            # validate fiat market is syntactically correct
            p = re.compile(r"^[A-Z]{3,8}$")
            if not p.match(fiatMarket):
                raise TypeError('Binance fiat market is invalid.')
        else:
            # crypto market should be either BCH, BTC, ETH, LTC or XLM
            if cryptoMarket not in ['BCH', 'BTC', 'ETH', 'LTC', 'XLM']:
                raise Exception(
                    'Invalid crypto market: BCH, BTC, ETH, LTC, ETH, or XLM')

            # fiat market should be either EUR, GBP, or USD
            if fiatMarket not in ['EUR', 'GBP', 'USD']:
                raise Exception('Invalid QUOTE market: EUR, GBP, USD')

        # reconstruct the exchange market using crypto and fiat inputs
        if self.app.getExchange() == 'binance':
            market = cryptoMarket + fiatMarket
        else:
            market = cryptoMarket + '-' + fiatMarket

        if self.app.getExchange() == 'binance':
            if self.mode == 'live':
                # execute a live market buy
                resp = self.client.order_market_buy(symbol=market,
                                                    quantity=fiatAmount)

                # TODO: not finished
                print(resp)
            else:
                # fiat amount should exceed balance
                if fiatAmount > self.getBalance(fiatMarket):
                    raise Exception('Insufficient funds.')

                # manual price must be an integer or float
                if not isinstance(manualPrice, float) and not isinstance(
                        manualPrice, int):
                    raise TypeError('Optional manual price not numeric.')

                price = manualPrice
                # if manualPrice is non-positive retrieve the current live price
                if manualPrice <= 0:
                    if self.app.getExchange() == 'binance':
                        api = BPublicAPI()
                        price = api.getTicker(market)[1]
                    else:
                        resp = requests.get(
                            'https://api-public.sandbox.pro.coinbase.com/products/'
                            + market + '/ticker')
                        if resp.status_code != 200:
                            raise Exception(
                                'GET /products/' + market +
                                '/ticker {}'.format(resp.status_code))
                        resp.raise_for_status()
                        json = resp.json()
                        price = float(json['price'])

                # calculate purchase fees
                fee = fiatAmount * 0.005
                fiatAmountMinusFee = fiatAmount - fee
                total = float(fiatAmountMinusFee / float(price))

                # append dummy order into orders dataframe
                ts = pd.Timestamp.now()
                price = (fiatAmountMinusFee * 100) / (total * 100)
                order = pd.DataFrame([[
                    '', market, 'buy', 'market',
                    float('{:.8f}'.format(total)), fiatAmountMinusFee, 'done',
                    '{:.8f}'.format(float(price))
                ]],
                                     columns=[
                                         'created_at', 'market', 'action',
                                         'type', 'size', 'value', 'status',
                                         'price'
                                     ],
                                     index=[ts])
                order['created_at'] = order.index
                self.orders = pd.concat(
                    [self.orders, pd.DataFrame(order)], ignore_index=False)

                # update the dummy fiat balance
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'balance'] = self.getBalance(fiatMarket) - fiatAmount
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'available'] = self.getBalance(fiatMarket) - fiatAmount

                # update the dummy crypto balance
                self.balance.loc[self.balance['currency'] == cryptoMarket,
                                 'balance'] = self.getBalance(cryptoMarket) + (
                                     fiatAmountMinusFee / price)
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'available'] = self.getBalance(cryptoMarket) + (
                        fiatAmountMinusFee / price)

        else:
            if self.mode == 'live':
                # connect to coinbase pro api (authenticated)
                model = CBAuthAPI(self.app.getAPIKey(),
                                  self.app.getAPISecret(),
                                  self.app.getAPIPassphrase(),
                                  self.app.getAPIURL())

                # execute a live market buy
                if fiatAmount > 0:
                    resp = model.marketBuy(market, fiatAmount)
                else:
                    resp = model.marketBuy(market,
                                           float(self.getBalance(fiatMarket)))

                # TODO: not finished
                print(resp)
            else:
                # fiat amount should exceed balance
                if fiatAmount > self.getBalance(fiatMarket):
                    raise Exception('Insufficient funds.')

                # manual price must be an integer or float
                if not isinstance(manualPrice, float) and not isinstance(
                        manualPrice, int):
                    raise TypeError('Optional manual price not numeric.')

                price = manualPrice
                # if manualPrice is non-positive retrieve the current live price
                if manualPrice <= 0:
                    resp = requests.get(
                        'https://api-public.sandbox.pro.coinbase.com/products/'
                        + market + '/ticker')
                    if resp.status_code != 200:
                        raise Exception('GET /products/' + market +
                                        '/ticker {}'.format(resp.status_code))
                    resp.raise_for_status()
                    json = resp.json()
                    price = float(json['price'])

                # calculate purchase fees
                fee = fiatAmount * 0.005
                fiatAmountMinusFee = fiatAmount - fee
                total = float(fiatAmountMinusFee / price)

                # append dummy order into orders dataframe
                ts = pd.Timestamp.now()
                price = (fiatAmountMinusFee * 100) / (total * 100)
                order = pd.DataFrame([[
                    '', market, 'buy', 'market',
                    float('{:.8f}'.format(total)), fiatAmountMinusFee, 'done',
                    price
                ]],
                                     columns=[
                                         'created_at', 'market', 'action',
                                         'type', 'size', 'value', 'status',
                                         'price'
                                     ],
                                     index=[ts])
                order['created_at'] = order.index
                self.orders = pd.concat(
                    [self.orders, pd.DataFrame(order)], ignore_index=False)

                # update the dummy fiat balance
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'balance'] = self.getBalance(fiatMarket) - fiatAmount
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'available'] = self.getBalance(fiatMarket) - fiatAmount

                # update the dummy crypto balance
                self.balance.loc[self.balance['currency'] == cryptoMarket,
                                 'balance'] = self.getBalance(cryptoMarket) + (
                                     fiatAmountMinusFee / price)
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'available'] = self.getBalance(cryptoMarket) + (
                        fiatAmountMinusFee / price)