diff --git a/README.md b/README.md
index 95eefd9a008..bececc71b51 100644
--- a/README.md
+++ b/README.md
@@ -328,6 +328,7 @@ Distributed under the MIT License. See [LICENSE](https://github.com/DidierRLopes
[Artem Veremy](https://www.linkedin.com/in/veremey/) - artem@veremey.net
+[James Maslek](https://www.linkedin.com/in/james-maslek-b6810186/) - jmaslek11@gmail.com
## Acknowledgments
* [VICE article](https://www.vice.com/en/article/qjp9vp/gamestonk-terminal-is-a-diy-meme-stock-version-of-bloomberg-terminal)
diff --git a/ROADMAP.md b/ROADMAP.md
index 4c290755403..7a46642a5f2 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -202,7 +202,7 @@
### Short term
-- [ ] Add Coingecko
+- [x] Add Coingecko (@jmaslek) - [PR #283](#https://github.com/DidierRLopes/GamestonkTerminal/pulls)
- [ ] Add [Coinpaprika](https://coinpaprika.com/api/)
- [ ] Add crypto charts
diff --git a/gamestonk_terminal/cryptocurrency/README.md b/gamestonk_terminal/cryptocurrency/README.md
new file mode 100644
index 00000000000..fe328670d84
--- /dev/null
+++ b/gamestonk_terminal/cryptocurrency/README.md
@@ -0,0 +1,42 @@
+# Cryptocurrency
+
+This page gives an overview of the ability to load cryptocurrency data.
+
+Current crypto data is [Powered by CoinGecko API](#https://www.coingecko.com/en).
+This is an awesome service that currently requires no API Key!
+
+Current functionality is aimed to be similar to loading a stock ticker.
+
+* [load](#load)
+* [view](#view)
+* [clear](#clear)
+
+## load
+Load a given coin vs a given currency:
+
+````
+usage: load [-c --coin] [-d --days] [--vs]
+````
+* -c/--coin The coin you wish to load. This can either be the symbol or the name. `load -c btc` and `load -c bitcoin`
+ will load. The -c flag is optional, the above is equivalent to `load btc`.
+
+* -d/--days The number of days to look. Defaults to 30 days. As per the API: Minutely data will be used for duration within 1 day,
+ Hourly data will be used for duration between 1 day and 90 days, Daily data will be used for duration above 90 days.
+
+* --vs The currency to look against. Defaults to "usd".
+
+Currently only retrieves price, not volume or MarketCap.
+
+Example doge/eur for the past day:
+````
+load -c doge -d 1 --vs eur
+````
+
+## view
+Plot the loaded crypto data.
+````
+usage: view
+````
+After loading the above 1 day dogecoin/eur. Running view plots the data:
+
+
diff --git a/gamestonk_terminal/cryptocurrency/__init__.py b/gamestonk_terminal/cryptocurrency/__init__.py
new file mode 100644
index 00000000000..e69de29bb2d
diff --git a/gamestonk_terminal/cryptocurrency/coin_api.py b/gamestonk_terminal/cryptocurrency/coin_api.py
new file mode 100644
index 00000000000..3049c28163c
--- /dev/null
+++ b/gamestonk_terminal/cryptocurrency/coin_api.py
@@ -0,0 +1,115 @@
+import argparse
+import pandas as pd
+from pandas.plotting import register_matplotlib_converters
+import matplotlib.pyplot as plt
+from pycoingecko import CoinGeckoAPI
+from gamestonk_terminal.helper_funcs import parse_known_args_and_warn, plot_autoscale
+from gamestonk_terminal.cryptocurrency.crypto_helper import coin_symbol_to_id, coin_ids
+from gamestonk_terminal.config_plot import PLOT_DPI
+
+register_matplotlib_converters()
+# pylint: disable=inconsistent-return-statements
+
+
+def load(l_args):
+
+ cg = CoinGeckoAPI()
+ parser = argparse.ArgumentParser(
+ add_help=False,
+ prog="Crypto",
+ description="""
+ Cryptocurrencies
+ """,
+ )
+
+ parser.add_argument(
+ "-c",
+ "--coin",
+ required=True,
+ type=str,
+ dest="coin",
+ help="Coin to load data for",
+ )
+
+ parser.add_argument(
+ "-d", "--days", default=30, dest="days", help="Number of days to get data for"
+ )
+
+ parser.add_argument(
+ "--vs", default="usd", dest="vs", help="Currency to display vs coin"
+ )
+
+ try:
+ if l_args:
+ if "-" not in l_args[0]:
+ l_args.insert(0, "-c")
+
+ ns_parser = parse_known_args_and_warn(parser, l_args)
+
+ if not ns_parser:
+ return
+
+ if ns_parser.coin in coin_ids:
+ coin = ns_parser.coin
+ else:
+ try:
+ coin = coin_symbol_to_id[ns_parser.coin]
+ except KeyError:
+ print(f"Could not find coin with the id: {ns_parser.coin}")
+ print("")
+ return [None, pd.DataFrame]
+
+ prices = cg.get_coin_market_chart_by_id(
+ coin, vs_currency=ns_parser.vs, days=ns_parser.days
+ )
+ prices = prices["prices"]
+ prices = pd.DataFrame(data=prices, columns=["Time", "Price"])
+ prices["Time"] = pd.to_datetime(prices.Time, unit="ms")
+ prices = prices.set_index("Time")
+ prices["currency"] = ns_parser.vs
+ print(f"{coin}/{ns_parser.vs} loaded")
+ print("")
+ return [coin, prices]
+
+ except SystemExit:
+ print("")
+ return [None, pd.DataFrame()]
+
+ except Exception as e:
+ print(e)
+ print("")
+ return [None, pd.DataFrame()]
+
+
+def view(coin, prices, l_args):
+
+ parser = argparse.ArgumentParser(
+ add_help=False,
+ prog="Crypto",
+ description="""
+ Cryptocurrencies
+ """,
+ )
+ try:
+ ns_parser = parse_known_args_and_warn(parser, l_args)
+
+ if not ns_parser:
+ return
+ plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
+ plt.plot(prices.index, prices.Price, "-ok", ms=2)
+ plt.xlabel("Time")
+ plt.xlim(prices.index[0], prices.index[-1])
+ plt.ylabel("Price")
+ plt.grid(b=True, which="major", color="#666666", linestyle="-")
+ plt.minorticks_on()
+ plt.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
+ plt.title(f"{coin}/{prices['currency'][0]}")
+ plt.show()
+ print("")
+
+ except SystemExit:
+ print("")
+
+ except Exception as e:
+ print(e)
+ print("")
diff --git a/gamestonk_terminal/cryptocurrency/crypto_controller.py b/gamestonk_terminal/cryptocurrency/crypto_controller.py
new file mode 100644
index 00000000000..e494136cea3
--- /dev/null
+++ b/gamestonk_terminal/cryptocurrency/crypto_controller.py
@@ -0,0 +1,103 @@
+__docformat__ = "numpy"
+
+import argparse
+import pandas as pd
+import matplotlib.pyplot as plt
+from prompt_toolkit.completion import NestedCompleter
+from gamestonk_terminal import feature_flags as gtff
+from gamestonk_terminal.helper_funcs import get_flair
+from gamestonk_terminal.menu import session
+from gamestonk_terminal.cryptocurrency import coin_api
+
+
+class CryptoController:
+
+ CHOICES = ["help", "q", "quit", "load", "view"]
+
+ def __init__(self):
+ """ CONSTRUCTOR """
+
+ self.crypto_parser = argparse.ArgumentParser(add_help=False, prog="crypto")
+ self.crypto_parser.add_argument("cmd", choices=self.CHOICES)
+ self.current_coin = None
+ self.current_df = pd.DataFrame()
+
+ @staticmethod
+ def print_help(current_coin):
+ """ Print help """
+ print("\nCryptocurrency:")
+ print(" help show this menu again")
+ print(" q quit this menu, and shows back to main menu")
+ print(" quit quit to abandon program")
+ print(f"\nCurrent Coin : {current_coin}")
+ print("")
+ print(" load load cryptocurrency data")
+ print(" view load and view cryptocurrency data")
+ print("")
+
+ def switch(self, an_input: str):
+ """Process and dispatch input
+
+ Returns
+ -------
+ True, False or None
+ False - quit the menu
+ True - quit the program
+ None - continue in the menu
+ """
+ (known_args, other_args) = self.crypto_parser.parse_known_args(an_input.split())
+
+ return getattr(
+ self, "call_" + known_args.cmd, lambda: "Command not recognized!"
+ )(other_args)
+
+ def call_help(self, _):
+ """Process Help command"""
+ self.print_help(self.current_coin)
+
+ def call_q(self, _):
+ """Process Q command - quit the menu"""
+ return False
+
+ def call_quit(self, _):
+ """Process Quit command - quit the program"""
+ return True
+
+ def call_load(self, other_args):
+ self.current_coin, self.current_df = coin_api.load(other_args)
+
+ def call_view(self, other_args):
+ if self.current_coin:
+ coin_api.view(self.current_coin, self.current_df, other_args)
+
+ else:
+ print("No coin selected. Use 'load' to load the coin you want to look at.")
+ print("")
+
+
+def menu():
+ crypto_controller = CryptoController()
+ crypto_controller.print_help(crypto_controller.current_coin)
+ plt.close("all")
+ while True:
+ # Get input command from user
+ if session and gtff.USE_PROMPT_TOOLKIT:
+ completer = NestedCompleter.from_nested_dict(
+ {c: None for c in crypto_controller.CHOICES}
+ )
+ an_input = session.prompt(
+ f"{get_flair()} (crypto)> ",
+ completer=completer,
+ )
+ else:
+ an_input = input(f"{get_flair()} (crypto)> ")
+
+ try:
+ process_input = crypto_controller.switch(an_input)
+
+ if process_input is not None:
+ return process_input
+
+ except SystemExit:
+ print("The command selected doesn't exist\n")
+ continue
diff --git a/gamestonk_terminal/cryptocurrency/crypto_helper.py b/gamestonk_terminal/cryptocurrency/crypto_helper.py
new file mode 100644
index 00000000000..171b6b9b525
--- /dev/null
+++ b/gamestonk_terminal/cryptocurrency/crypto_helper.py
@@ -0,0 +1,11 @@
+from pycoingecko import CoinGeckoAPI
+
+
+cg = CoinGeckoAPI()
+coins = cg.get_coins()
+coin_symbol_to_id = {}
+coin_ids = []
+
+for coin in coins:
+ coin_symbol_to_id[coin["symbol"]] = coin["id"]
+ coin_ids.append(coin["id"])
diff --git a/gamestonk_terminal/main_helper.py b/gamestonk_terminal/main_helper.py
index 7bff6997eb6..c5d95f067f3 100644
--- a/gamestonk_terminal/main_helper.py
+++ b/gamestonk_terminal/main_helper.py
@@ -54,6 +54,7 @@ def print_help(s_ticker, s_start, s_interval, b_is_market_open):
" fred economic data, \t\t\t from: Federal Reserve Bank of St. Louis "
)
print(" pa portfolio analysis, \t\t Currently Supported: Robinhood ")
+ print(" crypto cryptocurrencies, \t\t coingecko api")
if s_ticker:
print(
diff --git a/poetry.lock b/poetry.lock
index d58561f577b..cc79aeb62c3 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -1799,6 +1799,17 @@ category = "dev"
optional = false
python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+[[package]]
+name = "pycoingecko"
+version = "1.4.0"
+description = "Python wrapper around the CoinGecko API"
+category = "main"
+optional = false
+python-versions = "*"
+
+[package.dependencies]
+requests = "*"
+
[[package]]
name = "pycparser"
version = "2.20"
@@ -2767,7 +2778,7 @@ prediction = ["fbprophet", "tensorflow", "pmdarima", "transformers", "flair", "t
[metadata]
lock-version = "1.1"
python-versions = "^3.6.8"
-content-hash = "ab13d87e3da8dcb61024c74340e528554cea71b5ccab8637e3c75ab88550fcd1"
+content-hash = "b05035fef8aa3a5dacf6c4713579493f1104296ea25305049466fc47e0c35401"
[metadata.files]
absl-py = [
@@ -3940,6 +3951,10 @@ pycodestyle = [
{file = "pycodestyle-2.7.0-py2.py3-none-any.whl", hash = "sha256:514f76d918fcc0b55c6680472f0a37970994e07bbb80725808c17089be302068"},
{file = "pycodestyle-2.7.0.tar.gz", hash = "sha256:c389c1d06bf7904078ca03399a4816f974a1d590090fecea0c63ec26ebaf1cef"},
]
+pycoingecko = [
+ {file = "pycoingecko-1.4.0-py3-none-any.whl", hash = "sha256:bc6e2d87a59bda88bd01a241b37d49c30104842534fdf65ba96616c90419d756"},
+ {file = "pycoingecko-1.4.0.tar.gz", hash = "sha256:082949e83b49ab89090d19b88b6177c9458679dc4a98323db950bd4cef7afa2e"},
+]
pycparser = [
{file = "pycparser-2.20-py2.py3-none-any.whl", hash = "sha256:7582ad22678f0fcd81102833f60ef8d0e57288b6b5fb00323d101be910e35705"},
{file = "pycparser-2.20.tar.gz", hash = "sha256:2d475327684562c3a96cc71adf7dc8c4f0565175cf86b6d7a404ff4c771f15f0"},
diff --git a/pyproject.toml b/pyproject.toml
index fbea026c225..f4c3f068266 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -49,6 +49,7 @@ robin-stocks = "^2.0.3"
termcolor = "^1.1.0"
alpaca-trade-api = "^1.0.1"
pyally = "^1.1.2"
+pycoingecko = "^1.4.0"
[tool.poetry.dev-dependencies]
pytest = "^6.2.2"
diff --git a/requirements-full.txt b/requirements-full.txt
index 0b3e88934d5..24784254cfe 100644
--- a/requirements-full.txt
+++ b/requirements-full.txt
@@ -126,6 +126,7 @@ py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implem
pyally==1.1.2
pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0"
+pycoingecko==1.4.0
pycparser==2.20; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5"
pygments==2.8.1; python_version >= "3.6"
pymeeus==0.5.9; python_version >= "3.5"
diff --git a/requirements-old.txt b/requirements-old.txt
index 8fb9b3235f1..6aaede2a75a 100644
--- a/requirements-old.txt
+++ b/requirements-old.txt
@@ -86,6 +86,7 @@ psaw==0.0.12; python_version >= "3"
pyally==1.1.2
pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0"
+pycoingecko==1.4.0
pymeeus==0.4.3; python_version >= "3.5"
pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6"
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
diff --git a/requirements-win.txt b/requirements-win.txt
index a3c055a89be..7cebb528db2 100644
--- a/requirements-win.txt
+++ b/requirements-win.txt
@@ -87,6 +87,7 @@ psaw==0.0.12; python_version >= "3"
pyally==1.1.2
pyasn1-modules==0.2.8; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.6.0"
pyasn1==0.4.8; python_version >= "3.5" and python_full_version < "3.0.0" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") or python_version >= "3.5" and python_version < "4" and (python_version >= "3.6" and python_full_version < "3.0.0" or python_full_version >= "3.6.0" and python_version >= "3.6") and python_full_version >= "3.6.0"
+pycoingecko==1.4.0
pymeeus==0.4.3; python_version >= "3.5"
pyparsing==2.4.7; python_full_version >= "3.6.0" and python_version >= "3.6"
pysocks==1.7.1; python_version >= "2.7" and python_full_version < "3.0.0" or python_full_version >= "3.5.0"
diff --git a/requirements.txt b/requirements.txt
index 0880e096d5a..919b6242f57 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -85,6 +85,7 @@ psaw==0.0.12; python_version >= "3"
ptyprocess==0.7.0; os_name != "nt" and python_version >= "3.6" and sys_platform != "win32"
py==1.10.0; python_version >= "3.6" and python_full_version < "3.0.0" and implementation_name == "pypy" or implementation_name == "pypy" and python_version >= "3.6" and python_full_version >= "3.4.0"
pyally==1.1.2
+pycoingecko==1.4.0
pycparser==2.20; python_version >= "3.5" and python_full_version < "3.0.0" or python_full_version >= "3.4.0" and python_version >= "3.5"
pygments==2.8.1; python_version >= "3.6"
pymeeus==0.5.9; python_version >= "3.5"
diff --git a/terminal.py b/terminal.py
index 4199658323c..e9e9665eabc 100644
--- a/terminal.py
+++ b/terminal.py
@@ -26,6 +26,7 @@ from gamestonk_terminal.comparison_analysis import ca_controller
from gamestonk_terminal.options import op_controller
from gamestonk_terminal.fred import fred_menu as fm
from gamestonk_terminal.portfolio import port_controller
+from gamestonk_terminal.cryptocurrency import crypto_controller
# import warnings
# warnings.simplefilter("always")
@@ -79,6 +80,7 @@ def main():
"op",
"fred",
"pa",
+ "crypto",
]
menu_parser.add_argument("opt", choices=choices)
completer = NestedCompleter.from_nested_dict({c: None for c in choices})
@@ -209,6 +211,9 @@ def main():
elif ns_known_args.opt == "pa":
b_quit = port_controller.menu()
+ elif ns_known_args.opt == "crypto":
+ b_quit = crypto_controller.menu()
+
elif ns_known_args.opt == "pred":
if not gtff.ENABLE_PREDICT: