Skip to content

Commit

Permalink
Adds filings function to the Stocks menu (#3910)
Browse files Browse the repository at this point in the history
* Fix plot look when using eval and add query to choices (#3881)

* convert index to datetime and update choices

* uncomment economy integration test

* fix treasury concat bug

* fix datasets concat on duplciates

* Lock ruff version so that new lints dont break our CI (#3905)

* Lock ruff version so that new lints dont break our CI

* Bumped pre-commit ruff version

* adds filings function

* Updates test_print_help.txt

* Adds new filings function to SDK documentation.

* updates Stocks Menu screenshot to include `filings`

* updating unit testing

* requested changes

* more changes

* black

* removed a trail here that should have stayed local

* adds export flag

* correction

Co-authored-by: montezdesousa <[email protected]>
Co-authored-by: Colin Delahunty <[email protected]>
Co-authored-by: James Maslek <[email protected]>
  • Loading branch information
4 people authored Jan 19, 2023
1 parent e7185b1 commit e2bad4d
Show file tree
Hide file tree
Showing 16 changed files with 6,359 additions and 1 deletion.
1 change: 1 addition & 0 deletions openbb_terminal/miscellaneous/data_sources_default.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
{
"stocks": {
"filings": ["FinancialModelingPrep"],
"search": ["FinanceDatabase"],
"quote": ["YahooFinance"],
"tob": ["CBOE"],
Expand Down
1 change: 1 addition & 0 deletions openbb_terminal/miscellaneous/i18n/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ en:
forecast: timeseries forecasting with machine learning
portfolio: perform portfolio optimization and look at portfolio performance and attribution
dashboards: interactive dashboards using voila and jupyter notebooks
stocks/filings: the most-recent form submissions to the SEC
stocks/search: search a specific stock ticker for analysis
stocks/load: load a specific stock ticker and additional info for analysis
stocks/_ticker: Stock
Expand Down
2 changes: 2 additions & 0 deletions openbb_terminal/miscellaneous/library/trail_map.csv
Original file line number Diff line number Diff line change
Expand Up @@ -548,3 +548,5 @@ futures.search,openbb_terminal.futures.yfinance_model.get_search_futures,
futures.historical,openbb_terminal.futures.yfinance_model.get_historical_futures,openbb_terminal.futures.yfinance_view.display_historical
futures.curve,openbb_terminal.futures.yfinance_model.get_curve_futures,openbb_terminal.futures.yfinance_view.display_curve
economy.get_groups,openbb_terminal.economy.finviz_model.get_groups,
stocks.filings,openbb_terminal.stocks.fundamental_analysis.fmp_model.get_filings,openbb_terminal.stocks.fundamental_analysis.fmp_view.display_filings

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
script: test_stocks_filings.openbb
- - - - - - - - - -

stocks
filings
filings --limit 200
filings --today
filings --pages 30 --limit 30000
exit
66 changes: 66 additions & 0 deletions openbb_terminal/stocks/fundamental_analysis/fmp_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -585,3 +585,69 @@ def clean_metrics_df(data: pd.DataFrame, num: int, mask: bool = True) -> pd.Data
)

return data


@log_start_end(log=logger)
@check_api_key(["API_KEY_FINANCIALMODELINGPREP"])
def get_filings(
pages: int = 1,
) -> pd.DataFrame:
"""Get SEC Filings RSS feed, disseminated by FMP
Parameters
----------
pages: range = 1
The range of most-rececnt pages to get entries from (1000 per page; maximum of 30 pages)
Returns
-------
df: pd.DataFrame
Dataframe of results
Examples
--------
df = openbb.stocks.filings()
df = openbb.stocks.filings(pages=30)
"""

temp = []
try:
for i in range(pages):
temp.append(
pd.read_json(
"https://financialmodelingprep.com/api/v3/rss_feed?&page="
f"{i}"
"&apikey="
f"{cfg.API_KEY_FINANCIALMODELINGPREP}"
)
)
df = pd.concat(temp)
df = df.rename(
columns={
"title": "Title",
"date": "Date",
"link": "URL",
"cik": "CIK",
"form_type": "Form Type",
"ticker": "Ticker",
},
)
df_columns = ["Date", "Ticker", "CIK", "Form Type", "Title", "URL"]
df = (
pd.DataFrame(df, columns=df_columns)
.set_index(keys=["Date"])
.copy()
.sort_index(ascending=False)
)

# Invalid API Keys
except ValueError as e:
console.print(e)
df = pd.DataFrame()
# Premium feature, API plan is not authorized
except HTTPError as e:
console.print(e)
df = pd.DataFrame()

return df
74 changes: 74 additions & 0 deletions openbb_terminal/stocks/fundamental_analysis/fmp_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import logging
import os

import datetime
import matplotlib.pyplot as plt
import pandas as pd

Expand Down Expand Up @@ -525,3 +526,76 @@ def display_financial_statement_growth(
else:
logger.error("Could not get data")
console.print("[red]Could not get data[/red]\n")


@log_start_end(log=logger)
@check_api_key(["API_KEY_FINANCIALMODELINGPREP"])
def display_filings(
pages: int = 1,
limit: int = 5,
today: bool = False,
export: str = "",
) -> None:
"""Display recent forms submitted to the SEC
Parameters
----------
pages: int = 1
The range of most-rececnt pages to get entries from (1000 per page, max 30 pages)
limit: int = 5
Limit the number of entries to display (default: 5)
today: bool = False
Show all from today
export: str = ""
Export data as csv, json, or xlsx
Examples
--------
openbb.stocks.display_filings()
openbb.stocks.display_filings(today = True, export = "csv")
"""
filings = fmp_model.get_filings(pages)
if today is True:
now: str = datetime.datetime.now().strftime("%Y-%m-%d")
iso_today: int = datetime.datetime.today().isoweekday()
if iso_today < 6 and not filings.empty:
filings = filings.filter(like=now, axis=0)
limit = 1000
else:
console.print(
"[red]No filings today, displaying the most recent submissions instead[/red]"
)

if not filings.empty:
filings.reset_index(["Date"], inplace=True)
for _, row in filings.head(limit).iterrows():
console.print(
"Timestamp: ",
f"{row['Date']}",
" US/Eastern",
"\n",
"Ticker: ",
f"{row['Ticker']}",
"\n",
"CIK: " f"{row['CIK']}",
"\n",
"Form Type: ",
f"{row['Form Type']}",
"\n",
f"{row['Title']}",
"\n",
f"{row['URL']}\n",
sep="",
)
export_data(
export,
os.path.dirname(os.path.abspath(__file__)),
"filings",
filings,
)
else:
logger.error("Could not get data")
console.print("[red]Could not get data[/red]\n")
42 changes: 42 additions & 0 deletions openbb_terminal/stocks/stocks_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from openbb_terminal.custom_prompt_toolkit import NestedCompleter
from openbb_terminal.decorators import log_start_end
from openbb_terminal.stocks import cboe_view
from openbb_terminal.stocks.fundamental_analysis import fmp_view

from openbb_terminal.helper_funcs import (
EXPORT_ONLY_RAW_DATA_ALLOWED,
Expand Down Expand Up @@ -50,6 +51,7 @@ class StocksController(StockBaseController):
"news",
"resources",
"codes",
"filings",
]
CHOICES_MENUS = [
"ta",
Expand Down Expand Up @@ -109,6 +111,7 @@ def print_help(self):
stock_text += f" (from {self.start.strftime('%Y-%m-%d')})"

mt = MenuText("stocks/", 100)
mt.add_cmd("filings")
mt.add_cmd("search")
mt.add_cmd("load")
mt.add_raw("\n")
Expand Down Expand Up @@ -151,6 +154,45 @@ def custom_reset(self):
]
return []

@log_start_end(log=logger)
def call_filings(self, other_args: List[str]) -> None:
"""Process Filings command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="filings",
description="The most-recent filings submitted to the SEC",
)
parser.add_argument(
"-p",
"--pages",
dest="pages",
metavar="pages",
type=int,
default=1,
help="The number of pages to get data from (1000 entries/page; maximum 30 pages)",
)
parser.add_argument(
"-t",
"--today",
dest="today",
action="store_true",
default=False,
help="Show all filings from today",
)
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-l")
ns_parser = self.parse_known_args_and_warn(
parser,
other_args,
EXPORT_ONLY_RAW_DATA_ALLOWED,
limit=5,
)
if ns_parser:
fmp_view.display_filings(
ns_parser.pages, ns_parser.limit, ns_parser.today, ns_parser.export
)

@log_start_end(log=logger)
def call_search(self, other_args: List[str]):
"""Process search command."""
Expand Down
Loading

0 comments on commit e2bad4d

Please sign in to comment.