Skip to content

Commit

Permalink
Merge branch 'develop' into hotfix/4833
Browse files Browse the repository at this point in the history
  • Loading branch information
the-praxs authored May 2, 2023
2 parents ace59b8 + 7a19424 commit bd1dad4
Show file tree
Hide file tree
Showing 22 changed files with 398 additions and 498 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ If you wish to install the OpenBB Terminal or the OpenBB SDK, please use one of
|:-|:-|
|[PyPI](https://docs.openbb.co/terminal/installation/pypi)|If you wish to use the OpenBB SDK in Python or Jupyter Notebooks|
|[Source](https://docs.openbb.co/terminal/installation/source)|If you wish to contribute to the development of the OpenBB Terminal|
nbsp;|
<!-- nbsp;| -->

## 2. Contributing

Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/core/models/system_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ class SystemModel(BaseModel):
PLATFORM: str = str(platform.platform())

# OpenBB section
VERSION = "3.0.0"
VERSION: str = "3.0.0"

# Logging section
LOGGING_APP_ID: str = "REPLACE_ME"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,10 @@ def plot_bbands(self, fig: OpenBBFigure, df_ta: pd.DataFrame, inchart_index: int
secondary_y=self.show_volume,
)
bbands_text = (
columns_regex(df_ta, "BBL")[0]
.replace("BBL_", "BB")
.replace("_", ",")
.split(".")[0]
columns_regex(df_ta, "BBL")[0].replace("BBL_", "BB").replace("_", ",")
)
if float(bbands_text.split(",")[1]) % 1 == 0:
bbands_text = bbands_text.split(".")[0]
fig.add_annotation(
xref="paper",
yref="paper",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,7 @@ def options(self):
Attributes:
`chains`: Get Option Chain For A Stock. No greek data is returned\n
`dte`: Gets days to expiration from yfinance option date\n
`dte`: Returns a new column containing the DTE as an integer, including 0.\n
`eodchain`: Get full EOD option date across all expirations\n
`expirations`: Get Option Chain Expirations\n
`generate_data`: Gets x values, and y values before and after premiums\n
Expand Down
4 changes: 2 additions & 2 deletions openbb_terminal/core/sdk/models/stocks_sdk_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -449,7 +449,7 @@ class StocksOptions(Category):
Attributes:
`chains`: Get Option Chain For A Stock. No greek data is returned\n
`dte`: Gets days to expiration from yfinance option date\n
`dte`: Returns a new column containing the DTE as an integer, including 0.\n
`eodchain`: Get full EOD option date across all expirations\n
`expirations`: Get Option Chain Expirations\n
`generate_data`: Gets x values, and y values before and after premiums\n
Expand Down Expand Up @@ -477,7 +477,7 @@ class StocksOptions(Category):
def __init__(self):
super().__init__()
self.chains = lib.stocks_options_sdk_helper.get_full_option_chain
self.dte = lib.stocks_options_yfinance_model.get_dte
self.dte = lib.stocks_options_helpers.get_dte
self.eodchain = lib.stocks_options_intrinio_model.get_full_chain_eod
self.expirations = lib.stocks_options_sdk_helper.get_option_expirations
self.generate_data = lib.stocks_options_yfinance_model.generate_data
Expand Down
1 change: 1 addition & 0 deletions openbb_terminal/core/sdk/sdk_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@
intrinio_model as stocks_options_intrinio_model,
intrinio_view as stocks_options_intrinio_view,
nasdaq_model as stocks_options_nasdaq_model,
op_helpers as stocks_options_helpers,
options_sdk_helper as stocks_options_sdk_helper,
options_view as stocks_options_view,
tradier_model as stocks_options_tradier_model,
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/core/sdk/trail_map.csv
Original file line number Diff line number Diff line change
Expand Up @@ -503,7 +503,7 @@ stocks.ins.stats,stocks_insider_sdk_helper.stats,
stocks.load,stocks_helper.load,
stocks.news,common_ultima_newsmonitor_model.get_news,
stocks.options.chains,stocks_options_sdk_helper.get_full_option_chain,
stocks.options.dte,stocks_options_yfinance_model.get_dte,
stocks.options.dte,stocks_options_helpers.get_dte,
stocks.options.eodchain,stocks_options_intrinio_model.get_full_chain_eod,
stocks.options.expirations,stocks_options_sdk_helper.get_option_expirations,
stocks.options.generate_data,stocks_options_yfinance_model.generate_data,
Expand Down
2 changes: 1 addition & 1 deletion openbb_terminal/helper_funcs.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ def check_indicator_parameters(args: str, _help: bool = False) -> str:


def check_positive_float(value) -> float:
"""Argparse type to check positive int."""
"""Argparse type to check positive float."""
new_value = float(value)
if new_value <= 0:
log_and_raise(
Expand Down
168 changes: 54 additions & 114 deletions openbb_terminal/stocks/fundamental_analysis/business_insider_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@

import json
import logging
import re
from typing import Tuple

import pandas as pd
Expand Down Expand Up @@ -193,120 +192,61 @@ def get_estimates(symbol: str) -> Tuple[pd.DataFrame, pd.DataFrame, pd.DataFrame
"lxml",
)

l_estimates_year_header = list()
l_estimates_quarter_header = list()
for estimates_header in text_soup_market_business_insider.findAll(
"th", {"class": "table__th text-right"}
):
s_estimates_header = estimates_header.text.strip()
if s_estimates_header.isdigit():
l_estimates_year_header.append(s_estimates_header)
elif ("in %" not in s_estimates_header) and ("Job" not in s_estimates_header):
l_estimates_quarter_header.append(s_estimates_header)

l_estimates_year_metric = list()
for estimates_year_metric in text_soup_market_business_insider.findAll(
"td", {"class": "table__td black"}
):
l_estimates_year_metric.append(estimates_year_metric.text)

l_estimates_quarter_metric = list()
for estimates_quarter_metric in text_soup_market_business_insider.findAll(
"td", {"class": "table__td font-color-dim-gray"}
):
l_estimates_quarter_metric.append(estimates_quarter_metric.text)

d_metric_year = dict()
d_metric_quarter_earnings = dict()
d_metric_quarter_revenues = dict()
l_metrics = list()
n_metrics = 0
b_year = True
for idx, metric_value in enumerate(
text_soup_market_business_insider.findAll(
"td", {"class": "table__td text-right"}
)
):
if b_year:
# YEAR metrics
l_metrics.append(metric_value.text.strip())

# Check if we have processed all year metrics
if n_metrics > len(l_estimates_year_metric) - 1:
b_year = False
n_metrics = 0
l_metrics = list()
idx_y = idx

# Add value to dictionary
if (idx + 1) % len(l_estimates_year_header) == 0:
d_metric_year[l_estimates_year_metric[n_metrics]] = l_metrics
l_metrics = list()
n_metrics += 1

if not b_year:
# QUARTER metrics
l_metrics.append(metric_value.text.strip())

# Check if we have processed all quarter metrics
if n_metrics > len(l_estimates_quarter_metric) - 1:
break

# Add value to dictionary
if (idx - idx_y + 1) % len(l_estimates_quarter_header) == 0:
if n_metrics < 4:
d_metric_quarter_earnings[
l_estimates_quarter_metric[n_metrics]
] = l_metrics
else:
d_metric_quarter_revenues[
l_estimates_quarter_metric[n_metrics - 4]
] = l_metrics
l_metrics = list()
n_metrics += 1

df_year_estimates = pd.DataFrame.from_dict(
d_metric_year, orient="index", columns=l_estimates_year_header
)
df_year_estimates.index.name = "YEARLY ESTIMATES"
df_quarter_earnings = pd.DataFrame.from_dict(
d_metric_quarter_earnings,
orient="index",
columns=l_estimates_quarter_header,
# Get all tables and convert them to list of pandas dataframes
tables = text_soup_market_business_insider.find_all("table")
list_df = pd.read_html(str(tables))

# Get year estimates
df_year_estimates = list_df[3]
l_year_estimates_columns = df_year_estimates.columns.tolist()
l_year_estimates_columns[0] = "YEARLY ESTIMATES"
df_year_estimates.columns = l_year_estimates_columns
df_year_estimates.set_index("YEARLY ESTIMATES", inplace=True)

df_quarter = list_df[4]
date_row = dict()

# Get quarter earnings estimates
df_quarter_earnings = df_quarter.iloc[0:5, :].reset_index(drop=True).copy()
df_quarter_earnings.drop(index=0, inplace=True)
l_quarter_earnings_columns = df_quarter_earnings.columns.tolist()
l_quarter_earnings_columns[0] = "QUARTER EARNINGS ESTIMATES"
date_row["QUARTER EARNINGS ESTIMATES"] = "Date"

# Adding Date info to add to dataframe
for col in l_quarter_earnings_columns[1:]:
key = col.split("ending")[0].strip()
value = col[col.find("ending") :].strip()
date_row[key] = value

df_quarter_earnings.columns = date_row.keys()
date_row = pd.DataFrame(date_row, index=[0])
df_quarter_earnings = pd.concat([date_row, df_quarter_earnings]).reset_index(
drop=True
)
# df_quarter_earnings.index.name = 'Earnings'
df_quarter_revenues = pd.DataFrame.from_dict(
d_metric_quarter_revenues,
orient="index",
columns=l_estimates_quarter_header,
df_quarter_earnings.set_index("QUARTER EARNINGS ESTIMATES", inplace=True)

# Setting date_row to empty dict object
date_row = dict()

# Get quarter revenues estimates
df_quarter_revenues = df_quarter.iloc[5:, :].reset_index(drop=True).copy()
df_quarter_revenues.drop(index=0, inplace=True)
l_quarter_revenues_columns = df_quarter_revenues.columns.tolist()
l_quarter_revenues_columns[0] = "QUARTER REVENUES ESTIMATES"
date_row["QUARTER REVENUES ESTIMATES"] = "Date"

# Adding Date info to add to dataframe
for col in l_quarter_revenues_columns[1:]:
key = col.split("ending")[0].strip()
value = col[col.find("ending") :].strip()
date_row[key] = value

df_quarter_revenues.columns = date_row.keys()
date_row = pd.DataFrame(date_row, index=[0])
df_quarter_revenues = pd.concat([date_row, df_quarter_revenues]).reset_index(
drop=True
)
# df_quarter_revenues.index.name = 'Revenues'

if not df_quarter_earnings.empty:
l_quarter = list()
l_date = list()
for quarter_title in df_quarter_earnings.columns:
l_quarter.append(re.split(" ending", quarter_title)[0])
if len(re.split(" ending", quarter_title)) == 2:
l_date.append(
"ending " + re.split(" ending", quarter_title)[1].strip()
)
else:
l_date.append("-")

df_quarter_earnings.index.name = "QUARTER EARNINGS ESTIMATES"
df_quarter_earnings.columns = l_quarter
df_quarter_earnings.loc["Date"] = l_date
df_quarter_earnings = df_quarter_earnings.reindex(
["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]
)

if not df_quarter_revenues.empty:
df_quarter_revenues.index.name = "QUARTER REVENUES ESTIMATES"
df_quarter_revenues.columns = l_quarter
df_quarter_revenues.loc["Date"] = l_date
df_quarter_revenues = df_quarter_revenues.reindex(
["Date", "No. of Analysts", "Average Estimate", "Year Ago", "Publish Date"]
)
df_quarter_revenues.set_index("QUARTER REVENUES ESTIMATES", inplace=True)

return df_year_estimates, df_quarter_earnings, df_quarter_revenues
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def display_estimates(
df_quarter_revenues,
) = business_insider_model.get_estimates(symbol)

if estimate == "annualearnings":
if estimate == "annual_earnings":
print_rich_table(
df_year_estimates,
headers=list(df_year_estimates.columns),
Expand All @@ -231,7 +231,7 @@ def display_estimates(
sheet_name,
)

elif estimate == "quarterearnings":
elif estimate == "quarter_earnings":
print_rich_table(
df_quarter_earnings,
headers=list(df_quarter_earnings.columns),
Expand All @@ -247,7 +247,7 @@ def display_estimates(
sheet_name,
)

elif estimate == "annualrevenue":
elif estimate == "quarter_revenues":
print_rich_table(
df_quarter_revenues,
headers=list(df_quarter_revenues.columns),
Expand Down
4 changes: 2 additions & 2 deletions openbb_terminal/stocks/fundamental_analysis/fa_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ class FundamentalAnalysisController(StockBaseController):
PATH = "/stocks/fa/"

SHRS_CHOICES = ["major", "institutional", "mutualfund"]
ESTIMATE_CHOICES = ["annualrevenue", "annualearnings", "quarterearnings"]
ESTIMATE_CHOICES = ["annual_earnings", "quarter_earnings", "quarter_revenues"]
CHOICES_GENERATION = True

def __init__(
Expand Down Expand Up @@ -1858,7 +1858,7 @@ def call_est(self, other_args: List[str]):
help="Estimates to get",
dest="estimate",
choices=self.ESTIMATE_CHOICES,
default="annualearnings",
default="annual_earnings",
)
ns_parser = self.parse_known_args_and_warn(
parser, other_args, EXPORT_ONLY_RAW_DATA_ALLOWED
Expand Down
19 changes: 16 additions & 3 deletions openbb_terminal/stocks/options/op_helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
# pylint: disable=too-many-arguments


@log_start_end(log=logger)
def get_strikes(
min_sp: float, max_sp: float, current_price: float
) -> Tuple[float, float]:
Expand Down Expand Up @@ -58,7 +57,6 @@ def get_loss_at_strike(strike: float, chain: pd.DataFrame) -> float:
return loss


@log_start_end(log=logger)
def calculate_max_pain(chain: pd.DataFrame) -> Union[int, float]:
"""Returns the max pain for a given call/put dataframe
Expand Down Expand Up @@ -104,7 +102,6 @@ def convert(orig: str, to: str) -> float:
raise ValueError("Invalid to format, please use '%' or ','.")


@log_start_end(log=logger)
def rn_payoff(x: str, df: pd.DataFrame, put: bool, delta: int, rf: float) -> float:
"""The risk neutral payoff for a stock
Parameters
Expand Down Expand Up @@ -594,3 +591,19 @@ def Vomma(self, change):
* norm.pdf(self.d1)
/ self._sigma
)


def get_dte(chain: pd.DataFrame) -> pd.DataFrame:
"""
Returns a new column containing the DTE as an integer, including 0.
Requires the chain to have the column labeled as, expiration.
"""
if "expiration" not in chain.columns:
raise ValueError("No column labeled 'expiration' was found.")

now = datetime.now()
temp = pd.DatetimeIndex(chain.expiration)
temp_ = (temp - now).days + 1
chain["dte"] = temp_

return chain
3 changes: 2 additions & 1 deletion openbb_terminal/stocks/technical_analysis/ta_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
EXPORT_ONLY_RAW_DATA_ALLOWED,
check_indicator_parameters,
check_positive,
check_positive_float,
check_positive_list,
valid_date,
)
Expand Down Expand Up @@ -1159,7 +1160,7 @@ def call_bbands(self, other_args: List[str]):
"--std",
action="store",
dest="n_std",
type=check_positive,
type=check_positive_float,
default=2,
help="std",
)
Expand Down
Loading

0 comments on commit bd1dad4

Please sign in to comment.