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)
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
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)
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)
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.")
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
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
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']))
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
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
# 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()
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
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)
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)