def __init__(self, sandbox_mode=False):
        LIVE_URL = 'https://api.pro.coinbase.com/'
        SANDBOX_URL = 'https://api-public.sandbox.pro.coinbase.com/'

        base_url = SANDBOX_URL if sandbox_mode else LIVE_URL
        self.history = History(base_url)
        self.api = API(base_url)

        self.products = self.api.get('products').json()
        self.currencies = self.api.get('currencies').json()
Ejemplo n.º 2
0
    def __init__(self, credentials, sandbox_mode=False):

        LIVE_URL = 'https://api.pro.coinbase.com/'
        SANDBOX_URL = 'https://api-public.sandbox.pro.coinbase.com/'

        base_url = SANDBOX_URL if sandbox_mode else LIVE_URL

        self.cb_public = CBProPublic(sandbox_mode=sandbox_mode)
        self.api = API(base_url)
        self.auth = Auth(**credentials)
        self.accounts = self.api.get('accounts', auth=self.auth).json()
    def __init__(self, base_url):
        self.api = API(base_url)

        self.ONE_MINUTE = 60
        self.MAX_CANDLES = 300

        self.api_granularities = {
            'minute': self.ONE_MINUTE,
            'five_minute': self.ONE_MINUTE * 5,
            'fifteen_minute': self.ONE_MINUTE * 15,
            'hourly': self.ONE_MINUTE * 60,
            'six_hour': self.ONE_MINUTE * 60 * 6,
            'daily': self.ONE_MINUTE * 60 * 24
        }
class History():
    def __init__(self, base_url):
        self.api = API(base_url)

        self.ONE_MINUTE = 60
        self.MAX_CANDLES = 300

        self.api_granularities = {
            'minute': self.ONE_MINUTE,
            'five_minute': self.ONE_MINUTE * 5,
            'fifteen_minute': self.ONE_MINUTE * 15,
            'hourly': self.ONE_MINUTE * 60,
            'six_hour': self.ONE_MINUTE * 60 * 6,
            'daily': self.ONE_MINUTE * 60 * 24
        }

    def build(self, product_id, window_start_datetime, window_end_datetime,
              candle_interval, debug):

        self._set_internal_variables(product_id, window_start_datetime,
                                     window_end_datetime, candle_interval,
                                     debug)

        if self.date_range_specified:

            request_array = np.arange(1, self.required_request_count + 1)
            request_timeline = list(
                ft.reduce(self._create_request_timeline, request_array, []))

            # complete all requests in the request timeline
            candles = map(self._send_request, request_timeline)
            candles = list(map(self._format_candle, it.chain(*candles)))

            return candles

        else:
            candles = self._send_request((None, None, 0))
            candles = list(map(self._format_candle, candles))
            return candles[:-1]

    def _set_internal_variables(self, product_id, window_start_datetime,
                                window_end_datetime, candle_interval, debug):
        self.debug = debug
        self.product_id = product_id.upper()
        self.endpoint = f'/products/{self.product_id}/candles'

        self.candle_length_seconds = self.api_granularities[candle_interval]
        self.candle_length_minutes = self.candle_length_seconds / self.ONE_MINUTE

        self.date_range_specified = window_start_datetime and window_end_datetime

        if self.date_range_specified:
            self.window_start_datetime = datetime.fromisoformat(
                window_start_datetime)
            self.window_end_datetime = datetime.fromisoformat(
                window_end_datetime)  # exclusive
        else:
            return

        window_delta_seconds = (self.window_end_datetime -
                                self.window_start_datetime).total_seconds()
        self.candles_in_window = int(
            window_delta_seconds / self.candle_length_seconds) - 1
        self.required_request_count = math.ceil(self.candles_in_window /
                                                self.MAX_CANDLES)

    def _create_request_timeline(self, accumulator, request_number):

        is_first_request = request_number == 1
        on_last_request = request_number == self.required_request_count

        one_candle_delta = timedelta(minutes=self.candle_length_minutes)
        request_delta = timedelta(minutes=self.candle_length_minutes *
                                  (self.MAX_CANDLES - 1))

        previous_request_end_date = accumulator[-1][1] if len(
            accumulator) > 0 else None
        request_start_date = self.window_start_datetime if is_first_request else previous_request_end_date + one_candle_delta
        request_end_date = self.window_end_datetime - one_candle_delta if on_last_request else request_start_date + request_delta
        wait_time = 0 if is_first_request else self.api._random_float_between_zero_one(
        )
        accumulator.append((request_start_date, request_end_date, wait_time))

        return accumulator

    def _send_request(self, request_info):

        start_iso, end_iso, wait_time = request_info

        params = {
            'granularity': self.candle_length_seconds,
            'start': start_iso,
            'end': end_iso,
        }

        time.sleep(wait_time)
        candles = self.api.get(self.endpoint, params=params).json()

        candles.reverse()
        if self.debug:
            candle_count = len(candles)

            print(
                f'Candles Returned: {candle_count}\nTotal Candles Needed: {self.candles_in_window}'
            )
            oldest_candle_datetime = datetime.utcfromtimestamp(
                candles[0][0]).isoformat()
            most_recent_candle_datetime = datetime.utcfromtimestamp(
                candles[-1][0]).isoformat()

            print(
                f'\nStart Date: {oldest_candle_datetime}\nEnd Date: {most_recent_candle_datetime}\n\n'
            )

        return candles

    @staticmethod
    def _format_candle(candle):
        '''
        Parameters:
            candle (list): [
                'unix_timestamp',
                'low (int or float)',
                'high (int or float)',
                'open (int or float)',
                'close (int or float)',
                'volume (int or float)'
            ]
        '''

        candle_attributes = [
            'open_iso_datetime', 'low', 'high', 'open', 'close', 'volume'
        ]

        utc_datetime = datetime.utcfromtimestamp(candle[0]).isoformat()
        prices_and_volume = list(map(str, candle[1:]))

        candle = [utc_datetime, *prices_and_volume]
        candle = dict(zip(candle_attributes, candle))

        return candle
class CBProPublic():
    def __init__(self, sandbox_mode=False):
        LIVE_URL = 'https://api.pro.coinbase.com/'
        SANDBOX_URL = 'https://api-public.sandbox.pro.coinbase.com/'

        base_url = SANDBOX_URL if sandbox_mode else LIVE_URL
        self.history = History(base_url)
        self.api = API(base_url)

        self.products = self.api.get('products').json()
        self.currencies = self.api.get('currencies').json()
    

    def twenty_four_hour_stats(self, product_id):
        return self.api.get(f'products/{product_id}/stats').json()

    def usd_market_volume(self):
        '''get min $ volume of __/USD trading pairs in past 24 hrs'''
        usd_trading_pairs = [x for x in self.trading_pairs() if x.split('-')[1] == 'USD']
        
        payload = []

        for pair in usd_trading_pairs:
            stats = self.twenty_four_hour_stats(pair)
            volume = str(round(Decimal(stats['volume']) * Decimal(stats['low']), 2))
            payload.append({'currency_pair': pair, 'usd_volume': volume})
            time.sleep(0.4)
        
        sorted_payload = sorted(payload, key=lambda x: Decimal(x['usd_volume']), reverse=True)

        return sorted_payload
            
    def usd_price(self, currency, delay=False):
        '''Get the price in USD for a given asset'''
        endpoint = f'products/{currency.upper()}-USD/ticker'
        price = self.api.get(endpoint).json()['price']

        if delay:
            time.sleep(0.4)

        return price
    
    def exchange_rate(self, currency_pair):
        '''Get the exchange_rate for a given asset'''
        endpoint = f'products/{currency_pair.upper()}/ticker'
        price = self.api.get(endpoint).json()['price']
        return price

    def exchange_time(self):
        '''Return the exchange time in an iso formatted string'''
        endpoint = 'time'
        time_str = self.api.get(endpoint).json()['iso']
        exchange_time = datetime.strptime(time_str, '%Y-%m-%dT%H:%M:%S.%fZ')

        return exchange_time.isoformat(sep=' ')
    
    def historical_prices(self, product_id, start=None, end=None, candle_interval='daily', debug=False):
        return self.history.build(product_id, start, end, candle_interval, debug)

    def trading_pairs(self):
        product_info = self.api.get('products').json()

        return [d['id'] for d in product_info]
def live_base_api():
    return API('https://api.pro.coinbase.com/')
Ejemplo n.º 7
0
class CBProAuthenticated():
    def __init__(self, credentials, sandbox_mode=False):

        LIVE_URL = 'https://api.pro.coinbase.com/'
        SANDBOX_URL = 'https://api-public.sandbox.pro.coinbase.com/'

        base_url = SANDBOX_URL if sandbox_mode else LIVE_URL

        self.cb_public = CBProPublic(sandbox_mode=sandbox_mode)
        self.api = API(base_url)
        self.auth = Auth(**credentials)
        self.accounts = self.api.get('accounts', auth=self.auth).json()

    def __getattr__(self, name):
        try:
            return getattr(self.cb_public, name)
        except AttributeError:
            raise AttributeError(
                f'The authenticated and public api objects do not have attribute {name}.'
            )

    def refresh_accounts(self):
        self.accounts = self.api.get('accounts', auth=self.auth).json()

    def fill_history(self,
                     product_id,
                     order_id=None,
                     start_date=None,
                     end_date=None):
        '''Get all fills associated with a given product id'''
        end_point = 'fills'
        params = {'product_id': product_id.upper()}
        data = self.api.handle_page_nation(end_point,
                                           params=params,
                                           start_date=start_date,
                                           auth=self.auth)
        returned_value = data.copy().to_dict(orient='records')
        return returned_value if data is not None else None

    @staticmethod
    def _apply_unique_id_to_activity(entry):
        if entry['type'] == 'match':
            entry['unique_id'] = entry['details.order_id']
            entry['unique_id_type'] = 'order_id'

        if entry['type'] == 'transfer':
            entry['unique_id'] = entry['details.transfer_id']
            entry['unique_id_type'] = 'transfer_id'

        return entry

    def asset_activity(self, asset_symbol, start_date=None, end_date=None):
        '''Get all activity related to a given asset'''

        asset_symbol = asset_symbol.upper()
        account_id = [
            account['id'] for account in self.accounts
            if account['currency'] == asset_symbol
        ][0]
        activity = self.api.handle_page_nation(f"accounts/{account_id}/ledger",
                                               start_date=start_date,
                                               auth=self.auth)
        no_activity = len(activity) == 0

        if no_activity:
            return activity

        activity = map(self._apply_unique_id_to_activity, activity)

        activity = [{
            **entry, 'created_at':
            entry['created_at'].strftime('%Y-%m-%d %H:%M:%S:%f'),
            'symbol':
            asset_symbol,
            'amount':
            str(entry['amount']),
            'balance':
            str(entry['balance'])
        } for entry in activity]

        return activity

    def completed_orders(self, product_id=None):
        orders = self.api.handle_page_nation('orders',
                                             date_field='done_at',
                                             start_date='2019-01-01',
                                             auth=self.auth,
                                             params={'status': 'done'})

        orders = list(
            filter(lambda order: order['done_reason'] == 'filled', orders))

        return orders

    def market_buy(self, funds, product_id, delay=False):
        '''send order to api and handle errors'''

        order_payload = {
            'side': 'buy',
            'type': 'market',
            'product_id': product_id.upper(),
            'funds': str(funds),
        }

        r = self.api.post('orders',
                          params={},
                          data=order_payload,
                          auth=self.auth)

        if delay:
            time.sleep(0.4)

        return r

    def market_sell(self, size, product_id, delay=False):
        '''send order to api and handle errors'''

        order_payload = {
            'side': 'sell',
            'type': 'market',
            'product_id': product_id.upper(),
            'size': str(size),
        }

        r = self.api.post('orders',
                          params={},
                          data=order_payload,
                          auth=self.auth)

        if delay:
            time.sleep(0.4)

        return r