mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
Reformatting
This commit is contained in:
@@ -4,7 +4,7 @@ __docformat__ = "numpy"
|
||||
import argparse
|
||||
import logging
|
||||
import os
|
||||
from datetime import datetime, timedelta, date
|
||||
from datetime import datetime, timedelta
|
||||
from typing import List, Optional
|
||||
|
||||
import yfinance as yf
|
||||
@@ -657,7 +657,7 @@ class ETFController(BaseController):
|
||||
type=valid_date,
|
||||
default=(datetime.now().date() - timedelta(days=366)),
|
||||
dest="start",
|
||||
help="The starting date (format YYYY-MM-DD) to get each holding's price"
|
||||
help="The starting date (format YYYY-MM-DD) to get each holding's price",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e",
|
||||
@@ -665,7 +665,7 @@ class ETFController(BaseController):
|
||||
type=valid_date,
|
||||
default=datetime.now().date(),
|
||||
dest="end",
|
||||
help="The ending date (format YYYY-MM-DD) to get each holding's price"
|
||||
help="The ending date (format YYYY-MM-DD) to get each holding's price",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
@@ -678,9 +678,11 @@ class ETFController(BaseController):
|
||||
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,
|
||||
ns_parser = self.parse_known_args_and_warn(
|
||||
parser,
|
||||
other_args,
|
||||
export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES,
|
||||
raw=True
|
||||
raw=True,
|
||||
)
|
||||
if ns_parser:
|
||||
if self.etf_name:
|
||||
|
||||
@@ -3,9 +3,10 @@ __docformat__ = "numpy"
|
||||
|
||||
import json
|
||||
import logging
|
||||
from typing import Dict, List
|
||||
from typing import Any, Dict, List, Union
|
||||
from urllib.error import HTTPError
|
||||
from urllib.request import urlopen
|
||||
|
||||
import pandas as pd
|
||||
|
||||
from openbb_terminal.core.session.current_user import get_current_user
|
||||
@@ -50,9 +51,12 @@ def get_etf_sector_weightings(name: str) -> Dict:
|
||||
|
||||
return data
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(['API_KEY_FINANCIALMODELINGPREP'])
|
||||
def get_stock_price_change(ticker: str, start_date: str, end_date: str) -> float:
|
||||
@check_api_key(["API_KEY_FINANCIALMODELINGPREP"])
|
||||
def get_stock_price_change(
|
||||
ticker: str, start_date: str, end_date: str
|
||||
) -> Union[None, float]:
|
||||
"""Get stock's price percent change over specified time period.
|
||||
|
||||
Parameters
|
||||
@@ -66,11 +70,13 @@ def get_stock_price_change(ticker: str, start_date: str, end_date: str) -> float
|
||||
|
||||
Returns
|
||||
-------
|
||||
float
|
||||
Union[None, float]
|
||||
Percent change of closing price over time period
|
||||
"""
|
||||
current_user = get_current_user()
|
||||
url = f'''https://financialmodelingprep.com/api/v3/historical-price-full/{ticker}?from={start_date}&to={end_date}&serietype=line&apikey={current_user.credentials.API_KEY_FINANCIALMODELINGPREP}'''
|
||||
url = f"""https://financialmodelingprep.com/api/v3/historical-price-full/{ticker}?
|
||||
from={start_date}&to={end_date}&serietype=line
|
||||
&apikey={current_user.credentials.API_KEY_FINANCIALMODELINGPREP}"""
|
||||
response = request(url)
|
||||
if response.status_code != 200 or "Error Message" in response.json():
|
||||
message = f"Error, Status Code: {response.status_code}."
|
||||
@@ -83,15 +89,16 @@ def get_stock_price_change(ticker: str, start_date: str, end_date: str) -> float
|
||||
return None
|
||||
data = response.json()
|
||||
|
||||
close_end = data['historical'][0]['close']
|
||||
close_start = data['historical'][-1]['close']
|
||||
close_end = data["historical"][0]["close"]
|
||||
close_start = data["historical"][-1]["close"]
|
||||
pct_change = 100 * (close_end - close_start) / close_start
|
||||
|
||||
return pct_change
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(['API_KEY_FINANCIALMODELINGPREP'])
|
||||
def get_etf_holdings(ticker: str) -> List[Dict[str,any]]:
|
||||
@check_api_key(["API_KEY_FINANCIALMODELINGPREP"])
|
||||
def get_etf_holdings(ticker: str) -> List[Dict[str, Any]]:
|
||||
"""This endpoint returns all stocks held by a specific ETF.
|
||||
|
||||
Parameters
|
||||
@@ -106,7 +113,8 @@ def get_etf_holdings(ticker: str) -> List[Dict[str,any]]:
|
||||
"""
|
||||
|
||||
current_user = get_current_user()
|
||||
url = f'''https://financialmodelingprep.com/api/v3/etf-holder/{ticker}?apikey={current_user.credentials.API_KEY_FINANCIALMODELINGPREP}'''
|
||||
url = f"""https://financialmodelingprep.com/api/v3/etf-holder/{ticker}?
|
||||
apikey={current_user.credentials.API_KEY_FINANCIALMODELINGPREP}"""
|
||||
response = request(url)
|
||||
if response.status_code != 200 or "Error Message" in response.json():
|
||||
message = f"Error, Status Code: {response.status_code}."
|
||||
@@ -120,9 +128,12 @@ def get_etf_holdings(ticker: str) -> List[Dict[str,any]]:
|
||||
|
||||
return response.json()
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(['API_KEY_FINANCIALMODELINGPREP'])
|
||||
def get_holdings_pct_change(ticker: str, start_date: str, end_date: str) -> pd.DataFrame:
|
||||
@check_api_key(["API_KEY_FINANCIALMODELINGPREP"])
|
||||
def get_holdings_pct_change(
|
||||
ticker: str, start_date: str, end_date: str
|
||||
) -> pd.DataFrame:
|
||||
"""Calculate percent change for each holding in ETF.
|
||||
|
||||
Parameters
|
||||
@@ -140,16 +151,21 @@ def get_holdings_pct_change(ticker: str, start_date: str, end_date: str) -> pd.D
|
||||
return pd.DataFrame()
|
||||
data_list = []
|
||||
for stock in holdings:
|
||||
if stock['asset']:
|
||||
pct_change = get_stock_price_change(ticker=stock['asset'],
|
||||
start_date=start_date, end_date=end_date)
|
||||
data_list.append({"Ticker": stock['asset'], "Name": stock["name"],
|
||||
"Percent Change": pct_change})
|
||||
if stock["asset"]:
|
||||
pct_change = get_stock_price_change(
|
||||
ticker=stock["asset"], start_date=start_date, end_date=end_date
|
||||
)
|
||||
data_list.append(
|
||||
{
|
||||
"Ticker": stock["asset"],
|
||||
"Name": stock["name"],
|
||||
"Percent Change": pct_change,
|
||||
}
|
||||
)
|
||||
else:
|
||||
data_list.append({"Ticker": '', "Name": stock["name"],
|
||||
"Percent Change": 0})
|
||||
data_list.append({"Ticker": "", "Name": stock["name"], "Percent Change": 0})
|
||||
|
||||
df = pd.DataFrame(data_list)
|
||||
df.sort_values(by='Percent Change',ascending=False, inplace=True)
|
||||
df.sort_values(by="Percent Change", ascending=False, inplace=True)
|
||||
|
||||
return df
|
||||
|
||||
@@ -10,10 +10,7 @@ import pandas as pd
|
||||
from openbb_terminal import OpenBBFigure, theme
|
||||
from openbb_terminal.decorators import check_api_key, log_start_end
|
||||
from openbb_terminal.etf import fmp_model
|
||||
from openbb_terminal.helper_funcs import (
|
||||
export_data,
|
||||
print_rich_table,
|
||||
)
|
||||
from openbb_terminal.helper_funcs import export_data, print_rich_table
|
||||
from openbb_terminal.rich_config import console
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -123,26 +120,34 @@ def display_etf_weightings(
|
||||
|
||||
|
||||
@log_start_end(log=logger)
|
||||
@check_api_key(['API_KEY_FINANCIALMODELINGPREP'])
|
||||
def view_etf_holdings_performance(ticker: str, start_date: str, end_date: str, limit: int = 10, raw: bool = False, export: str = "", sheet_name: Optional[str] = None):
|
||||
'''Display ETF's holdings' performance over specified time. [Source: FinancialModelingPrep]
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
ETF ticker
|
||||
start_date: str
|
||||
Date from which data is fetched in format YYYY-MM-DD
|
||||
end: str
|
||||
Date from which data is fetched in format YYYY-MM-DD
|
||||
limit: int
|
||||
Limit number of holdings to view. Sorted by descending percent change.
|
||||
raw: bool
|
||||
Display holding performance
|
||||
sheet_name: str
|
||||
Optionally specify the name of the sheet the data is exported to.
|
||||
export: str
|
||||
Type of format to export data
|
||||
'''
|
||||
@check_api_key(["API_KEY_FINANCIALMODELINGPREP"])
|
||||
def view_etf_holdings_performance(
|
||||
ticker: str,
|
||||
start_date: str,
|
||||
end_date: str,
|
||||
limit: int = 10,
|
||||
raw: bool = False,
|
||||
export: str = "",
|
||||
sheet_name: Optional[str] = None,
|
||||
):
|
||||
"""Display ETF's holdings' performance over specified time. [Source: FinancialModelingPrep]
|
||||
Parameters
|
||||
----------
|
||||
ticker: str
|
||||
ETF ticker
|
||||
start_date: str
|
||||
Date from which data is fetched in format YYYY-MM-DD
|
||||
end: str
|
||||
Date from which data is fetched in format YYYY-MM-DD
|
||||
limit: int
|
||||
Limit number of holdings to view. Sorted by descending percent change.
|
||||
raw: bool
|
||||
Display holding performance
|
||||
sheet_name: str
|
||||
Optionally specify the name of the sheet the data is exported to.
|
||||
export: str
|
||||
Type of format to export data
|
||||
"""
|
||||
data = fmp_model.get_holdings_pct_change(ticker, start_date, end_date)[0:limit]
|
||||
|
||||
if raw:
|
||||
@@ -158,14 +163,15 @@ def view_etf_holdings_performance(ticker: str, start_date: str, end_date: str, l
|
||||
fig = OpenBBFigure()
|
||||
|
||||
if not raw or fig.is_image_export(export):
|
||||
|
||||
fig.add_bar(
|
||||
hovertext=[f'{x:.2f}'+"%" for x in data['Percent Change']],
|
||||
x=data['Percent Change'],
|
||||
y=data['Name'],
|
||||
name = 'Stock',
|
||||
orientation='h',
|
||||
marker_color=['darkgreen' if x > 0 else 'darkred' for x in data['Percent Change']],
|
||||
hovertext=[f"{x:.2f}" + "%" for x in data["Percent Change"]],
|
||||
x=data["Percent Change"],
|
||||
y=data["Name"],
|
||||
name="Stock",
|
||||
orientation="h",
|
||||
marker_color=[
|
||||
"darkgreen" if x > 0 else "darkred" for x in data["Percent Change"]
|
||||
],
|
||||
)
|
||||
|
||||
fig.update_layout(
|
||||
@@ -185,4 +191,6 @@ def view_etf_holdings_performance(ticker: str, start_date: str, end_date: str, l
|
||||
)
|
||||
return
|
||||
|
||||
return fig.show(external= raw or export)
|
||||
fig.show(external=raw or bool(export))
|
||||
|
||||
return
|
||||
|
||||
@@ -45,50 +45,4 @@ interactions:
|
||||
status:
|
||||
code: 401
|
||||
message: Unauthorized
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- '*/*'
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://financialmodelingprep.com/api/v3/etf-holder/ARKK?apikey=MOCK_API_KEY
|
||||
response:
|
||||
body:
|
||||
string: "{\n \"Error Message\": \"Invalid API KEY. Please retry or visit our
|
||||
documentation to create one FREE https://site.financialmodelingprep.com/developer/docs\"\n}"
|
||||
headers:
|
||||
Access-Control-Allow-Credentials:
|
||||
- 'true'
|
||||
Access-Control-Allow-Headers:
|
||||
- X-Requested-With, content-type, auth-token, Authorization, stripe-signature,
|
||||
APPS
|
||||
Access-Control-Allow-Methods:
|
||||
- GET, POST, OPTIONS
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Access-Control-Max-Age:
|
||||
- '3600'
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Length:
|
||||
- '154'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Wed, 27 Sep 2023 17:43:14 GMT
|
||||
ETag:
|
||||
- W/"9a-ufKRTAmgqkT6Vv3bqU5trChBRE8"
|
||||
Server:
|
||||
- nginx/1.18.0 (Ubuntu)
|
||||
X-Frame-Options:
|
||||
- SAMEORIGIN
|
||||
X-Powered-By:
|
||||
- Express
|
||||
status:
|
||||
code: 401
|
||||
message: Unauthorized
|
||||
version: 1
|
||||
|
||||
@@ -43,7 +43,7 @@ def test_get_etf_holdings(recorder, ticker):
|
||||
assert result.count != 0
|
||||
recorder.capture(result)
|
||||
|
||||
@pytest.mark.vcr(record_mode='all')
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"ticker",
|
||||
[
|
||||
@@ -51,7 +51,7 @@ def test_get_etf_holdings(recorder, ticker):
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"start_date",
|
||||
"start_date",
|
||||
[
|
||||
"2022-09-01",
|
||||
],
|
||||
@@ -68,6 +68,7 @@ def test_get_holdings_pct_change(recorder, ticker: str, start_date: str, end_dat
|
||||
assert result.empty
|
||||
recorder.capture(result)
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
@pytest.mark.parametrize(
|
||||
"ticker",
|
||||
@@ -76,7 +77,7 @@ def test_get_holdings_pct_change(recorder, ticker: str, start_date: str, end_dat
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"start_date",
|
||||
"start_date",
|
||||
[
|
||||
"2022-09-01",
|
||||
],
|
||||
@@ -90,4 +91,4 @@ def test_get_holdings_pct_change(recorder, ticker: str, start_date: str, end_dat
|
||||
def test_get_stock_price_change(recorder, ticker: str, start_date: str, end_date: str):
|
||||
result = fmp_model.get_holdings_pct_change(ticker, start_date, end_date)
|
||||
|
||||
recorder.capture(result)
|
||||
recorder.capture(result)
|
||||
|
||||
@@ -25,6 +25,7 @@ def vcr_config():
|
||||
def test_display_etf_weightings(name):
|
||||
fmp_view.display_etf_weightings(name, raw=True, export="")
|
||||
|
||||
|
||||
@pytest.mark.vcr
|
||||
@pytest.mark.parametrize(
|
||||
"ticker",
|
||||
@@ -33,7 +34,7 @@ def test_display_etf_weightings(name):
|
||||
],
|
||||
)
|
||||
@pytest.mark.parametrize(
|
||||
"start_date",
|
||||
"start_date",
|
||||
[
|
||||
"2022-09-01",
|
||||
],
|
||||
@@ -45,4 +46,6 @@ def test_display_etf_weightings(name):
|
||||
],
|
||||
)
|
||||
def test_view_etf_holdings_performance(ticker, start_date, end_date):
|
||||
fmp_view.view_etf_holdings_performance(ticker, start_date, end_date, raw=True, export="")
|
||||
fmp_view.view_etf_holdings_performance(
|
||||
ticker, start_date, end_date, raw=True, export=""
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user