Files
OpenBB/gamestonk_terminal/stocks/comparison_analysis/ca_controller.py
LBolte29 fd58219282 adjusted format of logs (#1292)
adjusted format of logs
2022-02-17 12:33:59 +01:00

983 lines
34 KiB
Python

"""Comparison Analysis Controller Module"""
__docformat__ = "numpy"
import argparse
import logging
import random
from datetime import datetime, timedelta
from typing import List
import yfinance as yf
from prompt_toolkit.completion import NestedCompleter
from gamestonk_terminal import feature_flags as gtff
from gamestonk_terminal.decorators import log_start_end
from gamestonk_terminal.helper_funcs import (
EXPORT_ONLY_RAW_DATA_ALLOWED,
check_non_negative,
check_positive,
parse_known_args_and_warn,
valid_date,
)
from gamestonk_terminal.menu import session
from gamestonk_terminal.parent_classes import BaseController
from gamestonk_terminal.portfolio.portfolio_optimization import po_controller
from gamestonk_terminal.rich_config import console
from gamestonk_terminal.stocks.comparison_analysis import (
finbrain_view,
finnhub_model,
finviz_compare_model,
finviz_compare_view,
marketwatch_view,
polygon_model,
yahoo_finance_model,
yahoo_finance_view,
)
# pylint: disable=E1121,C0302,R0904
# TODO: HELP WANTED! This controller still has some view functionality that should be
# refactored in order to implement an API wrapper. Use the discovery controller
# as an example.
logger = logging.getLogger(__name__)
class ComparisonAnalysisController(BaseController):
"""Comparison Analysis Controller class"""
CHOICES_COMMANDS = [
"ticker",
"getpoly",
"getfinnhub",
"getfinviz",
"set",
"add",
"rmv",
"historical",
"hcorr",
"volume",
"income",
"balance",
"cashflow",
"sentiment",
"scorr",
"overview",
"valuation",
"financial",
"ownership",
"performance",
"technical",
"tsne",
]
CHOICES_MENUS = [
"po",
]
PATH = "/stocks/ca/"
def __init__(self, similar: List[str] = None, queue: List[str] = None):
"""Constructor"""
super().__init__(queue)
self.ticker = ""
self.user = ""
if similar:
self.similar = similar
if len(similar) == 1:
self.ticker = self.similar[0].upper()
else:
self.similar = []
if session and gtff.USE_PROMPT_TOOLKIT:
choices: dict = {c: {} for c in self.controller_choices}
self.completer = NestedCompleter.from_nested_dict(choices)
def print_help(self):
"""Print help"""
has_ticker_start = "" if self.ticker else "[unvl]"
has_ticker_end = "" if self.ticker else "[/unvl]"
has_similar_start = "" if self.similar and len(self.similar) > 1 else "[unvl]"
has_similar_end = "" if self.similar and len(self.similar) > 1 else "[/unvl]"
help_text = f"""[cmds]
ticker set ticker to get similar companies from[/cmds]
[param]Ticker to get similar companies from: [/param]{self.ticker}
[cmds]{has_ticker_start}
tsne run TSNE on all SP500 stocks and returns closest tickers
getpoly get similar stocks from polygon API
getfinnhub get similar stocks from finnhub API
getfinviz get similar stocks from finviz API{has_ticker_end}
set reset and set similar companies
add add more similar companies
rmv remove similar companies individually or all[/cmds]
{has_similar_start}
[param]Similar Companies: [/param]{', '.join(self.similar) if self.similar else ''}
[src][Yahoo Finance][/src]
historical historical price data comparison
hcorr historical price correlation
volume historical volume data comparison
[src][Market Watch][/src]
income income financials comparison
balance balance financials comparison
cashflow cashflow comparison
[src][Finbrain][/src]
sentiment sentiment analysis comparison
scorr sentiment correlation
[src][Finviz][/src]
overview brief overview comparison
valuation brief valuation comparison
financial brief financial comparison
ownership brief ownership comparison
performance brief performance comparison
technical brief technical comparison
[menu]> po portfolio optimization for selected tickers[/menu]{has_similar_end}
"""
console.print(text=help_text, menu="Stocks - Comparison Analysis")
def custom_reset(self):
"""Class specific component of reset command"""
if self.similar:
return ["stocks", "ca", f"set {','.join(self.similar)}"]
return []
# TODO: Figure out if this function is actually needed here
@log_start_end(log=logger)
def call_ticker(self, other_args: List[str]):
"""Process ticker command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ticker",
description="""Set ticker to extract similar from""",
)
parser.add_argument(
"-t",
"--ticker",
dest="ticker",
type=str,
required="-h" not in other_args,
help="Ticker get similar tickers from",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if "," in ns_parser.ticker:
console.print("Only one ticker must be selected!")
else:
stock_data = yf.download(
ns_parser.ticker,
progress=False,
)
if stock_data.empty:
console.print(
f"The ticker '{ns_parser.ticker}' provided does not exist!"
)
else:
self.ticker = ns_parser.ticker.upper()
console.print("")
@log_start_end(log=logger)
def call_tsne(self, other_args: List[str]):
"""Process tsne command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="tsne",
description="""Get similar companies to compare with using sklearn TSNE.""",
)
parser.add_argument(
"-r",
"--learnrate",
default=200,
dest="lr",
type=check_non_negative,
help="TSNE Learning rate. Typical values are between 50 and 200",
)
parser.add_argument(
"-l",
"--limit",
default=10,
dest="limit",
type=check_positive,
help="Limit of stocks to retrieve. The subsample will occur randomly.",
)
parser.add_argument(
"-p", "--no_plot", action="store_true", default=False, dest="no_plot"
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-l")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if self.ticker:
self.similar = yahoo_finance_model.get_sp500_comps_tsne(
self.ticker,
lr=ns_parser.lr,
no_plot=ns_parser.no_plot,
num_tickers=ns_parser.limit,
)
self.similar = [self.ticker] + self.similar
console.print(
f"[ML] Similar Companies: {', '.join(self.similar)}", "\n"
)
else:
console.print(
"You need to 'set' a ticker to get similar companies from first!"
)
@log_start_end(log=logger)
def call_getfinviz(self, other_args: List[str]):
"""Process getfinviz command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="getfinviz",
description="""Get similar companies from finviz to compare with.""",
)
parser.add_argument(
"-n",
"--nocountry",
action="store_true",
default=False,
dest="b_no_country",
help="Similar stocks from finviz using only Industry and Sector.",
)
parser.add_argument(
"-l",
"--limit",
default=10,
dest="limit",
type=check_positive,
help="Limit of stocks to retrieve.",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-l")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if self.ticker:
if ns_parser.b_no_country:
compare_list = ["Sector", "Industry"]
else:
compare_list = ["Sector", "Industry", "Country"]
self.similar, self.user = finviz_compare_model.get_similar_companies(
self.ticker, compare_list
)
if self.ticker.upper() in self.similar:
self.similar.remove(self.ticker.upper())
if len(self.similar) > ns_parser.limit:
random.shuffle(self.similar)
self.similar = sorted(self.similar[: ns_parser.limit])
console.print(
f"The limit of stocks to compare are {ns_parser.limit}. The subsample will occur randomly.\n",
)
if self.similar:
self.similar = [self.ticker] + self.similar
console.print(
f"[{self.user}] Similar Companies: {', '.join(self.similar)}",
"\n",
)
else:
console.print(
"You need to 'set' a ticker to get similar companies from first!"
)
@log_start_end(log=logger)
def call_getpoly(self, other_args: List[str]):
"""Process get command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="getpoly",
description="""Get similar companies from polygon to compare with.""",
)
parser.add_argument(
"-u",
"--us_only",
action="store_true",
default=False,
dest="us_only",
help="Show only stocks from the US stock exchanges",
)
parser.add_argument(
"-l",
"--limit",
default=10,
dest="limit",
type=check_positive,
help="Limit of stocks to retrieve.",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-l")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if self.ticker:
self.similar, self.user = polygon_model.get_similar_companies(
self.ticker, ns_parser.us_only
)
if self.ticker.upper() in self.similar:
self.similar.remove(self.ticker.upper())
if len(self.similar) > ns_parser.limit:
random.shuffle(self.similar)
self.similar = sorted(self.similar[: ns_parser.limit])
console.print(
f"The limit of stocks to compare are {ns_parser.limit}. The subsample will occur randomly.\n",
)
self.similar = [self.ticker] + self.similar
if self.similar:
console.print(
f"[{self.user}] Similar Companies: {', '.join(self.similar)}",
"\n",
)
else:
console.print(
"You need to 'set' a ticker to get similar companies from first!"
)
@log_start_end(log=logger)
def call_getfinnhub(self, other_args: List[str]):
"""Process get command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="getfinnhub",
description="""Get similar companies from finnhub to compare with.""",
)
parser.add_argument(
"-l",
"--limit",
default=10,
dest="limit",
type=check_positive,
help="Limit of stocks to retrieve.",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-l")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if self.ticker:
self.similar, self.user = finnhub_model.get_similar_companies(
self.ticker
)
if self.ticker.upper() in self.similar:
self.similar.remove(self.ticker.upper())
if len(self.similar) > ns_parser.limit:
random.shuffle(self.similar)
self.similar = sorted(self.similar[: ns_parser.limit])
console.print(
f"The limit of stocks to compare are {ns_parser.limit}. The subsample will occur randomly.\n",
)
self.similar = [self.ticker] + self.similar
if self.similar:
console.print(
f"[{self.user}] Similar Companies: {', '.join(self.similar)}",
"\n",
)
else:
console.print(
"You need to 'set' a ticker to get similar companies from first!"
)
@log_start_end(log=logger)
def call_add(self, other_args: List[str]):
"""Process add command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="add",
description="""Add similar tickers to compare with.""",
)
parser.add_argument(
"-s",
"--similar",
dest="l_similar",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=[],
help="Tickers to add to similar list",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-s")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if self.similar:
self.similar = list(set(self.similar + ns_parser.l_similar))
else:
self.similar = ns_parser.l_similar
self.user = "Custom"
console.print(
f"[{self.user}] Similar Companies: {', '.join(self.similar)}", "\n"
)
@log_start_end(log=logger)
def call_rmv(self, other_args: List[str]):
"""Process rmv command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="rmv",
description="""Remove similar tickers to compare with.""",
)
parser.add_argument(
"-s",
"--similar",
dest="l_similar",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=[],
help="Tickers to remove from similar list",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-s")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if ns_parser.l_similar:
for symbol in ns_parser.l_similar:
if symbol in self.similar:
self.similar.remove(symbol)
else:
console.print(
f"Ticker {symbol} does not exist in similar list to be removed"
)
console.print(
f"[{self.user}] Similar Companies: {', '.join(self.similar)}"
)
else:
self.similar = []
console.print("")
self.user = "Custom"
@log_start_end(log=logger)
def call_set(self, other_args: List[str]):
"""Process set command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="set",
description="""Select similar companies to compare with.""",
)
parser.add_argument(
"-s",
"--similar",
dest="l_similar",
type=lambda s: [str(item).upper() for item in s.split(",")],
default=[],
help="similar companies to compare with.",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-s")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
self.similar = list(set(ns_parser.l_similar))
self.user = "Custom"
console.print(
f"[{self.user}] Similar Companies: {', '.join(self.similar)}", "\n"
)
@log_start_end(log=logger)
def call_historical(self, other_args: List[str]):
"""Process historical command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="historical",
description="""Historical price comparison between similar companies.""",
)
parser.add_argument(
"-t",
"--type",
action="store",
dest="type_candle",
type=str,
choices=["o", "h", "l", "c", "a"],
default="a", # in case it's adjusted close
help="Candle data to use: o-open, h-high, l-low, c-close, a-adjusted close.",
)
parser.add_argument(
"-n",
"--no-scale",
action="store_false",
dest="no_scale",
default=False,
help="Flag to not put all prices on same 0-1 scale",
)
parser.add_argument(
"-s",
"--start",
type=valid_date,
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
dest="start",
help="The starting date (format YYYY-MM-DD) of the stock",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
yahoo_finance_view.display_historical(
similar_tickers=self.similar,
start=ns_parser.start.strftime("%Y-%m-%d"),
candle_type=ns_parser.type_candle,
normalize=not ns_parser.no_scale,
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_hcorr(self, other_args: List[str]):
"""Process historical correlation command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="hcorr",
description=""" Correlation heatmap based on historical price comparison between similar
companies.
""",
)
parser.add_argument(
"-t",
"--type",
action="store",
dest="type_candle",
type=str,
choices=["o", "h", "l", "c", "a"],
default="a", # in case it's adjusted close
help="Candle data to use: o-open, h-high, l-low, c-close, a-adjusted close.",
)
parser.add_argument(
"-s",
"--start",
type=valid_date,
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
dest="start",
help="The starting date (format YYYY-MM-DD) of the stock",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")
ns_parser = parse_known_args_and_warn(parser, other_args)
if ns_parser:
if self.similar and len(self.similar) > 1:
yahoo_finance_view.display_correlation(
similar_tickers=self.similar,
start=ns_parser.start.strftime("%Y-%m-%d"),
candle_type=ns_parser.type_candle,
)
else:
console.print("Please make sure there are similar tickers selected. \n")
@log_start_end(log=logger)
def call_income(self, other_args: List[str]):
"""Process income command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="income",
description="""
Prints either yearly or quarterly income statement the company, and compares
it against similar companies.
""",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter financial data flag.",
)
parser.add_argument(
"-t",
"--timeframe",
dest="s_timeframe",
type=str,
default=None,
help="Specify yearly/quarterly timeframe. Default is last.",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
marketwatch_view.display_income_comparison(
similar=self.similar,
timeframe=ns_parser.s_timeframe,
quarter=ns_parser.b_quarter,
)
@log_start_end(log=logger)
def call_volume(self, other_args: List[str]):
"""Process volume command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="volume",
description="""Historical volume comparison between similar companies.
""",
)
parser.add_argument(
"-s",
"--start",
type=valid_date,
default=(datetime.now() - timedelta(days=366)).strftime("%Y-%m-%d"),
dest="start",
help="The starting date (format YYYY-MM-DD) of the stock",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-s")
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
yahoo_finance_view.display_volume(
similar_tickers=self.similar,
start=ns_parser.start.strftime("%Y-%m-%d"),
export=ns_parser.export,
)
else:
console.print("Please make sure there are similar tickers selected. \n")
@log_start_end(log=logger)
def call_balance(self, other_args: List[str]):
"""Process balance command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="balance",
description="""
Prints either yearly or quarterly balance statement the company, and compares
it against similar companies.
""",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter financial data flag.",
)
parser.add_argument(
"-t",
"--timeframe",
dest="s_timeframe",
type=str,
default=None,
help="Specify yearly/quarterly timeframe. Default is last.",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
marketwatch_view.display_balance_comparison(
similar=self.similar,
timeframe=ns_parser.s_timeframe,
quarter=ns_parser.b_quarter,
)
@log_start_end(log=logger)
def call_cashflow(self, other_args: List[str]):
"""Process cashflow command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="cashflow",
description="""
Prints either yearly or quarterly cashflow statement the company, and compares
it against similar companies.
""",
)
parser.add_argument(
"-q",
"--quarter",
action="store_true",
default=False,
dest="b_quarter",
help="Quarter financial data flag.",
)
parser.add_argument(
"-t",
"--timeframe",
dest="s_timeframe",
type=str,
default=None,
help="Specify yearly/quarterly timeframe. Default is last.",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
marketwatch_view.display_cashflow_comparison(
similar=self.similar,
timeframe=ns_parser.s_timeframe,
quarter=ns_parser.b_quarter,
)
@log_start_end(log=logger)
def call_sentiment(self, other_args: List[str]):
"""Process sentiment command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sentiment_compare",
description="""
FinBrain's sentiment comparison across similar tickers.
""",
)
parser.add_argument(
"-r",
"--raw",
action="store_true",
default=False,
help="Display raw sentiment data",
dest="raw",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finbrain_view.display_sentiment_compare(
similar=self.similar,
raw=ns_parser.raw,
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_scorr(self, other_args: List[str]):
"""Process sentiment correlation command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="sentiment_compare",
description="""
FinBrain's sentiment correlation across similar tickers.
""",
)
parser.add_argument(
"-r",
"--raw",
action="store_true",
default=False,
help="Display raw sentiment data",
dest="raw",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finbrain_view.display_sentiment_correlation(
similar=self.similar,
raw=ns_parser.raw,
export=ns_parser.export,
)
else:
console.print("Please make sure there are similar tickers selected. \n")
@log_start_end(log=logger)
def call_overview(self, other_args: List[str]):
"""Process overview command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="overview",
description="""
Prints screener data of similar companies. [Source: Finviz]
""",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finviz_compare_view.screener(
similar=self.similar,
data_type="overview",
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_valuation(self, other_args: List[str]):
"""Process valuation command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="valuation",
description="""
Prints screener data of similar companies. [Source: Finviz]
""",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finviz_compare_view.screener(
similar=self.similar,
data_type="valuation",
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_financial(self, other_args: List[str]):
"""Process financial command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="financial",
description="""
Prints screener data of similar companies. [Source: Finviz]
""",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finviz_compare_view.screener(
similar=self.similar,
data_type="financial",
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_ownership(self, other_args: List[str]):
"""Process ownership command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="ownership",
description="""
Prints screener data of similar companies. [Source: Finviz]
""",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finviz_compare_view.screener(
similar=self.similar,
data_type="ownership",
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_performance(self, other_args: List[str]):
"""Process performance command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="performance",
description="""
Prints screener data of similar companies. [Source: Finviz]
""",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finviz_compare_view.screener(
similar=self.similar,
data_type="performance",
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_technical(self, other_args: List[str]):
"""Process technical command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="technical",
description="""
Prints screener data of similar companies. [Source: Finviz]
""",
)
ns_parser = parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
)
if ns_parser:
if self.similar and len(self.similar) > 1:
finviz_compare_view.screener(
similar=self.similar,
data_type="technical",
export=ns_parser.export,
)
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)
@log_start_end(log=logger)
def call_po(self, _):
"""Call the portfolio optimization menu with selected tickers"""
if self.similar and len(self.similar) > 1:
self.queue = po_controller.PortfolioOptimization(
self.similar, self.queue
).menu(custom_path_menu_above="/portfolio/")
else:
console.print(
"Please make sure there are more than 1 similar tickers selected. \n"
)