Beispiel #1
0
def coinMarketCapData():
    from pymarketcap import Pymarketcap
    coinmarketcap = Pymarketcap()
    symbols = coinmarketcap.symbols

    # ###### Set initial Date/Time.. Will be setting throughout

    # In[45]:

    #Pulls date and time information
    moment = time.strftime("%Y-%b-%d__%H_%M_%S", time.localtime())
    today = pd.Timestamp("today").strftime("%m/%d/%Y")
    hh = pd.Timestamp("today").strftime("%H")
    mm = pd.Timestamp("today").strftime("%M")

    # ###### Coinmarketcap statistics - up to date 1/14/2018

    # In[47]:

    try:
        stats = coinmarketcap.stats()
        stats = pd.DataFrame(stats, index=[0])

        stats['Date'] = today
        stats['Hour'] = hh
        stats['Minute'] = mm
        stats['Now'] = pd.Timestamp("today")

        stats.to_csv('Coinmarketcap/boom/stats/stats_' + moment + '.csv',
                     sep=',')
        print("Look at all those stats 0.o")
    except:
        print("*NO STATS GATHERED*")

    # ###### Coin Data - Updated 1/14/2018

    # In[49]:

    try:
        from pymarketcap import Pymarketcap
        coinmarketcap = Pymarketcap()
        ticker = coinmarketcap.ticker(limit=1500, convert="BTC")
        ticker = pd.DataFrame(ticker)

        ticker['Date'] = today
        ticker['Hour'] = hh
        ticker['Minute'] = mm
        ticker['Now'] = pd.Timestamp("today")

        ticker.to_csv('Coinmarketcap/boom/coins/coins_' + moment + '.csv',
                      sep=',')
        print("Chaaaa-CHING! The coin data is in")
    except:
        print("*NO COINS GATHERED* *YOU ARE LOSING OUT ON BAGS*")

    # ###### Coin exchange info for each token - Updated 1/14/2018

    # In[ ]:

    for coin2 in symbols:
        try:
            from pymarketcap import Pymarketcap
            coinmarketcap = Pymarketcap()
            markets = coinmarketcap.markets(coin2)
            markets = pd.DataFrame(markets['markets'])

            markets['Date'] = today
            markets['Hour'] = hh
            markets['Minute'] = mm
            markets['Now'] = pd.Timestamp("today")

            markets.to_csv('Coinmarketcap/boom/markets/markets_' + coin2 +
                           '_' + moment + '.csv',
                           sep=',')
        except:
            print("No market data was captured for ", coin2)
            pass
    print("I hear the exchange trades from here.. exchange data collected :)")

    # ###### Gainers and Losers (1h, 24h, 7d) - Updated 1/14/2018

    # ###### ******Currently no 7d Gainers being captured******

    # ###### New coins - Updated 1/14/2018

    # In[102]:

    #Set date and time
    today = pd.Timestamp("today").strftime("%m/%d/%Y")
    hh = pd.Timestamp("today").strftime("%H")
    mm = pd.Timestamp("today").strftime("%M")
    moment = time.strftime("%Y-%b-%d__%H_%M_%S", time.localtime())

    data = coinmarketcap.recently()
    data = pd.DataFrame(data)

    data.head()

    data['Date'] = today
    data['Hour'] = hh
    data['Minute'] = mm
    data['days_ago'] = data['added'].str.extract('(\d.)', expand=True)
    data['Now'] = pd.Timestamp("today")
    data['days_ago'] = data['days_ago'].apply(pd.to_numeric)
    data['Date_Added'] = data['Now'] - pd.to_timedelta(data['days_ago'],
                                                       unit='d')
    data['Date_Added'] = data['Date_Added'].dt.date

    #Reimport due to naming issues
    from pymarketcap import Pymarketcap
    coinmarketcap = Pymarketcap()

    #Get Market date for new coins
    for coin2 in data["symbol"]:
        try:
            markets = coinmarketcap.markets(coin2)
            markets = pd.DataFrame(markets['markets'])

            #add 'Today' 'Hour' and 'minutes' column
            markets['Date'] = today
            markets['Hour'] = hh
            markets['Minute'] = mm
            markets['Now'] = pd.Timestamp("today")

            #Save CSV
            markets.to_csv('Coinmarketcap/boom/markets/new/markerts_' + coin2 +
                           '_' + moment + '.csv',
                           sep=',')
            print("Market info for new coin", coin2, " captured!")
        except:
            print("************ERROR COIN", coin2,
                  "DATA NOT CAPUTRED*************")
            pass

        ###Upload datafile

    data.to_csv('Coinmarketcap/boom/new/new_' + moment + '.csv', sep=',')
    print("Gotta catch all the new coins!")
Beispiel #2
0
class TestScraperCoinmarketcap(unittest.TestCase):
    """
    Tests for Coinmarketcap Api commands. 
    These will fail in the absence of an internet 
    connection or if Coinmarketcap API goes down.
    """
    def setUp(self):
        self.coinmarketcap = Pymarketcap()

    def test_endpoints(self):
        from requests import get

        endpoints = [
            'currencies/%s/' % config.COIN_NAME,
            'gainers-losers/',
            'currencies/%s/historical-data/'\
                 % config.COIN_NAME,
            'new',
            'exchanges/%s/' % config.EXCHANGE,
            'exchanges/volume/24-hour/all/'
                    ]
        base_url = self.coinmarketcap.web_url

        for e in endpoints:
            _status_code = get(base_url + e).status_code
            self.assertEqual(_status_code, 200)

    def test_markets(self):
        actual = self.coinmarketcap.markets(config.COIN)
        value_types = {
            'price_usd': Decimal,
            '24h_volume_usd': int,
            'percent_volume': Decimal,
            'pair': str,
            'exchange': str
        }

        self.assertIs(type(actual), list)
        self.assertIs(len(actual) > 0, True)
        for source in actual:
            self.assertIs(type(source), dict)
            for key, value in source.items():
                self.assertIs(type(value), value_types[key])

    def test_ranks(self):
        temps = ['1h', '24h', '7d']
        queries = ['gainers', 'losers']
        value_types = {
            'percent_change': Decimal,
            '24h_volume_usd': int,
            'symbol': str,
            'price_usd': Decimal,
            'name': str
        }

        actual = self.coinmarketcap.ranks()

        self.assertIs(type(actual), dict)
        for q, temp in actual.items():
            self.assertIn(q, queries)
            self.assertIs(type(temp), dict)
            for t, data in temp.items():
                self.assertIn(t, temps)
                self.assertIs(type(data), list)
                self.assertIs(len(data) > 0, True)
                for d in data:
                    self.assertIs(type(d), dict)
                    for key, value in d.items():
                        self.assertIs(type(value), value_types[key])

        # Test invalid argument
        with self.assertRaises(AttributeError):
            self.coinmarketcap.ranks('8d')

    def test_historical(self):
        from datetime import datetime
        value_types = {
            'close': Decimal,
            'low': Decimal,
            'usd_volume': int,
            'open': Decimal,
            'usd_market_cap': int,
            'high': Decimal,
            'date': datetime
        }

        actual = self.coinmarketcap.historical(config.COIN,
                                               datetime(2017, 9, 30),
                                               datetime(2017, 10, 10))
        self.assertIs(type(actual), list)
        for tick in actual:
            self.assertIs(type(tick), dict)
            for key, value in tick.items():
                self.assertIs(type(value), value_types[key])

    def test_recently(self):
        actual = self.coinmarketcap.recently()
        value_types = {
            'price_usd': Decimal,
            'mineable': bool,
            'symbol': str,
            'usd_market_cap': [str, int],
            'circulating_supply': [str, int],
            'volume_24h_usd': [str, int],
            'days_ago': [str, int],
            'name': str
        }
        self.assertIs(type(actual), list)
        for c in actual:
            self.assertIs(type(c), dict)
            for key, value in c.items():
                if type(value_types[key]) is list:
                    self.assertIn(type(value), value_types[key])
                else:
                    self.assertIs(type(value), value_types[key])

    def test_exchange(self):
        actual = self.coinmarketcap.exchange(config.EXCHANGE)
        value_types = {
            'market': str,
            'price_usd': Decimal,
            'rank': int,
            'volume_24h_usd': int,
            'name': str,
            'perc_volume': Decimal
        }

        self.assertIs(type(actual), list)
        for market in actual:
            self.assertIs(type(market), dict)
            for key, value in market.items():
                self.assertIs(type(value), value_types[key])

    def test_exchanges(self):
        actual = self.coinmarketcap.exchanges()
        value_types = {
            'market': str,
            'price_usd': Decimal,
            'rank': int,
            'volume_24h_usd': int,
            'name': str,
            'perc_volume': Decimal,
            'perc_change': Decimal
        }

        self.assertIs(type(actual), list)
        for exch in actual:
            self.assertIs(type(exch), dict)
            for key, value in exch.items():
                if key in ('rank', 'volume_usd'):
                    self.assertIs(type(value), int)
                elif key == 'name':
                    self.assertIs(type(value), str)
                elif key == 'markets':
                    self.assertIs(type(value), list)
                    for m in value:
                        self.assertIs(type(m), dict)
                        for _key, _value in m.items():
                            self.assertIs(type(_value), value_types[_key])

    def test_exchange_names(self):
        actual = self.coinmarketcap.exchange_names
        self.assertIs(type(actual), list)
Beispiel #3
0
class TestScraperCoinmarketcap(unittest.TestCase):
    """
    Tests for Coinmarketcap Api commands.
    These will fail in the absence of an internet
    connection or if coinmarketcap.com goes down.
    """
    def __init__(self, *args, **kwargs):
        super(TestScraperCoinmarketcap, self).__init__(*args, **kwargs)
        self.coinmarketcap = Pymarketcap()
        self.config = ConfigTest()

    def tearDown(self):
        # Prevent to many requests error in tests
        time.sleep(.25)

    def test_markets(self):
        actual = self.coinmarketcap.markets(self.config.COIN)
        value_types = {
            'price_usd': Decimal,
            '24h_volume_usd': int,
            'percent_volume': Decimal,
            'pair': str,
            'exchange': str,
            'updated': bool
        }

        self.assertIs(type(actual), list)
        self.assertIs(len(actual) > 0, True)
        for source in actual:
            self.assertIs(type(source), dict)
            for key, value in source.items():
                self.assertIs(type(value), value_types[key])

    def test_ranks(self):
        temps = ['1h', '24h', '7d']
        queries = ['gainers', 'losers']
        value_types = {
            'percent_change': Decimal,
            '24h_volume_usd': int,
            'symbol': str,
            'price_usd': Decimal,
            'name': str
        }

        actual = self.coinmarketcap.ranks()

        self.assertIs(type(actual), dict)
        for q, temp in actual.items():
            self.assertIn(q, queries)
            self.assertIs(type(temp), dict)
            for t, data in temp.items():
                self.assertIn(t, temps)
                self.assertIs(type(data), list)
                self.assertIs(len(data) > 0, True)
                for d in data:
                    self.assertIs(type(d), dict)
                    for key, value in d.items():
                        self.assertIs(type(value), value_types[key])

        # Test invalid argument
        with self.assertRaises(AttributeError):
            self.coinmarketcap.ranks('8d')

    def test_historical(self):
        from datetime import datetime
        value_types = {
            'close': Decimal,
            'low': Decimal,
            'usd_volume': int,
            'open': Decimal,
            'usd_market_cap': int,
            'high': Decimal,
            'date': datetime
        }

        actual = self.coinmarketcap.historical(self.config.COIN,
                                               datetime(2017, 9, 30),
                                               datetime(2017, 10, 10))
        self.assertIs(type(actual), list)
        for tick in actual:
            self.assertIs(type(tick), dict)
            for key, value in tick.items():
                self.assertIs(type(value), value_types[key])

    def test_recently(self):
        actual = self.coinmarketcap.recently()
        value_types = {
            'price_usd': [Decimal, str],
            'mineable': bool,
            'symbol': str,
            'usd_market_cap': [str, int],
            'circulating_supply': [str, int],
            'volume_24h_usd': [str, int],
            'days_ago': [str, int],
            'name': str,
        }
        self.assertIs(type(actual), list)
        for c in actual:
            self.assertIs(type(c), dict)
            for key, value in c.items():
                if type(value_types[key]) is list:
                    self.assertIn(type(value), value_types[key])
                else:
                    self.assertIs(type(value), value_types[key])

    def test_exchange(self):
        actual = self.coinmarketcap.exchange(self.config.EXCHANGE)
        value_types = {
            'market': str,
            'price_usd': Decimal,
            'rank': int,
            'volume_24h_usd': int,
            'name': str,
            'perc_volume': Decimal
        }

        self.assertIs(type(actual), list)
        for market in actual:
            self.assertIs(type(market), dict)
            for key, value in market.items():
                self.assertIs(type(value), value_types[key])

    def test_exchanges(self):
        actual = self.coinmarketcap.exchanges()
        value_types = {
            'market': str,
            'price_usd': Decimal,
            'rank': int,
            'volume_24h_usd': int,
            'name': str,
            'perc_volume': Decimal,
            'perc_change': Decimal
        }

        self.assertIs(type(actual), list)
        for exch in actual:
            self.assertIs(type(exch), dict)
            for key, value in exch.items():
                if key in ('rank', 'volume_usd'):
                    self.assertIs(type(value), int)
                elif key == 'name':
                    self.assertIs(type(value), str)
                elif key == 'markets':
                    self.assertIs(type(value), list)
                    for m in value:
                        self.assertIs(type(m), dict)
                        for _key, _value in m.items():
                            self.assertIs(type(_value), value_types[_key])

    def test_exchange_names(self):
        actual = self.coinmarketcap.exchange_names
        self.assertIs(type(actual), list)

    def _assert_graphs_data_structure(self, data):
        self.assertIs(type(data), dict)

        for key, value in data.items():
            self.assertIs(type(value), list)
            for timestamp in value:
                self.assertIs(type(timestamp), list)
                for _value in timestamp:
                    self.assertIn(type(_value), (float, int))

    def test_graphs_currency(self):
        actual = self.coinmarketcap.graphs.currency(self.config.COIN)
        self._assert_graphs_data_structure(actual)

    def test_graphs_global_cap(self):
        actual = self.coinmarketcap.graphs.global_cap(bitcoin=True)
        self._assert_graphs_data_structure(actual)

    def test_graphs_dominance(self):
        actual = self.coinmarketcap.graphs.dominance()
        self._assert_graphs_data_structure(actual)

    def test_download_logo(self):
        filename = self.coinmarketcap.download_logo(self.config.COIN)
        self.assertNotEqual(filename, None)
        if filename:
            os.remove(filename)
Beispiel #4
0
class coinmarkets(object):
    def __init__(self, app):
        self.app = app
        self.webhook = "YOUR SLACK WEBHOOK"
        self.coinmarketcap = Pymarketcap()
        self.bittrex = ccxt.bittrex()
        self.poloniex = ccxt.poloniex()
        self.quadraigacx = ccxt.poloniex()
        self.exchanges = {
            'bittrex': self.bittrex,
            'poloniex': self.poloniex,
            'quadraigacx': self.quadraigacx,
            'coinmarketcap': self.coinmarketcap
        }
        self.loadMarkets()
        self.dispatch_map = {
            'showalert': self.showAlert,
            'removealert': self.removeAlert,
            'alert': self.createAlert,
            'topten': self.topten,
            'updatecoin': self.updatecoin,
            'gainers': self.gainers,
            'losers': self.losers,
            'symbols': self.symbols
        }
        alertFile = Path("alert.p")
        if alertFile.is_file():
            self.alerts = pickle.load(open('alert.p', "rb"))
        else:
            self.alerts = []
        self.symbols = []
        self.timeframe = ['7d', '24h', '1h']
        self.symbols = self.coinmarketcap.symbols
        self.coinmarket_latestinfo = []
        self.bittrex_latestinfo = []
        self.poloniex_latestinfo = []
        self.quadraigacx_latestinfo = []
        scheduler = BackgroundScheduler()
        scheduler.add_job(self.refreshinfo, 'interval', seconds=20)
        logging.basicConfig()
        scheduler.start()

    def parseCommand(self, command, text, responseUrl, username):
        args = tuple(text.split())
        #method = getattr(self, method_name, lambda: "nothing")
        print(text)
        print(args)
        print(command)
        if args:
            self.dispatch_map[command](args, responseUrl, username)
        else:
            self.dispatch_map[command](["empty"], responseUrl, username)
        return "processing request"

    def loadMarkets(self):
        self.bittrex.loadMarkets()
        self.poloniex.loadMarkets()
        self.quadraigacx.loadMarkets()

    def showAlert(self, args, responseUrl, username):
        if args[0] == "empty":
            results = tasks.search(self.alerts, 'username', username)
            if not results:
                tasks.sendTextResponse(responseUrl,
                                       "no alerts found for " + username,
                                       "ephemeral")
            else:
                data = simplejson.dumps(self.alerts, use_decimal=True)
                tasks.sendTextResponse(responseUrl, data, "ephemeral")
        else:
            if args[0] == "all":
                data = simplejson.dumps(self.alerts, use_decimal=True)
                tasks.sendTextResponse(responseUrl, data, "ephemeral")
                #tasks.sendJsonResponse(responseUrl, "all alerts" , data, "ephemeral")
            else:
                tasks.sendTextResponse(responseUrl, "invalid command",
                                       "ephemeral")

    def createAlert(self, args, responseUrl, username):
        # args = [cointype,price,market]
        btcUSD = 0
        timestamp = str(int(time.time()))
        if len(args) < 3:
            return "invalid command"
        else:
            market = args[2]

        if args[0] in self.symbols:
            symbol = str(args[0])
            if (symbol == "BTC"):
                pair = "BTC/USDT"
                exchange = self.exchanges[args[2]]
                currentPrice = exchange.fetch_ticker(pair)['last']
            else:
                pair = symbol + "/BTC"
                exchange = self.exchanges[args[2]]
                results = exchange.fetch_ticker(pair)
                if not results:
                    return tasks.sendTextResponse(
                        responseUrl, "currency not found in " + market,
                        "ephemeral")
                else:
                    btcUSD = exchange.fetch_ticker('BTC/USDT')['last']
                    currentPrice = float(results['last'] * btcUSD)

            if ('%' in args[1]):
                change = args[1].replace('%', ' ')
                if ('-' in change):
                    change = float(change.replace('-', ' '))
                    percentage = float((100 - change) / 100)
                    setPrice = float(percentage * float(currentPrice))
                else:
                    percentage = float((100 + float(change)) / 100)
                    setPrice = float(percentage * float(currentPrice))
            else:
                setPrice = float(args[1])
            if float(currentPrice) < setPrice:
                alertType = "high"
            elif float(currentPrice) > setPrice:
                alertType = 'low'  #alert when the price is lower than the setPrice
            else:
                return tasks.sendTextResponse(
                    responseUrl, "error: current price == set price",
                    "ephemeral")

            alert = {
                'symbol': symbol,
                'setPrice': setPrice,
                'market': market,
                'originalPrice': currentPrice,
                'type': alertType,
                'username': username,
                "timestamp": timestamp
            }
            self.alerts.append(alert)
            pickle.dump(self.alerts, open("alert.p", "wb"))
            tasks.createAlertResponse(alert, str(currentPrice),
                                      "Alert Created", responseUrl)
            return tasks.sendTextResponse(responseUrl, "command received",
                                          "ephemeral")
        else:
            return tasks.sendTextResponse(responseUrl, "invalid command",
                                          "ephemeral")

    def topten(self, args1, responseUrl, username):
        results = self.coinmarketcap.ticker(limit=10)
        results = results[0]
        print(results)
        return json.dumps(results, default=decimal_default)

    def updatecoin(self, args, responseUrl, username):
        if len(args) < 2:
            market = self.coinmarketcap.ticker(args[0], convert='USD')
            percentChange = " | 1h: " + str(
                market['percent_change_1h']) + " % " + " | 24h: " + str(
                    market['percent_change_24h']) + " % " + " | 7d: " + str(
                        market['percent_change_7d']) + " % "
            text = str("Current Price for " + str(args[0]) + ": " +
                       str(market['price_usd']) + percentChange + " | " +
                       "coinmarketcap")
            return tasks.sendTextResponse(responseUrl, text, "in_channel")
        elif args[1] == "all":
            data = self.coinmarketcap.markets(args[0])
            tasks.updateAllCoinHelper.delay(args, data, responseUrl)
        else:
            #data = self.coinmarketcap.exchange(args[1])
            exchange = self.exchanges[args[1]]
            tasks.updateCoinHelper(
                args,
                exchange,
                responseUrl,
            )
            return tasks.sendTextResponse(responseUrl, "updatecoin received",
                                          "ephemeral")

        return "command received"

    def symbols(self, args1, responseUrl, username):
        print(args1)
        print(self.coinmarketcap.symbols)

        return json.dumps(self.coinmarketcap.symbols)

    def gainers(self, args, responseUrl, username):
        if args[0] == "empty" or args[0] not in self.timeframe or args[
                0] == "1h":
            args[0] = '1h'
            json_data = (self.coinmarketcap.ranks('gainers', args[0])[args[0]])
        elif args[0] == '24h':
            json_data = (self.coinmarketcap.ranks('gainers', args[0])[args[0]])
        elif args[0] == '7d':
            json_data = (self.coinmarketcap.ranks('gainers', args[0])[args[0]])
        else:
            return tasks.sendTextResponse(responseUrl, "invalid timeframe",
                                          "ephemeral")
        tasks.gainerLoserHelper.delay(args, responseUrl, json_data, "gainers")
        return tasks.sendTextResponse(responseUrl, "top gainers received",
                                      "ephemeral")

    def losers(self, args, responseUrl, username):
        if args[0] == "empty" or args[0] not in self.timeframe or args[
                0] == "1h":
            json_data = (self.coinmarketcap.ranks('losers', '1h')['1h'])
        elif args[0] == '24h':
            json_data = (self.coinmarketcap.ranks('losers', args[0])[args[0]])
        elif args[0] == '7d':
            json_data = (self.coinmarketcap.ranks('losers', args[0])[args[0]])
        else:
            return tasks.sendTextResponse(responseUrl, "invalid timeframe",
                                          "ephemeral")
        tasks.gainerLoserHelper.delay(args, responseUrl, json_data, "losers")
        return tasks.sendTextResponse(responseUrl, "top losers received",
                                      "ephemeral")

    def refreshinfo(self):
        #self.coinmarket_latestinfo = self.coinmarketcap.ticker(limit=20)
        self.bittrex_latestinfo = self.bittrex.fetch_tickers()
        self.poloniex_latestinfo = self.poloniex.fetch_tickers()
        self.quadrigacx_latestinfo = self.quadraigacx.fetch_tickers()
        self.evaluateAlert(self.alerts)

    def removeAlert(self, args, responseUrl, username):
        for i, alert in enumerate(self.alerts):
            if alert['timestamp'] == args[0]:
                self.alerts.pop(i)
                pickle.dump(self.alerts, open("alert.p", "wb"))
                print("alerts list")
                print(*self.alerts)
                if responseUrl != "empty":
                    return tasks.sendTextResponse(
                        responseUrl,
                        "alert " + alert['timestamp'] + " removed",
                        "ephemeral")
                return "alert " + alert['timestamp'] + " removed"
        if responseUrl != "empty":
            return tasks.sendTextResponse(responseUrl, "alert not found",
                                          "ephemeral")
        return "alert not found"

    def evaluateAlert(self, alerts):
        if not alerts:
            return
        else:
            for i, alert in enumerate(alerts):
                alertType = alert["type"]
                if alert['market'] == 'coinmarketcap':
                    currentPrice = float(
                        self.coinmarketcap.ticker(alert['symbol'],
                                                  convert='USD')['price_usd'])
                    if alertType == 'low':
                        if (currentPrice <= float(alert['setPrice'])):
                            data = tasks.createAlertResponse(
                                alert, currentPrice, "Price reached",
                                self.webhook)
                            requests.post(self.webhook, json=data)
                            alerts.pop(i)
                    elif alertType == 'high':
                        if (currentPrice >= float(alert['setPrice'])):
                            data = tasks.createAlertResponse(
                                alert, currentPrice, "Price reached",
                                self.webhook)
                            requests.post(self.webhook, json=data)
                            alerts.pop(i)
                elif alert['market'] == 'bittrex':
                    tasks.sendAlert.delay(alerts, alert, self.webhook,
                                          self.bittrex_latestinfo)
                elif alert['market'] == 'quadrigacx':
                    tasks.sendAlert.delay(alerts, alert, self.webhook,
                                          self.quadrigacx_latestinfo)
                elif alert['market'] == 'poloniex':
                    tasks.sendAlert.delay(alerts, alert, self.webhook,
                                          self.poloniex_latestinfo)
class CryptoBacktester:
    def __init__(self, allowed_exchanges):
        self.allowed_exchanges = allowed_exchanges

        self.cmc = Pymarketcap()

        self.indicator_calc = IndicatorCalc()

    def filter_markets(self):
        ranks_filtered = {
            'gainers': {
                '1h': [],
                '24h': [],
                '7d': []
            },
            'losers': {
                '1h': [],
                '24h': [],
                '7d': []
            }
        }

        failed_products = {
            'gainers': {
                '1h': [],
                '24h': [],
                '7d': []
            },
            'losers': {
                '1h': [],
                '24h': [],
                '7d': []
            }
        }

        time_bins = ['1h', '24h', '7d']

        ranks = self.cmc.ranks()

        gainers = ranks['gainers']
        losers = ranks['losers']

        for bin in time_bins:
            logger.debug('bin: ' + str(bin))

            for mkt in gainers[bin]:
                logger.debug('[gainers] mkt: ' + str(mkt))

                try:
                    markets = self.cmc.markets(mkt['website_slug'])

                    for exch in markets['markets']:
                        if exch['source'].lower() in self.allowed_exchanges:
                            ranks_filtered['gainers'][bin].append((mkt, exch))

                except Exception as e:
                    logger.exception(e)

                    failed_products['gainers'][bin].append(mkt)

            for mkt in losers[bin]:
                logger.debug('[losers] mkt: ' + str(mkt))

                try:
                    markets = self.cmc.markets(mkt['website_slug'])

                    for exch in markets['markets']:
                        if exch['source'].lower() in self.allowed_exchanges:
                            ranks_filtered['losers'][bin].append((mkt, exch))

                except Exception as e:
                    logger.exception(e)

                    failed_products['losers'][bin].append(mkt)

        return ranks_filtered, failed_products

    def get_best_pairs(self, ranked_products):
        best_pairs = {'success': True, 'result': {}}

        #conversion_currencies = ['BTC', 'ETH', 'USD']

        try:
            for rank_type in ranked_products:
                logger.debug('rank_type: ' + rank_type)

                best_pairs['result'][rank_type] = {}

                for time_bin in ranked_products[rank_type]:
                    logger.debug('time_bin: ' + time_bin)

                    best_pairs['result'][rank_type][time_bin] = {}

                    for product in ranked_products[rank_type][time_bin]:
                        logger.debug('product: ' + str(product))

                        if product[0]['symbol'] not in best_pairs['result'][
                                rank_type][time_bin]:
                            best_pairs['result'][rank_type][time_bin][
                                product[0]['symbol']] = {}

                        if product[1]['pair'].split('/')[1] not in best_pairs[
                                'result'][rank_type][time_bin][product[0]
                                                               ['symbol']]:
                            best_pairs['result'][rank_type][time_bin][
                                product[0]['symbol']][product[1]['pair'].split(
                                    '/')[1]] = self.cmc.ticker(
                                        currency=product[0]['website_slug'],
                                        convert=product[1]['pair'].split('/')
                                        [1])['data']['quotes'][
                                            product[1]['pair'].split('/')[1]]

                            time.sleep(2)

        except Exception as e:
            logger.exception('Exception raised in get_best_pairs().')
            logger.exception(e)

            best_pairs['success'] = False

        finally:
            return best_pairs

    def get_candles(self, exchange, market, interval=0):
        candles = {'success': True, 'result': {}}

        #try:
        logger.debug('exchange: ' + exchange)
        logger.debug('market: ' + market)
        logger.debug('interval: ' + interval)

        valid_intervals = [
            60, 180, 300, 900, 1800, 3600, 7200, 14400, 21600, 43200, 86400,
            259200, 604800
        ]

        endpoint = '/markets/' + exchange.lower() + '/' + market.lower(
        ) + '/ohlc'

        url = 'https://api.cryptowat.ch' + endpoint

        url_params = {}

        if interval == 0:
            pass

        else:
            candle_url_param = str(int(round(float(interval), 0)))

            url_params['periods'] = candle_url_param

            if interval not in valid_intervals:
                logger.error(
                    'Invalid interval passed to get_candles(). Exiting.')

                sys.exit(1)

        try:
            r = requests.get(url, params=url_params)

            time.sleep(request_delay)

            results = r.json()

            if 'result' not in results or 'allowance' not in results:
                logger.debug(
                    '[get_candles()] Failed to acquire valid candles.')

                candles['success'] = False

                if 'error' in results:
                    logger.error('Error while calling Cryptowat.ch API.')
                    logger.error(results['error'])

                    if results['error'] == 'Out of allowance':
                        allowance_remaining = 0

            else:
                allowance_remaining = results['allowance']['remaining']
                allowance_cost = results['allowance']['cost']

                #allowance_avg_cost = average_api_cost(allowance_cost)

                if candles['success'] == True:
                    for time_bin in results['result']:
                        data = results['result'][time_bin]

                        np_historical = np.array(data, dtype='f8')

                        candles[time_bin] = {}

                        candles[time_bin]['close_time'] = np_historical[:, 0]
                        candles[time_bin]['open'] = np_historical[:, 1]
                        candles[time_bin]['high'] = np_historical[:, 2]
                        candles[time_bin]['low'] = np_historical[:, 3]
                        candles[time_bin]['close'] = np_historical[:, 4]
                        candles[time_bin]['volume'] = np_historical[:, 5]

        except requests.exceptions.RequestException as e:
            logger.exception('RequestException while retrieving candles.')
            logger.exception(e)

            #candle_data['RequestException'] = True
            candles['success'] = False

        except requests.exceptions.ConnectionError as e:
            logger.error('ConnectionError while retrieving candles.')
            logger.error(e)

            #candle_data['Error'] = True
            candles['success'] = False

        except json.JSONDecodeError as e:
            logger.error('JSONDecodeError while retrieving candles.')
            logger.error(e)

            #candle_data['Error'] = True
            candles['success'] = False

        except Exception as e:
            logger.exception('Uncaught exception while retrieving candles.')
            logger.exception(e)

            #candle_data['Exception'] = True
            candles['success'] = False

        finally:
            return candles