New alternative data context + first sub context (Covid) (#1142)

This commit is contained in:
jmaslek
2022-01-06 13:12:38 -05:00
committed by GitHub
parent 4dddaf74c4
commit 966cd3c6d5
19 changed files with 1329 additions and 1 deletions

0
exports/alternative/covid/.gitkeep vendored Normal file
View File

View File

@@ -0,0 +1,227 @@
"""Alternative Data Controller Module"""
__docformat__ = "numpy"
import argparse
import difflib
import logging
from typing import List, Union
from prompt_toolkit.completion import NestedCompleter
from rich.console import Console
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.helper_funcs import (
get_flair,
system_clear,
)
from gamestonk_terminal.menu import session
t_console = Console()
logger = logging.getLogger(__name__)
# pylint:disable=import-outside-toplevel
class AlternativeDataController:
"""alternative Controller class"""
# Command choices
CHOICES = [
"cls",
"home",
"h",
"?",
"help",
"q",
"quit",
"..",
"exit",
"r",
"reset",
]
CHOICES_COMMANDS: List[str] = []
CHOICES_MENUS = ["covid"]
CHOICES += CHOICES_COMMANDS + CHOICES_MENUS
def __init__(self, queue: List[str] = None):
"""Constructor"""
self.alt_parser = argparse.ArgumentParser(add_help=False, prog="alternative")
self.alt_parser.add_argument(
"cmd",
choices=self.CHOICES,
)
self.queue = queue if queue else list()
self.completer: Union[None, NestedCompleter] = None
if session and gtff.USE_PROMPT_TOOLKIT:
choices: dict = {c: {} for c in self.CHOICES}
self.completer = NestedCompleter.from_nested_dict(choices)
@staticmethod
def print_help():
"""Print help"""
help_str = """
> covid cases, deaths, rates
"""
t_console.print(help_str)
def switch(self, an_input: str):
"""Process and dispatch input
Returns
-------
List[str]
List of commands in the queue to execute
"""
# Empty command
if not an_input:
t_console.print("")
return self.queue
# Navigation slash is being used
if "/" in an_input:
actions = an_input.split("/")
# Absolute path is specified
if not actions[0]:
an_input = "home"
# Relative path so execute first instruction
else:
an_input = actions[0]
# Add all instructions to the queue
for cmd in actions[1:][::-1]:
if cmd:
self.queue.insert(0, cmd)
logger.info(an_input)
(known_args, other_args) = self.alt_parser.parse_known_args(an_input.split())
# Redirect commands to their correct functions
if known_args.cmd:
if known_args.cmd in ("..", "q"):
known_args.cmd = "quit"
elif known_args.cmd in ("?", "h"):
known_args.cmd = "help"
elif known_args.cmd == "r":
known_args.cmd = "reset"
getattr(
self,
"call_" + known_args.cmd,
lambda _: "Command not recognized!",
)(other_args)
return self.queue
def call_cls(self, _):
"""Process cls command"""
system_clear()
def call_home(self, _):
"""Process home command"""
self.queue.insert(0, "quit")
def call_help(self, _):
"""Process help command"""
self.print_help()
def call_quit(self, _):
"""Process quit menu command"""
t_console.print("")
self.queue.insert(0, "quit")
def call_exit(self, _):
"""Process exit terminal command"""
self.queue.insert(0, "quit")
self.queue.insert(0, "quit")
def call_reset(self, _):
"""Process reset command"""
self.queue.insert(0, "alternative")
self.queue.insert(0, "reset")
self.queue.insert(0, "quit")
def call_covid(self, _):
"""Process covid command"""
from gamestonk_terminal.alternative.covid import covid_controller
self.queue = covid_controller.menu(self.queue)
def menu(queue: List[str] = None):
"""Resoualte Collection Menu"""
alt_controller = AlternativeDataController(queue)
an_input = "HELP_ME"
logger.info("AlternativeMenu")
while True:
# There is a command in the queue
if alt_controller.queue and len(alt_controller.queue) > 0:
# If the command is quitting the menu we want to return in here
if alt_controller.queue[0] in ("q", "..", "quit"):
t_console.print("")
if len(alt_controller.queue) > 1:
return alt_controller.queue[1:]
return []
# Consume 1 element from the queue
an_input = alt_controller.queue[0]
alt_controller.queue = alt_controller.queue[1:]
# Print the current location because this was an instruction and we want user to know what was the action
if an_input and an_input.split(" ")[0] in alt_controller.CHOICES_COMMANDS:
t_console.print(f"{get_flair()} /alternative/ $ {an_input}")
# Get input command from user
else:
# Display help menu when entering on this menu from a level above
if an_input == "HELP_ME":
alt_controller.print_help()
# Get input from user using auto-completion
if session and gtff.USE_PROMPT_TOOLKIT and alt_controller.completer:
try:
an_input = session.prompt(
f"{get_flair()} /alternative/ $ ",
completer=alt_controller.completer,
search_ignore_case=True,
)
except KeyboardInterrupt:
# Exit in case of keyboard interrupt
an_input = "exit"
# Get input from user without auto-completion
else:
an_input = input(f"{get_flair()} /alternative/ $ ")
try:
# Process the input command
alt_controller.queue = alt_controller.switch(an_input)
except SystemExit:
t_console.print(
f"\nThe command '{an_input}' doesn't exist on the /alternative menu.\n"
)
similar_cmd = difflib.get_close_matches(
an_input.split(" ")[0] if " " in an_input else an_input,
alt_controller.CHOICES,
n=1,
cutoff=0.7,
)
if similar_cmd:
if " " in an_input:
candidate_input = (
f"{similar_cmd[0]} {' '.join(an_input.split(' ')[1:])}"
)
if candidate_input == an_input:
an_input = ""
alt_controller.queue = []
t_console.print("")
continue
an_input = candidate_input
else:
an_input = similar_cmd[0]
t_console.print(f" Replacing by '{an_input}'.")
alt_controller.queue.insert(0, an_input)
else:
print("")

View File

@@ -0,0 +1,198 @@
Countries
Suriname
Qatar
Romania
Cabo Verde
Malawi
Micronesia
Belarus
Denmark
Fiji
Cambodia
Madagascar
Saint Vincent and the Grenadines
Paraguay
Eritrea
Barbados
Ethiopia
Laos
Zimbabwe
Lithuania
Comoros
Namibia
Spain
Papua New Guinea
Central African Republic
Honduras
Equatorial Guinea
Botswana
Canada
Italy
Jordan
Chad
Czechia
Uzbekistan
Azerbaijan
Poland
US
El Salvador
Ghana
Kiribati
Kuwait
Senegal
Holy See
Mauritius
Oman
Sierra Leone
Zambia
Nigeria
Kosovo
Brunei
China
Gabon
Seychelles
Guatemala
Somalia
Peru
Sao Tome and Principe
Sweden
Pakistan
Moldova
Togo
Niger
Ukraine
Sudan
Trinidad and Tobago
Netherlands
Philippines
Australia
Burkina Faso
Tajikistan
United Arab Emirates
Kyrgyzstan
Costa Rica
Portugal
Mozambique
Mauritania
Timor-Leste
Vietnam
Montenegro
Guyana
Mongolia
Bahrain
Cameroon
Palau
Jamaica
New Zealand
Iraq
Mali
Saint Kitts and Nevis
Brazil
Belgium
Maldives
Egypt
Panama
Rwanda
Israel
Russia
Nicaragua
Switzerland
Kazakhstan
Guinea-Bissau
Albania
Thailand
Cuba
Uruguay
Liechtenstein
Bosnia and Herzegovina
Haiti
Andorra
Taiwan*
Dominica
Congo (Kinshasa)
Ecuador
Malta
Vanuatu
Dominican Republic
Lesotho
Morocco
West Bank and Gaza
Lebanon
South Sudan
Armenia
Afghanistan
Grenada
Indonesia
Sri Lanka
Iran
Bolivia
Luxembourg
North Macedonia
Cyprus
Iceland
Serbia
Greece
United Kingdom
Georgia
Saint Lucia
Venezuela
Austria
Tonga
Saudi Arabia
Argentina
Summer Olympics 2020
Angola
Algeria
Latvia
Yemen
Singapore
Turkey
Belize
Burundi
Ireland
South Africa
Bulgaria
India
Diamond Princess
Cote d'Ivoire
Libya
Slovenia
Benin
Djibouti
Congo (Brazzaville)
Tunisia
Nepal
Bahamas
Bhutan
Colombia
Hungary
Malaysia
Germany
Tanzania
Samoa
San Marino
Syria
Liberia
Korea, South
Uganda
Gambia
Marshall Islands
Kenya
Finland
Bangladesh
Eswatini
Slovakia
Burma
MS Zaandam
Japan
Guinea
Monaco
Mexico
Solomon Islands
Estonia
Chile
Croatia
Antigua and Barbuda
Norway
France
All

View File

@@ -0,0 +1,419 @@
"""COVID Controller Module"""
__docformat__ = "numpy"
import argparse
import difflib
import logging
import pathlib
from typing import List, Union
import pandas as pd
from prompt_toolkit.completion import NestedCompleter
from rich.console import Console
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.alternative.covid import covid_view
from gamestonk_terminal.helper_funcs import (
get_flair,
parse_known_args_and_warn,
system_clear,
try_except,
EXPORT_BOTH_RAW_DATA_AND_FIGURES,
EXPORT_ONLY_RAW_DATA_ALLOWED,
check_positive,
)
from gamestonk_terminal.menu import session
logger = logging.getLogger(__name__)
t_console = Console()
country_file = pathlib.Path(__file__).parent.joinpath("countries.txt")
class CovidController:
"""Covid Controller class"""
# Command choices
CHOICES = [
"cls",
"home",
"h",
"?",
"help",
"q",
"quit",
"..",
"exit",
"r",
"reset",
]
CHOICES_COMMANDS = ["country", "ov", "deaths", "cases", "rates", "slopes"]
CHOICES += CHOICES_COMMANDS
def __init__(self, queue: List[str] = None):
"""Constructor"""
self.covid_parser = argparse.ArgumentParser(add_help=False, prog="covid")
self.covid_parser.add_argument(
"cmd",
choices=self.CHOICES,
)
self.queue = queue if queue else list()
self.completer: Union[None, NestedCompleter] = None
self.country = "US"
self.COUNTRY_LIST = pd.read_csv(country_file, sep="\n", index_col=None)[
"Countries"
].to_list()
if session and gtff.USE_PROMPT_TOOLKIT:
choices: dict = {c: {} for c in self.CHOICES}
choices["country"] = {c: None for c in self.COUNTRY_LIST}
self.completer = NestedCompleter.from_nested_dict(choices)
def print_help(self):
"""Print help"""
help_str = f"""
slopes get countries with highest slope in cases
country select country for data
Country: [cyan]{self.country}[/cyan]
ov get overview (cases and deaths) for selected country
deaths get deaths for selected country
cases get cases for selected country
rates get death/cases rate for selected country
"""
t_console.print(help_str)
def switch(self, an_input: str):
"""Process and dispatch input
Returns
-------
List[str]
List of commands in the queue to execute
"""
# Empty command
if not an_input:
t_console.print("")
return self.queue
# Navigation slash is being used
if "/" in an_input:
actions = an_input.split("/")
# Absolute path is specified
if not actions[0]:
an_input = "home"
# Relative path so execute first instruction
else:
an_input = actions[0]
# Add all instructions to the queue
for cmd in actions[1:][::-1]:
if cmd:
self.queue.insert(0, cmd)
logger.info(an_input)
(known_args, other_args) = self.covid_parser.parse_known_args(an_input.split())
# Redirect commands to their correct functions
if known_args.cmd:
if known_args.cmd in ("..", "q"):
known_args.cmd = "quit"
elif known_args.cmd in ("?", "h"):
known_args.cmd = "help"
elif known_args.cmd == "r":
known_args.cmd = "reset"
getattr(
self,
"call_" + known_args.cmd,
lambda _: "Command not recognized!",
)(other_args)
return self.queue
def call_cls(self, _):
"""Process cls command"""
system_clear()
def call_home(self, _):
"""Process home command"""
self.queue.insert(0, "quit")
self.queue.insert(0, "quit")
def call_help(self, _):
"""Process help command"""
self.print_help()
def call_quit(self, _):
"""Process quit menu command"""
t_console.print("")
self.queue.insert(0, "quit")
def call_exit(self, _):
"""Process exit terminal command"""
self.queue.insert(0, "quit")
self.queue.insert(0, "quit")
self.queue.insert(0, "quit")
def call_reset(self, _):
"""Process reset command"""
self.queue.insert(0, f"country {self.country}")
self.queue.insert(0, "covid")
self.queue.insert(0, "alternative")
self.queue.insert(0, "reset")
self.queue.insert(0, "quit")
self.queue.insert(0, "quit")
def call_country(self, other_args: List[str]):
"""Process country command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="country",
description="Select a country to look at data for.",
)
parser.add_argument(
"-c",
"--country",
nargs="+",
type=str,
dest="country",
help="Country to get data for.",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-c")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if ns_parser.country:
country = " ".join(ns_parser.country)
if country not in self.COUNTRY_LIST:
t_console.print(f"[red]{country} not a valid selection.[/red]\n")
return
self.country = country
t_console.print(f"[cyan]{country}[/cyan] loaded\n")
else:
t_console.print("[red]Please input a country.[/red]\n")
@try_except
def call_ov(self, other_args: List[str]):
"""Process hist command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ov",
description="Show historical cases and deaths by country.",
)
ns_parser = parse_known_args_and_warn(
parser,
other_args,
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
raw=True,
limit=10,
)
if ns_parser:
covid_view.display_covid_ov(
self.country,
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
)
@try_except
def call_rates(self, other_args: List[str]):
"""Process hist command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="rates",
description="Show historical rates country.",
)
ns_parser = parse_known_args_and_warn(
parser,
other_args,
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
raw=True,
limit=10,
)
if ns_parser:
covid_view.display_covid_stat(
self.country,
stat="rates",
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
)
@try_except
def call_deaths(self, other_args: List[str]):
"""Process deaths command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="deaths",
description="Show historical deaths by country.",
)
ns_parser = parse_known_args_and_warn(
parser,
other_args,
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
raw=True,
limit=10,
)
if ns_parser:
covid_view.display_covid_stat(
self.country,
stat="deaths",
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
)
@try_except
def call_cases(self, other_args: List[str]):
"""Process cases command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cases",
description="Show historical cases for country.",
)
ns_parser = parse_known_args_and_warn(
parser,
other_args,
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
raw=True,
limit=10,
)
if ns_parser:
covid_view.display_covid_stat(
self.country,
stat="cases",
raw=ns_parser.raw,
limit=ns_parser.limit,
export=ns_parser.export,
)
@try_except
def call_slopes(self, other_args: List[str]):
"""Process cases command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="slopes",
description="Show countries with highest slopes.",
)
parser.add_argument(
"-d",
"--days",
type=check_positive,
help="Number of days back to look",
dest="days",
default=30,
)
parser.add_argument(
"-a",
"--ascend",
action="store_true",
default=False,
help="Show in ascending order",
)
parser.add_argument(
"-t",
"--threshold",
default=10000,
dest="threshold",
help="Threshold for total cases over period",
type=check_positive,
)
ns_parser = parse_known_args_and_warn(
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED, limit=10
)
if ns_parser:
covid_view.display_country_slopes(
days_back=ns_parser.days,
limit=ns_parser.limit,
ascend=ns_parser.ascend,
threshold=ns_parser.threshold,
)
def menu(queue: List[str] = None):
"""Covid Menu"""
covid_controller = CovidController(queue)
an_input = "HELP_ME"
logger.info("CovidMenu")
while True:
# There is a command in the queue
if covid_controller.queue and len(covid_controller.queue) > 0:
# If the command is quitting the menu we want to return in here
if covid_controller.queue[0] in ("q", "..", "quit"):
t_console.print("")
if len(covid_controller.queue) > 1:
return covid_controller.queue[1:]
return []
# Consume 1 element from the queue
an_input = covid_controller.queue[0]
covid_controller.queue = covid_controller.queue[1:]
# Print the current location because this was an instruction and we want user to know what was the action
if an_input and an_input.split(" ")[0] in covid_controller.CHOICES_COMMANDS:
t_console.print(f"{get_flair()} /alternative/covid/ $ {an_input}")
# Get input command from user
else:
# Display help menu when entering on this menu from a level above
if an_input == "HELP_ME":
covid_controller.print_help()
# Get input from user using auto-completion
if session and gtff.USE_PROMPT_TOOLKIT and covid_controller.completer:
try:
an_input = session.prompt(
f"{get_flair()} /alternative/covid/ $ ",
completer=covid_controller.completer,
search_ignore_case=True,
)
except KeyboardInterrupt:
# Exit in case of keyboard interrupt
an_input = "exit"
# Get input from user without auto-completion
else:
an_input = input(f"{get_flair()} /alternative/covid/ $ ")
try:
# Process the input command
covid_controller.queue = covid_controller.switch(an_input)
except SystemExit:
t_console.print(
f"\nThe command '{an_input}' doesn't exist on the /alternative/covid menu."
)
similar_cmd = difflib.get_close_matches(
an_input.split(" ")[0] if " " in an_input else an_input,
covid_controller.CHOICES,
n=1,
cutoff=0.7,
)
if similar_cmd:
if " " in an_input:
candidate_input = (
f"{similar_cmd[0]} {' '.join(an_input.split(' ')[1:])}"
)
if candidate_input == an_input:
an_input = ""
covid_controller.queue = []
t_console.print("\n")
continue
an_input = candidate_input
else:
an_input = similar_cmd[0]
t_console.print(f" Replacing by '{an_input}'.")
covid_controller.queue.insert(0, an_input)
else:
t_console.print("")

View File

@@ -0,0 +1,108 @@
"""Covid Model"""
__docformat__ = "numpy"
import warnings
import pandas as pd
import numpy as np
global_cases_time_series = (
"https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_"
"covid_19_time_series/time_series_covid19_confirmed_global.csv"
)
global_deaths_time_series = (
"https://raw.githubusercontent.com/CSSEGISandData/COVID-19/master/csse_covid_19_data/csse_"
"covid_19_time_series/time_series_covid19_deaths_global.csv"
)
def get_global_cases(country: str) -> pd.DataFrame:
"""Get historical cases for given country
Parameters
----------
country: str
Country to search for
Returns
-------
pd.DataFrame
Dataframe of historical cases
"""
cases = pd.read_csv(global_cases_time_series)
cases = cases.rename(columns={"Country/Region": "Country"})
cases = (
cases.drop(columns=["Province/State", "Lat", "Long"])
.groupby("Country")
.agg("sum")
.T
)
cases.index = pd.to_datetime(cases.index)
cases = pd.DataFrame(cases[country]).diff().dropna()
if cases.shape[1] > 1:
return pd.DataFrame(cases.sum(axis=1))
return cases
def get_global_deaths(country: str) -> pd.DataFrame:
"""Get historical deaths for given country
Parameters
----------
country: str
Country to search for
Returns
-------
pd.DataFrame
Dataframe of historical deaths
"""
deaths = pd.read_csv(global_deaths_time_series)
deaths = deaths.rename(columns={"Country/Region": "Country"})
deaths = (
deaths.drop(columns=["Province/State", "Lat", "Long"])
.groupby("Country")
.agg("sum")
.T
)
deaths.index = pd.to_datetime(deaths.index)
deaths = pd.DataFrame(deaths[country]).diff().dropna()
if deaths.shape[1] > 1:
return pd.DataFrame(deaths.sum(axis=1))
return deaths
def get_case_slopes(days_back: int = 30, threshold: int = 10000) -> pd.DataFrame:
"""Load cases and find slope over period
Parameters
----------
days_back: int
Number of historical days to consider
threshold: int
Threshold for total number of cases
Returns
-------
pd.DataFrame
Dataframe containing slopes
"""
# Ignore the pandas warning for setting a slace with a value
warnings.filterwarnings("ignore")
cases = pd.read_csv(global_cases_time_series)
cases = cases.rename(columns={"Country/Region": "Country"})
cases = (
(
cases.drop(columns=["Province/State", "Lat", "Long"])
.groupby("Country")
.agg("sum")
)
.diff()
.dropna()
)
hist = cases.iloc[:, -days_back:]
hist["Sum"] = hist.sum(axis=1)
hist = hist[hist.Sum > threshold].drop(columns="Sum")
hist["Slope"] = hist.apply(
lambda x: np.polyfit(np.arange(days_back), x, 1)[0], axis=1
)
return pd.DataFrame(hist["Slope"])

View File

@@ -0,0 +1,206 @@
"""Covid View"""
__docformat__ = "numpy"
import os
import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd
from rich.console import Console
import gamestonk_terminal.feature_flags as gtff
from gamestonk_terminal.alternative.covid import covid_model
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal.helper_funcs import (
plot_autoscale,
export_data,
rich_table_from_df,
)
t_console = Console()
def display_covid_ov(country, raw: bool = False, limit: int = 10, export: str = ""):
"""Show historical cases and deaths by country
Parameters
----------
country: str
Country to get data for
raw: bool
Flag to display raw data
limit: int
Number of raw data to show
export: str
Format to export data
"""
t_console.print("")
cases = covid_model.get_global_cases(country) / 1_000
deaths = covid_model.get_global_deaths(country)
ov = pd.concat([cases, deaths], axis=1)
ov.columns = ["Cases", "Deaths"]
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax.plot(cases.index, cases, alpha=0.2, c="b")
ax.plot(cases.index, cases.rolling(7).mean(), lw=4, c="b")
ax.set_ylabel("Cases (1k)", color="blue")
ax.tick_params(axis="y", labelcolor="blue")
ax2 = ax.twinx()
ax2.plot(deaths.index, deaths, "r", alpha=0.2)
ax2.plot(deaths.index, deaths.rolling(7).mean(), "r", lw=4)
ax2.grid()
ax2.set_title(f"Overview for {country.upper()}")
ax2.set_xlabel("Date")
ax2.set_ylabel("Deaths", color="red")
ax2.tick_params(axis="y", labelcolor="red")
dateFmt = mdates.DateFormatter("%Y-%m-%d")
ax.xaxis.set_major_formatter(dateFmt)
ax.tick_params(axis="x", labelrotation=45)
ax.set_xlim(ov.index[0], ov.index[-1])
fig.tight_layout(pad=2)
if gtff.USE_ION:
plt.ion()
plt.show()
if raw:
ov.index = [x.strftime("%Y-%m-%d") for x in ov.index]
if gtff.USE_TABULATE_DF:
t_console.print(
rich_table_from_df(
ov.tail(limit),
headers=[x.title() for x in ov.columns],
show_index=True,
index_name="Date",
title=f"[bold]{country} COVID Numbers[/bold]",
)
)
else:
t_console.print(ov.tail(limit).to_string())
t_console.print("")
if export:
export_data(export, os.path.dirname(os.path.abspath(__file__)), "ov", ov)
def display_covid_stat(
country, stat: str = "cases", raw: bool = False, limit: int = 10, export: str = ""
):
"""Show historical cases and deaths by country
Parameters
----------
country: str
Country to get data for
stat: str
Statistic to get. Either "cases", "deaths" or "rates"
raw: bool
Flag to display raw data
limit: int
Number of raw data to show
export: str
Format to export data
"""
t_console.print("")
if stat == "cases":
data = covid_model.get_global_cases(country) / 1_000
elif stat == "deaths":
data = covid_model.get_global_deaths(country)
elif stat == "rates":
cases = covid_model.get_global_cases(country)
deaths = covid_model.get_global_deaths(country)
data = (deaths / cases).fillna(0) * 100
else:
t_console.print("Invalid stat selected.\n")
return
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax.plot(data.index, data, alpha=0.2, c="b")
ax.plot(data.index, data.rolling(7).mean(), lw=4, c="b")
if stat == "cases":
ax.set_ylabel(stat.title() + " (1k)", color="blue")
else:
ax.set_ylabel(stat.title(), color="blue")
ax.tick_params(axis="y", labelcolor="blue")
ax.grid("on")
dateFmt = mdates.DateFormatter("%Y-%m-%d")
ax.xaxis.set_major_formatter(dateFmt)
ax.tick_params(axis="x", labelrotation=45)
ax.spines["right"].set_visible(False)
ax.spines["top"].set_visible(False)
ax.set_title(f"{country} COVID {stat}")
ax.set_xlim(data.index[0], data.index[-1])
fig.tight_layout(pad=2)
if gtff.USE_ION:
plt.ion()
plt.show()
if raw:
data.index = [x.strftime("%Y-%m-%d") for x in data.index]
if gtff.USE_TABULATE_DF:
t_console.print(
rich_table_from_df(
data.tail(limit),
headers=[stat.title()],
show_index=True,
index_name="Date",
title=f"[bold]{country} COVID {stat}[/bold]",
)
)
else:
t_console.print(data.tail(limit).to_string())
t_console.print("")
export_data(export, os.path.dirname(os.path.abspath(__file__)), stat, data)
def display_country_slopes(
days_back: int = 30,
limit: int = 10,
ascend: bool = False,
threshold: int = 10000,
export: str = "",
):
"""
Parameters
----------
days_back: int
Number of historical days to get slope for
limit: int
Number to show in table
ascend: bool
Boolean to sort in ascending order
threshold: int
Threshold for total cases over period
export : str
Format to export data
"""
hist_slope = covid_model.get_case_slopes(days_back, threshold).sort_values(
by="Slope", ascending=ascend
)
if gtff.USE_TABULATE_DF:
t_console.print(
rich_table_from_df(
hist_slope.head(limit),
show_index=True,
index_name="Country",
title=f"[bold]{('Highest','Lowest')[ascend]} Sloping Cases[/bold] (Cases/Day)",
)
)
else:
t_console.print(hist_slope.head(limit).to_string())
t_console.print("")
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
f"slopes_{days_back}day",
hist_slope,
)

View File

@@ -565,6 +565,8 @@ def parse_known_args_and_warn(
parser: argparse.ArgumentParser,
other_args: List[str],
export_allowed: int = NO_EXPORT,
raw: bool = False,
limit: int = 0,
):
"""Parses list of arguments into the supplied parser
@@ -577,7 +579,10 @@ def parse_known_args_and_warn(
export_allowed: int
Choose from NO_EXPORT, EXPORT_ONLY_RAW_DATA_ALLOWED,
EXPORT_ONLY_FIGURES_ALLOWED and EXPORT_BOTH_RAW_DATA_AND_FIGURES
raw: bool
Add the --raw flag
limit: int
Add a --limit flag with this number default
Returns
-------
ns_parser:
@@ -609,6 +614,24 @@ def parse_known_args_and_warn(
help=help_export,
)
if raw:
parser.add_argument(
"--raw",
dest="raw",
action="store_true",
default=False,
help="Flag to display raw data",
)
if limit > 0:
parser.add_argument(
"-l",
"--limit",
dest="limit",
default=limit,
help="Number of entries to show in data.",
type=int,
)
if gtff.USE_CLEAR_AFTER_CMD:
system_clear()

14
scripts/test_alt_covid.gst vendored Normal file
View File

@@ -0,0 +1,14 @@
alternative
covid
country Australia
reset
slopes
country US
ov
country Russia
deaths
country United Kingdom
cases
country Canada
rates
exit

View File

@@ -66,6 +66,7 @@ class TerminalController:
"resources",
"jupyter",
"funds",
"alternative",
]
CHOICES += CHOICES_COMMANDS
CHOICES += CHOICES_MENUS
@@ -133,6 +134,7 @@ Timezone: {get_user_timezone_or_invalid()}
> portfolio
> jupyter
> resources
> alternative
"""
print(help_text)
@@ -266,6 +268,12 @@ Timezone: {get_user_timezone_or_invalid()}
self.queue = resources_controller.menu(self.queue)
def call_alternative(self, _):
"""Process resources command"""
from gamestonk_terminal.alternative import alt_controller
self.queue = alt_controller.menu(self.queue)
def call_portfolio(self, _):
"""Process portfolio command"""
from gamestonk_terminal.portfolio import portfolio_controller

5
website/content/alternative/_index.md vendored Normal file
View File

@@ -0,0 +1,5 @@
---
geekdocCollapseSection: true
---
{{< toc-tree >}}

View File

@@ -0,0 +1,5 @@
---
geekdocCollapseSection: true
---
{{< toc-tree >}}

View File

@@ -0,0 +1,16 @@
```
usage: cases [-h] [--export {csv,json,xlsx,png,jpg,pdf,svg}] [--raw] [-l LIMIT]
```
Show historical cases for country.
```
optional arguments:
-h, --help show this help message (default: False)
--export {csv,json,xlsx,png,jpg,pdf,svg}
Export raw data into csv, json, xlsx and figure into png, jpg, pdf, svg (default: )
--raw Flag to display raw data (default: False)
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
![cases](https://user-images.githubusercontent.com/18151143/148297650-1f4bf956-0ede-4118-bef5-195685e5a137.png)

View File

@@ -0,0 +1,16 @@
```u
sage: deaths [-h] [--export {csv,json,xlsx,png,jpg,pdf,svg}] [--raw] [-l LIMIT]
```
Show historical deaths by country.
```
optional arguments:
-h, --help show this help message (default: False)
--export {csv,json,xlsx,png,jpg,pdf,svg}
Export raw data into csv, json, xlsx and figure into png, jpg, pdf, svg (default: )
--raw Flag to display raw data (default: False)
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
![deaths](https://user-images.githubusercontent.com/18151143/148297683-7f263f7c-9db5-496b-831b-254c9324e660.png)

View File

@@ -0,0 +1,16 @@
```
usage: ov [-h] [--export {csv,json,xlsx,png,jpg,pdf,svg}] [--raw] [-l LIMIT]
```
Show historical cases and deaths by country.
```
optional arguments:
-h, --help show this help message (default: False)
--export {csv,json,xlsx,png,jpg,pdf,svg}
Export raw data into csv, json, xlsx and figure into png, jpg, pdf, svg (default: )
--raw Flag to display raw data (default: False)
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
![ov](https://user-images.githubusercontent.com/18151143/148297718-cde24b47-468b-4929-935b-b36c2140007a.png)

View File

@@ -0,0 +1,15 @@
```
usage: rates [-h] [--export {csv,json,xlsx,png,jpg,pdf,svg}] [--raw] [-l LIMIT]
```
Show historical rates country.
```
optional arguments:
-h, --help show this help message (default: False)
--export {csv,json,xlsx,png,jpg,pdf,svg}
Export raw data into csv, json, xlsx and figure into png, jpg, pdf, svg (default: )
--raw Flag to display raw data (default: False)
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
![rates](https://user-images.githubusercontent.com/18151143/148297759-b4baba6f-3556-4da4-babf-846a9754ab4b.png)

View File

@@ -0,0 +1,36 @@
```
usage: slopes [-d DAYS] [-a] [-t THRESHOLD] [-h] [--export {csv,json,xlsx}] [-l LIMIT]
```
Show countries with highest slopes in cases.
```
optional arguments:
-d DAYS, --days DAYS Number of days back to look (default: 30)
-a, --ascend Show in ascending order (default: False)
-t THRESHOLD, --threshold THRESHOLD
Threshold for total cases over period (default: 10000)
-h, --help show this help message (default: False)
--export {csv,json,xlsx}
Export raw data into csv, json, xlsx (default: )
-l LIMIT, --limit LIMIT
Number of entries to show in data. (default: 10)
```
```
2022 Jan 05, 17:01 (✨) /alternative/covid/ $ slopes -l 4
Highest Sloping Cases
┏━━━━━━━━━━━━━━━━┳━━━━━━━━━━━┓
┃ Country ┃ Slope ┃
┡━━━━━━━━━━━━━━━━╇━━━━━━━━━━━┩
│ US │ 210153.96 │
├────────────────┼───────────┤
│ United Kingdom │ 104611.68 │
├────────────────┼───────────┤
│ France │ 81275.88 │
├────────────────┼───────────┤
│ Spain │ 47986.82 │
└────────────────┴───────────┘
```

View File

@@ -1076,3 +1076,19 @@ main:
ref: "/forex/candle"
- name: resources
ref: "/resources"
- name: alternative
ref: "/alternative"
sub:
- name: covid
ref: "/alternative/covid"
sub:
- name: slopes
ref: "/alternative/covid/slopes"
- name: ov
ref: "/alternative/covid/ov"
- name: deaths
ref: "/alternative/covid/deaths"
- name: cases
ref: "/alternative/covid/cases"
- name: rates
ref: "/alternative/covid/rates"