Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new premium source End of Day Historical Data #2019

Merged
merged 33 commits into from
Aug 31, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
56d2111
Add new premium source https://eodhistoricaldata.com/r/?ref=869U7F4J
pauljsymonds Jun 29, 2022
566347e
Merge branch 'OpenBB-finance:main' into main
pauljsymonds Jun 29, 2022
5ced239
Added eod dependency to requirements.txt
pauljsymonds Jun 29, 2022
f2a12f9
Added eod dependency to requirements.txt via poetry and fixed typo
pauljsymonds Jun 30, 2022
24a240b
Merge branch 'main' into main
colin99d Jun 30, 2022
2561955
fixed some display bugs for stock info
pauljsymonds Jul 1, 2022
91c7555
Merge branch 'main' into main
colin99d Jul 1, 2022
3406d66
Merge branch 'main' of github.com:pauljsymonds/OpenBBTerminal into eodhd
pauljsymonds Jul 1, 2022
ad7cc69
Implemented stock/load for eodhd, use keys / eodhd demo for key.
pauljsymonds Jul 1, 2022
032d56f
Merge branch 'main' into main
colin99d Jul 1, 2022
b6f3f6e
Commit before Pull -Implemented stock/load for eodhd, use keys / eod…
pauljsymonds Jul 1, 2022
72e41ab
Commit before Pull -Implemented stock/load for eodhd, use keys / eod…
pauljsymonds Jul 1, 2022
7831769
Added Fixes to merge conflicts
colin99d Aug 30, 2022
4be99cf
Merge branch 'OpenBB-finance:main' into main
pauljsymonds Aug 30, 2022
2c84835
Committing files so I can merge
pauljsymonds Aug 30, 2022
fb3e900
Committing files so I can merge
pauljsymonds Aug 30, 2022
554ab4a
Committing files so I can merge
pauljsymonds Aug 30, 2022
cfd436d
Committing files so I can merge
pauljsymonds Aug 30, 2022
6012d99
Committing files so I can merge
pauljsymonds Aug 30, 2022
d080635
Committing files so I can merge
pauljsymonds Aug 30, 2022
2c4f695
Committing files so I can merge
pauljsymonds Aug 30, 2022
cd4092a
Committing files so I can merge
pauljsymonds Aug 30, 2022
f1aae2f
Merge
colin99d Aug 30, 2022
c2e8012
Merge branch 'main' of https://github.com/pauljsymonds/OpenBBTerminal…
colin99d Aug 30, 2022
c50ff2d
Fixed dependencies
colin99d Aug 30, 2022
20e0e57
Committing files so I can merge
pauljsymonds Aug 30, 2022
f5ef1db
Merge branch 'main' of github.com:pauljsymonds/OpenBBTerminal into eodhd
pauljsymonds Aug 30, 2022
a8b1315
Committing Stock_Helper with pylint: disable=R091
pauljsymonds Aug 30, 2022
d5f6962
Downgraded charset normalizer
colin99d Aug 30, 2022
16fb5f9
Fixed issues with keys
colin99d Aug 30, 2022
a8bd7a4
Committing fixes to eodhd
pauljsymonds Aug 31, 2022
833f029
Committing fixes to eodhd remove eod library
pauljsymonds Aug 31, 2022
38cddc1
Merge branch 'main' into main
colin99d Aug 31, 2022
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion data_sources_default.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@
"yf",
"iex",
"av",
"polygon"
"polygon",
"eodhd"
],
"dps": {
"psi": [
Expand Down
3 changes: 3 additions & 0 deletions openbb_terminal/config_terminal.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,3 +167,6 @@

# https://academy.santiment.net/products-and-plans/create-an-api-key/
API_SANTIMENT_KEY = os.getenv("OPENBB_API_SANTIMENT_KEY") or "REPLACE_ME"

# https://eodhistoricaldata.com/r/?ref=869U7F4J
API_EODHD_TOKEN = os.getenv("OPENBB_API_EODHD_KEY") or "REPLACE_ME"
53 changes: 52 additions & 1 deletion openbb_terminal/keys_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ class KeysController(BaseController): # pylint: disable=too-many-public-methods
"ethplorer",
"smartstake",
"github",
"eodhd",
"messari",
"santiment",
]
Expand Down Expand Up @@ -755,6 +756,24 @@ def check_messari_key(self, show_output: bool = False) -> None:
if show_output:
console.print(self.key_dict["MESSARI"] + "\n")

def check_eodhd_key(self, show_output: bool = False) -> None:
"""Check End of Day Historical Data key"""
self.cfg_dict["EODHD"] = "eodhd"
if cfg.API_EODHD_TOKEN == "REPLACE_ME": # nosec
logger.info("End of Day Historical Data key not defined")
self.key_dict["EODHD"] = "not defined"
else:
try:
pyEX.Client(api_token=cfg.API_EODHD_TOKEN, version="v1")
logger.info("End of Day Historical Data key defined, test passed")
self.key_dict["EODHD"] = "defined, test passed"
except PyEXception:
logger.exception("End of Day Historical Data key defined, test failed")
self.key_dict["EODHD"] = "defined, test failed"

if show_output:
console.print(self.key_dict["EODHD"] + "\n")

def check_santiment_key(self, show_output: bool = False) -> None:
"""Check Santiment key"""
self.cfg_dict["SANTIMENT"] = "santiment"
Expand Down Expand Up @@ -816,6 +835,7 @@ def check_keys_status(self) -> None:
self.check_smartstake_key()
self.check_github_key()
self.check_messari_key()
self.check_eodhd_key()
self.check_santiment_key()

def print_help(self):
Expand Down Expand Up @@ -1693,6 +1713,7 @@ def call_coinglass(self, other_args: List[str]):
other_args.insert(0, "-k")
ns_parser = parse_simple_args(parser, other_args)
if ns_parser:
print(type(ns_parser.key))
os.environ["OPENBB_API_COINGLASS_KEY"] = ns_parser.key
dotenv.set_key(self.env_file, "OPENBB_API_COINGLASS_KEY", ns_parser.key)
cfg.API_COINGLASS_KEY = ns_parser.key
Expand Down Expand Up @@ -1832,6 +1853,35 @@ def call_messari(self, other_args: List[str]):
self.check_messari_key(show_output=True)

@log_start_end(log=logger)
def call_eodhd(self, other_args: List[str]):
"""Process eodhd command"""
parser = argparse.ArgumentParser(
add_help=False,
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
prog="eodhd",
description="Set End of Day Historical Data API key.",
)
parser.add_argument(
"-k",
"--key",
type=str,
dest="key",
help="key",
)
if not other_args:
console.print(
"For your API Key, visit: https://eodhistoricaldata.com/r/?ref=869U7F4J\n"
)
return
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-k")
ns_parser = parse_simple_args(parser, other_args)
if ns_parser:
os.environ["API_EODHD_TOKEN"] = ns_parser.key
dotenv.set_key(self.env_file, "API_EODHD_TOKEN", ns_parser.key)
cfg.API_EODHD_TOKEN = ns_parser.key
self.check_eodhd_key(show_output=True)

def call_santiment(self, other_args: List[str]):
"""Process santiment command"""
parser = argparse.ArgumentParser(
Expand All @@ -1849,7 +1899,8 @@ def call_santiment(self, other_args: List[str]):
)
if not other_args:
console.print(
"For your API Key, visit: https://academy.santiment.net/products-and-plans/create-an-api-key\n"
"For your API Key, visit: "
"https://academy.santiment.net/products-and-plans/create-an-api-key\n"
)
return
if other_args and "-" not in other_args[0][0]:
Expand Down
7 changes: 3 additions & 4 deletions openbb_terminal/parent_classes.py
Original file line number Diff line number Diff line change
Expand Up @@ -798,10 +798,7 @@ def call_load(self, other_args: List[str]):
if other_args and "-" not in other_args[0][0]:
other_args.insert(0, "-t")

ns_parser = self.parse_known_args_and_warn(
parser,
other_args,
)
ns_parser = self.parse_known_args_and_warn(parser, other_args)

if ns_parser:
if ns_parser.weekly and ns_parser.monthly:
Expand Down Expand Up @@ -864,6 +861,8 @@ def call_load(self, other_args: List[str]):

if ns_parser.source == "iex":
self.start = self.stock.index[0].to_pydatetime()
elif ns_parser.source == "eodhd":
self.start = self.stock.index[0].to_pydatetime()
else:
self.start = ns_parser.start
self.interval = f"{ns_parser.interval}min"
Expand Down
88 changes: 79 additions & 9 deletions openbb_terminal/stocks/stocks_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@
logger = logging.getLogger(__name__)

# pylint: disable=no-member,too-many-branches,C0302,R0913
# pylint: disable=R0915

INTERVALS = [1, 5, 15, 30, 60]
SOURCES = ["yf", "av", "iex"]
SOURCES = ["yf", "av", "iex", "eodhd"]

market_coverage_suffix = {
"USA": ["CBT", "CME", "NYB", "CMX", "NYM", "US", ""],
Expand Down Expand Up @@ -626,14 +627,21 @@ def load(
monthly: bool = False,
):
"""
Load a symbol to perform analysis using the string above as a template. Optional arguments and their
descriptions are listed above. The default source is, yFinance (https://pypi.org/project/yfinance/).
Alternatively, one may select either AlphaVantage (https://www.alphavantage.co/documentation/)
or IEX Cloud (https://iexcloud.io/docs/api/) as the data source for the analysis.
Please note that certain analytical features are exclusive to the source.
Load a symbol to perform analysis using the string above as a template.

Optional arguments and their descriptions are listed above.

The default source is, yFinance (https://pypi.org/project/yfinance/).
Other sources:
- AlphaVantage (https://www.alphavantage.co/documentation/)
- IEX Cloud (https://iexcloud.io/docs/api/)
- Eod Historical Data (https://eodhistoricaldata.com/financial-apis/)

Please note that certain analytical features are exclusive to the specific source.

To load a symbol from an exchange outside of the NYSE/NASDAQ default, use yFinance as the source and
add the corresponding exchange to the end of the symbol. i.e. ‘BNS.TO’.
add the corresponding exchange to the end of the symbol. i.e. ‘BNS.TO’. Note this may be possible with
other paid sources check their docs.

BNS is a dual-listed stock, there are separate options chains and order books for each listing.
Opportunities for arbitrage may arise from momentary pricing discrepancies between listings
Expand Down Expand Up @@ -749,6 +757,70 @@ def load(

df_stock_candidate.index.name = "date"

# TODO: eodhd start ###########################

# End of Day Historical Data Source
elif source == "eodhd":
df_stock_candidate = pd.DataFrame()

if weekly:
int_ = "w"
int_string = "Weekly"
elif monthly:
int_ = "m"
int_string = "Monthly"
else:
int_ = "d"
int_string = "Daily"

request_url = (
f"https://eodhistoricaldata.com/api/eod/"
f"{symbol.upper()}?"
f"{start_date.strftime('%Y-%m-%d')}&"
f"to={end_date.strftime('%Y-%m-%d')}&"
f"period={int_}&"
f"api_token={cfg.API_EODHD_TOKEN}&"
f"fmt=json&"
f"order=d"
)

r = requests.get(request_url)
if r.status_code != 200:
console.print("[red]Invalid API Key for eodhistoricaldata [/red]")
console.print(
"Get your Key here: https://eodhistoricaldata.com/r/?ref=869U7F4J\n"
)
return pd.DataFrame()

r_json = r.json()

df_stock_candidate = pd.DataFrame(r_json).dropna(axis=0)

# Check that loading a stock was not successful
if df_stock_candidate.empty:
console.print("No data found from End Of Day Historical Data.\n")
return df_stock_candidate

df_stock_candidate = df_stock_candidate[
["date", "open", "high", "low", "close", "adjusted_close", "volume"]
]

df_stock_candidate = df_stock_candidate.rename(
columns={
"date": "Date",
"close": "Close",
"high": "High",
"low": "Low",
"open": "Open",
"adjusted_close": "Adj Close",
"volume": "Volume",
}
)
df_stock_candidate["Date"] = pd.to_datetime(df_stock_candidate.Date)
df_stock_candidate.set_index("Date", inplace=True)
df_stock_candidate.sort_index(ascending=True, inplace=True)
# TODO: ###########################

# IEX Cloud Source
elif source == "iex":
df_stock_candidate = pd.DataFrame()
Expand Down Expand Up @@ -1382,12 +1454,10 @@ def find_trendline(

def additional_info_about_ticker(ticker: str) -> str:
"""Information about trading the ticker such as exchange, currency, timezone and market status

Parameters
----------
ticker : str
The stock ticker to extract if stock market is open or not

Returns
-------
str
Expand Down
Loading