mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-11-11 20:01:16 +00:00
DISC Cleanup (#1058)
* Get rid/cleanup of marketbeat functions * Get rid of last unused disc function + fix related tests * fix test
This commit is contained in:
@@ -4,7 +4,6 @@ __docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
import difflib
|
||||
from datetime import datetime
|
||||
from typing import List
|
||||
|
||||
from matplotlib import pyplot as plt
|
||||
@@ -16,7 +15,6 @@ from gamestonk_terminal.helper_funcs import (
|
||||
parse_known_args_and_warn,
|
||||
check_non_negative,
|
||||
check_positive,
|
||||
valid_date,
|
||||
check_int_range,
|
||||
try_except,
|
||||
system_clear,
|
||||
@@ -639,7 +637,7 @@ NASDAQ Data Link (Formerly Quandl):
|
||||
)
|
||||
parser.add_argument(
|
||||
"-a",
|
||||
"-ascend",
|
||||
"--ascend",
|
||||
dest="ascend",
|
||||
help="Flag to sort in ascending order",
|
||||
action="store_true",
|
||||
@@ -772,15 +770,7 @@ NASDAQ Data Link (Formerly Quandl):
|
||||
default=5,
|
||||
help="number of articles being printed",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--date",
|
||||
action="store",
|
||||
dest="s_date",
|
||||
type=valid_date,
|
||||
default=datetime.now().strftime("%Y-%m-%d"),
|
||||
help="starting date of articles",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--export",
|
||||
choices=["csv", "json", "xlsx"],
|
||||
@@ -798,10 +788,8 @@ NASDAQ Data Link (Formerly Quandl):
|
||||
return
|
||||
|
||||
seeking_alpha_view.news(
|
||||
news_type="trending",
|
||||
article_id=ns_parser.n_id,
|
||||
num=ns_parser.n_num,
|
||||
start_date=ns_parser.s_date,
|
||||
export=ns_parser.export,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,93 +0,0 @@
|
||||
""" MarketBeat Model """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from typing import List
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from gamestonk_terminal.helper_funcs import get_user_agent
|
||||
|
||||
|
||||
def get_ratings_html(url_ratings: str) -> str:
|
||||
"""Wraps HTTP requests.get for testibility
|
||||
|
||||
Parameters
|
||||
----------
|
||||
url_ratings : str
|
||||
Ratings URL
|
||||
|
||||
Returns
|
||||
-------
|
||||
str
|
||||
HTML page of ratings
|
||||
"""
|
||||
ratings_html = requests.get(
|
||||
url_ratings, headers={"User-Agent": get_user_agent()}
|
||||
).text
|
||||
|
||||
return ratings_html
|
||||
|
||||
|
||||
def get_ratings() -> List[dict]:
|
||||
"""Returns a list of ratings
|
||||
|
||||
Parameters
|
||||
----------
|
||||
None
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
Ratings list
|
||||
"""
|
||||
|
||||
ratings = []
|
||||
url_ratings = "https://www.marketbeat.com/ratings/"
|
||||
|
||||
text_soup_ratings = BeautifulSoup(
|
||||
get_ratings_html(url_ratings),
|
||||
"lxml",
|
||||
)
|
||||
|
||||
for stock_rows in text_soup_ratings.findAll("tr"):
|
||||
tds = stock_rows.findAll("td")
|
||||
if len(tds) == 8:
|
||||
rating = {}
|
||||
# company
|
||||
td = tds[0]
|
||||
company = td.find("div", {"class": "title-area"}).text
|
||||
ticker = td.find("div", {"class": "ticker-area"}).text
|
||||
rating["company"] = company
|
||||
rating["ticker"] = ticker
|
||||
# action
|
||||
td = tds[1]
|
||||
action = td.text
|
||||
rating["action"] = action
|
||||
# brokerage
|
||||
td = tds[2]
|
||||
brokerage = td.find("a").text
|
||||
rating["brokerage"] = brokerage
|
||||
# current price
|
||||
td = tds[3]
|
||||
if td.find("span"):
|
||||
td.span.extract()
|
||||
analyst = td.text
|
||||
rating["analyst"] = analyst
|
||||
# target price
|
||||
td = tds[4]
|
||||
current_price = td.text
|
||||
rating["current_price"] = current_price
|
||||
# new rating
|
||||
td = tds[5]
|
||||
target_price = td.text
|
||||
rating["target_price"] = target_price
|
||||
# impact on price
|
||||
td = tds[6]
|
||||
if td.find("a"):
|
||||
rate = td.find("a").text
|
||||
else:
|
||||
rate = td.text
|
||||
rating["rate"] = rate
|
||||
ratings.append(rating)
|
||||
|
||||
return ratings
|
||||
@@ -1,127 +0,0 @@
|
||||
""" MarketBeat View """
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import argparse
|
||||
from typing import List
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from gamestonk_terminal.helper_funcs import (
|
||||
check_positive,
|
||||
parse_known_args_and_warn,
|
||||
)
|
||||
from gamestonk_terminal.stocks.discovery import marketbeat_model
|
||||
|
||||
|
||||
def ratings_view(other_args: List[str]):
|
||||
"""Prints top ratings updates [Source: MarketBeat]
|
||||
|
||||
MarketBeat has changed the access to their data. Now, a user needs to have 'MarketBeat All Access'
|
||||
to make the most out of this command.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
other_args : List[str]
|
||||
argparse other args - ["-t", "100"]
|
||||
"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="ratings",
|
||||
description="""Top ratings updates. MarketBeat has changed the access to their data.
|
||||
Now, a user needs to have 'MarketBeat All Access' to make the most out of this command.
|
||||
[Source: MarketBeat]""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--threshold",
|
||||
action="store",
|
||||
dest="n_threshold",
|
||||
type=check_positive,
|
||||
default=0, # Change to 0 because of the preview shown by MarketBeat
|
||||
help="Minimum threshold in percentage change between current and target price to show ratings",
|
||||
)
|
||||
|
||||
if other_args:
|
||||
if "-" not in other_args[0]:
|
||||
other_args.insert(0, "-t")
|
||||
|
||||
ns_parser = parse_known_args_and_warn(parser, other_args)
|
||||
if not ns_parser:
|
||||
return
|
||||
|
||||
ratings = marketbeat_model.get_ratings()
|
||||
|
||||
df_ratings = pd.DataFrame(ratings)
|
||||
|
||||
df_ratings = df_ratings[df_ratings["target_price"] != ""]
|
||||
df_ratings["old_target"] = (
|
||||
df_ratings["target_price"]
|
||||
.apply(lambda x: x.split(" ➝ ")[0].replace("$", "") if "➝" in x else "")
|
||||
.astype(float)
|
||||
)
|
||||
df_ratings["new_target"] = (
|
||||
df_ratings["target_price"]
|
||||
.apply(lambda x: x.split(" ➝ ")[1].replace("$", "") if "➝" in x else x)
|
||||
.astype(float)
|
||||
)
|
||||
|
||||
df_ratings["clean_current_price"] = (
|
||||
df_ratings["current_price"]
|
||||
.apply(lambda x: x.replace("0.0%", "").replace("+", "").replace("$", ""))
|
||||
.astype(float)
|
||||
)
|
||||
|
||||
df_ratings.drop(columns=["analyst", "current_price", "target_price"], inplace=True)
|
||||
|
||||
df_ratings["pct_increase"] = round(
|
||||
100
|
||||
* (df_ratings["new_target"] - df_ratings["clean_current_price"])
|
||||
/ df_ratings["clean_current_price"],
|
||||
2,
|
||||
)
|
||||
|
||||
df_ratings = df_ratings.sort_values(by=["pct_increase"], ascending=False)
|
||||
|
||||
df_ratings["pct_abs"] = np.abs(df_ratings["pct_increase"])
|
||||
|
||||
df_ratings_top = df_ratings[df_ratings["pct_abs"] > ns_parser.n_threshold][
|
||||
[
|
||||
"ticker",
|
||||
"action",
|
||||
"brokerage",
|
||||
"rate",
|
||||
"old_target",
|
||||
"new_target",
|
||||
"clean_current_price",
|
||||
"pct_increase",
|
||||
]
|
||||
]
|
||||
|
||||
df_ratings_top["old_target"] = df_ratings_top["old_target"].apply(
|
||||
lambda x: str(x) + " $"
|
||||
)
|
||||
|
||||
df_ratings_top["new_target"] = df_ratings_top["new_target"].apply(
|
||||
lambda x: str(x) + " $"
|
||||
)
|
||||
|
||||
df_ratings_top["clean_current_price"] = df_ratings_top["clean_current_price"].apply(
|
||||
lambda x: str(x) + " $"
|
||||
)
|
||||
|
||||
df_ratings_top["pct_increase"] = df_ratings_top["pct_increase"].apply(
|
||||
lambda x: str(x) + " %"
|
||||
)
|
||||
|
||||
df_ratings_top = df_ratings_top.rename(
|
||||
columns={
|
||||
"old_target": "Old Target",
|
||||
"new_target": "New Target",
|
||||
"clean_current_price": "Current Price",
|
||||
"pct_increase": "Increase",
|
||||
}
|
||||
)
|
||||
|
||||
print(df_ratings_top.to_string(index=False))
|
||||
print("")
|
||||
@@ -2,7 +2,6 @@
|
||||
__docformat__ = "numpy"
|
||||
|
||||
from typing import List, Dict
|
||||
from datetime import datetime
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
import pandas as pd
|
||||
@@ -90,59 +89,6 @@ def get_articles_html(url_articles: str) -> str:
|
||||
return articles_html
|
||||
|
||||
|
||||
def get_article_list(start_date: datetime, num: int) -> List[dict]:
|
||||
"""Returns a list of latest articles
|
||||
|
||||
Parameters
|
||||
----------
|
||||
start_date : datetime
|
||||
Starting date
|
||||
num : int
|
||||
Number of articles
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
Latest articles list
|
||||
"""
|
||||
|
||||
articles: List[dict] = []
|
||||
page = 1
|
||||
url_articles = f"https://seekingalpha.com/market-news/{page}"
|
||||
while len(articles) < num:
|
||||
text_soup_articles = BeautifulSoup(
|
||||
get_articles_html(url_articles),
|
||||
"lxml",
|
||||
)
|
||||
|
||||
for item_row in text_soup_articles.findAll("li", {"class": "item"}):
|
||||
item = item_row.find("a", {"class": "add-source-assigned"})
|
||||
if item is None:
|
||||
continue
|
||||
article_url = item["href"]
|
||||
if not article_url.startswith("/news/"):
|
||||
continue
|
||||
article_id = article_url.split("/")[2].split("-")[0]
|
||||
article_date = datetime.strptime(
|
||||
item_row["data-last-date"], "%Y-%m-%d %H:%M:%S %z"
|
||||
)
|
||||
if start_date.date() < article_date.date():
|
||||
continue
|
||||
articles.append(
|
||||
{
|
||||
"title": item.text,
|
||||
"publishedAt": article_date.strftime("%Y-%m-%d %H:%M:%S"),
|
||||
"url": "https://seekingalpha.com" + article_url,
|
||||
"id": article_id,
|
||||
}
|
||||
)
|
||||
|
||||
page += 1
|
||||
url_articles = f"https://seekingalpha.com/market-news/{page}"
|
||||
|
||||
return articles
|
||||
|
||||
|
||||
def get_trending_list(num: int) -> list:
|
||||
"""Returns a list of trending articles
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ __docformat__ = "numpy"
|
||||
|
||||
from typing import List
|
||||
import os
|
||||
from datetime import datetime
|
||||
from tabulate import tabulate
|
||||
import pandas as pd
|
||||
from gamestonk_terminal.helper_funcs import export_data
|
||||
@@ -78,30 +77,22 @@ def upcoming_earning_release_dates(num_pages: int, num_earnings: int, export: st
|
||||
)
|
||||
|
||||
|
||||
def news(news_type: str, article_id: int, num: int, start_date: datetime, export: str):
|
||||
def news(article_id: int, num: int, export: str):
|
||||
"""Prints the latest news article list. [Source: Seeking Alpha]
|
||||
|
||||
Parameters
|
||||
----------
|
||||
news_type: str
|
||||
Select between 'latest' or 'trending'
|
||||
article_id: int
|
||||
Article ID. If -1, none is selected
|
||||
num: int
|
||||
Number of articles to display. Only used if article_id is -1.
|
||||
start_date : datetime
|
||||
Date from when to get articles dates. Only used if article_id is -1.
|
||||
|
||||
export : str
|
||||
Export dataframe data to csv,json,xlsx file
|
||||
"""
|
||||
# User wants to see all latest news
|
||||
if article_id == -1:
|
||||
if news_type == "latest":
|
||||
articles = seeking_alpha_model.get_article_list(start_date, num)
|
||||
elif news_type == "trending":
|
||||
articles = seeking_alpha_model.get_trending_list(num)
|
||||
else:
|
||||
print("Wrong type of news selected", "\n")
|
||||
articles = seeking_alpha_model.get_trending_list(num)
|
||||
|
||||
if export:
|
||||
df_articles = pd.DataFrame(articles)
|
||||
@@ -122,12 +113,7 @@ def news(news_type: str, article_id: int, num: int, start_date: datetime, export
|
||||
|
||||
# User wants to access specific article
|
||||
else:
|
||||
if news_type == "latest":
|
||||
article = seeking_alpha_model.get_article_data(article_id)
|
||||
elif news_type == "trending":
|
||||
article = seeking_alpha_model.get_article_data(article_id)
|
||||
else:
|
||||
print("Wrong type of news selected", "\n")
|
||||
article = seeking_alpha_model.get_article_data(article_id)
|
||||
|
||||
if export:
|
||||
df_articles = pd.DataFrame(article)
|
||||
@@ -147,7 +133,7 @@ def news(news_type: str, article_id: int, num: int, start_date: datetime, export
|
||||
export_data(
|
||||
export,
|
||||
os.path.dirname(os.path.abspath(__file__)),
|
||||
news_type,
|
||||
"trending",
|
||||
df_articles,
|
||||
)
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
# IMPORTATION STANDARD
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
@@ -248,14 +247,11 @@ def test_call_quit():
|
||||
[
|
||||
"--id=123",
|
||||
"--num=5",
|
||||
"--date=2020-12-02",
|
||||
"--export=csv",
|
||||
],
|
||||
{
|
||||
"news_type": "trending",
|
||||
"article_id": 123,
|
||||
"num": 5,
|
||||
"start_date": datetime.strptime("2020-12-02", "%Y-%m-%d"),
|
||||
"export": "csv",
|
||||
},
|
||||
),
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
# IMPORTATION STANDARD
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
|
||||
# IMPORTATION INTERNAL
|
||||
from gamestonk_terminal.stocks.discovery import marketbeat_model
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vcr_config():
|
||||
return {
|
||||
"filter_headers": [("User-Agent", None)],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_get_ratings(recorder):
|
||||
ratings = marketbeat_model.get_ratings()
|
||||
|
||||
recorder.capture(ratings)
|
||||
@@ -1,21 +0,0 @@
|
||||
# IMPORTATION STANDARD
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
|
||||
# IMPORTATION INTERNAL
|
||||
from gamestonk_terminal.stocks.discovery import marketbeat_view
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vcr_config():
|
||||
return {
|
||||
"filter_headers": [("User-Agent", None)],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.skip("Broken + unused ?")
|
||||
@pytest.mark.vcr
|
||||
@pytest.mark.record_stdout
|
||||
def test_ratings_view():
|
||||
marketbeat_view.ratings_view(other_args=[])
|
||||
@@ -1,5 +1,4 @@
|
||||
# IMPORTATION STANDARD
|
||||
from datetime import datetime
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
@@ -21,13 +20,6 @@ def test_get_next_earnings(recorder):
|
||||
recorder.capture(df_earnings)
|
||||
|
||||
|
||||
@pytest.mark.skip("Broken ?")
|
||||
@pytest.mark.vcr
|
||||
def test_get_article_list():
|
||||
start_date = datetime.strptime("2020-12-10", "%Y-%m-%d")
|
||||
seeking_alpha_model.get_article_list(start_date=start_date, num=2)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
def test_get_trending_list(recorder):
|
||||
trending_list = seeking_alpha_model.get_trending_list(num=2)
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
# IMPORTATION STANDARD
|
||||
from datetime import datetime
|
||||
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
@@ -29,10 +28,8 @@ def test_upcoming_earning_release_dates():
|
||||
@pytest.mark.record_stdout
|
||||
def test_news():
|
||||
seeking_alpha_view.news(
|
||||
news_type="trending",
|
||||
article_id=-1,
|
||||
num=2,
|
||||
start_date=datetime.strptime("2020-12-10", "%Y-%m-%d"),
|
||||
export="",
|
||||
)
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
No recent congress trading data found
|
||||
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
No recent congress trading data found
|
||||
|
||||
|
||||
Reference in New Issue
Block a user