def getOrders(self, market='', action='', status='all'):
        """Retrieves orders either live or simulation

        Parameters
        ----------
        market : str, optional
            Filters orders by market
        action : str, optional
            Filters orders by action
        status : str
            Filters orders by status, defaults to 'all'
        """

        # validate market is syntactically correct
        self._checkMarketSyntax(market)

        if action != '':
            # validate action is either a buy or sell
            if not action in ['buy', 'sell']:
                raise ValueError('Invalid order action.')

        # validate status is open, pending, done, active or all
        if not status in ['open', 'pending', 'done', 'active', 'all', 'filled']:
            raise ValueError('Invalid order status.')

        if self.app.getExchange() == 'binance':
            if self.mode == 'live':
                # if config is provided and live connect to Coinbase Pro account portfolio
                model = BAuthAPI(self.app.getAPIKey(), self.app.getAPISecret(), self.app.getAPIURL())
                # retrieve orders from live Binance account portfolio
                self.orders = model.getOrders(market, action, status)
                return self.orders
            else:
                # return dummy orders
                if market == '':
                    return self.orders
                else:
                    return self.orders[self.orders['market'] == market]             
        if self.app.getExchange() == 'coinbasepro':
            if self.mode == 'live':
                # if config is provided and live connect to Coinbase Pro account portfolio
                model = CBAuthAPI(self.app.getAPIKey(), self.app.getAPISecret(), self.app.getAPIPassphrase(), self.app.getAPIURL())
                # retrieve orders from live Coinbase Pro account portfolio
                self.orders = model.getOrders(market, action, status)
                return self.orders
            else:
                # return dummy orders
                if market == '':
                    return self.orders
                else:
                    return self.orders[self.orders['market'] == market]
Example #2
0
    def getOrders(self, market='', action='', status='all'):
        """Retrieves orders either live or simulation

        Parameters
        ----------
        market : str, optional
            Filters orders by market
        action : str, optional
            Filters orders by action
        status : str
            Filters orders by status, defaults to 'all'
        """

        # validate market is syntactically correct
        self._checkMarketSyntax(market)

        if action != '':
            # validate action is either a buy or sell
            if not action in ['buy', 'sell']:
                raise ValueError('Invalid order action.')

        # validate status is open, pending, done, active or all
        if not status in [
                'open', 'pending', 'done', 'active', 'all', 'filled'
        ]:
            raise ValueError('Invalid order status.')

        if self.app.getExchange() == 'binance':
            if self.mode == 'live':
                resp = self.client.get_all_orders(symbol=market)
                if len(resp) > 0:
                    df = pd.DataFrame(resp)
                else:
                    df = pd.DataFrame()

                if len(df) == 0:
                    return pd.DataFrame()

                df = df[[
                    'time', 'symbol', 'side', 'type', 'executedQty',
                    'cummulativeQuoteQty', 'status'
                ]]
                df.columns = [
                    'created_at', 'market', 'action', 'type', 'size', 'value',
                    'status'
                ]
                df['created_at'] = df['created_at'].apply(
                    lambda x: int(str(x)[:10]))
                df['created_at'] = df['created_at'].astype("datetime64[s]")
                df['size'] = df['size'].astype(float)
                df['value'] = df['value'].astype(float)
                df['action'] = df['action'].str.lower()
                df['type'] = df['type'].str.lower()
                df['status'] = df['status'].str.lower()
                df['price'] = df['value'] / df['size']

                # pylint: disable=unused-variable
                for k, v in df.items():
                    if k == 'status':
                        df[k] = df[k].map(self.__convertStatus)

                if action != '':
                    df = df[df['action'] == action]
                    df = df.reset_index(drop=True)

                if status != 'all' and status != '':
                    df = df[df['status'] == status]
                    df = df.reset_index(drop=True)

                return df
            else:
                # return dummy orders
                if market == '':
                    return self.orders
                else:
                    if (len(self.orders) > 0):
                        return self.orders[self.orders['market'] == market]
                    else:
                        return pd.DataFrame()
        if self.app.getExchange() == 'coinbasepro':
            if self.mode == 'live':
                # if config is provided and live connect to Coinbase Pro account portfolio
                model = CBAuthAPI(self.app.getAPIKey(),
                                  self.app.getAPISecret(),
                                  self.app.getAPIPassphrase(),
                                  self.app.getAPIURL())
                # retrieve orders from live Coinbase Pro account portfolio
                self.orders = model.getOrders(market, action, status)
                return self.orders
            else:
                # return dummy orders
                if market == '':
                    return self.orders
                else:
                    return self.orders[self.orders['market'] == market]
Example #3
0
    def sell(self,
             cryptoMarket,
             fiatMarket,
             cryptoAmount,
             manualPrice=0.00000000):
        """Places a sell 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
        """
        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

        # crypto amount must be an integer or float
        if not isinstance(cryptoAmount, float) and not isinstance(
                cryptoAmount, int):
            raise TypeError('Crypto amount not numeric.')

        # crypto amount must be positive
        if cryptoAmount <= 0:
            raise Exception('Invalid crypto amount.')

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

                # TODO: not finished
                print(resp)
            else:
                # crypto amount should exceed balance
                if cryptoAmount > self.getBalance(cryptoMarket):
                    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.')

                # calculate purchase fees
                fee = cryptoAmount * 0.005
                cryptoAmountMinusFee = cryptoAmount - fee

                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'])

                total = price * cryptoAmountMinusFee

                # append dummy order into orders dataframe
                ts = pd.Timestamp.now()
                price = ((price * cryptoAmount) * 100) / (cryptoAmount * 100)
                order = pd.DataFrame([[
                    '', market, 'sell', 'market', cryptoAmountMinusFee,
                    float('{:.8f}'.format(total)), '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) + total
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'available'] = self.getBalance(fiatMarket) + total

                # update the dummy crypto balance
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'balance'] = self.getBalance(cryptoMarket) - cryptoAmount
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'available'] = self.getBalance(cryptoMarket) - cryptoAmount

        else:
            if self.mode == 'live':
                # connect to Coinbase Pro API live
                model = CBAuthAPI(self.app.getAPIKey(),
                                  self.app.getAPISecret(),
                                  self.app.getAPIPassphrase(),
                                  self.app.getAPIURL())

                # execute a live market sell
                resp = model.marketSell(market,
                                        float(self.getBalance(cryptoMarket)))

                # TODO: not finished
                print(resp)
            else:
                # crypto amount should exceed balance
                if cryptoAmount > self.getBalance(cryptoMarket):
                    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.')

                # calculate purchase fees
                fee = cryptoAmount * 0.005
                cryptoAmountMinusFee = cryptoAmount - fee

                price = manualPrice
                if manualPrice <= 0:
                    # if manualPrice is non-positive retrieve the current live price
                    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'])

                total = price * cryptoAmountMinusFee

                # append dummy order into orders dataframe
                ts = pd.Timestamp.now()
                price = ((price * cryptoAmount) * 100) / (cryptoAmount * 100)
                order = pd.DataFrame([[
                    market, 'sell', 'market', cryptoAmountMinusFee,
                    float('{:.8f}'.format(total)), 'done', price
                ]],
                                     columns=[
                                         '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) + total
                self.balance.loc[
                    self.balance['currency'] == fiatMarket,
                    'available'] = self.getBalance(fiatMarket) + total

                # update the dummy crypto balance
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'balance'] = self.getBalance(cryptoMarket) - cryptoAmount
                self.balance.loc[
                    self.balance['currency'] == cryptoMarket,
                    'available'] = self.getBalance(cryptoMarket) - cryptoAmount
Example #4
0
    def getBalance(self, currency=''):
        """Retrieves balance either live or simulation

        Parameters
        ----------
        currency: str, optional
            Filters orders by currency
        """

        if self.app.getExchange() == 'binance':
            if self.mode == 'live':
                resp = self.client.get_account()
                if 'balances' in resp:
                    df = pd.DataFrame(resp['balances'])
                    df = df[(df['free'] != '0.00000000')
                            & (df['free'] != '0.00')]
                    df['free'] = df['free'].astype(float)
                    df['locked'] = df['locked'].astype(float)
                    df['balance'] = df['free'] - df['locked']
                    df.columns = ['currency', 'available', 'hold', 'balance']
                    df = df[['currency', 'balance', 'hold', 'available']]
                    df = df.reset_index(drop=True)

                    if currency == '':
                        # retrieve all balances
                        return df
                    else:
                        # retrieve balance of specified currency
                        df_filtered = df[df['currency'] ==
                                         currency]['available']
                        if len(df_filtered) == 0:
                            # return nil balance if no positive balance was found
                            return 0.0
                        else:
                            # return balance of specified currency (if positive)
                            if currency in ['EUR', 'GBP', 'USD']:
                                return float(
                                    self.app.truncate(
                                        float(df[df['currency'] == currency]
                                              ['available'].values[0]), 2))
                            else:
                                return float(
                                    self.app.truncate(
                                        float(df[df['currency'] == currency]
                                              ['available'].values[0]), 4))
                else:
                    return 0.0
            else:
                # return dummy balances
                if currency == '':
                    # retrieve all balances
                    return self.balance
                else:
                    if self.app.getExchange() == 'binance':
                        self.balance = self.balance.replace('QUOTE', currency)
                    else:
                        # replace QUOTE and BASE placeholders
                        if currency in ['EUR', 'GBP', 'USD']:
                            self.balance = self.balance.replace(
                                'QUOTE', currency)
                        else:
                            self.balance = self.balance.replace(
                                'BASE', currency)

                    if self.balance.currency[self.balance.currency.isin(
                        [currency])].empty == True:
                        self.balance.loc[len(
                            self.balance)] = [currency, 0, 0, 0]

                    # retrieve balance of specified currency
                    df = self.balance
                    df_filtered = df[df['currency'] == currency]['available']

                    if len(df_filtered) == 0:
                        # return nil balance if no positive balance was found
                        return 0.0
                    else:
                        # return balance of specified currency (if positive)
                        if currency in ['EUR', 'GBP', 'USD']:
                            return float(
                                self.app.truncate(
                                    float(df[df['currency'] == currency]
                                          ['available'].values[0]), 2))
                        else:
                            return float(
                                self.app.truncate(
                                    float(df[df['currency'] == currency]
                                          ['available'].values[0]), 4))

        else:
            if self.mode == 'live':
                # if config is provided and live connect to Coinbase Pro account portfolio
                model = CBAuthAPI(self.app.getAPIKey(),
                                  self.app.getAPISecret(),
                                  self.app.getAPIPassphrase(),
                                  self.app.getAPIURL())
                if currency == '':
                    # retrieve all balances
                    return model.getAccounts()[[
                        'currency', 'balance', 'hold', 'available'
                    ]]
                else:
                    df = model.getAccounts()
                    # retrieve balance of specified currency
                    df_filtered = df[df['currency'] == currency]['available']
                    if len(df_filtered) == 0:
                        # return nil balance if no positive balance was found
                        return 0.0
                    else:
                        # return balance of specified currency (if positive)
                        if currency in ['EUR', 'GBP', 'USD']:
                            return float(
                                self.app.truncate(
                                    float(df[df['currency'] == currency]
                                          ['available'].values[0]), 2))
                        else:
                            return float(
                                self.app.truncate(
                                    float(df[df['currency'] == currency]
                                          ['available'].values[0]), 4))

            else:
                # return dummy balances

                if currency == '':
                    # retrieve all balances
                    return self.balance
                else:
                    # replace QUOTE and BASE placeholders
                    if currency in ['EUR', 'GBP', 'USD']:
                        self.balance = self.balance.replace('QUOTE', currency)
                    elif currency in ['BCH', 'BTC', 'ETH', 'LTC', 'XLM']:
                        self.balance = self.balance.replace('BASE', currency)

                    if self.balance.currency[self.balance.currency.isin(
                        [currency])].empty == True:
                        self.balance.loc[len(
                            self.balance)] = [currency, 0, 0, 0]

                    # retrieve balance of specified currency
                    df = self.balance
                    df_filtered = df[df['currency'] == currency]['available']

                    if len(df_filtered) == 0:
                        # return nil balance if no positive balance was found
                        return 0.0
                    else:
                        # return balance of specified currency (if positive)
                        if currency in ['EUR', 'GBP', 'USD']:
                            return float(
                                self.app.truncate(
                                    float(df[df['currency'] == currency]
                                          ['available'].values[0]), 2))
                        else:
                            return float(
                                self.app.truncate(
                                    float(df[df['currency'] == currency]
                                          ['available'].values[0]), 4))
                printHelp()
                sys.exit()

            if 'cryptoMarket' in config:
                base_currency = config['cryptoMarket']
            elif 'base_currency' in config:
                base_currency = config['base_currency']

            if 'fiatMarket' in config:
                quote_currency = config['fiatMarket']
            elif 'base_currency' in config:
                quote_currency = config['quote_currency']

            market = base_currency + '-' + quote_currency

            api = CBAuthAPI(api_key, api_secret, api_pass)

            orders = api.getOrders()
            df = pd.concat([df, orders])

            transfers = api.getTransfers()
            df = pd.concat([df, transfers])

    df['created_at'] = df['created_at'].map(
        lambda x: re.sub(r"\.\d{1,6}\+00$", "", str(x)))
    df['created_at'] = df['created_at'].map(
        lambda x: re.sub(r"\+00:00$", "", str(x)))

    save_file = 'profitandloss.csv'

    try: