Пример #1
0
def get_coin_pair_data(exclude=[], include=[]):
    cg = CoinGeckoAPI()
    coins = cg.get_coins_list()
    random.shuffle(coins)
    coin_data = []
    for coin in coins:
        try:
            market_data = cg.get_coin_by_id(coin['id'])['tickers']
            pairs_data = []
            for i in market_data:
                market = i['market']['name']
                price = float(i['converted_last']['usd'])
                volume = float(i['converted_volume']['usd'])
                info = {
                    'market': market,
                    'price': price,
                    'target': i['target'],
                    'volume': volume
                }
                if len(include) == 0:
                    if market not in exclude:
                        pairs_data.append(info)
                else:
                    if market in include:
                        pairs_data.append(info)
            coin_data.append({'name': i['base'], 'market data': pairs_data})
        except:
            continue
    return (coin_data)
Пример #2
0
def single_coin_exchanges(coin):
    cg = CoinGeckoAPI()
    exchange_info = []
    Exchanges = namedtuple('Exchanges', 'name volume')
    data = cg.get_coin_by_id(coin.lower())['tickers']
    names = [name['market']['name'] for name in data if name['target'] == 'USDT']
    volumes = [round(vol['volume'], 2) for vol in data if vol['target'] == 'USDT']
    for i in range(5):
        exchange = Exchanges(name=names[i], volume=volumes[i])
        exchange_info.append(exchange)
    return exchange_info
Пример #3
0
def single_coin_data(coin):
    cg = CoinGeckoAPI()
    SingleCoin = namedtuple('SingleCoin', 'id symbol link1 link2 image market_cap_rank ath price mcap volume')
    data = cg.get_coin_by_id(coin.lower())
    id = data['id'].title()
    symbol = data['symbol'].upper()
    link1 = data['links']['homepage'][0]
    link2 = data['links']['blockchain_site'][0]
    image = data['image']['small']
    market_cap_rank = data['market_cap_rank']
    price_data = cg.get_coins_markets('usd')[market_cap_rank-1]
    ath = '$' + str(data['market_data']['ath']['usd'])
    price = price_data['current_price']
    mcap = price_data['market_cap']
    volume = price_data['total_volume']
    return SingleCoin(id=id, symbol=symbol, link1=link1, link2=link2, image=image,
                      market_cap_rank=market_cap_rank, ath=ath, price=price, mcap=mcap, volume=volume)
Пример #4
0
def get_coin_pair_data(exclude=[], include_exchanges=[], include_coins=[]):
    cg = CoinGeckoAPI()
    coins = []
    if (include_coins == []):
        coins = cg.get_coins_list()
        random.shuffle(coins)
    else:
        coins = include_coins

    coin_data = []
    for coin in coins:
        print("Getting coin: " + coin["id"])
        try:
            market_data = cg.get_coin_by_id(coin['id'])['tickers']
            pairs_data = []
            for i in market_data:
                market = i['market']['name']
                price = float(i['converted_last']['usd'])
                volume = float(i['converted_volume']['usd'])
                info = {
                    'market': market,
                    'price': price,
                    'target': i['target'],
                    'volume': volume
                }
                if len(include_exchanges) == 0:
                    if market not in exclude:
                        pairs_data.append(info)
                else:
                    if market in include_exchanges:
                        pairs_data.append(info)
            coin_data.append({'name': i['base'], 'market data': pairs_data})
        except Exception as e:
            print("ERROR:")
            print(e)
            continue
    return (coin_data)
Пример #5
0
class CryptoCommands(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

        self.cg = CoinGeckoAPI()
        self.coinlist = self.cg.get_coins_list()
        self.top300coins = self.cg.get_coins_markets(
            'usd', per_page=250) + self.cg.get_coins_markets(
                'usd', per_page=50, page=6)

    @staticmethod
    def isNumber(arg):
        """
        Check if the argument is a number (different from isnumeric() builtin method)
        :param arg: the number to check.
        :return: True if the arg is a number. Else False.
        """
        if arg == "nan":  # float() considers "nan" is a number
            return False  # but i dont want it.
        try:
            float(arg)
            return True
        except ValueError:
            return False

    @staticmethod
    def localizeNB(arg):
        """
        Format the number to be more easily readable.
        :param arg: the integer to format.
        :return: a string.
        """
        return locale.format_string("%d", arg, grouping=True)

    def get_coin_by_regex(self, arg):
        """
        Search the id or name or symbol in the list of coins provided by the API.
        :param arg: the string to search.
        :return:  either a list or raise an error if the query provided by the user is invalid.
        """
        for coin in self.coinlist:
            for coin_names in coin.values():
                r = re.search(f'(?<!\S){arg}(?!\S)', coin_names)
                if r is not None:
                    return self.cg.get_coin_by_id(coin['id'])

        raise InvalidCoinID  # Will raise exception if arg is not found in the list

    @commands.command(name='ath')
    async def comm_get_ath(self, ctx, arg):
        """
        Return the ATH of the coin
        :param ctx: Discord context
        :param arg: the coin
        :return: Discord embed
        """
        logger.info(f'{ctx.author} asked {ctx.command} with {arg}')
        try:
            coin = self.get_coin_by_regex(arg)

            date = coin['market_data']['ath_date']['eur']
            day = re.search("[0-9]{4}-[0-9]{2}-[0-9]{2}", date).group()
            time = re.search("[0-9]{2}:[0-9]{2}:[0-9]{2}", date).group()
            diff = datetime.datetime.today() - datetime.datetime.strptime(
                day, "%Y-%m-%d")

            embed = discord.Embed(
                title=f"{coin['name']} ATH",
                color=discord.Color.blurple(),
                url=f'https://www.coingecko.com/en/coins/{coin["id"]}')

            embed.set_thumbnail(url=coin['image']['small'])
            embed.add_field(name='USD',
                            value=coin['market_data']['ath']['usd'],
                            inline=True)
            embed.add_field(name='EUR',
                            value=coin['market_data']['ath']['eur'],
                            inline=True)
            embed.add_field(name='Date',
                            value=f'{day} {time} ({diff.days} days ago)',
                            inline=False)
            embed.set_footer(text=f'Powered by coingecko.com')

            await ctx.send(embed=embed)

        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='mcsim', aliases=['sim'])
    async def comm_get_mcsim(self, ctx, *args):
        """
        Simulate the market cap of a coin with the given price
        :param ctx: Discord context
        :param args: the coin then the wanted price
        :return: Discord embed
        """
        if len(args) != 2:
            await ctx.send("Not enough parameters provided (2 required).")
            return
        logger.info(
            f'{ctx.author} asked {ctx.command} with {args[0]}/{args[1]}')

        try:
            if not str(args[0]).isalpha():
                await ctx.send("Parameter 1 has to be a string.")
                return
            if not self.isNumber(args[1]):
                await ctx.send("Parameter 2 has to be number.")
                return

            coin = self.get_coin_by_regex(args[0])

            embed = discord.Embed(
                title=f"{coin['name']} simulated market cap (USD)",
                color=discord.Color.blurple(),
                url=f'https://www.coingecko.com/en/coins/{coin["id"]}')

            wantedSimPrice = float(args[1])

            mcSimmed = coin['market_data'][
                'circulating_supply'] * wantedSimPrice
            if coin['market_data']['total_supply']:
                mcMaxSimmed = self.localizeNB(
                    coin['market_data']['total_supply'] * wantedSimPrice)
            else:
                mcMaxSimmed = "infinite supply"
            # marketcap = coin['market_data']['market_cap']['usd']

            leng = len(self.top300coins) - 1
            estimatedRank = 301
            while mcSimmed > self.top300coins[leng]['market_cap'] and leng > 0:
                leng -= 1
                estimatedRank = self.top300coins[leng]['market_cap_rank']

            if estimatedRank == 301:
                estimatedRank = "300+"

            currentPrice = coin['market_data']['current_price']['usd']

            currentPrice = round(
                currentPrice,
                6) if currentPrice < 10 else self.localizeNB(currentPrice)

            simmedprice = round(
                wantedSimPrice,
                6) if wantedSimPrice < 10 else self.localizeNB(wantedSimPrice)

            marketcap = self.localizeNB(
                coin['market_data']['market_cap']['usd'])

            mcSimmed = self.localizeNB(mcSimmed)

            embed.set_thumbnail(url=coin['image']['small'])
            embed.add_field(name='Current price',
                            value=f"{currentPrice}",
                            inline=True)
            embed.add_field(name='Current market cap',
                            value=f"{marketcap}",
                            inline=True)
            embed.add_field(name='\u200B', value='\u200B', inline=True)
            embed.add_field(name='Simulated price',
                            value=f"{simmedprice}",
                            inline=True)
            embed.add_field(name='Simulated market cap',
                            value=f"{mcSimmed}",
                            inline=True)
            embed.add_field(name='\u200B', value='\u200B', inline=True)
            embed.add_field(name='Simulated market cap with max supply',
                            value=f"{mcMaxSimmed}",
                            inline=False)
            embed.add_field(name='Simulated market cap rank',
                            value=f"{estimatedRank}",
                            inline=False)

            embed.set_footer(text=f'Powered by coingecko.com')

            await ctx.send(embed=embed)

        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='trending')
    async def comm_get_trending(self, ctx):
        """
        Return the seven trending coins on CoinGecko
        :param ctx: Discord context
        :return: Discord embed
        """
        logger.info(f'{ctx.author} asked {ctx.command}')
        try:
            trending = self.cg.get_search_trending()['coins']

            def text_with_url(text, link):
                return f"[{text}](https://www.coingecko.com/en/coins/{link})"

            embed = discord.Embed(title="Top 7 trending coin in the last 24h",
                                  color=discord.Color.blurple())

            listcoins = []
            top7_dict = {}

            for coin in trending:
                listcoins.append(coin['item']['id'])

            # Because Coingecko's get_search_trending() doesn't return prices we have to get them ourselves
            clist = self.cg.get_price(ids=listcoins,
                                      vs_currencies=['usd'],
                                      include_24hr_change='true').items()
            for name, prices in clist:
                top7_dict[name] = prices

            for coin in trending:
                embed.add_field(name=f"Top {coin['item']['score'] + 1}",
                                value=text_with_url(coin['item']['name'],
                                                    coin['item']['id']),
                                inline=True)
                embed.add_field(
                    name=f"Value",
                    value=f"{round(top7_dict[coin['item']['id']]['usd'], 5)}",
                    inline=True)
                embed.add_field(
                    name=f"24h change",
                    value=
                    f"{round(top7_dict[coin['item']['id']]['usd_24h_change'], 2)}%",
                    inline=True)

            embed.set_footer(text=f'Powered by coingecko.com')

            await ctx.send(embed=embed)

        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='binance')
    async def comm_get_binance(self, ctx, arg):
        """
        Check if the coin is available on Binance exchange platform
        :param ctx: Discord context
        :param arg: the coin
        :return: Discord embed
        """
        logger.info(f'{ctx.author} asked {ctx.command}')
        try:
            coin = self.get_coin_by_regex(arg)

            binance = False
            for x in coin['tickers']:
                if binance is False:
                    if x['market']['name'] == 'Binance':
                        binance = True

            if binance:
                await ctx.send(
                    f"{coin['name']} is avaible on Binance! :white_check_mark:"
                )
            else:
                await ctx.send(f"{coin['name']} is NOT avaible on Binance! :x:"
                               )

        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='randomcoin')
    async def comm_randomcoin(self, ctx):
        """
        Return a random coin from the 300 market cap coin if the coin is available
        on Binance exchange platform and with the USDT pair.
        :param ctx: Discord context
        :return: Discord embed
        """
        logger.info(f'{ctx.author} asked {ctx.command}')
        try:
            temp = discord.Embed(
                title=
                'Please wait while I find the next Moon shot :rocket::full_moon_with_face:',
                color=discord.Color.blurple(),
            )
            msg = await ctx.send(embed=temp)

            async def get_coin():
                ccoin = self.cg.get_coin_by_id(
                    random.choice(self.top300coins)['id'])
                binance = False
                usdt = False
                for x in ccoin['tickers']:
                    if usdt is False:
                        if x['target'] == "USDT":
                            usdt = True
                    if binance is False:
                        if x['market']['name'] == 'Binance':
                            binance = True

                if False in (binance, usdt):
                    await get_coin()

                return ccoin

            coin = await get_coin()

            embed = discord.Embed(
                title=coin['name'],
                color=discord.Color.blurple(),
                url=f'https://www.coingecko.com/en/coins/{coin["id"]}')

            marketcap = self.localizeNB(
                coin['market_data']['market_cap']['usd'])

            embed.add_field(name='Available with USDT',
                            value='Yes :white_check_mark:',
                            inline=True)
            embed.add_field(name='Available on Binance',
                            value='Yes :white_check_mark:',
                            inline=True)
            embed.add_field(name='\u200B', value='\u200B', inline=True)

            embed.add_field(name='Market cap',
                            value=f"{marketcap} USD",
                            inline=True)
            embed.add_field(name='USD price',
                            value=coin['market_data']['current_price']['usd'],
                            inline=True)

            embed.set_thumbnail(url=coin['image']['small'])

            embed.set_footer(text=f'Powered by coingecko.com')

            await msg.edit(content=None, embed=embed)

        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='getcurr', aliases=['curr'])
    async def comm_getcurr(self, ctx, arg):
        """
        Return basic infos of the coin
        :param ctx: Discord contect
        :param arg: the coin
        :return: Discord emebed
        """
        logger.info(f'{ctx.author} asked {ctx.command} with {arg}')
        try:
            coin = self.get_coin_by_regex(arg)

            diff = coin['market_data']['price_change_percentage_24h']

            if diff >= 0.00:
                color = discord.Color.green()
                diff = f'+{diff}% :chart_with_upwards_trend:'
            else:
                color = discord.Color.red()
                diff = f'{diff}% :chart_with_downwards_trend:'

            embed = discord.Embed(
                title=coin['name'],
                color=color,
                url=f'https://www.coingecko.com/en/coins/{coin["id"]}')

            marketcap = self.localizeNB(
                coin['market_data']['market_cap']['usd'])

            circulating_supply = self.localizeNB(
                coin['market_data']['circulating_supply'])
            if coin['market_data']['total_supply']:
                percentSupply = round(
                    (coin['market_data']['circulating_supply'] /
                     coin['market_data']['total_supply']) * 100, 2)
                circulating_supply = f"{circulating_supply} ({percentSupply}%)"

            embed.set_thumbnail(url=coin['image']['small'])
            embed.add_field(name='USD',
                            value=coin['market_data']['current_price']['usd'],
                            inline=True)
            embed.add_field(name='EUR',
                            value=coin['market_data']['current_price']['eur'],
                            inline=True)
            embed.add_field(name='24h difference', value=diff, inline=False)
            embed.add_field(
                name='Market cap (#rank)',
                value=f"{marketcap} USD (#{coin['market_cap_rank']})",
                inline=False)
            embed.add_field(name='Circulating supply',
                            value=f"{circulating_supply}",
                            inline=False)

            embed.set_footer(text=f'Powered by coingecko.com')

            await ctx.send(embed=embed)

        except (ValueError, TypeError) as e:
            logger.exception(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified ({arg})")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='getcurrmore', aliases=['more'])
    async def comm_getcurrmore(self, ctx, arg):
        """
        Return a bit more infos on the coin
        :param ctx: Discord context
        :param arg: the coin
        :return: Discord embed
        """
        logger.info(f'{ctx.author} asked {ctx.command} with {arg}')
        try:
            coin = self.get_coin_by_regex(arg)

            embed = discord.Embed(
                title=coin['name'],
                color=discord.Color.blurple(),
                url=f'https://www.coingecko.com/en/coins/{coin["id"]}')

            embed.set_thumbnail(url=coin['image']['small'])
            embed.add_field(
                name='Highest 24h',
                value=
                f"{coin['market_data']['high_24h']['eur']}€ / {coin['market_data']['high_24h']['usd']}$",
                inline=True)
            embed.add_field(
                name='Lowest 24h',
                value=
                f"{coin['market_data']['low_24h']['eur']}€ / {coin['market_data']['low_24h']['usd']}$",
                inline=True)
            embed.add_field(name='\u200B', value='\u200B', inline=True)
            embed.add_field(
                name='7 days difference',
                value=round(coin['market_data']['price_change_percentage_7d'],
                            2),
                inline=True)
            embed.add_field(
                name='14 days difference',
                value=round(coin['market_data']['price_change_percentage_14d'],
                            2),
                inline=True)
            embed.add_field(name='\u200B', value='\u200B', inline=True)

            await ctx.send(embed=embed)

        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")

    @commands.command(name='top10', aliases=['top'])
    async def get_top10(self, ctx):
        logger.info(f'{ctx.author} asked {ctx.command}')

        top5 = self.cg.get_coins_markets('usd', per_page=5)
        top10 = self.cg.get_coins_markets('usd', per_page=5, page=2)

        def text_with_url(text, cid):
            return f"[{text}](https://www.coingecko.com/en/coins/{cid})"

        embed = discord.Embed(
            title="Top 10 market cap (1/2)",
            color=discord.Color.blurple(),
        )

        embed2 = discord.Embed(
            title="Top 10 market cap (2/2)",
            color=discord.Color.blurple(),
        )

        for coin in top5:
            embed.add_field(name=f"Top {coin['market_cap_rank']}",
                            value=text_with_url(coin['name'], coin['id']),
                            inline=True)
            embed.add_field(name=f"Value",
                            value=f"{round(coin['current_price'], 5)}",
                            inline=True)
            embed.add_field(
                name=f"24h change",
                value=f"{round(coin['price_change_percentage_24h'], 2)}%",
                inline=True)
        await ctx.send(embed=embed)

        for coin in top10:
            embed2.add_field(name=f"Top {coin['market_cap_rank']}",
                             value=text_with_url(coin['name'], coin['id']),
                             inline=True)
            embed2.add_field(name=f"Value",
                             value=f"{round(coin['current_price'], 5)}",
                             inline=True)
            embed2.add_field(
                name=f"24h change",
                value=f"{round(coin['price_change_percentage_24h'], 2)}%",
                inline=True)
        await ctx.send(embed=embed2)

    @commands.command(name='kill')
    async def comm_kill(self, ctx, arg):
        """
        (Fun command) Return a message stating that the coin have been killed
        :param ctx: Discord context
        :param arg: the coin
        :return: Discord message
        """
        logger.info(f'{ctx.author} asked {ctx.message} with {arg}')

        try:
            coin = self.get_coin_by_regex(arg)

            excla = "!" * random.randrange(2, 12)
            msg = f"{coin['name']} has been killed{excla}"
            await ctx.send(msg)
        except (ValueError, TypeError) as e:
            logger.warning(e)
            await ctx.send(e)
        except InvalidCoinID:
            logger.warning(f"Wrong coin specified.")
            await ctx.send(f"Can not find requested crypto.")
Пример #6
0
class Coin:
    """Coin class, it holds loaded coin"""
    def __init__(self, symbol: str, load_from_api: bool = False):
        self.client = CoinGeckoAPI()
        if load_from_api:
            self._coin_list = self.client.get_coins_list()
        else:
            self._coin_list = read_file_data("coingecko_coins.json")
        self.coin_symbol, self.symbol = self._validate_coin(symbol)

        if self.coin_symbol:
            self.coin: Dict[Any, Any] = self._get_coin_info()

    def __str__(self):
        return f"{self.coin_symbol}"

    def _validate_coin(
            self, search_coin: str) -> Tuple[Optional[Any], Optional[Any]]:
        """Validate if given coin symbol or id exists in list of available coins on CoinGecko.
        If yes it returns coin id. [Source: CoinGecko]

        Parameters
        ----------
        symbol: str
            Either coin symbol or coin id

        Returns
        -------
        Tuple[str, str]
            - str with coin
            - str with symbol
        """

        coin = None
        symbol = None
        for dct in self._coin_list:
            if search_coin.lower() in [
                    dct["id"],
                    dct["symbol"],
            ]:
                coin = dct.get("id")
                symbol = dct.get("symbol")
                return coin, symbol
        raise ValueError(
            f"Could not find coin with the given id: {search_coin}\n")

    def coin_list(self) -> list:
        """List all available coins [Source: CoinGecko]

        Returns
        -------
        list
            list of all available coin ids
        """

        return [token.get("id") for token in self._coin_list]

    def _get_coin_info(self) -> dict:
        """Helper method which fetch the coin information by id from CoinGecko API like:
         (name, price, market, ... including exchange tickers) [Source: CoinGecko]

        Returns
        -------
        dict
            Coin information
        """

        params = dict(localization="false", tickers="false", sparkline=True)
        return self.client.get_coin_by_id(self.coin_symbol, **params)

    def _get_links(self) -> Dict:
        """Helper method that extracts links from coin [Source: CoinGecko]

        Returns
        -------
        dict
            Links related to coin
        """

        return self.coin.get("links", {})

    @property
    def get_repositories(self) -> Optional[Any]:
        """Get list of all repositories for given coin [Source: CoinGecko]

        Returns
        -------
        list
            Repositories related to coin
        """

        return self._get_links().get("repos_url")

    @property
    def get_developers_data(self) -> pd.DataFrame:
        """Get coin development data from GitHub or BitBucket like:
            number of pull requests, contributor etc [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Developers Data
            Columns: Metric, Value
        """

        dev = self.coin.get("developer_data", {})
        useless_keys = (
            "code_additions_deletions_4_weeks",
            "last_4_weeks_commit_activity_series",
        )
        remove_keys(useless_keys, dev)
        df = pd.Series(dev).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)

        return df[df["Value"].notna()]

    @property
    def get_blockchain_explorers(self) -> Union[pd.DataFrame, Any]:
        """Get list of URLs to blockchain explorers for given coin. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Blockchain Explorers
            Columns: Metric, Value
        """

        blockchain = self._get_links().get("blockchain_site")
        if blockchain:
            dct = filter_list(blockchain)
            df = pd.Series(dct).to_frame().reset_index()
            df.columns = ["Metric", "Value"]
            df["Metric"] = df["Metric"].apply(
                lambda x: replace_underscores_in_column_names(x)
                if isinstance(x, str) else x)
            return df[df["Value"].notna()]
        return None

    @property
    def get_social_media(self) -> pd.DataFrame:
        """Get list of URLs to social media like twitter, facebook, reddit... [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Urls to social media
            Columns: Metric, Value
        """

        social_dct = {}
        links = self._get_links()
        for (channel) in CHANNELS.keys():  # pylint: disable=consider-iterating-dictionary)
            if channel in links:
                value = links.get(channel, "")
                if channel == "twitter_screen_name":
                    value = "https://twitter.com/" + value
                elif channel == "bitcointalk_thread_identifier" and value is not None:
                    value = f"https://bitcointalk.org/index.php?topic={value}"
                social_dct[channel] = value
        social_dct["discord"] = find_discord(links.get("chat_url"))
        dct = rename_columns_in_dct(social_dct, CHANNELS)
        df = pd.Series(dct).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)
        return df[df["Value"].notna()]

    @property
    def get_websites(self) -> pd.DataFrame:
        """Get list of URLs to websites like homepage of coin, forum. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Urls to website, homepage, forum
            Columns: Metric, Value
        """

        websites_dct = {}
        links = self._get_links()
        sites = ["homepage", "official_forum_url", "announcement_url"]
        for site in sites:
            websites_dct[site] = filter_list(links.get(site))
        df = pd.Series(websites_dct).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Value"] = df["Value"].apply(lambda x: ",".join(x))
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)
        return df[df["Value"].notna()]

    @property
    def get_categories(self) -> Union[Dict[Any, Any], List[Any]]:
        """Coins categories. [Source: CoinGecko]

        Returns
        -------
        list/dict
            Coin categories
        """

        return self.coin.get("categories", {})

    def _get_base_market_data_info(self) -> dict:
        """Helper method that fetches all the base market/price information about given coin. [Source: CoinGecko]

        Returns
        -------
        dict
            All market related information for given coin
        """
        market_dct = {}
        market_data = self.coin.get("market_data", {})
        for stat in [
                "total_supply",
                "max_supply",
                "circulating_supply",
                "price_change_percentage_24h",
                "price_change_percentage_7d",
                "price_change_percentage_30d",
        ]:
            market_dct[stat] = market_data.get(stat)
        prices = create_dictionary_with_prefixes(["current_price"],
                                                 market_data, DENOMINATION)
        market_dct.update(prices)
        return market_dct

    @property
    def get_base_info(self) -> pd.DataFrame:
        """Get all the base information about given coin. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Base information about coin
        """

        regx = r'<a href="(.+?)">|</a>'

        results = {}
        for attr in BASE_INFO:
            info_obj = self.coin.get(attr, {})
            if attr == "description":
                info_obj = info_obj.get("en")
                info_obj = re.sub(regx, "", info_obj)
                info_obj = re.sub(r"\r\n\r\n", " ", info_obj)
            results[attr] = info_obj
        results.update(self._get_base_market_data_info())
        df = pd.Series(results).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)

        return df[df["Value"].notna()]

    @property
    def get_market_data(self) -> pd.DataFrame:
        """Get all the base market information about given coin. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Base market information about coin
            Metric,Value
        """

        market_data = self.coin.get("market_data", {})
        market_columns_denominated = [
            "market_cap",
            "fully_diluted_valuation",
            "total_volume",
            "high_24h",
            "low_24h",
        ]
        denominated_data = create_dictionary_with_prefixes(
            market_columns_denominated, market_data, DENOMINATION)

        market_single_columns = [
            "market_cap_rank",
            "total_supply",
            "max_supply",
            "circulating_supply",
            "price_change_percentage_24h",
            "price_change_percentage_7d",
            "price_change_percentage_30d",
            "price_change_percentage_60d",
            "price_change_percentage_1y",
            "market_cap_change_24h",
        ]
        single_stats = {}
        for col in market_single_columns:
            single_stats[col] = market_data.get(col)
        single_stats.update(denominated_data)

        try:
            single_stats["circulating_supply_to_total_supply_ratio"] = (
                single_stats["circulating_supply"] /
                single_stats["total_supply"])
        except (ZeroDivisionError, TypeError) as e:
            console.print(e)
        df = pd.Series(single_stats).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)
        return df[df["Value"].notna()]

    def get_all_time_high(self, currency: str = "usd") -> pd.DataFrame:
        """Get all time high data for given coin. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            All time high price data
            Metric,Value
        """

        market_data = self.coin.get("market_data", {})
        if market_data == {}:
            return pd.DataFrame()
        ath_columns = [
            "current_price",
            "ath",
            "ath_date",
            "ath_change_percentage",
        ]

        results = {}
        for column in ath_columns:
            results[column] = market_data[column].get(currency)

        df = pd.Series(results).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)
        df["Metric"] = df["Metric"].apply(
            lambda x: x.replace("Ath", "All Time High"))
        df["Metric"] = df["Metric"] + f" {currency.upper()}"
        return df[df["Value"].notna()]

    def get_all_time_low(self, currency: str = "usd") -> pd.DataFrame:
        """Get all time low data for given coin. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            All time low price data
            Metric,Value
        """

        market_data = self.coin.get("market_data", {})
        if market_data == {}:
            return pd.DataFrame()

        ath_columns = [
            "current_price",
            "atl",
            "atl_date",
            "atl_change_percentage",
        ]
        results = {}
        for column in ath_columns:
            results[column] = market_data[column].get(currency)

        df = pd.Series(results).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)
        df["Metric"] = df["Metric"].apply(
            lambda x: x.replace("Atl", "All Time Low"))
        df["Metric"] = df["Metric"] + f" {currency.upper()}"
        return df[df["Value"].notna()]

    @property
    def get_scores(self) -> pd.DataFrame:
        """Get different kind of scores for given coin. [Source: CoinGecko]

        Returns
        -------
        pandas.DataFrame
            Social, community, sentiment scores for coin
            Metric,Value
        """

        score_columns = [
            "coingecko_rank",
            "coingecko_score",
            "developer_score",
            "community_score",
            "liquidity_score",
            "sentiment_votes_up_percentage",
            "sentiment_votes_down_percentage",
            "public_interest_score",
            "community_data",
            "public_interest_stats",
        ]

        single_stats = {col: self.coin.get(col) for col in score_columns[:-2]}
        nested_stats = {}
        for col in score_columns[-2:]:
            _dct = self.coin.get(col, {})
            for k, _ in _dct.items():
                nested_stats[k] = _dct.get(k, {})

        single_stats.update(nested_stats)
        df = pd.Series(single_stats).reset_index()
        df.replace({0: ""}, inplace=True)
        df = df.fillna("")
        df.columns = ["Metric", "Value"]

        # pylint: disable=unsupported-assignment-operation
        df["Metric"] = df["Metric"].apply(
            lambda x: replace_underscores_in_column_names(x)
            if isinstance(x, str) else x)
        return df[df["Value"].notna()]

    def get_coin_market_chart(self,
                              vs_currency: str = "usd",
                              days: int = 30,
                              **kwargs: Any) -> pd.DataFrame:
        """Get prices for given coin. [Source: CoinGecko]

        Parameters
        ----------
        vs_currency: str
            currency vs which display data
        days: int
            number of days to display the data
        kwargs

        Returns
        -------
        pandas.DataFrame
            Prices for given coin
            Columns: time, price, currency
        """

        prices = self.client.get_coin_market_chart_by_id(
            self.coin_symbol, vs_currency, days, **kwargs)
        prices = prices["prices"]
        df = pd.DataFrame(data=prices, columns=["time", "price"])
        df["time"] = pd.to_datetime(df.time, unit="ms")
        df = df.set_index("time")
        df["currency"] = vs_currency
        return df

    def get_ohlc(self,
                 vs_currency: str = "usd",
                 days: int = 90) -> pd.DataFrame:
        """Get Open, High, Low, Close prices for given coin. [Source: CoinGecko]

        Parameters
        ----------
        vs_currency: str
            currency vs which display data
        days: int
            number of days to display the data
            on from (1/7/14/30/90/180/365, max)

        Returns
        -------
        pandas.DataFrame
            OHLC data for coin
            Columns: time, price, currency
        """

        prices = self.client.get_coin_ohlc_by_id(self.coin_symbol, vs_currency,
                                                 days)
        df = pd.DataFrame(data=prices,
                          columns=["time", "open", "high", "low", "close"])
        df["time"] = pd.to_datetime(df.time, unit="ms")
        df = df.set_index("time")
        df["currency"] = vs_currency
        return df
Пример #7
0
class CoinData:
    """Gathers all relevant data from the CoinGecko
    API, and returns it to the app pages."""
    def __init__(self) -> None:
        self.info = CoinGeckoAPI()

    def get_coin_by_ticker(self, coin_ticker):
        """A lookup that is used in case the user passes a
        coin's ticker into the form. Coins are only accessible
        via the API by their id, but users may pass in a ticker
        instead. This method handles that situation."""
        names = {
            coin['symbol']: coin['id']
            for coin in self.info.get_coins_list()
        }
        return names.get(coin_ticker.lower(), coin_ticker)

    def get_all_coin_data(self, logos):
        """This method returns the relevant data for all coins
        in the top 25 coins ranked by market cap."""
        top_coins = []
        for idx, item in enumerate(
                self.info.get_coins_markets('usd')[:TOP_COINS], start=1):
            coin = Coin(rank=idx,
                        logo=logos[idx - 1],
                        name=item['id'].title(),
                        price=item['current_price'],
                        market_cap=item['market_cap'],
                        volume=item['total_volume'],
                        change=item['price_change_24h'],
                        percent_change=round(
                            item['price_change_percentage_24h'], 2))
            top_coins.append(coin)
        return top_coins

    def single_coin_data(self, coin):
        """This method gathers all the relevant data for a single
        coin that the user may search for."""
        try:
            data = self.info.get_coin_by_id(coin.lower())
            id = data['id'].title()
            symbol = data['symbol'].upper()
            link1 = data['links']['homepage'][0]
            link2 = data['links']['blockchain_site'][0]
            image = data['image']['small']
            market_cap_rank = data['market_cap_rank']
            price_data = self.info.get_coins_markets('usd')[market_cap_rank -
                                                            1]
            ath = '$' + str(data['market_data']['ath']['usd'])
            price = price_data['current_price']
            mcap = price_data['market_cap']
            volume = price_data['total_volume']
            return SingleCoin(id=id,
                              symbol=symbol,
                              link1=link1,
                              link2=link2,
                              image=image,
                              market_cap_rank=market_cap_rank,
                              ath=ath,
                              price=price,
                              mcap=mcap,
                              volume=volume)
        except TypeError:
            pass

    def single_coin_exchanges(self, coin):
        """Gathers all relevant exchange data for a
        single coin."""
        exchange_info = []
        Exchanges = namedtuple('Exchanges', 'name volume')
        data = self.info.get_coin_by_id(coin.lower())['tickers']
        names = [
            name['market']['name'] for name in data if name['target'] == 'USDT'
        ]
        volumes = [
            round(vol['volume'], 2) for vol in data if vol['target'] == 'USDT'
        ]
        for i in range(TOP_EXCHANGES):
            exchange = Exchanges(name=names[i], volume=volumes[i])
            exchange_info.append(exchange)
        return exchange_info

    def portfolio_coins(self, user):
        """Gets all of the data for a user's coins
        to display on the portfolio page."""
        coin_list = []
        user_coins = PortfolioHoldings.objects.filter(person=user)
        for coin in user_coins.iterator():
            name = self.get_coin_by_ticker(coin.coin_ticker)
            image = self.single_coin_data(name).image
            coin = CoinSet(ticker=coin.coin_ticker,
                           amount=coin.number_of_coins,
                           usd=coin.amount_in_usd,
                           image=image)
            coin_list.append(coin)
        return coin_list
Пример #8
0
from pycoingecko import CoinGeckoAPI
cg = CoinGeckoAPI()

print("This shows the coin's market data.")
id = input("Enter the coin name - ")
data = cg.get_coin_by_id(id)['market_data']
print(id + 'coin current rank = ' + str(data['market_cap_rank']))

Пример #9
0
class QuoteProcessor(object):
    imageOverlays = {
        "Alpha depth":
        Image.open("app/assets/overlays/quotes/depth.png").convert("RGBA")
    }

    stableCoinTickers = [
        "USD", "USDT", "USDC", "DAI", "HUSD", "TUSD", "PAX", "USDK", "USDN",
        "BUSD", "GUSD", "USDS"
    ]
    lastBitcoinQuote = {}

    def __init__(self):
        self.isServiceAvailable = True
        signal.signal(signal.SIGINT, self.exit_gracefully)
        signal.signal(signal.SIGTERM, self.exit_gracefully)

        self.logging = error_reporting.Client(service="quote_server")

        self.coinGecko = CoinGeckoAPI()
        self.lastBitcoinQuote = {
            "quotePrice": [0],
            "quoteVolume":
            None,
            "ticker":
            Ticker("BTCUSD", "BTCUSD", "BTC", "USD", "BTC/USD",
                   hasParts=False),
            "exchange":
            None,
            "timestamp":
            time.time()
        }

        try:
            rawData = self.coinGecko.get_coin_by_id(id="bitcoin",
                                                    localization="false",
                                                    tickers=False,
                                                    market_data=True,
                                                    community_data=False,
                                                    developer_data=False)
            self.lastBitcoinQuote["quotePrice"] = [
                rawData["market_data"]["current_price"]["usd"]
            ]
            self.lastBitcoinQuote["quoteVolume"] = rawData["market_data"][
                "total_volume"]["usd"]
        except:
            pass

        context = zmq.Context.instance()
        self.socket = context.socket(zmq.ROUTER)
        self.socket.bind("tcp://*:6900")

        print("[Startup]: Quote Server is online")

    def exit_gracefully(self):
        print("[Startup]: Quote Server is exiting")
        self.socket.close()
        self.isServiceAvailable = False

    def run(self):
        while self.isServiceAvailable:
            try:
                response = None, None
                origin, delimeter, clientId, service, request = self.socket.recv_multipart(
                )
                request = pickle.loads(zlib.decompress(request))
                if request.timestamp + 60 < time.time(): continue

                if service == b"quote":
                    response = self.request_quote(request)
                elif service == b"depth":
                    response = self.request_depth(request)

            except (KeyboardInterrupt, SystemExit):
                return
            except Exception:
                print(traceback.format_exc())
                if os.environ["PRODUCTION_MODE"]:
                    self.logging.report_exception()
            finally:
                try:
                    self.socket.send_multipart([
                        origin, delimeter,
                        zlib.compress(pickle.dumps(response, -1))
                    ])
                except:
                    pass

    def request_depth(self, request):
        payload, quoteMessage, updatedQuoteMessage = None, None, None

        for platform in request.platforms:
            request.set_current(platform=platform)

            if platform == "CCXT":
                payload, updatedQuoteMessage = self.request_ccxt_depth(request)
            elif platform == "IEXC":
                payload, updatedQuoteMessage = self.request_iexc_depth(request)

            if payload is not None:
                if request.authorId != 401328409499664394 and request.requests[
                        platform].ticker.base is not None and request.authorId not in constants.satellites:
                    database.document("dataserver/statistics/{}/{}".format(
                        platform, str(uuid.uuid4()))).set({
                            "timestamp":
                            time.time(),
                            "authorId":
                            str(request.authorId),
                            "ticker": {
                                "base": request.requests[platform].ticker.base,
                                "quote":
                                request.requests[platform].ticker.quote,
                                "id": request.requests[platform].ticker.id,
                                "bias": request.parserBias
                            },
                            "exchange":
                            None if request.requests[platform].exchange is None
                            else request.requests[platform].exchange.id
                        })
                return payload, updatedQuoteMessage
            elif updatedQuoteMessage is not None:
                quoteMessage = updatedQuoteMessage

        return None, quoteMessage

    def request_quote(self, request):
        payload, quoteMessage, updatedQuoteMessage = None, None, None

        for platform in request.platforms:
            request.set_current(platform=platform)

            if platform == "Alternative.me":
                payload, updatedQuoteMessage = self.request_fear_greed_index(
                    request)
            elif platform == "LLD":
                payload, updatedQuoteMessage = self.request_lld_quote(request)
            elif platform == "CoinGecko":
                payload, updatedQuoteMessage = self.request_coingecko_quote(
                    request)
            elif platform == "CCXT":
                payload, updatedQuoteMessage = self.request_ccxt_quote(request)
            elif platform == "IEXC":
                payload, updatedQuoteMessage = self.request_iexc_quote(request)
            elif platform == "Quandl":
                pass

            if payload is not None:
                if request.authorId != 401328409499664394 and request.requests[
                        platform].ticker.base is not None and request.authorId not in constants.satellites:
                    database.document("dataserver/statistics/{}/{}".format(
                        platform, str(uuid.uuid4()))).set({
                            "timestamp":
                            time.time(),
                            "authorId":
                            str(request.authorId),
                            "ticker": {
                                "base": request.requests[platform].ticker.base,
                                "quote":
                                request.requests[platform].ticker.quote,
                                "id": request.requests[platform].ticker.id,
                                "bias": request.parserBias
                            },
                            "exchange":
                            None if request.requests[platform].exchange is None
                            else request.requests[platform].exchange.id
                        })
                return payload, updatedQuoteMessage
            elif updatedQuoteMessage is not None:
                quoteMessage = updatedQuoteMessage

        return None, quoteMessage

    def request_coingecko_quote(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        try:
            try:
                rawData = self.coinGecko.get_coin_by_id(id=ticker.symbol,
                                                        localization="false",
                                                        tickers=False,
                                                        market_data=True,
                                                        community_data=False,
                                                        developer_data=False)
            except:
                return None, None

            if ticker.quote.lower() not in rawData["market_data"][
                    "current_price"] or ticker.quote.lower(
                    ) not in rawData["market_data"]["total_volume"]:
                return None, "Requested price for `{}` is not available.".format(
                    ticker.name)

            price = rawData["market_data"]["current_price"][
                ticker.quote.lower()]
            if ticker.isReversed: price = 1 / price
            volume = rawData["market_data"]["total_volume"][
                ticker.quote.lower()]
            priceChange = rawData["market_data"][
                "price_change_percentage_24h_in_currency"][ticker.quote.lower(
                )] if ticker.quote.lower() in rawData["market_data"][
                    "price_change_percentage_24h_in_currency"] else 0
            if ticker.isReversed:
                priceChange = (1 / (priceChange / 100 + 1) - 1) * 100

            payload = {
                "quotePrice":
                str(price),
                "quoteVolume":
                volume,
                "title":
                ticker.name,
                "baseTicker":
                ticker.base,
                "quoteTicker":
                ticker.quote,
                "change":
                priceChange,
                "thumbnailUrl":
                TickerParser.get_coingecko_image(ticker.base),
                "messageColor":
                "amber" if priceChange == 0 else
                ("green" if priceChange > 0 else "red"),
                "sourceText":
                "from CoinGecko",
                "platform":
                "CoinGecko",
                "raw": {
                    "quotePrice": [price],
                    "quoteVolume": volume,
                    "ticker": ticker,
                    "exchange": exchange,
                    "timestamp": time.time()
                }
            }
            if ticker.quote != "USD":
                payload["quoteConvertedPrice"] = "≈ ${:,.6f}".format(
                    rawData["market_data"]["current_price"]["usd"])
                payload["quoteConvertedVolume"] = "≈ ${:,.4f}".format(
                    rawData["market_data"]["total_volume"]["usd"])

            if ticker == Ticker("BTCUSD",
                                "BTCUSD",
                                "BTC",
                                "USD",
                                "BTC/USD",
                                hasParts=False):
                self.lastBitcoinQuote = payload["raw"]
            return payload, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_ccxt_quote(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        try:
            if exchange is None: return None, None
            exchange = Exchange(exchange.id, "crypto")

            tf, limitTimestamp, candleOffset = Utils.get_highest_supported_timeframe(
                exchange.properties,
                datetime.datetime.now().astimezone(pytz.utc))
            try:
                rawData = exchange.properties.fetch_ohlcv(ticker.symbol,
                                                          timeframe=tf.lower(),
                                                          since=limitTimestamp,
                                                          limit=300)
                if len(rawData) == 0 or rawData[-1][4] is None or rawData[0][
                        1] is None:
                    return None, None
            except:
                return None, None

            price = [rawData[-1][4], rawData[0][1]
                     ] if len(rawData) < candleOffset else [
                         rawData[-1][4], rawData[-candleOffset][1]
                     ]
            if ticker.isReversed: price = [1 / price[0], 1 / price[1]]
            volume = None if price[0] is None else sum([
                candle[5] for candle in rawData if int(candle[0] / 1000) >=
                int(exchange.properties.milliseconds() / 1000) - 86400
            ]) / (
                price[0] if exchange.id in ["bitmex", "binancefutures"] else 1)
            priceChange = 0 if tf == "1m" or price[1] == 0 else (
                price[0] / price[1]) * 100 - 100

            payload = {
                "quotePrice":
                "{:,.8f}".format(price[0])
                if ticker.isReversed else TickerParser.get_formatted_price(
                    exchange.id, ticker.symbol, price[0]),
                "quoteVolume":
                volume,
                "title":
                ticker.name,
                "baseTicker":
                "USD" if ticker.base in QuoteProcessor.stableCoinTickers else
                ticker.base,
                "quoteTicker":
                "USD" if ticker.quote in QuoteProcessor.stableCoinTickers else
                ticker.quote,
                "change":
                priceChange,
                "thumbnailUrl":
                TickerParser.get_coingecko_image(ticker.base),
                "messageColor":
                "amber" if priceChange == 0 else
                ("green" if priceChange > 0 else "red"),
                "sourceText":
                "on {}".format(exchange.name),
                "platform":
                "CCXT",
                "raw": {
                    "quotePrice": [price[0]] if tf == "1m" else price[:1],
                    "quoteVolume": volume,
                    "ticker": ticker,
                    "exchange": exchange,
                    "timestamp": time.time()
                }
            }
            if ticker.quote == "BTC":
                payload["quoteConvertedPrice"] = "≈ ${:,.6f}".format(
                    price[0] * self.lastBitcoinQuote["quotePrice"][0])
                payload["quoteConvertedVolume"] = "≈ ${:,.4f}".format(
                    volume * self.lastBitcoinQuote["quotePrice"][0])

            return payload, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_lld_quote(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()
        filters = request.get_filters()
        action = request.find_parameter_in_list("lld", filters)

        try:
            if exchange is not None: exchange = Exchange(exchange.id, "crypto")

            if action == "funding":
                if exchange.id in ["bitmex"]:
                    try:
                        rawData = exchange.properties.public_get_instrument(
                            {"symbol": ticker.id})[0]
                    except:
                        return None, "Requested funding data for `{}` is not available.".format(
                            ticker.name)

                    if rawData["fundingTimestamp"] is not None:
                        fundingDate = datetime.datetime.strptime(
                            rawData["fundingTimestamp"],
                            "%Y-%m-%dT%H:%M:00.000Z").replace(tzinfo=pytz.utc)
                    else:
                        fundingDate = datetime.datetime.now().replace(
                            tzinfo=pytz.utc)
                    indicativeFundingTimestamp = datetime.datetime.timestamp(
                        fundingDate) + 28800
                    indicativeFundingDate = datetime.datetime.utcfromtimestamp(
                        indicativeFundingTimestamp).replace(tzinfo=pytz.utc)
                    deltaFunding = fundingDate - datetime.datetime.now(
                    ).astimezone(pytz.utc)
                    deltaIndicative = indicativeFundingDate - datetime.datetime.now(
                    ).astimezone(pytz.utc)

                    hours1, seconds1 = divmod(
                        deltaFunding.days * 86400 + deltaFunding.seconds, 3600)
                    minutes1 = int(seconds1 / 60)
                    hoursFunding = "{:d} {} ".format(
                        hours1, "hours"
                        if hours1 > 1 else "hour") if hours1 > 0 else ""
                    minutesFunding = "{:d} {}".format(
                        minutes1 if hours1 > 0 or minutes1 > 0 else seconds1,
                        "{}".format("minute" if minutes1 == 1 else "minutes")
                        if hours1 > 0 or minutes1 > 0 else
                        ("second" if seconds1 == 1 else "seconds"))
                    deltaFundingText = "{}{}".format(hoursFunding,
                                                     minutesFunding)

                    hours2, seconds2 = divmod(
                        deltaIndicative.days * 86400 + deltaIndicative.seconds,
                        3600)
                    minutes2 = int(seconds2 / 60)
                    hoursIndicative = "{:d} {} ".format(
                        hours2, "hours"
                        if hours2 > 1 else "hour") if hours2 > 0 else ""
                    minutesIndicative = "{:d} {}".format(
                        minutes2 if hours2 > 0 or minutes2 > 0 else seconds2,
                        "{}".format("minute" if minutes2 == 1 else "minutes")
                        if hours2 > 0 or minutes2 > 0 else
                        ("second" if seconds2 == 1 else "seconds"))
                    deltaIndicativeText = "{}{}".format(
                        hoursIndicative, minutesIndicative)

                    fundingRate = float(rawData["fundingRate"]) * 100
                    predictedFundingRate = float(
                        rawData["indicativeFundingRate"]) * 100
                    averageFundingRate = (fundingRate +
                                          predictedFundingRate) / 2

                    payload = {
                        "quotePrice":
                        "Funding Rate: {:+.4f} % *(in {})*\nPredicted Rate: {:+.4f} % *(in {})*"
                        .format(fundingRate, deltaFundingText,
                                predictedFundingRate, deltaIndicativeText),
                        "title":
                        ticker.name,
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "yellow" if averageFundingRate == 0.01 else
                        ("light green"
                         if averageFundingRate < 0.01 else "deep orange"),
                        "sourceText":
                        "Contract details on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [fundingRate, predictedFundingRate],
                            "ticker": ticker,
                            "exchange": exchange,
                            "timestamp": time.time()
                        }
                    }
                    return payload, None
                return None, "Funding data is only available on BitMEX."
            elif action == "oi":
                if exchange.id in ["bitmex"]:
                    try:
                        rawData = exchange.properties.public_get_instrument(
                            {"symbol": ticker.id})[0]
                    except:
                        return None, "Requested open interest data for `{}` is not available.".format(
                            ticker.name)

                    payload = {
                        "quotePrice":
                        "Open interest: {:,.0f} {}\nOpen value: {:,.4f} XBT".
                        format(float(rawData["openInterest"]),
                               "USD" if ticker.id == "XBTUSD" else "contracts",
                               float(rawData["openValue"]) / 100000000),
                        "title":
                        ticker.name,
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "deep purple",
                        "sourceText":
                        "Contract details on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [
                                float(rawData["openInterest"]),
                                float(rawData["openValue"]) / 100000000
                            ],
                            "ticker":
                            ticker,
                            "exchange":
                            exchange,
                            "timestamp":
                            time.time()
                        }
                    }
                    return payload, None
                return None, "Open interest and open value data is only available on BitMEX."
            elif action == "ls":
                if exchange.id in ["bitfinex2"]:
                    try:
                        longs = exchange.properties.publicGetStats1KeySizeSymbolLongLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "long",
                                "section": "last"
                            })
                        shorts = exchange.properties.publicGetStats1KeySizeSymbolShortLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "long",
                                "section": "last"
                            })
                        ratio = longs[1] / (longs[1] + shorts[1]) * 100
                    except:
                        return None, None

                    payload = {
                        "quotePrice":
                        "{:.1f} % longs / {:.1f} % shorts".format(
                            ratio, 100 - ratio),
                        "title":
                        "{} longs/shorts ratio".format(ticker.name),
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "deep purple",
                        "sourceText":
                        "Data on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [longs[1], shorts[1]],
                            "ticker": ticker,
                            "exchange": exchange,
                            "timestamp": time.time()
                        }
                    }
                    return payload, None
                return None, "Longs and shorts data is only available on Bitfinex."
            elif action == "sl":
                if exchange.id in ["bitfinex2"]:
                    try:
                        longs = exchange.properties.publicGetStats1KeySizeSymbolLongLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "short",
                                "section": "last"
                            })
                        shorts = exchange.properties.publicGetStats1KeySizeSymbolShortLast(
                            {
                                "key": "pos.size",
                                "size": "1m",
                                "symbol": "t{}".format(ticker.id),
                                "side": "short",
                                "section": "last"
                            })
                        ratio = shorts[1] / (longs[1] + shorts[1]) * 100
                    except:
                        return None, None

                    payload = {
                        "quotePrice":
                        "{:.1f} % shorts / {:.1f} % longs".format(
                            ratio, 100 - ratio),
                        "title":
                        "{} shorts/longs ratio".format(ticker.name),
                        "baseTicker":
                        ticker.base,
                        "quoteTicker":
                        ticker.quote,
                        "thumbnailUrl":
                        TickerParser.get_coingecko_image(ticker.base),
                        "messageColor":
                        "deep purple",
                        "sourceText":
                        "Data on {}".format(exchange.name),
                        "platform":
                        "LLD",
                        "raw": {
                            "quotePrice": [longs[1], shorts[1]],
                            "ticker": ticker,
                            "exchange": exchange,
                            "timestamp": time.time()
                        }
                    }
                    return payload, None
                return None, "Longs and shorts data is only available on Bitfinex."
            elif action == "dom":
                try:
                    rawData = self.coinGecko.get_global()
                except:
                    return None, "Requested dominance data for `{}` is not available.".format(
                        ticker.name)
                if ticker.base.lower() not in rawData["market_cap_percentage"]:
                    return None, "Dominance for {} does not exist.".format(
                        ticker.base)
                coinDominance = rawData["market_cap_percentage"][
                    ticker.base.lower()]

                payload = {
                    "quotePrice":
                    "{} dominance: {:,.2f} %".format(ticker.base,
                                                     coinDominance),
                    "title":
                    "Market Dominance",
                    "baseTicker":
                    ticker.base,
                    "quoteTicker":
                    ticker.quote,
                    "thumbnailUrl":
                    TickerParser.get_coingecko_image(ticker.base),
                    "messageColor":
                    "deep purple",
                    "sourceText":
                    "Market information from CoinGecko",
                    "platform":
                    "LLD",
                    "raw": {
                        "quotePrice": coinDominance,
                        "ticker": ticker,
                        "timestamp": time.time()
                    }
                }
                return payload, None
            else:
                return None, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_iexc_quote(self, request):
        payload, quoteMessage, updatedQuoteMessage = None, None, None

        for platform in ["Stocks", "Forex"]:
            if platform == "Stocks":
                payload, updatedQuoteMessage = self.request_iexc_stocks(
                    request)
            elif platform == "Forex":
                payload, updatedQuoteMessage = self.request_iexc_forex(request)

            if payload is not None:
                return payload, updatedQuoteMessage
            elif updatedQuoteMessage is not None:
                quoteMessage = updatedQuoteMessage

        return None, quoteMessage

    def request_iexc_stocks(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        try:
            try:
                stock = Stock(ticker.id, token=os.environ["IEXC_KEY"])
                rawData = stock.get_quote().loc[ticker.id]
                if ticker.quote is None and exchange is not None:
                    return None, "Price for `{}` is only available on `{}`.".format(
                        ticker.id, rawData["primaryExchange"])
                if rawData is None or (rawData["latestPrice"] is None
                                       and rawData["delayedPrice"] is None):
                    return None, None
            except:
                return None, None

            try:
                coinThumbnail = stock.get_logo().loc[ticker.id]["url"]
            except:
                coinThumbnail = static_storage.icon

            latestPrice = rawData["delayedPrice"] if rawData[
                "latestPrice"] is None else rawData["latestPrice"]
            price = float(latestPrice if "isUSMarketOpen" not in rawData or
                          rawData["isUSMarketOpen"] or "extendedPrice" not in
                          rawData or rawData["extendedPrice"] is None else
                          rawData["extendedPrice"])
            if ticker.isReversed: price = 1 / price
            volume = float(rawData["latestVolume"])
            priceChange = (1 / rawData["change"] if ticker.isReversed
                           and rawData["change"] != 0 else rawData["change"]
                           ) / price * 100 if "change" in rawData and rawData[
                               "change"] is not None else 0

            payload = {
                "quotePrice":
                "{:,.5f}".format(price)
                if ticker.isReversed else "{}".format(price),
                "quoteVolume":
                volume,
                "title":
                ticker.name,
                "baseTicker":
                "contracts",
                "quoteTicker":
                "USD" if ticker.quote is None else ticker.quote,
                "change":
                priceChange,
                "thumbnailUrl":
                coinThumbnail,
                "messageColor":
                "amber" if priceChange == 0 else
                ("green" if priceChange > 0 else "red"),
                "sourceText":
                "provided by IEX Cloud",
                "platform":
                "IEXC",
                "raw": {
                    "quotePrice": [price],
                    "quoteVolume": volume,
                    "ticker": ticker,
                    "exchange": exchange,
                    "timestamp": time.time()
                }
            }
            return payload, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_iexc_forex(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        try:
            try:
                if exchange is not None: return None, None
                rawData = requests.get(
                    "https://cloud.iexapis.com/stable/fx/latest?symbols={}&token={}"
                    .format(ticker.id, os.environ["IEXC_KEY"])).json()
                if rawData is None or type(rawData) is not list or len(
                        rawData) == 0:
                    return None, None
            except:
                return None, None

            price = rawData[0]["rate"]
            if ticker.isReversed: price = 1 / price

            payload = {
                "quotePrice": "{:,.5f}".format(price),
                "title": ticker.name,
                "baseTicker": ticker.base,
                "quoteTicker": ticker.quote,
                "thumbnailUrl": static_storage.icon,
                "messageColor": "deep purple",
                "sourceText": "provided by IEX Cloud",
                "platform": "IEXC",
                "raw": {
                    "quotePrice": [price],
                    "ticker": ticker,
                    "exchange": exchange,
                    "timestamp": time.time()
                }
            }
            return payload, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_fear_greed_index(self, request):
        try:
            requestUrl, _ = request.build_url()
            r = requests.get(requestUrl).json()
            greedIndex = int(r["data"][0]["value"])

            payload = {
                "quotePrice":
                greedIndex,
                "quoteConvertedPrice":
                "≈ {}".format(r["data"][0]["value_classification"].lower()),
                "title":
                "Fear & Greed Index",
                "change":
                greedIndex - int(r["data"][1]["value"]),
                "thumbnailUrl":
                static_storage.icon,
                "messageColor":
                "deep purple",
                "sourceText":
                "Data provided by Alternative.me",
                "platform":
                "Alternative.me",
                "raw": {
                    "quotePrice": [greedIndex],
                    "ticker": request.get_ticker(),
                    "timestamp": time.time()
                }
            }
            return payload, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_ccxt_depth(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        imageStyle = request.get_image_style()
        forceMode = "force" in imageStyle and request.authorId == 361916376069439490
        uploadMode = "upload" in imageStyle and request.authorId == 361916376069439490

        try:
            if exchange is None: return None, None
            exchange = Exchange(exchange.id, "crypto")

            try:
                depthData = exchange.properties.fetch_order_book(ticker.symbol)
                bestBid = depthData["bids"][0]
                bestAsk = depthData["asks"][0]
                lastPrice = (bestBid[0] + bestAsk[0]) / 2
            except:
                return None, None

            imageData = self.generate_depth_image(depthData, bestBid, bestAsk,
                                                  lastPrice)
            if uploadMode:
                bucket.blob("uploads/{}.png".format(int(
                    time.time() * 1000))).upload_from_string(
                        base64.decodebytes(imageData))

            return imageData, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def request_iexc_depth(self, request):
        ticker = request.get_ticker()
        exchange = request.get_exchange()

        imageStyle = request.get_image_style()
        forceMode = "force" in imageStyle and request.authorId == 361916376069439490
        uploadMode = "upload" in imageStyle and request.authorId == 361916376069439490

        try:
            try:
                stock = Stock(ticker.id, token=os.environ["IEXC_KEY"])
                depthData = stock.get_book()[ticker.id]
                rawData = stock.get_quote().loc[ticker.id]
                if ticker.quote is None and exchange is not None:
                    return None, "Orderbook visualization for `{}` is only available on `{}`.".format(
                        ticker.id, rawData["primaryExchange"])
                depthData = {
                    "bids": [[e.get("price"), e.get("size")]
                             for e in depthData["bids"]],
                    "asks": [[e.get("price"), e.get("size")]
                             for e in depthData["asks"]]
                }
                bestBid = depthData["bids"][0]
                bestAsk = depthData["asks"][0]
                lastPrice = (bestBid[0] + bestAsk[0]) / 2
            except:
                return None, None

            imageData = self.generate_depth_image(depthData, bestBid, bestAsk,
                                                  lastPrice)
            if uploadMode:
                bucket.blob("uploads/{}.png".format(int(
                    time.time() * 1000))).upload_from_string(
                        base64.decodebytes(imageData))

            return imageData, None
        except Exception:
            print(traceback.format_exc())
            if os.environ["PRODUCTION_MODE"]:
                self.logging.report_exception(user=ticker.id)
            return None, None

    def generate_depth_image(self, depthData, bestBid, bestAsk, lastPrice):
        bidTotal = 0
        xBids = [bestBid[0]]
        yBids = [0]
        for bid in depthData['bids']:
            if len(xBids) < 10 or bid[0] > lastPrice * 0.9:
                bidTotal += bid[1]
                xBids.append(bid[0])
                yBids.append(bidTotal)

        askTotal = 0
        xAsks = [bestAsk[0]]
        yAsks = [0]
        for ask in depthData['asks']:
            if len(xAsks) < 10 or ask[0] < lastPrice * 1.1:
                askTotal += ask[1]
                xAsks.append(ask[0])
                yAsks.append(askTotal)

        fig = plt.figure(facecolor="#131722")
        ax = fig.add_subplot(1, 1, 1)
        ax.tick_params(color="#787878", labelcolor="#D9D9D9")
        ax.step(xBids, yBids, where="post", color="#27A59A")
        ax.step(xAsks, yAsks, where="post", color="#EF534F")
        ax.fill_between(xBids,
                        yBids,
                        0,
                        facecolor="#27A59A",
                        interpolate=True,
                        step="post",
                        alpha=0.33,
                        zorder=2)
        ax.fill_between(xAsks,
                        yAsks,
                        0,
                        facecolor="#EF534F",
                        interpolate=True,
                        step="post",
                        alpha=0.33,
                        zorder=2)
        plt.axvline(x=lastPrice, color="#758696", linestyle="--")

        ax.set_facecolor("#131722")
        for spine in ax.spines.values():
            spine.set_edgecolor("#787878")
        ax.autoscale(enable=True, axis="both", tight=True)

        def on_draw(event):
            bboxes = []
            for label in ax.get_yticklabels():
                bbox = label.get_window_extent()
                bboxi = bbox.transformed(fig.transFigure.inverted())
                bboxes.append(bboxi)

            bbox = mtransforms.Bbox.union(bboxes)
            if fig.subplotpars.left < bbox.width:
                fig.subplots_adjust(left=1.1 * bbox.width)
                fig.canvas.draw()
            return False

        ax.yaxis.set_major_formatter(
            tkr.FuncFormatter(lambda x, p: format(int(x), ',')))
        plt.setp(ax.get_xticklabels(),
                 rotation=45,
                 horizontalalignment='right')
        lastPriceLabel = bestAsk[0] if bestAsk[1] >= bestBid[1] else bestBid[0]
        xLabels = list(plt.xticks()[0][1:])
        yLabels = list(plt.yticks()[0][1:])
        for label in xLabels:
            plt.axvline(x=label, color="#363C4F", linewidth=1, zorder=1)
        for label in yLabels:
            plt.axhline(y=label, color="#363C4F", linewidth=1, zorder=1)
        diffLabels = 1 - xLabels[0] / xLabels[1]
        bottomBound, topBound = lastPriceLabel * (
            1 - diffLabels * (1 / 4)), lastPriceLabel * (1 + diffLabels *
                                                         (1 / 4))
        xLabels = [l for l in xLabels if not (bottomBound <= l <= topBound)]

        plt.xticks(xLabels + [lastPriceLabel])
        plt.yticks(yLabels)
        ax.set_xlim([xBids[-1], xAsks[-1]])
        ax.set_ylim([0, max(bidTotal, askTotal)])

        fig.canvas.mpl_connect("draw_event", on_draw)
        plt.tight_layout()

        rawImageData = BytesIO()
        plt.savefig(rawImageData, format="png", edgecolor="none")
        rawImageData.seek(0)

        imageBuffer = BytesIO()
        chartImage = Image.new("RGBA", (1600, 1200))
        chartImage.paste(Image.open(rawImageData))
        chartImage = Image.alpha_composite(chartImage,
                                           self.imageOverlays["Alpha depth"])
        chartImage.save(imageBuffer, format="png")
        imageData = base64.b64encode(imageBuffer.getvalue())
        imageBuffer.close()

        return imageData
Пример #10
0
def display_value(n_clicks, symbol: str):
    if n_clicks is None:
        raise PreventUpdate
    if symbol is None:
        raise PreventUpdate
    else:
        symbol = symbol.upper()
        cg = CoinGeckoAPI()
        coin_list = cg.get_coins_list()
        coin_list_df = pd.DataFrame.from_records(coin_list)
        coin_list_df['symbol'] = coin_list_df['symbol'].str.upper()
        coin_list_df.set_index('symbol', inplace=True)
        try:
            data = cg.get_coin_by_id(str(coin_list_df.loc[symbol].id),
                                     localization='false')
        except (ValueError, KeyError):
            # treating symbol as slug
            data = cg.get_coin_by_id(symbol.lower(), localization='false')
            symbol = data['symbol']
        if not data:
            return dbc.Alert(dcc.Markdown('''
            Could not fetch data for symbol : **{0}**.
            ---
            Check [CoinGecko](https://www.coingecko.com/en)
             or [CoinMarketCap](https://coinmarketcap.com/)
             for a valid symbol.
            '''.format(symbol)),
                             color="danger"),
        with open('config.json', 'r') as file:
            config = json.load(file)['crypto']
        tickers = [
            ticker for ticker in data['tickers']
            if ticker['market']['identifier'] in config['viewer']['markets']
        ]
        if len(tickers) <= 4 or config['viewer']['markets'][0] == "*":
            tickers = data['tickers']
        tickers = sorted(tickers, key=lambda t: t['market']['identifier'])
        markets = sorted(
            list(set([t['market']['identifier'] for t in data['tickers']])))
        market_data = get_market_data(data=data)
        stats = {
            "Current Price":
            f'${market_data["current_price"]["usd"]:,}',
            "Market Cap":
            f'{market_data["market_cap"]["usd"]:,}',
            "24H Low/High":
            f'${market_data["low_24h"]["usd"]:,}/${market_data["high_24h"]["usd"]:,}',
            "24H Trading Volume":
            f'{market_data["total_volume"]["usd"]:,}',
            "Circulating supply":
            f'{data["market_data"]["circulating_supply"]:,}'
            if data["market_data"]["circulating_supply"] is not None else "--",
            "Total supply":
            f'{data["market_data"]["total_supply"]:,}'
            if data["market_data"]["total_supply"] is not None else "--",
            "Max supply":
            f'{data["market_data"]["max_supply"]:,}'
            if data["market_data"]["max_supply"] is not None else "--",
        }
        col1 = {
            k: market_data[k]
            for k in market_data if "percentage" not in k
        }
        col2 = {k: market_data[k] for k in market_data if "percentage" in k}
        current_price = data['market_data']['current_price']
        return [
            dbc.Container(get_ticker_carousel(tickers=tickers), fluid=True),
            html.Hr(),
            dbc.Container(
                dbc.Row([
                    dbc.Col([
                        dbc.Row([
                            html.Img(src=data['image']['small']),
                            html.A(html.H2(data['name']),
                                   href=data['links']['homepage'][0])
                        ],
                                align='end',
                                justify='start'),
                        html.Br(),
                        dbc.Row([get_links(data=data)],
                                align='end',
                                justify='start'),
                        html.Br(),
                        dbc.Row([get_social_links(data=data)],
                                align='end',
                                justify='start'),
                        html.Br(),
                        display_contract_address(data=data),
                        html.Br(),
                        get_avalable_markets_popover(markets=markets),
                    ]),
                    dbc.Col(dbc.Table([
                        html.Tr([
                            html.Td(html.Div(key, style={'float': 'left'})),
                            html.Td(html.Div(value, style={'float': 'right'})),
                        ]) for key, value in stats.items()
                    ],
                                      hover=True,
                                      size='sm',
                                      striped=False,
                                      borderless=True),
                            width='auto'),
                ],
                        align='center',
                        justify='center')),
            dbc.Modal([
                dbc.ModalHeader('Description'),
                dbc.ModalBody([
                    DangerouslySetInnerHTML('<p>' + data['description']['en'] +
                                            '</p>')
                ]),
                dbc.ModalFooter(
                    dbc.Button("Close",
                               id="description-modal-close",
                               color='secondary')),
            ],
                      id='description-modal'),
            html.Hr(),
            dbc.Container(fluid=True,
                          children=get_currency_converter(
                              current_price=current_price,
                              symbol=data['symbol']),
                          style={'width': '50rem'}),
            html.Hr(),
            # dbc.Row(children=[
            dbc.Container(
                get_currency_tabs(col1=col1, col2=col2, config=config)),
            # ]),
            html.Hr(),
            dbc.Container(
                dbc.Row(get_stats(data=data),
                        align='start',
                        justify='center',
                        style={'height': '100rem'}))
        ], current_price
Пример #11
0
# conditons for evaluation
coin_list = cg.get_coins_list()
base_currency = 'usd'
crypto = ['ethereum', 'monero', 'bitcoin-cash']

# from_unix = time.mktime(datetime(2021, 5, 7, 12, 00).timetuple())
from_ts = tc.date_to_unix('2020-01-01 00:00:00')
to_ts = tc.date_to_unix('2021-05-06 00:00:00')

for i in range(len(crypto)):

    # get chart from CoinGecko API
    chart = cg.get_coin_market_chart_range_by_id(crypto[i], base_currency,
                                                 from_ts, to_ts)
    coin_data = cg.get_coin_by_id(crypto[i])
    coin_name, coin_symbol = coin_data['name'], coin_data['symbol']

    # create list with prices and dates
    date = [(chart['prices'][ii][0]) for ii in range(len(chart['prices']))]
    prices = [(chart['prices'][ii][1]) for ii in range(len(chart['prices']))]
    date_str = [tc.unix_to_date(date[ii]) for ii in range(len(date))]
    dates_list = pd.to_datetime(date_str, format='%Y-%m-%d %H:%M:%S.%f')

    # plot results
    plt.figure('Price-time')
    plt.plot(dates_list, prices, linewidth=1, label=coin_name)
    plt.ylabel('Price [' + base_currency + ']')
    plt.xlabel('Date')
    plt.xticks(rotation=25)
    plt.legend()
Пример #12
0
class Network_dashboard(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.cg = CoinGeckoAPI()
        self.price_usd = 0.0
        self.price_btc = 0.0

    #@commands.Cog.listener() -> use for events like on_ready

    @commands.Cog.listener()
    async def on_ready(self):
        dashboard_channel = self.bot.get_channel(
            crypto_perams.CRYPTO_DASHBOARD_CHANNEL)
        dashboard_message = await dashboard_channel.send(
            "------------Starting Dashboard------------")
        self.update_dashboard_network.start(dashboard_message)

        coingecko_message = await dashboard_channel.send(
            "------------Starting Price Monitoring------------")
        self.update_dashboard_coingecko_pricing.start(coingecko_message)

        masternode_message = await dashboard_channel.send(
            "------------Starting Masternode Stats------------")
        self.update_dashboard_masternode_stats.start(masternode_message)

    @tasks.loop(seconds=5.0)
    async def update_dashboard_network(self, message):
        rpc_connection_CRYPTO = 'http://{0}:{1}@{2}:{3}'.format(
            crypto_perams.CRYPTO_RPC_USER, crypto_perams.CRYPTO_RPC_PW,
            crypto_perams.CRYPTO_RPC_IP, crypto_perams.CRYPTO_RPC_PORT)
        wallet = AuthServiceProxy(rpc_connection_CRYPTO)

        getmininginfo_response = wallet.getmininginfo()

        embed = discord.Embed(title="Shib Stats",
                              color=discord.Color.from_rgb(193, 151, 79))

        #1440 blocksper day
        #7.2 mn reward

        #row 1
        embed.add_field(
            name="Version",
            value=str(wallet.getnetworkinfo()["subversion"]).replace("/", ""),
            inline=True)
        embed.add_field(name="Connections",
                        value=str(wallet.getconnectioncount()),
                        inline=True)
        embed.add_field(name="Block Count",
                        value=getmininginfo_response["blocks"],
                        inline=True)

        embed.add_field(name="Difficulty",
                        value=round(getmininginfo_response["difficulty"], 2),
                        inline=True)
        embed.add_field(name="Nethash",
                        value=calc_converted_nethash(
                            getmininginfo_response["networkhashps"]),
                        inline=True)
        best_hash = wallet.getbestblockhash()

        #print("best hash = "+best_hash)

        embed.add_field(name="Blockhash",
                        value=best_hash[:8] + "..." + best_hash[-8:],
                        inline=True)

        embed.timestamp = datetime.datetime.utcnow()
        embed.set_footer(text="Last updated")
        #row 2
        embed.set_author(name=self.bot.user.name,
                         url=crypto_perams.WALLET_LINK,
                         icon_url=self.bot.user.avatar_url)

        await message.edit(content="", embed=embed)
        #await message.channel.send(self.ctr)
        #self.ctr=self.ctr+5

    @tasks.loop(seconds=5.0)
    async def update_dashboard_coingecko_pricing(self, message):

        embed = discord.Embed(title="Price Stats",
                              color=discord.Color.from_rgb(193, 151, 79))

        coin_info = self.cg.get_coin_by_id(
            id=crypto_perams.COINGECKO_API_CRYPTO_NAME,
            localization="false",
            tickers=False,
            market_data=True,
            community_data=False,
            developer_data=False,
            sparkline=False)
        self.price_usd = coin_info["market_data"]["current_price"]["usd"]
        self.price_btc = coin_info["market_data"]["current_price"]["btc"]
        #print(price_info)
        embed.add_field(name="Price (USD)",
                        value="$" + str(round(self.price_usd, 2)),
                        inline=True)
        embed.add_field(name="Price (BTC)",
                        value=("{:.8f}฿").format(self.price_btc),
                        inline=True)
        embed.add_field(name="\u200b", value="\u200b", inline=True)
        #embed.add_field(name="ATH", value=str(coin_info["market_data"]["ath"]["usd"]), inline=True)
        #print("pass")
        embed.add_field(
            name="1 Day",
            value=str(
                round(coin_info["market_data"]["price_change_percentage_24h"],
                      2)) + "%",
            inline=True)
        embed.add_field(
            name="1 Week",
            value=str(
                round(coin_info["market_data"]["price_change_percentage_7d"],
                      2)) + "%",
            inline=True)
        embed.add_field(
            name="1 Month",
            value=str(
                round(coin_info["market_data"]["price_change_percentage_30d"],
                      2)) + "%",
            inline=True)

        embed.add_field(name="Market Cap (USD)",
                        value="$" +
                        str(coin_info["market_data"]["market_cap"]["usd"]),
                        inline=True)
        embed.add_field(
            name="Market Cap (BTC)",
            value=str(round(coin_info["market_data"]["market_cap"]["btc"],
                            3)) + "฿",
            inline=True)
        embed.add_field(name="Trading Volume (24 Hr)",
                        value="$" +
                        str(coin_info["market_data"]["total_volume"]["usd"]),
                        inline=True)

        embed.timestamp = datetime.datetime.utcnow()
        embed.set_footer(text="Last updated")

        embed.set_author(name=self.bot.user.name,
                         url=crypto_perams.PRICE_SOURCE_LINK,
                         icon_url=self.bot.user.avatar_url)

        await message.edit(content="", embed=embed)

    @tasks.loop(seconds=10.0)
    async def update_dashboard_masternode_stats(self, message):
        embed = discord.Embed(title="Masternode Stats",
                              color=discord.Color.from_rgb(193, 151, 79))

        rpc_connection_CRYPTO = 'http://{0}:{1}@{2}:{3}'.format(
            crypto_perams.CRYPTO_RPC_USER, crypto_perams.CRYPTO_RPC_PW,
            crypto_perams.CRYPTO_RPC_IP, crypto_perams.CRYPTO_RPC_PORT)
        wallet = AuthServiceProxy(rpc_connection_CRYPTO)

        masternode_count_data = wallet.getmasternodecount()

        embed.add_field(name="Total Masternodes",
                        value=str(masternode_count_data["total"]),
                        inline=True)
        embed.add_field(name="MN Reward",
                        value=str(crypto_perams.CRYPTO_REWARD) + " " +
                        crypto_perams.CRYPTO_TICKER,
                        inline=True)
        amount_of_rewards_per_day = 86400 / crypto_perams.CRYPTO_BLOCKTIME / masternode_count_data[
            "total"]
        avg_reward = round(
            pow(amount_of_rewards_per_day, -1) * 24, 1
        )  #change the * factor to change, base is in days per reward, solve from there
        embed.add_field(name="MN Frequency",
                        value=str(avg_reward) + " hours",
                        inline=True)

        reward_per_day = round(
            amount_of_rewards_per_day * crypto_perams.CRYPTO_REWARD, 2)

        embed.add_field(name="Daily Income",
                        value="${:.2f}\n{:.2f}".format(
                            reward_per_day * self.price_usd, reward_per_day) +
                        " " + crypto_perams.CRYPTO_TICKER +
                        "\n{:.8f}฿".format(reward_per_day * self.price_btc),
                        inline=True)
        embed.add_field(
            name="Monthly Income",
            value="${:.2f}\n{:.2f}".format(
                reward_per_day * self.price_usd * 31, reward_per_day * 31) +
            " " + crypto_perams.CRYPTO_TICKER +
            "\n{:.8f}฿".format(reward_per_day * self.price_btc * 31),
            inline=True)
        embed.add_field(
            name="Yearly Income",
            value="${:.2f}\n{:.2f}".format(
                reward_per_day * self.price_usd * 365, reward_per_day * 365) +
            " " + crypto_perams.CRYPTO_TICKER +
            "\n{:.8f}฿".format(reward_per_day * self.price_btc * 365),
            inline=True)

        embed.timestamp = datetime.datetime.utcnow()

        embed.set_footer(text="Last updated")
        embed.set_author(name=self.bot.user.name,
                         url=crypto_perams.MNO_LINK,
                         icon_url=self.bot.user.avatar_url)

        await message.edit(content="", embed=embed)
class Coin:
    """Coin class, it holds loaded coin"""
    def __init__(self, symbol):
        self.client = CoinGeckoAPI()
        self._coin_list = self.client.get_coins_list()
        self.coin_symbol = self._validate_coin(symbol)

        if self.coin_symbol:
            self.coin = self._get_coin_info()

    def __str__(self):
        return f"{self.coin_symbol}"

    def _validate_coin(self, symbol):
        """Validate if given coin symbol or id exists in list of available coins on CoinGecko.
        If yes it returns coin id.

        Parameters
        ----------
        symbol: str
            Either coin symbol or coin id

        Returns
        -------
        id of the coin on CoinGecko service.

        """
        coin = None
        for dct in self._coin_list:
            if symbol.lower() in list(dct.values()):
                coin = dct.get("id")
        if not coin:
            raise ValueError(
                f"Could not find coin with the given id: {symbol}\n")
        return coin

    def coin_list(self):
        """
        Returns
        -------
        list of all available coin ids
        """
        return [token.get("id") for token in self._coin_list]

    def _get_coin_info(self):
        """Helper method which fetch the coin information by id from CoinGecko API like:
         (name, price, market, ... including exchange tickers)

        Returns
        -------
        dict
        """
        params = dict(localization="false", tickers="false", sparkline=True)
        return self.client.get_coin_by_id(self.coin_symbol, **params)

    def _get_links(self):
        """Helper method that extracts links from coin

        Returns
        -------
        dict
        """
        return self.coin.get("links")

    @property
    def repositories(self):
        """Get list of all repositories for given coin

        Returns
        -------
        list with repositories
        """
        return self._get_links().get("repos_url")

    @property
    def developers_data(self):
        """Get coin development data from GitHub or BitBucket like:
            number of pull requests, contributor etc

        Returns
        -------
        pandas.DataFrame
            Metric, Value
        """
        dev = self.coin.get("developer_data")
        useless_keys = (
            "code_additions_deletions_4_weeks",
            "last_4_weeks_commit_activity_series",
        )
        remove_keys(useless_keys, dev)
        df = pd.Series(dev).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        return df

    @property
    def blockchain_explorers(self):
        """Get list of URLs to blockchain explorers for given coin:

        Returns
        -------
        pandas.DataFrame
            Metric, Value
        """
        blockchain = self._get_links().get("blockchain_site")
        if blockchain:
            dct = filter_list(blockchain)
            df = pd.Series(dct).to_frame().reset_index()
            df.columns = ["Metric", "Value"]
            return df
        return None

    @property
    def social_media(self):
        """Get list of URLs to social media like twitter, facebook, reddit...

        Returns
        -------
        pandas.DataFrame
            Metric, Value
        """
        social_dct = {}
        links = self._get_links()
        for (channel) in CHANNELS.keys():  # pylint: disable=consider-iterating-dictionary)
            if channel in links:
                value = links.get(channel)
                if channel == "twitter_screen_name":
                    value = "https://twitter.com/" + value
                elif channel == "bitcointalk_thread_identifier" and value is not None:
                    value = f"https://bitcointalk.org/index.php?topic={value}"
                social_dct[channel] = value
        social_dct["discord"] = find_discord(links.get("chat_url"))
        dct = rename_columns_in_dct(social_dct, CHANNELS)
        df = pd.Series(dct).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        return df

    @property
    def websites(self):
        """Get list of URLs to websites like homepage of coin, forum,

        Returns
        -------
        pandas.DataFrame
            Metric, Value
        """
        websites_dct = {}
        links = self._get_links()
        sites = ["homepage", "official_forum_url", "announcement_url"]
        for site in sites:
            websites_dct[site] = filter_list(links.get(site))
        df = pd.Series(websites_dct).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        df["Value"] = df["Value"].apply(lambda x: ",".join(x))
        return df

    @property
    def categories(self):
        """Coins categories
        Returns
        -------
        list/dict
        """
        return self.coin.get("categories")

    def _get_base_market_data_info(self):
        """Helper method that fetches all the base market/price information about given coin

        Returns
        -------
        dict
        """
        market_dct = {}
        market_data = self.coin.get("market_data")
        for stat in [
                "total_supply",
                "max_supply",
                "circulating_supply",
                "price_change_percentage_24h",
                "price_change_percentage_7d",
                "price_change_percentage_30d",
        ]:
            market_dct[stat] = market_data.get(stat)
        prices = create_dictionary_with_prefixes(["current_price"],
                                                 market_data, DENOMINATION)
        market_dct.update(prices)
        return market_dct

    @property
    def base_info(self):
        """Get all the base information about given coin

        Returns
        -------
        pandas.DataFrame
        """
        results = {}
        for attr in BASE_INFO:
            info_obj = self.coin.get(attr)
            if attr == "description":
                info_obj = info_obj.get("en")
            results[attr] = info_obj
        results.update(self._get_base_market_data_info())
        return pd.Series(results).to_frame().reset_index()

    @property
    def market_data(self):
        """Get all the base market information about given coin

        Returns
        -------
        pandas.DataFrame
            Metric,Value
        """
        market_data = self.coin.get("market_data")
        market_columns_denominated = [
            "market_cap",
            "fully_diluted_valuation",
            "total_volume",
            "high_24h",
            "low_24h",
        ]
        denominated_data = create_dictionary_with_prefixes(
            market_columns_denominated, market_data, DENOMINATION)

        market_single_columns = [
            "market_cap_rank",
            "total_supply",
            "max_supply",
            "circulating_supply",
            "price_change_percentage_24h",
            "price_change_percentage_7d",
            "price_change_percentage_30d",
            "price_change_percentage_60d",
            "price_change_percentage_1y",
            "market_cap_change_24h",
        ]
        single_stats = {}
        for col in market_single_columns:
            single_stats[col] = market_data.get(col)
        single_stats.update(denominated_data)

        try:
            single_stats["circulating_supply_to_total_supply_ratio"] = (
                single_stats["circulating_supply"] /
                single_stats["total_supply"])
        except (ZeroDivisionError, TypeError) as e:
            print(e)
        df = pd.Series(single_stats).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        return df

    @property
    def all_time_high(self):
        """Get all time high data for given coin

        Returns
        -------
        pandas.DataFrame
            Metric,Value
        """
        market_data = self.coin.get("market_data")
        ath_columns = [
            "current_price",
            "ath",
            "ath_date",
            "ath_change_percentage",
        ]
        results = create_dictionary_with_prefixes(ath_columns, market_data,
                                                  DENOMINATION)
        df = pd.Series(results).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        return df

    @property
    def all_time_low(self):
        """Get all time low data for given coin

        Returns
        -------
        pandas.DataFrame
            Metric,Value
        """
        market_data = self.coin.get("market_data")
        ath_columns = [
            "current_price",
            "atl",
            "atl_date",
            "atl_change_percentage",
        ]
        results = create_dictionary_with_prefixes(ath_columns, market_data,
                                                  DENOMINATION)
        df = pd.Series(results).to_frame().reset_index()
        df.columns = ["Metric", "Value"]
        return df

    @property
    def scores(self):
        """Get different kind of scores for given coin

        Returns
        -------
        pandas.DataFrame
            Metric,Value
        """
        score_columns = [
            "coingecko_rank",
            "coingecko_score",
            "developer_score",
            "community_score",
            "liquidity_score",
            "sentiment_votes_up_percentage",
            "sentiment_votes_down_percentage",
            "public_interest_score",
            "community_data",
            "public_interest_stats",
        ]

        single_stats = {col: self.coin.get(col) for col in score_columns[:-2]}
        nested_stats = {}
        for col in score_columns[-2:]:
            _dct = self.coin.get(col)
            for k, _ in _dct.items():
                nested_stats[k] = _dct.get(k)

        single_stats.update(nested_stats)
        df = pd.Series(single_stats).reset_index()
        df.replace({0: ""}, inplace=True)
        df = df.fillna("")
        df.columns = ["Metric", "Value"]
        return df

    def get_coin_market_chart(self, vs_currency="usd", days=30, **kwargs):
        """Get prices for given coin

        Parameters
        ----------
        vs_currency: str
            currency vs which display data
        days: int
            number of days to display the data
        kwargs

        Returns
        -------
        pandas.DataFrame
            time, price, currency
        """
        prices = self.client.get_coin_market_chart_by_id(
            self.coin_symbol, vs_currency, days, **kwargs)
        prices = prices["prices"]
        df = pd.DataFrame(data=prices, columns=["time", "price"])
        df["time"] = pd.to_datetime(df.time, unit="ms")
        df = df.set_index("time")
        df["currency"] = vs_currency
        return df

    def get_ohlc(self, vs_currency="usd", days=90):
        """Get Open, High, Low, Close prices for given coin

        Parameters
        ----------
        vs_currency: str
            currency vs which display data
        days: int
            number of days to display the data
            on from (1/7/14/30/90/180/365, max)

        Returns
        -------
        pandas.DataFrame
            time, price, currency
        """

        prices = self.client.get_coin_ohlc_by_id(self.coin_symbol, vs_currency,
                                                 days)
        df = pd.DataFrame(data=prices,
                          columns=["time", "open", "high", "low", "close"])
        df["time"] = pd.to_datetime(df.time, unit="ms")
        df = df.set_index("time")
        df["currency"] = vs_currency
        return df
Пример #14
0
from string import printable
import time
import click
from pycoingecko import CoinGeckoAPI

### Get data from coingecko.com
cg = CoinGeckoAPI()
data = cg.get_coins_list()

#List to add each entrie of each coin
data_coins = []

with click.progressbar(length=len(data), show_pos=True) as progress_bar:
    for elem in data:
        progress_bar.update(1)
        json_coin = cg.get_coin_by_id(id=elem['id'])

        #1. Get the the Homepages
        data_homepage = []
        if json_coin['links']['homepage'] != []:
            for homepage in json_coin['links']['homepage']:
                if homepage != "":
                    data_homepage.append(homepage)
        data_homepage = [x for x in data_homepage if x is not None]

        #2. Get the Categories
        data_categories = []
        if json_coin['categories'] != []:
            for categories in json_coin['categories']:
                if categories != "" and categories != None:
                    data_categories.append(categories)
Пример #15
0
class Monkey():

    def __init__(self):
        self.budget = 0
        self.portfolioList = {}
        #self.portfolio = Portfolio()
        self.coingecko = CoinGeckoAPI()

    def createPortfolio(self, portfolio, numberOfAssets=None):
        if numberOfAssets is None:
            numberOfAssets = random.randint(1,25)
        #Get Coins
        coinList = self.coingecko.get_coins_markets(
            vs_currency="usd",
            order="market_cap_desc",
            per_page="250",
            page="1",
            sparkline="false"
        )
        for i in range(numberOfAssets):
            if i < numberOfAssets - 1:
                self.buyRandomCrypto(portfolio, coinList)
            else:
                self.buyRandomCrypto(portfolio, coinList, blowRestOfBudget=True)

        self.showPortfolio()

    def buyRandomCrypto(self, portfolio, coinList, blowRestOfBudget=False):
        #coinList cointains a list of JSON objects of coins with the following data
        #{ id: String,
        #  symbol: String,
        #  name: String,
        #  image: String,
        #  current_price: Decimal,
        #  market_cap: Decimal,
        #  market_cap_rank: Decimal,
        #  fully_diluted_valuation: Decimal,
        #  total_volume: Decimal,
        #  high_24h: 55474,
        #  low_24h: 47882,
        #  price_change_24h: Decimal,
        #  price_change_percentage_24h: Decimal,
        #  market_cap_change_24h: Decimal,
        #  market_cap_change_percentage_24h: Decimal,
        #  circulating_supply: Decimal,
        #  total_supply: Decimal,
        #  max_supply: Decimal,
        #  ath: Decimal,
        #  ath_change_percentage: Decimal,
        #  ath_date: DateString,
        #  atl: Decimal,
        #  atl_change_percentage: Decimal,
        #  atl_date: DateString,
        #  roi: null,
        #  last_updated: DateString
        #}
        crypto = self.pickRandomCrypto(coinList)

        if blowRestOfBudget is True:
            amountToBuyInPercent = 1
        else:
            amountToBuyInPercent = round(random.random(), 2)
        boughtCrypto, tokens = self.buyCrypto(crypto, amountToBuyInPercent)

        portfolio.add(boughtCrypto, tokens) #crypto will be a json; ToDO: build parse function in new portfolio class

    #takes in Json list of cryptos and returns a Crypto object
    def pickRandomCrypto(self, coinList):
        satisfiesCriteria = False
        pick = None
        while(satisfiesCriteria is False):
            pick = random.choice(coinList)
            satisfiesCriteria = self.checkCriteria(pick)
        assert pick is not None, "You didn't pick anything, fool!"
        crypto = Crypto(pick)

        return crypto

    def buyCrypto(self, crypto, amountInPercent):
        moneyToBeSpent = self.budget * amountInPercent
        tokens = moneyToBeSpent / crypto.price
        self.budget -= moneyToBeSpent

        return crypto, tokens

    def checkCriteria(self, crypto):
        #ToDo: extract markets and ticker symbol from crypto object
        symbol = crypto["symbol"].lower()
        marketData = self.coingecko.get_coin_by_id(
            id=crypto["id"],
            localization="false",
            tickers="true",
            marketData="false",
            community_data="false",
            developer_data="false",
            sparkline="false"
        )
        markets = []
        for market in marketData["ticker"]:
            markets.append(market["market"]["name"].lower())

        return self.exchangeTest(markets) and self.isNotStablecoin(symbol)

    def exchangeTest(self, available):
        allowedExchanges = ["binance", "coinbase", "coinbase pro" "ftx", "kraken", "ftx.us", "kucoin", "huobi global"]
        for exchange in available:
            if exchange in allowedExchanges:
                return True

    def isNotStablecoin(self, symbol):
        prohibitedTickers = ["usdc", "usdt", "ust", "tusd", "dai", "pax"]

        return symbol not in prohibitedTickers

    def showPortfolio(self, name, portfolio):
        self.updatePortfolio(portfolio)
        self.postPortfolio(name, portfolio.toString())

    def updatePortfolio(self, portfolio):
        assetIds = []
        for asset in portfolio.assets:
            assetIds.append(asset.Crypto.id)
        currentMarketData = self.coingecko.get_price(ids=assetIds, vs_currencies="usd", include_market_cap=True)
        portfolio.update(currentMarketData)

    def postPortfolio(self, name, portfolioString):


    def botCreatePortfolio(self, numberOfAssets=None, portfolioname=None):
        # initiate empty Portfolio
        portfolio = Portfolio()
        if portfolioname is not None:
            if not self.portfolioList.keys().__contains__(portfolioname):
                self.portfolioList[portfolioname] = portfolio
            else:
                self.sendNameTakenMsg(portfolioname)
        else:
            self.portfolioList[self.portfolioList.__len__()] = portfolio

        self.createPortfolio(portfolio, numberOfAssets=numberOfAssets)

    def botShowPortfolio(self, portfolioname=None):
        keys = list(self.portfolioList.keys())
        if portfolioname is None:
            # show last added portfolio
            name = keys[keys.__len__() - 1]
            self.showPortfolio(name, self.portfolioList[name])
        elif portfolioname in keys:
            self.showPortfolio(portfolioname, self.portfolioList[portfolioname])
        else:
            self.sendNameNotFoundMsg(portfolioname)