mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 20:42:26 +00:00
Add cramer recommendations (+ inverse :) ) (#1427)
Co-authored-by: didierlopes.eth <dro.lopes@campus.fct.unl.pt>
This commit is contained in:
80
gamestonk_terminal/stocks/discovery/cramer_model.py
Normal file
80
gamestonk_terminal/stocks/discovery/cramer_model.py
Normal file
@@ -0,0 +1,80 @@
|
||||
"""Cramer Model"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import re
|
||||
|
||||
import pandas as pd
|
||||
import requests
|
||||
import numpy as np
|
||||
import yfinance as yf
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from gamestonk_terminal.helper_funcs import get_user_agent
|
||||
|
||||
|
||||
def get_cramer_daily(inverse: bool = True) -> pd.DataFrame:
|
||||
"""Scrape the daily recommendations of Jim Cramer
|
||||
|
||||
Parameters
|
||||
----------
|
||||
inverse: bool
|
||||
Whether to include inverse
|
||||
|
||||
Returns
|
||||
-------
|
||||
pd.DataFrame
|
||||
Datafreme of daily Cramer recommendations
|
||||
"""
|
||||
cramer_link = "https://madmoney.thestreet.com/screener/index.cfm"
|
||||
r = requests.get(cramer_link, headers={"User-Agent": get_user_agent()})
|
||||
if r.status_code != 200:
|
||||
return pd.DataFrame()
|
||||
soup = BeautifulSoup(r.text, "html.parser")
|
||||
table = soup.find_all("table")[0]
|
||||
trs = table.find_all("tr")
|
||||
recs = {
|
||||
"1": "Sell",
|
||||
"2": "Sell",
|
||||
"3": "Hold",
|
||||
"4": "Buy",
|
||||
"5": "Buy",
|
||||
}
|
||||
|
||||
rec = []
|
||||
|
||||
for tr in trs[1:]:
|
||||
rec.append(recs[tr.find_all("td")[3].find("img")["src"][-5]])
|
||||
|
||||
df = pd.read_html("https://madmoney.thestreet.com/screener/index.cfm")[0]
|
||||
df["Symbol"] = df.Company.apply(lambda x: re.findall(r"[\w]+", x)[-1])
|
||||
last_price = []
|
||||
for ticker in df.Symbol:
|
||||
last_price.append(
|
||||
round(
|
||||
yf.download(ticker, period="1d", interval="1h", progress=False)[
|
||||
"Close"
|
||||
][-1],
|
||||
2,
|
||||
)
|
||||
)
|
||||
df["LastPrice"] = last_price
|
||||
df["Price"] = df.Price.apply(lambda x: float(x.strip("$")))
|
||||
df = df.drop(columns=["Segment", "Call", "Portfolio"])
|
||||
df["Change (%)"] = 100 * np.round((df["LastPrice"] - df["Price"]) / df.LastPrice, 4)
|
||||
df["Recommendation"] = rec
|
||||
df["Company"] = df.apply(lambda x: x.Company.replace(f"({x.Symbol})", ""), axis=1)
|
||||
cols = [
|
||||
"Date",
|
||||
"Company",
|
||||
"Symbol",
|
||||
"Price",
|
||||
"LastPrice",
|
||||
"Change (%)",
|
||||
"Recommendation",
|
||||
]
|
||||
if inverse:
|
||||
df["InverseCramer"] = df["Recommendation"].apply(
|
||||
lambda x: ["Buy", "Sell"][x == "Buy"]
|
||||
)
|
||||
cols.append("InverseCramer")
|
||||
return df[cols]
|
||||
29
gamestonk_terminal/stocks/discovery/cramer_view.py
Normal file
29
gamestonk_terminal/stocks/discovery/cramer_view.py
Normal file
@@ -0,0 +1,29 @@
|
||||
"""Cramer View"""
|
||||
__docformat__ = "numpy"
|
||||
|
||||
import os
|
||||
from gamestonk_terminal.helper_funcs import print_rich_table, export_data
|
||||
from gamestonk_terminal.stocks.discovery import cramer_model
|
||||
from gamestonk_terminal.rich_config import console
|
||||
|
||||
|
||||
def display_cramer_daily(inverse: bool = True, export: str = ""):
|
||||
"""
|
||||
|
||||
Parameters
|
||||
----------
|
||||
inverse:bool
|
||||
Flag to include inverse recommendation
|
||||
export:str
|
||||
Format to export data
|
||||
"""
|
||||
|
||||
recs = cramer_model.get_cramer_daily(inverse)
|
||||
if recs.empty:
|
||||
console.print("[red]Error getting request.\n[/red]")
|
||||
date = recs.Date[0]
|
||||
recs = recs.drop(columns=["Date"])
|
||||
console.print()
|
||||
print_rich_table(recs, title=f"Jim Cramer Recommendations for {date}")
|
||||
console.print()
|
||||
export_data(export, os.path.dirname(os.path.abspath(__file__)), "cramer", recs)
|
||||
@@ -23,6 +23,7 @@ from .shortinterest_view import low_float as lowfloat
|
||||
from .seeking_alpha_view import display_news as cnews
|
||||
from .shortinterest_view import hot_penny_stocks as hotpenny
|
||||
from .nasdaq_view import display_top_retail as rtat
|
||||
from .cramer_view import display_cramer_daily as cramer
|
||||
|
||||
# Models
|
||||
models = _models(os.path.abspath(os.path.dirname(__file__)))
|
||||
|
||||
@@ -30,6 +30,7 @@ from gamestonk_terminal.stocks.discovery import (
|
||||
seeking_alpha_view,
|
||||
shortinterest_view,
|
||||
yahoofinance_view,
|
||||
cramer_view,
|
||||
)
|
||||
|
||||
# pylint:disable=C0302
|
||||
@@ -60,6 +61,7 @@ class DiscoveryController(BaseController):
|
||||
"cnews",
|
||||
"rtat",
|
||||
"divcal",
|
||||
"cramer",
|
||||
]
|
||||
|
||||
arkord_sortby_choices = [
|
||||
@@ -159,7 +161,9 @@ class DiscoveryController(BaseController):
|
||||
hotpenny today's hot penny stocks
|
||||
[src][NASDAQ Data Link (Formerly Quandl)][/src]
|
||||
rtat top 10 retail traded stocks per day
|
||||
divcal dividend calendar for selected date[/cmds]
|
||||
divcal dividend calendar for selected date
|
||||
[src][Jim Cramer][/src]
|
||||
cramer Jim Cramer's daily recommendations[/cmds]
|
||||
"""
|
||||
console.print(text=help_text, menu="Stocks - Discovery")
|
||||
|
||||
@@ -883,3 +887,30 @@ class DiscoveryController(BaseController):
|
||||
nasdaq_view.display_top_retail(
|
||||
n_days=ns_parser.limit, export=ns_parser.export
|
||||
)
|
||||
|
||||
@log_start_end(log=logger)
|
||||
def call_cramer(self, other_args: List[str]):
|
||||
"""Process fds command"""
|
||||
parser = argparse.ArgumentParser(
|
||||
add_help=False,
|
||||
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
|
||||
prog="cramer",
|
||||
description="""
|
||||
Show daily cramer recommendation
|
||||
""",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i",
|
||||
"--inverse",
|
||||
default=False,
|
||||
action="store_true",
|
||||
help="Show inverse recommendation",
|
||||
dest="inverse",
|
||||
)
|
||||
|
||||
ns_parser = parse_known_args_and_warn(
|
||||
parser, other_args, export_allowed=EXPORT_ONLY_RAW_DATA_ALLOWED
|
||||
)
|
||||
|
||||
if ns_parser:
|
||||
cramer_view.display_cramer_daily(inverse=ns_parser.inverse)
|
||||
|
||||
2307
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders.yaml
vendored
Normal file
2307
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders[False].yaml
vendored
Normal file
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders[False].yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders[True].yaml
vendored
Normal file
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders[True].yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders__no_inverse.yaml
vendored
Normal file
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders__no_inverse.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders_inverse.yaml
vendored
Normal file
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_model/test_get_orders_inverse.yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_view/test_get_orders[False].yaml
vendored
Normal file
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_view/test_get_orders[False].yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_view/test_get_orders[True].yaml
vendored
Normal file
2296
tests/gamestonk_terminal/stocks/discovery/cassettes/test_cramer_view/test_get_orders[True].yaml
vendored
Normal file
File diff suppressed because it is too large
Load Diff
10
tests/gamestonk_terminal/stocks/discovery/csv/test_cramer_model/test_get_orders[False].csv
vendored
Normal file
10
tests/gamestonk_terminal/stocks/discovery/csv/test_cramer_model/test_get_orders[False].csv
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
,Date,Company,Symbol,Price,LastPrice,Change (%),Recommendation
|
||||
0,03/01,Academy Sports and Outdoo ,ASO,30.65,30.65,0.0,Buy
|
||||
1,03/01,Salesforce ,CRM,208.89,208.89,0.0,Buy
|
||||
2,03/01,Coterra Energy ,CTRA,24.36,24.36,0.0,Buy
|
||||
3,03/01,Domino's Pizza ,DPZ,432.21,432.21,0.0,Buy
|
||||
4,03/01,Nio ,NIO,21.87,21.87,0.0,Sell
|
||||
5,03/01,Origin Materials ,ORGN,5.51,5.51,0.0,Sell
|
||||
6,03/01,Rent-A-Center ,RCII,27.08,27.08,0.0,Sell
|
||||
7,03/01,B. Riley Financial ,RILY,59.07,59.07,0.0,Sell
|
||||
8,03/01,Stem ,STEM,9.33,9.33,0.0,Sell
|
||||
|
10
tests/gamestonk_terminal/stocks/discovery/csv/test_cramer_model/test_get_orders[True].csv
vendored
Normal file
10
tests/gamestonk_terminal/stocks/discovery/csv/test_cramer_model/test_get_orders[True].csv
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
,Date,Company,Symbol,Price,LastPrice,Change (%),Recommendation,InverseCramer
|
||||
0,03/01,Academy Sports and Outdoo ,ASO,30.65,30.65,0.0,Buy,Sell
|
||||
1,03/01,Salesforce ,CRM,208.89,208.89,0.0,Buy,Sell
|
||||
2,03/01,Coterra Energy ,CTRA,24.36,24.36,0.0,Buy,Sell
|
||||
3,03/01,Domino's Pizza ,DPZ,432.21,432.21,0.0,Buy,Sell
|
||||
4,03/01,Nio ,NIO,21.87,21.87,0.0,Sell,Buy
|
||||
5,03/01,Origin Materials ,ORGN,5.51,5.51,0.0,Sell,Buy
|
||||
6,03/01,Rent-A-Center ,RCII,27.08,27.08,0.0,Sell,Buy
|
||||
7,03/01,B. Riley Financial ,RILY,59.07,59.07,0.0,Sell,Buy
|
||||
8,03/01,Stem ,STEM,9.33,9.33,0.0,Sell,Buy
|
||||
|
@@ -0,0 +1,22 @@
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
|
||||
# IMPORTATION INTERNAL
|
||||
from gamestonk_terminal.stocks.discovery import cramer_model
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vcr_config():
|
||||
return {
|
||||
"filter_headers": [("User-Agent", None)],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.vcr()
|
||||
@pytest.mark.parametrize(
|
||||
"inverse",
|
||||
[True, False],
|
||||
)
|
||||
def test_get_orders(recorder, inverse):
|
||||
recommendations = cramer_model.get_cramer_daily(inverse=inverse)
|
||||
recorder.capture(recommendations)
|
||||
@@ -0,0 +1,22 @@
|
||||
# IMPORTATION THIRDPARTY
|
||||
import pytest
|
||||
|
||||
# IMPORTATION INTERNAL
|
||||
from gamestonk_terminal.stocks.discovery import cramer_view
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def vcr_config():
|
||||
return {
|
||||
"filter_headers": [("User-Agent", None)],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.vcr()
|
||||
@pytest.mark.record_stdout
|
||||
@pytest.mark.parametrize(
|
||||
"inverse",
|
||||
[True, False],
|
||||
)
|
||||
def test_get_orders(inverse):
|
||||
cramer_view.display_cramer_daily(inverse=inverse)
|
||||
12
tests/gamestonk_terminal/stocks/discovery/txt/test_cramer_view/test_get_orders[False].txt
vendored
Normal file
12
tests/gamestonk_terminal/stocks/discovery/txt/test_cramer_view/test_get_orders[False].txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
Company Symbol Price LastPrice Change (%) Recommendation
|
||||
0 Academy Sports and Outdoo ASO 30.65 30.65 0.0 Buy
|
||||
1 Salesforce CRM 208.89 208.89 0.0 Buy
|
||||
2 Coterra Energy CTRA 24.36 24.36 0.0 Buy
|
||||
3 Domino's Pizza DPZ 432.21 432.21 0.0 Buy
|
||||
4 Nio NIO 21.87 21.87 0.0 Sell
|
||||
5 Origin Materials ORGN 5.51 5.51 0.0 Sell
|
||||
6 Rent-A-Center RCII 27.08 27.08 0.0 Sell
|
||||
7 B. Riley Financial RILY 59.07 59.07 0.0 Sell
|
||||
8 Stem STEM 9.33 9.33 0.0 Sell
|
||||
|
||||
12
tests/gamestonk_terminal/stocks/discovery/txt/test_cramer_view/test_get_orders[True].txt
vendored
Normal file
12
tests/gamestonk_terminal/stocks/discovery/txt/test_cramer_view/test_get_orders[True].txt
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
Company Symbol Price LastPrice Change (%) Recommendation InverseCramer
|
||||
0 Academy Sports and Outdoo ASO 30.65 30.65 0.0 Buy Sell
|
||||
1 Salesforce CRM 208.89 208.89 0.0 Buy Sell
|
||||
2 Coterra Energy CTRA 24.36 24.36 0.0 Buy Sell
|
||||
3 Domino's Pizza DPZ 432.21 432.21 0.0 Buy Sell
|
||||
4 Nio NIO 21.87 21.87 0.0 Sell Buy
|
||||
5 Origin Materials ORGN 5.51 5.51 0.0 Sell Buy
|
||||
6 Rent-A-Center RCII 27.08 27.08 0.0 Sell Buy
|
||||
7 B. Riley Financial RILY 59.07 59.07 0.0 Sell Buy
|
||||
8 Stem STEM 9.33 9.33 0.0 Sell Buy
|
||||
|
||||
@@ -25,4 +25,6 @@
|
||||
[NASDAQ Data Link (Formerly Quandl)]
|
||||
rtat top 10 retail traded stocks per day
|
||||
divcal dividend calendar for selected date
|
||||
[Jim Cramer]
|
||||
cramer Jim Cramer's daily recommendations
|
||||
|
||||
|
||||
38
website/content/stocks/discovery/cramer/_index.md
vendored
Normal file
38
website/content/stocks/discovery/cramer/_index.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
```
|
||||
usage: cramer [-i] [-h] [--export {csv,json,xlsx}]
|
||||
```
|
||||
Show daily Cramer recommendations
|
||||
```
|
||||
optional arguments:
|
||||
-i, --inverse Show inverse recommendation (default: False)
|
||||
-h, --help show this help message (default: False)
|
||||
--export {csv,json,xlsx}
|
||||
Export raw data into csv, json, xlsx (default: )
|
||||
|
||||
```
|
||||
```
|
||||
2022 Mar 01, 21:41 (✨) /stocks/disc/ $ cramer --inverse
|
||||
|
||||
Cramer Recs for 03/01
|
||||
┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
|
||||
┃ Company ┃ Symbol ┃ Price ┃ LastPrice ┃ Change (%) ┃ Recommendation ┃ InverseCramer ┃
|
||||
┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
|
||||
│ Academy Sports and Outdoo │ ASO │ 30.65 │ 30.65 │ 0.00 │ Buy │ Sell │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Salesforce │ CRM │ 208.89 │ 208.77 │ -0.06 │ Buy │ Sell │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Coterra Energy │ CTRA │ 24.36 │ 24.37 │ 0.04 │ Buy │ Sell │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Domino's Pizza │ DPZ │ 432.21 │ 432.18 │ -0.01 │ Buy │ Sell │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Nio │ NIO │ 21.87 │ 21.88 │ 0.05 │ Sell │ Buy │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Origin Materials │ ORGN │ 5.51 │ 5.50 │ -0.18 │ Sell │ Buy │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Rent-A-Center │ RCII │ 27.08 │ 27.09 │ 0.04 │ Sell │ Buy │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ B. Riley Financial │ RILY │ 59.07 │ 59.09 │ 0.03 │ Sell │ Buy │
|
||||
├────────────────────────────┼────────┼────────┼───────────┼────────────┼────────────────┼───────────────┤
|
||||
│ Stem │ STEM │ 9.33 │ 9.32 │ -0.11 │ Sell │ Buy │
|
||||
└────────────────────────────┴────────┴────────┴───────────┴────────────┴────────────────┴───────────────┘
|
||||
```
|
||||
2
website/data/menu/main.yml
vendored
2
website/data/menu/main.yml
vendored
@@ -54,6 +54,8 @@ main:
|
||||
ref: "/stocks/discovery/rtat"
|
||||
- name: divcal
|
||||
ref: "/stocks/discovery/divcal"
|
||||
- name: cramer
|
||||
ref: "/stocks/discovery/cramer"
|
||||
- name: Sector and Industry Analysis (SIA)
|
||||
ref: "/stocks/sia"
|
||||
sub:
|
||||
|
||||
Reference in New Issue
Block a user