From b932f1cceb49bda678a3a48094f228536ebdda8a Mon Sep 17 00:00:00 2001 From: nectariosouzo Date: Wed, 27 Sep 2023 15:45:18 -0400 Subject: [PATCH] Reformatting --- openbb_terminal/etf/etf_controller.py | 12 ++-- openbb_terminal/etf/fmp_model.py | 56 +++++++++------ openbb_terminal/etf/fmp_view.py | 72 ++++++++++--------- ...ct_change[2023-09-01-2022-09-01-ARKK].yaml | 46 ------------ tests/openbb_terminal/etf/test_fmp_model.py | 9 +-- tests/openbb_terminal/etf/test_fmp_view.py | 7 +- 6 files changed, 93 insertions(+), 109 deletions(-) diff --git a/openbb_terminal/etf/etf_controller.py b/openbb_terminal/etf/etf_controller.py index 130a070aefb..792179fdb04 100644 --- a/openbb_terminal/etf/etf_controller.py +++ b/openbb_terminal/etf/etf_controller.py @@ -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: diff --git a/openbb_terminal/etf/fmp_model.py b/openbb_terminal/etf/fmp_model.py index 62db201957d..fa7d7fe0218 100644 --- a/openbb_terminal/etf/fmp_model.py +++ b/openbb_terminal/etf/fmp_model.py @@ -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 diff --git a/openbb_terminal/etf/fmp_view.py b/openbb_terminal/etf/fmp_view.py index 7d6e77c4edc..b875a0eb9b7 100644 --- a/openbb_terminal/etf/fmp_view.py +++ b/openbb_terminal/etf/fmp_view.py @@ -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 diff --git a/tests/openbb_terminal/etf/cassettes/test_fmp_model/test_get_holdings_pct_change[2023-09-01-2022-09-01-ARKK].yaml b/tests/openbb_terminal/etf/cassettes/test_fmp_model/test_get_holdings_pct_change[2023-09-01-2022-09-01-ARKK].yaml index 22cfe40220c..8858b828d78 100644 --- a/tests/openbb_terminal/etf/cassettes/test_fmp_model/test_get_holdings_pct_change[2023-09-01-2022-09-01-ARKK].yaml +++ b/tests/openbb_terminal/etf/cassettes/test_fmp_model/test_get_holdings_pct_change[2023-09-01-2022-09-01-ARKK].yaml @@ -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 diff --git a/tests/openbb_terminal/etf/test_fmp_model.py b/tests/openbb_terminal/etf/test_fmp_model.py index b21403dabdd..3b6ef6dd919 100644 --- a/tests/openbb_terminal/etf/test_fmp_model.py +++ b/tests/openbb_terminal/etf/test_fmp_model.py @@ -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) \ No newline at end of file + recorder.capture(result) diff --git a/tests/openbb_terminal/etf/test_fmp_view.py b/tests/openbb_terminal/etf/test_fmp_view.py index 21396ef9523..351a825f31d 100644 --- a/tests/openbb_terminal/etf/test_fmp_view.py +++ b/tests/openbb_terminal/etf/test_fmp_view.py @@ -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="") \ No newline at end of file + fmp_view.view_etf_holdings_performance( + ticker, start_date, end_date, raw=True, export="" + )