Add sentiment analysis comparison and correlation

This commit is contained in:
didier
2021-03-21 20:48:50 +00:00
parent 01e039fb1b
commit df7e4d2f27
2 changed files with 294 additions and 6 deletions

View File

@@ -6,12 +6,13 @@ import requests
from typing import List
from datetime import datetime
import pandas as pd
from matplotlib import pyplot as plt
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal import config_terminal as cfg
from gamestonk_terminal.helper_funcs import get_flair, parse_known_args_and_warn
from gamestonk_terminal.comparison_analysis import yahoo_finance_api as yf_api
from gamestonk_terminal.comparison_analysis import market_watch_api as mw_api
from gamestonk_terminal.comparison_analysis import finbrain_api as f_api
from gamestonk_terminal.menu import session
from prompt_toolkit.completion import NestedCompleter
@@ -27,10 +28,12 @@ class ComparisonAnalysisController:
"get",
"select",
"historical",
"corr",
"hcorr",
"income",
"balance",
"cashflow",
"sentiment",
"scorr",
]
def __init__(
@@ -84,13 +87,16 @@ class ComparisonAnalysisController:
print(" select select similar companies")
print("")
if self.similar:
print(" historical historical data comparison")
print(" corr correlation between similar companies")
print(" historical historical price data comparison")
print(" hcorr historical price correlation")
print("")
print(" income income financials comparison")
print(" balance balance financials comparison")
print(" cashflow cashflow comparison")
print("")
print(" sentiment sentiment analysis comparison")
print(" scorr sentiment correlation")
print("")
return
@staticmethod
@@ -201,8 +207,8 @@ class ComparisonAnalysisController:
other_args, self.stock, self.ticker, self.start, self.interval, self.similar
)
def call_corr(self, other_args: List[str]):
"""Process correlation command"""
def call_hcorr(self, other_args: List[str]):
"""Process historical correlation command"""
yf_api.correlation(
other_args, self.stock, self.ticker, self.start, self.interval, self.similar
)
@@ -219,6 +225,14 @@ class ComparisonAnalysisController:
"""Process cashflow command"""
mw_api.compare_cashflow(other_args, self.ticker, self.similar)
def call_sentiment(self, other_args: List[str]):
"""Process sentiment command"""
f_api.sentiment_compare(other_args, self.ticker, self.similar)
def call_scorr(self, other_args: List[str]):
"""Process sentiment correlation command"""
f_api.sentiment_correlation(other_args, self.ticker, self.similar)
def menu(stock: pd.DataFrame, ticker: str, start: datetime, interval: str):
"""Comparison Analysis Menu"""
@@ -242,6 +256,8 @@ def menu(stock: pd.DataFrame, ticker: str, start: datetime, interval: str):
an_input = input(f"{get_flair()} (ca)> ")
try:
plt.close("all")
process_input = ca_controller.switch(an_input)
if process_input is not None:

View File

@@ -0,0 +1,272 @@
""" Comparison Analysis Finbrain API """
__docformat__ = "numpy"
import argparse
from typing import List
import requests
from matplotlib import pyplot as plt
import matplotlib.dates as mdates
import pandas as pd
from pandas.plotting import register_matplotlib_converters
import numpy as np
import seaborn as sns
from gamestonk_terminal.helper_funcs import (
parse_known_args_and_warn,
plot_autoscale,
)
from gamestonk_terminal.config_plot import PLOT_DPI
from gamestonk_terminal import feature_flags as gtff
register_matplotlib_converters()
def sentiment_compare(other_args: List[str], ticker: str, similar: List[str]):
"""Plot sentiments across similar companies
Parameters
----------
other_args : List[str]
Command line arguments to be processed with argparse
ticker : str
Main ticker to compare income
similar : List[str]
Similar companies to compare income with
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="sentiment_compare",
description="""
FinBrain's sentiment comparison across similar tickers.
Finbrain collects the news headlines from 15+ major financial news
sources on a daily basis and analyzes them to generate sentiment scores
for more than 4500 US stocks.FinBrain Technologies develops deep learning
algorithms for financial analysis and prediction, which currently serves
traders from more than 150 countries all around the world.
[Source: https://finbrain.tech]
""",
)
parser.add_argument(
"-s",
"--similar",
dest="l_similar",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=similar,
help="similar companies to compare with.",
)
parser.add_argument(
"-a",
"--also",
dest="l_also",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=[],
help="apart from loaded similar companies also compare with.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
l_similar = ns_parser.l_similar
l_similar += ns_parser.l_also
# Add main ticker to similar list of companies
l_similar = [ticker] + l_similar
df_sentiment = get_sentiments(l_similar)
if not df_sentiment.empty:
plot_sentiments(df_sentiment, l_similar)
print("")
except Exception as e:
print(e, "\n")
return
def sentiment_correlation(other_args: List[str], ticker: str, similar: List[str]):
"""Plot correlation sentiments across similar companies
Parameters
----------
other_args : List[str]
Command line arguments to be processed with argparse
ticker : str
Main ticker to compare income
similar : List[str]
Similar companies to compare income with
"""
parser = argparse.ArgumentParser(
add_help=False,
prog="sentiment_compare",
description="""
FinBrain's sentiment correlation across similar tickers.
Finbrain collects the news headlines from 15+ major financial news
sources on a daily basis and analyzes them to generate sentiment scores
for more than 4500 US stocks.FinBrain Technologies develops deep learning
algorithms for financial analysis and prediction, which currently serves
traders from more than 150 countries all around the world.
[Source: https://finbrain.tech]
""",
)
parser.add_argument(
"-s",
"--similar",
dest="l_similar",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=similar,
help="similar companies to compare with.",
)
parser.add_argument(
"-a",
"--also",
dest="l_also",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=[],
help="apart from loaded similar companies also compare with.",
)
try:
ns_parser = parse_known_args_and_warn(parser, other_args)
if not ns_parser:
return
l_similar = ns_parser.l_similar
l_similar += ns_parser.l_also
# Add main ticker to similar list of companies
l_similar = [ticker] + l_similar
df_sentiment = get_sentiments(l_similar)
if not df_sentiment.empty:
plot_correlation(df_sentiment, l_similar)
print("")
except Exception as e:
print(e, "\n")
return
def get_sentiments(similar: List[str]) -> pd.DataFrame:
"""Gets Sentiment analysis from several tickers provided by FinBrain's API
Parameters
----------
similar : List[str]
Similar tickers to get the sentiment analysis from
Returns
-------
DataFrame()
Contains sentiment analysis from several tickers
"""
df_sentiment = pd.DataFrame()
for ticker in similar:
result = requests.get(f"https://api.finbrain.tech/v0/sentiments/{ticker}")
if result.status_code == 200:
if "sentimentAnalysis" in result.json():
df_sentiment[ticker] = [
float(val)
for val in list(result.json()["sentimentAnalysis"].values())
]
else:
print(f"Unexpected data format from FinBrain API for {ticker}")
else:
print(f"Request error in retrieving {ticker} sentiment from FinBrain API")
if not df_sentiment.empty:
df_sentiment.index = list(result.json()["sentimentAnalysis"].keys())
df_sentiment.sort_index(ascending=True, inplace=True)
return df_sentiment
def plot_sentiments(df_sentiment: pd.DataFrame, similar: List[str]):
"""Plot Sentiment analysis comparison between similar companies
Parameters
----------
df_sentiment : pd.DataFrame
Dataframe with sentiment analysis from several similar companies
similar : List[str]
List of similar companies
"""
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
for idx, ticker in enumerate(similar):
offset = 2 * idx
plt.axhline(y=offset, color="k", linestyle="--", lw=2)
plt.axhline(y=offset + 1, color="k", linestyle="--", lw=1)
senValues = np.array(pd.to_numeric(df_sentiment[ticker].values))
senNone = np.array(0 * len(df_sentiment))
plt.fill_between(
df_sentiment.index,
pd.to_numeric(df_sentiment[ticker].values) + offset,
offset,
where=(senValues < senNone),
alpha=0.60,
color="red",
interpolate=True,
)
plt.fill_between(
df_sentiment.index,
pd.to_numeric(df_sentiment[ticker].values) + offset,
offset,
where=(senValues >= senNone),
alpha=0.60,
color="green",
interpolate=True,
)
plt.xlabel("Time")
plt.ylabel("Sentiment")
plt.axhline(y=-1, color="k", linestyle="--", lw=1)
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.yticks(np.arange(len(similar)) * 2, similar)
plt.title(f"FinBrain's Sentiment Analysis since {df_sentiment.index[0]}")
plt.gca().xaxis.set_major_locator(mdates.DayLocator(interval=1))
plt.gcf().autofmt_xdate()
if gtff.USE_ION:
plt.ion()
plt.show()
def plot_correlation(df_sentiment: pd.DataFrame, similar: List[str]):
"""Plot Sentiment correlation between similar companies
Parameters
----------
df_sentiment : pd.DataFrame
Dataframe with sentiment analysis from several similar companies
similar : List[str]
List of similar companies
"""
plt.figure(figsize=plot_autoscale(), dpi=PLOT_DPI)
mask = np.zeros((len(similar), len(similar)), dtype=bool)
mask[np.triu_indices(len(mask))] = True
sns.heatmap(
df_sentiment.corr(),
cbar_kws={"ticks": [-1.0, -0.5, 0.0, 0.5, 1.0]},
cmap="RdYlGn",
linewidths=1,
annot=True,
vmin=-1,
vmax=1,
mask=mask,
)
if gtff.USE_ION:
plt.ion()
plt.show()