Skip to content

Commit

Permalink
Global plot styles (OpenBB-finance#1228)
Browse files Browse the repository at this point in the history
* Add default stylesheets

* Add terminal style helper class and global style initialization in cfg

* Style comments and docstrings

* Load rich terminal theme from config file

* Add application chart styles to candle charts

* Add todos

* Remove explicit color setting for some ta charts

* Add user styles folder to gitignore

* Update default stylesheets

* Add matplotlib font manager support

* Add matplotlib font manager support

* Update docstrings and default style

* Update stocks candle chart formatting (return fig to style title)

* Style common ta overlap view

* Make up and down market colors a part of the style helper

* Update stylesheets

* Style common ta volume view

* Style common ta momentum view

* Style common ta trend indicators view

* Style common ta volatility view

* Style common ta volume view

* Style common ta custom indicators view

* Fix styling bugs and remove the obvious time x lablel

* Style charts in the covid menu

* Set legend position to upper left in the mpl stylesheet

* Add mpl_rcparams configs for parameters not covered by stylesheets

* Remove font configuration files

* Update style class utility functions

* Implement passing external axes and style utility usage in ema & stoch

* Add theme watermark and output helpers

* Rename style to theme

* Update helper usage in ta/ma and ta/stoch

* Update style to theme in sample menus

* Style forex (OpenBB-finance#1305)

* Make tight layout optional 'cause mplfinance doesn't support it

* Apply global style to the forex menu

* Update code layout in oanda view and black

* Style common TA (OpenBB-finance#1315)

* Make tight layout optional 'cause mplfinance doesn't support it

* Apply global style to the forex menu

* Add linewidth to theme for use in mpf's addplots

* Add vwap to the stocks notebook api

* Update common/ta overlap to follow charting style

* Apply style on TerminalStyle init

* Enable infrastructure for excluding non-trading days from plots

* Update notebook api to include there and resolve bandit warning

* Update ta/common/overlap to exclude non-trading days

* Enable external ax, style and non-trading days in common/ta/momentum

* Enable external ax, style and non-trading days in common/ta/trend

* Update vwap to the argument naming convention

* Enable external ax, style and non-trading days in common/ta/volatility

* Enable external ax, style and non-trading days in common/ta/volume

* Enable external ax, style and non-trading days in common/ta/custom

* Fix controller tests

* Forgot to disable rewriting of the cassettes ...

* Fix controller errors that came up because a merge conflict

* Fix price label position on fib

* Fix line having wrong x values in fib

Co-authored-by: Colin Delahunty <[email protected]>

* Style economy (OpenBB-finance#1308)

* Began converting

* Added alphavan_view

* Added CNN View

* Updated nasdaq view, fixed glitch

* Added fred

* Refactored URL

* Theo's requested changes

* Updated docstrings

* Updated tests

* Fixed pylint

* Fixed tests

* Theo changes

* Econ Fix

* Refactor chart style for Crypto context (OpenBB-finance#1306)

* Remove mock for gff

* Mock visualize_output helper function

* Refactor

* Fix plot helper

* Update legend loc

* Refactor mplfinance candle plot

* Fix errors in the helper function

* Fix binbook having the wrong call_ function name

* Remove hardcoded style params

* Resolve kwargs future warning from pandas

* Remove warnings import

Co-authored-by: Theodore Aptekarev <[email protected]>

* funds + custom (OpenBB-finance#1311)

* funds + custom

* cleanup cleanup everybody everywhere

* Fix external axes conditional and a typo

Co-authored-by: Theodore Aptekarev <[email protected]>

* Add external axes mode to covid charts (OpenBB-finance#1328)

* Add portfolio menu plots (OpenBB-finance#1318)

* Portfolio view plots (commenting out report stuff)

* PA Menu broken.  Commenting out and fix tests

* portfolio optimization

* comment out commented api line

* Add notes on disabling the pa submenu

Co-authored-by: Theodore Aptekarev <[email protected]>

* Plot updates in common BA (OpenBB-finance#1335)

* Add external axes support to common/ba/finbrain

* Add external axes support to common/ba/twitter

* Add external axes support to common/ba/google

* Add external axes support to common/ba/sentimentinvestor

* Add sentimentinvestor to the notebooks API

* Fix tests

* Etf refactor (OpenBB-finance#1323)

* Refactored no ETF

* Fixed gtff import

* Fixed tests

* Fix pie chart style

* Refactored etf/candle

* Added pylint fix

* Fixed tests

* Update candle chart layout

* Update etf controller test

* Remove strange binary file

Co-authored-by: Theodore Aptekarev <[email protected]>

* Expose ETF candle function in the notebooks API

* Common BA and Common QA charts update (OpenBB-finance#1342)

* Add external axes support to common/ba/finbrain

* Add external axes support to common/ba/twitter

* Add external axes support to common/ba/google

* Add external axes support to common/ba/sentimentinvestor

* Add sentimentinvestor to the notebooks API

* Fix tests

* Update stylesheet files

* Refactor charts for common/qa

* Update the forgotten line plot

* Update tests

* Add missing arg to a docstring

* Remove scientific notation

* Black imports

Co-authored-by: Minh Hoang <[email protected]>

* Options refactor (OpenBB-finance#1324)

* Fixed alphaquery_view

* finished options

* Fixed pylint

* Fixed tests

* Fixed tests

* Fixed tests

* update yfinance

* Tradier + Chartexchange

* change mocks from gtff to theme.visualize output

* tests

Co-authored-by: Theodore Aptekarev <[email protected]>
Co-authored-by: james <[email protected]>

* Refactor Stocks menu (OpenBB-finance#1325)

* Fix backtesting menu

* Refactor comparison analysis

* Refactor Dark pool shorts

* Refactor rest of menu

* Fix test

* Fix tests failing

* Fix tests fail

* Fix test failing

* Remove record mode=none to record new output

* Rewrite test output

* Rewrite test outputs

* Adding more rewritten test output

* Mock plt.show

* Mock missing plt.show

* Missing @pytest.mark.vcr

* Updating tests : common/behavioural_analysis/finbrain

* Improve notebooks API coverage for CA and DPS

* Silence annoying flake8 warning

Co-authored-by: Chavithra PARANA <[email protected]>
Co-authored-by: Theodore Aptekarev <[email protected]>

* Charts update for common/pred (OpenBB-finance#1344)

* Add external axes support to common/ba/finbrain

* Add external axes support to common/ba/twitter

* Add external axes support to common/ba/google

* Add external axes support to common/ba/sentimentinvestor

* Add sentimentinvestor to the notebooks API

* Fix tests

* Update stylesheet files

* Refactor charts for common/qa

* Update the forgotten line plot

* Update tests

* Add missing arg to a docstring

* Style pred helper and controllers

* Update ETS plot

* Update plots in KNN and pred helper

* Update plot and pretty table for arima

* Update plot for common/pred/regression

* Refactor mc_view

* Fix linting

* Fix mypy

* Move plot title to the axis level to make more vertical space

Co-authored-by: Minh Hoang <[email protected]>
Co-authored-by: jmaslek <[email protected]>

* linter

* Update common/ba test data

* Change etf candle to match stock candle

* try updating sia test

Co-authored-by: Colin Delahunty <[email protected]>
Co-authored-by: jmaslek <[email protected]>
Co-authored-by: minhhoang1023 <[email protected]>
Co-authored-by: Minh Hoang <[email protected]>
Co-authored-by: Chavithra PARANA <[email protected]>
  • Loading branch information
6 people authored Feb 12, 2022
1 parent 0c0ef39 commit e1b6022
Show file tree
Hide file tree
Showing 280 changed files with 93,935 additions and 13,270 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -40,5 +40,8 @@ jupyterlab/*/ui-tests/tests/*.ts-snapshots/
# Sphinx documentation build files
docs/_build

# User stylesheets
styles/user

# the file containing the API keys for the web version
gamestonk_terminal_web/setenv
2 changes: 1 addition & 1 deletion gamestonk_terminal/alternative/covid/covid_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def call_rates(self, other_args: List[str]):
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="rates",
description="Show historical rates country.",
description="Show historical death/cases rates for a country.",
)
ns_parser = parse_known_args_and_warn(
parser,
Expand Down
110 changes: 66 additions & 44 deletions gamestonk_terminal/alternative/covid/covid_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,12 @@

import logging
import os
from typing import Optional, List

import matplotlib.dates as mdates
import matplotlib.pyplot as plt
import pandas as pd

import gamestonk_terminal.feature_flags as gtff
from gamestonk_terminal.config_terminal import theme
from gamestonk_terminal.alternative.covid import covid_model
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal.decorators import log_start_end
Expand All @@ -24,7 +24,11 @@

@log_start_end(log=logger)
def display_covid_ov(
country, raw: bool = False, limit: int = 10, export: str = ""
country,
raw: bool = False,
limit: int = 10,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Show historical cases and deaths by country
Expand All @@ -38,38 +42,45 @@ def display_covid_ov(
Number of raw data to show
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
External axes (2 axis is expected in the list), by default None
"""
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()
# This plot has 2 axes
if external_axes is None:
_, ax1 = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
ax2 = ax1.twinx()
else:
if len(external_axes) != 2:
console.print("[red]Expected list of 1 axis item./n[/red]")
return
ax1, ax2 = external_axes

ax1.plot(cases.index, cases, color=theme.up_color, alpha=0.2)
ax1.plot(cases.index, cases.rolling(7).mean(), color=theme.up_color)
ax1.set_ylabel("Cases (1k)")
theme.style_primary_axis(ax1)
ax1.yaxis.set_label_position("left")

ax2.plot(deaths.index, deaths, color=theme.down_color, alpha=0.2)
ax2.plot(deaths.index, deaths.rolling(7).mean(), color=theme.down_color)
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")
ax2.set_ylabel("Deaths")
theme.style_twin_axis(ax2)
ax2.yaxis.set_label_position("right")

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])
ax1.set_xlim(ov.index[0], ov.index[-1])
legend = ax2.legend(ov.columns)
legend.legendHandles[1].set_color(theme.down_color)
legend.legendHandles[0].set_color(theme.up_color)

fig.tight_layout(pad=2)
if gtff.USE_ION:
plt.ion()
plt.show()
if external_axes is None:
theme.visualize_output()

if raw:
ov.index = [x.strftime("%Y-%m-%d") for x in ov.index]
Expand All @@ -80,7 +91,6 @@ def display_covid_ov(
index_name="Date",
title=f"[bold]{country} COVID Numbers[/bold]",
)

console.print("")

if export:
Expand All @@ -89,7 +99,12 @@ def display_covid_ov(

@log_start_end(log=logger)
def display_covid_stat(
country, stat: str = "cases", raw: bool = False, limit: int = 10, export: str = ""
country,
stat: str = "cases",
raw: bool = False,
limit: int = 10,
export: str = "",
external_axes: Optional[List[plt.Axes]] = None,
) -> None:
"""Show historical cases and deaths by country
Expand All @@ -105,6 +120,8 @@ def display_covid_stat(
Number of raw data to show
export: str
Format to export data
external_axes : Optional[List[plt.Axes]], optional
External axes (1 axis is expected in the list), by default None
"""
console.print("")
if stat == "cases":
Expand All @@ -119,27 +136,33 @@ def display_covid_stat(
console.print("Invalid stat selected.\n")
return

fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
# This plot has 1 axes
if external_axes is None:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
else:
if len(external_axes) != 1:
console.print("[red]Expected list of 1 axis item./n[/red]")
return
(ax,) = external_axes

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")
ax.set_ylabel(stat.title() + " (1k)")
color = theme.up_color
elif stat == "deaths":
ax.set_ylabel(stat.title())
color = theme.down_color
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_ylabel(stat.title() + " (Deaths/Cases)")
color = theme.get_colors(reverse=True)[0]

ax.plot(data.index, data, color=color, alpha=0.2)
ax.plot(data.index, data.rolling(7).mean(), color=color)
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()
theme.style_primary_axis(ax)

if external_axes is None:
theme.visualize_output()

if raw:
data.index = [x.strftime("%Y-%m-%d") for x in data.index]
Expand All @@ -150,7 +173,6 @@ def display_covid_stat(
index_name="Date",
title=f"[bold]{country} COVID {stat}[/bold]",
)

console.print("")

export_data(export, os.path.dirname(os.path.abspath(__file__)), stat, data)
Expand Down
2 changes: 2 additions & 0 deletions gamestonk_terminal/api.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,5 @@
from .forex import forex_api as forex
from .mutual_funds import mutual_fund_api as funds
from .portfolio import portfolio_api as portfolio

from .config_terminal import theme
54 changes: 31 additions & 23 deletions gamestonk_terminal/common/behavioural_analysis/finbrain_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,14 @@

import logging
import os
from typing import Optional, List

import matplotlib.dates as mdates
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
from pandas.plotting import register_matplotlib_converters

from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.config_terminal import theme
from gamestonk_terminal.common.behavioural_analysis import finbrain_model
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal.decorators import log_start_end
Expand All @@ -23,8 +23,6 @@

logger = logging.getLogger(__name__)

register_matplotlib_converters()


@log_start_end(log=logger)
def sentiment_coloring(val: float, last_val: float) -> str:
Expand All @@ -34,7 +32,9 @@ def sentiment_coloring(val: float, last_val: float) -> str:


@log_start_end(log=logger)
def plot_sentiment(sentiment: pd.DataFrame, ticker: str) -> None:
def plot_sentiment(
sentiment: pd.DataFrame, ticker: str, external_axes: Optional[List[plt.Axes]] = None
) -> None:
"""Plot Sentiment analysis provided by FinBrain's API
Parameters
Expand All @@ -44,25 +44,31 @@ def plot_sentiment(sentiment: pd.DataFrame, ticker: str) -> None:
ticker : str
Ticker to get the sentiment analysis from
"""
fig, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
# This plot has 1 axis
if external_axes is None:
_, ax = plt.subplots(figsize=plot_autoscale(), dpi=PLOT_DPI)
else:
if len(external_axes) != 1:
console.print("[red]Expected list of one axis item./n[/red]")
return
(ax,) = external_axes

for index, row in sentiment.iterrows():
if float(row["Sentiment Analysis"]) >= 0:
ax.scatter(index, float(row["Sentiment Analysis"]), s=100, c="green")
ax.scatter(
index, float(row["Sentiment Analysis"]), s=100, color=theme.up_color
)
else:
ax.scatter(index, float(row["Sentiment Analysis"]), s=100, c="red")
ax.axhline(y=0, color="k", linestyle="--", lw=2)
ax.scatter(
index, float(row["Sentiment Analysis"]), s=100, color=theme.down_color
)
ax.axhline(y=0, linestyle="--")
ax.set_xlabel("Time")
ax.set_ylabel("Sentiment")
ax.grid(b=True, which="major", color="#666666", linestyle="-")
ax.minorticks_on()
ax.grid(b=True, which="minor", color="#999999", linestyle="-", alpha=0.2)
start_date = sentiment.index[-1].strftime("%Y/%m/%d")
ax.set_title(
f"FinBrain's Sentiment Analysis for {ticker.upper()} since {start_date}"
)
plt.gca().xaxis.set_major_formatter(mdates.DateFormatter("%Y/%m/%d"))
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=1))
plt.gcf().autofmt_xdate()
ax.set_ylim([-1.1, 1.1])
senValues = np.array(pd.to_numeric(sentiment["Sentiment Analysis"].values))
senNone = np.array(0 * len(sentiment))
Expand All @@ -72,7 +78,7 @@ def plot_sentiment(sentiment: pd.DataFrame, ticker: str) -> None:
0,
where=(senValues < senNone),
alpha=0.30,
color="red",
color=theme.down_color,
interpolate=True,
)
ax.fill_between(
Expand All @@ -81,17 +87,19 @@ def plot_sentiment(sentiment: pd.DataFrame, ticker: str) -> None:
0,
where=(senValues >= senNone),
alpha=0.30,
color="green",
color=theme.up_color,
interpolate=True,
)
if gtff.USE_ION:
plt.ion()
fig.tight_layout()
plt.show()
theme.style_primary_axis(ax)

if external_axes is None:
theme.visualize_output()


@log_start_end(log=logger)
def display_sentiment_analysis(ticker: str, export: str = ""):
def display_sentiment_analysis(
ticker: str, export: str = "", external_axes: Optional[List[plt.Axes]] = None
):
"""Sentiment analysis from FinBrain
Parameters
Expand All @@ -106,7 +114,7 @@ def display_sentiment_analysis(ticker: str, export: str = ""):
console.print("No sentiment data found.\n")
return

plot_sentiment(df_sentiment, ticker)
plot_sentiment(sentiment=df_sentiment, ticker=ticker, external_axes=external_axes)

df_sentiment.sort_index(ascending=True, inplace=True)

Expand Down
Loading

0 comments on commit e1b6022

Please sign in to comment.