diff --git a/assets/extensions/obbject.json b/assets/extensions/obbject.json index ce70c67916b0..5c168e67db80 100644 --- a/assets/extensions/obbject.json +++ b/assets/extensions/obbject.json @@ -1,6 +1,7 @@ [ { "packageName": "openbb-charting", + "optional": true, "description": "Create custom charts from OBBject data." } ] \ No newline at end of file diff --git a/assets/extensions/provider.json b/assets/extensions/provider.json index ebc981853806..92a2cd842969 100644 --- a/assets/extensions/provider.json +++ b/assets/extensions/provider.json @@ -1,6 +1,7 @@ [ { "packageName": "openbb-alpha-vantage", + "optional": true, "reprName": "Alpha Vantage", "description": "Alpha Vantage provides realtime and historical\nfinancial market data through a set of powerful and developer-friendly data APIs\nand spreadsheets. From traditional asset classes (e.g., stocks, ETFs, mutual funds)\nto economic indicators, from foreign exchange rates to commodities,\nfrom fundamental data to technical indicators, Alpha Vantage\nis your one-stop-shop for enterprise-grade global market data delivered through\ncloud-based APIs, Excel, and Google Sheets. ", "credentials": [ @@ -14,16 +15,17 @@ }, { "packageName": "openbb-benzinga", + "optional": false, "reprName": "Benzinga", "description": "Benzinga is a financial data provider that offers an API\nfocused on information that moves the market.", "credentials": [ "benzinga_api_key" ], - "website": "https://www.benzinga.com", - "logoUrl": "https://www.benzinga.com/sites/all/themes/bz2/images/Benzinga-logo-navy.svg" + "website": "https://www.benzinga.com" }, { "packageName": "openbb-biztoc", + "optional": true, "reprName": "BizToc", "description": "BizToc uses Rapid API for its REST API.\nYou may sign up for your free account at https://rapidapi.com/thma/api/biztoc.\n\nThe Base URL for all requests is:\n\n https://biztoc.p.rapidapi.com/\n\nIf you're not a developer but would still like to use Biztoc outside of the main website,\nwe've partnered with OpenBB, allowing you to pull in BizToc's news stream in their Terminal.", "credentials": [ @@ -33,61 +35,61 @@ "API_BIZTOC_TOKEN" ], "website": "https://api.biztoc.com", - "instructions": "The BizToc API is hosted on RapidAPI. To set up, go to: https://rapidapi.com/thma/api/biztoc.\n\n![biztoc0](https://github.com/marban/OpenBBTerminal/assets/18151143/04cdd423-f65e-4ad8-ad5a-4a59b0f5ddda)\n\nIn the top right, select 'Sign Up'. After answering some questions, you will be prompted to select one of their plans.\n\n![biztoc1](https://github.com/marban/OpenBBTerminal/assets/18151143/9f3b72ea-ded7-48c5-aa33-bec5c0de8422)\n\nAfter signing up, navigate back to https://rapidapi.com/thma/api/biztoc. If you are logged in, you will see a header called X-RapidAPI-Key.\n\n![biztoc2](https://github.com/marban/OpenBBTerminal/assets/18151143/0f3b6c91-07e0-447a-90cd-a9e23522929f)", - "logoUrl": "https://c.biztoc.com/274/logo.svg" + "instructions": "The BizToc API is hosted on RapidAPI. To set up, go to: https://rapidapi.com/thma/api/biztoc.\n\n![biztoc0](https://github.com/marban/OpenBBTerminal/assets/18151143/04cdd423-f65e-4ad8-ad5a-4a59b0f5ddda)\n\nIn the top right, select 'Sign Up'. After answering some questions, you will be prompted to select one of their plans.\n\n![biztoc1](https://github.com/marban/OpenBBTerminal/assets/18151143/9f3b72ea-ded7-48c5-aa33-bec5c0de8422)\n\nAfter signing up, navigate back to https://rapidapi.com/thma/api/biztoc. If you are logged in, you will see a header called X-RapidAPI-Key.\n\n![biztoc2](https://github.com/marban/OpenBBTerminal/assets/18151143/0f3b6c91-07e0-447a-90cd-a9e23522929f)" }, { "packageName": "openbb-cboe", + "optional": true, "reprName": "Chicago Board Options Exchange (CBOE)", "description": "Cboe is the world's go-to derivatives and exchange network,\ndelivering cutting-edge trading, clearing and investment solutions to people\naround the world.", "credentials": [], - "website": "https://www.cboe.com", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Cboe_Global_Markets_Logo.svg/2880px-Cboe_Global_Markets_Logo.svg.png" + "website": "https://www.cboe.com" }, { "packageName": "openbb-ecb", + "optional": true, "reprName": "European Central Bank (ECB)", "description": "The ECB Data Portal provides access to all official ECB statistics.\nThe portal also provides options to download data and comprehensive metadata for each dataset.\nStatistical publications and dashboards offer a compilation of key data on selected topics.", "credentials": [], - "website": "https://data.ecb.europa.eu", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Logo_European_Central_Bank.svg/720px-Logo_European_Central_Bank.svg.png" + "website": "https://data.ecb.europa.eu" }, { "packageName": "openbb-econdb", + "optional": false, "reprName": "EconDB", "description": "The mission of the company is to process information in ways that\nfacilitate understanding of the economic situation at different granularity levels.\n\nThe sources of data include official statistics agencies and so-called alternative\ndata sources where we collect direct observations of the market and generate\naggregate statistics.", "credentials": [ "econdb_api_key" ], - "website": "https://econdb.com", - "logoUrl": "https://avatars.githubusercontent.com/u/21289885?v=4" + "website": "https://econdb.com" }, { "packageName": "openbb-federal-reserve", + "optional": false, "reprName": "Federal Reserve (FED)", "description": "Access data provided by the Federal Reserve System,\nthe Central Bank of the United States.", "credentials": [], - "website": "https://www.federalreserve.gov/data.htm", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Seal_of_the_United_States_Federal_Reserve_System.svg/498px-Seal_of_the_United_States_Federal_Reserve_System.svg.png" + "website": "https://www.federalreserve.gov/data.htm" }, { "packageName": "openbb-finra", + "optional": true, "reprName": "Financial Industry Regulatory Authority (FINRA)", "description": "FINRA Data provides centralized access to the abundance of data FINRA\nmakes available to the public, media, researchers and member firms.", "credentials": [], - "website": "https://www.finra.org/finra-data", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/FINRA_logo.svg/1024px-FINRA_logo.svg.png" + "website": "https://www.finra.org/finra-data" }, { "packageName": "openbb-finviz", + "optional": true, "reprName": "FinViz", "description": "Unofficial Finviz API - https://github.com/lit26/finvizfinance/releases", "credentials": [], - "website": "https://finviz.com", - "logoUrl": "https://finviz.com/img/logo_3_2x.png" + "website": "https://finviz.com" }, { "packageName": "openbb-fmp", + "optional": false, "reprName": "Financial Modeling Prep (FMP)", "description": "Financial Modeling Prep is a new concept that informs you about\nstock market information (news, currencies, and stock prices).", "credentials": [ @@ -97,11 +99,11 @@ "API_KEY_FINANCIALMODELINGPREP" ], "website": "https://financialmodelingprep.com", - "instructions": "Go to: https://site.financialmodelingprep.com/developer/docs\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207821920-64553d05-d461-4984-b0fe-be0368c71186.png)\n\nClick on, \"Get my API KEY here\", and sign up for a free account.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207822184-a723092e-ef42-4f87-8c55-db150f09741b.png)\n\nWith an account created, sign in and navigate to the Dashboard, which shows the assigned token. by pressing the \"Dashboard\" button which will show the API key.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207823170-dd8191db-e125-44e5-b4f3-2df0e115c91d.png)", - "logoUrl": "https://intelligence.financialmodelingprep.com//images/fmp-brain-original.svg" + "instructions": "Go to: https://site.financialmodelingprep.com/developer/docs\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207821920-64553d05-d461-4984-b0fe-be0368c71186.png)\n\nClick on, \"Get my API KEY here\", and sign up for a free account.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207822184-a723092e-ef42-4f87-8c55-db150f09741b.png)\n\nWith an account created, sign in and navigate to the Dashboard, which shows the assigned token. by pressing the \"Dashboard\" button which will show the API key.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207823170-dd8191db-e125-44e5-b4f3-2df0e115c91d.png)" }, { "packageName": "openbb-fred", + "optional": false, "reprName": "Federal Reserve Economic Data | St. Louis FED (FRED)", "description": "Federal Reserve Economic Data is a database maintained by the\nResearch division of the Federal Reserve Bank of St. Louis that has more than\n816,000 economic time series from various sources.", "credentials": [ @@ -111,19 +113,19 @@ "API_FRED_KEY" ], "website": "https://fred.stlouisfed.org", - "instructions": "Go to: https://fred.stlouisfed.org\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827137-d143ba4c-72cb-467d-a7f4-5cc27c597aec.png)\n\nClick on, \"My Account\", create a new account or sign in with Google:\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827011-65cdd501-27e3-436f-bd9d-b0d8381d46a7.png)\n\nAfter completing the sign-up, go to \"My Account\", and select \"API Keys\". Then, click on, \"Request API Key\".\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827577-c869f989-4ef4-4949-ab57-6f3931f2ae9d.png)\n\nFill in the box for information about the use-case for FRED, and by clicking, \"Request API key\", at the bottom of the page, the API key will be issued.\n\n![FRED](https://user-images.githubusercontent.com/46355364/207828032-0a32d3b8-1378-4db2-9064-aa1eb2111632.png)", - "logoUrl": "https://fred.stlouisfed.org/images/fred-logo-2x.png" + "instructions": "Go to: https://fred.stlouisfed.org\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827137-d143ba4c-72cb-467d-a7f4-5cc27c597aec.png)\n\nClick on, \"My Account\", create a new account or sign in with Google:\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827011-65cdd501-27e3-436f-bd9d-b0d8381d46a7.png)\n\nAfter completing the sign-up, go to \"My Account\", and select \"API Keys\". Then, click on, \"Request API Key\".\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827577-c869f989-4ef4-4949-ab57-6f3931f2ae9d.png)\n\nFill in the box for information about the use-case for FRED, and by clicking, \"Request API key\", at the bottom of the page, the API key will be issued.\n\n![FRED](https://user-images.githubusercontent.com/46355364/207828032-0a32d3b8-1378-4db2-9064-aa1eb2111632.png)" }, { "packageName": "openbb-government-us", + "optional": true, "reprName": "Data.gov | United States Government", "description": "Data.gov is the United States government's open data website.\nIt provides access to datasets published by agencies across the federal government.\nData.gov is intended to provide access to government open data to the public, achieve\nagency missions, drive innovation, fuel economic activity, and uphold the ideals of\nan open and transparent government.", "credentials": [], - "website": "https://data.gov", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/0/06/Muq55HrN_400x400.png" + "website": "https://data.gov" }, { "packageName": "openbb-intrinio", + "optional": false, "reprName": "Intrinio", "description": "Intrinio is a financial data platform that provides real-time and\nhistorical financial market data to businesses and developers through an API.", "credentials": [ @@ -133,11 +135,11 @@ "API_INTRINIO_KEY" ], "website": "https://intrinio.com", - "instructions": "Go to: https://intrinio.com/starter-plan\n\n![Intrinio](https://user-images.githubusercontent.com/85772166/219207556-fcfee614-59f1-46ae-bff4-c63dd2f6991d.png)\n\nAn API key will be issued with a subscription. Find the token value within the account dashboard.", - "logoUrl": "https://assets-global.website-files.com/617960145ff34fe4a9fe7240/617960145ff34f9a97fe72c8_Intrinio%20Logo%20-%20Dark.svg" + "instructions": "Go to: https://intrinio.com/starter-plan\n\n![Intrinio](https://user-images.githubusercontent.com/85772166/219207556-fcfee614-59f1-46ae-bff4-c63dd2f6991d.png)\n\nAn API key will be issued with a subscription. Find the token value within the account dashboard." }, { "packageName": "openbb-nasdaq", + "optional": true, "reprName": "NASDAQ", "description": "Positioned at the nexus of technology and the capital markets, Nasdaq\nprovides premier platforms and services for global capital markets and beyond with\nunmatched technology, insights and markets expertise.", "credentials": [ @@ -147,19 +149,19 @@ "API_KEY_QUANDL" ], "website": "https://data.nasdaq.com", - "instructions": "Go to: https://www.quandl.com\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207823899-208a3952-f557-4b73-aee6-64ac00faedb7.png)\n\nClick on, \"Sign Up\", and register a new account.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824214-4b6b2b74-e709-4ed4-adf2-14803e6f3568.png)\n\nFollow the sign-up instructions, and upon completion the API key will be assigned.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824664-3c82befb-9c69-42df-8a82-510d85c19a97.png)", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/NASDAQ_logo.svg/1600px-NASDAQ_logo.svg.png" + "instructions": "Go to: https://www.quandl.com\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207823899-208a3952-f557-4b73-aee6-64ac00faedb7.png)\n\nClick on, \"Sign Up\", and register a new account.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824214-4b6b2b74-e709-4ed4-adf2-14803e6f3568.png)\n\nFollow the sign-up instructions, and upon completion the API key will be assigned.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824664-3c82befb-9c69-42df-8a82-510d85c19a97.png)" }, { "packageName": "openbb-oecd", + "optional": false, "reprName": "Organization for Economic Co-operation and Development (OECD)", "description": "OECD.Stat includes data and metadata for OECD countries and selected\nnon-member economies.", "credentials": [], - "website": "https://stats.oecd.org", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/OECD_logo.svg/400px-OECD_logo.svg.png" + "website": "https://stats.oecd.org" }, { "packageName": "openbb-polygon", + "optional": false, "reprName": "Polygon.io", "description": "The Polygon.io Stocks API provides REST endpoints that let you query\nthe latest market data from all US stock exchanges. You can also find data on\ncompany financials, stock market holidays, corporate actions, and more.", "credentials": [ @@ -169,53 +171,53 @@ "API_POLYGON_KEY" ], "website": "https://polygon.io", - "instructions": "Go to: https://polygon.io\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825623-fcd7f0a3-131a-4294-808c-754c13e38e2a.png)\n\nClick on, \"Get your Free API Key\".\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825952-ca5540ec-6ed2-4cef-a0ed-bb50b813932c.png)\n\nAfter signing up, the API Key is found at the bottom of the account dashboard page.\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207826258-b1f318fa-fd9c-41d9-bf5c-fe16722e6601.png)", - "logoUrl": "https://polygon.io/_next/image?url=%2Flogo.svg&w=640&q=75" + "instructions": "Go to: https://polygon.io\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825623-fcd7f0a3-131a-4294-808c-754c13e38e2a.png)\n\nClick on, \"Get your Free API Key\".\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825952-ca5540ec-6ed2-4cef-a0ed-bb50b813932c.png)\n\nAfter signing up, the API Key is found at the bottom of the account dashboard page.\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207826258-b1f318fa-fd9c-41d9-bf5c-fe16722e6601.png)" }, { "packageName": "openbb-sec", + "optional": false, "reprName": "Securities and Exchange Commission (SEC)", "description": "SEC is the public listings regulatory body for the United States.", "credentials": [], - "website": "https://www.sec.gov/data", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Seal_of_the_United_States_Securities_and_Exchange_Commission.svg/1920px-Seal_of_the_United_States_Securities_and_Exchange_Commission.svg.png" + "website": "https://www.sec.gov/data" }, { "packageName": "openbb-seeking-alpha", + "optional": true, "reprName": "Seeking Alpha", "description": "Seeking Alpha is a data provider with access to news, analysis, and\nreal-time alerts on stocks.", "credentials": [], - "website": "https://seekingalpha.com", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Seeking_Alpha_Logo.svg/280px-Seeking_Alpha_Logo.svg.png" + "website": "https://seekingalpha.com" }, { "packageName": "openbb-stockgrid", + "optional": true, "reprName": "Stockgrid", "description": "Stockgrid gives you a detailed view of what smart money is doing.\nGet in depth data about large option blocks being traded, including\nthe sentiment score, size, volume and order type. Stop guessing and\nbuild a strategy around the number 1 factor moving the market: money.", "credentials": [], - "website": "https://www.stockgrid.io", - "logoUrl": "https://www.stockgrid.io/img/logo_white2.41ee5250.svg" + "website": "https://www.stockgrid.io" }, { "packageName": "openbb-tiingo", + "optional": false, "reprName": "Tiingo", "description": "A Reliable, Enterprise-Grade Financial Markets API. Tiingo's APIs\npower hedge funds, tech companies, and individuals.", "credentials": [ "tiingo_token" ], - "website": "https://tiingo.com", - "logoUrl": "https://www.tiingo.com/dist/images/tiingo/logos/tiingo_full_light_color.svg" + "website": "https://tiingo.com" }, { "packageName": "openbb-tmx", + "optional": true, "reprName": "TMX", "description": "Unofficial TMX Data Provider Extension\n TMX Group Companies\n - Toronto Stock Exchange\n - TSX Venture Exchange\n - TSX Trust\n - Montr\u00e9al Exchange\n - TSX Alpha Exchange\n - Shorcan\n - CDCC\n - CDS\n - TMX Datalinx\n - Trayport\n ", "credentials": [], - "website": "https://www.tmx.com", - "logoUrl": "https://www.tmx.com/assets/application/img/tmx_logo_en.1593799726.svg" + "website": "https://www.tmx.com" }, { "packageName": "openbb-tradier", + "optional": true, "reprName": "Tradier", "description": "Tradier provides a full range of services in a scalable, secure,\nand easy-to-use REST-based API for businesses and individual developers.\nFast, secure, simple. Start in minutes.\nGet access to trading, account management, and market-data for\nTradier Brokerage accounts through our APIs.", "credentials": [ @@ -226,33 +228,32 @@ "API_TRADIER_TOKEN" ], "website": "https://tradier.com", - "instructions": "Go to: https://documentation.tradier.com\n\n![Tradier](https://user-images.githubusercontent.com/46355364/207829178-a8bba770-f2ea-4480-b28e-efd81cf30980.png)\n\nClick on, \"Open Account\", to start the sign-up process. After the account has been setup, navigate to [Tradier Broker Dash](https://dash.tradier.com/login?redirect=settings.api) and create the application. Request a sandbox access token.", - "logoUrl": "https://tradier.com/assets/images/tradier-logo.svg" + "instructions": "Go to: https://documentation.tradier.com\n\n![Tradier](https://user-images.githubusercontent.com/46355364/207829178-a8bba770-f2ea-4480-b28e-efd81cf30980.png)\n\nClick on, \"Open Account\", to start the sign-up process. After the account has been setup, navigate to [Tradier Broker Dash](https://dash.tradier.com/login?redirect=settings.api) and create the application. Request a sandbox access token." }, { "packageName": "openbb-tradingeconomics", + "optional": false, "reprName": "Trading Economics", "description": "Trading Economics provides its users with accurate information for\n196 countries including historical data and forecasts for more than 20 million economic\nindicators, exchange rates, stock market indexes, government bond yields and commodity\nprices. Our data for economic indicators is based on official sources, not third party\ndata providers, and our facts are regularly checked for inconsistencies.\nTrading Economics has received nearly 2 billion page views from all around the\nworld.", "credentials": [ "tradingeconomics_api_key" ], - "website": "https://tradingeconomics.com", - "logoUrl": "https://developer.tradingeconomics.com/Content/Images/logo.svg" + "website": "https://tradingeconomics.com" }, { "packageName": "openbb-wsj", + "optional": true, "reprName": "Wall Street Journal (WSJ)", "description": "WSJ (Wall Street Journal) is a business-focused, English-language\ninternational daily newspaper based in New York City. The Journal is published six\ndays a week by Dow Jones & Company, a division of News Corp, along with its Asian\nand European editions. The newspaper is published in the broadsheet format and\nonline. The Journal has been printed continuously since its inception on\nJuly 8, 1889, by Charles Dow, Edward Jones, and Charles Bergstresser.\nThe WSJ is the largest newspaper in the United States, by circulation.\n ", "credentials": [], - "website": "https://www.wsj.com", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/WSJ_Logo.svg/1594px-WSJ_Logo.svg.png" + "website": "https://www.wsj.com" }, { "packageName": "openbb-yfinance", + "optional": false, "reprName": "Yahoo Finance", "description": "Yahoo! Finance is a web-based platform that offers financial news,\ndata, and tools for investors and individuals interested in tracking and analyzing\nfinancial markets and assets.", "credentials": [], - "website": "https://finance.yahoo.com", - "logoUrl": "https://upload.wikimedia.org/wikipedia/commons/8/8f/Yahoo%21_Finance_logo_2021.png" + "website": "https://finance.yahoo.com" } ] \ No newline at end of file diff --git a/assets/extensions/router.json b/assets/extensions/router.json index 2f88caa82cf8..2c1fb008cac2 100644 --- a/assets/extensions/router.json +++ b/assets/extensions/router.json @@ -1,58 +1,72 @@ [ { "packageName": "openbb-commodity", + "optional": false, "description": "Commodity market data." }, { "packageName": "openbb-crypto", + "optional": false, "description": "Cryptocurrency market data." }, { "packageName": "openbb-currency", + "optional": false, "description": "Foreign exchange (FX) market data." }, { "packageName": "openbb-derivatives", + "optional": false, "description": "Derivatives market data." }, { "packageName": "openbb-econometrics", + "optional": true, "description": "Econometrics analysis tools." }, { "packageName": "openbb-economy", + "optional": false, "description": "Economic data." }, { "packageName": "openbb-equity", + "optional": false, "description": "Equity market data." }, { "packageName": "openbb-etf", + "optional": false, "description": "Exchange Traded Funds market data." }, { "packageName": "openbb-fixedincome", + "optional": false, "description": "Fixed Income market data." }, { "packageName": "openbb-index", + "optional": false, "description": "Indices data." }, { "packageName": "openbb-news", + "optional": false, "description": "Financial market news data." }, { "packageName": "openbb-quantitative", + "optional": true, "description": "Quantitative analysis tools." }, { "packageName": "openbb-regulators", + "optional": false, "description": "Financial market regulators data." }, { "packageName": "openbb-technical", + "optional": true, "description": "Technical Analysis tools." } ] \ No newline at end of file diff --git a/assets/scripts/generate_extension_data.py b/assets/scripts/generate_extension_data.py index 1949cafea4ed..55bb35d9545b 100644 --- a/assets/scripts/generate_extension_data.py +++ b/assets/scripts/generate_extension_data.py @@ -8,11 +8,12 @@ from poetry.core.pyproject.toml import PyProjectTOML THIS_DIR = Path(__file__).parent -PROVIDERS_PATH = Path(THIS_DIR, "..", "..", "openbb_platform/providers") -EXTENSIONS_PATH = Path(THIS_DIR, "..", "..", "openbb_platform/extensions") -OBBJECT_EXTENSIONS_PATH = Path( - THIS_DIR, "..", "..", "openbb_platform/obbject_extensions" -) +OPENBB_PLATFORM_PATH = Path(THIS_DIR, "..", "..", "openbb_platform") +PROVIDERS_PATH = OPENBB_PLATFORM_PATH / "providers" +EXTENSIONS_PATH = OPENBB_PLATFORM_PATH / "extensions" +OBBJECT_EXTENSIONS_PATH = OPENBB_PLATFORM_PATH / "obbject_extensions" + +OPENBB_PLATFORM_TOML = PyProjectTOML(OPENBB_PLATFORM_PATH / "pyproject.toml") def to_title(string: str) -> str: @@ -30,7 +31,7 @@ def get_packages(path: Path, plugin_key: str) -> Dict[str, Any]: poetry = pyproject.data["tool"]["poetry"] name = poetry["name"] plugin = poetry.get("plugins", {}).get(plugin_key) - packages[name] = list(plugin.values())[0] if plugin else "" + packages[name] = {"plugin": list(plugin.values())[0] if plugin else ""} return packages @@ -46,11 +47,15 @@ def to_camel(string: str): return components[0] + "".join(x.title() for x in components[1:]) -def createItem(package_name: str, obj: object, attrs: List[str]) -> Dict[str, str]: +def createItem(package_name: str, obj: object, obj_attrs: List[str]) -> Dict[str, Any]: """Create dictionary item from object attributes.""" - item = {"packageName": package_name} + pkg_spec = OPENBB_PLATFORM_TOML.data["tool"]["poetry"]["dependencies"].get( + package_name + ) + optional = pkg_spec.get("optional", False) if isinstance(pkg_spec, dict) else False + item = {"packageName": package_name, "optional": optional} item.update( - {to_camel(a): getattr(obj, a) for a in attrs if getattr(obj, a) is not None} + {to_camel(a): getattr(obj, a) for a in obj_attrs if getattr(obj, a) is not None} ) return item @@ -58,54 +63,56 @@ def createItem(package_name: str, obj: object, attrs: List[str]) -> Dict[str, st def generate_provider_extensions() -> None: """Generate providers_extensions.json.""" packages = get_packages(PROVIDERS_PATH, "openbb_provider_extension") - data: List[Dict[str, str]] = [] - attrs = [ + data: List[Dict[str, Any]] = [] + obj_attrs = [ "repr_name", "description", "credentials", "v3_credentials", "website", "instructions", - "logo_url", ] - for pkg_name, plugin in sorted(packages.items()): + for pkg_name, details in sorted(packages.items()): + plugin = details.get("plugin", "") file_obj = plugin.split(":") if len(file_obj) == 2: file, obj = file_obj[0], file_obj[1] module = import_module(file) provider_obj = getattr(module, obj) - data.append(createItem(pkg_name, provider_obj, attrs)) + data.append(createItem(pkg_name, provider_obj, obj_attrs)) write("provider", data) def generate_router_extensions() -> None: """Generate router_extensions.json.""" packages = get_packages(EXTENSIONS_PATH, "openbb_core_extension") - data: List[Dict[str, str]] = [] - attrs = ["description"] - for pkg_name, plugin in sorted(packages.items()): + data: List[Dict[str, Any]] = [] + obj_attrs = ["description"] + for pkg_name, details in sorted(packages.items()): + plugin = details.get("plugin", "") file_obj = plugin.split(":") if len(file_obj) == 2: file, obj = file_obj[0], file_obj[1] module = import_module(file) router_obj = getattr(module, obj) - data.append(createItem(pkg_name, router_obj, attrs)) + data.append(createItem(pkg_name, router_obj, obj_attrs)) write("router", data) def generate_obbject_extensions() -> None: """Generate obbject_extensions.json.""" packages = get_packages(OBBJECT_EXTENSIONS_PATH, "openbb_obbject_extension") - data: List[Dict[str, str]] = [] - attrs = ["description"] - for pkg_name, plugin in sorted(packages.items()): + data: List[Dict[str, Any]] = [] + obj_attrs = ["description"] + for pkg_name, details in sorted(packages.items()): + plugin = details.get("plugin", "") file_obj = plugin.split(":") if len(file_obj) == 2: file, obj = file_obj[0], file_obj[1] module = import_module(file) ext_obj = getattr(module, obj) - data.append(createItem(pkg_name, ext_obj, attrs)) + data.append(createItem(pkg_name, ext_obj, obj_attrs)) write("obbject", data) diff --git a/cli/CONTRIBUTING.md b/cli/CONTRIBUTING.md deleted file mode 100644 index 5a65b709b688..000000000000 --- a/cli/CONTRIBUTING.md +++ /dev/null @@ -1,1723 +0,0 @@ -# CONTRIBUTING - -First off, thanks for taking the time to contribute (or at least read the Contributing Guidelines)! πŸš€ - -The following is a set of guidelines for contributing to OpenBB Terminal. These are mostly guidelines, not rules. -Use your best judgment, and feel free to propose changes to this document in a pull request. - -- [CONTRIBUTING](#contributing) -- [BASIC](#basic) - - [Adding a new command](#adding-a-new-command) - - [Select Feature](#select-feature) - - [Model](#model) - - [Data sources](#data-sources) - - [View](#view) - - [Controller](#controller) - - [Add SDK endpoint (V3)](#add-sdk-endpoint-v3) - - [Add OpenBB Platform endpoint (V4)](#add-openbb-platform-endpoint-v4) - - [Add Unit Tests](#add-unit-tests) - - [Open a Pull Request](#open-a-pull-request) - - [Review Process](#review-process) - - [Understand Code Structure](#understand-code-structure) - - [Backend](#backend) - - [Frontend](#frontend) - - [Follow Coding Guidelines](#follow-coding-guidelines) - - [General Code Requirements](#general-code-requirements) - - [File Specific Requirements](#file-specific-requirements) - - [Coding Style](#coding-style) - - [OpenBB Style Guide](#openbb-style-guide) - - [Flags](#flags) - - [Output format](#output-format) - - [Time-related](#time-related) - - [Data selection and manipulation](#data-selection-and-manipulation) - - [Financial instrument characteristics](#financial-instrument-characteristics) - - [Naming Convention](#naming-convention) - - [Docstrings](#docstrings) - - [Linters](#linters) - - [Command names](#command-names) - - [UI and UX](#ui-and-ux) - - [External API Keys](#external-api-keys) - - [Creating API key](#creating-api-key) - - [Setting and checking API key](#setting-and-checking-api-key) -- [ADVANCED](#advanced) - - [Important functions and classes](#important-functions-and-classes) - - [Base controller class](#base-controller-class) - - [Default Data Sources](#default-data-sources) - - [Export Data](#export-data) - - [Queue and pipeline](#queue-and-pipeline) - - [Auto Completer](#auto-completer) - - [Logging](#logging) - - [Internationalization](#internationalization) - - [Settings](#settings) - - [Write Code and Commit](#write-code-and-commit) - - [Pre Commit Hooks](#pre-commit-hooks) - - [Coding](#coding) - - [Git Process](#git-process) - - [Branch Naming Conventions](#branch-naming-conventions) - - [Installers](#installers) - -# BASIC - -## Adding a new command - -Before implementing a new command we highly recommend that you go through [Understand Code Structure](#understand-code-structure) and [Follow Coding Guidelines](#follow-coding-guidelines). This will allow you to get your PR merged faster and maintain consistency in our code base. - -In the next sections we describe the process to add a new command. -We will be adding a function to get price targets from the Financial Modeling Prep API. Note that there already exists a function to get price targets from the Business Insider website, `stocks/fa/pt`, so we will be adding a new function to get price targets from the Financial Modeling Prep API, and go through adding sources. - -### Select Feature - -- Pick a feature you want to implement or a bug you want to fix from [our issues](https://github.com/OpenBB-finance/OpenBBTerminal/issues). -- Feel free to discuss what you'll be working on either directly on [the issue](https://github.com/OpenBB-finance/OpenBBTerminal/issues) or on [our Discord](https://openbb.co/discord). - - This ensures someone from the team can help you and there isn't duplicated work. - -Before writing any code, it is good to understand what the data will look like. In this case, we will be getting the price targets from the Financial Modeling Prep API, and the data will look like this: - -```json -[ - { - "symbol": "AAPL", - "publishedDate": "2023-02-03T16:19:00.000Z", - "newsURL": "https://pulse2.com/apple-stock-receives-a-195-price-target-aapl/", - "newsTitle": "Apple Stock Receives A $195 Price Target (AAPL)", - "analystName": "Cowen Cowen", - "priceTarget": 195, - "adjPriceTarget": 195, - "priceWhenPosted": 154.5, - "newsPublisher": "Pulse 2.0", - "newsBaseURL": "pulse2.com", - "analystCompany": "Cowen & Co." - } -``` - -### Model - -1. Create a file with the source of data as the name followed by `_model` if it doesn't exist. In this case, the file `openbb_terminal/stocks/fundamental_analysis/fmp_model.py` already exists, so we will add the function to that file. -2. Add the documentation header -3. Do the necessary imports to get the data -4. Define a function starting with `get_` -5. In this function: - 1. Use type hinting - 2. Write a descriptive description where at the end the source is specified. - 3. Utilize an official API, get and return the data. - -```python -""" Financial Modeling Prep Model """ -__docformat__ = "numpy" - -import logging - -import pandas as pd - -from src.current_user import get_current_user -from openbb_terminal.decorators import check_api_key, log_start_end -from openbb_terminal.helpers import request - -logger = logging.getLogger(__name__) - - -@check_api_key(["API_KEY_FINANCIALMODELINGPREP"]) -def get_price_targets(cls, symbol: str) -> pd.DataFrame: - """Get price targets for a company [Source: Financial Modeling Prep] - - Parameters - ---------- - symbol : str - Symbol to get data for - - Returns - ------- - pd.DataFrame - DataFrame of price targets - """ - current_user = get_current_user() - - url = f"https://financialmodelingprep.com/api/v4/price-target?symbol={symbol}&apikey={current_user.credentials.API_KEY_FINANCIALMODELINGPREP}" - response = request(url) - - # Check if the response is valid - if response.status_code != 200 or "Error Message" in response.json(): - message = f"Error, Status Code: {response.status_code}." - message = ( - message - if "Error Message" not in response.json() - else message + "\n" + response.json()["Error Message"] + ".\n" - ) - console.print(message) - return pd.DataFrame() - - return pd.DataFrame(response.json()) -``` - -In this function: - -- We import the current user object and, consequently, preferences using the `get_current_user` function. API keys are stored in `current_user.credentials` -- We use the `@log_start_end` decorator to add the function to our logs for debugging purposes. -- We add the `@check_api_key` decorator to confirm the API key is valid. -- We have type hinting and a docstring describing the function. -- We use the openbb_terminal helper function `request`, which is an abstracted version of the requests library, which allows us to add user agents, timeouts, caches, etc. to any HTTP request in the terminal. -- We check for different error messages. This will depend on the API provider and usually requires some trial and error. With the FMP API, if there is an invalid symbol, we get a response code of 200, but the json response has an error message field. Same with an invalid API key. -- When an error is caught, we still return an empty dataframe. -- We return the json response as a pandas dataframe. Most functions in the terminal should return a dataframe, but if not, make sure that the return type is specified. - -Note: - -1. If the function is applicable to many asset classes, it is possible that this file needs to be created under `common/` directory rather than `stocks/`, which means the function should be written in a generic way, i.e. not mentioning stocks or a specific context. -2. If the model requires an API key, make sure to handle the error and output relevant message. -3. If the data provider is not yet supported, you'll most likely need to do some extra steps in order to add it to the `keys` menu. See [this section](#external-api-keys) for more details. - -Some of the most common error messages are: - -- Error in the request (HTTP error) -- Invalid API Keys -- API Keys not authorized for Premium feature -- Empty return payload -- Invalid arguments (Optional) - -In the example below, you can see that we explicitly handle some of them. -It's not always possible to distinguish error types using `status_code`. So depending on the API provider, you can use either error messages or exceptions. - -```python - -@check_api_key(["API_NEWS_TOKEN"]) -def get_news( - query: str, - limit: int = 10, - start_date: Optional[str] = None, - show_newest: bool = True, - sources: str = "", -) -> pd.DataFrame: - - ... - - link += f"&apiKey={get_current_user().credentials.API_NEWS_TOKEN}" - response = request(link) - articles = {} - - if response.status_code == 200: - response_json = response.json() - articles = (response_json["articles"] if show_newest else response_json["articles"][::-1]) - - elif response.status_code == 426: - console.print(f"Error in request: {response.json()['message']}", "\n") - elif response.status_code == 401: - console.print("[red]Invalid API Key[/red]\n") - elif response.status_code == 429: - console.print("[red]Exceeded number of calls per minute[/red]\n") - else: - console.print(f"Error in request: {response.json()['message']}", "\n") - - ... -``` - -> Click [here](openbb_terminal/common/newsapi_model.py) to see the example in detail. - -### Data sources - -Now that we have added the model function getting, we need to specify that this is an available data source. To do so, we edit the `openbb_terminal/miscellaneous/sources/openbb_default.json` file. This file, described below, uses a dictionary structure to identify available sources. Since we are adding FMP to `stocks/fa/pt`, we find that entry and append it: - -```json - "fa": { - "pt": ["BusinessInsider", "FinancialModelingPrep"], -``` - -If you are adding a new function with a new data source, make a new value in the file. If the data source requires an -API key, please refer to the guide below for adding them. Instructions for obtaining the new api key -should be included in the file `OpenBBTerminal/website/content/terminal/usage/data/api-keys.md`. - -### View - -1. Create a file with the source of data as the name followed by `_view` if it doesn't exist, e.g. `fmp_view` -2. Add the documentation header -3. Do the necessary imports to display the data. One of these is the `_model` associated with this `_view`. I.e. from same data source. -4. Define a function starting with `display_` -5. In this function: - - Use typing hints - - Write a descriptive description where at the end the source is specified - - Get the data from the `_model` and parse it to be output in a more meaningful way. - - Do not degrade the main data dataframe coming from model if there's an export flag. This is so that the export can have all the data rather than the short amount of information we may show to the user. Thus, in order to do so `df_data = df.copy()` can be useful as if you change `df_data`, `df` remains intact. -6. If the source requires an API Key or some sort of tokens, add `check_api_key` decorator on that specific view. This will throw a warning if users forget to set their API Keys -7. Finally, call `export_data` where the variables are export variable, current filename, command name, and dataframe. - -```python - -@check_api_key(["API_KEY_FINANCIALMODELINGPREP"]) -def display_price_targets( - symbol: str, limit: int = 10, export: str = "", sheet_name: Optional[str] = None -): - """Display price targets for a given ticker. [Source: Financial Modeling Prep] - - Parameters - ---------- - symbol : str - Symbol - limit: int - Number of last days ratings to display - export: str - Export dataframe data to csv,json,xlsx file - sheet_name: str - Optionally specify the name of the sheet the data is exported to. - """ - columns_to_show = [ - "publishedDate", - "analystCompany", - "adjPriceTarget", - "priceWhenPosted", - ] - price_targets = fmp_model.get_price_targets(symbol) - if price_targets.empty: - console.print(f"[red]No price targets found for {symbol}[/red]\n") - return - price_targets["publishedDate"] = price_targets["publishedDate"].apply( - lambda x: datetime.strptime(x, "%Y-%m-%dT%H:%M:%S.%fZ").strftime("%Y-%m-%d %H:%M") - ) - export_data( - export, - os.path.dirname(os.path.abspath(__file__)), - "pt", - price_targets, - sheet_name, - ) - - print_rich_table( - price_targets[columns_to_show].head(limit), - headers=["Date", "Company", "Target", "Posted Price"], - show_index=False, - title=f"{symbol.upper()} Price Targets", - ) -``` - -In this function: - -- We use the same log and API decorators as in the model. -- We define the columns we want to show to the user. -- We get the data from the fmp_model function -- We check if there is data. If something went wrong, we don't want to show it, so we print a message and return. Note that because we have error messages in both the model and view, there will be two print outs. If you wish to just show one, it is better to handle in the model. -- We do some parsing of the data to make it more readable. In this case, the output from FMP is not very clear at quick glance, we we put it into something more readable. -- We export the data. In this function, I decided to export after doing the manipulation. If we do any removing of columns, we should copy the dataframe before exporting. -- We print the data in table form using our `print_rich_table`. This provides a nice console print using the rich library. Note that here I show the top `limit` rows of the dataframe. Care should be taken to make sure that things are sorted. If a sort is required, there is a `reverse` argument that can be added to sort in reverse order. - -### Controller - -Now that we have the model and views, it is time to add to the controller. - -1. Import the associated `_view` function to the controller. -2. Add command name to variable `CHOICES_COMMANDS` from `FundamentalAnalysisController` class. -3. Add command and source to `print_help()`. - - ```python - def print_help(self): - """Print help.""" - mt = MenuText("stocks/fa/") - mt.add_cmd("load") - mt.add_raw("\n") - mt.add_param("_ticker", self.ticker.upper()) - mt.add_raw("\n") - mt.add_info("_company_overview") - mt.add_cmd("mktcap") - mt.add_cmd("overview") - mt.add_cmd("divs", not self.suffix) - - ... - - mt.add_cmd("pt") - mt.add_cmd("dcf") - mt.add_cmd("dcfc") - console.print(text=mt.menu_text, menu="Stocks - Fundamental Analysis") - ``` - -4. If there is a condition to display or not the command, this is something that can be leveraged through the `add_cmd` method, e.g. `mt.add_cmd("divs", not self.suffix)`. - -5. Add command description to file `i18n/en.yml`. Use the path and command name as key, e.g. `stocks/fa/pt` and the value as description. Please fill in other languages if this is something that you know. - -6. Add a method to `FundamentalAnalysisController` class with name: `call_` followed by command name. - - This method must start defining a parser with arguments `add_help=False` and - `formatter_class=argparse.ArgumentDefaultsHelpFormatter`. In addition `prog` must have the same name as the command, and `description` should be self-explanatory ending with a mention of the data source. - - Add parser arguments after defining parser. One important argument to add is the export capability. All commands should be able to export data. - - If there is a single or even a main argument, a block of code must be used to insert a fake argument on the list of args provided by the user. This makes the terminal usage being faster. - - ```python - if other_args and "-" not in other_args[0][0]: - other_args.insert(0, "-l") - ``` - - - Parse known args from list of arguments and values provided by the user. - - Call the function contained in a `_view.py` file with the arguments parsed by argparse. - -Note that the function self.parse_known_args_and_warn() has some additional options we can add. If the function is showing a chart, but we want the option to show raw data, we can add the `raw=True` keyword and the resulting namespace will have the `raw` attribute. -Same with limit, we can pass limit=10 to add the `-l` flag with default=10. Here we also specify the export, and whether it is data only, plots only or anything else. This function also adds the `source` attribute to the namespace. In our example, this is important because we added an additional source. - -Our new function will be: - -```python - - def call_pt(self, other_args: List[str]): - """Process pt command""" - parser = argparse.ArgumentParser( - add_help=False, - prog="pt", - description="""Prints price target from analysts. [Source: Business Insider and Financial Modeling Prep]""", - ) - parser.add_argument( - "-t", - "--ticker", - dest="ticker", - help="Ticker to analyze", - type=str, - default=None, - ) - 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, EXPORT_BOTH_RAW_DATA_AND_FIGURES, raw=True, limit=10 - ) - if ns_parser: - if ns_parser.ticker: - self.ticker = ns_parser.ticker - self.custom_load_wrapper([self.ticker]) - - if ns_parser.source == "BusinessInsider": - business_insider_view.display_price_target_from_analysts( - symbol=self.ticker, - data=self.stock, - start_date=self.start, - limit=ns_parser.limit, - raw=ns_parser.raw, - export=ns_parser.export, - sheet_name=" ".join(ns_parser.sheet_name) - if ns_parser.sheet_name - else None, - ) - elif ns_parser.source == "FinancialModelingPrep": - fmp_view.display_price_targets( - symbol=self.ticker, - limit=ns_parser.limit, - export=ns_parser.export, - sheet_name=" ".join(ns_parser.sheet_name) - if ns_parser.sheet_name - else None, - ) -``` - -Here, we make the parser, add the arguments, and then parse the arguments. In order to use the fact that we had a new source, we add the logic to access the correct view function. In this specific menu, we also allow the user to specify the symbol with -t, which is what the first block is doing. - -Note that in the `fa` submenu, we allow the function to be run by specifying a ticker, ie `pt -t AAPL`. In this submenu we do a `load` behind the scenes with the ticker selected so that other functions can be run without specifying the ticker. - -Now from the terminal, this function can be run as desired: - -```bash -2023 Mar 03, 11:37 (πŸ¦‹) /stocks/fa/ $ pt -t aapl --source FinancialModelingPrep - - AAPL Price Targets -┏━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━┳━━━━━━━━━━━━━━┓ -┃ Date ┃ Company ┃ Target ┃ Posted Price ┃ -┑━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━╇━━━━━━━━━━━━━━┩ -β”‚ 2023-02-03 16:19 β”‚ Cowen & Co. β”‚ 195.00 β”‚ 154.50 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-03 09:31 β”‚ D.A. Davidson β”‚ 173.00 β”‚ 157.09 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-03 08:30 β”‚ Rosenblatt Securities β”‚ 173.00 β”‚ 150.82 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-03 08:29 β”‚ Wedbush β”‚ 180.00 β”‚ 150.82 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-03 07:21 β”‚ Raymond James β”‚ 170.00 β”‚ 150.82 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-03 07:05 β”‚ Barclays β”‚ 145.00 β”‚ 150.82 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-03 03:08 β”‚ KeyBanc β”‚ 177.00 β”‚ 150.82 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-02 02:08 β”‚ Rosenblatt Securities β”‚ 165.00 β”‚ 145.43 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-02 02:08 β”‚ Deutsche Bank β”‚ 160.00 β”‚ 145.43 β”‚ -β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”Όβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€ -β”‚ 2023-02-02 02:08 β”‚ J.P. Morgan β”‚ 180.00 β”‚ 145.43 β”‚ -β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”΄β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ -``` - -When adding a new menu, the code looks like this: - -```python - -def call_fa(self, _): - """Process fa command""" - from openbb_terminal.stocks.fundamental_analysis.fa_controller import ( - FundamentalAnalysisController, - ) - - self.queue = self.load_class( - FundamentalAnalysisController, self.ticker, self.start, self.stock, self.queue - ) -``` - -The **import only occurs inside this menu call**, this is so that the loading time only happens here and not at the terminal startup. This is to avoid slow loading times for users that are not interested in `stocks/fa` menu. - -In addition, note the `self.load_class` which allows to not create a new `FundamentalAnalysisController` instance but re-load the previous created one. Unless the arguments `self.ticker`, `self.start` or `self.stock` have changed since. The `self.queue` list of commands is passed around as it contains the commands that the terminal must perform. - -### Add SDK endpoint (V3) - -In order to add a command to the SDK, follow these steps: - -1. If you've created a new model or view file, add the import with an alias to `openbb_terminal/core/sdk/sdk_init.py` following this structure: - - ```python - # Stocks - Fundamental Analysis - from openbb_terminal.stocks.fundamental_analysis import ( - finviz_model as stocks_fa_finviz_model, - finnhub_model as stocks_fa_finnhub_model, - finnhub_view as stocks_fa_finnhub_view, - ) - ``` - -2. Go to the `trail_map.csv` file located in `openbb_terminal/core/sdk`, which should look like this: - - ```csv - trail,model,view - stocks.fa.analyst,stocks_fa_finviz_model.get_analyst_data, - stocks.fa.rot,stocks_fa_finnhub_model.get_rating_over_time,stocks_fa_finnhub_view.rating_over_time - - ... - - ``` - - In this file, the trail represents the path to the function to be called. The model represents the import alias we gave to the `_model` file. The view represents the import alias we gave to the `_view` file. - -3. Add your new function to this structure. In the below example of the `pt` function, our trail would be `stocks.fa.pt`. - - Our naming convention is such that the data source should not be included in the trail. In this example, calling a new function `pt_fmp` would not be allowed. - For functions with multiple sources, there should be a single `pt` function that takes in the source as an argument. - In the following example, we will stick with showing how the business_insider was initially added to the sdk. - - The model is the import alias to the `_model` function that was written: - - - `stocks_fa_business_insider_model.get_price_target_from_analysts` - - The view is the import alias to the `_view` function that was written: - - - `stocks_fa_business_insider_view.display_price_target_from_analysts` - - The added line of the file should look like this: - - ```csv - stocks.fa.pt,stocks_fa_business_insider_model.get_price_target_from_analysts,stocks_fa_business_insider_view.display_price_target_from_analysts - ``` - -4. Generate the SDK files by running `python generate_sdk.py` from the root of the project. This will automatically generate the SDK `openbb_terminal/sdk.py`, corresponding `openbb_terminal/core/sdk/controllers/` and `openbb_terminal/core/sdk/models/` class files. - - To sort the `trail_map.csv` file and generate the SDK files, run the following command - - ```bash - python generate_sdk.py sort - ``` - -### Add OpenBB Platform endpoint (V4) - -Refer to the documentation [here](https://docs.openbb.co/platform/development). - -### Add Unit Tests - -This is a vital part of the contribution process. We have a set of unit tests that are run on every Pull Request. These tests are located in the `tests` folder. - -Unit tests minimize errors in code and quickly find errors when they do arise. Integration tests are standard usage examples, which are also used to identify errors. - -A thorough introduction on the usage of unit tests and integration tests in OpenBBTerminal can be found on the following page: - -[Unit Test README](tests/README.md) - -[Integration Test README](openbb_terminal/miscellaneous/integration_tests_scripts/README.MD) - -Any new features that do not contain unit tests will not be accepted. - -### Open a Pull Request - -For starters, you should ensure that your branch is up to date with the `develop` branch. To do that, one can run the following commands: - -```bash -git fetch upstream -git checkout develop -git merge upstream/develop -``` - -After that, you can create a new branch for your feature. E.g. `git checkout -b feature/AmazingFeature`. - -Once you're happy with what you have, push your branch to remote. E.g. `git push origin feature/AmazingFeature`. - -> Note that we follow gitflow naming convention, so your branch name should be prefixed with `feature/` or `hotfix/` depending on the type of work you are doing. To learn more, please refer to [Branch Naming Conventions](#branch-naming-conventions). - -A user may create a **Draft Pull Request** when there is the intention to discuss implementation with the team. - -### Review Process - -As soon as the Pull Request is opened, our repository has a specific set of github actions that will not only run -linters on the branch just pushed, but also run `pytest` on it. This allows for another layer of safety on the code developed. - -In addition, our team is known for performing `diligent` code reviews. This not only allows us to reduce the amount of iterations on that code and have it to be more future proof, but also allows the developer to learn/improve his coding skills. - -Often in the past the reviewers have suggested better coding practices, e.g. using `1_000_000` instead of `1000000` for better visibility, or suggesting a speed optimization improvement. - -## Understand Code Structure - -### Backend - -CLI :computer: β†’ `_controller.py` :robot: β†’ `_view.py` :art:     β†’      `_model.py` :brain:
-                         -                          -     -`chart=True` -                 -`chart=False` -
-                           -                           -                 - ↑ -    -`sdk.py` :factory: -   - ↑ - -| **File                           ** | **Role** | **Description** | -| :------------------------- | :------------- | :----------------------------------------------------- | -| **_controller.py** :robot: | The router/input validator | The controller file should hold the least amount of logic possible. Its role is to be a stupid (no logic) router and redirect the command correctly while checking the input with argparser. | -| **_view.py** :art: | The artist | The view file should only output or visualize the data it gets from the `_model` file! The `_view` can limit the data coming from the `_model`, otherwise the data object should be identical in the `_view` and the `_model` files. | -| **_model.py** 🧠 |The brain | The model file is where everything fun happens. The data is gathered (external APIs), processed and returned here. | -| **sdk.py** 🏭 |The SDK Factory | The SDK file is where the callable functions are created for the SDK. There is only one SDK file in the openbb_terminal folder. | - -### Frontend - -| **Item** | **Description** | **Example** | -| :----------- | :--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | :----------------------------------------------- | -| **CONTEXT** | Specific instrument _world_ to analyse. | `stocks`, `crypto`, `economy` | -| **CATEGORY** | Group of similar COMMANDS to do on the instrument
There are specialized categories, specific to each CONTEXT and there are common categories which are not specific to one CONTEXT. | `due_diligence`, `technical_analysis`, `insider` | -| **COMMAND** | Operation on one or no instrument that retrieves data in form of string, table or plot. | `rating`, `supplier`, `sentiment` | - -The following layout is expected: `///` - -If there are sub-categories, the layout will be: `////` - -**Example:** - -```text -openbb_terminal/stocks/stocks_controller.py - /stocks_helper.py - /technical_analysis/ta_controller.py - /tradingview_view.py - /tradingview_model.py - /common/technical_analysis/overlap_view.py - /overlap_model.py - /crypto/crypto_controller.py - /crypto_helper.py - /due_diligence/dd_controller.py - /binance_view.py - /binance_model.py - /technical_analysis/ta_controller.py -``` - -With: - -| **Context** | **Category** | **File** | **Description** | -| :---------- | :-------------------- | :--------------------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `stocks/` | | `stocks_controller.py` | Manages **stocks** _context_ from a user perspective, i.e. routing _commands_ and arguments to output data, or, more importantly, redirecting to the selected _category_. | -| `stocks/` | | `stocks_helper.py` | Helper to `stocks` menu. This file is meant to hold generic purpose `stocks` functionalities. | -| `stocks/` | `technical_analysis/` | `ta_controller.py` | Manages **technical_analysis** _category_ from **stocks** _context_ from a user perspective, i.e. routing _commands_ and arguments to output data. -| `stocks/` | `technical_analysis/` | `tradingview_view.py` | This file contains functions that rely on **TradingView** data. These functions represent _commands_ that belong to **technical_analysis** _category_ from **stocks** _context_. These functions are called by `ta_controller.py` using the arguments given by the user and will output either a string, table or plot. | -| `stocks/` | `technical_analysis/` | `tradingview_model.py` | This file contains functions that rely on **TradingView** data. These functions represent _commands_ that belong to **technical_analysis** _category_ from **stocks** _context_. These functions are called by `tradingview_view.py` and will return data to be processed in either a string, dictionary or dataframe format. | -| `common/` | `technical_analysis/` | `overlap_view.py` | This file contains functions that rely on **overlap** data. In this case **overlap** is not a data source, but the type of technical analysis performed. These functions represent _commands_ that belong to **technical_analysis** _category_ from **MULTIPLE** _contexts_. These functions are called by `ta_controller.py`, from **MULTIPLE** _contexts_, using the arguments given by the user and will output either a string, table or plot. Due to the fact that this file is **common** to multiple _contexts_ the functions need to be generic enough to accommodate for this. E.g. if we are providing a dataframe to these functions, we should make sure that `stocks/ta_controller.py` and `crypto/ta_controller` use the same formatting. | -| `common/` | `technical_analysis/` | `overlap_model.py` | This file contains functions that rely on **overlap** data. In this case **overlap** is not a data source, but the type of technical analysis performed. These functions represent _commands_ that belong to **technical_analysis** _category_ from **MULTIPLE** _contexts_. These functions are called by `overlap_view.py`, and will return data to be processed in either a string, dictionary or dataframe format. Due to the fact that this file is **common** to multiple _contexts_ the functions need to be generic enough to accommodate for this. E.g. if we are getting the sentiment of an instrument, we should ensure that these functions accept both a "GME" or a "BTC", for `stocks` and `crypto`, respectively. | - -## Follow Coding Guidelines - -### General Code Requirements - -1. Each function should have default values for non critical kwargs - - - Why? It increases code readability and acts as an input example for the function's arguments. This increases the ease of use of the functions through the SDK, but also just generally. - - > Watch out, add default values whenever possible, but take care for not adding mutable default arguments! [More info](https://docs.python-guide.org/writing/gotchas/#mutable-default-arguments) - -
- - - - - - - - - -
Good code :white_check_mark: Bad code :x:
- - ```python - def display_last_uni_swaps( - top: int = 10, - sortby: str = "timestamp", - descend: bool = False, - export: str = "",) -> None: - ``` - - - - ```python - def display_last_uni_swaps( - top: int, - sortby: str, - descend: bool, - export: str,) -> None: - ``` - -
- -
- -2. Simple and understandable input objects; avoid for example weird dictionaries packed with data: {β€œtitle”: DataFrame} - - - Why? Ease of use and often these complex formats are clumsy, prone to error and the formatting required for complex parameters is time consuming and unneeded. - -
- - - - - - - - - -
Good code :white_check_mark: Bad code :x:
- - ```python - def get_coins( - top: int = 250, - category: str = "") -> pd.DataFrame: - ``` - - - - ```python - def load( - file: str, - file_types: list, - data_files: Dict[Any, Any], - data_examples: Dict[Any, Any],) -> pd.DataFrame: - ``` - -
- -
- -3. Each function needs to have a docstring explaining what it does, its parameters and what it returns. - - - Why? You can use the function without reading its source code. This improves the developing experience and SDK usage. The SDK factory also can’t handle functions without docstrings. - -
- -4. Consistent and clear argument naming; not `symbol` in `_view` and then `ticker` in `_file` -> ticker everywhere; the name should be descriptive of what information it holds (see Style Guide section below) - - - Why? You can quickly understand what the input should be; example: tickers and stock names are fundamentally different, but they’re both strings so they should be named accordingly. - -
- - - - - - - - - -
Good code :white_check_mark: Bad code :x:
- - ```python - data: pd.Series, dataset_name: str, y_label: str, - ``` - - - - ```python - data: pd.Series, dataset: str, column: str, - ``` - -
- -
- -5. Classes (for example the portfolio class) should hold the relevant data and perform no other calculations, these calculations should be done in an independent function. - - - Why? Two reasons: - - These calculations can then be used outside of the class with custom data; for example via the sdk or for tests. - - ```python - from openbb_terminal.portfolio.portfolio_helper import get_gaintopain_ratio - - # Direct function access - get_gaintopain_ratio(historical_trade_data, benchmark_trades, benchmark_returns) - ``` - - The function can be loaded in SDK factory as an endpoint and user can get result by passing the class instance. - - ```python - from openbb_terminal.sdk import openbb - from openbb_terminal.sdk import Portfolio - - transactions = Portfolio.read_orderbook("../../portfolio/holdings/example.csv") - P = Portfolio(transactions) - P.generate_portfolio_data() - P.set_benchmark() - - # SDK endpoint access - openbb.portfolio.gaintopain(P) - ``` - - - - - - - - - -
Good code :white_check_mark: Bad code :x:
- - ```python - def get_gaintopain_ratio(portfolio: PortfolioEngine) -> pd.DataFrame: - - """...""" - - gtp_period_df = portfolio_helper.get_gaintopain_ratio( - portfolio.historical_trade_data, - portfolio.benchmark_trades, - portfolio.benchmark_returns) - - return gtp_period_df - ``` - - - - ```python - def get_gaintopain_ratio(self) -> pd.DataFrame: - - """...""" - - vals = list() - - for period in portfolio_helper.PERIODS: - port_rets = portfolio_helper.filter_df_by_period(self.portfolio_returns, period) - bench_rets = portfolio_helper.filter_df_by_period(self.benchmark_returns, period) - - ... - ``` - -
- -
- -6. Naming among related model and view functions should be obvious; just different prefix if possible - - - Why? Eases SDK factory mapping and keeps code clean. - -
- - - - - - - - - -
Good code :white_check_mark: Bad code :x:
- - ```python - # [fred_view.py] - - def display_yieldcurve(country: str): - - df = fred_model.get_yieldcurve(country) - - … - - # [fred_model.py] - - def get_yieldcurve(country: str) -> pd.Dataframe: - - … - ``` - - - - ```python - # [fred_view.py] - - def display_bondscrv(country: str): - - df = fred_model.get_yieldcurve(country) - - … - - # [fred_model.py] - - def get_yldcurve(country: str) -> pd.Dataframe: - - … - ``` - -
- -
- -### File Specific Requirements - -1. No data altering in the view file or controller file (view and model with same args) - - - Why? Consistency and good code structure. This also improves the SDK user experience. Thus follows that view and model files will have the same arguments (except for output options like raw, export, external_axes), since no data changes shall be done in the view file. - -
- -2. Each model (get_) should almost always have its own view function (display_) - - - Why? To respect the principles laid out in Code Structure and the previous bullet point. If your code does not have this `get_` β†’ `display_` map it’s likely that i. and/or ii. fail to hold. - - i. Data is processed in `_model` files and displayed in `_view` files - - ii. `_view` and `_model` files will have the same arguments (except for output options) - -
- -### Coding Style - -When in doubt, follow . - -#### OpenBB Style Guide - -The style guide is a reverse dictionary for argument names, where a brief definition is mapped to an OpenBB recommended argument name and type. When helpful a code snippet example is added below. Following this guide will help keep argument naming consistent and improve SDK users experience. - -Style guide structure: - -```python - : e.g. - -def func(..., argument_name: argument_type = default, ...): - ... -``` - -
- -#### Flags - -Show raw data : `raw` _(bool)_ - -```python -def display_data(..., raw: bool = False, ...): - ... - if raw: - print_rich_table(...) -``` - -Sort in ascending order : `ascend` _(bool)_ - -```python -def display_data(..., sortby: str = "", ascend: bool = False, ...): - ... - if sortby: - data = data.sort_values(by=sortby, ascend=ascend) -``` - -Show plot : `plot` _(bool)_ - -```python -def display_data(..., plot: bool = False, ...): - ... - if plot: - ... - fig.add_scatter(...) -``` - -
- -#### Output format - -Format to export data : `export` _(str), e.g. csv, json, xlsx_ - -```python -def display_data(..., export: str = "", ...): - ... - export_data(export, os.path.dirname(os.path.abspath(__file__)), "func", data) -``` - -Whether to display plot or return figure _(False: display, True: return)_ : `external_axes` _(bool)_ - -```python -def display_data(..., external_axes: bool = False, ...): - ... - fig = OpenBBFigure() - fig.add_scatter(...) - return fig.show(external=external_axes) -``` - -Field by which to sort : `sortby` _(str), e.g. "Volume"_ - -```python -def display_data(..., sortby: str = "col", ...): - ... - if sortby: - data = data.sort_values(by=sortby) -``` - -Maximum limit number of output items : `limit` _(int)_ - -```python -def display_data(..., limit = 10, ...): - ... - print_rich_table( - data[:limit], - ... - ) -``` - -
- -#### Time-related - -Date from which data is fetched (YYYY-MM-DD) : `start_date` _(str), e.g. 2022-01-01_ - -Date up to which data is fetched (YYYY-MM-DD) : `end_date` _(str), e.g. 2022-12-31_ - -Note: We want to accept dates in string because it is easier to deal from user standpoint. Inside the function you can convert it to datetime and check its validity. Please specify date format in docstring. - -```python -def get_historical_data(..., start_date: str = "2022-01-01", end_date: str = "2022-12-31",): - """ - ... - Parameters - ---------- - start_date: str - Date from which data is fetched in format YYYY-MM-DD - end_date: str - Date up to which data is fetched in format YYYY-MM-DD - ... - """ - data = source_model.get_data(data_name, start_date, end_date, ...) -``` - -Year from which data is fetched (YYYY) : `start_year` _(str), e.g. 2022_ - -Year up to which data is fetched (YYYY) : `end_year` _(str), e.g. 2023_ - -```python -def get_historical_data(..., start_year: str = "2022", end_year str = "2023", ...): - ... - data = source_model.get_data(data_name, start_year, end_year, ...) -``` - -Interval for data observations : `interval` _(str), e.g. 60m, 90m, 1h_ - -```python -def get_prices(interval: str = "60m", ...): - ... - data = source.download( - ..., - interval=interval, - ... - ) -``` - -Rolling window length : `window` _(int/str), e.g. 252, 252d_ - -```python -def get_rolling_sum(returns: pd.Series, window: str = "252d"): - rolling_sum = returns.rolling(window=window).sum() -``` - -
- -#### Data selection and manipulation - -Search term used to query : `query` (str) - -Maximum limit of search items/periods in data source: `limit` _(int)_ - -Note: please specify limit application in docstring - -```python -def get_data_from_source(..., limit: int = 10, ...): - """ - Parameters - ---------- - ... - limit: int - Number of results to fetch from source - ... - """ - data = source.get_data(data_name, n_results=limit, ...) -``` - -Dictionary of input datasets : `datasets` _(Dict[str, pd.DataFrame])_ - -Note: Most occurrences are on the econometrics menu and might be refactored in near future - -Input dataset : `data` _(pd.DataFrame)_ - -```python -def process_data(..., data: pd.DataFrame, ...): - """ - ... - Parameters - ---------- - ... - data : pd.DataFrame - Dataframe of ... - ... - """ - col_data = pd.DataFrame(data["Col"]) -``` - -Dataset name : `dataset_name` _(str)_ - -Input series : `data` _(pd.Series)_ - -Dependent variable series : `dependent_series` _(pd.Series)_ - -Independent variable series : `independent_series` _(pd.Series)_ - -```python -def get_econometric_test(dependent_series, independent_series, ...): - ... - dataset = pd.concat([dependent_series, independent_series], axis=1) - result = econometric_test(dataset, ...) -``` - -Country name : `country` _(str), e.g. United States, Portugal_ - -Country initials or abbreviation : `country_code` _(str) e.g. US, PT, USA, POR_ - -Currency to convert data : `currency` _(str) e.g. EUR, USD_ - -
- -#### Financial instrument characteristics - -Instrument ticker, name or currency pair : `symbol` _(str), e.g. AAPL, ethereum, ETH, ETH-USD_ - -```python -def get_prices(symbol: str = "AAPL", ...): - ... - data = source.download( - tickers=symbol, - ... - ) -``` - -Instrument name: `name` _(str)_ - -Note: If a function has both name and symbol as parameter, we should distinguish them and call it name - -List of instrument tickers, names or currency pairs : `symbols` _(List/List[str]), e.g. ["AAPL", "MSFT"]_ - -Base currency under ***BASE***-QUOTE β†’ ***XXX***-YYY convention : `from_symbol` _(str), e.g. ETH in ETH-USD_ - -Quote currency under BASE-***QUOTE*** β†’ XXX-***YYY*** convention : `to_symbol` _(str), e.g. USD in ETH-USD_ - -```python -def get_exchange_rate(from_symbol: str = "", to_symbol: str = "", ...): - ... - df = source.get_quotes(from_symbol, to_symbol, ...) -``` - -Instrument price : `price` _(float)_ - -Instrument implied volatility : `implied_volatility` _(float)_ - -Option strike price : `strike_price` _(float)_ - -Option days until expiration : `time_to_expiration` _(float/str)_ - -Risk free rate : `risk_free_rate` _(float)_ - -Options expiry date : `expiry` _(str)_ - -
- -#### Naming Convention - -- The name of the variables must be descriptive of what they stand for. I.e. `ticker` is descriptive, `aux` is not. -- Single character variables **must** be avoided. Except if they correspond to the iterator of a loop. - -#### Docstrings - -The docstring format used in **numpy**, an example is shown below: - -```python -def command_foo(var1: str, var2: List[int], var3: bool = False) -> Tuple[int, pd.DataFrame]: -"""Small description - -[Optional: Longer description] - -Parameters ----------- -var1 : str - var1 description -var2 : List[int] - var2 description -var3 : bool, optional - var3 description - -Returns -------- -foo : int - returned foo description -pd.DataFrame - dataframe returned -""" -``` - -#### Linters - -The following linters are used by our codebase: - -| Linter | Description | -| ------------ | --------------------------------- | -| bandit | security analyzer | -| black | code formatter | -| codespell | spelling checker | -| ruff | a fast python linter | -| mypy | static typing checker | -| pylint | static code analysis | -| markdownlint | markdown linter | - -#### Command names - -- The command name should be as short as possible. -- The command name should allow the user to know what the command refers to without needing to read description. (e.g. `earn`) - - - If this is not possible, then the command name should be an abbreviation of what the functionality corresponds to (e.g. `ycrv` for `yield curve`) - -- The command name **should not** have the data source explicit - -#### UI and UX - -Screenshot 2022-10-26 at 12 17 19 - -It is important to keep a coherent UI/UX throughout the terminal. These are the rules we must abide: - -- There is 1 single empty line between user input and start of the command output. -- There is 1 single empty line between command output and the user input. -- The menu help has 1 empty line above text and 1 empty line below. Both still within the rectangular panel. -- From menu help rectangular panel there's no empty line below - this makes it more clear to the user that they are inside such menu. - -## External API Keys - -### Creating API key - -OpenBB Terminal currently has over 100 different data sources. Most of these require an API key that allows access to some free tier features from the data provider, but also paid ones. - -When a new API data source is added to the platform, it must be added through [credentials_model.py](/openbb_terminal/core/models/credentials_model.py). - -In order to do that, you'll simply need to choose from one the following files: - -1. [local_credentials.json](openbb_terminal/miscellaneous/models/local_credentials.json) --> credentials that should only be stored locally and not pushed to the [OpenBB Hub](https://my.openbb.co/) like brokerage keys or other very sensitive or personal to the user. -2. [hub_credentials.json](openbb_terminal/miscellaneous/models/hub_credentials.json) --> credentials that should be stored in the [OpenBB Hub](https://my.openbb.co/) like API keys to access your favorite providers. - -Then just update [all_api_keys.json](openbb_terminal/miscellaneous/models/all_api_keys.json) with the instructions to get -the api key from the data source website. Make sure that this file has the correct `.json` format, otherwise the API keys page in the Hub will break (e.g. in json the last element key-value pair shouldn't be followed by a comma, and the last object in a list of dictionaries should also not be followed by a comma). - -> Note: By differentiating between local and hub credentials, we can ensure that the user's credentials are not pushed to the [OpenBB Hub](https://my.openbb.co/) and are only stored locally. This does not mean that the credentials are not secure in the OpenBB Hub, but rather that the user can choose to store them locally if they wish. - -### Setting and checking API key - -One of the first steps once adding a new data source that requires an API key is to add that key to our [keys_controller.py](/openbb_terminal/keys_controller.py). This menu allows the user to set API keys and check their validity. - -The following code allows to check the validity of the Polygon API key. - -```python - -def check_polygon_key(show_output: bool = False) -> str: - """Check Polygon key - - Parameters - ---------- - show_output: bool - Display status string or not. By default, False. - - Returns - ------- - str - Status of key set - """ - - current_user = get_current_user() - - if current_user.credentials.API_POLYGON_KEY == "REPLACE_ME": - logger.info("Polygon key not defined") - status = KeyStatus.NOT_DEFINED - else: - r = request( - "https://api.polygon.io/v2/aggs/ticker/AAPL/range/1/day/2020-06-01/2020-06-17" - f"?apiKey={current_user.credentials.API_POLYGON_KEY}" - ) - if r.status_code in [403, 401]: - logger.warning("Polygon key defined, test failed") - status = KeyStatus.DEFINED_TEST_FAILED - elif r.status_code == 200: - logger.info("Polygon key defined, test passed") - status = KeyStatus.DEFINED_TEST_PASSED - else: - logger.warning("Polygon key defined, test inconclusive") - status = KeyStatus.DEFINED_TEST_INCONCLUSIVE - - if show_output: - console.print(status.colorize()) - - return str(status) -``` - -Note that there are usually 3 states: - -- **defined, test passed**: The user has set their API key and it is valid. -- **defined, test failed**: The user has set their API key but it is not valid. -- **not defined**: The user has not defined any API key. - -Note: Sometimes the user may have the correct API key but still not have access to a feature from that data source, and that may be because such feature required an API key of a higher level. - -A function can then be created with the following format to allow the user to change its environment key directly from the terminal. - -```python -def call_polygon(self, other_args: List[str]): - """Process polygon command""" - parser = argparse.ArgumentParser( - add_help=False, - formatter_class=argparse.ArgumentDefaultsHelpFormatter, - prog="polygon", - description="Set Polygon 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://polygon.io") - return - - if other_args and "-" not in other_args[0][0]: - other_args.insert(0, "-k") - ns_parser = self.parse_simple_args(parser, other_args) - if ns_parser: - self.status_dict["polygon"] = keys_model.set_polygon_key( - key=ns_parser.key, persist=True, show_output=True - ) -``` - -# ADVANCED - -## Important functions and classes - -### Base controller class - -This `BaseController` class is inherited by all controllers on the terminal. - -This class contains both important variables and methods that are common across all terminal controllers. - -**CHOICES_COMMON**: List of common commands across all controllers - -- `cls`: clear screen -- `home`: go back to the main root -- `h`, `?` and `help`: display the help menu the user is in -- `q`, `quit` and `..`: go back to one menu above -- `exit`: exit the platform -- `r` and `reset`: reset the platform (reading code and settings again but going into the same state) -- `support`: create a support request ticket - -All of these variables have a `call_FUNCTION` associated with them. - -Worthy methods to mention are: - -- `load_class`: Checks for an existing instance of the controller before creating a new one to speed up access to that menu. -- `custom_reset`: Should be used by controllers that rely on a state variable - meant to be overridden. They should add the commands necessary to have the same data loaded. -- `print_help`: Meant to be overridden by each controller -- `parse_input`: Processes the string the user inputs into a list of actionable commands -- `switch`: Acts upon the command action received -- `parse_known_args_and_warn`: Parses the command with the `-` and `--` flags and variables. Some built-in flags are: - - `export_allowed`: Which can be set to `_NO_EXPORT_`, `_EXPORT_ONLY_RAW_DATA_ALLOWED_`, `_EXPORT_ONLY_FIGURES_ALLOWED_` and `_EXPORT_BOTH_RAW_DATA_AND_FIGURES_` - - `raw`: Displaying the data raw - - `limit`: Number of rows to display -- `menu`: Most important method. When a menu is executed, the way to call it is through `stocks_menu.menu()` - -## Default Data Sources - -The document [openbb_default.json](openbb_terminal/miscellaneous/sources/openbb_default.json) contains all data sources that the terminal has access to and specifies the data source utilized by default for each command. - -The convention is as follows: - -```python -{ - "stocks": { - "search": [ - "FinanceDatabase" - ], - "quote": [ - "FinancialModelingPrep" - ], - "tob": [ - "CBOE" - ], - "candle": [], - "codes": [ - "Polygon" - ], - "news": [ - "Feedparser", - "NewsApi", - ], - ... -``` - -The way to interpret this file is by following the path to a data source, e.g. - -- `stocks/search` relies on `FinanceDatabase` -- `stocks/candle` does not rely on any data source. This means that it relies on data that has been loaded before. -- `stocks/load` relies on `YahooFinance`, `AlphaVantage`, `Polygon` or `EODHD`. - - **The order is important as the first data source is the one utilized by default.** -- `stocks/options/unu` relies on `FDScanner`. -- `stocks/options/exp` relies on `YahooFinance` by default but `Tradier` and `Nasdaq` sources are allowed. - -> Note: The default data sources can be changed directly in the [OpenBB Hub](https://my.openbb.co/) by the user and automatically synchronized with the terminal on login. - -## Export Data - -In the `_view.py` files it is common having at the end of each function `export_data` being called. This typically looks like: - -```python - export_data( - export, - os.path.dirname(os.path.abspath(__file__)), - "pt", - df_analyst_data, - sheet_name, - fig, - ) -``` - -Let's go into each of these arguments: - -- `export` corresponds to the type of file we are exporting. - - If the user doesn't have anything selected, then this function doesn't do anything. - - The user can export multiple files and even name the files. - - The allowed type of files `json,csv,xlsx` for raw data and `jpg,pdf,png,svg` for figures depends on the `export_allowed` variable defined in `parse_known_args_and_warn`. -- `os.path.dirname(os.path.abspath(__file__))` corresponds to the directory path - - This is important when `export folder` selected is the default because the data gets stored based on where it is called. - - If this is called from a `common` folder, we can use `os.path.dirname(os.path.abspath(__file__)).replace("common", "stocks")` instead -- `"pt"` corresponds to the name of the exported file (+ unique datetime) if the user doesn't provide one -- `df_analyst_data` corresponds to the dataframe with data. -- `sheet_name` corresponds to the name of the sheet in the excel file. -- `fig` corresponds to the figure to be exported as an image or pdf. - -If `export_allowed=EXPORT_BOTH_RAW_DATA_AND_FIGURES` in `parse_known_args_and_warn`, valid examples are: - -- `cmd --export csv` -- `cmd --export csv,png,jpg` -- `cmd --export mydata.csv` -- `cmd --export mydata.txt,alsomydata.csv,alsoalsomydata.png` - -Note that these files are saved on a location based on the environment variable: `EXPORT_FOLDER_PATH`. Which can be set in `settings/export`. - -The default location is the `exports` folder and the data will be stored with the same organization of the terminal. But, if the user specifies the name of the file, then that will be dropped onto the folder as is with the datetime attached. - -## Queue and pipeline - -The variable `self.queue` contains a list of all actions to be run on the platform. That is the reason why this variable is always passed as an argument to a new controller class and received back. - -```python - self.queue = self.load_class( - DarkPoolShortsController, self.ticker, self.start, self.stock, self.queue - ) -``` - -Example: - -If a user is in the root of the terminal and runs: - -```shell -stocks/load AAPL/dps/psi -l 90 -``` - -The queue created becomes: -`self.queue = ["stocks", "load AAPL", "dps", "psi -l 90"]` - -And the user goes into the `stocks` menu and runs `load AAPL`. Then the queue is updated to -`self.queue = ["dps", "psi -l 90"]` - -At that point the user goes into the `dps` menu and runs the command `psi` with the argument `-l 90` therefore displaying price vs short interest of the past 90 days. - -## Auto Completer - -In order to help users with a powerful autocomplete, we have implemented our own (which can be found [here](/openbb_terminal/custom_prompt_toolkit.py)). - -The queue, discussed in the previous section [Queue and pipeline](#queue-and-pipeline), is expected to link together with the autocompletion in order to provide the user with the available options for each command. -Here is an example of how it will look like: - -```bash -2023 Apr 11, 11:41 (πŸ¦‹) /stocks/dps/ $ psi - --nyse - --help - -h - --export - --raw - --limit - -l - --source -``` - -> Where `nyse`, `help`, `h`, `export`, `raw`, `limit`, `l` and `source` are the available options for the `psi` command. -> Those are selectable using the arrow keys and the `tab` key. - -The list of options for each command is automatically generated, if you're interested take a look at its implementation [here](/openbb_terminal/core/completer/choices.py). - -To leverage this functionality, you need to add the following line to the top of the desired controller: - -```python -CHOICES_GENERATION = True -``` - -Here's an example of how to use it, on the [`forex` controller](/openbb_terminal/forex/forex_controller.py): - -```python -class ForexController(BaseController): - """Forex Controller class.""" - - CHOICES_COMMANDS = [ - "fwd", - "candle", - "load", - "quote", - ] - CHOICES_MENUS = [ - "forecast", - "qa", - "ta", - ] - RESOLUTION = ["i", "d", "w", "m"] - - PATH = "/forex/" - FILE_PATH = os.path.join(os.path.dirname(__file__), "README.md") - CHOICES_GENERATION = True - - def __init__(self, queue: Optional[List[str]] = None): - """Construct Data.""" - super().__init__(queue) - - self.fx_pair = "" - self.from_symbol = "" - self.to_symbol = "" - self.source = get_ordered_list_sources(f"{self.PATH}load")[0] - self.data = pd.DataFrame() - - if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - choices: dict = self.choices_default - choices["load"].update({c: {} for c in FX_TICKERS}) - - self.completer = NestedCompleter.from_nested_dict(choices) - - - ... -``` - -In case the user is interested in a **DYNAMIC** list of options which changes based on user's state, then a class method must be defined. - -The example below shows an excerpt from `update_runtime_choices` method in the [`options` controller](/openbb_terminal/stocks/options/options_controller.py). - -```python -def update_runtime_choices(self): - """Update runtime choices""" - if session and get_current_user().preferences.USE_PROMPT_TOOLKIT: - if not self.chain.empty: - strike = set(self.chain["strike"]) - - self.choices["hist"]["--strike"] = {str(c): {} for c in strike} - self.choices["grhist"]["-s"] = "--strike" - self.choices["grhist"]["--strike"] = {str(c): {} for c in strike} - self.choices["grhist"]["-s"] = "--strike" - self.choices["binom"]["--strike"] = {str(c): {} for c in strike} - self.choices["binom"]["-s"] = "--strike" -``` - -This method should only be called when the user's state changes leads to the auto-complete not being accurate. - -In this case, this method is called as soon as the user successfully loads a new ticker since the options expiry dates vary based on the ticker. Note that the completer is recreated from it. - -## Logging - -A logging system is used to help tracking errors inside the OpenBBTerminal. - -This is storing every logged message inside the following location : - -`$HOME/OpenBBUserData/logs` - -Where $HOME is the user home directory, for instance: - -- `C:\Users\foo` if you are in Windows and your name is foo -- `/home/bar/` if you are in macOS or Linux and your name is bar - -The user can override this location using the settings key `OPENBB_USER_DATA_DIRECTORY`. - -If you want to log a particular message inside a function you can do like so: - -```python -import logging - -logger = logging.getLogger(__name__) - -def your_function() -> pd.DataFrame: - logger.info("Some log message with the level INFO") - logger.warning("Some log message with the level WARNING") - logger.fatal("Some log message with the level FATAL") -``` - -You can also use the decorator `@log_start_end` to automatically record a message every time a function starts and ends, like this: - -```python -import logging - - - -logger = logging.getLogger(__name__) - - -def your_function() -> pd.DataFrame: - pass -``` - -> **Note**: if you don't want your logs to be collected, you can set the `OPENBB_LOG_COLLECT` environment variable on your `.env` file to `False`. -> -> **Disclaimer**: all the user paths, names, IPs, credentials and other sensitive information are anonymized, [take a look at how we do it](/openbb_terminal/core/log/generation/formatter_with_exceptions.py). - -## Internationalization - -WORK IN PROGRESS - The menu can be internationalised BUT we do not support yet help commands`-h` internationalization. - -In order to add support for a new language, the best approach is to: - -1. Copy-paste `i18n/en.yml` -2. Rename that file to a short version of language you are translating to, e.g. `i18n/pt.yml` for portuguese -3. Then just update the text on the right. E.g. - -```text - stocks/NEWS: latest news of the company -``` - -becomes - -```text - stocks/NEWS: mais recentes notΓ­cias da empresa -``` - -Note: To speed up translation, the team developed a [script](/i18n/help_translation.ipynb) that uses Google translator API to help translating the entire `en.yml` document to the language of choice. Then the output still needs to be reviewed, but this can be a useful bootstrap. - -This is the convention in use for creating a new key/value pair: - -- `stocks/search` - Under `stocks` context, short command `search` description on the `help menu` -- `stocks/SEARCH` - Under `stocks` context, long command `search` description, when `search -h` -- `stocks/SEARCH_query` - Under `stocks` context, `query` description when inquiring about `search` command with `search -h` -- `stocks/_ticker` - Under `stocks` context, `_ticker` is used as a key of a parameter, and the displayed parameter description is given as value -- `crypto/dd/_tokenomics_` - Under `crypto` context and under `dd` menu, `_tokenomics_` is used as a key of an additional information, and the displayed information is given as value - -## Settings - -The majority of the settings used in the OpenBB Terminal are handled using [Pydantic Dataclasses](https://docs.pydantic.dev/usage/dataclasses/). -Some examples are: - -1. [SystemModel](openbb_terminal/core/models/system_model.py) -2. [UserModel](openbb_terminal/core/models/user_model.py) -3. [CredentialsModel](openbb_terminal/core/models/credentials_model.py) -4. ... - -This means that the settings are pretty much validated and documented automatically, as well as centralized in a single place. -This allows us to develop faster, efficiantly and with predictability. -Depending on your use case you'll most likely need to interact with these dataclasses or expand them with new settings. - -**Disclaimer**: avoid at all costs to use the `os.environ` or `os.getenv` methods to retrieve settings. Settings should be retrieved using the appropriate methods from the respective class. - -Here is an example of **accessing** a setting: - -```python - -from src.current_system import get_current_system - -system = get_current_system() -system = get_current_system() -print(system.VERSION) - -# 3.0.0 - -``` - -And here is an example of **changing** a setting: - -```python - -from src.current_system import get_current_system - -set_system_variable("TEST_MODE", True) - -``` - -## Write Code and Commit - -At this stage it is assumed that you have already forked the project and are ready to start working. - -### Pre Commit Hooks - -Git hook scripts are useful for identifying simple issues before submission to code review. We run our hooks on every -commit to automatically point out issues in code such as missing semicolons, trailing whitespace, and debug statements. -By pointing these issues out before code review, this allows a code reviewer to focus on the architecture of a change -while not wasting time with trivial style nitpicks. - -Install the pre-commit hooks by running: `pre-commit install`. - -### Coding - -Although the Coding Guidelines section has been already explained, it is worth mentioning that if you want to be faster -at developing a new feature, you may implement it first on a `jupyter notebook` and then carry it across to the -terminal. This is mostly useful when the feature relies on scraping data from a website, or implementing a Neural -Network model. - -### Git Process - -1. Create your Feature Branch, e.g. `git checkout -b feature/AmazingFeature` -2. Check the files you have touched using `git status` -3. Stage the files you want to commit, e.g. - `git add openbb_terminal/stocks/stocks_controller.py openbb_terminal/stocks/stocks_helper.py`. - Note: **DON'T** add `config_terminal.py` or `.env` files with personal information, or even `feature_flags.py` which is user-dependent. -4. Write a concise commit message under 50 characters, e.g. `git commit -m "meaningful commit message"`. If your PR - solves an issue raised by a user, you may specify such issue by adding #ISSUE_NUMBER to the commit message, so that - these get linked. Note: If you installed pre-commit hooks and one of the formatters re-formats your code, you'll need - to go back to step 3 to add these. - -### Branch Naming Conventions - -The accepted branch naming conventions are: - -- `feature/feature-name` -- `hotfix/hotfix-name` -- `release/2.1.0` or `release/2.1.0rc0`. -- `bugfix/bugfix-name` -- `docs/docs-name` - -All `feature/feature-name` and `bugfix/bugfix-name` related branches can only have PRs pointing to `develop` branch. `release/*` branches can only have PRs pointing to `main` branch, while `hotfix/hotfix-name` should first be merged to `main` and then into `develop` to sync the hotfix changes. - -When `develop` branch is merged to `main`, a GitHub action will run scripts that generate documentation content (reference sections, data models, etc.) and trigger the website deployment. Those scripts can be found in the following path `website/generate_*.py`. - -The `develop` branch is only merged to `main` right before a new release, but sometimes you might need to update the website in-between releases. To do this follow these steps: - -1. create `docs/[my-update]` branch from `main` -2. commit your changes to `docs/[my-update]` -3. merge `docs/[my-update]` into `main` -> website deployment triggered -4. merge `docs/[my-update]` into `develop` -> NO website deployment, just to sync branches - -## Installers - -When implementing a new feature or fixing something within the codebase, it is necessary to ensure that it is working -appropriately on the terminal. However, it is equally as important to ensure that new features or fixes work on the -installer terminal too. This is because a large portion of users utilize the installer to use OpenBB Terminal. -More information on how to build an installer can be found [here](build/README.md). diff --git a/cli/README.md b/cli/README.md index 28bcbff336d2..2ab4656c0fa1 100644 --- a/cli/README.md +++ b/cli/README.md @@ -1,3 +1,67 @@ -# OpenBB CLI +# OpenBB Platform CLI -Work in progress. +[![Downloads](https://static.pepy.tech/badge/openbb)](https://pepy.tech/project/openbb) +[![LatestRelease](https://badge.fury.io/py/openbb.svg)](https://github.com/OpenBB-finance/OpenBBTerminal) + +| OpenBB is committed to build the future of investment research by focusing on an open source infrastructure accessible to everyone, everywhere. | +| :---------------------------------------------------------------------------------------------------------------------------------------------: | +| ![OpenBBLogo](https://user-images.githubusercontent.com/25267873/218899768-1f0964b8-326c-4f35-af6f-ea0946ac970b.png) | +| Check our website at [openbb.co](www.openbb.co) | + +## Overview + +The OpenBB CLI is a command line interface that wraps [OpenBB Platform](https://docs.openbb.co/platform). + +It offers a convenient way to interact with the OpenBB Platform and its extensions, as well as automate data collection via OpenBB Routine Scripts. + +Find the most complete documentation, examples, and usage guides for the OpenBB Platform CLI [here](https://my.openbb.co/app/cli). + +## Installation + +The command below provides access to the all the available OpenBB extensions behind the OpenBB Platform, find the complete list [here](https://my.openbb.co/app/platform/extensions). + +```bash +pip install openbb-cli +``` + +> Note: Find the most complete installation hints and tips [here](https://my.openbb.co/app/cli/installation). + +After the installation is complete, you can deploy the OpenBB CLI by running the following command: + +```bash +openbb +``` + +Which should result in the following output: + +![image](https://github.com/OpenBB-finance/OpenBBTerminal/assets/48914296/f606bb6e-fa00-4fc8-bad2-8269bb4fc38e) + +## API keys + +To fully leverage the OpenBB Platform you need to get some API keys to connect with data providers. Here are the 3 options on where to set them: + +1. OpenBB Hub +2. Local file + +### 1. OpenBB Hub + +Set your keys at [OpenBB Hub](https://my.openbb.co/app/platform/credentials) and get your personal access token from to connect with your account. + +> Once you log in, on the Platform CLI (through the `/account` menu, all your credentials will be in sync with the OpenBB Hub.) + +### 2. Local file + +You can specify the keys directly in the `~/.openbb_platform/user_settings.json` file. + +Populate this file with the following template and replace the values with your keys: + +```json +{ + "credentials": { + "fmp_api_key": "REPLACE_ME", + "polygon_api_key": "REPLACE_ME", + "benzinga_api_key": "REPLACE_ME", + "fred_api_key": "REPLACE_ME" + } +} +``` diff --git a/openbb_platform/README.md b/openbb_platform/README.md index 40bf3f7fc747..c3c2084fc38f 100644 --- a/openbb_platform/README.md +++ b/openbb_platform/README.md @@ -80,7 +80,7 @@ To fully leverage the OpenBB Platform you need to get some API keys to connect w ### 1. OpenBB Hub -Set your keys at [OpenBB Hub](https://my.openbb.co/app/sdk/api-keys) and get your personal access token from to connect with your account. +Set your keys at [OpenBB Hub](https://my.openbb.co/app/platform/credentials) and get your personal access token from to connect with your account. ```python >>> from openbb import obb diff --git a/openbb_platform/core/openbb_core/app/service/hub_service.py b/openbb_platform/core/openbb_core/app/service/hub_service.py index e60b667ae0d6..419eef955dd1 100644 --- a/openbb_platform/core/openbb_core/app/service/hub_service.py +++ b/openbb_platform/core/openbb_core/app/service/hub_service.py @@ -233,7 +233,7 @@ def hub2platform(self, settings: HubUserSettings) -> Credentials: } msg = "" for k, v in deprecated.items(): - msg += f"\n'{k}' -> '{v}', " + msg += f"\n'{k}' -> '{v.upper()}', " msg = msg.strip(", ") warn( message=f"\nDeprecated v3 credentials found.\n{msg}" diff --git a/openbb_platform/core/openbb_core/app/static/package_builder.py b/openbb_platform/core/openbb_core/app/static/package_builder.py index 5db17483a191..11fcc5766b0a 100644 --- a/openbb_platform/core/openbb_core/app/static/package_builder.py +++ b/openbb_platform/core/openbb_core/app/static/package_builder.py @@ -319,6 +319,8 @@ def get_function_hint_type_list(cls, func: Callable) -> List[Type]: hint_type_list.append(parameter.annotation) if return_type: + if not issubclass(return_type, OBBject): + raise ValueError("Return type must be an OBBject.") hint_type = get_args(get_type_hints(return_type)["results"])[0] hint_type_list.append(hint_type) diff --git a/openbb_platform/core/openbb_core/provider/abstract/provider.py b/openbb_platform/core/openbb_core/provider/abstract/provider.py index 6da989d807a8..756060ba59bc 100644 --- a/openbb_platform/core/openbb_core/provider/abstract/provider.py +++ b/openbb_platform/core/openbb_core/provider/abstract/provider.py @@ -19,7 +19,6 @@ def __init__( repr_name: Optional[str] = None, v3_credentials: Optional[List[str]] = None, instructions: Optional[str] = None, - logo_url: Optional[str] = None, ) -> None: """Initialize the provider. @@ -41,8 +40,6 @@ def __init__( List of corresponding v3 credentials, by default None. instructions: Optional[str] Instructions on how to setup the provider. For example, how to get an API key. - logo_url: Optional[str] - Provider logo URL. """ self.name = name self.description = description @@ -57,4 +54,3 @@ def __init__( self.repr_name = repr_name self.v3_credentials = v3_credentials self.instructions = instructions - self.logo_url = logo_url diff --git a/openbb_platform/providers/benzinga/openbb_benzinga/__init__.py b/openbb_platform/providers/benzinga/openbb_benzinga/__init__.py index 279f6a90b499..91cd544c3784 100644 --- a/openbb_platform/providers/benzinga/openbb_benzinga/__init__.py +++ b/openbb_platform/providers/benzinga/openbb_benzinga/__init__.py @@ -19,5 +19,4 @@ "PriceTarget": BenzingaPriceTargetFetcher, }, repr_name="Benzinga", - logo_url="https://www.benzinga.com/sites/all/themes/bz2/images/Benzinga-logo-navy.svg", ) diff --git a/openbb_platform/providers/biztoc/openbb_biztoc/__init__.py b/openbb_platform/providers/biztoc/openbb_biztoc/__init__.py index b3449af194d6..8fc02244e207 100644 --- a/openbb_platform/providers/biztoc/openbb_biztoc/__init__.py +++ b/openbb_platform/providers/biztoc/openbb_biztoc/__init__.py @@ -22,5 +22,4 @@ repr_name="BizToc", v3_credentials=["API_BIZTOC_TOKEN"], instructions="The BizToc API is hosted on RapidAPI. To set up, go to: https://rapidapi.com/thma/api/biztoc.\n\n![biztoc0](https://github.com/marban/OpenBBTerminal/assets/18151143/04cdd423-f65e-4ad8-ad5a-4a59b0f5ddda)\n\nIn the top right, select 'Sign Up'. After answering some questions, you will be prompted to select one of their plans.\n\n![biztoc1](https://github.com/marban/OpenBBTerminal/assets/18151143/9f3b72ea-ded7-48c5-aa33-bec5c0de8422)\n\nAfter signing up, navigate back to https://rapidapi.com/thma/api/biztoc. If you are logged in, you will see a header called X-RapidAPI-Key.\n\n![biztoc2](https://github.com/marban/OpenBBTerminal/assets/18151143/0f3b6c91-07e0-447a-90cd-a9e23522929f)", # noqa: E501 pylint: disable=line-too-long - logo_url="https://c.biztoc.com/274/logo.svg", ) diff --git a/openbb_platform/providers/cboe/openbb_cboe/__init__.py b/openbb_platform/providers/cboe/openbb_cboe/__init__.py index 612d8a3e41f8..9179377acec1 100644 --- a/openbb_platform/providers/cboe/openbb_cboe/__init__.py +++ b/openbb_platform/providers/cboe/openbb_cboe/__init__.py @@ -38,5 +38,4 @@ "OptionsChains": CboeOptionsChainsFetcher, }, repr_name="Chicago Board Options Exchange (CBOE)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/8/8a/Cboe_Global_Markets_Logo.svg/2880px-Cboe_Global_Markets_Logo.svg.png", # noqa: E501 pylint: disable=line-too-long ) diff --git a/openbb_platform/providers/ecb/openbb_ecb/__init__.py b/openbb_platform/providers/ecb/openbb_ecb/__init__.py index a339718e1758..e828ea75a1aa 100644 --- a/openbb_platform/providers/ecb/openbb_ecb/__init__.py +++ b/openbb_platform/providers/ecb/openbb_ecb/__init__.py @@ -17,5 +17,4 @@ "EUYieldCurve": ECBEUYieldCurveFetcher, }, repr_name="European Central Bank (ECB)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/c/cb/Logo_European_Central_Bank.svg/720px-Logo_European_Central_Bank.svg.png", # noqa: E501 pylint: disable=line-too-long ) diff --git a/openbb_platform/providers/econdb/openbb_econdb/__init__.py b/openbb_platform/providers/econdb/openbb_econdb/__init__.py index edde522a9eed..a0a0e9f18c89 100644 --- a/openbb_platform/providers/econdb/openbb_econdb/__init__.py +++ b/openbb_platform/providers/econdb/openbb_econdb/__init__.py @@ -23,5 +23,4 @@ "EconomicIndicators": EconDbEconomicIndicatorsFetcher, }, repr_name="EconDB", - logo_url="https://avatars.githubusercontent.com/u/21289885?v=4", ) diff --git a/openbb_platform/providers/federal_reserve/openbb_federal_reserve/__init__.py b/openbb_platform/providers/federal_reserve/openbb_federal_reserve/__init__.py index 749e3e1ad3e4..4e1b249ec798 100644 --- a/openbb_platform/providers/federal_reserve/openbb_federal_reserve/__init__.py +++ b/openbb_platform/providers/federal_reserve/openbb_federal_reserve/__init__.py @@ -20,5 +20,4 @@ "FEDFUNDS": FederalReserveFEDFetcher, }, repr_name="Federal Reserve (FED)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1a/Seal_of_the_United_States_Federal_Reserve_System.svg/498px-Seal_of_the_United_States_Federal_Reserve_System.svg.png", # noqa: E501 pylint: disable=line-too-long ) diff --git a/openbb_platform/providers/finra/openbb_finra/__init__.py b/openbb_platform/providers/finra/openbb_finra/__init__.py index 4428b0f7e152..6654ee44b0a8 100644 --- a/openbb_platform/providers/finra/openbb_finra/__init__.py +++ b/openbb_platform/providers/finra/openbb_finra/__init__.py @@ -15,5 +15,4 @@ "EquityShortInterest": FinraShortInterestFetcher, }, repr_name="Financial Industry Regulatory Authority (FINRA)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/9/95/FINRA_logo.svg/1024px-FINRA_logo.svg.png", ) diff --git a/openbb_platform/providers/finviz/openbb_finviz/__init__.py b/openbb_platform/providers/finviz/openbb_finviz/__init__.py index 75da4ea6c342..8862746c64bb 100644 --- a/openbb_platform/providers/finviz/openbb_finviz/__init__.py +++ b/openbb_platform/providers/finviz/openbb_finviz/__init__.py @@ -21,5 +21,4 @@ "PriceTarget": FinvizPriceTargetFetcher, }, repr_name="FinViz", - logo_url="https://finviz.com/img/logo_3_2x.png", ) diff --git a/openbb_platform/providers/fmp/openbb_fmp/__init__.py b/openbb_platform/providers/fmp/openbb_fmp/__init__.py index c4d372a4541a..01f9a5019e54 100644 --- a/openbb_platform/providers/fmp/openbb_fmp/__init__.py +++ b/openbb_platform/providers/fmp/openbb_fmp/__init__.py @@ -138,5 +138,4 @@ repr_name="Financial Modeling Prep (FMP)", v3_credentials=["API_KEY_FINANCIALMODELINGPREP"], instructions='Go to: https://site.financialmodelingprep.com/developer/docs\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207821920-64553d05-d461-4984-b0fe-be0368c71186.png)\n\nClick on, "Get my API KEY here", and sign up for a free account.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207822184-a723092e-ef42-4f87-8c55-db150f09741b.png)\n\nWith an account created, sign in and navigate to the Dashboard, which shows the assigned token. by pressing the "Dashboard" button which will show the API key.\n\n![FinancialModelingPrep](https://user-images.githubusercontent.com/46355364/207823170-dd8191db-e125-44e5-b4f3-2df0e115c91d.png)', # noqa: E501 pylint: disable=line-too-long - logo_url="https://intelligence.financialmodelingprep.com//images/fmp-brain-original.svg", ) diff --git a/openbb_platform/providers/fred/openbb_fred/__init__.py b/openbb_platform/providers/fred/openbb_fred/__init__.py index ccf1f046a6b2..b6efbd173a6c 100644 --- a/openbb_platform/providers/fred/openbb_fred/__init__.py +++ b/openbb_platform/providers/fred/openbb_fred/__init__.py @@ -62,5 +62,4 @@ repr_name="Federal Reserve Economic Data | St. Louis FED (FRED)", v3_credentials=["API_FRED_KEY"], instructions='Go to: https://fred.stlouisfed.org\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827137-d143ba4c-72cb-467d-a7f4-5cc27c597aec.png)\n\nClick on, "My Account", create a new account or sign in with Google:\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827011-65cdd501-27e3-436f-bd9d-b0d8381d46a7.png)\n\nAfter completing the sign-up, go to "My Account", and select "API Keys". Then, click on, "Request API Key".\n\n![FRED](https://user-images.githubusercontent.com/46355364/207827577-c869f989-4ef4-4949-ab57-6f3931f2ae9d.png)\n\nFill in the box for information about the use-case for FRED, and by clicking, "Request API key", at the bottom of the page, the API key will be issued.\n\n![FRED](https://user-images.githubusercontent.com/46355364/207828032-0a32d3b8-1378-4db2-9064-aa1eb2111632.png)', # noqa: E501 pylint: disable=line-too-long - logo_url="https://fred.stlouisfed.org/images/fred-logo-2x.png", ) diff --git a/openbb_platform/providers/government_us/openbb_government_us/__init__.py b/openbb_platform/providers/government_us/openbb_government_us/__init__.py index 5b1ed1aafaed..2a15283a7a9e 100644 --- a/openbb_platform/providers/government_us/openbb_government_us/__init__.py +++ b/openbb_platform/providers/government_us/openbb_government_us/__init__.py @@ -21,5 +21,4 @@ "TreasuryPrices": GovernmentUSTreasuryPricesFetcher, }, repr_name="Data.gov | United States Government", - logo_url="https://upload.wikimedia.org/wikipedia/commons/0/06/Muq55HrN_400x400.png", ) diff --git a/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py b/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py index 276873d94604..ae473c72e5c3 100644 --- a/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py +++ b/openbb_platform/providers/intrinio/openbb_intrinio/__init__.py @@ -100,5 +100,4 @@ repr_name="Intrinio", v3_credentials=["API_INTRINIO_KEY"], instructions="Go to: https://intrinio.com/starter-plan\n\n![Intrinio](https://user-images.githubusercontent.com/85772166/219207556-fcfee614-59f1-46ae-bff4-c63dd2f6991d.png)\n\nAn API key will be issued with a subscription. Find the token value within the account dashboard.", # noqa: E501 pylint: disable=line-too-long - logo_url="https://assets-global.website-files.com/617960145ff34fe4a9fe7240/617960145ff34f9a97fe72c8_Intrinio%20Logo%20-%20Dark.svg", ) diff --git a/openbb_platform/providers/nasdaq/openbb_nasdaq/__init__.py b/openbb_platform/providers/nasdaq/openbb_nasdaq/__init__.py index f365f02c9255..28babefdc607 100644 --- a/openbb_platform/providers/nasdaq/openbb_nasdaq/__init__.py +++ b/openbb_platform/providers/nasdaq/openbb_nasdaq/__init__.py @@ -36,5 +36,4 @@ repr_name="NASDAQ", v3_credentials=["API_KEY_QUANDL"], instructions='Go to: https://www.quandl.com\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207823899-208a3952-f557-4b73-aee6-64ac00faedb7.png)\n\nClick on, "Sign Up", and register a new account.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824214-4b6b2b74-e709-4ed4-adf2-14803e6f3568.png)\n\nFollow the sign-up instructions, and upon completion the API key will be assigned.\n\n![Quandl](https://user-images.githubusercontent.com/46355364/207824664-3c82befb-9c69-42df-8a82-510d85c19a97.png)', # noqa: E501 pylint: disable=line-too-long - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/NASDAQ_logo.svg/1600px-NASDAQ_logo.svg.png", ) diff --git a/openbb_platform/providers/oecd/openbb_oecd/__init__.py b/openbb_platform/providers/oecd/openbb_oecd/__init__.py index 2d5e58463b87..49b94a9e703e 100644 --- a/openbb_platform/providers/oecd/openbb_oecd/__init__.py +++ b/openbb_platform/providers/oecd/openbb_oecd/__init__.py @@ -24,5 +24,4 @@ "LTIR": OECDLTIRFetcher, }, repr_name="Organization for Economic Co-operation and Development (OECD)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a2/OECD_logo.svg/400px-OECD_logo.svg.png", ) diff --git a/openbb_platform/providers/polygon/openbb_polygon/__init__.py b/openbb_platform/providers/polygon/openbb_polygon/__init__.py index 917c121f9b27..27b715652c17 100644 --- a/openbb_platform/providers/polygon/openbb_polygon/__init__.py +++ b/openbb_platform/providers/polygon/openbb_polygon/__init__.py @@ -42,5 +42,4 @@ repr_name="Polygon.io", v3_credentials=["API_POLYGON_KEY"], instructions='Go to: https://polygon.io\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825623-fcd7f0a3-131a-4294-808c-754c13e38e2a.png)\n\nClick on, "Get your Free API Key".\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207825952-ca5540ec-6ed2-4cef-a0ed-bb50b813932c.png)\n\nAfter signing up, the API Key is found at the bottom of the account dashboard page.\n\n![Polygon](https://user-images.githubusercontent.com/46355364/207826258-b1f318fa-fd9c-41d9-bf5c-fe16722e6601.png)', # noqa: E501 pylint: disable=line-too-long - logo_url="https://polygon.io/_next/image?url=%2Flogo.svg&w=640&q=75", ) diff --git a/openbb_platform/providers/sec/openbb_sec/__init__.py b/openbb_platform/providers/sec/openbb_sec/__init__.py index e45329a720ae..d130dd64cf9c 100644 --- a/openbb_platform/providers/sec/openbb_sec/__init__.py +++ b/openbb_platform/providers/sec/openbb_sec/__init__.py @@ -33,5 +33,4 @@ "SymbolMap": SecSymbolMapFetcher, }, repr_name="Securities and Exchange Commission (SEC)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/1/1c/Seal_of_the_United_States_Securities_and_Exchange_Commission.svg/1920px-Seal_of_the_United_States_Securities_and_Exchange_Commission.svg.png", # noqa: E501 pylint: disable=line-too-long ) diff --git a/openbb_platform/providers/seeking_alpha/openbb_seeking_alpha/__init__.py b/openbb_platform/providers/seeking_alpha/openbb_seeking_alpha/__init__.py index 4195a6642e1a..e4022980de84 100644 --- a/openbb_platform/providers/seeking_alpha/openbb_seeking_alpha/__init__.py +++ b/openbb_platform/providers/seeking_alpha/openbb_seeking_alpha/__init__.py @@ -14,5 +14,4 @@ "UpcomingReleaseDays": SAUpcomingReleaseDaysFetcher, }, repr_name="Seeking Alpha", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/Seeking_Alpha_Logo.svg/280px-Seeking_Alpha_Logo.svg.png", ) diff --git a/openbb_platform/providers/stockgrid/openbb_stockgrid/__init__.py b/openbb_platform/providers/stockgrid/openbb_stockgrid/__init__.py index fc3e6c3288b0..ecba54bb5331 100644 --- a/openbb_platform/providers/stockgrid/openbb_stockgrid/__init__.py +++ b/openbb_platform/providers/stockgrid/openbb_stockgrid/__init__.py @@ -14,5 +14,4 @@ "ShortVolume": StockgridShortVolumeFetcher, }, repr_name="Stockgrid", - logo_url="https://www.stockgrid.io/img/logo_white2.41ee5250.svg", ) diff --git a/openbb_platform/providers/tiingo/openbb_tiingo/__init__.py b/openbb_platform/providers/tiingo/openbb_tiingo/__init__.py index 1b122816d80d..029f57a13c47 100644 --- a/openbb_platform/providers/tiingo/openbb_tiingo/__init__.py +++ b/openbb_platform/providers/tiingo/openbb_tiingo/__init__.py @@ -24,5 +24,4 @@ "TrailingDividendYield": TiingoTrailingDivYieldFetcher, }, repr_name="Tiingo", - logo_url="https://www.tiingo.com/dist/images/tiingo/logos/tiingo_full_light_color.svg", ) diff --git a/openbb_platform/providers/tmx/openbb_tmx/__init__.py b/openbb_platform/providers/tmx/openbb_tmx/__init__.py index 7377d9a7598e..72f31fabdeab 100644 --- a/openbb_platform/providers/tmx/openbb_tmx/__init__.py +++ b/openbb_platform/providers/tmx/openbb_tmx/__init__.py @@ -68,5 +68,4 @@ "TreasuryPrices": TmxTreasuryPricesFetcher, }, repr_name="TMX", - logo_url="https://www.tmx.com/assets/application/img/tmx_logo_en.1593799726.svg", ) diff --git a/openbb_platform/providers/tradier/openbb_tradier/__init__.py b/openbb_platform/providers/tradier/openbb_tradier/__init__.py index a8d332166ecf..85b5d219ec82 100644 --- a/openbb_platform/providers/tradier/openbb_tradier/__init__.py +++ b/openbb_platform/providers/tradier/openbb_tradier/__init__.py @@ -28,5 +28,4 @@ repr_name="Tradier", v3_credentials=["API_TRADIER_TOKEN"], instructions='Go to: https://documentation.tradier.com\n\n![Tradier](https://user-images.githubusercontent.com/46355364/207829178-a8bba770-f2ea-4480-b28e-efd81cf30980.png)\n\nClick on, "Open Account", to start the sign-up process. After the account has been setup, navigate to [Tradier Broker Dash](https://dash.tradier.com/login?redirect=settings.api) and create the application. Request a sandbox access token.', # noqa: E501 pylint: disable=line-too-long - logo_url="https://tradier.com/assets/images/tradier-logo.svg", ) diff --git a/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/__init__.py b/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/__init__.py index f87a720feb7b..ae82a774f70f 100644 --- a/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/__init__.py +++ b/openbb_platform/providers/tradingeconomics/openbb_tradingeconomics/__init__.py @@ -16,5 +16,4 @@ credentials=["api_key"], fetcher_dict={"EconomicCalendar": TEEconomicCalendarFetcher}, repr_name="Trading Economics", - logo_url="https://developer.tradingeconomics.com/Content/Images/logo.svg", ) diff --git a/openbb_platform/providers/wsj/openbb_wsj/__init__.py b/openbb_platform/providers/wsj/openbb_wsj/__init__.py index 5d413b2045c4..c27e000e2daf 100644 --- a/openbb_platform/providers/wsj/openbb_wsj/__init__.py +++ b/openbb_platform/providers/wsj/openbb_wsj/__init__.py @@ -22,5 +22,4 @@ "ETFActive": WSJActiveFetcher, }, repr_name="Wall Street Journal (WSJ)", - logo_url="https://upload.wikimedia.org/wikipedia/commons/thumb/4/4a/WSJ_Logo.svg/1594px-WSJ_Logo.svg.png", ) diff --git a/openbb_platform/providers/yfinance/openbb_yfinance/__init__.py b/openbb_platform/providers/yfinance/openbb_yfinance/__init__.py index 0cb4df8b9147..fe6e2934de8e 100644 --- a/openbb_platform/providers/yfinance/openbb_yfinance/__init__.py +++ b/openbb_platform/providers/yfinance/openbb_yfinance/__init__.py @@ -73,5 +73,4 @@ "ShareStatistics": YFinanceShareStatisticsFetcher, }, repr_name="Yahoo Finance", - logo_url="https://upload.wikimedia.org/wikipedia/commons/8/8f/Yahoo%21_Finance_logo_2021.png", )