diff --git a/.github/workflows/linting.yml b/.github/workflows/linting.yml index a04cc30e005..d4460e25bff 100644 --- a/.github/workflows/linting.yml +++ b/.github/workflows/linting.yml @@ -48,7 +48,7 @@ jobs: pip install types-pytz types-requests types-termcolor types-tabulate types-PyYAML types-python-dateutil types-setuptools types-six - run: bandit -x ./tests -r . || true - run: black --diff --check . - - run: codespell --ignore-words-list=vai,mis,gard,commun,parana,statics,ro,zar,zlot,jewl,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,vie,hel,ket,toke,certi,buidl,ot,te,buda,shs,welp --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./website/config.toml -x openbb_terminal/economy/fedreserve_model.py + - run: codespell --ignore-words-list=vai,mis,gard,commun,parana,statics,ro,zar,zlot,jewl,ba,buil,coo,ether,hist,hsi,mape,navagation,operatio,pres,ser,yeld,shold,ist,varian,datas,ake,creat,vie,hel,ket,toke,certi,buidl,ot,te,buda,shs,welp,fo,nwe --quiet-level=2 --skip=./tests,.git,*.css,*.csv,*.html,*.ini,*.ipynb,*.js,*.json,*.lock,*.scss,*.txt,*.yaml,./build/pyinstaller,./website/config.toml -x openbb_terminal/economy/fedreserve_model.py - run: ruff . - run: mypy --ignore-missing-imports openbb_terminal - run: pylint terminal.py openbb_terminal tests diff --git a/openbb_sdk/extensions/charting/openbb_charting/charting_router.py b/openbb_sdk/extensions/charting/openbb_charting/charting_router.py index 8bf1b9440c9..f259b6b385b 100644 --- a/openbb_sdk/extensions/charting/openbb_charting/charting_router.py +++ b/openbb_sdk/extensions/charting/openbb_charting/charting_router.py @@ -238,6 +238,722 @@ def news_sectornews(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: ) +def providers_benzinga_global_news_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/benzinga/global/news/standardized` does not have a charting function" + ) + + +def providers_benzinga_stock_news_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/benzinga/stock/news/standardized` does not have a charting function" + ) + + +def providers_fmp_key_executives_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/key/executives/standardized` does not have a charting function" + ) + + +def providers_fmp_stock_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/historical/standardized` does not have a charting function" + ) + + +def providers_fmp_global_news_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/global/news/standardized` does not have a charting function" + ) + + +def providers_fmp_stock_news_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/news/standardized` does not have a charting function" + ) + + +def providers_fmp_income_statement_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/income/statement/standardized` does not have a charting function" + ) + + +def providers_fmp_balance_sheet_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/balance/sheet/standardized` does not have a charting function" + ) + + +def providers_fmp_cash_flow_statement_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/cash/flow/statement/standardized` does not have a charting function" + ) + + +def providers_fmp_share_statistics_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/share/statistics/standardized` does not have a charting function" + ) + + +def providers_fmp_major_indices_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/major/indices/historical/standardized` does not have a charting function" + ) + + +def providers_fmp_revenue_geographic_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/revenue/geographic/standardized` does not have a charting function" + ) + + +def providers_fmp_revenue_business_line_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/revenue/business/line/standardized` does not have a charting function" + ) + + +def providers_fmp_institutional_ownership_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/institutional/ownership/standardized` does not have a charting function" + ) + + +def providers_fmp_company_overview_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/company/overview/standardized` does not have a charting function" + ) + + +def providers_fmp_stock_insider_trading_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/insider/trading/standardized` does not have a charting function" + ) + + +def providers_fmp_stock_ownership_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/ownership/standardized` does not have a charting function" + ) + + +def providers_fmp_e_s_g_score_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/e/s/g/score/standardized` does not have a charting function" + ) + + +def providers_fmp_e_s_g_sector_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/e/s/g/sector/standardized` does not have a charting function" + ) + + +def providers_fmp_e_s_g_risk_rating_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/e/s/g/risk/rating/standardized` does not have a charting function" + ) + + +def providers_fmp_stock_price_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/price/standardized` does not have a charting function" + ) + + +def providers_fmp_price_target_consensus_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/price/target/consensus/standardized` does not have a charting function" + ) + + +def providers_fmp_price_target_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/price/target/standardized` does not have a charting function" + ) + + +def providers_fmp_analyst_estimates_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/analyst/estimates/standardized` does not have a charting function" + ) + + +def providers_fmp_earnings_calendar_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/earnings/calendar/standardized` does not have a charting function" + ) + + +def providers_fmp_earnings_call_transcript_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/earnings/call/transcript/standardized` does not have a charting function" + ) + + +def providers_fmp_historical_stock_splits_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/historical/stock/splits/standardized` does not have a charting function" + ) + + +def providers_fmp_historical_dividends_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/historical/dividends/standardized` does not have a charting function" + ) + + +def providers_fmp_key_metrics_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/key/metrics/standardized` does not have a charting function" + ) + + +def providers_fmp_s_e_c_filings_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/s/e/c/filings/standardized` does not have a charting function" + ) + + +def providers_fmp_treasury_rates_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/treasury/rates/standardized` does not have a charting function" + ) + + +def providers_fmp_executive_compensation_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/executive/compensation/standardized` does not have a charting function" + ) + + +def providers_fmp_crypto_price_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/crypto/price/standardized` does not have a charting function" + ) + + +def providers_fmp_crypto_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/crypto/historical/standardized` does not have a charting function" + ) + + +def providers_fmp_major_indices_price_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/major/indices/price/standardized` does not have a charting function" + ) + + +def providers_fmp_forex_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/forex/historical/standardized` does not have a charting function" + ) + + +def providers_polygon_stock_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/stock/historical/standardized` does not have a charting function" + ) + + +def providers_polygon_stock_news_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/stock/news/standardized` does not have a charting function" + ) + + +def providers_polygon_balance_sheet_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/balance/sheet/standardized` does not have a charting function" + ) + + +def providers_polygon_income_statement_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/income/statement/standardized` does not have a charting function" + ) + + +def providers_polygon_cash_flow_statement_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/cash/flow/statement/standardized` does not have a charting function" + ) + + +def providers_polygon_stock_price_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/stock/price/standardized` does not have a charting function" + ) + + +def providers_polygon_crypto_price_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/crypto/price/standardized` does not have a charting function" + ) + + +def providers_polygon_crypto_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/crypto/historical/standardized` does not have a charting function" + ) + + +def providers_polygon_major_indices_historical_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/major/indices/historical/standardized` does not have a charting function" + ) + + +def providers_polygon_major_indices_price_standardized( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/major/indices/price/standardized` does not have a charting function" + ) + + +def providers_benzinga_global_news_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/benzinga/global/news/simple` does not have a charting function" + ) + + +def providers_benzinga_stock_news_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/benzinga/stock/news/simple` does not have a charting function" + ) + + +def providers_fmp_key_executives_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/key/executives/simple` does not have a charting function" + ) + + +def providers_fmp_stock_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/historical/simple` does not have a charting function" + ) + + +def providers_fmp_global_news_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/global/news/simple` does not have a charting function" + ) + + +def providers_fmp_stock_news_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/news/simple` does not have a charting function" + ) + + +def providers_fmp_income_statement_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/income/statement/simple` does not have a charting function" + ) + + +def providers_fmp_balance_sheet_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/balance/sheet/simple` does not have a charting function" + ) + + +def providers_fmp_cash_flow_statement_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/cash/flow/statement/simple` does not have a charting function" + ) + + +def providers_fmp_share_statistics_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/share/statistics/simple` does not have a charting function" + ) + + +def providers_fmp_major_indices_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/major/indices/historical/simple` does not have a charting function" + ) + + +def providers_fmp_revenue_geographic_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/revenue/geographic/simple` does not have a charting function" + ) + + +def providers_fmp_revenue_business_line_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/revenue/business/line/simple` does not have a charting function" + ) + + +def providers_fmp_institutional_ownership_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/institutional/ownership/simple` does not have a charting function" + ) + + +def providers_fmp_company_overview_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/company/overview/simple` does not have a charting function" + ) + + +def providers_fmp_stock_insider_trading_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/insider/trading/simple` does not have a charting function" + ) + + +def providers_fmp_stock_ownership_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/ownership/simple` does not have a charting function" + ) + + +def providers_fmp_e_s_g_score_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/e/s/g/score/simple` does not have a charting function" + ) + + +def providers_fmp_e_s_g_sector_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/e/s/g/sector/simple` does not have a charting function" + ) + + +def providers_fmp_e_s_g_risk_rating_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/e/s/g/risk/rating/simple` does not have a charting function" + ) + + +def providers_fmp_stock_price_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/stock/price/simple` does not have a charting function" + ) + + +def providers_fmp_price_target_consensus_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/price/target/consensus/simple` does not have a charting function" + ) + + +def providers_fmp_price_target_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/price/target/simple` does not have a charting function" + ) + + +def providers_fmp_analyst_estimates_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/analyst/estimates/simple` does not have a charting function" + ) + + +def providers_fmp_earnings_calendar_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/earnings/calendar/simple` does not have a charting function" + ) + + +def providers_fmp_earnings_call_transcript_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/earnings/call/transcript/simple` does not have a charting function" + ) + + +def providers_fmp_historical_stock_splits_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/historical/stock/splits/simple` does not have a charting function" + ) + + +def providers_fmp_historical_dividends_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/historical/dividends/simple` does not have a charting function" + ) + + +def providers_fmp_key_metrics_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/key/metrics/simple` does not have a charting function" + ) + + +def providers_fmp_s_e_c_filings_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/s/e/c/filings/simple` does not have a charting function" + ) + + +def providers_fmp_treasury_rates_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/treasury/rates/simple` does not have a charting function" + ) + + +def providers_fmp_executive_compensation_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/executive/compensation/simple` does not have a charting function" + ) + + +def providers_fmp_crypto_price_simple(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/crypto/price/simple` does not have a charting function" + ) + + +def providers_fmp_crypto_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/crypto/historical/simple` does not have a charting function" + ) + + +def providers_fmp_major_indices_price_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/major/indices/price/simple` does not have a charting function" + ) + + +def providers_fmp_forex_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/fmp/forex/historical/simple` does not have a charting function" + ) + + +def providers_polygon_stock_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/stock/historical/simple` does not have a charting function" + ) + + +def providers_polygon_stock_news_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/stock/news/simple` does not have a charting function" + ) + + +def providers_polygon_balance_sheet_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/balance/sheet/simple` does not have a charting function" + ) + + +def providers_polygon_income_statement_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/income/statement/simple` does not have a charting function" + ) + + +def providers_polygon_cash_flow_statement_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/cash/flow/statement/simple` does not have a charting function" + ) + + +def providers_polygon_stock_price_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/stock/price/simple` does not have a charting function" + ) + + +def providers_polygon_crypto_price_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/crypto/price/simple` does not have a charting function" + ) + + +def providers_polygon_crypto_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/crypto/historical/simple` does not have a charting function" + ) + + +def providers_polygon_major_indices_historical_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/major/indices/historical/simple` does not have a charting function" + ) + + +def providers_polygon_major_indices_price_simple( + **kwargs, +) -> Tuple[OpenBBFigure, Dict[str, Any]]: + raise NotImplementedError( + "Command `providers/polygon/major/indices/price/simple` does not have a charting function" + ) + + def qa_normality(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: raise NotImplementedError( "Command `qa/normality` does not have a charting function" @@ -1026,9 +1742,9 @@ def stocks_options_dte(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: ) -def stocks_options_eodchain(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: +def stocks_options_historicalchain(**kwargs) -> Tuple[OpenBBFigure, Dict[str, Any]]: raise NotImplementedError( - "Command `stocks/options/eodchain` does not have a charting function" + "Command `stocks/options/historicalchain` does not have a charting function" ) diff --git a/openbb_sdk/extensions/crypto/openbb_crypto/crypto_router.py b/openbb_sdk/extensions/crypto/openbb_crypto/crypto_router.py index 21a0024cff5..ac89f01cc92 100644 --- a/openbb_sdk/extensions/crypto/openbb_crypto/crypto_router.py +++ b/openbb_sdk/extensions/crypto/openbb_crypto/crypto_router.py @@ -13,12 +13,12 @@ router = Router(prefix="") # pylint: disable=unused-argument -@router.command(model="CryptoEOD") +@router.command(model="CryptoHistorical") def load( cc: CommandContext, provider_choices: ProviderChoices, standard_params: StandardParams, extra_params: ExtraParams, ) -> OBBject[BaseModel]: - """Crypto EOD Price.""" + """Crypto Historical Price.""" return OBBject(results=Query(**locals()).execute()) diff --git a/openbb_sdk/extensions/economy/openbb_economy/economy_router.py b/openbb_sdk/extensions/economy/openbb_economy/economy_router.py index ed2fd60ffa9..ae483167b06 100644 --- a/openbb_sdk/extensions/economy/openbb_economy/economy_router.py +++ b/openbb_sdk/extensions/economy/openbb_economy/economy_router.py @@ -40,14 +40,36 @@ def cpi( return OBBject(results=Query(**locals()).execute()) -@router.command(model="MajorIndicesEOD") +@router.command(model="MajorIndicesHistorical") def index( cc: CommandContext, provider_choices: ProviderChoices, standard_params: StandardParams, extra_params: ExtraParams, ) -> OBBject[BaseModel]: - """Get OHLCV data for an index.""" + """Get historical levels for an index.""" + return OBBject(results=Query(**locals()).execute()) + + +@router.command(model="EuropeanIndexHistorical") +def european_index( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject[BaseModel]: + """Get historical close values for select European indices.""" + return OBBject(results=Query(**locals()).execute()) + + +@router.command(model="EuropeanIndexConstituents") +def european_index_constituents( + cc: CommandContext, + provider_choices: ProviderChoices, + standard_params: StandardParams, + extra_params: ExtraParams, +) -> OBBject[BaseModel]: + """Get current levels for constituents of select European indices.""" return OBBject(results=Query(**locals()).execute()) @@ -58,7 +80,7 @@ def available_indices( standard_params: StandardParams, extra_params: ExtraParams, ) -> OBBject[BaseModel]: - """AVAILABLE_INDICES.""" + """Lists of available indices from a provider.""" return OBBject(results=Query(**locals()).execute()) diff --git a/openbb_sdk/extensions/forex/openbb_forex/forex_router.py b/openbb_sdk/extensions/forex/openbb_forex/forex_router.py index d82014036ce..28396d45e55 100644 --- a/openbb_sdk/extensions/forex/openbb_forex/forex_router.py +++ b/openbb_sdk/extensions/forex/openbb_forex/forex_router.py @@ -25,7 +25,7 @@ def pairs( # pylint: disable=unused-argument -@router.command(model="ForexEOD") +@router.command(model="ForexHistorical") def load( cc: CommandContext, provider_choices: ProviderChoices, diff --git a/openbb_sdk/extensions/futures/openbb_futures/futures_router.py b/openbb_sdk/extensions/futures/openbb_futures/futures_router.py index cced115f570..ca1da1fd2ea 100644 --- a/openbb_sdk/extensions/futures/openbb_futures/futures_router.py +++ b/openbb_sdk/extensions/futures/openbb_futures/futures_router.py @@ -13,14 +13,14 @@ router = Router(prefix="") # pylint: disable=unused-argument -@router.command(model="FuturesEOD") +@router.command(model="FuturesHistorical") def load( cc: CommandContext, provider_choices: ProviderChoices, standard_params: StandardParams, extra_params: ExtraParams, ) -> OBBject[BaseModel]: - """Futures EOD Price.""" + """Futures Historical Price.""" return OBBject(results=Query(**locals()).execute()) @@ -31,5 +31,5 @@ def curve( standard_params: StandardParams, extra_params: ExtraParams, ) -> OBBject[BaseModel]: - """Futures EOD Price.""" + """Futures Historical Price.""" return OBBject(results=Query(**locals()).execute()) diff --git a/openbb_sdk/extensions/stocks/openbb_stocks/stocks_router.py b/openbb_sdk/extensions/stocks/openbb_stocks/stocks_router.py index a0eca454dba..2783143315c 100644 --- a/openbb_sdk/extensions/stocks/openbb_stocks/stocks_router.py +++ b/openbb_sdk/extensions/stocks/openbb_stocks/stocks_router.py @@ -35,7 +35,7 @@ router.include_router(options_router) # router.include_router(ins_router) -@router.command(model="StockEOD") +@router.command(model="StockHistorical") def load( cc: CommandContext, provider_choices: ProviderChoices, diff --git a/openbb_sdk/openbb/package/__extensions__.py b/openbb_sdk/openbb/package/__extensions__.py index f7de27006cf..b72edde1849 100644 --- a/openbb_sdk/openbb/package/__extensions__.py +++ b/openbb_sdk/openbb/package/__extensions__.py @@ -10,8 +10,11 @@ class Extensions(Container): /economy /fixedincome /forex + /futures /news + /qa /stocks + /ta """ def __repr__(self) -> str: @@ -41,14 +44,32 @@ class Extensions(Container): return forex.CLASS_forex(command_runner=self._command_runner) + @property + def futures(self): # route = "/futures" + from . import futures + + return futures.CLASS_futures(command_runner=self._command_runner) + @property def news(self): # route = "/news" from . import news return news.CLASS_news(command_runner=self._command_runner) + @property + def qa(self): # route = "/qa" + from . import qa + + return qa.CLASS_qa(command_runner=self._command_runner) + @property def stocks(self): # route = "/stocks" from . import stocks return stocks.CLASS_stocks(command_runner=self._command_runner) + + @property + def ta(self): # route = "/ta" + from . import ta + + return ta.CLASS_ta(command_runner=self._command_runner) diff --git a/openbb_sdk/openbb/package/crypto.py b/openbb_sdk/openbb/package/crypto.py index e36cf43bb3d..8a5574dd000 100644 --- a/openbb_sdk/openbb/package/crypto.py +++ b/openbb_sdk/openbb/package/crypto.py @@ -1,14 +1,14 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### import datetime -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import validate_arguments +from typing_extensions import Annotated class CLASS_crypto(Container): @@ -22,27 +22,26 @@ class CLASS_crypto(Container): @validate_arguments def load( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[Literal["fmp", "polygon", "yfinance"]] = None, **kwargs ) -> OBBject[List]: - """Crypto EOD Price. + """Crypto Historical Price. Parameters ---------- @@ -52,13 +51,11 @@ class CLASS_crypto(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'polygon', 'yfinance']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. - timeseries : Union[pydantic.types.NonNegativeInt, NoneType] + timeseries : Optional[pydantic.types.NonNegativeInt] Number of days to look back. (provider: fmp) timespan : Literal['minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'] Timespan of the data. (provider: polygon) @@ -70,13 +67,23 @@ class CLASS_crypto(Container): Whether the data is adjusted. (provider: polygon) multiplier : PositiveInt Multiplier of the timespan. (provider: polygon) + interval : Optional[Literal['1m', '2m', '5m', '15m', '30m', '60m', '90m', '1h', '1d', '5d', '1wk', '1mo', '3mo']] + Data granularity. (provider: yfinance) + period : Optional[Literal['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']] + Period of the data to return. (provider: yfinance) + prepost : bool + Include Pre and Post market data. (provider: yfinance) + adjust : bool + Adjust all the data automatically. (provider: yfinance) + back_adjust : bool + Back-adjusted data to mimic true historical prices. (provider: yfinance) Returns ------- OBBject - results : List[CryptoEOD] + results : List[CryptoHistorical] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -85,8 +92,8 @@ class CLASS_crypto(Container): metadata: Optional[Metadata] Metadata info about the command execution. - CryptoEOD - --------- + CryptoHistorical + ---------------- date : Optional[datetime] The date of the data. open : Optional[PositiveFloat] @@ -127,7 +134,6 @@ class CLASS_crypto(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/economy.py b/openbb_sdk/openbb/package/economy.py index b8a6d0a8720..30c962f2726 100644 --- a/openbb_sdk/openbb/package/economy.py +++ b/openbb_sdk/openbb/package/economy.py @@ -1,14 +1,14 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### import datetime -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import validate_arguments +from typing_extensions import Annotated class CLASS_economy(Container): @@ -16,6 +16,8 @@ class CLASS_economy(Container): available_indices const cpi + european_index + european_index_constituents index risk """ @@ -25,28 +27,25 @@ class CLASS_economy(Container): @validate_arguments def available_indices( - self, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, - **kwargs + self, provider: Optional[Literal["cboe", "fmp", "yfinance"]] = None, **kwargs ) -> OBBject[List]: - """AVAILABLE_INDICES. + """Lists of available indices from a provider. Parameters ---------- - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['cboe', 'fmp', 'yfinance']] The provider to use for the query, by default None. - If None, the provider specified in defaults is selected or 'fmp' if there is + If None, the provider specified in defaults is selected or 'cboe' if there is no default. + europe : bool + Filter for European indices. False for US indices. (provider: cboe) Returns ------- OBBject results : List[AvailableIndices] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['cboe', 'fmp', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -57,16 +56,38 @@ class CLASS_economy(Container): AvailableIndices ---------------- - symbol : Optional[str] - Symbol to get data for. name : Optional[str] Name of the index. currency : Optional[str] Currency the index is traded in. + isin : Optional[str] + ISIN code for the index. Valid only for European indices. (provider: cboe) + region : Optional[str] + Region for the index. Valid only for European indices (provider: cboe) + symbol : Optional[str] + Symbol for the index. (provider: cboe) + description : Optional[str] + Description for the index. Valid only for US indices. (provider: cboe) + data_delay : Optional[int] + Data delay for the index. Valid only for US indices. (provider: cboe) + open_time : Optional[time] + Opening time for the index. Valid only for US indices. (provider: cboe) + close_time : Optional[time] + Closing time for the index. Valid only for US indices. (provider: cboe) + time_zone : Optional[str] + Time zone for the index. Valid only for US indices. (provider: cboe) + tick_days : Optional[str] + The trading days for the index. Valid only for US indices. (provider: cboe) + tick_frequency : Optional[str] + The frequency of the index ticks. Valid only for US indices. (provider: cboe) + tick_period : Optional[str] + The period of the index ticks. Valid only for US indices. (provider: cboe) stock_exchange : Optional[str] - Stock exchange where the index is listed. + Stock exchange where the index is listed. (provider: fmp) exchange_short_name : Optional[str] - Short name of the stock exchange where the index is listed.""" # noqa: E501 + Short name of the stock exchange where the index is listed. (provider: fmp) + code : Optional[str] + ID code for keying the index in the OpenBB Terminal. (provider: yfinance)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -74,7 +95,6 @@ class CLASS_economy(Container): }, standard_params={}, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -85,14 +105,13 @@ class CLASS_economy(Container): @validate_arguments def const( self, - index: typing_extensions.Annotated[ + index: Annotated[ Literal["nasdaq", "sp500", "dowjones"], OpenBBCustomParameter( description="Index for which we want to fetch the constituents." ), ] = "dowjones", - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Get the constituents of an index. @@ -101,9 +120,7 @@ class CLASS_economy(Container): ---------- index : Literal['nasdaq', 'sp500', 'dowjones'] Index for which we want to fetch the constituents. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -113,7 +130,7 @@ class CLASS_economy(Container): OBBject results : List[MajorIndicesConstituents] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -149,7 +166,6 @@ class CLASS_economy(Container): "index": index, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -160,7 +176,7 @@ class CLASS_economy(Container): @validate_arguments def cpi( self, - countries: typing_extensions.Annotated[ + countries: Annotated[ List[ Literal[ "australia", @@ -216,34 +232,33 @@ class CLASS_economy(Container): ], OpenBBCustomParameter(description="The country or countries to get data."), ], - units: typing_extensions.Annotated[ + units: Annotated[ Literal["growth_previous", "growth_same", "index_2015"], OpenBBCustomParameter(description="The data units."), ] = "growth_same", - frequency: typing_extensions.Annotated[ + frequency: Annotated[ Literal["monthly", "quarter", "annual"], OpenBBCustomParameter(description="The data time frequency."), ] = "monthly", - harmonized: typing_extensions.Annotated[ + harmonized: Annotated[ bool, OpenBBCustomParameter( description="Whether you wish to obtain harmonized data." ), ] = False, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """CPI. @@ -262,9 +277,7 @@ class CLASS_economy(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -274,7 +287,7 @@ class CLASS_economy(Container): OBBject results : List[CPI] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -307,7 +320,6 @@ class CLASS_economy(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -316,29 +328,28 @@ class CLASS_economy(Container): ) @validate_arguments - def index( + def european_index( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[Literal["cboe"]] = None, **kwargs ) -> OBBject[List]: - """Get OHLCV data for an index. + """Get historical close values for select European indices. Parameters ---------- @@ -348,16 +359,182 @@ class CLASS_economy(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['cboe']] The provider to use for the query, by default None. - If None, the provider specified in defaults is selected or 'fmp' if there is + If None, the provider specified in defaults is selected or 'cboe' if there is no default. - timeseries : Union[pydantic.types.NonNegativeInt, NoneType] + interval : Optional[Literal['1d', '1m']] + Use interval, 1m, for intraday prices during the most recent trading period. (provider: cboe) + + Returns + ------- + OBBject + results : List[EuropeanIndexHistorical] + Serializable results. + provider : Optional[Literal['cboe']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + EuropeanIndexHistorical + ----------------------- + date : Union[date, datetime] + The date of the data. + close : Optional[float] + The close price of the symbol. + open : Optional[float] + Opening price for the interval. Only valid when interval is 1m. (provider: cboe) + high : Optional[float] + High price for the interval. Only valid when interval is 1m. (provider: cboe) + low : Optional[float] + Low price for the interval. Only valid when interval is 1m. (provider: cboe) + utc_datetime : Optional[datetime] + UTC datetime. Only valid when interval is 1m. (provider: cboe)""" # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, + "start_date": start_date, + "end_date": end_date, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/economy/european_index", + **inputs, + ) + + @validate_arguments + def european_index_constituents( + self, + symbol: Annotated[ + Union[str, List[str]], + OpenBBCustomParameter(description="Symbol to get data for."), + ], + provider: Optional[Literal["cboe"]] = None, + **kwargs + ) -> OBBject[List]: + """Get current levels for constituents of select European indices. + + Parameters + ---------- + symbol : Union[str, List[str]] + Symbol to get data for. + provider : Optional[Literal['cboe']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'cboe' if there is + no default. + + Returns + ------- + OBBject + results : List[EuropeanIndexConstituents] + Serializable results. + provider : Optional[Literal['cboe']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + EuropeanIndexConstituents + ------------------------- + symbol : Optional[str] + Symbol of the constituent company in the index. + price : Optional[float] + Current price of the constituent company in the index. + open : Optional[float] + The open price of the symbol. + high : Optional[float] + The high price of the symbol. + low : Optional[float] + The low price of the symbol. + close : Optional[float] + The close price of the symbol. + volume : Optional[float] + The volume of the symbol. + prev_close : Optional[float] + Previous closing price. (provider: cboe) + change : Optional[float] + Change in price. (provider: cboe) + change_percent : Optional[float] + Change in price as a percentage. (provider: cboe) + tick : Optional[str] + Whether the last sale was an up or down tick. (provider: cboe) + last_trade_timestamp : Optional[datetime] + Last trade timestamp for the symbol. (provider: cboe) + exchange_id : Optional[int] + The Exchange ID number. (provider: cboe) + seqno : Optional[int] + Sequence number of the last trade on the tape. (provider: cboe) + asset_type : Optional[str] + Type of asset. (provider: cboe)""" # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/economy/european_index_constituents", + **inputs, + ) + + @validate_arguments + def index( + self, + symbol: Annotated[ + Union[str, List[str]], + OpenBBCustomParameter(description="Symbol to get data for."), + ], + start_date: Annotated[ + Union[datetime.date, None, str], + OpenBBCustomParameter( + description="Start date of the data, in YYYY-MM-DD format." + ), + ] = None, + end_date: Annotated[ + Union[datetime.date, None, str], + OpenBBCustomParameter( + description="End date of the data, in YYYY-MM-DD format." + ), + ] = None, + provider: Optional[Literal["cboe", "fmp", "polygon", "yfinance"]] = None, + **kwargs + ) -> OBBject[List]: + """Get historical levels for an index. + + Parameters + ---------- + symbol : Union[str, List[str]] + Symbol to get data for. + start_date : Union[datetime.date, NoneType, str] + Start date of the data, in YYYY-MM-DD format. + end_date : Union[datetime.date, NoneType, str] + End date of the data, in YYYY-MM-DD format. + provider : Optional[Literal['cboe', 'fmp', 'polygon', 'yfinance']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'cboe' if there is + no default. + interval : Union[Literal['1d', '1m'], NoneType, Literal['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'], Literal['1m', '2m', '5m', '15m', '30m', '60m', '90m', '1h', '1d', '5d', '1wk', '1mo', '3mo']] + None + timeseries : Optional[pydantic.types.NonNegativeInt] Number of days to look back. (provider: fmp) - interval : Literal['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'] - Interval of the data to fetch. (provider: fmp) timespan : Literal['minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'] Timespan of the data. (provider: polygon) sort : Literal['asc', 'desc'] @@ -368,13 +545,21 @@ class CLASS_economy(Container): Whether the data is adjusted. (provider: polygon) multiplier : PositiveInt Multiplier of the timespan. (provider: polygon) + period : Optional[Literal['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']] + Period of the data to return. (provider: yfinance) + prepost : bool + Include Pre and Post market data. (provider: yfinance) + adjust : bool + Adjust all the data automatically. (provider: yfinance) + back_adjust : bool + Back-adjusted data to mimic true historical prices. (provider: yfinance) Returns ------- OBBject - results : List[MajorIndicesEOD] + results : List[MajorIndicesHistorical] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['cboe', 'fmp', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -383,8 +568,8 @@ class CLASS_economy(Container): metadata: Optional[Metadata] Metadata info about the command execution. - MajorIndicesEOD - --------------- + MajorIndicesHistorical + ---------------------- date : Optional[datetime] The date of the data. open : Optional[PositiveFloat] @@ -395,10 +580,14 @@ class CLASS_economy(Container): The low price of the symbol. close : Optional[PositiveFloat] The close price of the symbol. - volume : Optional[float] + volume : Optional[NonNegativeInt] The volume of the symbol. - vwap : Optional[float] - Volume Weighted Average Price of the symbol. + calls_volume : Optional[float] + Number of calls traded during the most recent trading period. Only valid if interval is 1m. (provider: cboe) + puts_volume : Optional[float] + Number of puts traded during the most recent trading period. Only valid if interval is 1m. (provider: cboe) + total_options_volume : Optional[float] + Total number of options traded during the most recent trading period. Only valid if interval is 1m. (provider: cboe) adj_close : Optional[float] Adjusted Close Price of the symbol. (provider: fmp) unadjusted_volume : Optional[float] @@ -411,8 +600,6 @@ class CLASS_economy(Container): Human readable format of the date. (provider: fmp) change_over_time : Optional[float] Change \\% in the price of the symbol over a period of time. (provider: fmp) - n : Optional[PositiveInt] - Number of transactions for the symbol in the time period. (provider: polygon) """ # noqa: E501 inputs = filter_inputs( @@ -425,7 +612,6 @@ class CLASS_economy(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -435,18 +621,13 @@ class CLASS_economy(Container): @validate_arguments def risk( - self, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, - **kwargs + self, provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Market Risk Premium. Parameters ---------- - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -456,7 +637,7 @@ class CLASS_economy(Container): OBBject results : List[RiskPremium] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -482,7 +663,6 @@ class CLASS_economy(Container): }, standard_params={}, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/extension_map.json b/openbb_sdk/openbb/package/extension_map.json index 508b6e9bfa8..bfff08afd9a 100644 --- a/openbb_sdk/openbb/package/extension_map.json +++ b/openbb_sdk/openbb/package/extension_map.json @@ -4,13 +4,22 @@ "economy@0.1.0", "fixedincome@0.1.0", "forex@0.1.0", + "futures@0.1.0", "news@0.1.0", - "stocks@0.1.0" + "openbb_charting@0.1.0", + "qa@0.1.0", + "stocks@0.1.0", + "ta@0.1.0" ], "openbb_provider_extension": [ + "alpha_vantage@0.1.0", "benzinga@0.1.0", + "cboe@0.1.0", "fmp@0.1.0", "fred@0.1.0", - "polygon@0.1.0" + "intrinio@0.1.0", + "polygon@0.1.0", + "quandl@0.1.0", + "yfinance@0.1.0" ] } \ No newline at end of file diff --git a/openbb_sdk/openbb/package/fixedincome.py b/openbb_sdk/openbb/package/fixedincome.py index 51bbcd86225..c1854d40f13 100644 --- a/openbb_sdk/openbb/package/fixedincome.py +++ b/openbb_sdk/openbb/package/fixedincome.py @@ -1,14 +1,14 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### import datetime -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import validate_arguments +from typing_extensions import Annotated class CLASS_fixedincome(Container): @@ -30,20 +30,19 @@ class CLASS_fixedincome(Container): @validate_arguments def ameribor( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """ @@ -57,9 +56,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -71,7 +68,7 @@ class CLASS_fixedincome(Container): OBBject results : List[AMERIBOR] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -96,7 +93,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -107,20 +103,19 @@ class CLASS_fixedincome(Container): @validate_arguments def estr( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """ @@ -135,9 +130,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -149,7 +142,7 @@ class CLASS_fixedincome(Container): OBBject results : List[ESTR] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -174,7 +167,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -185,20 +177,19 @@ class CLASS_fixedincome(Container): @validate_arguments def fed( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """ @@ -213,9 +204,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -227,7 +216,7 @@ class CLASS_fixedincome(Container): OBBject results : List[FEDFUNDS] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -252,7 +241,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -263,20 +251,19 @@ class CLASS_fixedincome(Container): @validate_arguments def iorb( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """ @@ -291,9 +278,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -303,7 +288,7 @@ class CLASS_fixedincome(Container): OBBject results : List[IORB] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -328,7 +313,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -338,10 +322,7 @@ class CLASS_fixedincome(Container): @validate_arguments def projections( - self, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, - **kwargs + self, provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """ Get Effective Federal Funds Rate data. A bank rate is the interest rate a nation's central bank charges to its @@ -351,9 +332,7 @@ class CLASS_fixedincome(Container): Parameters ---------- - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -365,7 +344,7 @@ class CLASS_fixedincome(Container): OBBject results : List[PROJECTIONS] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -399,7 +378,6 @@ class CLASS_fixedincome(Container): }, standard_params={}, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -410,20 +388,19 @@ class CLASS_fixedincome(Container): @validate_arguments def sofr( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """Get United States yield curve. @@ -434,9 +411,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -448,7 +423,7 @@ class CLASS_fixedincome(Container): OBBject results : List[SOFR] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -473,7 +448,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -484,20 +458,19 @@ class CLASS_fixedincome(Container): @validate_arguments def sonia( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """ @@ -511,9 +484,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -525,7 +496,7 @@ class CLASS_fixedincome(Container): OBBject results : List[SONIA] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -550,7 +521,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -561,20 +531,19 @@ class CLASS_fixedincome(Container): @validate_arguments def treasury( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Get treasury rates. @@ -585,9 +554,7 @@ class CLASS_fixedincome(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -597,7 +564,7 @@ class CLASS_fixedincome(Container): OBBject results : List[TreasuryRates] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -644,7 +611,6 @@ class CLASS_fixedincome(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -655,31 +621,28 @@ class CLASS_fixedincome(Container): @validate_arguments def ycrv( self, - date: typing_extensions.Annotated[ - Union[datetime.date, None], + date: Annotated[ + Optional[datetime.date], OpenBBCustomParameter( description="Date to get Yield Curve data. Defaults to the most recent FRED entry." ), ] = None, - inflation_adjusted: typing_extensions.Annotated[ - Union[bool, None], + inflation_adjusted: Annotated[ + Optional[bool], OpenBBCustomParameter(description="Get inflation adjusted rates."), ] = False, - chart: bool = False, - provider: Union[Literal["fred"], None] = None, + provider: Optional[Literal["fred"]] = None, **kwargs ) -> OBBject[List]: """Get United States yield curve. Parameters ---------- - date : Union[datetime.date, NoneType] + date : Optional[datetime.date] Date to get Yield Curve data. Defaults to the most recent FRED entry. - inflation_adjusted : Union[bool, NoneType] + inflation_adjusted : Optional[bool] Get inflation adjusted rates. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fred' if there is no default. @@ -689,7 +652,7 @@ class CLASS_fixedincome(Container): OBBject results : List[USYieldCurve] Serializable results. - provider : Union[Literal['fred'], NoneType] + provider : Optional[Literal['fred']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -714,7 +677,6 @@ class CLASS_fixedincome(Container): "inflation_adjusted": inflation_adjusted, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/forex.py b/openbb_sdk/openbb/package/forex.py index d40e096f622..8f065eba540 100644 --- a/openbb_sdk/openbb/package/forex.py +++ b/openbb_sdk/openbb/package/forex.py @@ -1,14 +1,14 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### import datetime -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import validate_arguments +from typing_extensions import Annotated class CLASS_forex(Container): @@ -23,24 +23,23 @@ class CLASS_forex(Container): @validate_arguments def load( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[Literal["fmp", "polygon", "yfinance"]] = None, **kwargs ) -> OBBject[List]: """Forex Intraday Price. @@ -53,9 +52,7 @@ class CLASS_forex(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'polygon', 'yfinance']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -69,13 +66,23 @@ class CLASS_forex(Container): Whether the data is adjusted. (provider: polygon) multiplier : PositiveInt Multiplier of the timespan. (provider: polygon) + interval : Optional[Literal['1m', '2m', '5m', '15m', '30m', '60m', '90m', '1h', '1d', '5d', '1wk', '1mo', '3mo']] + Data granularity. (provider: yfinance) + period : Optional[Literal['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']] + Period of the data to return. (provider: yfinance) + prepost : bool + Include Pre and Post market data. (provider: yfinance) + adjust : bool + Adjust all the data automatically. (provider: yfinance) + back_adjust : bool + Back-adjusted data to mimic true historical prices. (provider: yfinance) Returns ------- OBBject - results : List[ForexEOD] + results : List[ForexHistorical] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -84,8 +91,8 @@ class CLASS_forex(Container): metadata: Optional[Metadata] Metadata info about the command execution. - ForexEOD - -------- + ForexHistorical + --------------- date : Optional[datetime] The date of the data. open : Optional[PositiveFloat] @@ -126,7 +133,6 @@ class CLASS_forex(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -136,34 +142,29 @@ class CLASS_forex(Container): @validate_arguments def pairs( - self, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, - **kwargs + self, provider: Optional[Literal["fmp", "intrinio", "polygon"]] = None, **kwargs ) -> OBBject[List]: """Forex Available Pairs. Parameters ---------- - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. - symbol : Union[str, NoneType] + symbol : Optional[str] Symbol of the pair to search. (provider: polygon) - date : Union[datetime.date, NoneType] + date : Optional[datetime.date] A specific date to get data for. (provider: polygon) - search : Union[str, NoneType] + search : Optional[str] Search for terms within the ticker and/or company name. (provider: polygon) - active : Union[Literal[True, False], NoneType] + active : Optional[Literal[True, False]] Specify if the tickers returned should be actively traded on the queried date. (provider: polygon) - order : Union[Literal['asc', 'desc'], NoneType] + order : Optional[Literal['asc', 'desc']] Order data by ascending or descending. (provider: polygon) - sort : Union[Literal['ticker', 'name', 'market', 'locale', 'currency_symbol', 'currency_name', 'base_currency_symbol', 'base_currency_name', 'last_updated_utc', 'delisted_utc'], NoneType] + sort : Optional[Literal['ticker', 'name', 'market', 'locale', 'currency_symbol', 'currency_name', 'base_currency_symbol', 'base_currency_name', 'last_updated_utc', 'delisted_utc']] Sort field used for ordering. (provider: polygon) - limit : Union[pydantic.types.PositiveInt, NoneType] + limit : Optional[pydantic.types.PositiveInt] The number of data entries to return. (provider: polygon) Returns @@ -171,7 +172,7 @@ class CLASS_forex(Container): OBBject results : List[ForexPairs] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -192,6 +193,12 @@ class CLASS_forex(Container): Stock exchange of the currency pair. (provider: fmp) exchange_short_name : Optional[str] Short name of the stock exchange of the currency pair. (provider: fmp) + code : Optional[str] + Code of the currency pair. (provider: intrinio) + base_currency : Optional[str] + ISO 4217 currency code of the base currency. (provider: intrinio) + quote_currency : Optional[str] + ISO 4217 currency code of the quote currency. (provider: intrinio) market : Optional[str] The name of the trading market. Always 'fx'. (provider: polygon) locale : Optional[str] @@ -215,7 +222,6 @@ class CLASS_forex(Container): }, standard_params={}, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/futures.py b/openbb_sdk/openbb/package/futures.py new file mode 100644 index 00000000000..b5ffdb711e7 --- /dev/null +++ b/openbb_sdk/openbb/package/futures.py @@ -0,0 +1,187 @@ +### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### + +import datetime +from typing import List, Literal, Optional, Union + +from openbb_core.app.model.custom_parameter import OpenBBCustomParameter +from openbb_core.app.model.obbject import OBBject +from openbb_core.app.static.container import Container +from openbb_core.app.static.filters import filter_inputs +from pydantic import validate_arguments +from typing_extensions import Annotated + + +class CLASS_futures(Container): + """/futures + curve + load + """ + + def __repr__(self) -> str: + return self.__doc__ or "" + + @validate_arguments + def curve( + self, + symbol: Annotated[ + Union[str, List[str]], + OpenBBCustomParameter(description="Symbol to get data for."), + ], + date: Annotated[ + Optional[datetime.date], + OpenBBCustomParameter(description="Historical date to search curve for."), + ] = None, + provider: Optional[Literal["cboe", "yfinance"]] = None, + **kwargs + ) -> OBBject[List]: + """Futures Historical Price. + + Parameters + ---------- + symbol : Union[str, List[str]] + Symbol to get data for. + date : Optional[datetime.date] + Historical date to search curve for. + provider : Optional[Literal['cboe', 'yfinance']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'cboe' if there is + no default. + + Returns + ------- + OBBject + results : List[FuturesCurve] + Serializable results. + provider : Optional[Literal['cboe', 'yfinance']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + FuturesCurve + ------------ + expiration : Optional[str] + Futures expiration month. + price : Optional[float] + The close price of the symbol. + symbol : Optional[str] + The trading symbol for the tenor of future. (provider: cboe)""" # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, + "date": date, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/futures/curve", + **inputs, + ) + + @validate_arguments + def load( + self, + symbol: Annotated[ + Union[str, List[str]], + OpenBBCustomParameter(description="Symbol to get data for."), + ], + start_date: Annotated[ + Union[datetime.date, None, str], + OpenBBCustomParameter( + description="Start date of the data, in YYYY-MM-DD format." + ), + ] = None, + end_date: Annotated[ + Union[datetime.date, None, str], + OpenBBCustomParameter( + description="End date of the data, in YYYY-MM-DD format." + ), + ] = None, + expiration: Annotated[ + Optional[str], + OpenBBCustomParameter(description="Future expiry date with format YYYY-MM"), + ] = None, + provider: Optional[Literal["yfinance"]] = None, + **kwargs + ) -> OBBject[List]: + """Futures Historical Price. + + Parameters + ---------- + symbol : Union[str, List[str]] + Symbol to get data for. + start_date : Union[datetime.date, NoneType, str] + Start date of the data, in YYYY-MM-DD format. + end_date : Union[datetime.date, NoneType, str] + End date of the data, in YYYY-MM-DD format. + expiration : Optional[str] + Future expiry date with format YYYY-MM + provider : Optional[Literal['yfinance']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'yfinance' if there is + no default. + interval : Optional[Literal['1m', '2m', '5m', '15m', '30m', '60m', '90m', '1h', '1d', '5d', '1wk', '1mo', '3mo']] + Data granularity. (provider: yfinance) + period : Optional[Literal['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max']] + Period of the data to return. (provider: yfinance) + prepost : bool + Include Pre and Post market data. (provider: yfinance) + adjust : bool + Adjust all the data automatically. (provider: yfinance) + back_adjust : bool + Back-adjusted data to mimic true historical prices. (provider: yfinance) + + Returns + ------- + OBBject + results : List[FuturesHistorical] + Serializable results. + provider : Optional[Literal['yfinance']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + FuturesHistorical + ----------------- + date : Optional[datetime] + The date of the data. + open : Optional[float] + The open price of the symbol. + high : Optional[float] + The high price of the symbol. + low : Optional[float] + The low price of the symbol. + close : Optional[float] + The close price of the symbol. + volume : Optional[float] + The volume of the symbol.""" # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, + "start_date": start_date, + "end_date": end_date, + "expiration": expiration, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/futures/load", + **inputs, + ) diff --git a/openbb_sdk/openbb/package/module_map.json b/openbb_sdk/openbb/package/module_map.json index baff015a4b9..a75cc7694c9 100644 --- a/openbb_sdk/openbb/package/module_map.json +++ b/openbb_sdk/openbb/package/module_map.json @@ -6,6 +6,8 @@ "economy_available_indices": "/economy/available_indices", "economy_const": "/economy/const", "economy_cpi": "/economy/cpi", + "economy_european_index": "/economy/european_index", + "economy_european_index_constituents": "/economy/european_index_constituents", "economy_index": "/economy/index", "economy_risk": "/economy/risk", "fixedincome": "/fixedincome", @@ -21,8 +23,22 @@ "forex": "/forex", "forex_load": "/forex/load", "forex_pairs": "/forex/pairs", + "futures": "/futures", + "futures_curve": "/futures/curve", + "futures_load": "/futures/load", "news": "/news", "news_globalnews": "/news/globalnews", + "qa": "/qa", + "qa_capm": "/qa/capm", + "qa_kurtosis": "/qa/kurtosis", + "qa_normality": "/qa/normality", + "qa_om": "/qa/om", + "qa_quantile": "/qa/quantile", + "qa_sh": "/qa/sh", + "qa_skew": "/qa/skew", + "qa_so": "/qa/so", + "qa_summary": "/qa/summary", + "qa_unitroot": "/qa/unitroot", "stocks": "/stocks", "stocks_ca": "/stocks/ca", "stocks_ca_peers": "/stocks/ca/peers", @@ -56,8 +72,39 @@ "stocks_fa_shrs": "/stocks/fa/shrs", "stocks_fa_split": "/stocks/fa/split", "stocks_fa_transcript": "/stocks/fa/transcript", + "stocks_info": "/stocks/info", "stocks_load": "/stocks/load", "stocks_multiples": "/stocks/multiples", "stocks_news": "/stocks/news", - "stocks_quote": "/stocks/quote" + "stocks_options": "/stocks/options", + "stocks_options_chains": "/stocks/options/chains", + "stocks_quote": "/stocks/quote", + "stocks_search": "/stocks/search", + "ta": "/ta", + "ta_ad": "/ta/ad", + "ta_adosc": "/ta/adosc", + "ta_adx": "/ta/adx", + "ta_aroon": "/ta/aroon", + "ta_atr": "/ta/atr", + "ta_bbands": "/ta/bbands", + "ta_cci": "/ta/cci", + "ta_cg": "/ta/cg", + "ta_clenow": "/ta/clenow", + "ta_cones": "/ta/cones", + "ta_demark": "/ta/demark", + "ta_donchian": "/ta/donchian", + "ta_ema": "/ta/ema", + "ta_fib": "/ta/fib", + "ta_fisher": "/ta/fisher", + "ta_hma": "/ta/hma", + "ta_ichimoku": "/ta/ichimoku", + "ta_kc": "/ta/kc", + "ta_macd": "/ta/macd", + "ta_obv": "/ta/obv", + "ta_rsi": "/ta/rsi", + "ta_sma": "/ta/sma", + "ta_stoch": "/ta/stoch", + "ta_vwap": "/ta/vwap", + "ta_wma": "/ta/wma", + "ta_zlma": "/ta/zlma" } \ No newline at end of file diff --git a/openbb_sdk/openbb/package/news.py b/openbb_sdk/openbb/package/news.py index 675b4abfaa6..3e72297931b 100644 --- a/openbb_sdk/openbb/package/news.py +++ b/openbb_sdk/openbb/package/news.py @@ -1,14 +1,14 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### -from typing import List, Literal, Union +from typing import List, Literal, Optional import pydantic -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import validate_arguments +from typing_extensions import Annotated class CLASS_news(Container): @@ -22,12 +22,11 @@ class CLASS_news(Container): @validate_arguments def globalnews( self, - page: typing_extensions.Annotated[ + page: Annotated[ pydantic.types.NonNegativeInt, OpenBBCustomParameter(description="Page of the global news."), ] = 0, - chart: bool = False, - provider: Union[Literal["benzinga", "fmp"], None] = None, + provider: Optional[Literal["benzinga", "fmp", "intrinio"]] = None, **kwargs ) -> OBBject[List]: """Global News. @@ -36,9 +35,7 @@ class CLASS_news(Container): ---------- page : NonNegativeInt Page of the global news. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['benzinga', 'fmp'], NoneType] + provider : Optional[Literal['benzinga', 'fmp', 'intrinio']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'benzinga' if there is no default. @@ -46,39 +43,45 @@ class CLASS_news(Container): Number of results to return per page. (provider: benzinga) display_output : Literal['headline', 'summary', 'full', 'all'] Type of data to return. (provider: benzinga) - date : Union[datetime.datetime, NoneType] + date : Optional[datetime.datetime] Date of the news to retrieve. (provider: benzinga) - date_from : Union[datetime.datetime, NoneType] + date_from : Optional[datetime.datetime] Start date of the news to retrieve. (provider: benzinga) - date_to : Union[datetime.datetime, NoneType] + date_to : Optional[datetime.datetime] End date of the news to retrieve. (provider: benzinga) - updated_since : Union[int, NoneType] + updated_since : Optional[int] Number of seconds since the news was updated. (provider: benzinga) - published_since : Union[int, NoneType] + published_since : Optional[int] Number of seconds since the news was published. (provider: benzinga) - sort : Union[Literal['published_at', 'updated_at', 'title', 'author', 'channel', 'ticker', 'topic', 'content_type'], NoneType] + sort : Optional[Literal['published_at', 'updated_at', 'title', 'author', 'channel', 'ticker', 'topic', 'content_type']] Order in which to sort the news. (provider: benzinga) - isin : Union[str, NoneType] + isin : Optional[str] The ISIN of the news to retrieve. (provider: benzinga) - cusip : Union[str, NoneType] + cusip : Optional[str] The CUSIP of the news to retrieve. (provider: benzinga) - tickers : Union[str, NoneType] + tickers : Optional[str] Tickers of the news to retrieve. (provider: benzinga) - channels : Union[str, NoneType] + channels : Optional[str] Channels of the news to retrieve. (provider: benzinga) - topics : Union[str, NoneType] + topics : Optional[str] Topics of the news to retrieve. (provider: benzinga) - authors : Union[str, NoneType] + authors : Optional[str] Authors of the news to retrieve. (provider: benzinga) - content_types : Union[str, NoneType] + content_types : Optional[str] Content types of the news to retrieve. (provider: benzinga) + next_page : str + Token to get the next page of data from a previous API call. (provider: intrinio) + limit : Optional[int] + The number of data entries to return. (provider: intrinio) + all_pages : Optional[bool] + Returns all pages of data from the API call at once. (provider: intrinio) Returns ------- OBBject results : List[GlobalNews] Serializable results. - provider : Union[Literal['benzinga', 'fmp'], NoneType] + provider : Optional[Literal['benzinga', 'fmp', 'intrinio']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -108,7 +111,11 @@ class CLASS_news(Container): teaser : Optional[str] Teaser of the news. (provider: benzinga) site : Optional[str] - Site of the news. (provider: fmp)""" # noqa: E501 + Site of the news. (provider: fmp) + id : Optional[str] + Intrinio ID for the news article. (provider: intrinio) + company : Optional[Mapping[str, Any]] + Company details related to the news article. (provider: intrinio)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -118,7 +125,6 @@ class CLASS_news(Container): "page": page, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/qa.py b/openbb_sdk/openbb/package/qa.py new file mode 100644 index 00000000000..93b458a101a --- /dev/null +++ b/openbb_sdk/openbb/package/qa.py @@ -0,0 +1,375 @@ +### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### + +from typing import List, Literal, Union + +import openbb_provider +import openbb_qa.qa_models +import pandas +import pydantic +import pydantic.types +from openbb_core.app.model.obbject import OBBject +from openbb_core.app.static.container import Container +from openbb_core.app.static.filters import filter_inputs +from pydantic import validate_arguments + + +class CLASS_qa(Container): + """/qa + capm + kurtosis + normality + om + quantile + sh + skew + so + summary + unitroot + """ + + def __repr__(self) -> str: + return self.__doc__ or "" + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def capm( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + ) -> OBBject[openbb_qa.qa_models.CAPMModel]: + """Capital Asset Pricing Model.""" # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + ) + + return self._command_runner.run( + "/qa/capm", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def kurtosis( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + window: pydantic.types.PositiveInt, + ) -> OBBject[List]: + """Kurtosis. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + window : PositiveInt + Window size. + + Returns + ------- + OBBject[List[Data]] + Kurtosis. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + window=window, + ) + + return self._command_runner.run( + "/qa/kurtosis", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def normality( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + ) -> OBBject[openbb_qa.qa_models.NormalityModel]: + """ + Normality Statistics. + + - **Kurtosis**: whether the kurtosis of a sample differs from the normal distribution. + - **Skewness**: whether the skewness of a sample differs from the normal distribution. + - **Jarque-Bera**: whether the sample data has the skewness and kurtosis matching a normal distribution. + - **Shapiro-Wilk**: whether a random sample comes from a normal distribution. + - **Kolmogorov-Smirnov**: whether two underlying one-dimensional probability distributions differ. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + + Returns + ------- + OBBject[NormalityModel] + Normality tests summary. See qa_models.NormalityModel for details. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + ) + + return self._command_runner.run( + "/qa/normality", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def om( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + threshold_start: float = 0.0, + threshold_end: float = 1.5, + ) -> OBBject[List]: + """Omega Ratio. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + threshold_start : float, optional + Start threshold, by default 0.0 + threshold_end : float, optional + End threshold, by default 1.5 + + Returns + ------- + OBBject[List[OmegaModel]] + Omega ratios. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + threshold_start=threshold_start, + threshold_end=threshold_end, + ) + + return self._command_runner.run( + "/qa/om", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def quantile( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + window: pydantic.types.PositiveInt, + quantile_pct: pydantic.types.NonNegativeFloat = 0.5, + ) -> OBBject[List]: + """Quantile.""" # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + window=window, + quantile_pct=quantile_pct, + ) + + return self._command_runner.run( + "/qa/quantile", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def sh( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + rfr: float = 0.0, + window: pydantic.types.PositiveInt = 252, + ) -> OBBject[List]: + """Sharpe Ratio. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + rfr : float, optional + Risk-free rate, by default 0.0 + window : PositiveInt, optional + Window size, by default 252 + + Returns + ------- + OBBject[List[Data]] + Sharpe ratio. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + rfr=rfr, + window=window, + ) + + return self._command_runner.run( + "/qa/sh", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def skew( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + window: pydantic.types.PositiveInt, + ) -> OBBject[List]: + """Skewness. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + window : PositiveInt + Window size. + + Returns + ------- + OBBject[List[Data]] + Skewness. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + window=window, + ) + + return self._command_runner.run( + "/qa/skew", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def so( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + target_return: float = 0.0, + window: pydantic.types.PositiveInt = 252, + adjusted: bool = False, + ) -> OBBject[List]: + """Sortino Ratio. + + For method & terminology see: http://www.redrockcapital.com/Sortino__A__Sharper__Ratio_Red_Rock_Capital.pdf + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + target_return : float, optional + Target return, by default 0.0 + window : PositiveInt, optional + Window size, by default 252 + adjusted : bool, optional + Adjust sortino ratio to compare it to sharpe ratio, by default False + + Returns + ------- + OBBject[List[Data]] + Sortino ratio. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + target_return=target_return, + window=window, + adjusted=adjusted, + ) + + return self._command_runner.run( + "/qa/so", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def summary( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + ) -> OBBject[openbb_qa.qa_models.SummaryModel]: + """Summary. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + + Returns + ------- + OBBject[SummaryModel] + Summary table. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + ) + + return self._command_runner.run( + "/qa/summary", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def unitroot( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str, + fuller_reg: Literal["c", "ct", "ctt", "nc"] = "c", + kpss_reg: Literal["c", "ct"] = "c", + ) -> OBBject[openbb_qa.qa_models.UnitRootModel]: + """Unit Root Test. + + Augmented Dickey-Fuller test for unit root. + Kwiatkowski-Phillips-Schmidt-Shin test for unit root. + + Parameters + ---------- + data : List[Data] + Time series data. + target : str + Target column name. + fuller_reg : Literal["c", "ct", "ctt", "nc", "c"] + Regression type for ADF test. + kpss_reg : Literal["c", "ct"] + Regression type for KPSS test. + + Returns + ------- + OBBject[UnitRootModel] + Unit root tests summary. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + fuller_reg=fuller_reg, + kpss_reg=kpss_reg, + ) + + return self._command_runner.run( + "/qa/unitroot", + **inputs, + ) diff --git a/openbb_sdk/openbb/package/stocks.py b/openbb_sdk/openbb/package/stocks.py index 1a66cfe92da..a96fdf114c4 100644 --- a/openbb_sdk/openbb/package/stocks.py +++ b/openbb_sdk/openbb/package/stocks.py @@ -1,15 +1,16 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### import datetime -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union import pydantic -import typing_extensions +import pydantic.main from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs -from pydantic import validate_arguments +from pydantic import BaseModel, validate_arguments +from typing_extensions import Annotated class CLASS_stocks(Container): @@ -17,10 +18,13 @@ class CLASS_stocks(Container): /ca /dd /fa + info load multiples news + /options quote + search """ def __repr__(self) -> str: @@ -45,26 +49,143 @@ class CLASS_stocks(Container): return stocks_fa.CLASS_stocks_fa(command_runner=self._command_runner) @validate_arguments - def load( + def info( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - start_date: typing_extensions.Annotated[ + provider: Optional[Literal["cboe"]] = None, + **kwargs + ) -> OBBject[List]: + """Get general price and performance metrics of a stock. + + Parameters + ---------- + symbol : Union[str, List[str]] + Symbol to get data for. + provider : Optional[Literal['cboe']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'cboe' if there is + no default. + + Returns + ------- + OBBject + results : List[StockInfo] + Serializable results. + provider : Optional[Literal['cboe']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + StockInfo + --------- + symbol : Optional[str] + Symbol to get data for. + name : Optional[str] + Name associated with the ticker symbol. + price : Optional[float] + Last transaction price. + open : Optional[float] + Opening price of the stock. + high : Optional[float] + High price of the current trading day. + low : Optional[float] + Low price of the current trading day. + close : Optional[float] + Closing price of the most recent trading day. + change : Optional[float] + Change in price over the current trading period. + change_percent : Optional[float] + Percent change in price over the current trading period. + prev_close : Optional[float] + Previous closing price. + type : Optional[str] + Type of asset. (provider: cboe) + exchange_id : Optional[int] + The Exchange ID number. (provider: cboe) + tick : Optional[str] + Whether the last sale was an up or down tick. (provider: cboe) + bid : Optional[float] + Current bid price. (provider: cboe) + bid_size : Optional[float] + Bid lot size. (provider: cboe) + ask : Optional[float] + Current ask price. (provider: cboe) + ask_size : Optional[float] + Ask lot size. (provider: cboe) + volume : Optional[float] + Stock volume for the current trading day. (provider: cboe) + iv30 : Optional[float] + The 30-day implied volatility of the stock. (provider: cboe) + iv30_change : Optional[float] + Change in 30-day implied volatility of the stock. (provider: cboe) + last_trade_timestamp : Optional[datetime] + Last trade timestamp for the stock. (provider: cboe) + iv30_annual_high : Optional[float] + The 1-year high of implied volatility. (provider: cboe) + hv30_annual_high : Optional[float] + The 1-year high of realized volatility. (provider: cboe) + iv30_annual_low : Optional[float] + The 1-year low of implied volatility. (provider: cboe) + hv30_annual_low : Optional[float] + The 1-year low of realized volatility. (provider: cboe) + iv60_annual_high : Optional[float] + The 60-day high of implied volatility. (provider: cboe) + hv60_annual_high : Optional[float] + The 60-day high of realized volatility. (provider: cboe) + iv60_annual_low : Optional[float] + The 60-day low of implied volatility. (provider: cboe) + hv60_annual_low : Optional[float] + The 60-day low of realized volatility. (provider: cboe) + iv90_annual_high : Optional[float] + The 90-day high of implied volatility. (provider: cboe) + hv90_annual_high : Optional[float] + The 90-day high of realized volatility. (provider: cboe)""" # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/stocks/info", + **inputs, + ) + + @validate_arguments + def load( + self, + symbol: Annotated[ + Union[str, List[str]], + OpenBBCustomParameter(description="Symbol to get data for."), + ], + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[ + Literal["alpha_vantage", "cboe", "fmp", "intrinio", "polygon", "yfinance"] + ] = None, **kwargs ) -> OBBject[List]: """Load stock data for a specific ticker. @@ -79,31 +200,59 @@ class CLASS_stocks(Container): End date of the data, in YYYY-MM-DD format. chart : bool Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['alpha_vantage', 'cboe', 'fmp', 'intrinio', 'polygon', 'yfinance']] The provider to use for the query, by default None. - If None, the provider specified in defaults is selected or 'fmp' if there is + If None, the provider specified in defaults is selected or 'alpha_vantage' if there is no default. - timeseries : Union[pydantic.types.NonNegativeInt, NoneType] + period : Union[Literal['intraday', 'daily', 'weekly', 'monthly'], Literal['1d', '5d', '1mo', '3mo', '6mo', '1y', '2y', '5y', '10y', 'ytd', 'max'], NoneType] + None + interval : Union[Literal['1min', '5min', '15min', '30min', '60min'], NoneType, Literal['1d', '1m'], Literal['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'], Literal['1m', '2m', '5m', '15m', '30m', '60m', '90m', '1h', '1d', '5d', '1wk', '1mo', '3mo']] + None + adjusted : Optional[bool] + None + extended_hours : Optional[bool] + Extended trading hours during pre-market and after-hours. (provider: alpha_vantage) + month : Optional[str] + Query a specific month in history (in YYYY-MM format). (provider: alpha_vantage) + outputsize : Optional[Literal['compact', 'full']] + Compact returns only the latest 100 data points in the intraday time series; full returns trailing 30 days of the most recent intraday data if the month parameter (see above) is not specified, or the full intraday data for a specific month in history if the month parameter is specified. (provider: alpha_vantage) + timeseries : Optional[pydantic.types.NonNegativeInt] Number of days to look back. (provider: fmp) - interval : Literal['1min', '5min', '15min', '30min', '1hour', '4hour', '1day'] - Interval of the data to fetch. (provider: fmp) + timezone : Optional[Literal['Africa/Algiers', 'Africa/Cairo', 'Africa/Casablanca', 'Africa/Harare', 'Africa/Johannesburg', 'Africa/Monrovia', 'Africa/Nairobi', 'America/Argentina/Buenos_Aires', 'America/Bogota', 'America/Caracas', 'America/Chicago', 'America/Chihuahua', 'America/Denver', 'America/Godthab', 'America/Guatemala', 'America/Guyana', 'America/Halifax', 'America/Indiana/Indianapolis', 'America/Juneau', 'America/La_Paz', 'America/Lima', 'America/Los_Angeles', 'America/Mazatlan', 'America/Mexico_City', 'America/Monterrey', 'America/Montevideo', 'America/New_York', 'America/Phoenix', 'America/Regina', 'America/Santiago', 'America/Sao_Paulo', 'America/St_Johns', 'America/Tijuana', 'Asia/Almaty', 'Asia/Baghdad', 'Asia/Baku', 'Asia/Bangkok', 'Asia/Chongqing', 'Asia/Colombo', 'Asia/Dhaka', 'Asia/Hong_Kong', 'Asia/Irkutsk', 'Asia/Jakarta', 'Asia/Jerusalem', 'Asia/Kabul', 'Asia/Kamchatka', 'Asia/Karachi', 'Asia/Kathmandu', 'Asia/Kolkata', 'Asia/Krasnoyarsk', 'Asia/Kuala_Lumpur', 'Asia/Kuwait', 'Asia/Magadan', 'Asia/Muscat', 'Asia/Novosibirsk', 'Asia/Rangoon', 'Asia/Riyadh', 'Asia/Seoul', 'Asia/Shanghai', 'Asia/Singapore', 'Asia/Srednekolymsk', 'Asia/Taipei', 'Asia/Tashkent', 'Asia/Tbilisi', 'Asia/Tehran', 'Asia/Tokyo', 'Asia/Ulaanbaatar', 'Asia/Urumqi', 'Asia/Vladivostok', 'Asia/Yakutsk', 'Asia/Yekaterinburg', 'Asia/Yerevan', 'Atlantic/Azores', 'Atlantic/Cape_Verde', 'Atlantic/South_Georgia', 'Australia/Adelaide', 'Australia/Brisbane', 'Australia/Darwin', 'Australia/Hobart', 'Australia/Melbourne', 'Australia/Perth', 'Australia/Sydney', 'Etc/UTC', 'UTC', 'Europe/Amsterdam', 'Europe/Athens', 'Europe/Belgrade', 'Europe/Berlin', 'Europe/Bratislava', 'Europe/Brussels', 'Europe/Bucharest', 'Europe/Budapest', 'Europe/Copenhagen', 'Europe/Dublin', 'Europe/Helsinki', 'Europe/Istanbul', 'Europe/Kaliningrad', 'Europe/Kiev', 'Europe/Lisbon', 'Europe/Ljubljana', 'Europe/London', 'Europe/Madrid', 'Europe/Minsk', 'Europe/Moscow', 'Europe/Paris', 'Europe/Prague', 'Europe/Riga', 'Europe/Rome', 'Europe/Samara', 'Europe/Sarajevo', 'Europe/Skopje', 'Europe/Sofia', 'Europe/Stockholm', 'Europe/Tallinn', 'Europe/Vienna', 'Europe/Vilnius', 'Europe/Volgograd', 'Europe/Warsaw', 'Europe/Zagreb', 'Pacific/Apia', 'Pacific/Auckland', 'Pacific/Chatham', 'Pacific/Fakaofo', 'Pacific/Fiji', 'Pacific/Guadalcanal', 'Pacific/Guam', 'Pacific/Honolulu', 'Pacific/Majuro', 'Pacific/Midway', 'Pacific/Noumea', 'Pacific/Pago_Pago', 'Pacific/Port_Moresby', 'Pacific/Tongatapu']] + Returns trading times in this timezone. (provider: intrinio) + source : Optional[Literal['realtime', 'delayed', 'nasdaq_basic']] + The source of the data. (provider: intrinio) + start_time : Optional[datetime.time] + Return intervals starting at the specified time on the `start_date` formatted as 'hh:mm:ss'. (provider: intrinio) + end_time : Optional[datetime.time] + Return intervals stopping at the specified time on the `end_date` formatted as 'hh:mm:ss'. (provider: intrinio) + interval_size : Optional[Literal['1m', '5m', '10m', '15m', '30m', '60m', '1h']] + The data time frequency. (provider: intrinio) + limit : Union[pydantic.types.NonNegativeInt, NoneType, pydantic.types.PositiveInt] + None + next_page : Optional[str] + Token to get the next page of data from a previous API call. (provider: intrinio) + all_pages : Optional[bool] + Returns all pages of data from the API call at once. (provider: intrinio) timespan : Literal['minute', 'hour', 'day', 'week', 'month', 'quarter', 'year'] Timespan of the data. (provider: polygon) sort : Literal['asc', 'desc'] Sort order of the data. (provider: polygon) - limit : PositiveInt - The number of data entries to return. (provider: polygon) - adjusted : bool - Whether the data is adjusted. (provider: polygon) multiplier : PositiveInt Multiplier of the timespan. (provider: polygon) + prepost : bool + Include Pre and Post market data. (provider: yfinance) + adjust : bool + Adjust all the data automatically. (provider: yfinance) + back_adjust : bool + Back-adjusted data to mimic true historical prices. (provider: yfinance) Returns ------- OBBject - results : List[StockEOD] + results : List[StockHistorical] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['alpha_vantage', 'cboe', 'fmp', 'intrinio', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -112,8 +261,8 @@ class CLASS_stocks(Container): metadata: Optional[Metadata] Metadata info about the command execution. - StockEOD - -------- + StockHistorical + --------------- date : Optional[datetime] The date of the data. open : Optional[PositiveFloat] @@ -124,10 +273,22 @@ class CLASS_stocks(Container): The low price of the symbol. close : Optional[PositiveFloat] The close price of the symbol. - volume : Optional[float] + volume : Optional[NonNegativeInt] The volume of the symbol. vwap : Optional[PositiveFloat] Volume Weighted Average Price of the symbol. + adjusted_close : Optional[PositiveFloat] + The adjusted close price of the symbol. (provider: alpha_vantage) + dividend_amount : Optional[NonNegativeFloat] + Dividend amount paid for the corresponding date. (provider: alpha_vantage) + split_coefficient : Optional[NonNegativeFloat] + Split coefficient for the corresponding date. (provider: alpha_vantage) + calls_volume : Optional[float] + Number of calls traded during the most recent trading period. Only valid if interval is 1m. (provider: cboe) + puts_volume : Optional[float] + Number of puts traded during the most recent trading period. Only valid if interval is 1m. (provider: cboe) + total_options_volume : Optional[float] + Total number of options traded during the most recent trading period. Only valid if interval is 1m. (provider: cboe) adj_close : Optional[float] Adjusted Close Price of the symbol. (provider: fmp) unadjusted_volume : Optional[float] @@ -140,7 +301,13 @@ class CLASS_stocks(Container): Human readable format of the date. (provider: fmp) change_over_time : Optional[float] Change \\% in the price of the symbol over a period of time. (provider: fmp) - n : Optional[PositiveInt] + close_time : Optional[datetime] + The timestamp that represents the end of the interval span. (provider: intrinio) + interval : Optional[str] + The data time frequency. (provider: intrinio) + average : Optional[float] + Average trade price of an individual stock during the interval. (provider: intrinio) + transactions : Optional[PositiveInt] Number of transactions for the symbol in the time period. (provider: polygon) """ # noqa: E501 @@ -165,16 +332,16 @@ class CLASS_stocks(Container): @validate_arguments def multiples( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - limit: typing_extensions.Annotated[ - Union[int, None], + limit: Annotated[ + Optional[int], OpenBBCustomParameter(description="The number of data entries to return."), ] = 100, chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Get valuation multiples for a stock ticker. @@ -183,11 +350,11 @@ class CLASS_stocks(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - limit : Union[int, NoneType] + limit : Optional[int] The number of data entries to return. chart : bool Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -197,7 +364,7 @@ class CLASS_stocks(Container): OBBject results : List[StockMultiples] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -349,23 +516,25 @@ class CLASS_stocks(Container): @validate_arguments def news( self, - symbols: typing_extensions.Annotated[ + symbols: Annotated[ str, OpenBBCustomParameter(description="Symbol to get data for.") ], - page: typing_extensions.Annotated[ + page: Annotated[ int, OpenBBCustomParameter( description="Page of the stock news to be retrieved." ), ] = 0, - limit: typing_extensions.Annotated[ - Union[pydantic.types.NonNegativeInt, None], + limit: Annotated[ + Optional[pydantic.types.NonNegativeInt], OpenBBCustomParameter(description="Number of results to return per page."), ] = 15, chart: bool = False, - provider: Union[Literal["benzinga", "fmp", "polygon"], None] = None, + provider: Optional[ + Literal["benzinga", "fmp", "intrinio", "polygon", "yfinance"] + ] = None, **kwargs - ) -> OBBject[List]: + ) -> OBBject[BaseModel]: """Get news for one or more stock tickers. Parameters @@ -374,59 +543,63 @@ class CLASS_stocks(Container): Symbol to get data for. page : int Page of the stock news to be retrieved. - limit : Union[pydantic.types.NonNegativeInt, NoneType] + limit : Optional[pydantic.types.NonNegativeInt] Number of results to return per page. chart : bool Whether to create a chart or not, by default False. - provider : Union[Literal['benzinga', 'fmp', 'polygon'], NoneType] + provider : Optional[Literal['benzinga', 'fmp', 'intrinio', 'polygon', 'yfinance']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'benzinga' if there is no default. display_output : Literal['headline', 'summary', 'full', 'all'] Type of data to return. (provider: benzinga) - date : Union[datetime.datetime, NoneType] + date : Optional[datetime.datetime] Date of the news to retrieve. (provider: benzinga) - date_from : Union[datetime.datetime, NoneType] + date_from : Optional[datetime.datetime] Start date of the news to retrieve. (provider: benzinga) - date_to : Union[datetime.datetime, NoneType] + date_to : Optional[datetime.datetime] End date of the news to retrieve. (provider: benzinga) - updated_since : Union[int, NoneType] + updated_since : Optional[int] Number of seconds since the news was updated. (provider: benzinga) - published_since : Union[int, NoneType] + published_since : Optional[int] Number of seconds since the news was published. (provider: benzinga) sort : Union[Literal['published_at', 'updated_at', 'title', 'author', 'channel', 'ticker', 'topic', 'content_type'], NoneType, str] None - isin : Union[str, NoneType] + isin : Optional[str] The ISIN of the news to retrieve. (provider: benzinga) - cusip : Union[str, NoneType] + cusip : Optional[str] The CUSIP of the news to retrieve. (provider: benzinga) - channels : Union[str, NoneType] + channels : Optional[str] Channels of the news to retrieve. (provider: benzinga) - topics : Union[str, NoneType] + topics : Optional[str] Topics of the news to retrieve. (provider: benzinga) - authors : Union[str, NoneType] + authors : Optional[str] Authors of the news to retrieve. (provider: benzinga) - content_types : Union[str, NoneType] + content_types : Optional[str] Content types of the news to retrieve. (provider: benzinga) - ticker_lt : Union[str, NoneType] + next_page : Optional[str] + Token to get the next page of data from a previous API call. (provider: intrinio) + all_pages : Optional[bool] + Returns all pages of data from the API call at once. (provider: intrinio) + ticker_lt : Optional[str] Less than, by default None (provider: polygon) - ticker_lte : Union[str, NoneType] + ticker_lte : Optional[str] Less than or equal, by default None (provider: polygon) - ticker_gt : Union[str, NoneType] + ticker_gt : Optional[str] Greater than, by default None (provider: polygon) - ticker_gte : Union[str, NoneType] + ticker_gte : Optional[str] Greater than or equal, by default None (provider: polygon) - published_utc : Union[str, NoneType] + published_utc : Optional[str] Published date of the query, by default None (provider: polygon) - published_utc_lt : Union[str, NoneType] + published_utc_lt : Optional[str] Less than, by default None (provider: polygon) - published_utc_lte : Union[str, NoneType] + published_utc_lte : Optional[str] Less than or equal, by default None (provider: polygon) - published_utc_gt : Union[str, NoneType] + published_utc_gt : Optional[str] Greater than, by default None (provider: polygon) - published_utc_gte : Union[str, NoneType] + published_utc_gte : Optional[str] Greater than or equal, by default None (provider: polygon) - order : Union[Literal['asc', 'desc'], NoneType] + order : Optional[Literal['asc', 'desc']] Sort order of the query, by default None (provider: polygon) Returns @@ -434,7 +607,7 @@ class CLASS_stocks(Container): OBBject results : List[StockNews] Serializable results. - provider : Union[Literal['benzinga', 'fmp', 'polygon'], NoneType] + provider : Optional[Literal['benzinga', 'fmp', 'intrinio', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -469,20 +642,28 @@ class CLASS_stocks(Container): URL to the image of the news source. (provider: fmp) site : Optional[str] Name of the news source. (provider: fmp) + id : Optional[str] + Intrinio ID for the news article. (provider: intrinio) amp_url : Optional[str] AMP URL. (provider: polygon) author : Optional[str] Author of the article. (provider: polygon) - id : Optional[str] - Article ID. (provider: polygon) image_url : Optional[str] Image URL. (provider: polygon) keywords : Optional[List[str]] Keywords in the article (provider: polygon) - publisher : Optional[PolygonPublisher] + publisher : Union[PolygonPublisher, NoneType, str] Publisher of the article. (provider: polygon) tickers : Optional[List[str]] - Tickers covered in the article. (provider: polygon)""" # noqa: E501 + Tickers covered in the article. (provider: polygon) + uuid : Optional[str] + Unique identifier for the news article (provider: yfinance) + type : Optional[str] + Type of the news article (provider: yfinance) + thumbnail : Optional[Mapping[str, Any]] + Thumbnail related data to the ticker news article. (provider: yfinance) + related_tickers : Optional[str] + Tickers related to the news article. (provider: yfinance)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -502,15 +683,20 @@ class CLASS_stocks(Container): **inputs, ) + @property + def options(self): # route = "/stocks/options" + from . import stocks_options + + return stocks_options.CLASS_stocks_options(command_runner=self._command_runner) + @validate_arguments def quote( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp", "intrinio"]] = None, **kwargs ) -> OBBject[List]: """Load stock data for a specific ticker. @@ -519,19 +705,19 @@ class CLASS_stocks(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp', 'intrinio']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. + source : Literal['iex', 'bats', 'bats_delayed', 'utp_delayed', 'cta_a_delayed', 'cta_b_delayed', 'intrinio_mx', 'intrinio_mx_plus', 'delayed_sip'] + Source of the data. (provider: intrinio) Returns ------- OBBject results : List[StockQuote] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp', 'intrinio']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -542,50 +728,90 @@ class CLASS_stocks(Container): StockQuote ---------- - symbol : Optional[str] - Symbol of the company. - name : Optional[str] - Name of the company. - price : Optional[float] - Current trading price of the stock. - changes_percentage : Optional[float] - Change percentage of the stock price. - change : Optional[float] - Change of the stock price. day_low : Optional[float] Lowest price of the stock in the current trading day. day_high : Optional[float] Highest price of the stock in the current trading day. - year_high : Optional[float] - Highest price of the stock in the last 52 weeks. - year_low : Optional[float] - Lowest price of the stock in the last 52 weeks. - market_cap : Optional[float] - Market cap of the company. - price_avg50 : Optional[float] - 50 days average price of the stock. - price_avg200 : Optional[float] - 200 days average price of the stock. - volume : Optional[int] - Volume of the stock in the current trading day. - avg_volume : Optional[int] - Average volume of the stock in the last 10 trading days. - exchange : Optional[str] - Exchange the stock is traded on. - open : Optional[float] - Opening price of the stock in the current trading day. - previous_close : Optional[float] - Previous closing price of the stock. - eps : Optional[float] - Earnings per share of the stock. - pe : Optional[float] - Price earnings ratio of the stock. - earnings_announcement : Optional[str] - Earnings announcement date of the stock. - shares_outstanding : Optional[int] - Number of shares outstanding of the stock. date : Optional[datetime] - Timestamp of the stock quote.""" # noqa: E501 + Timestamp of the stock quote. + symbol : Optional[str] + Symbol of the company. (provider: fmp) + name : Optional[str] + Name of the company. (provider: fmp) + price : Optional[float] + Current trading price of the stock. (provider: fmp) + changes_percentage : Optional[float] + Change percentage of the stock price. (provider: fmp) + change : Optional[float] + Change in the stock price. (provider: fmp) + year_high : Optional[float] + Highest price of the stock in the last 52 weeks. (provider: fmp) + year_low : Optional[float] + Lowest price of the stock in the last 52 weeks. (provider: fmp) + market_cap : Optional[float] + Market cap of the company. (provider: fmp) + price_avg50 : Optional[float] + 50 days average price of the stock. (provider: fmp) + price_avg200 : Optional[float] + 200 days average price of the stock. (provider: fmp) + volume : Optional[int] + Volume of the stock in the current trading day. (provider: fmp) + avg_volume : Optional[int] + Average volume of the stock in the last 10 trading days. (provider: fmp) + exchange : Optional[str] + Exchange the stock is traded on. (provider: fmp) + open : Optional[float] + Opening price of the stock in the current trading day. (provider: fmp) + previous_close : Optional[float] + Previous closing price of the stock. (provider: fmp) + eps : Optional[float] + Earnings per share of the stock. (provider: fmp) + pe : Optional[float] + Price earnings ratio of the stock. (provider: fmp) + earnings_announcement : Optional[str] + Earnings announcement date of the stock. (provider: fmp) + shares_outstanding : Optional[int] + Number of shares outstanding of the stock. (provider: fmp) + last_price : Optional[float] + Price of the last trade. (provider: intrinio) + last_time : Optional[datetime] + Date and Time when the last trade occurred. (provider: intrinio) + last_size : Optional[int] + Size of the last trade. (provider: intrinio) + bid_price : Optional[float] + Price of the top bid order. (provider: intrinio) + bid_size : Optional[int] + Size of the top bid order. (provider: intrinio) + ask_price : Optional[float] + Price of the top ask order. (provider: intrinio) + ask_size : Optional[int] + Size of the top ask order. (provider: intrinio) + open_price : Optional[float] + Open price for the trading day. (provider: intrinio) + close_price : Optional[float] + Closing price for the trading day (IEX source only). (provider: intrinio) + high_price : Optional[float] + High Price for the trading day. (provider: intrinio) + low_price : Optional[float] + Low Price for the trading day. (provider: intrinio) + exchange_volume : Optional[int] + Number of shares exchanged during the trading day on the exchange. (provider: intrinio) + market_volume : Optional[int] + Number of shares exchanged during the trading day for the whole market. (provider: intrinio) + updated_on : Optional[datetime] + Date and Time when the data was last updated. (provider: intrinio) + source : Optional[str] + Source of the data. (provider: intrinio) + listing_venue : Optional[str] + Listing venue where the trade took place (SIP source only). (provider: intrinio) + sales_conditions : Optional[str] + Indicates any sales condition modifiers associated with the trade. (provider: intrinio) + quote_conditions : Optional[str] + Indicates any quote condition modifiers associated with the trade. (provider: intrinio) + market_center_code : Optional[str] + Market center character code. (provider: intrinio) + is_darkpool : Optional[bool] + Whether or not the current trade is from a darkpool. (provider: intrinio)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -595,10 +821,74 @@ class CLASS_stocks(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( "/stocks/quote", **inputs, ) + + @validate_arguments + def search( + self, + query: Annotated[str, OpenBBCustomParameter(description="Search query.")] = "", + ticker: Annotated[ + bool, + OpenBBCustomParameter(description="Whether to search by ticker symbol."), + ] = False, + provider: Optional[Literal["cboe"]] = None, + **kwargs + ) -> OBBject[List]: + """Search for a company or stock ticker. + + Parameters + ---------- + query : str + Search query. + ticker : bool + Whether to search by ticker symbol. + provider : Optional[Literal['cboe']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'cboe' if there is + no default. + + Returns + ------- + OBBject + results : List[StockSearch] + Serializable results. + provider : Optional[Literal['cboe']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + StockSearch + ----------- + symbol : Optional[str] + Symbol to get data for. + name : Optional[str] + Name of the company. + dpm_name : Optional[str] + Name of the primary market maker. (provider: cboe) + post_station : Optional[str] + Post and station location on the CBOE trading floor. (provider: cboe)""" # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "query": query, + "ticker": ticker, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/stocks/search", + **inputs, + ) diff --git a/openbb_sdk/openbb/package/stocks_ca.py b/openbb_sdk/openbb/package/stocks_ca.py index 173a3f97855..8c8d05c9d06 100644 --- a/openbb_sdk/openbb/package/stocks_ca.py +++ b/openbb_sdk/openbb/package/stocks_ca.py @@ -1,13 +1,13 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import BaseModel, validate_arguments +from typing_extensions import Annotated class CLASS_stocks_ca(Container): @@ -21,12 +21,11 @@ class CLASS_stocks_ca(Container): @validate_arguments def peers( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[BaseModel]: """Company peers. @@ -35,9 +34,7 @@ class CLASS_stocks_ca(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -47,7 +44,7 @@ class CLASS_stocks_ca(Container): OBBject results : List[StockPeers] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -71,7 +68,6 @@ class CLASS_stocks_ca(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/stocks_dd.py b/openbb_sdk/openbb/package/stocks_dd.py index 990701d7fe5..2656ec811bf 100644 --- a/openbb_sdk/openbb/package/stocks_dd.py +++ b/openbb_sdk/openbb/package/stocks_dd.py @@ -1,13 +1,13 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import validate_arguments +from typing_extensions import Annotated class CLASS_stocks_dd(Container): @@ -21,11 +21,11 @@ class CLASS_stocks_dd(Container): @validate_arguments def sec( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - type: typing_extensions.Annotated[ + type: Annotated[ Literal[ "1", "1-A", @@ -130,16 +130,15 @@ class CLASS_stocks_dd(Container): ], OpenBBCustomParameter(description="Type of the SEC filing form."), ] = "10-K", - page: typing_extensions.Annotated[ - Union[int, None], + page: Annotated[ + Optional[int], OpenBBCustomParameter(description="Page number of the results."), ] = 0, - limit: typing_extensions.Annotated[ - Union[int, None], + limit: Annotated[ + Optional[int], OpenBBCustomParameter(description="The number of data entries to return."), ] = 100, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """SEC Filings. @@ -150,13 +149,11 @@ class CLASS_stocks_dd(Container): Symbol to get data for. type : Literal['1', '1-A', '1-E', '1-K', '1-N', '1-SA', '1-U', '1-Z', '10', '10-D', '10-K', '10-M', '10-Q', '11-K', '12b-25', '13F', '13H', '144', '15', '15F', '17-H', '18', '18-K', '19b-4', '19b-4(e)', '19b-7', '2-E', '20-F', '24F-2', '25', '3', '4', '40-F', '5', '6-K', '7-M', '8-A', '8-K', '8-M', '9-M', 'ABS-15G', 'ABS-EE', 'ABS DD-15E', 'ADV', 'ADV-E', 'ADV-H', 'ADV-NR', 'ADV-W', 'ATS', 'ATS-N', 'ATS-R', 'BD', 'BD-N', 'BDW', 'C', 'CA-1', 'CB', 'CFPORTAL', 'CRS', 'CUSTODY', 'D', 'F-1', 'F-10', 'F-3', 'F-4', 'F-6', 'F-7', 'F-8', 'F-80', 'F-N', 'F-X', 'ID', 'MA', 'MA-I', 'MA-NR', 'MA-W', 'MSD', 'MSDW', 'N-14', 'N-17D-1', 'N-17f-1', 'N-17f-2', 'N-18f-1', 'N-1A', 'N-2', 'N-23c-3', 'N-27D-1', 'N-3', 'N-4', 'N-5', 'N-54A', 'N-54C', 'N-6', 'N-6EI-1', 'N-6F', 'N-8A', 'N-8B-2', 'N-8B-4', 'N-8F', 'N-CEN'] Type of the SEC filing form. - page : Union[int, NoneType] + page : Optional[int] Page number of the results. - limit : Union[int, NoneType] + limit : Optional[int] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -166,7 +163,7 @@ class CLASS_stocks_dd(Container): OBBject results : List[SECFilings] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -203,7 +200,6 @@ class CLASS_stocks_dd(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/stocks_fa.py b/openbb_sdk/openbb/package/stocks_fa.py index 8fcc9e59626..370773c2854 100644 --- a/openbb_sdk/openbb/package/stocks_fa.py +++ b/openbb_sdk/openbb/package/stocks_fa.py @@ -1,16 +1,16 @@ ### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### import datetime -from typing import List, Literal, Union +from typing import List, Literal, Optional, Union import pydantic import pydantic.main -import typing_extensions from openbb_core.app.model.custom_parameter import OpenBBCustomParameter from openbb_core.app.model.obbject import OBBject from openbb_core.app.static.container import Container from openbb_core.app.static.filters import filter_inputs from pydantic import BaseModel, validate_arguments +from typing_extensions import Annotated class CLASS_stocks_fa(Container): @@ -50,22 +50,21 @@ class CLASS_stocks_fa(Container): @validate_arguments def balance( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ + period: Annotated[ Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - limit: typing_extensions.Annotated[ - Union[pydantic.types.NonNegativeInt, None], + limit: Annotated[ + Optional[pydantic.types.NonNegativeInt], OpenBBCustomParameter(description="The number of data entries to return."), ] = 12, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[Literal["fmp", "intrinio", "polygon", "yfinance"]] = None, **kwargs - ) -> OBBject[List]: + ) -> OBBject[BaseModel]: """Balance Sheet. Parameters @@ -74,47 +73,47 @@ class CLASS_stocks_fa(Container): Symbol to get data for. period : Literal['annual', 'quarter'] Period of the data to return. - limit : Union[pydantic.types.NonNegativeInt, NoneType] + limit : Optional[pydantic.types.NonNegativeInt] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon', 'yfinance']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. - cik : Union[str, NoneType] - None - company_name : Union[str, NoneType] + type : Literal['reported', 'standardized'] + Type of the statement to be fetched. (provider: intrinio) + year : Optional[int] + Year of the statement to be fetched. (provider: intrinio) + company_name : Optional[str] Name of the company. (provider: polygon) - company_name_search : Union[str, NoneType] + company_name_search : Optional[str] Name of the company to search. (provider: polygon) - sic : Union[str, NoneType] + sic : Optional[str] The Standard Industrial Classification (SIC) of the company. (provider: polygon) - filing_date : Union[datetime.date, NoneType] + filing_date : Optional[datetime.date] Filing date of the financial statement. (provider: polygon) - filing_date_lt : Union[datetime.date, NoneType] + filing_date_lt : Optional[datetime.date] Filing date less than the given date. (provider: polygon) - filing_date_lte : Union[datetime.date, NoneType] + filing_date_lte : Optional[datetime.date] Filing date less than or equal to the given date. (provider: polygon) - filing_date_gt : Union[datetime.date, NoneType] + filing_date_gt : Optional[datetime.date] Filing date greater than the given date. (provider: polygon) - filing_date_gte : Union[datetime.date, NoneType] + filing_date_gte : Optional[datetime.date] Filing date greater than or equal to the given date. (provider: polygon) - period_of_report_date : Union[datetime.date, NoneType] + period_of_report_date : Optional[datetime.date] Period of report date of the financial statement. (provider: polygon) - period_of_report_date_lt : Union[datetime.date, NoneType] + period_of_report_date_lt : Optional[datetime.date] Period of report date less than the given date. (provider: polygon) - period_of_report_date_lte : Union[datetime.date, NoneType] + period_of_report_date_lte : Optional[datetime.date] Period of report date less than or equal to the given date. (provider: polygon) - period_of_report_date_gt : Union[datetime.date, NoneType] + period_of_report_date_gt : Optional[datetime.date] Period of report date greater than the given date. (provider: polygon) - period_of_report_date_gte : Union[datetime.date, NoneType] + period_of_report_date_gte : Optional[datetime.date] Period of report date greater than or equal to the given date. (provider: polygon) - include_sources : Union[bool, NoneType] + include_sources : Optional[bool] Whether to include the sources of the financial statement. (provider: polygon) - order : Union[Literal['asc', 'desc'], NoneType] + order : Optional[Literal['asc', 'desc']] Order of the financial statement. (provider: polygon) - sort : Union[Literal['filing_date', 'period_of_report_date'], NoneType] + sort : Optional[Literal['filing_date', 'period_of_report_date']] Sort of the financial statement. (provider: polygon) Returns @@ -122,7 +121,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[BalanceSheet] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -133,116 +132,114 @@ class CLASS_stocks_fa(Container): BalanceSheet ------------ + symbol : Optional[str] + Symbol to get data for. date : Optional[date] Date of the fetched statement. - symbol : Optional[str] - Symbol of the company. - cik : Optional[int] - Central Index Key. - currency : Optional[str] - Reporting currency. - filing_date : Optional[date] - Filling date. - accepted_date : Optional[datetime] - Accepted date. period : Optional[str] Reporting period of the statement. + cik : Optional[int] + Central Index Key (CIK) of the company. cash_and_cash_equivalents : Optional[int] Cash and cash equivalents short_term_investments : Optional[int] Short-term investments - inventory : Optional[int] - Inventory net_receivables : Optional[int] Receivables, net + inventory : Optional[int] + Inventory other_current_assets : Optional[int] Other current assets - current_assets : Optional[int] + total_current_assets : Optional[int] Total current assets - long_term_investments : Optional[int] - Long-term investments + marketable_securities : Optional[int] + Marketable securities property_plant_equipment_net : Optional[int] Property, plant and equipment, net goodwill : Optional[int] Goodwill intangible_assets : Optional[int] Intangible assets - other_non_current_assets : Optional[int] - Other non-current assets tax_assets : Optional[int] Accrued income taxes + other_non_current_assets : Optional[int] + Other non-current assets + total_non_current_assets : Optional[int] + Total non-current assets other_assets : Optional[int] Other assets - noncurrent_assets : Optional[int] - None - assets : Optional[int] - None + total_assets : Optional[int] + Total assets account_payables : Optional[int] - None - other_current_liabilities : Optional[int] - None + Accounts payables + short_term_debt : Optional[int] + Short-term borrowings, Long-term debt due within one year, Operating lease obligations due within one year, Finance lease obligations due within one year tax_payables : Optional[int] Accrued income taxes deferred_revenue : Optional[int] Accrued income taxes, other deferred revenue - short_term_debt : Optional[int] - Short-term borrowings, Long-term debt due within one year, Operating lease obligations due within one year, Finance lease obligations due within one year - current_liabilities : Optional[int] - None + other_current_liabilities : Optional[int] + Other current liabilities + total_current_liabilities : Optional[int] + Total current liabilities long_term_debt : Optional[int] Long-term debt, Operating lease obligations, Long-term finance lease obligations + deferred_revenue_non_current : Optional[int] + Deferred revenue, non-current + deferred_tax_liabilities_non_current : Optional[int] + Deferred income taxes and other other_non_current_liabilities : Optional[int] Deferred income taxes and other + total_non_current_liabilities : Optional[int] + Total non-current liabilities other_liabilities : Optional[int] - None - noncurrent_liabilities : Optional[int] - None - liabilities : Optional[int] - None - common_stock : Optional[int] - None - other_stockholder_equity : Optional[int] - Capital in excess of par value - accumulated_other_comprehensive_income_loss : Optional[int] - Accumulated other comprehensive income (loss) + Other liabilities + total_liabilities : Optional[int] + Total liabilities preferred_stock : Optional[int] Preferred stock + common_stock : Optional[int] + Common stock retained_earnings : Optional[int] Retained earnings + accumulated_other_comprehensive_income_loss : Optional[int] + Accumulated other comprehensive income (loss) + other_shareholder_equity : Optional[int] + Other shareholder's equity + total_shareholder_equity : Optional[int] + Total shareholder's equity + total_equity : Optional[int] + Total equity + total_liabilities_and_shareholders_equity : Optional[int] + Total liabilities and shareholder's equity minority_interest : Optional[int] Minority interest - total_stockholders_equity : Optional[int] - None - total_equity : Optional[int] - None - total_liabilities_and_stockholders_equity : Optional[int] - None total_liabilities_and_total_equity : Optional[int] - None + Total liabilities and total equity + reported_currency : Optional[str] + Reported currency in the statement. (provider: fmp) + filling_date : Optional[date] + Filling date. (provider: fmp) + accepted_date : Optional[datetime] + Accepted date. (provider: fmp) calendar_year : Optional[int] - None - link : Optional[str] - None - final_link : Optional[str] - None + Calendar year. (provider: fmp) cash_and_short_term_investments : Optional[int] - None + Cash and short term investments (provider: fmp) goodwill_and_intangible_assets : Optional[int] - None - deferred_revenue_non_current : Optional[int] - None - total_investments : Optional[int] - None + Goodwill and Intangible Assets (provider: fmp) capital_lease_obligations : Optional[int] - None - deferred_tax_liabilities_non_current : Optional[int] - None - total_non_current_liabilities : Optional[int] - None + Capital lease obligations (provider: fmp) + total_investments : Optional[int] + Total investments (provider: fmp) total_debt : Optional[int] - None + Total debt (provider: fmp) net_debt : Optional[int] - None""" # noqa: E501 + Net debt (provider: fmp) + link : Optional[str] + Link to the statement. (provider: fmp) + final_link : Optional[str] + Link to the final statement. (provider: fmp)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -254,7 +251,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -265,16 +261,15 @@ class CLASS_stocks_fa(Container): @validate_arguments def balance_growth( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - limit: typing_extensions.Annotated[ + limit: Annotated[ int, OpenBBCustomParameter(description="The number of data entries to return."), ] = 10, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Balance Sheet Statement Growth. @@ -285,9 +280,7 @@ class CLASS_stocks_fa(Container): Symbol to get data for. limit : int The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -297,7 +290,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[BalanceSheetGrowth] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -402,7 +395,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -413,20 +405,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def cal( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Show Dividend Calendar for a given start and end dates. @@ -437,9 +428,7 @@ class CLASS_stocks_fa(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -449,7 +438,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[DividendCalendar] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -486,7 +475,6 @@ class CLASS_stocks_fa(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -497,22 +485,21 @@ class CLASS_stocks_fa(Container): @validate_arguments def cash( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ + period: Annotated[ Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - limit: typing_extensions.Annotated[ - Union[pydantic.types.NonNegativeInt, None], + limit: Annotated[ + Optional[pydantic.types.NonNegativeInt], OpenBBCustomParameter(description="The number of data entries to return."), ] = 12, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[Literal["fmp", "intrinio", "polygon", "yfinance"]] = None, **kwargs - ) -> OBBject[List]: + ) -> OBBject[BaseModel]: """Cash Flow Statement. Parameters @@ -521,47 +508,47 @@ class CLASS_stocks_fa(Container): Symbol to get data for. period : Literal['annual', 'quarter'] Period of the data to return. - limit : Union[pydantic.types.NonNegativeInt, NoneType] + limit : Optional[pydantic.types.NonNegativeInt] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon', 'yfinance']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. - cik : Union[str, NoneType] - Central Index Key (CIK) of the company. (provider: fmp) - company_name : Union[str, NoneType] + type : Literal['reported', 'standardized'] + Type of the statement to be fetched. (provider: intrinio) + year : Optional[int] + Year of the statement to be fetched. (provider: intrinio) + company_name : Optional[str] Name of the company. (provider: polygon) - company_name_search : Union[str, NoneType] + company_name_search : Optional[str] Name of the company to search. (provider: polygon) - sic : Union[str, NoneType] + sic : Optional[str] The Standard Industrial Classification (SIC) of the company. (provider: polygon) - filing_date : Union[datetime.date, NoneType] + filing_date : Optional[datetime.date] Filing date of the financial statement. (provider: polygon) - filing_date_lt : Union[datetime.date, NoneType] + filing_date_lt : Optional[datetime.date] Filing date less than the given date. (provider: polygon) - filing_date_lte : Union[datetime.date, NoneType] + filing_date_lte : Optional[datetime.date] Filing date less than or equal to the given date. (provider: polygon) - filing_date_gt : Union[datetime.date, NoneType] + filing_date_gt : Optional[datetime.date] Filing date greater than the given date. (provider: polygon) - filing_date_gte : Union[datetime.date, NoneType] + filing_date_gte : Optional[datetime.date] Filing date greater than or equal to the given date. (provider: polygon) - period_of_report_date : Union[datetime.date, NoneType] + period_of_report_date : Optional[datetime.date] Period of report date of the financial statement. (provider: polygon) - period_of_report_date_lt : Union[datetime.date, NoneType] + period_of_report_date_lt : Optional[datetime.date] Period of report date less than the given date. (provider: polygon) - period_of_report_date_lte : Union[datetime.date, NoneType] + period_of_report_date_lte : Optional[datetime.date] Period of report date less than or equal to the given date. (provider: polygon) - period_of_report_date_gt : Union[datetime.date, NoneType] + period_of_report_date_gt : Optional[datetime.date] Period of report date greater than the given date. (provider: polygon) - period_of_report_date_gte : Union[datetime.date, NoneType] + period_of_report_date_gte : Optional[datetime.date] Period of report date greater than or equal to the given date. (provider: polygon) - include_sources : Union[bool, NoneType] + include_sources : Optional[bool] Whether to include the sources of the financial statement. (provider: polygon) - order : Union[Literal['asc', 'desc'], NoneType] + order : Optional[Literal['asc', 'desc']] Order of the financial statement. (provider: polygon) - sort : Union[Literal['filing_date', 'period_of_report_date'], NoneType] + sort : Optional[Literal['filing_date', 'period_of_report_date']] Sort of the financial statement. (provider: polygon) Returns @@ -569,7 +556,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[CashFlowStatement] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -580,88 +567,100 @@ class CLASS_stocks_fa(Container): CashFlowStatement ----------------- + symbol : Optional[str] + Symbol to get data for. date : Optional[date] Date of the fetched statement. - symbol : Optional[str] - Symbol of the company. - cik : Optional[int] - Central Index Key. - currency : Optional[str] - Reporting currency. - filing_date : Optional[date] - Filling date. - accepted_date : Optional[datetime] - Accepted date. period : Optional[str] Reporting period of the statement. - cash_at_beginning_of_period : Optional[int] - Cash at beginning of period. + cik : Optional[int] + Central Index Key (CIK) of the company. net_income : Optional[int] Net income. depreciation_and_amortization : Optional[int] Depreciation and amortization. stock_based_compensation : Optional[int] Stock based compensation. - other_non_cash_items : Optional[int] - Other non-cash items. deferred_income_tax : Optional[int] Deferred income tax. - inventory : Optional[int] - Inventory. - accounts_payables : Optional[int] - Accounts payables. + other_non_cash_items : Optional[int] + Other non-cash items. + changes_in_operating_assets_and_liabilities : Optional[int] + Changes in operating assets and liabilities. accounts_receivables : Optional[int] Accounts receivables. - change_in_working_capital : Optional[int] - Change in working capital. - other_working_capital : Optional[int] - Accrued expenses and other, Unearned revenue. - capital_expenditure : Optional[int] - Purchases of property and equipment. - other_investing_activities : Optional[int] - Proceeds from property and equipment sales and incentives. - acquisitions_net : Optional[int] - Acquisitions, net of cash acquired, and other - sales_maturities_of_investments : Optional[int] - Sales and maturities of investments. - purchases_of_investments : Optional[int] - Purchases of investments. + inventory : Optional[int] + Inventory. + vendor_non_trade_receivables : Optional[int] + Vendor non-trade receivables. + other_current_and_non_current_assets : Optional[int] + Other current and non-current assets. + accounts_payables : Optional[int] + Accounts payables. + deferred_revenue : Optional[int] + Deferred revenue. + other_current_and_non_current_liabilities : Optional[int] + Other current and non-current liabilities. net_cash_flow_from_operating_activities : Optional[int] Net cash flow from operating activities. - net_cash_flow_from_investing_activities : Optional[int] - Net cash flow from investing activities. - net_cash_flow_from_financing_activities : Optional[int] - Net cash flow from financing activities. + purchases_of_marketable_securities : Optional[int] + Purchases of investments. + sales_from_maturities_of_investments : Optional[int] + Sales and maturities of investments. investments_in_property_plant_and_equipment : Optional[int] Investments in property, plant, and equipment. - net_cash_used_for_investing_activities : Optional[int] + payments_from_acquisitions : Optional[int] + Acquisitions, net of cash acquired, and other + other_investing_activities : Optional[int] + Other investing activities + net_cash_flow_from_investing_activities : Optional[int] Net cash used for investing activities. - effect_of_forex_changes_on_cash : Optional[int] - Foreign currency effect on cash, cash equivalents, and restricted cash + taxes_paid_on_net_share_settlement : Optional[int] + Taxes paid on net share settlement of equity awards. dividends_paid : Optional[int] Payments for dividends and dividend equivalents - common_stock_issued : Optional[int] - Proceeds from issuance of common stock common_stock_repurchased : Optional[int] Payments related to repurchase of common stock + debt_proceeds : Optional[int] + Proceeds from issuance of term debt debt_repayment : Optional[int] Payments of long-term debt other_financing_activities : Optional[int] Other financing activities, net + net_cash_flow_from_financing_activities : Optional[int] + Net cash flow from financing activities. net_change_in_cash : Optional[int] Net increase (decrease) in cash, cash equivalents, and restricted cash - cash_at_end_of_period : Optional[int] - Cash, cash equivalents, and restricted cash at end of period - free_cash_flow : Optional[int] - Net cash flow from operating, investing and financing activities - operating_cash_flow : Optional[int] - Net cash flow from operating activities + reported_currency : Optional[str] + Reported currency in the statement. (provider: fmp) + filling_date : Optional[date] + Filling date. (provider: fmp) + accepted_date : Optional[datetime] + Accepted date. (provider: fmp) calendar_year : Optional[int] - Calendar Year (provider: fmp) + Calendar year. (provider: fmp) + change_in_working_capital : Optional[int] + Change in working capital. (provider: fmp) + other_working_capital : Optional[int] + Other working capital. (provider: fmp) + common_stock_issued : Optional[int] + Common stock issued. (provider: fmp) + effect_of_forex_changes_on_cash : Optional[int] + Effect of forex changes on cash. (provider: fmp) + cash_at_beginning_of_period : Optional[int] + Cash at beginning of period. (provider: fmp) + cash_at_end_of_period : Optional[int] + Cash, cash equivalents, and restricted cash at end of period (provider: fmp) + operating_cash_flow : Optional[int] + Operating cash flow. (provider: fmp) + capital_expenditure : Optional[int] + Capital expenditure. (provider: fmp) + free_cash_flow : Optional[int] + Free cash flow. (provider: fmp) link : Optional[str] - None + Link to the statement. (provider: fmp) final_link : Optional[str] - Final Link (provider: fmp)""" # noqa: E501 + Link to the final statement. (provider: fmp)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -673,7 +672,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -684,16 +682,15 @@ class CLASS_stocks_fa(Container): @validate_arguments def cash_growth( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - limit: typing_extensions.Annotated[ + limit: Annotated[ int, OpenBBCustomParameter(description="The number of data entries to return."), ] = 10, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Cash Flow Statement Growth. @@ -704,9 +701,7 @@ class CLASS_stocks_fa(Container): Symbol to get data for. limit : int The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -716,7 +711,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[CashFlowStatementGrowth] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -803,7 +798,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -814,12 +808,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def comp( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Executive Compensation. @@ -828,9 +821,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -840,7 +831,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[ExecutiveCompensation] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -886,7 +877,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -897,20 +887,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def comsplit( self, - start_date: typing_extensions.Annotated[ + start_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="Start date of the data, in YYYY-MM-DD format." ), ] = None, - end_date: typing_extensions.Annotated[ + end_date: Annotated[ Union[datetime.date, None, str], OpenBBCustomParameter( description="End date of the data, in YYYY-MM-DD format." ), ] = None, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Stock Split Calendar. @@ -921,9 +910,7 @@ class CLASS_stocks_fa(Container): Start date of the data, in YYYY-MM-DD format. end_date : Union[datetime.date, NoneType, str] End date of the data, in YYYY-MM-DD format. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -933,7 +920,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[StockSplitCalendar] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -964,7 +951,6 @@ class CLASS_stocks_fa(Container): "end_date": end_date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -975,12 +961,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def divs( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Historical Dividends. @@ -989,9 +974,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1001,7 +984,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[HistoricalDividends] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1035,7 +1018,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1046,16 +1028,15 @@ class CLASS_stocks_fa(Container): @validate_arguments def earning( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - limit: typing_extensions.Annotated[ - Union[int, None], + limit: Annotated[ + Optional[int], OpenBBCustomParameter(description="The number of data entries to return."), ] = 50, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Earnings Calendar. @@ -1064,11 +1045,9 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - limit : Union[int, NoneType] + limit : Optional[int] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1078,7 +1057,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[EarningsCalendar] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1117,7 +1096,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1128,12 +1106,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def emp( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Number of Employees. @@ -1142,9 +1119,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1154,7 +1129,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[HistoricalEmployees] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1192,7 +1167,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1203,20 +1177,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def est( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ - Literal["quarter", "annual"], + period: Annotated[ + Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - limit: typing_extensions.Annotated[ + limit: Annotated[ int, OpenBBCustomParameter(description="The number of data entries to return."), ] = 30, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Analyst Estimates. @@ -1225,13 +1198,11 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - period : Literal['quarter', 'annual'] + period : Literal['annual', 'quarter'] Period of the data to return. limit : int The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1241,7 +1212,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[AnalystEstimates] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1307,7 +1278,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1318,22 +1288,21 @@ class CLASS_stocks_fa(Container): @validate_arguments def income( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ + period: Annotated[ Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - limit: typing_extensions.Annotated[ - Union[pydantic.types.NonNegativeInt, None], + limit: Annotated[ + Optional[pydantic.types.NonNegativeInt], OpenBBCustomParameter(description="The number of data entries to return."), ] = 12, - chart: bool = False, - provider: Union[Literal["fmp", "polygon"], None] = None, + provider: Optional[Literal["fmp", "intrinio", "polygon", "yfinance"]] = None, **kwargs - ) -> OBBject[List]: + ) -> OBBject[BaseModel]: """Income Statement. Parameters @@ -1342,47 +1311,47 @@ class CLASS_stocks_fa(Container): Symbol to get data for. period : Literal['annual', 'quarter'] Period of the data to return. - limit : Union[pydantic.types.NonNegativeInt, NoneType] + limit : Optional[pydantic.types.NonNegativeInt] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon', 'yfinance']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. - cik : Union[str, NoneType] - The CIK of the company if no symbol is provided. (provider: fmp) - company_name : Union[str, NoneType] + type : Literal['reported', 'standardized'] + Type of the statement to be fetched. (provider: intrinio) + year : Optional[int] + Year of the statement to be fetched. (provider: intrinio) + company_name : Optional[str] Name of the company. (provider: polygon) - company_name_search : Union[str, NoneType] + company_name_search : Optional[str] Name of the company to search. (provider: polygon) - sic : Union[str, NoneType] + sic : Optional[str] The Standard Industrial Classification (SIC) of the company. (provider: polygon) - filing_date : Union[datetime.date, NoneType] + filing_date : Optional[datetime.date] Filing date of the financial statement. (provider: polygon) - filing_date_lt : Union[datetime.date, NoneType] + filing_date_lt : Optional[datetime.date] Filing date less than the given date. (provider: polygon) - filing_date_lte : Union[datetime.date, NoneType] + filing_date_lte : Optional[datetime.date] Filing date less than or equal to the given date. (provider: polygon) - filing_date_gt : Union[datetime.date, NoneType] + filing_date_gt : Optional[datetime.date] Filing date greater than the given date. (provider: polygon) - filing_date_gte : Union[datetime.date, NoneType] + filing_date_gte : Optional[datetime.date] Filing date greater than or equal to the given date. (provider: polygon) - period_of_report_date : Union[datetime.date, NoneType] + period_of_report_date : Optional[datetime.date] Period of report date of the financial statement. (provider: polygon) - period_of_report_date_lt : Union[datetime.date, NoneType] + period_of_report_date_lt : Optional[datetime.date] Period of report date less than the given date. (provider: polygon) - period_of_report_date_lte : Union[datetime.date, NoneType] + period_of_report_date_lte : Optional[datetime.date] Period of report date less than or equal to the given date. (provider: polygon) - period_of_report_date_gt : Union[datetime.date, NoneType] + period_of_report_date_gt : Optional[datetime.date] Period of report date greater than the given date. (provider: polygon) - period_of_report_date_gte : Union[datetime.date, NoneType] + period_of_report_date_gte : Optional[datetime.date] Period of report date greater than or equal to the given date. (provider: polygon) - include_sources : Union[bool, NoneType] + include_sources : Optional[bool] Whether to include the sources of the financial statement. (provider: polygon) - order : Union[Literal['asc', 'desc'], NoneType] + order : Optional[Literal['asc', 'desc']] Order of the financial statement. (provider: polygon) - sort : Union[Literal['filing_date', 'period_of_report_date'], NoneType] + sort : Optional[Literal['filing_date', 'period_of_report_date']] Sort of the financial statement. (provider: polygon) Returns @@ -1390,7 +1359,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[IncomeStatement] Serializable results. - provider : Union[Literal['fmp', 'polygon'], NoneType] + provider : Optional[Literal['fmp', 'intrinio', 'polygon', 'yfinance']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1401,22 +1370,14 @@ class CLASS_stocks_fa(Container): IncomeStatement --------------- + symbol : Optional[str] + Symbol to get data for. date : Optional[date] Date of the income statement. - symbol : Optional[str] - Symbol of the company. - cik : Optional[str] - Central Index Key. - currency : Optional[str] - Reporting currency. - filing_date : Optional[date] - Filling date. - accepted_date : Optional[datetime] - Accepted date. - calendar_year : Optional[int] - Calendar year. period : Optional[str] Period of the income statement. + cik : Optional[str] + Central Index Key. revenue : Optional[int] Revenue. cost_of_revenue : Optional[int] @@ -1473,24 +1434,26 @@ class CLASS_stocks_fa(Container): Weighted average shares outstanding. weighted_average_shares_outstanding_dil : Optional[int] Weighted average shares outstanding diluted. - link : Optional[str] - Link to the income statement. - final_link : Optional[str] - Final link to the income statement. + income_loss_from_continuing_operations_before_tax : Optional[float] + Income/Loss From Continuing Operations After Tax (provider: polygon) income_loss_from_continuing_operations_after_tax : Optional[float] - None + Income/Loss From Continuing Operations After Tax (provider: polygon) benefits_costs_expenses : Optional[float] - None - net_income_loss_attributable_to_noncontrolling_interest : Optional[int] - None + Benefits, Costs And Expenses (provider: polygon) + net_income_loss_attributable_to_noncontrolling_interest : Optional[float] + Net Income/Loss Attributable To Noncontrolling Interest (provider: polygon) net_income_loss_attributable_to_parent : Optional[float] - None - net_income_loss_available_to_common_stockholders_basic : Optional[float] - None + Net Income/Loss Attributable To Parent (provider: polygon) + income_tax_expense_benefit_deferred : Optional[float] + Income Tax Expense/Benefit Deferred (provider: polygon) participating_securities_distributed_and_undistributed_earnings_loss_basic : Optional[float] - None + Participating Securities Distributed And Undistributed Earnings Loss Basic (provider: polygon) + net_income_loss_available_to_common_stockholders_basic : Optional[float] + Net Income/Loss Available To Common Stockholders Basic (provider: polygon) + nonoperating_income_loss : Optional[float] + Nonoperating Income Loss (provider: polygon) preferred_stock_dividends_and_other_adjustments : Optional[float] - None""" # noqa: E501 + Preferred Stock Dividends And Other Adjustments (provider: polygon)""" # noqa: E501 inputs = filter_inputs( provider_choices={ @@ -1502,7 +1465,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1513,20 +1475,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def income_growth( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - limit: typing_extensions.Annotated[ + limit: Annotated[ int, OpenBBCustomParameter(description="The number of data entries to return."), ] = 10, - period: typing_extensions.Annotated[ + period: Annotated[ Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Income Statement Growth. @@ -1539,9 +1500,7 @@ class CLASS_stocks_fa(Container): The number of data entries to return. period : Literal['annual', 'quarter'] Period of the data to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1551,7 +1510,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[IncomeStatementGrowth] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1631,7 +1590,6 @@ class CLASS_stocks_fa(Container): "period": period, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1642,12 +1600,12 @@ class CLASS_stocks_fa(Container): @validate_arguments def ins( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - transactionType: typing_extensions.Annotated[ - Union[ + transactionType: Annotated[ + Optional[ List[ Literal[ "A-Award", @@ -1669,25 +1627,23 @@ class CLASS_stocks_fa(Container): "X-InTheMoney", "Z-Trust", ] - ], - None, + ] ], OpenBBCustomParameter(description="Type of the transaction."), ] = ["P-Purchase"], - reportingCik: typing_extensions.Annotated[ - Union[int, None], + reportingCik: Annotated[ + Optional[int], OpenBBCustomParameter(description="CIK of the reporting owner."), ] = None, - companyCik: typing_extensions.Annotated[ - Union[int, None], + companyCik: Annotated[ + Optional[int], OpenBBCustomParameter(description="CIK of the company owner."), ] = None, - page: typing_extensions.Annotated[ - Union[int, None], + page: Annotated[ + Optional[int], OpenBBCustomParameter(description="Page number of the data to fetch."), ] = 0, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Stock Insider Trading. @@ -1696,17 +1652,15 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - transactionType : Union[List[Literal['A-Award', 'C-Conversion', 'D-Return', 'E-ExpireShort', 'F-InKind', 'G-Gift', 'H-ExpireLong', 'I-Discretionary', 'J-Other', 'L-Small', 'M-Exempt', 'O-OutOfTheMoney', 'P-Purchase', 'S-Sale', 'U-Tender', 'W-Will', 'X-InTheMoney', 'Z-Trust']], NoneType] + transactionType : Optional[List[Literal['A-Award', 'C-Conversion', 'D-Return', 'E-ExpireShort', 'F-InKind', 'G-Gift', 'H-ExpireLong', 'I-Discretionary', 'J-Other', 'L-Small', 'M-Exempt', 'O-OutOfTheMoney', 'P-Purchase', 'S-Sale', 'U-Tender', 'W-Will', 'X-InTheMoney', 'Z-Trust']]] Type of the transaction. - reportingCik : Union[int, NoneType] + reportingCik : Optional[int] CIK of the reporting owner. - companyCik : Union[int, NoneType] + companyCik : Optional[int] CIK of the company owner. - page : Union[int, NoneType] + page : Optional[int] Page number of the data to fetch. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1716,7 +1670,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[StockInsiderTrading] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1770,7 +1724,6 @@ class CLASS_stocks_fa(Container): "page": page, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1781,19 +1734,18 @@ class CLASS_stocks_fa(Container): @validate_arguments def ins_own( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - include_current_quarter: typing_extensions.Annotated[ + include_current_quarter: Annotated[ bool, OpenBBCustomParameter(description="Include current quarter data.") ] = False, - date: typing_extensions.Annotated[ - Union[datetime.date, None], + date: Annotated[ + Optional[datetime.date], OpenBBCustomParameter(description="A specific date to get data for."), ] = None, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Institutional Ownership. @@ -1804,11 +1756,9 @@ class CLASS_stocks_fa(Container): Symbol to get data for. include_current_quarter : bool Include current quarter data. - date : Union[datetime.date, NoneType] + date : Optional[datetime.date] A specific date to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1818,7 +1768,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[InstitutionalOwnership] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -1913,7 +1863,6 @@ class CLASS_stocks_fa(Container): "date": date, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -1924,20 +1873,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def metrics( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ + period: Annotated[ Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - limit: typing_extensions.Annotated[ - Union[int, None], + limit: Annotated[ + Optional[int], OpenBBCustomParameter(description="The number of data entries to return."), ] = 100, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Key Metrics. @@ -1948,11 +1896,9 @@ class CLASS_stocks_fa(Container): Symbol to get data for. period : Literal['annual', 'quarter'] Period of the data to return. - limit : Union[int, NoneType] + limit : Optional[int] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -1962,7 +1908,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[KeyMetrics] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2104,7 +2050,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2115,12 +2060,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def mgmt( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Key Executives. @@ -2129,9 +2073,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2141,7 +2083,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[KeyExecutives] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2175,7 +2117,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2186,12 +2127,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def overview( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[BaseModel]: """Company Overview. @@ -2200,9 +2140,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2212,7 +2150,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[CompanyOverview] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2304,7 +2242,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2315,20 +2252,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def own( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - date: typing_extensions.Annotated[ - Union[datetime.date, None], + date: Annotated[ + Optional[datetime.date], OpenBBCustomParameter(description="A specific date to get data for."), ] = None, - page: typing_extensions.Annotated[ - Union[int, None], + page: Annotated[ + Optional[int], OpenBBCustomParameter(description="Page number of the data to fetch."), ] = 0, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Stock Ownership. @@ -2337,13 +2273,11 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - date : Union[datetime.date, NoneType] + date : Optional[datetime.date] A specific date to get data for. - page : Union[int, NoneType] + page : Optional[int] Page number of the data to fetch. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2353,7 +2287,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[StockOwnership] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2453,7 +2387,6 @@ class CLASS_stocks_fa(Container): "page": page, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2464,12 +2397,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def pt( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[BaseModel]: """Price Target Consensus. @@ -2478,9 +2410,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2490,7 +2420,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[PriceTargetConsensus] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2520,7 +2450,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2531,12 +2460,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def pta( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Price Target. @@ -2545,9 +2473,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2559,7 +2485,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[PriceTarget] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2607,7 +2533,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2618,20 +2543,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def ratios( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ + period: Annotated[ Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - limit: typing_extensions.Annotated[ - Union[pydantic.types.NonNegativeInt, None], + limit: Annotated[ + Optional[pydantic.types.NonNegativeInt], OpenBBCustomParameter(description="The number of data entries to return."), ] = 12, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Extensive set of ratios over time. @@ -2642,11 +2566,9 @@ class CLASS_stocks_fa(Container): Symbol to get data for. period : Literal['annual', 'quarter'] Period of the data to return. - limit : Union[pydantic.types.NonNegativeInt, NoneType] + limit : Optional[pydantic.types.NonNegativeInt] The number of data entries to return. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2656,7 +2578,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[FinancialRatios] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2792,7 +2714,6 @@ class CLASS_stocks_fa(Container): "limit": limit, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2803,20 +2724,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def revgeo( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ - Literal["quarter", "annual"], + period: Annotated[ + Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - structure: typing_extensions.Annotated[ + structure: Annotated[ Literal["hierarchical", "flat"], OpenBBCustomParameter(description="Structure of the returned data."), ] = "flat", - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Revenue Geographic. @@ -2825,13 +2745,11 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - period : Literal['quarter', 'annual'] + period : Literal['annual', 'quarter'] Period of the data to return. structure : Literal['hierarchical', 'flat'] Structure of the returned data. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2841,7 +2759,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[RevenueGeographic] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2877,7 +2795,6 @@ class CLASS_stocks_fa(Container): "structure": structure, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2888,20 +2805,19 @@ class CLASS_stocks_fa(Container): @validate_arguments def revseg( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - period: typing_extensions.Annotated[ - Literal["quarter", "annual"], + period: Annotated[ + Literal["annual", "quarter"], OpenBBCustomParameter(description="Period of the data to return."), ] = "annual", - structure: typing_extensions.Annotated[ + structure: Annotated[ Literal["hierarchical", "flat"], OpenBBCustomParameter(description="Structure of the returned data."), ] = "flat", - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Revenue Business Line. @@ -2910,13 +2826,11 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - period : Literal['quarter', 'annual'] + period : Literal['annual', 'quarter'] Period of the data to return. structure : Literal['hierarchical', 'flat'] Structure of the returned data. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2926,7 +2840,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[RevenueBusinessLine] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -2952,7 +2866,6 @@ class CLASS_stocks_fa(Container): "structure": structure, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -2963,12 +2876,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def shrs( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Share Statistics. @@ -2977,9 +2889,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -2989,7 +2899,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[ShareStatistics] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -3021,7 +2931,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -3032,12 +2941,11 @@ class CLASS_stocks_fa(Container): @validate_arguments def split( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Historical Stock Splits. @@ -3046,9 +2954,7 @@ class CLASS_stocks_fa(Container): ---------- symbol : Union[str, List[str]] Symbol to get data for. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -3058,7 +2964,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[HistoricalStockSplits] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -3086,7 +2992,6 @@ class CLASS_stocks_fa(Container): "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( @@ -3097,22 +3002,21 @@ class CLASS_stocks_fa(Container): @validate_arguments def transcript( self, - symbol: typing_extensions.Annotated[ + symbol: Annotated[ Union[str, List[str]], OpenBBCustomParameter(description="Symbol to get data for."), ], - year: typing_extensions.Annotated[ + year: Annotated[ int, OpenBBCustomParameter(description="Year of the earnings call transcript."), ], - quarter: typing_extensions.Annotated[ + quarter: Annotated[ Literal[1, 2, 3, 4], OpenBBCustomParameter( description="Quarter of the earnings call transcript." ), ] = 1, - chart: bool = False, - provider: Union[Literal["fmp"], None] = None, + provider: Optional[Literal["fmp"]] = None, **kwargs ) -> OBBject[List]: """Earnings Call Transcript. @@ -3125,9 +3029,7 @@ class CLASS_stocks_fa(Container): Year of the earnings call transcript. quarter : Literal[1, 2, 3, 4] Quarter of the earnings call transcript. - chart : bool - Whether to create a chart or not, by default False. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] The provider to use for the query, by default None. If None, the provider specified in defaults is selected or 'fmp' if there is no default. @@ -3137,7 +3039,7 @@ class CLASS_stocks_fa(Container): OBBject results : List[EarningsCallTranscript] Serializable results. - provider : Union[Literal['fmp'], NoneType] + provider : Optional[Literal['fmp']] Provider name. warnings : Optional[List[Warning_]] List of warnings. @@ -3169,7 +3071,6 @@ class CLASS_stocks_fa(Container): "quarter": quarter, }, extra_params=kwargs, - chart=chart, ) return self._command_runner.run( diff --git a/openbb_sdk/openbb/package/stocks_options.py b/openbb_sdk/openbb/package/stocks_options.py new file mode 100644 index 00000000000..545fe5f3112 --- /dev/null +++ b/openbb_sdk/openbb/package/stocks_options.py @@ -0,0 +1,147 @@ +### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### + +from typing import List, Literal, Optional, Union + +from openbb_core.app.model.custom_parameter import OpenBBCustomParameter +from openbb_core.app.model.obbject import OBBject +from openbb_core.app.static.container import Container +from openbb_core.app.static.filters import filter_inputs +from pydantic import validate_arguments +from typing_extensions import Annotated + + +class CLASS_stocks_options(Container): + """/stocks/options + chains + """ + + def __repr__(self) -> str: + return self.__doc__ or "" + + @validate_arguments + def chains( + self, + symbol: Annotated[ + Union[str, List[str]], + OpenBBCustomParameter(description="Symbol to get data for."), + ], + provider: Optional[Literal["cboe", "intrinio"]] = None, + **kwargs + ) -> OBBject[List]: + """Get the complete options chain for a ticker. + + Parameters + ---------- + symbol : Union[str, List[str]] + Symbol to get data for. + provider : Optional[Literal['cboe', 'intrinio']] + The provider to use for the query, by default None. + If None, the provider specified in defaults is selected or 'cboe' if there is + no default. + date : Union[datetime.date, str, NoneType] + Date for which the options chains are returned. (provider: intrinio) + + Returns + ------- + OBBject + results : List[OptionsChains] + Serializable results. + provider : Optional[Literal['cboe', 'intrinio']] + Provider name. + warnings : Optional[List[Warning_]] + List of warnings. + chart : Optional[Chart] + Chart object. + metadata: Optional[Metadata] + Metadata info about the command execution. + + OptionsChains + ------------- + expiration : Optional[datetime] + Expiration date of the contract. + strike : Optional[float] + Strike price of the contract. + option_type : Optional[str] + Call or Put. + contract_symbol : Optional[str] + Contract symbol for the option. + bid : Optional[float] + Bid price of the contract. + ask : Optional[float] + Ask price of the contract. + open_interest : Optional[float] + Open interest on the contract. + volume : Optional[float] + Current trading volume on the contract. + bid_size : Optional[int] + Bid size for the option. (provider: cboe) + ask_size : Optional[int] + Ask size for the option. (provider: cboe) + theoretical : Optional[float] + Theoretical value of the option. (provider: cboe) + open : Optional[float] + Opening price of the option. (provider: cboe) + high : Optional[float] + High price of the option. (provider: cboe) + low : Optional[float] + Low price of the option. (provider: cboe) + last_trade_price : Optional[float] + Last trade price of the option. (provider: cboe) + tick : Optional[str] + Whether the last tick was up or down in price. (provider: cboe) + prev_close : Optional[float] + Previous closing price of the option. (provider: cboe) + change : Optional[float] + Change in price of the option. (provider: cboe) + change_percent : Optional[float] + Change, in percent, of the option. (provider: cboe) + implied_volatility : Optional[float] + Implied volatility of the option. (provider: cboe) + delta : Optional[float] + Delta of the option. (provider: cboe) + gamma : Optional[float] + Gamma of the option. (provider: cboe) + vega : Optional[float] + Vega of the option. (provider: cboe) + theta : Optional[float] + Theta of the option. (provider: cboe) + rho : Optional[float] + Rho of the option. (provider: cboe) + last_trade_timestamp : Optional[datetime] + Last trade timestamp of the option. (provider: cboe) + dte : Optional[int] + Days to expiration for the option. (provider: cboe) + mark : Optional[float] + The mid-price between the latest bid-ask spread. (provider: intrinio) + open_bid : Optional[float] + The lowest bid price for the option that day. (provider: intrinio) + open_ask : Optional[float] + The lowest ask price for the option that day. (provider: intrinio) + bid_low : Optional[float] + The lowest bid price for the option that day. (provider: intrinio) + ask_low : Optional[float] + The lowest ask price for the option that day. (provider: intrinio) + bid_high : Optional[float] + The highest bid price for the option that day. (provider: intrinio) + ask_high : Optional[float] + The highest ask price for the option that day. (provider: intrinio) + close : Optional[float] + The close price for the option that day. (provider: intrinio) + eod_date : Optional[date] + Historical date for which the options chains data is from. (provider: intrinio) + """ # noqa: E501 + + inputs = filter_inputs( + provider_choices={ + "provider": provider, + }, + standard_params={ + "symbol": ",".join(symbol) if isinstance(symbol, list) else symbol, + }, + extra_params=kwargs, + ) + + return self._command_runner.run( + "/stocks/options/chains", + **inputs, + ) diff --git a/openbb_sdk/openbb/package/ta.py b/openbb_sdk/openbb/package/ta.py new file mode 100644 index 00000000000..3cfc2d7a1e8 --- /dev/null +++ b/openbb_sdk/openbb/package/ta.py @@ -0,0 +1,1486 @@ +### THIS FILE IS AUTO-GENERATED. DO NOT EDIT. ### + +from typing import List, Literal, Optional, Union + +import openbb_provider +import pandas +import pydantic +import pydantic.types +from openbb_core.app.model.obbject import OBBject +from openbb_core.app.static.container import Container +from openbb_core.app.static.filters import filter_inputs +from pydantic import validate_arguments + + +class CLASS_ta(Container): + """/ta + ad + adosc + adx + aroon + atr + bbands + cci + cg + clenow + cones + demark + donchian + ema + fib + fisher + hma + ichimoku + kc + macd + obv + rsi + sma + stoch + vwap + wma + zlma + """ + + def __repr__(self) -> str: + return self.__doc__ or "" + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def ad( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + offset: int = 0, + ) -> OBBject[List]: + """ + The Accumulation/Distribution Line is similar to the On Balance + Volume (OBV), which sums the volume times +1/-1 based on whether the close is + higher than the previous close. The Accumulation/Distribution indicator, however + multiplies the volume by the close location value (CLV). The CLV is based on the + movement of the issue within a single bar and can be +1, -1 or zero. + + + The Accumulation/Distribution Line is interpreted by looking for a divergence in + the direction of the indicator relative to price. If the Accumulation/Distribution + Line is trending upward it indicates that the price may follow. Also, if the + Accumulation/Distribution Line becomes flat while the price is still rising (or falling) + then it signals an impending flattening of the price. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + offset : int, optional + Offset of the AD, by default 0. + + Returns + ------- + OBBject[List[Data]] + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> ad_data = obb.ta.ad(data=stock_data.results,offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + offset=offset, + ) + + return self._command_runner.run( + "/ta/ad", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def adosc( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + fast: pydantic.types.PositiveInt = 3, + slow: pydantic.types.PositiveInt = 10, + offset: int = 0, + ) -> OBBject[List]: + """ + Accumulation/Distribution Oscillator, also known as the Chaikin Oscillator + is essentially a momentum indicator, but of the Accumulation-Distribution line + rather than merely price. It looks at both the strength of price moves and the + underlying buying and selling pressure during a given time period. The oscillator + reading above zero indicates net buying pressure, while one below zero registers + net selling pressure. Divergence between the indicator and pure price moves are + the most common signals from the indicator, and often flag market turning points. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + fast : PositiveInt, optional + Number of periods to be used for the fast calculation, by default 3. + slow : PositiveInt, optional + Number of periods to be used for the slow calculation, by default 10. + offset : int, optional + Offset to be used for the calculation, by default 0. + + Returns + ------- + OBBject[List[Data]] + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> adosc_data = obb.ta.adosc(data=stock_data.results, fast=3, slow=10, offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + fast=fast, + slow=slow, + offset=offset, + ) + + return self._command_runner.run( + "/ta/adosc", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def adx( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: int = 50, + scalar: float = 100.0, + drift: int = 1, + chart: bool = False, + ) -> OBBject[List]: + """ + The ADX is a Welles Wilder style moving average of the Directional Movement Index (DX). + The values range from 0 to 100, but rarely get above 60. To interpret the ADX, consider + a high number to be a strong trend, and a low number, a weak trend. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + length : int, optional + Number of periods for the ADX, by default 50. + scalar : float, optional + Scalar value for the ADX, by default 100.0. + drift : int, optional + Drift value for the ADX, by default 1. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> adx_data = obb.ta.adx(data=stock_data.results,length=50,scalar=100.0,drift=1) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + scalar=scalar, + drift=drift, + chart=chart, + ) + + return self._command_runner.run( + "/ta/adx", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def aroon( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: int = 25, + scalar: int = 100, + chart: bool = False, + ) -> OBBject[List]: + """ + The word aroon is Sanskrit for "dawn's early light." The Aroon + indicator attempts to show when a new trend is dawning. The indicator consists + of two lines (Up and Down) that measure how long it has been since the highest + high/lowest low has occurred within an n period range. + + When the Aroon Up is + staying between 70 and 100 then it indicates an upward trend. When the Aroon Down + is staying between 70 and 100 then it indicates an downward trend. A strong upward + trend is indicated when the Aroon Up is above 70 while the Aroon Down is below 30. + Likewise, a strong downward trend is indicated when the Aroon Down is above 70 while + the Aroon Up is below 30. Also look for crossovers. When the Aroon Down crosses above + the Aroon Up, it indicates a weakening of the upward trend (and vice versa). + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index: str, optional + Index column name to use with `data`, by default "date". + length : int, optional + Number of periods to be used for the calculation, by default 25. + scalar : int, optional + Scalar to be used for the calculation, by default 100. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> aroon_data = obb.ta.aroon(data=stock_data.results, length=25, scalar=100) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + scalar=scalar, + chart=chart, + ) + + return self._command_runner.run( + "/ta/aroon", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def atr( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: pydantic.types.PositiveInt = 14, + mamode: Literal["rma", "ema", "sma", "wma"] = "rma", + drift: pydantic.types.NonNegativeInt = 1, + offset: int = 0, + ) -> OBBject[List]: + """ + Average True Range is used to measure volatility, especially volatility caused by + gaps or limit moves. + + Parameters + ---------- + data : List[Data] + List of data to apply the indicator to. + index : str, optional + Index column name, by default "date" + length : PositiveInt, optional + It's period, by default 14 + mamode : Literal["rma", "ema", "sma", "wma"], optional + Moving average mode, by default "rma" + drift : NonNegativeInt, optional + The difference period, by default 1 + offset : int, optional + How many periods to offset the result, by default 0 + + Returns + ------- + OBBject[List[Data]] + List of data with the indicator applied. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> atr_data = obb.ta.atr(data=stock_data.results) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + mamode=mamode, + drift=drift, + offset=offset, + ) + + return self._command_runner.run( + "/ta/atr", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def bbands( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 50, + std: pydantic.types.NonNegativeFloat = 2, + mamode: Literal["sma", "ema", "wma", "rma"] = "sma", + offset: int = 0, + ) -> OBBject[List]: + """ + Bollinger Bands consist of three lines. The middle band is a simple + moving average (generally 20 periods) of the typical price (TP). The upper and lower + bands are F standard deviations (generally 2) above and below the middle band. + The bands widen and narrow when the volatility of the price is higher or lower, + respectively. + + Bollinger Bands do not, in themselves, generate buy or sell signals; + they are an indicator of overbought or oversold conditions. When the price is near the + upper or lower band it indicates that a reversal may be imminent. The middle band + becomes a support or resistance level. The upper and lower bands can also be + interpreted as price targets. When the price bounces off of the lower band and crosses + the middle band, then the upper band becomes the price target. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date". + length : int, optional + Number of periods to be used for the calculation, by default 50. + std : NonNegativeFloat, optional + Standard deviation to be used for the calculation, by default 2. + mamode : Literal["sma", "ema", "wma", "rma"], optional + Moving average mode to be used for the calculation, by default "sma". + offset : int, optional + Offset to be used for the calculation, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> bbands = obb.ta.bbands( + >>> data=stock_data.results, target="close", length=50, std=2, mamode="sma", offset=0 + >>> ) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + std=std, + mamode=mamode, + offset=offset, + ) + + return self._command_runner.run( + "/ta/bbands", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def cci( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: pydantic.types.PositiveInt = 14, + scalar: pydantic.types.PositiveFloat = 0.015, + ) -> OBBject[List]: + """ + The CCI is designed to detect beginning and ending market trends. + The range of 100 to -100 is the normal trading range. CCI values outside of this + range indicate overbought or oversold conditions. You can also look for price + divergence in the CCI. If the price is making new highs, and the CCI is not, + then a price correction is likely. + + Parameters + ---------- + data : List[Data] + The data to use for the CCI calculation. + index : str, optional + Index column name to use with `data`, by default "date". + length : PositiveInt, optional + The length of the CCI, by default 14. + scalar : PositiveFloat, optional + The scalar of the CCI, by default 0.015. + + Returns + ------- + OBBject[List[Data]] + The CCI data. + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + scalar=scalar, + ) + + return self._command_runner.run( + "/ta/cci", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def cg( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: pydantic.types.PositiveInt = 14, + ) -> OBBject[List]: + """ + The Center of Gravity indicator, in short, is used to anticipate future price movements + and to trade on price reversals as soon as they happen. However, just like other oscillators, + the COG indicator returns the best results in range-bound markets and should be avoided when + the price is trending. Traders who use it will be able to closely speculate the upcoming + price change of the asset. + + Parameters + ---------- + data : List[Data] + The data to use for the COG calculation. + index : str, optional + Index column name to use with `data`, by default "date" + length : PositiveInt, optional + The length of the COG, by default 14 + + Returns + ------- + OBBject[List[Data]] + The COG data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> cg_data = obb.ta.cg(data=stock_data.results, length=14) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + ) + + return self._command_runner.run( + "/ta/cg", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def clenow( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + target: str = "adj_close", + period: pydantic.types.PositiveInt = 90, + ) -> OBBject[List]: + """ + Clenow Volatility Adjusted Momentum. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + target : str, optional + Target column name, by default "adj_close". + period : PositiveInt, optional + Number of periods for the momentum, by default 90. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> clenow_data = obb.ta.clenow(data=stock_data.results,period=90) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + target=target, + period=period, + ) + + return self._command_runner.run( + "/ta/clenow", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def cones( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + lower_q: float = 0.25, + upper_q: float = 0.75, + model: Literal[ + "STD", + "Parkinson", + "Garman-Klass", + "Hodges-Tompkins", + "Rogers-Satchell", + "Yang-Zhang", + ] = "STD", + is_crypto: bool = False, + ) -> OBBject[List]: + """Calculate the realized volatility quantiles over rolling windows of time. + + The model for calculating volatility is selectable. + + Parameters + ---------- + data : List[Data] + The data to use for the calculation. + index : str, optional + Index column name to use with `data`, by default "date" + lower_q : float, optional + The lower quantile value for calculations + upper_q : float, optional + The upper quantile value for calculations + model : Literal["STD", "Parkinson", "Garman-Klass", "Hodges-Tompkins", "Rogers-Satchell", "Yang-Zhang"], optional + The model used to calculate realized volatility + + Standard deviation measures how widely returns are dispersed from the average return. + It is the most common (and biased) estimator of volatility. + + Parkinson volatility uses the high and low price of the day rather than just close to close prices. + It is useful for capturing large price movements during the day. + + Garman-Klass volatility extends Parkinson volatility by taking into account the opening and closing price. + As markets are most active during the opening and closing of a trading session; + it makes volatility estimation more accurate. + + Hodges-Tompkins volatility is a bias correction for estimation using an overlapping data sample. + It produces unbiased estimates and a substantial gain in efficiency. + + Rogers-Satchell is an estimator for measuring the volatility with an average return not equal to zero. + Unlike Parkinson and Garman-Klass estimators, Rogers-Satchell incorporates a drift term, + mean return not equal to zero. + + Yang-Zhang volatility is the combination of the overnight (close-to-open volatility). + It is a weighted average of the Rogers-Satchell volatility and the open-to-close volatility. + is_crypto : bool, optional + Whether the data is crypto or not. If True, volatility is calculated for 365 days instead of 252 + + Returns + ------- + OBBject[List[Data]] + The cones data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> cones_data = obb.ta.cones(data=stock_data.results, lower_q=0.25, upper_q=0.75, model="STD") + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + lower_q=lower_q, + upper_q=upper_q, + model=model, + is_crypto=is_crypto, + ) + + return self._command_runner.run( + "/ta/cones", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def demark( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + target: str = "close", + show_all: bool = False, + asint: bool = False, + offset: int = 0, + ) -> OBBject[List]: + """ + Demark sequential indicator + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + target : str, optional + Target column name, by default "close". + show_all : bool, optional + Show 1 - 13. If set to False, show 6 - 9 + asint : bool, optional + If True, fill NAs with 0 and change type to int, by default False + offset : int, optional + How many periods to offset the result + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> demark_data = obb.ta.demark(data=stock_data.results,offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + target=target, + show_all=show_all, + asint=asint, + offset=offset, + ) + + return self._command_runner.run( + "/ta/demark", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def donchian( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + lower_length: pydantic.types.PositiveInt = 20, + upper_length: pydantic.types.PositiveInt = 20, + offset: int = 0, + ) -> OBBject[List]: + """ + Donchian Channels are three lines generated by moving average + calculations that comprise an indicator formed by upper and lower + bands around a midrange or median band. The upper band marks the + highest price of a security over N periods while the lower band + marks the lowest price of a security over N periods. The area + between the upper and lower bands represents the Donchian Channel. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + lower_length : PositiveInt, optional + Number of periods for the lower band, by default 20. + upper_length : PositiveInt, optional + Number of periods for the upper band, by default 20. + offset : int, optional + Offset of the Donchian Channel, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> donchian_data = obb.ta.donchian(data=stock_data.results,lower_length=20,upper_length=20,offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + lower_length=lower_length, + upper_length=upper_length, + offset=offset, + ) + + return self._command_runner.run( + "/ta/donchian", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def ema( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 50, + offset: int = 0, + chart: bool = False, + ) -> OBBject[List]: + """ + The Exponential Moving Average is a staple of technical + analysis and is used in countless technical indicators. In a Simple Moving + Average, each value in the time period carries equal weight, and values outside + of the time period are not included in the average. However, the Exponential + Moving Average is a cumulative calculation, including all data. Past values have + a diminishing contribution to the average, while more recent values have a greater + contribution. This method allows the moving average to be more responsive to changes + in the data. + + Parameters + ---------- + data : List[Data] + The data to use for the calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date" + length : int, optional + The length of the calculation, by default 50. + offset : int, optional + The offset of the calculation, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> ema_data = obb.ta.ema(data=stock_data.results,target="close",length=50,offset=0) + + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + offset=offset, + chart=chart, + ) + + return self._command_runner.run( + "/ta/ema", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def fib( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + close_column: Literal["close", "adj_close"] = "close", + period: pydantic.types.PositiveInt = 120, + start_date: Optional[str] = None, + end_date: Optional[str] = None, + ) -> OBBject[List]: + """Create Fibonacci Retracement Levels. + + Parameters + ---------- + data : List[Data] + List of data to apply the indicator to. + index : str, optional + Index column name, by default "date" + period : PositiveInt, optional + Period to calculate the indicator, by default 120 + + Returns + ------- + OBBject[List[Data]] + List of data with the indicator applied. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> fib_data = obb.ta.fib(data=stock_data.results, period=120) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + close_column=close_column, + period=period, + start_date=start_date, + end_date=end_date, + ) + + return self._command_runner.run( + "/ta/fib", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def fisher( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: pydantic.types.PositiveInt = 14, + signal: pydantic.types.PositiveInt = 1, + ) -> OBBject[List]: + """ + The Fisher Transform is a technical indicator created by John F. Ehlers + that converts prices into a Gaussian normal distribution.1 The indicator + highlights when prices have moved to an extreme, based on recent prices. + This may help in spotting turning points in the price of an asset. It also + helps show the trend and isolate the price waves within a trend. + + Parameters + ---------- + data : List[Data] + List of data to apply the indicator to. + index : str, optional + Index column name, by default "date" + length : PositiveInt, optional + Fisher period, by default 14 + signal : PositiveInt, optional + Fisher Signal period, by default 1 + + Returns + ------- + OBBject[List[Data]] + List of data with the indicator applied. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> fisher_data = obb.ta.fisher(data=stock_data.results, length=14, signal=1) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + signal=signal, + ) + + return self._command_runner.run( + "/ta/fisher", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def hma( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 50, + offset: int = 0, + chart: bool = False, + ) -> OBBject[List]: + """ + The Hull Moving Average solves the age old dilemma of making a moving average + more responsive to current price activity whilst maintaining curve smoothness. + In fact the HMA almost eliminates lag altogether and manages to improve smoothing + at the same time. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date". + length : int, optional + Number of periods for the HMA, by default 50. + offset : int, optional + Offset of the HMA, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> hma_data = obb.ta.hma(data=stock_data.results,target="close",length=50,offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + offset=offset, + chart=chart, + ) + + return self._command_runner.run( + "/ta/hma", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def ichimoku( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + conversion: pydantic.types.PositiveInt = 9, + base: pydantic.types.PositiveInt = 26, + lagging: pydantic.types.PositiveInt = 52, + offset: pydantic.types.PositiveInt = 26, + lookahead: bool = False, + ) -> OBBject[List]: + """ + The Ichimoku Cloud, also known as Ichimoku Kinko Hyo, is a versatile indicator that + defines support and resistance, identifies trend direction, gauges momentum and provides + trading signals. Ichimoku Kinko Hyo translates into "one look equilibrium chart". With + one look, chartists can identify the trend and look for potential signals within that trend. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + conversion : PositiveInt, optional + Number of periods for the conversion line, by default 9. + base : PositiveInt, optional + Number of periods for the base line, by default 26. + lagging : PositiveInt, optional + Number of periods for the lagging span, by default 52. + offset : PositiveInt, optional + Number of periods for the offset, by default 26. + lookahead : bool, optional + drops the Chikou Span Column to prevent potential data leak + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + conversion=conversion, + base=base, + lagging=lagging, + offset=offset, + lookahead=lookahead, + ) + + return self._command_runner.run( + "/ta/ichimoku", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def kc( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + length: pydantic.types.PositiveInt = 20, + scalar: pydantic.types.PositiveFloat = 20, + mamode: Literal["ema", "sma", "wma", "hma", "zlma"] = "ema", + offset: pydantic.types.NonNegativeInt = 0, + ) -> OBBject[List]: + """ + Keltner Channels are volatility-based bands that are placed + on either side of an asset's price and can aid in determining + the direction of a trend.The Keltner channel uses the average + true range (ATR) or volatility, with breaks above or below the top + and bottom barriers signaling a continuation. + + Parameters + ---------- + data : List[Data] + The data to use for the Keltner Channels calculation. + index : str, optional + Index column name to use with `data`, by default "date" + length : PositiveInt, optional + The length of the Keltner Channels, by default 20 + scalar : PositiveFloat, optional + The scalar to use for the Keltner Channels, by default 20 + mamode : Literal["ema", "sma", "wma", "hma", "zlma"], optional + The moving average mode to use for the Keltner Channels, by default "ema" + offset : NonNegativeInt, optional + The offset to use for the Keltner Channels, by default 0 + + Returns + ------- + OBBject[List[Data]] + The Keltner Channels data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> kc_data = obb.ta.kc(data=stock_data.results, length=20, scalar=20, ma_mode="ema", offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + length=length, + scalar=scalar, + mamode=mamode, + offset=offset, + ) + + return self._command_runner.run( + "/ta/kc", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def macd( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + fast: int = 12, + slow: int = 26, + signal: int = 9, + chart: bool = False, + ) -> OBBject[List]: + """ + The Moving Average Convergence Divergence (MACD) is the difference + between two Exponential Moving Averages. The Signal line is an Exponential Moving + Average of the MACD. + + The MACD signals trend changes and indicates the start + of new trend direction. High values indicate overbought conditions, low values + indicate oversold conditions. Divergence with the price indicates an end to the + current trend, especially if the MACD is at extreme high or low values. When the MACD + line crosses above the signal line a buy signal is generated. When the MACD crosses + below the signal line a sell signal is generated. To confirm the signal, the MACD + should be above zero for a buy, and below zero for a sell. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + target : str + Target column name. + fast : int, optional + Number of periods for the fast EMA, by default 12. + slow : int, optional + Number of periods for the slow EMA, by default 26. + signal : int, optional + Number of periods for the signal EMA, by default 9. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> macd_data = obb.ta.macd(data=stock_data.results,target="close",fast=12,slow=26,signal=9) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + fast=fast, + slow=slow, + signal=signal, + chart=chart, + ) + + return self._command_runner.run( + "/ta/macd", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def obv( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + offset: int = 0, + ) -> OBBject[List]: + """ + The On Balance Volume (OBV) is a cumulative total of the up and + down volume. When the close is higher than the previous close, the volume is added + to the running total, and when the close is lower than the previous close, the volume + is subtracted from the running total. + + To interpret the OBV, look for the OBV + to move with the price or precede price moves. If the price moves before the OBV, + then it is a non-confirmed move. A series of rising peaks, or falling troughs, in the + OBV indicates a strong trend. If the OBV is flat, then the market is not trending. + + Parameters + ---------- + data : List[Data] + List of data to apply the indicator to. + index : str, optional + Index column name, by default "date" + offset : int, optional + How many periods to offset the result, by default 0. + + Returns + ------- + OBBject[List[Data]] + List of data with the indicator applied. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> obv_data = obb.ta.obv(data=stock_data.results, offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + offset=offset, + ) + + return self._command_runner.run( + "/ta/obv", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def rsi( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 14, + scalar: float = 100.0, + drift: int = 1, + chart: bool = False, + ) -> OBBject[List]: + """ + The Relative Strength Index (RSI) calculates a ratio of the + recent upward price movements to the absolute price movement. The RSI ranges + from 0 to 100. The RSI is interpreted as an overbought/oversold indicator when + the value is over 70/below 30. You can also look for divergence with price. If + the price is making new highs/lows, and the RSI is not, it indicates a reversal. + + Parameters + ---------- + data : List[Data] + The data to use for the RSI calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date" + length : int, optional + The length of the RSI, by default 14 + scalar : float, optional + The scalar to use for the RSI, by default 100.0 + drift : int, optional + The drift to use for the RSI, by default 1 + + Returns + ------- + OBBject[List[Data]] + The RSI data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> rsi_data = obb.ta.rsi(data=stock_data.results, target="close", length=14, scalar=100.0, drift=1) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + scalar=scalar, + drift=drift, + chart=chart, + ) + + return self._command_runner.run( + "/ta/rsi", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def sma( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 50, + offset: int = 0, + chart: bool = False, + ) -> OBBject[List]: + """ + Moving Averages are used to smooth the data in an array to + help eliminate noise and identify trends. The Simple Moving Average is literally + the simplest form of a moving average. Each output value is the average of the + previous n values. In a Simple Moving Average, each value in the time period carries + equal weight, and values outside of the time period are not included in the average. + This makes it less responsive to recent changes in the data, which can be useful for + filtering out those changes. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date". + length : int, optional + Number of periods to be used for the calculation, by default 50. + offset : int, optional + Offset from the current period, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> sma_data = obb.ta.sma(data=stock_data.results,target="close",length=50,offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + offset=offset, + chart=chart, + ) + + return self._command_runner.run( + "/ta/sma", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def stoch( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + fast_k_period: pydantic.types.NonNegativeInt = 14, + slow_d_period: pydantic.types.NonNegativeInt = 3, + slow_k_period: pydantic.types.NonNegativeInt = 3, + ) -> OBBject[List]: + """ + The Stochastic Oscillator measures where the close is in relation + to the recent trading range. The values range from zero to 100. %D values over 75 + indicate an overbought condition; values under 25 indicate an oversold condition. + When the Fast %D crosses above the Slow %D, it is a buy signal; when it crosses + below, it is a sell signal. The Raw %K is generally considered too erratic to use + for crossover signals. + + Parameters + ---------- + data : List[Data] + The data to use for the Stochastic Oscillator calculation. + index : str, optional + Index column name to use with `data`, by default "date". + fast_k_period : NonNegativeInt, optional + The fast %K period, by default 14. + slow_d_period : NonNegativeInt, optional + The slow %D period, by default 3. + slow_k_period : NonNegativeInt, optional + The slow %K period, by default 3. + + Returns + ------- + OBBject[List[Data]] + The Stochastic Oscillator data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> stoch_data = obb.ta.stoch(data=stock_data.results, fast_k_period=14, slow_d_period=3, slow_k_period=3) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + fast_k_period=fast_k_period, + slow_d_period=slow_d_period, + slow_k_period=slow_k_period, + ) + + return self._command_runner.run( + "/ta/stoch", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def vwap( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + index: str = "date", + anchor: str = "D", + offset: int = 0, + ) -> OBBject[List]: + """ + The Volume Weighted Average Price that measures the average typical price + by volume. It is typically used with intraday charts to identify general direction. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + index : str, optional + Index column name to use with `data`, by default "date". + anchor : str, optional + Anchor period to use for the calculation, by default "D". + See Timeseries Offset Aliases below for additional options: + https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#timeseries-offset-aliases + offset : int, optional + Offset from the current period, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> vwap_data = obb.ta.vwap(data=stock_data.results,anchor="D",offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + index=index, + anchor=anchor, + offset=offset, + ) + + return self._command_runner.run( + "/ta/vwap", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def wma( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 50, + offset: int = 0, + chart: bool = False, + ) -> OBBject[List]: + """ + A Weighted Moving Average puts more weight on recent data and less on past data. + This is done by multiplying each bar’s price by a weighting factor. Because of its + unique calculation, WMA will follow prices more closely than a corresponding Simple + Moving Average. + + Parameters + ---------- + data : List[Data] + The data to use for the calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date". + length : int, optional + The length of the WMA, by default 50. + offset : int, optional + The offset of the WMA, by default 0. + + Returns + ------- + OBBject[List[Data]] + The WMA data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> wma_data = obb.ta.wma(data=stock_data.results, target="close", length=50, offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + offset=offset, + chart=chart, + ) + + return self._command_runner.run( + "/ta/wma", + **inputs, + ) + + @validate_arguments(config=dict(arbitrary_types_allowed=True)) + def zlma( + self, + data: Union[List[openbb_provider.abstract.data.Data], pandas.DataFrame], + target: str = "close", + index: str = "date", + length: int = 50, + offset: int = 0, + chart: bool = False, + ) -> OBBject[List]: + """ + The zero lag exponential moving average (ZLEMA) indicator + was created by John Ehlers and Ric Way. The idea is do a + regular exponential moving average (EMA) calculation but + on a de-lagged data instead of doing it on the regular data. + Data is de-lagged by removing the data from "lag" days ago + thus removing (or attempting to) the cumulative effect of + the moving average. + + Parameters + ---------- + data : List[Data] + List of data to be used for the calculation. + target : str + Target column name. + index : str, optional + Index column name to use with `data`, by default "date". + length : int, optional + Number of periods to be used for the calculation, by default 50. + offset : int, optional + Offset to be used for the calculation, by default 0. + + Returns + ------- + OBBject[List[Data]] + The calculated data. + + Examples + -------- + >>> from openbb import obb + >>> stock_data = obb.stocks.load(symbol="TSLA", start_date="2023-01-01", provider="fmp") + >>> zlma_data = obb.ta.zlma(data=stock_data.results, target="close", length=50, offset=0) + """ # noqa: E501 + + inputs = filter_inputs( + data=data, + target=target, + index=index, + length=length, + offset=offset, + chart=chart, + ) + + return self._command_runner.run( + "/ta/zlma", + **inputs, + ) diff --git a/openbb_sdk/poetry.lock b/openbb_sdk/poetry.lock index 1b1f1ae724d..b13e9e015ce 100644 --- a/openbb_sdk/poetry.lock +++ b/openbb_sdk/poetry.lock @@ -306,7 +306,7 @@ uvloop = ["uvloop (>=0.15.2)"] name = "cattrs" version = "23.1.2" description = "Composable complex class support for attrs and dataclasses." -optional = true +optional = false python-versions = ">=3.7" files = [ {file = "cattrs-23.1.2-py3-none-any.whl", hash = "sha256:b2bb14311ac17bed0d58785e5a60f022e5431aca3932e3fc5cc8ed8639de50a4"}, @@ -727,6 +727,17 @@ zipp = {version = ">=3.1.0", markers = "python_version < \"3.10\""} docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] testing = ["pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-ruff"] +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +optional = true +python-versions = ">=3.5" +files = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] + [[package]] name = "iniconfig" version = "2.0.0" @@ -925,6 +936,17 @@ files = [ {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, ] +[[package]] +name = "more-itertools" +version = "10.1.0" +description = "More routines for operating on iterables, beyond itertools" +optional = true +python-versions = ">=3.8" +files = [ + {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"}, + {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"}, +] + [[package]] name = "multidict" version = "6.0.4" @@ -1088,6 +1110,22 @@ files = [ {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, ] +[[package]] +name = "openbb-alpha-vantage" +version = "0.1.0" +description = "" +optional = true +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +openbb-core = {path = "../../sdk/core"} + +[package.source] +type = "directory" +url = "providers/alpha_vantage" + [[package]] name = "openbb-benzinga" version = "0.1.0" @@ -1287,6 +1325,23 @@ openbb-core = {path = "../../sdk/core"} type = "directory" url = "extensions/futures" +[[package]] +name = "openbb-intrinio" +version = "0.1.0" +description = "Intrinio extension for OpenBB" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +openbb-core = {path = "../../sdk/core"} +requests-cache = "^1.1.0" + +[package.source] +type = "directory" +url = "providers/intrinio" + [[package]] name = "openbb-news" version = "0.1.0" @@ -1357,6 +1412,23 @@ statsmodels = "^0.14.0" type = "directory" url = "extensions/qa" +[[package]] +name = "openbb-quandl" +version = "0.1.0" +description = "" +optional = true +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +openbb-core = {path = "../../sdk/core"} +quandl = ">=3.7.0" + +[package.source] +type = "directory" +url = "providers/quandl" + [[package]] name = "openbb-stocks" version = "0.1.0" @@ -1922,6 +1994,26 @@ setproctitle = "*" [package.extras] dev = ["auditwheel", "wheel"] +[[package]] +name = "quandl" +version = "3.7.0" +description = "Package for quandl API access" +optional = true +python-versions = ">= 3.6" +files = [ + {file = "Quandl-3.7.0-py2.py3-none-any.whl", hash = "sha256:0e3e5dc60fd057c73c67380b1b0f2e3dc0e4c500fb5e6e146ac3a3c0d992cd1d"}, + {file = "Quandl-3.7.0.tar.gz", hash = "sha256:6e0b82fbc7861610b3577c5397277c4220e065eee0fed4e46cd6b6021655b64c"}, +] + +[package.dependencies] +inflection = ">=0.3.1" +more-itertools = "*" +numpy = ">=1.8" +pandas = ">=0.14" +python-dateutil = "*" +requests = ">=2.7.0" +six = "*" + [[package]] name = "referencing" version = "0.30.2" @@ -1981,7 +2073,7 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] name = "requests-cache" version = "1.1.0" description = "A persistent cache for python requests" -optional = true +optional = false python-versions = ">=3.7,<4.0" files = [ {file = "requests_cache-1.1.0-py3-none-any.whl", hash = "sha256:178282bce704b912c59e7f88f367c42bddd6cde6bf511b2a3e3cfb7e5332a92a"}, @@ -2535,7 +2627,7 @@ files = [ name = "url-normalize" version = "1.4.3" description = "URL normalization for Python" -optional = true +optional = false python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, @@ -2805,15 +2897,17 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] [extras] -all = ["openbb-cboe", "openbb-charting", "openbb-futures", "openbb-qa", "openbb-ta", "openbb-yfinance"] +all = ["openbb-alpha-vantage", "openbb-cboe", "openbb-charting", "openbb-futures", "openbb-qa", "openbb-quandl", "openbb-ta", "openbb-yfinance"] +alpha-vantage = ["openbb-alpha-vantage"] cboe = ["openbb-cboe"] charting = ["openbb-charting"] futures = ["openbb-futures"] qa = ["openbb-qa"] +quandl = ["openbb-quandl"] ta = ["openbb-ta"] yfinance = ["openbb-yfinance"] [metadata] lock-version = "2.0" python-versions = ">=3.8,<3.12" -content-hash = "e3a2f27c7308848ee2bc8fc6130ec2a7bc144803c53c9bca3b25565aeefb7580" +content-hash = "c5c289543644ffbafe04fec1a8c0b9ff14c2023f8f9102821882db7cce9cdf46" diff --git a/openbb_sdk/providers/alpha_vantage/README.md b/openbb_sdk/providers/alpha_vantage/README.md new file mode 100644 index 00000000000..6a6d3f6eda4 --- /dev/null +++ b/openbb_sdk/providers/alpha_vantage/README.md @@ -0,0 +1,11 @@ +# OpenBB Alpha Vantage Provider + +This extension integrates the Alpha Vantage data provider into the OpenBB SDK. + +## Installation + +To install the extension, run the following command in this folder: + +```bash +pip install . +``` diff --git a/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/__init__.py b/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/__init__.py new file mode 100644 index 00000000000..1fd690f1e32 --- /dev/null +++ b/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/__init__.py @@ -0,0 +1,20 @@ +"""Alpha Vantage Provider module.""" +from openbb_provider.abstract.provider import Provider + +from openbb_alpha_vantage.models.stock_historical import AVStockHistoricalFetcher + +alpha_vantage_provider = Provider( + name="alpha_vantage", + website="https://www.alphavantage.co/documentation/", + description="""Alpha Vantage provides realtime and historical + financial market data through a set of powerful and developer-friendly data APIs + and spreadsheets. From traditional asset classes (e.g., stocks, ETFs, mutual funds) + to economic indicators, from foreign exchange rates to commodities, + from fundamental data to technical indicators, Alpha Vantage + is your one-stop-shop for enterprise-grade global market data delivered through + cloud-based APIs, Excel, and Google Sheets. """, + required_credentials=["api_key"], + fetcher_dict={ + "StockHistorical": AVStockHistoricalFetcher, + }, +) diff --git a/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/models/__init__.py b/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/models/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/models/stock_historical.py b/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/models/stock_historical.py new file mode 100644 index 00000000000..fbbb402e14e --- /dev/null +++ b/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/models/stock_historical.py @@ -0,0 +1,247 @@ +"""Alpha Vantage Stock End of Day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional, get_args + +import pandas as pd +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_historical import ( + StockHistoricalData, + StockHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, NonNegativeFloat, PositiveFloat, root_validator, validator + + +class AVStockHistoricalQueryParams(StockHistoricalQueryParams): + """Alpha Vantage Stock End of Day Query. + + Source: https://www.alphavantage.co/documentation/ + """ + + _function: Literal[ + "TIME_SERIES_INTRADAY", + "TIME_SERIES_DAILY", + "TIME_SERIES_WEEKLY", + "TIME_SERIES_MONTHLY", + "TIME_SERIES_DAILY_ADJUSTED", + "TIME_SERIES_WEEKLY_ADJUSTED", + "TIME_SERIES_MONTHLY_ADJUSTED", + ] = Field( + description="The time series of your choice. ", + default="TIME_SERIES_DAILY", + ) + period: Literal["intraday", "daily", "weekly", "monthly"] = Field( + default="daily", description=QUERY_DESCRIPTIONS.get("period", "") + ) + interval: Optional[Literal["1min", "5min", "15min", "30min", "60min"]] = Field( + description="The interval between two consecutive data points in the time series.", + default="60min", + available_on_functions=["TIME_SERIES_INTRADAY"], + required_on_functions=["TIME_SERIES_INTRADAY"], + ) + adjusted: Optional[bool] = Field( + description="Output time series is adjusted by historical split and dividend events.", + default=True, + available_on_functions=["TIME_SERIES_INTRADAY"], + ) + extended_hours: Optional[bool] = Field( + description="Extended trading hours during pre-market and after-hours.", + default=False, + available_on_functions=["TIME_SERIES_INTRADAY"], + ) + month: Optional[str] = Field( + description="Query a specific month in history (in YYYY-MM format).", + default=None, + available_on_functions=["TIME_SERIES_INTRADAY"], + ) + outputsize: Optional[Literal["compact", "full"]] = Field( + description="Compact returns only the latest 100 data points in the intraday " + "time series; full returns trailing 30 days of the most recent intraday data " + "if the month parameter (see above) is not specified, or the full intraday " + "data for a specific month in history if the month parameter is specified.", + default="full", + available_on_functions=[ + "TIME_SERIES_INTRADAY", + "TIME_SERIES_DAILY", + "TIME_SERIES_DAILY_ADJUSTED", + ], + ) + + @root_validator + def setup_function(cls, values): # pylint: disable=E0213 + """Set the function based on the period.""" + + functions_based_on_period = { + "intraday": "TIME_SERIES_INTRADAY", + "daily": "TIME_SERIES_DAILY", + "weekly": "TIME_SERIES_WEEKLY", + "monthly": "TIME_SERIES_MONTHLY", + } + values["_function"] = functions_based_on_period[values["period"]] + return values + + @root_validator + def adjusted_function_validate(cls, values): # pylint: disable=E0213 + """ + Validate that the function is adjusted if the `adjusted` parameter is set to True. + """ + + function = values["_function"] + adjusted = values.get("adjusted", None) + + if function != "TIME_SERIES_INTRADAY": + values["_function"] = function if not adjusted else f"{function}_ADJUSTED" + + return values + + @root_validator + def on_functions_validate(cls, values): # pylint: disable=E0213 + """ + Validate that the functions used on custom extra Field attributes + `available_on_functions` and `required_on_functions` are valid functions. + """ + custom_attributes = ["available_on_functions", "required_on_functions"] + + fields = cls.__fields__ + available_functions = get_args(cls.__annotations__["_function"]) + + if values["_function"] not in available_functions: + raise ValueError( + f"Function {values['_function']} must be on of the following: {available_functions}" + ) + + def validate_functions(functions: List[str]): + for f in functions: + if f not in available_functions: + raise ValueError( + f"Function {f} must be on of the following: {available_functions}" + ) + + for field in fields: + for attr in custom_attributes: + if functions := fields[field].field_info.extra.get(attr, None): + validate_functions(functions) + + return values + + @root_validator + def on_functions_criteria_validate(cls, values): # pylint: disable=E0213 + """ + Validate that the fields are set to None if the function is not available + and that the required fields are not None if the function is required. + """ + + fields = cls.__fields__ + function = values["_function"] + + for field in fields: + if ( + available_on_functions := fields[field].field_info.extra.get( + "available_on_functions", None + ) + ) and function not in available_on_functions: + values[field] = None + if ( + ( + required_on_functions := fields[field].field_info.extra.get( + "required_on_functions", None + ) + ) + and function in required_on_functions + and values[field] is None + ): + raise ValueError(f"Field {field} is required on function {function}") + + return values + + @validator("month") + def month_validate(cls, v): # pylint: disable=E0213 + """Validate month, check if the month is in YYYY-MM format.""" + if v is not None: + try: + datetime.strptime(v, "%Y-%m") + except ValueError as e: + raise e + return v + + +class AVStockHistoricalData(StockHistoricalData): + """Alpha Vantage Stock End of Day Data.""" + + class Config: + """Pydantic alias config using fields dict.""" + + fields = {"date": "timestamp", "adj_close": "adjusted_close"} + + adjusted_close: PositiveFloat = Field( + description=DATA_DESCRIPTIONS.get("adj_close", "") + ) + dividend_amount: NonNegativeFloat = Field( + description="Dividend amount paid for the corresponding date.", + ) + split_coefficient: NonNegativeFloat = Field( + description="Split coefficient for the corresponding date.", + ) + + +class AVStockHistoricalFetcher( + Fetcher[ + AVStockHistoricalQueryParams, + List[AVStockHistoricalData], + ] +): + """Transform the query, extract and transform the data from the Alpha Vantage endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> AVStockHistoricalQueryParams: + """Transform the query.""" + + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + + return AVStockHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: AVStockHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the Alpha Vantage endpoint.""" + + api_key = credentials.get("alpha_vantage_api_key") if credentials else "" + + query_dict = query.dict() + query_dict["function"] = query_dict.pop("_function") + + query_str = get_querystring(query_dict, ["start_date", "end_date"]) + + url = f"https://www.alphavantage.co/query?{query_str}&datatype=csv&apikey={api_key}" + + data = pd.read_csv(url) + data["timestamp"] = pd.to_datetime(data["timestamp"]) + + data = data[ + (data["timestamp"] >= pd.to_datetime(query.start_date)) + & (data["timestamp"] <= pd.to_datetime(query.end_date)) + ] + + return data.to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[AVStockHistoricalData]: + """Transform the data to the standard format.""" + + return [AVStockHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/utils/__init__.py b/openbb_sdk/providers/alpha_vantage/openbb_alpha_vantage/utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/alpha_vantage/poetry.lock b/openbb_sdk/providers/alpha_vantage/poetry.lock new file mode 100644 index 00000000000..4ceb7c5e95f --- /dev/null +++ b/openbb_sdk/providers/alpha_vantage/poetry.lock @@ -0,0 +1,1057 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.0.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, + {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.22)"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bcrypt" +version = "4.0.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.6" +files = [ + {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e"}, + {file = "bcrypt-4.0.1-cp36-abi3-win32.whl", hash = "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab"}, + {file = "bcrypt-4.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71"}, + {file = "bcrypt-4.0.1.tar.gz", hash = "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + +[[package]] +name = "black" +version = "23.7.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.2.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "ecdsa" +version = "0.18.0" +description = "ECDSA cryptographic signature library (pure python)" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"}, + {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"}, +] + +[package.dependencies] +six = ">=1.9.0" + +[package.extras] +gmpy = ["gmpy"] +gmpy2 = ["gmpy2"] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fastapi" +version = "0.100.1" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.7" +files = [ + {file = "fastapi-0.100.1-py3-none-any.whl", hash = "sha256:ec6dd52bfc4eff3063cfcd0713b43c87640fefb2687bbbe3d8a08d94049cdf32"}, + {file = "fastapi-0.100.1.tar.gz", hash = "sha256:522700d7a469e4a973d92321ab93312448fbe20fca9c8da97effc7e7bc56df23"}, +] + +[package.dependencies] +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0" +starlette = ">=0.27.0,<0.28.0" +typing-extensions = ">=4.5.0" + +[package.extras] +all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "html5lib" +version = "1.1" +description = "HTML parser based on the WHATWG HTML specification" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] + +[package.dependencies] +six = ">=1.9" +webencodings = "*" + +[package.extras] +all = ["chardet (>=2.2)", "genshi", "lxml"] +chardet = ["chardet (>=2.2)"] +genshi = ["genshi"] +lxml = ["lxml"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "monotonic" +version = "1.6" +description = "An implementation of time.monotonic() for Python 2 & < 3.3" +optional = false +python-versions = "*" +files = [ + {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, + {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + +[[package]] +name = "numpy" +version = "1.25.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, +] + +[[package]] +name = "openbb-core" +version = "0.1.0" +description = "OpenBB package with core functionality" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +bcrypt = "^4.0.1" +black = "^23.7.0" +fastapi = "^0.100.1" +html5lib = "^1.1" +openbb-provider = {path = "../provider"} +pandas = ">=1.5.3" +passlib = "^1.7.4" +posthog = "^3.0.1" +python-jose = "^3.3.0" +python-multipart = "^0.0.6" +ruff = "0.0.256" +uuid7 = "^0.1.0" +uvicorn = "^0.20.0" +websockets = "^10.4" + +[package.source] +type = "directory" +url = "../../sdk/core" + +[[package]] +name = "openbb-provider" +version = "0.1.0" +description = "OpenBB package to execute queries to financial data providers" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +importlib-metadata = "^6.8.0" +pydantic = {version = "^1.10", extras = ["dotenv"]} +requests = "^2.31.0" +urllib3 = "<2.0.0" + +[package.source] +type = "directory" +url = "../../sdk/provider" + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pandas" +version = "2.0.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.1" + +[package.extras] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +aws = ["s3fs (>=2021.08.0)"] +clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] +compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] +computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2021.07.0)"] +gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] +hdf5 = ["tables (>=3.6.1)"] +html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] +mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] +spss = ["pyreadstat (>=1.1.2)"] +sql-other = ["SQLAlchemy (>=1.4.16)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.6.3)"] + +[[package]] +name = "passlib" +version = "1.7.4" +description = "comprehensive password hashing framework supporting over 30 schemes" +optional = false +python-versions = "*" +files = [ + {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, + {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, +] + +[package.extras] +argon2 = ["argon2-cffi (>=18.2.0)"] +bcrypt = ["bcrypt (>=3.1.0)"] +build-docs = ["cloud-sptheme (>=1.10.1)", "sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)"] +totp = ["cryptography"] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "posthog" +version = "3.0.2" +description = "Integrate PostHog into any python application." +optional = false +python-versions = "*" +files = [ + {file = "posthog-3.0.2-py2.py3-none-any.whl", hash = "sha256:a8c0af6f2401fbe50f90e68c4143d0824b54e872de036b1c2f23b5abb39d88ce"}, + {file = "posthog-3.0.2.tar.gz", hash = "sha256:701fba6e446a4de687c6e861b587e7b7741955ad624bf34fe013c06a0fec6fb3"}, +] + +[package.dependencies] +backoff = ">=1.10.0" +monotonic = ">=1.5" +python-dateutil = ">2.1" +requests = ">=2.7,<3.0" +six = ">=1.5" + +[package.extras] +dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"] +sentry = ["django", "sentry-sdk"] +test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest"] + +[[package]] +name = "pyasn1" +version = "0.5.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, + {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"}, +] + +[[package]] +name = "pydantic" +version = "1.10.12" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, + {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, + {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, + {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, + {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, + {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, + {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, + {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, + {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, +] + +[package.dependencies] +python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""} +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "1.0.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-jose" +version = "3.3.0" +description = "JOSE implementation in Python" +optional = false +python-versions = "*" +files = [ + {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, + {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, +] + +[package.dependencies] +ecdsa = "!=0.15" +pyasn1 = "*" +rsa = "*" + +[package.extras] +cryptography = ["cryptography (>=3.4.0)"] +pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"] +pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] + +[[package]] +name = "python-multipart" +version = "0.0.6" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, + {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, +] + +[package.extras] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] + +[[package]] +name = "pytz" +version = "2023.3" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, + {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "ruff" +version = "0.0.256" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.256-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:eb8e949f6e7fb16f9aa163fcc13318e2b7910577513468417e5b003b984410a1"}, + {file = "ruff-0.0.256-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:48a42f0ec4c5a3c3b062e947b2a5f8f7a4264761653fb0ee656a9b535ae6d8d7"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ca633cfc335869643a13e2006f13a63bc4cb94073aa9508ceb08a1e3afe3af"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:80fa5d3a40dd0b65c6d6adea4f825984d5d3a215a25d90cc6139978cb22ea1cd"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0f88839b886db3577136375865bd080b9ed6f9b85bb990d897780e5a30ca3c2"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe6d77a43b2d52f45ee42f6f682198ed1c34cd0165812e276648981dfd50ad36"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3878593507b281b2615702ece06426e8b27076e8fedf658bf0c5e1e5e2ad1b40"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e052ec4d5c92663caa662b68fe1902ec10eddac2783229b1c5f20f3df62a865"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2116bd67e52ade9f90e5a3a3aa511a9b179c699690221bdd5bb267dbf7e94b22"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3c6e93d7818a75669328e49a0f7070c40e18676ca8e56ca9c566633bef4d8d05"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ebb7de4e62d751b65bb15418a83ac5d555afb3eaa3ad549dea21744da34ae86"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f310bfc76c0404a487759c8904f57bf51653c46e686c800efc1ff1d165a59a04"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:93a0cfec812b2ba57bff22b176901e0ddf44e4d42a9bd7da7ffb5e53df13fd6e"}, + {file = "ruff-0.0.256-py3-none-win32.whl", hash = "sha256:d63e5320bc2d91e94925cd1863e381a48edf087041035967faf2614bb36a6a0d"}, + {file = "ruff-0.0.256-py3-none-win_amd64.whl", hash = "sha256:859c8ffb1801895fe043a2b85a45cd0ff35667ddea4b465ba2a29d275550814a"}, + {file = "ruff-0.0.256-py3-none-win_arm64.whl", hash = "sha256:64b276149e86c3d234608d3fe1da77535865e03debd3a1d5d04576f7f5031bbb"}, + {file = "ruff-0.0.256.tar.gz", hash = "sha256:f9a96b34a4870ee8cf2f3779cd7854620d1788a83b52374771266cf800541bb7"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "starlette" +version = "0.27.0" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.7" +files = [ + {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, + {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "urllib3" +version = "1.26.16" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, + {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "uuid7" +version = "0.1.0" +description = "UUID version 7, generating time-sorted UUIDs with 200ns time resolution and 48 bits of randomness" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uuid7-0.1.0-py2.py3-none-any.whl", hash = "sha256:5e259bb63c8cb4aded5927ff41b444a80d0c7124e8a0ced7cf44efa1f5cccf61"}, + {file = "uuid7-0.1.0.tar.gz", hash = "sha256:8c57aa32ee7456d3cc68c95c4530bc571646defac01895cfc73545449894a63c"}, +] + +[[package]] +name = "uvicorn" +version = "0.20.0" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.7" +files = [ + {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"}, + {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "websockets" +version = "10.4" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, + {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, + {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, + {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, + {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, + {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, + {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, + {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, + {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, + {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, + {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, + {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, + {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, + {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, + {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, + {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, + {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, + {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, + {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, + {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, + {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, + {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, + {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, + {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, +] + +[[package]] +name = "zipp" +version = "3.16.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "ed5c1001c4f47bae1cfde8d8509294643e3b3ea101a8482c3f0248085360bb18" diff --git a/openbb_sdk/providers/alpha_vantage/pyproject.toml b/openbb_sdk/providers/alpha_vantage/pyproject.toml new file mode 100644 index 00000000000..64ca1cdc6f0 --- /dev/null +++ b/openbb_sdk/providers/alpha_vantage/pyproject.toml @@ -0,0 +1,18 @@ +[tool.poetry] +name = "openbb-alpha-vantage" +version = "0.1.0" +description = "" +authors = ["OpenBB Team "] +readme = "README.md" +packages = [{ include = "openbb_alpha_vantage" }] + +[tool.poetry.dependencies] +python = "^3.8" +openbb-core = { path = "../../sdk/core" } + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.plugins."openbb_provider_extension"] +alpha_vantage = "openbb_alpha_vantage:alpha_vantage_provider" diff --git a/openbb_sdk/providers/alpha_vantage/tests/.gitkeep b/openbb_sdk/providers/alpha_vantage/tests/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/cboe/openbb_cboe/__init__.py b/openbb_sdk/providers/cboe/openbb_cboe/__init__.py index ad624d02a84..7f6c94eb990 100644 --- a/openbb_sdk/providers/cboe/openbb_cboe/__init__.py +++ b/openbb_sdk/providers/cboe/openbb_cboe/__init__.py @@ -3,8 +3,21 @@ from openbb_provider.abstract.provider import Provider +from openbb_cboe.models.available_indices import CboeAvailableIndicesFetcher +from openbb_cboe.models.european_index_constituents import ( + CboeEuropeanIndexConstituentsFetcher, +) +from openbb_cboe.models.european_index_historical import ( + CboeEuropeanIndexHistoricalFetcher, +) +from openbb_cboe.models.futures_curve import CboeFuturesCurveFetcher +from openbb_cboe.models.index_search import CboeIndexSearchFetcher +from openbb_cboe.models.index_snapshots import CboeIndexSnapshotsFetcher +from openbb_cboe.models.major_indices_historical import ( + CboeMajorIndicesHistoricalFetcher, +) from openbb_cboe.models.options_chains import CboeOptionsChainsFetcher -from openbb_cboe.models.stock_eod import CboeStockEODFetcher +from openbb_cboe.models.stock_historical import CboeStockHistoricalFetcher from openbb_cboe.models.stock_info import CboeStockInfoFetcher from openbb_cboe.models.stock_search import CboeStockSearchFetcher @@ -18,7 +31,14 @@ cboe_provider = Provider( fetcher_dict={ "StockSearch": CboeStockSearchFetcher, "OptionsChains": CboeOptionsChainsFetcher, - "StockEOD": CboeStockEODFetcher, + "StockHistorical": CboeStockHistoricalFetcher, "StockInfo": CboeStockInfoFetcher, + "FuturesCurve": CboeFuturesCurveFetcher, + "AvailableIndices": CboeAvailableIndicesFetcher, + "EuropeanIndexConstituents": CboeEuropeanIndexConstituentsFetcher, + "EuropeanIndexHistorical": CboeEuropeanIndexHistoricalFetcher, + "MajorIndicesHistorical": CboeMajorIndicesHistoricalFetcher, + "IndexSearch": CboeIndexSearchFetcher, + "IndexSnapshots": CboeIndexSnapshotsFetcher, }, ) diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/available_indices.py b/openbb_sdk/providers/cboe/openbb_cboe/models/available_indices.py new file mode 100644 index 00000000000..b401279577d --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/available_indices.py @@ -0,0 +1,106 @@ +"""Available Indices fetcher for CBOE""" + +from datetime import time +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.available_indices import ( + AvailableIndicesData, + AvailableIndicesQueryParams, +) +from pydantic import Field + +from openbb_cboe.utils.helpers import Europe, get_cboe_index_directory + + +class CboeAvailableIndicesQueryParams(AvailableIndicesQueryParams): + """CBOE Available Indices query. + + Source: https://www.cboe.com/europe/indices/ + """ + + europe: bool = Field( + description="Filter for European indices. False for US indices.", default=False + ) + + +class CboeAvailableIndicesData(AvailableIndicesData): + """CBOE Available Indices data. + + Source: https://www.cboe.com/europe/indices/ + """ + + isin: Optional[str] = Field( + description="ISIN code for the index. Valid only for European indices." + ) + + region: Optional[str] = Field( + description="Region for the index. Valid only for European indices" + ) + + symbol: Optional[str] = Field(description="Symbol for the index.") + + description: Optional[str] = Field( + description="Description for the index. Valid only for US indices." + ) + + data_delay: Optional[int] = Field( + description="Data delay for the index. Valid only for US indices." + ) + + open_time: Optional[time] = Field( + description="Opening time for the index. Valid only for US indices." + ) + + close_time: Optional[time] = Field( + description="Closing time for the index. Valid only for US indices." + ) + + time_zone: Optional[str] = Field( + description="Time zone for the index. Valid only for US indices." + ) + + tick_days: Optional[str] = Field( + description="The trading days for the index. Valid only for US indices." + ) + + tick_frequency: Optional[str] = Field( + description="The frequency of the index ticks. Valid only for US indices." + ) + + tick_period: Optional[str] = Field( + description="The period of the index ticks. Valid only for US indices." + ) + + +class CboeAvailableIndicesFetcher( + Fetcher[ + CboeAvailableIndicesQueryParams, + CboeAvailableIndicesData, + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> CboeAvailableIndicesQueryParams: + """Transform the query params.""" + + return CboeAvailableIndicesQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeAvailableIndicesQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + if query.europe is True: + return Europe.list_indices() + return get_cboe_index_directory().sort_index().reset_index().to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[CboeAvailableIndicesData]: + """Transform the data to the standard format""" + + return [CboeAvailableIndicesData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/european_index_constituents.py b/openbb_sdk/providers/cboe/openbb_cboe/models/european_index_constituents.py new file mode 100644 index 00000000000..67c876c4c0b --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/european_index_constituents.py @@ -0,0 +1,113 @@ +"""CBOE European Index Constituents fetcher.""" + +from datetime import datetime +from typing import Any, Dict, List, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.european_index_constituents import ( + EuropeanIndexConstituentsData, + EuropeanIndexConstituentsQueryParams, +) +from openbb_provider.utils.helpers import make_request +from pydantic import Field, validator + +from openbb_cboe.utils.helpers import EUR_INDEX_CONSTITUENTS_COLUMNS, Europe + + +class CboeEuropeanIndexConstituentsQueryParams(EuropeanIndexConstituentsQueryParams): + """CBOE Stock end of day query. + + Source: https://www.cboe.com/ + + Gets the current price data for all constituents of the CBOE European Index. + """ + + +class CboeEuropeanIndexConstituentsData(EuropeanIndexConstituentsData): + """CBOE European Index Constituents Data. + + Current trading day price data for all constituents of the CBOE European Index. + """ + + prev_close: Optional[float] = Field(description="Previous closing price.") + change: Optional[float] = Field(description="Change in price.") + change_percent: Optional[float] = Field( + description="Change in price as a percentage." + ) + tick: Optional[str] = Field( + description="Whether the last sale was an up or down tick." + ) + last_trade_timestamp: Optional[datetime] = Field( + description="Last trade timestamp for the symbol." + ) + exchange_id: Optional[int] = Field(description="The Exchange ID number.") + seqno: Optional[int] = Field( + description="Sequence number of the last trade on the tape." + ) + asset_type: Optional[str] = Field(description="Type of asset.", alias="type") + + @validator("last_trade_timestamp", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the datetime object from the date string""" + + return datetime.strftime(v, "%Y-%m-%d %H:%M:%S") + + +class CboeEuropeanIndexConstituentsFetcher( + Fetcher[ + CboeEuropeanIndexConstituentsQueryParams, + List[CboeEuropeanIndexConstituentsData], + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query( + params: Dict[str, Any] + ) -> CboeEuropeanIndexConstituentsQueryParams: + """Transform the query.""" + + return CboeEuropeanIndexConstituentsQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeEuropeanIndexConstituentsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + SYMBOLS = pd.DataFrame(Europe.list_indices())["symbol"].to_list() + query.symbol = query.symbol.upper() + + if query.symbol not in SYMBOLS: + raise RuntimeError( + f"The symbol, {query.symbol}," + "was not found in the CBOE European Index directory. " + "Use `available_indices(europe=True)` to see the full list of indices." + ) + url = f"https://cdn.cboe.com/api/global/european_indices/constituent_quotes/{query.symbol}.json" + + r = make_request(url) + if r.status_code != 200: + raise RuntimeError(r.status_code) + + r_json = r.json() + + data = ( + pd.DataFrame.from_records(r_json["data"])[ + list(EUR_INDEX_CONSTITUENTS_COLUMNS.keys()) + ] + .rename(columns=EUR_INDEX_CONSTITUENTS_COLUMNS) + .round(2) + ) + data["last_trade_timestamp"] = pd.to_datetime(data["last_trade_timestamp"]) + + return data.to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[CboeEuropeanIndexConstituentsData]: + """Transform the data to the standard format""" + + return [CboeEuropeanIndexConstituentsData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/european_index_historical.py b/openbb_sdk/providers/cboe/openbb_cboe/models/european_index_historical.py new file mode 100644 index 00000000000..e289f000561 --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/european_index_historical.py @@ -0,0 +1,134 @@ +"""European Indices End of Day fetcher for CBOE.""" + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.european_index_historical import ( + EuropeanIndexHistoricalData, + EuropeanIndexHistoricalQueryParams, +) +from openbb_provider.utils.helpers import make_request +from pydantic import Field, validator + +from openbb_cboe.utils.helpers import Europe + + +class CboeEuropeanIndexHistoricalQueryParams(EuropeanIndexHistoricalQueryParams): + """CBOE European Indices End of Day query. + + Source: https://www.cboe.com/europe/indices/ + """ + + interval: Optional[Literal["1d", "1m"]] = Field( + description="Use interval, 1m, for intraday prices during the most recent trading period.", + default="1d", + ) + + +class CboeEuropeanIndexHistoricalData(EuropeanIndexHistoricalData): + """CBOE Stocks End of Day Data.""" + + open: Optional[float] = Field( + description="Opening price for the interval. Only valid when interval is 1m." + ) + high: Optional[float] = Field( + description="High price for the interval. Only valid when interval is 1m." + ) + low: Optional[float] = Field( + description="Low price for the interval. Only valid when interval is 1m." + ) + utc_datetime: Optional[datetime] = Field( + description="UTC datetime. Only valid when interval is 1m." + ) + + @validator("close", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the datetime object from the date string""" + return float(v) + + +class CboeEuropeanIndexHistoricalFetcher( + Fetcher[ + CboeEuropeanIndexHistoricalQueryParams, + List[CboeEuropeanIndexHistoricalData], + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query( + params: Dict[str, Any] + ) -> CboeEuropeanIndexHistoricalQueryParams: + """Transform the query.""" + + return CboeEuropeanIndexHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeEuropeanIndexHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + data = pd.DataFrame() + query.symbol = query.symbol.upper() + SYMBOLS = pd.DataFrame(Europe.list_indices())["symbol"].to_list() + + if query.symbol not in SYMBOLS: + raise RuntimeError( + f"The symbol, {query.symbol}," + "was not found in the CBOE European Index directory. " + "Use `available_indices(europe=True)` to see the full list of indices." + ) + if query.interval == "1d": + url = f"https://cdn.cboe.com/api/global/european_indices/index_history/{query.symbol}.json" + + r = make_request(url) + if r.status_code != 200: + raise RuntimeError(r.status_code) + + r_json = r.json() + + data = pd.DataFrame.from_records(r_json["data"]).set_index("date") + + data.index = pd.to_datetime(data.index, format="%Y-%m-%d") + + if query.start_date is not None: + query.end_date = ( + query.end_date if query.end_date else datetime.now().date() + ) + + data = data[ + (data.index >= pd.to_datetime(query.start_date, format="%Y-%m-%d")) + & (data.index <= pd.to_datetime(query.end_date, format="%Y-%m-%d")) + ] + data.index = data.index.astype(str) + data = data.reset_index() + + if query.interval == "1m": + url = f"https://cdn.cboe.com/api/global/european_indices/intraday_chart_data/{query.symbol}.json" + + r = make_request(url) + if r.status_code != 200: + raise RuntimeError(r.status_code) + + r_json = r.json()["data"] + + data = pd.DataFrame.from_records(pd.DataFrame(r_json)["price"]) + data["date"] = pd.DataFrame(r_json)["datetime"] + data["utc_datetime"] = pd.to_datetime(pd.DataFrame(r_json)["utc_datetime"]) + + data = data[["utc_datetime", "date", "open", "high", "low", "close"]].round( + 2 + ) + + return data.to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[CboeEuropeanIndexHistoricalData]: + """Transform the data to the standard format""" + + return [CboeEuropeanIndexHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/futures_curve.py b/openbb_sdk/providers/cboe/openbb_cboe/models/futures_curve.py new file mode 100644 index 00000000000..dcbecf4e67d --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/futures_curve.py @@ -0,0 +1,70 @@ +"""CBOE Futures Curve Fetcher.""" + +# IMPORT STANDARD +from typing import Any, Dict, List, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.futures_curve import ( + FuturesCurveData, + FuturesCurveQueryParams, +) +from pydantic import Field + +from openbb_cboe.utils.helpers import get_settlement_prices + + +class CboeFuturesCurveQueryParams(FuturesCurveQueryParams): + """CBOE Futures Curve Query. + + Source: https://www.cboe.com/ + """ + + +class CboeFuturesCurveData(FuturesCurveData): + """CBOE Futures Curve Data.""" + + symbol: str = Field(description="The trading symbol for the tenor of future.") + + +class CboeFuturesCurveFetcher( + Fetcher[ + CboeFuturesCurveQueryParams, + List[CboeFuturesCurveData], + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> CboeFuturesCurveQueryParams: + return CboeFuturesCurveQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeFuturesCurveQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the CBOE endpoint.""" + + query.symbol = query.symbol.upper() + FUTURES = get_settlement_prices(settlement_date=query.date) + if len(FUTURES) == 0: + return pd.DataFrame() + + if query.symbol not in FUTURES["product"].unique().tolist(): + raise RuntimeError( + "The symbol, " + f"{query.symbol}" + ", is not valid. Chose from: " + f"{FUTURES['product'].unique().tolist()}" + ) + + data = get_settlement_prices(settlement_date=query.date) + data = data[data["product"] == query.symbol] + + return data[["expiration", "symbol", "price"]].to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[CboeFuturesCurveData]: + return [CboeFuturesCurveData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/index_search.py b/openbb_sdk/providers/cboe/openbb_cboe/models/index_search.py new file mode 100644 index 00000000000..bf3545b7720 --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/index_search.py @@ -0,0 +1,99 @@ +"""CBOE Index Search fetcher.""" + +from datetime import time +from typing import Any, Dict, List, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.index_search import ( + IndexSearchData, + IndexSearchQueryParams, +) +from pydantic import Field + +from openbb_cboe.utils.helpers import Europe, get_cboe_index_directory + + +class CboeIndexSearchQueryParams(IndexSearchQueryParams): + """CBOE Index Search query. Search the CBOE company directory by name or ticker. + + Source: https://www.cboe.com/ + """ + + europe: bool = Field( + description="Filter for European indices. False for US indices.", default=False + ) + + +class CboeIndexSearchData(IndexSearchData): + """CBOE Company Search Data.""" + + isin: Optional[str] = Field( + description="ISIN code for the index. Valid only for European indices." + ) + region: Optional[str] = Field( + description="Region for the index. Valid only for European indices" + ) + description: Optional[str] = Field(description="Description for the index.") + data_delay: Optional[int] = Field( + description="Data delay for the index. Valid only for US indices." + ) + currency: Optional[str] = Field(description="Currency for the index.") + time_zone: Optional[str] = Field( + description="Time zone for the index. Valid only for US indices." + ) + open_time: Optional[time] = Field( + description="Opening time for the index. Valid only for US indices." + ) + close_time: Optional[time] = Field( + description="Closing time for the index. Valid only for US indices." + ) + tick_days: Optional[str] = Field( + description="The trading days for the index. Valid only for US indices." + ) + tick_frequency: Optional[str] = Field( + description="Tick frequency for the index. Valid only for US indices." + ) + tick_period: Optional[str] = Field( + description="Tick period for the index. Valid only for US indices." + ) + + +class CboeIndexSearchFetcher( + Fetcher[ + CboeIndexSearchQueryParams, + List[CboeIndexSearchData], + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> CboeIndexSearchQueryParams: + """Transform the query""" + + return CboeIndexSearchQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeIndexSearchQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + symbols = pd.DataFrame() + if query.europe is True: + symbols = pd.DataFrame(Europe.list_indices()) + if query.europe is False: + symbols = get_cboe_index_directory().reset_index() + + target = "name" if not query.symbol else "symbol" + idx = symbols[target].str.contains(query.query, case=False) + result = symbols[idx] + + return result.to_dict("records") + + @staticmethod + def transform_data(data: dict) -> List[CboeIndexSearchData]: + """Transform the data to the standard format""" + return [CboeIndexSearchData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/index_snapshots.py b/openbb_sdk/providers/cboe/openbb_cboe/models/index_snapshots.py new file mode 100644 index 00000000000..defd3f13f55 --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/index_snapshots.py @@ -0,0 +1,136 @@ +"""CBOE Index Snapshots fetcher.""" + +from datetime import datetime +from typing import Any, Dict, List, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.index_snapshots import ( + IndexSnapshotsData, + IndexSnapshotsQueryParams, +) +from openbb_provider.utils.helpers import make_request +from pydantic import Field + +from openbb_cboe.utils.helpers import ( + EUR_INDEX_COLUMNS, + US_INDEX_COLUMNS, + Europe, + get_cboe_directory, + get_cboe_index_directory, +) + + +class CboeIndexSnapshotsQueryParams(IndexSnapshotsQueryParams): + """CBOE Index Snapshots query. Returns quotes for all indices by region. + + Source: https://www.cboe.com/ + """ + + +class CboeIndexSnapshotsData(IndexSnapshotsData): + """CBOE Company Search Data.""" + + isin: Optional[str] = Field( + description="ISIN code for the index. Valid only for European indices." + ) + last_trade_timestamp: Optional[datetime] = Field( + description="Last trade timestamp for the index." + ) + + +class CboeIndexSnapshotsFetcher( + Fetcher[ + CboeIndexSnapshotsQueryParams, + List[CboeIndexSnapshotsData], + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> CboeIndexSnapshotsQueryParams: + """Transform the query""" + + return CboeIndexSnapshotsQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeIndexSnapshotsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + data = pd.DataFrame() + + if query.region == "US": + r = make_request( + "https://cdn.cboe.com/api/global/delayed_quotes/quotes/all_us_indices.json" + ) + + if r.status_code != 200: + raise RuntimeError(r.status_code) + + INDEXES = pd.concat( + [get_cboe_index_directory(), get_cboe_directory()], axis=0 + ) + data = pd.DataFrame.from_records(r.json()["data"]) + + data.rename(columns=US_INDEX_COLUMNS, inplace=True) + data["symbol"] = data["symbol"].str.replace("^", "") + data["name"] = "" + data = data.set_index("symbol") + for i in data.index: + if i in INDEXES.index: + data.at[i, "name"] = INDEXES.at[i, "name"] + + data["name"] = data["name"].astype(str) + data["currency"] = "USD" + data = data[ + [ + "name", + "price", + "prev_close", + "change", + "change_percent", + "open", + "high", + "low", + "close", + "currency", + "last_trade_timestamp", + ] + ] + + if query.region == "EU": + r = make_request( + "https://cdn.cboe.com/api/global/european_indices/index_quotes/all-indices.json" + ) + + if r.status_code != 200: + raise RuntimeError(r.status_code) + + data = ( + pd.DataFrame.from_records(r.json()["data"]) + .drop(columns=["symbol"]) + .rename(columns={"index": "symbol"}) + .set_index("symbol") + .round(2) + ) + + INDEXES = pd.DataFrame(Europe.list_indices()).set_index("symbol") + + for i in data.index: + data.loc[i, ("isin")] = INDEXES.at[i, "isin"] + data.loc[i, ("name")] = INDEXES.at[i, "name"] + data.loc[i, ("currency")] = INDEXES.at[i, "currency"] + + data = data[list(EUR_INDEX_COLUMNS.keys())] + data.columns = list(EUR_INDEX_COLUMNS.values()) + + return data.reset_index().to_dict("records") + + @staticmethod + def transform_data(data: dict) -> List[CboeIndexSnapshotsData]: + """Transform the data to the standard format""" + return [CboeIndexSnapshotsData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/major_indices_historical.py b/openbb_sdk/providers/cboe/openbb_cboe/models/major_indices_historical.py new file mode 100644 index 00000000000..f7a0f9060a8 --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/major_indices_historical.py @@ -0,0 +1,212 @@ +"""CBOE Major Indices End of Day fetcher.""" + +from datetime import datetime, timedelta +from typing import Any, Dict, List, Literal, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.major_indices_historical import ( + MajorIndicesHistoricalData, + MajorIndicesHistoricalQueryParams, +) +from openbb_provider.utils.helpers import make_request +from pydantic import Field + +from openbb_cboe.utils.helpers import ( + TICKER_EXCEPTIONS, + get_cboe_index_directory, + get_ticker_info, +) + + +class CboeMajorIndicesHistoricalQueryParams(MajorIndicesHistoricalQueryParams): + """CBOE Stock end of day query. + + Source: https://www.cboe.com/ + """ + + interval: Optional[Literal["1d", "1m"]] = Field( + description="Use interval, 1m, for intraday prices during the most recent trading period.", + default="1d", + ) + + +class CboeMajorIndicesHistoricalData(MajorIndicesHistoricalData): + """CBOE Stocks End of Day Data.""" + + calls_volume: Optional[float] = Field( + description="Number of calls traded during the most recent trading period. Only valid if interval is 1m." + ) + puts_volume: Optional[float] = Field( + description="Number of puts traded during the most recent trading period. Only valid if interval is 1m." + ) + total_options_volume: Optional[float] = Field( + description="Total number of options traded during the most recent trading period. Only valid if interval is 1m." + ) + + +class CboeMajorIndicesHistoricalFetcher( + Fetcher[ + CboeMajorIndicesHistoricalQueryParams, + CboeMajorIndicesHistoricalData, + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query( + params: Dict[str, Any] + ) -> CboeMajorIndicesHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + return CboeMajorIndicesHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeMajorIndicesHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + # Synbol directories are cached for seven days and are used for error handling and URL generation. + INDEXES = get_cboe_index_directory().index.to_list() + query.symbol = query.symbol.upper() + data = pd.DataFrame() + if "^" in query.symbol: + query.symbol = query.symbol.replace("^", "") + if query.symbol == "NDX" and query.interval == "1d": + raise RuntimeError( + "NDX time series data is only supported when `interval='1m'`." + ) + + now = datetime.now() + query.start_date = ( + query.start_date if query.start_date else now - timedelta(days=50000) + ) + query.end_date = query.end_date if query.end_date else now + + if query.symbol not in INDEXES and query.symbol not in TICKER_EXCEPTIONS: + raise RuntimeError( + f"The symbol, {query.symbol}, was not found in the CBOE index directory. " + "Use `index_search()` to find supported indices. If the index is European, try `european_index()`." + ) + + def __generate_historical_prices_url( + symbol, + data_type: Optional[Literal["intraday", "historical"]] = "historical", + ) -> str: + """Generate the final URL for historical prices data.""" + url: str = ( + f"https://cdn.cboe.com/api/global/delayed_quotes/charts/{data_type}" + ) + url = ( + url + f"/_{symbol}.json" + if symbol in TICKER_EXCEPTIONS or symbol in INDEXES + else url + f"/{symbol}.json" + ) + return url + + url = ( + __generate_historical_prices_url(query.symbol, "intraday") + if query.interval == "1m" + else __generate_historical_prices_url(query.symbol) + ) + r = make_request(url) + + if r.status_code != 200: + raise RuntimeError(r.status_code) + + if query.interval == "1d": + data = ( + pd.DataFrame(r.json()["data"])[ + ["date", "open", "high", "low", "close", "volume"] + ] + ).set_index("date") + + # Fill in missing data from current or most recent trading session. + + today = pd.to_datetime(datetime.now().date()) + if today.weekday() > 4: + day_minus = today.weekday() - 4 + today = pd.to_datetime(today - timedelta(days=day_minus)) + if today != data.index[-1]: + _today = pd.Series(get_ticker_info(query.symbol)) + today_df = pd.Series(dtype="object") + today_df["open"] = round(_today["open"], 2) + today_df["high"] = round(_today["high"], 2) + today_df["low"] = round(_today["low"], 2) + today_df["close"] = round(_today["close"], 2) + if ( + query.symbol not in INDEXES + and query.symbol not in TICKER_EXCEPTIONS + ): + data = data[data["volume"] > 0] + today_df["volume"] = _today["volume"] + today_df["date"] = today.date() + today_df = pd.DataFrame(today_df).transpose().set_index("date") + + data = pd.concat([data, today_df], axis=0) + + # If ticker is an index there is no volume data and the types must be set. + + if query.symbol in INDEXES or query.symbol in TICKER_EXCEPTIONS: + data = data[["open", "high", "low", "close", "volume"]] + data["open"] = round(data.open.astype(float), 2) + data["high"] = round(data.high.astype(float), 2) + data["low"] = round(data.low.astype(float), 2) + data["close"] = round(data.close.astype(float), 2) + data["volume"] = 0 + + data.index = pd.to_datetime(data.index, format="%Y-%m-%d") + data = data[data["open"] > 0] + + data = data[ + (data.index >= pd.to_datetime(query.start_date, format="%Y-%m-%d")) + & (data.index <= pd.to_datetime(query.end_date, format="%Y-%m-%d")) + ] + data.index = data.index.astype(str) + + if query.interval == "1m": + data_list = r.json()["data"] + date: List[datetime] = [] + open: List[float] = [] + high: List[float] = [] + low: List[float] = [] + close: List[float] = [] + volume: List[float] = [] + calls_volume: List[float] = [] + puts_volume: List[float] = [] + total_options_volume: List[float] = [] + + for i in range(0, len(data_list)): + date.append(data_list[i]["datetime"]) + open.append(data_list[i]["price"]["open"]) + high.append(data_list[i]["price"]["high"]) + low.append(data_list[i]["price"]["low"]) + close.append(data_list[i]["price"]["close"]) + volume.append(data_list[i]["volume"]["stock_volume"]) + calls_volume.append(data_list[i]["volume"]["calls_volume"]) + puts_volume.append(data_list[i]["volume"]["puts_volume"]) + total_options_volume.append( + data_list[i]["volume"]["total_options_volume"] + ) + data = pd.DataFrame() + data["date"] = pd.to_datetime(date) + data["open"] = open + data["high"] = high + data["low"] = low + data["close"] = close + data["volume"] = volume + data["calls_volume"] = calls_volume + data["puts_volume"] = puts_volume + data["total_options_volume"] = total_options_volume + data = data.set_index("date").sort_index() + data.index = data.index.astype(str) + data = data[data["open"] > 0] + + return data.reset_index().to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[CboeMajorIndicesHistoricalData]: + """Transform the data to the standard format""" + return [CboeMajorIndicesHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/options_chains.py b/openbb_sdk/providers/cboe/openbb_cboe/models/options_chains.py index 5afcc22426b..25f7929a576 100644 --- a/openbb_sdk/providers/cboe/openbb_cboe/models/options_chains.py +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/options_chains.py @@ -4,18 +4,24 @@ from datetime import datetime from typing import Any, Dict, List, Optional +import pandas as pd from openbb_provider.abstract.fetcher import Fetcher from openbb_provider.standard_models.options_chains import ( OptionsChainsData, OptionsChainsQueryParams, ) +from openbb_provider.utils.helpers import make_request from pydantic import Field, validator -from openbb_cboe.utils.helpers import get_chains +from openbb_cboe.utils.helpers import ( + TICKER_EXCEPTIONS, + get_cboe_directory, + get_cboe_index_directory, +) class CboeOptionsChainsQueryParams(OptionsChainsQueryParams): - """CBOE Options Chains query. + """Get the complete options chains for a ticker from CBOE. Source: https://www.cboe.com/ """ @@ -24,36 +30,12 @@ class CboeOptionsChainsQueryParams(OptionsChainsQueryParams): class CboeOptionsChainsData(OptionsChainsData): """CBOE Options Chains Data.""" - contract_symbol: str = Field( - description="Contract symbol for the option.", - ) - dte: int = Field( - description="Days to expiration for the option.", - ) bid_size: int = Field( description="Bid size for the option.", ) ask_size: int = Field( description="Ask size for the option.", ) - implied_volatility: float = Field( - description="Implied volatility of the option.", - ) - delta: float = Field( - description="Delta of the option.", - ) - gamma: float = Field( - description="Gamma of the option.", - ) - theta: float = Field( - description="Theta of the option.", - ) - rho: float = Field( - description="Rho of the option.", - ) - vega: float = Field( - description="Vega of the option.", - ) theoretical: float = Field( description="Theoretical value of the option.", ) @@ -72,7 +54,7 @@ class CboeOptionsChainsData(OptionsChainsData): tick: str = Field( description="Whether the last tick was up or down in price.", ) - previous_close: float = Field( + prev_close: float = Field( description="Previous closing price of the option.", ) change: float = Field( @@ -81,9 +63,30 @@ class CboeOptionsChainsData(OptionsChainsData): change_percent: float = Field( description="Change, in percent, of the option.", ) + implied_volatility: float = Field( + description="Implied volatility of the option.", + ) + delta: float = Field( + description="Delta of the option.", + ) + gamma: float = Field( + description="Gamma of the option.", + ) + vega: float = Field( + description="Vega of the option.", + ) + theta: float = Field( + description="Theta of the option.", + ) + rho: float = Field( + description="Rho of the option.", + ) last_trade_timestamp: datetime = Field( description="Last trade timestamp of the option.", ) + dte: int = Field( + description="Days to expiration for the option.", + ) @validator("expiration", pre=True, check_fields=False) def date_validate(cls, v): # pylint: disable=E0213 @@ -109,9 +112,86 @@ class CboeOptionsChainsFetcher( query: CboeOptionsChainsQueryParams, credentials: Optional[Dict[str, str]], **kwargs: Any, - ) -> dict: + ) -> List[Dict]: """Return the raw data from the CBOE endpoint""" - return get_chains(query.symbol).to_dict("records") + + symbol = query.symbol.upper() + + INDEXES = get_cboe_index_directory() + SYMBOLS = get_cboe_directory() + + if symbol not in SYMBOLS.index: + raise RuntimeError(f"{symbol} was not found in the CBOE directory.") + + quotes_url = ( + f"https://cdn.cboe.com/api/global/delayed_quotes/options/_{symbol}.json" + if symbol in TICKER_EXCEPTIONS or symbol in INDEXES.index + else f"https://cdn.cboe.com/api/global/delayed_quotes/options/{symbol}.json" + ) + + r = make_request(quotes_url) + if r.status_code != 200: + raise RuntimeError(f"No options data found for the symbol, {symbol}.") + + r_json = r.json() + options_df = pd.DataFrame.from_records(r_json["data"]["options"]) + + options_df = options_df.rename( + columns={ + "option": "contract_symbol", + "iv": "implied_volatility", + "theo": "theoretical", + "last_trade_price": "last_trade_price", + "last_trade_time": "last_trade_timestamp", + "percent_change": "change_percent", + "prev_day_close": "prev_close", + } + ) + + # Parses the option symbols into columns for expiration, strike, and option_type + + option_df_index = options_df["contract_symbol"].str.extractall( + r"^(?P\D*)(?P\d*)(?P\D*)(?P\d*)" + ) + option_df_index = option_df_index.reset_index().drop( + columns=["match", "level_0"] + ) + option_df_index.option_type = option_df_index.option_type.str.replace( + "C", "call" + ).str.replace("P", "put") + option_df_index.strike = [ele.lstrip("0") for ele in option_df_index.strike] + option_df_index.strike = pd.Series(option_df_index.strike).astype(float) + option_df_index.strike = option_df_index.strike * (1 / 1000) + option_df_index.strike = option_df_index.strike.to_list() + option_df_index.expiration = [ + ele.lstrip("1") for ele in option_df_index.expiration + ] + option_df_index.expiration = pd.DatetimeIndex( + option_df_index.expiration, yearfirst=True + ).astype(str) + option_df_index = option_df_index.drop(columns=["Ticker"]) + + # Joins the parsed symbol into the dataframe. + + quotes = option_df_index.join(options_df) + + now = datetime.now() + temp = pd.DatetimeIndex(quotes.expiration) + temp_ = (temp - now).days + 1 + quotes["dte"] = temp_ + + quotes["last_trade_timestamp"] = pd.to_datetime(quotes["last_trade_timestamp"]) + quotes = quotes.set_index( + keys=["expiration", "strike", "option_type"] + ).sort_index() + quotes["open_interest"] = quotes["open_interest"].astype("int64") + quotes["volume"] = quotes["volume"].astype("int64") + quotes["bid_size"] = quotes["bid_size"].astype("int64") + quotes["ask_size"] = quotes["ask_size"].astype("int64") + quotes["prev_close"] = round(quotes["prev_close"], 2) + quotes["change_percent"] = round(quotes["change_percent"], 2) + + return quotes.reset_index().to_dict("records") @staticmethod def transform_data( diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/stock_historical.py b/openbb_sdk/providers/cboe/openbb_cboe/models/stock_historical.py new file mode 100644 index 00000000000..8d91be12e83 --- /dev/null +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/stock_historical.py @@ -0,0 +1,210 @@ +"""CBOE Major Indices End of Day fetcher.""" + +from datetime import datetime, timedelta +from typing import Any, Dict, List, Literal, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_historical import ( + StockHistoricalData, + StockHistoricalQueryParams, +) +from openbb_provider.utils.helpers import make_request +from pydantic import Field + +from openbb_cboe.utils.helpers import ( + TICKER_EXCEPTIONS, + get_cboe_directory, + get_cboe_index_directory, + get_ticker_info, +) + + +class CboeStockHistoricalQueryParams(StockHistoricalQueryParams): + """CBOE Stock end of day query. + + Source: https://www.cboe.com/ + """ + + interval: Optional[Literal["1d", "1m"]] = Field( + description="Use interval, 1m, for intraday prices during the most recent trading period.", + default="1d", + ) + + +class CboeStockHistoricalData(StockHistoricalData): + """CBOE Stocks End of Day Data.""" + + calls_volume: Optional[float] = Field( + description="Number of calls traded during the most recent trading period. Only valid if interval is 1m." + ) + puts_volume: Optional[float] = Field( + description="Number of puts traded during the most recent trading period. Only valid if interval is 1m." + ) + total_options_volume: Optional[float] = Field( + description="Total number of options traded during the most recent trading period. Only valid if interval is 1m." + ) + + +class CboeStockHistoricalFetcher( + Fetcher[ + CboeStockHistoricalQueryParams, + CboeStockHistoricalData, + ] +): + """Transform the query, extract and transform the data from the CBOE endpoints""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> CboeStockHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + return CboeStockHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: CboeStockHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the CBOE endpoint""" + + # Synbol directories are cached for seven days and are used for error handling and URL generation. + SYMBOLS = get_cboe_directory() + INDEXES = get_cboe_index_directory().index.to_list() + query.symbol = query.symbol.upper() + data = pd.DataFrame() + if "^" in query.symbol: + query.symbol = query.symbol.replace("^", "") + if query.symbol == "NDX" and query.interval == "1d": + raise RuntimeError( + "NDX time series data is only supported when `interval='1m'`." + ) + + now = datetime.now() + query.start_date = ( + query.start_date if query.start_date else now - timedelta(days=50000) + ) + query.end_date = query.end_date if query.end_date else now + + if query.symbol not in SYMBOLS.index and query.symbol not in INDEXES: + raise RuntimeError( + f"The symbol, {query.symbol}, was not found in the CBOE directory. Use `search()`." + ) + + def __generate_historical_prices_url( + symbol, + data_type: Optional[Literal["intraday", "historical"]] = "historical", + ) -> str: + """Generate the final URL for historical prices data.""" + url: str = ( + f"https://cdn.cboe.com/api/global/delayed_quotes/charts/{data_type}" + ) + url = ( + url + f"/_{symbol}.json" + if symbol in TICKER_EXCEPTIONS or symbol in INDEXES + else url + f"/{symbol}.json" + ) + return url + + url = ( + __generate_historical_prices_url(query.symbol, "intraday") + if query.interval == "1m" + else __generate_historical_prices_url(query.symbol) + ) + r = make_request(url) + + if r.status_code != 200: + raise RuntimeError(r.status_code) + + if query.interval == "1d": + data = ( + pd.DataFrame(r.json()["data"])[ + ["date", "open", "high", "low", "close", "volume"] + ] + ).set_index("date") + + # Fill in missing data from current or most recent trading session. + + today = pd.to_datetime(datetime.now().date()) + if today.weekday() > 4: + day_minus = today.weekday() - 4 + today = pd.to_datetime(today - timedelta(days=day_minus)) + if today != data.index[-1]: + _today = pd.Series(get_ticker_info(query.symbol)) + today_df = pd.Series(dtype="object") + today_df["open"] = round(_today["open"], 2) + today_df["high"] = round(_today["high"], 2) + today_df["low"] = round(_today["low"], 2) + today_df["close"] = round(_today["close"], 2) + if ( + query.symbol not in INDEXES + and query.symbol not in TICKER_EXCEPTIONS + ): + data = data[data["volume"] > 0] + today_df["volume"] = _today["volume"] + today_df["date"] = today.date() + today_df = pd.DataFrame(today_df).transpose().set_index("date") + + data = pd.concat([data, today_df], axis=0) + + # If ticker is an index there is no volume data and the types must be set. + + if query.symbol in INDEXES or query.symbol in TICKER_EXCEPTIONS: + data = data[["open", "high", "low", "close", "volume"]] + data["open"] = round(data.open.astype(float), 2) + data["high"] = round(data.high.astype(float), 2) + data["low"] = round(data.low.astype(float), 2) + data["close"] = round(data.close.astype(float), 2) + data["volume"] = 0 + + data.index = pd.to_datetime(data.index, format="%Y-%m-%d") + data = data[data["open"] > 0] + data = data[ + (data.index >= pd.to_datetime(query.start_date, format="%Y-%m-%d")) + & (data.index <= pd.to_datetime(query.end_date, format="%Y-%m-%d")) + ] + data.index = data.index.astype(str) + if query.interval == "1m": + data_list = r.json()["data"] + date: List[datetime] = [] + open: List[float] = [] + high: List[float] = [] + low: List[float] = [] + close: List[float] = [] + volume: List[float] = [] + calls_volume: List[float] = [] + puts_volume: List[float] = [] + total_options_volume: List[float] = [] + + for i in range(0, len(data_list)): + date.append(data_list[i]["datetime"]) + open.append(data_list[i]["price"]["open"]) + high.append(data_list[i]["price"]["high"]) + low.append(data_list[i]["price"]["low"]) + close.append(data_list[i]["price"]["close"]) + volume.append(data_list[i]["volume"]["stock_volume"]) + calls_volume.append(data_list[i]["volume"]["calls_volume"]) + puts_volume.append(data_list[i]["volume"]["puts_volume"]) + total_options_volume.append( + data_list[i]["volume"]["total_options_volume"] + ) + data = pd.DataFrame() + data["date"] = pd.to_datetime(date) + data["open"] = open + data["high"] = high + data["low"] = low + data["close"] = close + data["volume"] = volume + data["calls_volume"] = calls_volume + data["puts_volume"] = puts_volume + data["total_options_volume"] = total_options_volume + data = data.set_index("date").sort_index() + data.index = data.index.astype(str) + data = data[data["open"] > 0] + + data["volume"] = round(data["volume"].astype("int64")) + return data.drop_duplicates().reset_index().to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[CboeStockHistoricalData]: + """Transform the data to the standard format""" + return [CboeStockHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/stock_info.py b/openbb_sdk/providers/cboe/openbb_cboe/models/stock_info.py index d7f9d9b03ef..7778e9a9792 100644 --- a/openbb_sdk/providers/cboe/openbb_cboe/models/stock_info.py +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/stock_info.py @@ -4,6 +4,7 @@ from datetime import datetime from typing import Any, Dict, List, Optional +import pandas as pd from openbb_provider.abstract.fetcher import Fetcher from openbb_provider.standard_models.stock_info import ( StockInfoData, @@ -11,7 +12,12 @@ from openbb_provider.standard_models.stock_info import ( ) from pydantic import Field -from openbb_cboe.utils.helpers import get_info +from openbb_cboe.utils.helpers import ( + get_cboe_directory, + get_cboe_index_directory, + get_ticker_info, + get_ticker_iv, +) class CboeStockInfoQueryParams(StockInfoQueryParams): @@ -25,6 +31,7 @@ class CboeStockInfoData(StockInfoData): """CBOE Company Search Data.""" type: Optional[str] = Field(description="Type of asset.") + exchange_id: Optional[int] = Field(description="The Exchange ID number.") tick: Optional[str] = Field( description="Whether the last sale was an up or down tick." ) @@ -35,43 +42,43 @@ class CboeStockInfoData(StockInfoData): volume: Optional[float] = Field( description="Stock volume for the current trading day." ) - iv_thirty: Optional[float] = Field( + iv30: Optional[float] = Field( description="The 30-day implied volatility of the stock." ) - iv_thirty_change: Optional[float] = Field( + iv30_change: Optional[float] = Field( description="Change in 30-day implied volatility of the stock." ) last_trade_timestamp: Optional[datetime] = Field( description="Last trade timestamp for the stock." ) - iv_thirty_one_year_high: Optional[float] = Field( + iv30_annual_high: Optional[float] = Field( description="The 1-year high of implied volatility." ) - hv_thirty_one_year_high: Optional[float] = Field( + hv30_annual_high: Optional[float] = Field( description="The 1-year high of realized volatility." ) - iv_thirty_one_year_low: Optional[float] = Field( + iv30_annual_low: Optional[float] = Field( description="The 1-year low of implied volatility." ) - hv_thirty_one_year_low: Optional[float] = Field( + hv30_annual_low: Optional[float] = Field( description="The 1-year low of realized volatility." ) - iv_sixty_one_year_high: Optional[float] = Field( + iv60_annual_high: Optional[float] = Field( description="The 60-day high of implied volatility." ) - hv_sixty_one_year_high: Optional[float] = Field( + hv60_annual_high: Optional[float] = Field( description="The 60-day high of realized volatility." ) - iv_sixty_one_year_low: Optional[float] = Field( + iv60_annual_low: Optional[float] = Field( description="The 60-day low of implied volatility." ) - hv_sixty_one_year_low: Optional[float] = Field( + hv60_annual_low: Optional[float] = Field( description="The 60-day low of realized volatility." ) - iv_ninety_one_year_high: Optional[float] = Field( + iv90_annual_high: Optional[float] = Field( description="The 90-day high of implied volatility." ) - hv_ninety_one_year_high: Optional[float] = Field( + hv90_annual_high: Optional[float] = Field( description="The 90-day high of realized volatility." ) @@ -96,7 +103,26 @@ class CboeStockInfoFetcher( **kwargs: Any, ) -> dict: """Return the raw data from the CBOE endpoint""" - return get_info(query.symbol).to_dict() + + query.symbol = query.symbol.upper() + INDEXES = get_cboe_index_directory().index.to_list() + SYMBOLS = get_cboe_directory() + + if query.symbol not in SYMBOLS.index and query.symbol not in INDEXES: + raise RuntimeError( + f"The symbol, {query.symbol}, was not found in the CBOE directory." + ) + + _info = pd.Series(get_ticker_info(query.symbol)) + _iv = pd.Series(get_ticker_iv(query.symbol)) + data = ( + pd.DataFrame(pd.concat([_info, _iv])) + .transpose() + .drop(columns="seqno") + .iloc[0] + ) + + return data.to_dict() @staticmethod def transform_data(data: dict) -> List[CboeStockInfoData]: diff --git a/openbb_sdk/providers/cboe/openbb_cboe/models/stock_search.py b/openbb_sdk/providers/cboe/openbb_cboe/models/stock_search.py index c227945296b..8e23abfce53 100644 --- a/openbb_sdk/providers/cboe/openbb_cboe/models/stock_search.py +++ b/openbb_sdk/providers/cboe/openbb_cboe/models/stock_search.py @@ -10,7 +10,7 @@ from openbb_provider.standard_models.stock_search import ( ) from pydantic import Field -from openbb_cboe.utils.helpers import stock_search +from openbb_cboe.utils.helpers import get_cboe_directory class CboeStockSearchQueryParams(StockSearchQueryParams): @@ -23,20 +23,9 @@ class CboeStockSearchQueryParams(StockSearchQueryParams): class CboeStockSearchData(StockSearchData): """CBOE Company Search Data.""" - class Config: - """Pydantic alias config using fields dict""" - - fields = { - "name": "Company Name", - } - - dpm_name: Optional[str] = Field( - description="Name of the primary market maker.", - alias="DPM Name", - ) + dpm_name: Optional[str] = Field(description="Name of the primary market maker.") post_station: Optional[str] = Field( - description="Post and station location on the CBOE trading floor.", - alias="Post/Station", + description="Post and station location on the CBOE trading floor." ) @@ -60,14 +49,17 @@ class CboeStockSearchFetcher( **kwargs: Any, ) -> dict: """Return the raw data from the CBOE endpoint.""" - data = stock_search(query.query, ticker=query.ticker) - if "results" in data: - return data["results"] + data = {} + symbols = get_cboe_directory().reset_index() + target = "name" if not query.ticker else "symbol" + idx = symbols[target].str.contains(query.query, case=False) + result = symbols[idx].to_dict("records") + data.update({"results": result}) - raise ValueError("No results found.") + return data @staticmethod def transform_data(data: dict) -> List[CboeStockSearchData]: """Transform the data to the standard format.""" - return [CboeStockSearchData.parse_obj(d) for d in data] + return [CboeStockSearchData.parse_obj(d) for d in data["results"]] diff --git a/openbb_sdk/providers/cboe/openbb_cboe/utils/helpers.py b/openbb_sdk/providers/cboe/openbb_cboe/utils/helpers.py index 2885d343d84..b3b0341b890 100644 --- a/openbb_sdk/providers/cboe/openbb_cboe/utils/helpers.py +++ b/openbb_sdk/providers/cboe/openbb_cboe/utils/helpers.py @@ -1,16 +1,13 @@ """CBOE Helpers Module.""" -import os -import warnings -from datetime import date, datetime, timedelta -from io import StringIO -from pathlib import Path -from typing import List, Optional, Tuple +from datetime import date, timedelta +from io import BytesIO, StringIO +from typing import Any, Dict, List, Optional -import numpy as np import pandas as pd import requests import requests_cache +from openbb_provider.utils.helpers import to_snake_case TICKER_EXCEPTIONS = ["NDX", "RUT"] # This will cache the import requests for 7 days. Ideally to speed up subsequent imports. @@ -19,71 +16,62 @@ cboe_session = requests_cache.CachedSession( "OpenBB_CBOE", expire_after=timedelta(days=7), use_cache_dir=True ) +US_INDEX_COLUMNS = { + "symbol": "symbol", + "name": "name", + "current_price": "price", + "open": "open", + "high": "high", + "low": "low", + "close": "close", + "prev_day_close": "prev_close", + "price_change": "change", + "price_change_percent": "change_percent", + "last_trade_time": "last_trade_timestamp", +} -def get_user_agent() -> str: - """Get a not very random user agent.""" - user_agent_strings = [ - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.10; rv:86.1) Gecko/20100101 Firefox/86.1", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:86.1) Gecko/20100101 Firefox/86.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.10; rv:82.1) Gecko/20100101 Firefox/82.1", - "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.13; rv:86.0) Gecko/20100101 Firefox/86.0", - "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:86.0) Gecko/20100101 Firefox/86.0", - "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10.10; rv:83.0) Gecko/20100101 Firefox/83.0", - "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:84.0) Gecko/20100101 Firefox/84.0", - ] +EUR_INDEX_COLUMNS = { + "name": "name", + "isin": "isin", + "currency": "currency", + "current_price": "price", + "open": "open", + "high": "high", + "low": "low", + "close": "close", + "prev_day_close": "prev_close", + "price_change": "change", + "price_change_percent": "change_percent", + "last_trade_time": "last_trade_timestamp", +} - return np.random.choice(user_agent_strings) # nosec +EUR_INDEX_CONSTITUENTS_COLUMNS = { + "symbol": "symbol", + "current_price": "price", + "open": "open", + "high": "high", + "low": "low", + "close": "close", + "volume": "volume", + "seqno": "seqno", + "prev_day_close": "prev_close", + "price_change": "change", + "price_change_percent": "change_percent", + "last_trade_time": "last_trade_timestamp", + "exchange_id": "exchange_id", + "tick": "tick", + "security_type": "type", +} -def request( - url: str, method: str = "GET", timeout: int = 10, **kwargs -) -> requests.Response: - """Abstract helper to make requests from a url with potential headers and params. - - Parameters - ---------- - url : str - Url to make the request to - method : str, optional - HTTP method to use. Can be "GET" or "POST", by default "GET" - timeout : int, optional - Timeout in seconds, by default 10 - - Returns - ------- - requests.Response - Request response object - - Raises - ------ - ValueError - If invalid method is passed - """ - - # If there are headers, check if there is a user agent, if not add one. - # Some requests seem to work only with a specific user agent, so we want to be able to override it. - headers = kwargs.pop("headers", {}) - - if "User-Agent" not in headers: - headers["User-Agent"] = get_user_agent() - - if (func := getattr(requests, method.lower(), None)) is not None: - return func( - url, - headers=headers, - timeout=timeout, - **kwargs, - ) - - raise ValueError("Method must be valid HTTP method") +# This will cache certain requests for 7 days. Ideally to speed up subsequent queries. +# Only used on functions with static values like symbol directories. +cboe_session = requests_cache.CachedSession( + "OpenBB_CBOE", expire_after=timedelta(days=7), use_cache_dir=True +) -def camel_to_snake(string: str) -> str: - """Convert camelCase to snake_case.""" - return "".join(["_" + i.lower() if i.isupper() else i for i in string]).lstrip("_") - - -def get_cboe_directory() -> pd.DataFrame: +def get_cboe_directory(**kwargs) -> pd.DataFrame: """Get the US Listings Directory for the CBOE. Returns @@ -91,276 +79,133 @@ def get_cboe_directory() -> pd.DataFrame: pd.DataFrame: CBOE_DIRECTORY DataFrame of the CBOE listings directory """ - try: - CBOE_DIRECTORY: pd.DataFrame = pd.read_csv( - StringIO( - cboe_session.get( - "https://www.cboe.com/us/options/symboldir/equity_index_options/?download=csv", - timeout=10, - ).text - ) - ) - CBOE_DIRECTORY = CBOE_DIRECTORY.rename( - columns={ - " Stock Symbol": "Symbol", - " DPM Name": "DPM Name", - " Post/Station": "Post/Station", - } - ).set_index("Symbol") - return CBOE_DIRECTORY - except requests.HTTPError: - return pd.DataFrame() + + r = cboe_session.get( + "https://www.cboe.com/us/options/symboldir/equity_index_options/?download=csv", + timeout=10, + ) + + if r.status_code != 200: + raise RuntimeError(r.status_code) + + r_json = StringIO(r.text) + + CBOE_DIRECTORY = pd.read_csv(r_json) + + CBOE_DIRECTORY = CBOE_DIRECTORY.rename( + columns={ + " Stock Symbol": "symbol", + " DPM Name": "dpm_name", + " Post/Station": "post_station", + "Company Name": "name", + } + ).set_index("symbol") + + return CBOE_DIRECTORY -def get_cboe_index_directory() -> pd.DataFrame: +def get_cboe_index_directory(**kwargs) -> pd.DataFrame: """Get the US Listings Directory for the CBOE Returns ------- pd.DataFrame: CBOE_INDEXES """ - try: - r = cboe_session.get( - "https://cdn.cboe.com/api/global/us_indices/definitions/all_indices.json", - timeout=10, - ) - if r.status_code != 200: - raise requests.HTTPError + r = cboe_session.get( + "https://cdn.cboe.com/api/global/us_indices/definitions/all_indices.json", + timeout=10, + ) - CBOE_INDEXES = pd.DataFrame(r.json()) + if r.status_code != 200: + raise requests.HTTPError(r.status_code) - CBOE_INDEXES = CBOE_INDEXES.rename( - columns={ - "calc_end_time": "Close Time", - "calc_start_time": "Open Time", - "currency": "Currency", - "description": "Description", - "display": "Display", - "featured": "Featured", - "featured_order": "Featured Order", - "index_symbol": "Ticker", - "mkt_data_delay": "Data Delay", - "name": "Name", - "tick_days": "Tick Days", - "tick_frequency": "Frequency", - "tick_period": "Period", - "time_zone": "Time Zone", - }, - ) + CBOE_INDEXES = pd.DataFrame(r.json()) - indices_order: List[str] = [ - "Ticker", - "Name", - "Description", - "Currency", - "Tick Days", - "Frequency", - "Period", - "Time Zone", - ] + CBOE_INDEXES = CBOE_INDEXES.rename( + columns={ + "calc_end_time": "close_time", + "calc_start_time": "open_time", + "index_symbol": "symbol", + "mkt_data_delay": "data_delay", + }, + ) - CBOE_INDEXES = pd.DataFrame(CBOE_INDEXES, columns=indices_order).set_index( - "Ticker" - ) + indices_order: List[str] = [ + "symbol", + "name", + "description", + "currency", + "open_time", + "close_time", + "tick_days", + "tick_frequency", + "tick_period", + "time_zone", + "data_delay", + ] - return CBOE_INDEXES + CBOE_INDEXES = pd.DataFrame(CBOE_INDEXES, columns=indices_order).set_index("symbol") - except requests.HTTPError: - return pd.DataFrame() + idx = ( + (CBOE_INDEXES.time_zone.str.contains("America/Chicago")) + & (CBOE_INDEXES.currency.str.contains("USD")) + & (CBOE_INDEXES.description.str.contains("Daily Risk Control") == 0) + & (CBOE_INDEXES.name.str.contains("OEX%-SML% INDEX") == 0) + & (CBOE_INDEXES.name.str.contains("Defined Risk Volatility Income") == 0) + & (CBOE_INDEXES.description.str.contains("is designed to track") == 0) + ) + + return CBOE_INDEXES[idx] -INDEXES = get_cboe_index_directory().index.tolist() -SYMBOLS = pd.DataFrame() -try: - SYMBOLS = get_cboe_directory() -except SYMBOLS.empty: - current_dir = os.path.dirname(os.path.realpath(__file__)) - file = "cboe_companies.json" - SYMBOLS = pd.read_json(Path(current_dir, file)) - - -def stock_search(query: str, ticker: bool = False) -> dict: - """Search the CBOE company directory by name or ticker. - Parameters - ----------- - query: str - The search query - ticker: bool - Whether to search by ticker. Default is False. - - Returns - ------- - dict - Dictionary of the results. - """ - data = {} - symbols = SYMBOLS.copy() if not SYMBOLS.empty else get_cboe_directory() - symbols = symbols.reset_index() - target = "Company Name" if not ticker else "Symbol" - idx = symbols[target].str.contains(query, case=False) - result = symbols[idx].to_dict("records") - if len(result) > 0: - data.update({"results": result}) - return data - warnings.warn(f"No results found for: {query}. Try another search query.") - return pd.DataFrame() - - -def get_ticker_info(symbol: str) -> Tuple[pd.DataFrame, List[str]]: - """Get basic info for the symbol and expiration dates - - Parameters - ---------- - symbol: str - The ticker to lookup - - Returns - ------- - Tuple: [pd.DataFrame, pd.Series] - ticker_details - ticker_expirations - """ - - stock = "stock" - index = "index" +def get_ticker_info(symbol: str, **kwargs) -> dict[str, Any]: symbol = symbol.upper() - new_ticker: str = "" - ticker_details = pd.DataFrame() - ticker_expirations: list = [] - try: - if symbol in TICKER_EXCEPTIONS: - new_ticker = "^" + symbol - elif symbol not in INDEXES: - new_ticker = symbol + SYMBOLS = get_cboe_directory() + INDEXES = get_cboe_index_directory() + data: dict[str, Any] = {} - elif symbol in INDEXES: - new_ticker = "^" + symbol + if symbol not in SYMBOLS.index and symbol not in INDEXES.index: + raise RuntimeError(f"Data not found for: {symbol}") - # Get the data to return, and if none returns empty Tuple # + url = ( + f"https://cdn.cboe.com/api/global/delayed_quotes/quotes/_{symbol}.json" + if symbol in INDEXES.index or symbol in TICKER_EXCEPTIONS + else f"https://cdn.cboe.com/api/global/delayed_quotes/quotes/{symbol}.json" + ) - symbol_info_url = ( - "https://www.cboe.com/education/tools/trade-optimizer/symbol-info/?symbol=" - f"{new_ticker}" - ) + r = requests.get(url, timeout=10) - symbol_info = request(symbol_info_url) - symbol_info_json = pd.Series(symbol_info.json()) + if r.status_code not in set([200, 403]): + raise requests.HTTPError(r.status_code) - if symbol_info_json.success is False: - ticker_details = pd.DataFrame() - ticker_expirations = [] - warnings.warn("No data found for the symbol: " f"{symbol}" "") - else: - symbol_details = pd.Series(symbol_info_json["details"]) - symbol_details = pd.DataFrame(symbol_details).transpose() - symbol_details = symbol_details.reset_index() - ticker_expirations = symbol_info_json["expirations"] + if r.status_code == 403: + raise RuntimeError(f"Data was not found for, {symbol}.") - # Cleans columns depending on if the security type is a stock or an index + data = r.json()["data"] - type_ = symbol_details.security_type + if symbol in SYMBOLS.index.to_list(): + data.update({"name": SYMBOLS.at[symbol, "name"]}) + if symbol in INDEXES.index.to_list(): + data.update({"name": INDEXES.at[symbol, "name"]}) - if stock[0] in type_[0]: - stock_details = symbol_details - ticker_details = pd.DataFrame(stock_details).rename( - columns={ - "current_price": "price", - "bid_size": "bidSize", - "ask_size": "askSize", - "iv30": "ivThirty", - "prev_day_close": "previousClose", - "price_change": "change", - "price_change_percent": "changePercent", - "iv30_change": "ivThirtyChange", - "iv30_percent_change": "ivThirtyChangePercent", - "last_trade_time": "lastTradeTimestamp", - "exchange_id": "exchangeID", - "tick": "tick", - "security_type": "type", - } - ) - details_columns = [ - "symbol", - "type", - "tick", - "bid", - "bidSize", - "askSize", - "ask", - "price", - "open", - "high", - "low", - "close", - "volume", - "previousClose", - "change", - "changePercent", - "ivThirty", - "ivThirtyChange", - "ivThirtyChangePercent", - "lastTradeTimestamp", - ] - ticker_details = ( - pd.DataFrame(ticker_details, columns=details_columns) - .set_index(keys="symbol") - .dropna(axis=1) - .transpose() - ) + _data = pd.DataFrame.from_dict(data, orient="index").transpose() - if index[0] in type_[0]: - index_details = symbol_details - ticker_details = pd.DataFrame(index_details).rename( - columns={ - "symbol": "symbol", - "security_type": "type", - "current_price": "price", - "price_change": "change", - "price_change_percent": "changePercent", - "prev_day_close": "previousClose", - "iv30": "ivThirty", - "iv30_change": "ivThirtyChange", - "iv30_change_percent": "ivThirtyChangePercent", - "last_trade_time": "lastTradeTimestamp", - } - ) + _data = _data.rename( + columns={ + "current_price": "price", + "prev_day_close": "prev_close", + "price_change": "change", + "price_change_percent": "change_percent", + "last_trade_time": "last_trade_timestamp", + "security_type": "type", + } + ) - index_columns = [ - "symbol", - "type", - "tick", - "price", - "open", - "high", - "low", - "close", - "previousClose", - "change", - "changePercent", - "ivThirty", - "ivThirtyChange", - "ivThirtyChangePercent", - "lastTradeTimestamp", - ] - - ticker_details = ( - pd.DataFrame(ticker_details, columns=index_columns) - .set_index(keys="symbol") - .dropna(axis=1) - .transpose() - ).rename(columns={f"{new_ticker}": f"{symbol}"}) - - except requests.HTTPError: - warnings.warn("There was an error with the request'\n") - ticker_details = pd.DataFrame() - ticker_expirations = list() - return ticker_details, ticker_expirations - - return ticker_details, ticker_expirations + return _data.transpose()[0].to_dict() -def get_ticker_iv(symbol: str) -> pd.DataFrame: +def get_ticker_iv(symbol: str, **kwargs) -> dict[str, float]: """Get annualized high/low historical and implied volatility over 30/60/90 day windows. Parameters @@ -373,341 +218,186 @@ def get_ticker_iv(symbol: str) -> pd.DataFrame: pd.DataFrame: ticker_iv """ - # Checks ticker to determine if ticker is an index or an exception that requires modifying the request's URLs + symbol = symbol.upper() - try: - if symbol in TICKER_EXCEPTIONS: - quotes_iv_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/_" - f"{symbol}" - ".json" - ) - elif symbol not in INDEXES: - quotes_iv_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/" - f"{symbol}" - ".json" - ) + INDEXES = get_cboe_index_directory().index.to_list() - elif symbol in INDEXES: - quotes_iv_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/_" - f"{symbol}" - ".json" - ) - h_iv = request(quotes_iv_url) + quotes_iv_url = ( + "https://cdn.cboe.com/api/global/delayed_quotes/historical_data/_" + f"{symbol}" + ".json" + if symbol in TICKER_EXCEPTIONS or symbol in INDEXES + else f"https://cdn.cboe.com/api/global/delayed_quotes/historical_data/{symbol}.json" + ) - if h_iv.status_code != 200: - warnings.warn("No data found for the symbol: " f"{symbol}" "") - return pd.DataFrame() + h_iv = requests.get(quotes_iv_url, timeout=10) - data = h_iv.json() - h_data = pd.DataFrame(data)[2:-1]["data"].rename(f"{symbol}") - h_data.rename( - { - "hv30_annual_high": "hvThirtyOneYearHigh", - "hv30_annual_low": "hvThirtyOneYearLow", - "hv60_annual_high": "hvSixtyOneYearHigh", - "hv60_annual_low": "hvSixtyOneYearLow", - "hv90_annual_high": "hvNinetyOneYearHigh", - "hv90_annual_low": "hvNinetyOneYearLow", - "iv30_annual_high": "ivThirtyOneYearHigh", - "iv30_annual_low": "ivThirtyOneYearLow", - "iv60_annual_high": "ivSixtyOneYearHigh", - "iv60_annual_low": "ivSixtyOneYearLow", - "iv90_annual_high": "ivNinetyOneYearHigh", - "iv90_annual_low": "ivNinetyOneYearLow", - }, - inplace=True, - ) + if h_iv.status_code not in set([200, 403]): + raise requests.HTTPError(h_iv.status_code) - iv_order = [ - "ivThirtyOneYearHigh", - "hvThirtyOneYearHigh", - "ivThirtyOneYearLow", - "hvThirtyOneYearLow", - "ivSixtyOneYearHigh", - "hvSixtyOneYearHigh", - "ivSixtyOneYearLow", - "hvSixtyOneYearLow", - "ivNinetyOneYearHigh", - "hvNinetyOneYearHigh", - "ivNinetyOneYearLow", - "hvNinetyOneYearLow", - ] + if h_iv.status_code == 403: + raise RuntimeError(f"Data was not found for, {symbol}.") - ticker_iv = pd.DataFrame(h_data).transpose() - except requests.HTTPError: - warnings.warn("There was an error with the request'\n") + data = pd.DataFrame(h_iv.json())[2:-1]["data"].rename(f"{symbol}") - return pd.DataFrame(ticker_iv, columns=iv_order).transpose() + return data.to_dict() -def get_chains(symbol: str) -> pd.DataFrame: - """Get the complete options chains for a ticker. - - Parameters - ---------- - symbol: str - The ticker get options data for +def list_futures(**kwargs) -> List[dict]: + """List of CBOE futures and their underlying symbols. Returns - ------- + -------- pd.DataFrame - DataFrame with all active options contracts for the underlying symbol. + Pandas DataFrame with results. """ - # Checks ticker to determine if ticker is an index or an exception that requires modifying the request's URLs. - symbol = symbol.upper() - try: - if symbol in TICKER_EXCEPTIONS: - quotes_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/options/_" - f"{symbol}" - ".json" - ) - else: - if symbol not in INDEXES: - quotes_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/options/" - f"{symbol}" - ".json" - ) - if symbol in INDEXES: - quotes_url = ( - "https://cdn.cboe.com/api/global/delayed_quotes/options/_" - f"{symbol}" - ".json" - ) + r = requests.get( + "https://cdn.cboe.com/api/global/delayed_quotes/symbol_book/futures-roots.json", + timeout=10, + ) - result = request(quotes_url) - if result.status_code != 200: - warnings.warn("No data found for the symbol: " f"{symbol}" "") - return pd.DataFrame() + if r.status_code != 200: + raise requests.HTTPError(r.status_code) - r_json = result.json() - data = pd.DataFrame(r_json["data"]) - options = pd.Series(data.options, index=data.index) - options_columns = list(options[0]) - options_data = list(options[:]) - options_df = pd.DataFrame(options_data, columns=options_columns) - - options_df = options_df.rename( - columns={ - "option": "contractSymbol", - "bid_size": "bidSize", - "ask_size": "askSize", - "iv": "impliedVolatility", - "open_interest": "openInterest", - "theo": "theoretical", - "last_trade_price": "lastTradePrice", - "last_trade_time": "lastTradeTimestamp", - "percent_change": "changePercent", - "prev_day_close": "previousClose", - } - ) - - # Parses the option symbols into columns for expiration, strike, and optionType - - option_df_index = options_df["contractSymbol"].str.extractall( - r"^(?P\D*)(?P\d*)(?P\D*)(?P\d*)" - ) - option_df_index = option_df_index.reset_index().drop( - columns=["match", "level_0"] - ) - option_df_index.optionType = option_df_index.optionType.str.replace( - "C", "call" - ).str.replace("P", "put") - option_df_index.strike = [ele.lstrip("0") for ele in option_df_index.strike] - option_df_index.strike = pd.Series(option_df_index.strike).astype(float) - option_df_index.strike = option_df_index.strike * (1 / 1000) - option_df_index.strike = option_df_index.strike.to_list() - option_df_index.expiration = [ - ele.lstrip("1") for ele in option_df_index.expiration - ] - option_df_index.expiration = pd.DatetimeIndex( - option_df_index.expiration, yearfirst=True - ).astype(str) - option_df_index = option_df_index.drop(columns=["Ticker"]) - - # Joins the parsed symbol into the dataframe. - - quotes = option_df_index.join(options_df) - - now = datetime.now() - temp = pd.DatetimeIndex(quotes.expiration) - temp_ = (temp - now).days + 1 - quotes["dte"] = temp_ - - quotes["lastTradeTimestamp"] = pd.to_datetime(quotes["lastTradeTimestamp"]) - quotes = quotes.set_index( - keys=["expiration", "strike", "optionType"] - ).sort_index() - quotes["openInterest"] = quotes["openInterest"].astype("int64") - quotes["volume"] = quotes["volume"].astype("int64") - quotes["bidSize"] = quotes["bidSize"].astype("int64") - quotes["askSize"] = quotes["askSize"].astype("int64") - quotes["previousClose"] = round(quotes["previousClose"], 2) - quotes["changePercent"] = round(quotes["changePercent"], 2) - - except requests.HTTPError: - warnings.warn("There was an error with the request'\n") - return pd.DataFrame() - - return quotes.reset_index() + return r.json()["data"] -def __generate_historical_prices_url( - symbol, data_type: Optional[str] = "historical" -) -> str: - """Generate the final URL for historical prices data.""" - - url: str = "" - - if data_type not in ["historical", "intraday"]: - warnings.warn( - "Invalid data_type. Must be either 'historical' or 'intraday'. Defaulting to 'historical'." - ) - data_type = "historical" - - if symbol in TICKER_EXCEPTIONS: - url = ( - f"https://cdn.cboe.com/api/global/delayed_quotes/charts/{data_type}/_" - f"{symbol}" - ".json" - ) - elif symbol not in INDEXES: - url = ( - f"https://cdn.cboe.com/api/global/delayed_quotes/charts/{data_type}/" - f"{symbol}" - ".json" - ) - - elif symbol in INDEXES: - url = ( - f"https://cdn.cboe.com/api/global/delayed_quotes/charts/{data_type}/_" - f"{symbol}" - ".json" - ) - return url - - -def get_eod_prices( - symbol: str, - start_date: Optional[date] = None, - end_date: Optional[date] = None, +def get_settlement_prices( + settlement_date: Optional[date] = None, + options: bool = False, + archives: bool = False, + final_settlement: bool = False, + **kwargs, ) -> pd.DataFrame: - """Get EOD data from CBOE. + """Gets the settlement prices of CBOE futures. Parameters - ---------- - symbol: str - The symbol of the company. - start_date: Optional[date] - The start date. [YYYY-MM-DD] - end_date: Optional[date] - The end date. [YYYY-MM-DD] - - Returns - ------- - pd.DataFrame - DataFrame of daily EOD OHLC+V prices. - """ - - symbol = symbol.upper() - if symbol == ("NDX", "^NDX"): - warnings.warn( - "NDX time series data is not currently supported by the CBOE provider." - ) - return pd.DataFrame() - if "^" in symbol: - symbol = symbol.replace("^", "") - now = datetime.now() - start_date = start_date if start_date else now - timedelta(days=50000) - end_date = end_date if end_date else now - if symbol not in SYMBOLS.index: - warnings.warn( - "The symbol, " f"{symbol}" ", was not found in the CBOE directory." - ) - return pd.DataFrame() - - url = __generate_historical_prices_url(symbol) - result = request(url) - - if result.status_code != 200: - warnings.warn(f"Error: {result.status_code}") - return pd.DataFrame() - - data = ( - pd.DataFrame(result.json()["data"])[ - ["date", "open", "high", "low", "close", "volume"] - ] - ).set_index("date") - - # Fill in missing data from current or most recent trading session. - - today = pd.to_datetime(datetime.now().date()) - if today.weekday() > 4: - day_minus = today.weekday() - 4 - today = pd.to_datetime(today - timedelta(days=day_minus)) - if today != data.index[-1]: - _today, _ = get_ticker_info(symbol) - today_df = pd.DataFrame() - today_df["open"] = round(_today.loc["open"].astype(float), 2) - today_df["high"] = round(_today.loc["high"].astype(float), 2) - today_df["low"] = round(_today.loc["low"].astype(float), 2) - today_df["close"] = round(_today.loc["close"].astype(float), 2) - if symbol not in INDEXES and symbol not in TICKER_EXCEPTIONS: - data = data[data["volume"] > 0] - today_df["volume"] = _today.loc["volume"] - today_df["date"] = today - today_df = today_df.reset_index(drop=True).set_index("date") - - data = pd.concat([data, today_df], axis=0) - - # If ticker is an index there is no volume data and the types must be set. - - if symbol in INDEXES or symbol in TICKER_EXCEPTIONS: - data = data[["open", "high", "low", "close", "volume"]] - data["open"] = round(data.open.astype(float), 2) - data["high"] = round(data.high.astype(float), 2) - data["low"] = round(data.low.astype(float), 2) - data["close"] = round(data.close.astype(float), 2) - data["volume"] = 0 - - data.index = pd.to_datetime(data.index, format="%Y-%m-%d") - data = data[data["open"] > 0] - - data = data[ - (data.index >= pd.to_datetime(start_date, format="%Y-%m-%d")) - & (data.index <= pd.to_datetime(end_date, format="%Y-%m-%d")) - ] - data.index = data.index.strftime("%Y-%m-%d") - return data.reset_index() - - -def get_info(symbol: str) -> pd.DataFrame: - """Get information and current statistics for a ticker. - - Parameters - ---------- - symbol: str - The symbol of the company. + ----------- + settlement_date: Optional[date] + The settlement date. Only valid for active contracts. [YYYY-MM-DD] + options: bool + If true, returns options on futures. + archives: bool + Settlement price archives for select years and products. Overridden by other parameters. + final_settlement: bool + Final settlement prices for expired contracts. Overrides archives. Returns ------- pd.DataFrame Pandas DataFrame with results. """ + url = "" + if archives is True: + url = "https://cdn.cboe.com/resources/futures/archive/volume-and-price/CFE_FinalSettlement_Archive.csv" - symbol = symbol.upper() - info = pd.DataFrame() + if settlement_date is not None: + url = f"https://www.cboe.com/us/futures/market_statistics/settlement/csv?dt={settlement_date}" + if options is True: + url = f"https://www.cboe.com/us/futures/market_statistics/settlement/csv?options=t&dt={settlement_date}" - _info = get_ticker_info(symbol)[0] - _iv = get_ticker_iv(symbol) - info = pd.concat([_info, _iv]) - info.index = [camel_to_snake(c) for c in info.index] - info.loc["symbol", symbol] = symbol - info.loc["name", symbol] = SYMBOLS[SYMBOLS.index == symbol]["Company Name"][0] + if settlement_date is None: + url = "https://www.cboe.com/us/futures/market_statistics/settlement/csv" + if options is True: + url = "https://www.cboe.com/us/futures/market_statistics/settlement/csv?options=t" - return info[symbol] + if final_settlement is True: + url = "https://www.cboe.com/us/futures/market_statistics/final_settlement_prices/csv/" + + r = requests.get(url, timeout=10) + + if r.status_code != 200: + raise RuntimeError(r.status_code) + + data = pd.read_csv(BytesIO(r.content), index_col=None, parse_dates=True) + + if data.empty: + error_string = ( + f"No results found for, {settlement_date}." + if settlement_date is not None + else "No results found." + ) + raise RuntimeError(error_string) + + data.columns = [to_snake_case(c) for c in data.columns] + data = data.rename(columns={"expiration_date": "expiration"}) + + if len(data) > 0: + return data + + return pd.DataFrame() + + +class Europe: + """Class for European CBOE data.""" + + @staticmethod + def get_all_index_definitions(**kwargs) -> dict[Any, Any]: + """Get the full list of European index definitions. + + Returns + ------- + dict[Any, Any] + Dictionary with results. + """ + + r = cboe_session.get( + "https://cdn.cboe.com/api/global/european_indices/definitions/all-definitions.json", + timeout=10, + ) + + if r.status_code != 200: + raise requests.HTTPError(r.status_code) + return r.json()["data"] + + @staticmethod + def list_indices(**kwargs) -> List[Dict]: + """Gets names, currencies, ISINs, regions, and symbols for European indices. + + Returns + ------- + dict[str, str] + List of dictionaries with the results. + """ + + data = Europe.get_all_index_definitions() + data = ( + pd.DataFrame.from_records(pd.DataFrame(data)["index"]) + .drop(columns=["short_name"]) + .rename(columns={"long_name": "name"}) + ) + return data.to_dict("records") + + @staticmethod + def list_index_constituents(symbol: str, **kwargs) -> List[str]: + """List symbols for constituents of a European index. + + Parameters + ---------- + symbol: str + The symbol of the index. + + Returns + ------- + List[str] + List of constituents as ticker symbols. + """ + + SYMBOLS = pd.DataFrame(Europe.list_indices())["symbol"].to_list() + symbol = symbol.upper() + + if symbol not in SYMBOLS: + raise RuntimeError( + f"The symbol, {symbol}, was not found in the CBOE European Index directory.", + ) + + url = f"https://cdn.cboe.com/api/global/european_indices/definitions/{symbol}.json" + r = requests.get(url, timeout=10) + + if r.status_code != 200: + raise requests.HTTPError(r.status_code) + + r_json = r.json()["constituents"] + + return [r_json[i]["constituent_symbol"] for i in range(0, len(r_json))] diff --git a/openbb_sdk/providers/cboe/poetry.lock b/openbb_sdk/providers/cboe/poetry.lock index bbdeb006281..c492fe2bfcd 100644 --- a/openbb_sdk/providers/cboe/poetry.lock +++ b/openbb_sdk/providers/cboe/poetry.lock @@ -541,37 +541,14 @@ files = [ ] [[package]] -name = "pandas" -version = "2.0.3" -description = "Powerful data structures for data analysis, time series, and statistics" +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." optional = false -python-versions = ">=3.8" +python-versions = ">=3.7" files = [ - {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, - {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, - {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, - {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, - {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, - {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, - {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, - {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, - {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, - {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, - {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, - {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, - {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, - {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, - {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, - {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, - {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, - {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, - {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, - {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, - {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, - {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, - {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, - {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, - {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, ] [package.dependencies] @@ -965,14 +942,14 @@ files = [ ] [[package]] -name = "tzdata" -version = "2023.3" -description = "Provider of IANA time zone data" +name = "url-normalize" +version = "1.4.3" +description = "URL normalization for Python" optional = false -python-versions = ">=2" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" files = [ - {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, - {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, + {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, + {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, ] [[package]] diff --git a/openbb_sdk/providers/fmp/openbb_fmp/__init__.py b/openbb_sdk/providers/fmp/openbb_fmp/__init__.py index 8329e778b87..deab8f902b4 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/__init__.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/__init__.py @@ -8,13 +8,13 @@ from openbb_fmp.models.balance_sheet_growth import FMPBalanceSheetGrowthFetcher from openbb_fmp.models.cash_flow import FMPCashFlowStatementFetcher from openbb_fmp.models.cash_flow_growth import FMPCashFlowStatementGrowthFetcher from openbb_fmp.models.company_overview import FMPCompanyOverviewFetcher -from openbb_fmp.models.crypto_eod import FMPCryptoEODFetcher +from openbb_fmp.models.crypto_historical import FMPCryptoHistoricalFetcher from openbb_fmp.models.dividend_calendar import FMPDividendCalendarFetcher from openbb_fmp.models.earnings_calendar import FMPEarningsCalendarFetcher from openbb_fmp.models.earnings_call_transcript import FMPEarningsCallTranscriptFetcher from openbb_fmp.models.executive_compensation import FMPExecutiveCompensationFetcher from openbb_fmp.models.financial_ratios import FMPFinancialRatiosFetcher -from openbb_fmp.models.forex_eod import FMPForexEODFetcher +from openbb_fmp.models.forex_historical import FMPForexHistoricalFetcher from openbb_fmp.models.forex_pairs import FMPForexPairsFetcher from openbb_fmp.models.global_news import FMPGlobalNewsFetcher from openbb_fmp.models.historical_dividends import FMPHistoricalDividendsFetcher @@ -28,7 +28,7 @@ from openbb_fmp.models.key_metrics import FMPKeyMetricsFetcher from openbb_fmp.models.major_indices_constituents import ( FMPMajorIndicesConstituentsFetcher, ) -from openbb_fmp.models.major_indices_eod import FMPMajorIndicesEODFetcher +from openbb_fmp.models.major_indices_historical import FMPMajorIndicesHistoricalFetcher from openbb_fmp.models.price_target import FMPPriceTargetFetcher from openbb_fmp.models.price_target_consensus import FMPPriceTargetConsensusFetcher from openbb_fmp.models.revenue_business_line import FMPRevenueBusinessLineFetcher @@ -36,7 +36,7 @@ from openbb_fmp.models.revenue_geographic import FMPRevenueGeographicFetcher from openbb_fmp.models.risk_premium import FMPRiskPremiumFetcher from openbb_fmp.models.sec_filings import FMPSECFilingsFetcher from openbb_fmp.models.share_statistics import FMPShareStatisticsFetcher -from openbb_fmp.models.stock_eod import FMPStockEODFetcher +from openbb_fmp.models.stock_historical import FMPStockHistoricalFetcher from openbb_fmp.models.stock_insider_trading import FMPStockInsiderTradingFetcher from openbb_fmp.models.stock_multiples import FMPStockMultiplesFetcher from openbb_fmp.models.stock_news import FMPStockNewsFetcher @@ -54,7 +54,7 @@ fmp_provider = Provider( required_credentials=["api_key"], fetcher_dict={ "KeyExecutives": FMPKeyExecutivesFetcher, - "StockEOD": FMPStockEODFetcher, + "StockHistorical": FMPStockHistoricalFetcher, "GlobalNews": FMPGlobalNewsFetcher, "StockNews": FMPStockNewsFetcher, "IncomeStatement": FMPIncomeStatementFetcher, @@ -64,7 +64,7 @@ fmp_provider = Provider( "CashFlowStatement": FMPCashFlowStatementFetcher, "CashFlowStatementGrowth": FMPCashFlowStatementGrowthFetcher, "ShareStatistics": FMPShareStatisticsFetcher, - "MajorIndicesEOD": FMPMajorIndicesEODFetcher, + "MajorIndicesHistorical": FMPMajorIndicesHistoricalFetcher, "RevenueGeographic": FMPRevenueGeographicFetcher, "RevenueBusinessLine": FMPRevenueBusinessLineFetcher, "InstitutionalOwnership": FMPInstitutionalOwnershipFetcher, @@ -83,8 +83,8 @@ fmp_provider = Provider( "SECFilings": FMPSECFilingsFetcher, "TreasuryRates": FMPTreasuryRatesFetcher, "ExecutiveCompensation": FMPExecutiveCompensationFetcher, - "CryptoEOD": FMPCryptoEODFetcher, - "ForexEOD": FMPForexEODFetcher, + "CryptoHistorical": FMPCryptoHistoricalFetcher, + "ForexHistorical": FMPForexHistoricalFetcher, "ForexPairs": FMPForexPairsFetcher, "StockPeers": FMPStockPeersFetcher, "StockMultiples": FMPStockMultiplesFetcher, diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/available_indices.py b/openbb_sdk/providers/fmp/openbb_fmp/models/available_indices.py index 340559b8d66..b8cc90e9afd 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/models/available_indices.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/available_indices.py @@ -8,6 +8,7 @@ from openbb_provider.standard_models.available_indices import ( AvailableIndicesData, AvailableIndicesQueryParams, ) +from pydantic import Field from openbb_fmp.utils.helpers import get_data_many @@ -22,6 +23,22 @@ class FMPAvailableIndicesQueryParams(AvailableIndicesQueryParams): class FMPAvailableIndicesData(AvailableIndicesData): """FMP Available Indices Data.""" + class Config: + """Pydantic alias config using fields Dict.""" + + fields = { + "stock_exchange": "stockExchange", + "exchange_short_name": "exchangeShortName", + } + + stock_exchange: str = Field( + description="Stock exchange where the index is listed.", alias="stockExchange" + ) + exchange_short_name: str = Field( + description="Short name of the stock exchange where the index is listed.", + alias="exchangeShortName", + ) + class FMPAvailableIndicesFetcher( Fetcher[ diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/balance_sheet.py b/openbb_sdk/providers/fmp/openbb_fmp/models/balance_sheet.py index 4b615c7bedb..5ca1409a3cc 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/models/balance_sheet.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/balance_sheet.py @@ -1,6 +1,10 @@ """FMP Balance Sheet Fetcher.""" +from datetime import ( + date as dateType, + datetime, +) from typing import Any, Dict, List, Optional from openbb_provider.abstract.fetcher import Fetcher @@ -8,7 +12,7 @@ from openbb_provider.standard_models.balance_sheet import ( BalanceSheetData, BalanceSheetQueryParams, ) -from pydantic import root_validator +from pydantic import Field, validator from openbb_fmp.utils.helpers import create_url, get_data_many @@ -19,14 +23,7 @@ class FMPBalanceSheetQueryParams(BalanceSheetQueryParams): Source: https://financialmodelingprep.com/developer/docs/#Balance-Sheet """ - cik: Optional[str] - - @root_validator() - def check_symbol_or_cik(cls, values): # pylint: disable=no-self-argument - """Check if symbol or cik is provided.""" - if values.get("symbol") is None and values.get("cik") is None: - raise ValueError("symbol or cik must be provided") - return values + symbol: str = Field(description="Symbol/CIK of the company.") class FMPBalanceSheetData(BalanceSheetData): @@ -36,31 +33,43 @@ class FMPBalanceSheetData(BalanceSheetData): """Pydantic alias config using fields Dict.""" fields = { - "currency": "reportedCurrency", - "current_assets": "totalCurrentAssets", - "noncurrent_assets": "totalNonCurrentAssets", - "assets": "totalAssets", - "current_liabilities": "totalCurrentLiabilities", - "noncurrent_liabilities": "totalNonCurrentLiabilities", - "liabilities": "totalLiabilities", - "other_stockholder_equity": "othertotalStockholdersEquity", + "marketable_securities": "longTermInvestments", + "other_shareholder_equity": "othertotalStockholdersEquity", + "total_shareholder_equity": "totalStockholdersEquity", + "total_liabilities_and_shareholders_equity": "totalLiabilitiesAndStockholdersEquity", } - # Leftovers below - calendarYear: Optional[int] - link: Optional[str] - finalLink: Optional[str] + reported_currency: str = Field(description="Reported currency in the statement.") - cashAndShortTermInvestments: Optional[int] - goodwillAndIntangibleAssets: Optional[int] - deferredRevenueNonCurrent: Optional[int] - totalInvestments: Optional[int] + filling_date: dateType = Field(description="Filling date.") + accepted_date: datetime = Field(description="Accepted date.") + calendar_year: int = Field(description="Calendar year.") - capitalLeaseObligations: Optional[int] - deferredTaxLiabilitiesNonCurrent: Optional[int] - totalNonCurrentLiabilities: Optional[int] - totalDebt: Optional[int] - netDebt: Optional[int] + cash_and_short_term_investments: Optional[int] = Field( + description="Cash and short term investments" + ) + goodwill_and_intangible_assets: Optional[int] = Field( + description="Goodwill and Intangible Assets" + ) + capital_lease_obligations: Optional[int] = Field( + description="Capital lease obligations" + ) + total_investments: Optional[int] = Field(description="Total investments") + total_debt: Optional[int] = Field(description="Total debt") + net_debt: Optional[int] = Field(description="Net debt") + + link: str = Field(description="Link to the statement.") + final_link: str = Field(description="Link to the final statement.") + + @validator("filing_date", pre=True, check_fields=False) + def filing_date_validate(cls, v): # pylint: disable=no-self-argument + """Validate the filing date.""" + return datetime.strptime(v, "%Y-%m-%d").date() + + @validator("accepted_date", pre=True, check_fields=False) + def accepted_date_validate(cls, v): # pylint: disable=no-self-argument + """Validate the accepted date.""" + return datetime.strptime(v, "%Y-%m-%d %H:%M:%S") class FMPBalanceSheetFetcher( diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/cash_flow.py b/openbb_sdk/providers/fmp/openbb_fmp/models/cash_flow.py index d70bfdde0f4..8b309aeb91f 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/models/cash_flow.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/cash_flow.py @@ -1,14 +1,18 @@ """FMP Cash Flow Statement Fetcher.""" +from datetime import ( + date as dateType, + datetime, +) from typing import Any, Dict, List, Optional from openbb_provider.abstract.fetcher import Fetcher -from openbb_provider.standard_models.cash_flows import ( +from openbb_provider.standard_models.cash_flow import ( CashFlowStatementData, CashFlowStatementQueryParams, ) -from pydantic import Field, root_validator +from pydantic import Field, validator from openbb_fmp.utils.helpers import create_url, get_data_many @@ -19,14 +23,7 @@ class FMPCashFlowStatementQueryParams(CashFlowStatementQueryParams): Source: https://financialmodelingprep.com/developer/docs/#Cash-Flow-Statement """ - cik: Optional[str] = Field(description="Central Index Key (CIK) of the company.") - - @root_validator() - def check_symbol_or_cik(cls, values): # pylint: disable=no-self-argument - """Validate that either a symbol or CIK is provided.""" - if values.get("symbol") is None and values.get("cik") is None: - raise ValueError("symbol or cik must be provided") - return values + symbol: str = Field(description="Symbol/CIK of the company.") class FMPCashFlowStatementData(CashFlowStatementData): @@ -36,20 +33,52 @@ class FMPCashFlowStatementData(CashFlowStatementData): """Pydantic alias config using fields dict.""" fields = { - "currency": "reportedCurrency", "net_cash_flow_from_operating_activities": "netCashProvidedByOperatingActivities", + "purchases_of_marketable_securities": "purchasesOfInvestments", + "sales_from_maturities_of_investments": "salesMaturitiesOfInvestments", + "payments_from_acquisitions": "acquisitionsNet", "other_investing_activities": "otherInvestingActivites", - "net_cash_used_for_investing_activities": "netCashUsedForInvestingActivites", + "net_cash_flow_from_investing_activities": "netCashUsedForInvestingActivites", "other_financing_activities": "otherFinancingActivites", "net_cash_flow_from_financing_activities": "netCashUsedProvidedByFinancingActivities", } - # Leftovers below - calendar_year: Optional[int] = Field( - description="Calendar Year", alias="calendarYear" + reported_currency: str = Field(description="Reported currency in the statement.") + filling_date: dateType = Field(description="Filling date.") + accepted_date: datetime = Field(description="Accepted date.") + calendar_year: int = Field(description="Calendar year.") + + change_in_working_capital: Optional[int] = Field( + description="Change in working capital." ) - link: Optional[str] - final_link: Optional[str] = Field(description="Final Link", alias="finalLink") + other_working_capital: Optional[int] = Field(description="Other working capital.") + common_stock_issued: Optional[int] = Field(description="Common stock issued.") + effect_of_forex_changes_on_cash: Optional[int] = Field( + description="Effect of forex changes on cash." + ) + + cash_at_beginning_of_period: Optional[int] = Field( + description="Cash at beginning of period." + ) + cash_at_end_of_period: Optional[int] = Field( + description="Cash, cash equivalents, and restricted cash at end of period" + ) + operating_cash_flow: Optional[int] = Field(description="Operating cash flow.") + capital_expenditure: Optional[int] = Field(description="Capital expenditure.") + free_cash_flow: Optional[int] = Field(description="Free cash flow.") + + link: str = Field(description="Link to the statement.") + final_link: str = Field(description="Link to the final statement.") + + @validator("filing_date", pre=True, check_fields=False) + def filing_date_validate(cls, v): # pylint: disable=no-self-argument + """Validate the filing date.""" + return datetime.strptime(v, "%Y-%m-%d").date() + + @validator("accepted_date", pre=True, check_fields=False) + def accepted_date_validate(cls, v): # pylint: disable=no-self-argument + """Validate the accepted date.""" + return datetime.strptime(v, "%Y-%m-%d %H:%M:%S") class FMPCashFlowStatementFetcher( diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/crypto_historical.py b/openbb_sdk/providers/fmp/openbb_fmp/models/crypto_historical.py new file mode 100644 index 00000000000..9662c743e75 --- /dev/null +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/crypto_historical.py @@ -0,0 +1,100 @@ +"""FMP Cryptos end of day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.crypto_historical import ( + CryptoHistoricalData, + CryptoHistoricalQueryParams, +) +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, NonNegativeInt, validator + +from openbb_fmp.utils.helpers import get_data_many + + +class FMPCryptoHistoricalQueryParams(CryptoHistoricalQueryParams): + # noqa: E501 + """FMP Crypto end of day Query. + + Source: + https://site.financialmodelingprep.com/developer/docs/cryptocurrency-historical-data-api/#Historical-Daily-Prices + """ + + timeseries: Optional[NonNegativeInt] = Field( + default=None, description="Number of days to look back." + ) + + +class FMPCryptoHistoricalData(CryptoHistoricalData): + """FMP Crypto end of day Data.""" + + adjClose: float = Field( + description="Adjusted Close Price of the symbol.", alias="adj_close" + ) + unadjustedVolume: float = Field( + description="Unadjusted volume of the symbol.", alias="unadjusted_volume" + ) + change: float = Field( + description="Change in the price of the symbol from the previous day.", + alias="change", + ) + changePercent: float = Field( + description=r"Change \% in the price of the symbol.", alias="change_percent" + ) + label: str = Field(description="Human readable format of the date.") + changeOverTime: float = Field( + description=r"Change \% in the price of the symbol over a period of time.", + alias="change_over_time", + ) + + @validator("date", pre=True) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return datetime.strptime(v, "%Y-%m-%d") + + +class FMPCryptoHistoricalFetcher( + Fetcher[ + FMPCryptoHistoricalQueryParams, + List[FMPCryptoHistoricalData], + ] +): + """Transform the query, extract and transform the data from the FMP endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> FMPCryptoHistoricalQueryParams: + """Transform the query params. Start and end dates are set to 1 year interval.""" + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return FMPCryptoHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: FMPCryptoHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the FMP endpoint.""" + api_key = credentials.get("fmp_api_key") if credentials else "" + + base_url = "https://financialmodelingprep.com/api/v3/" + query_str = get_querystring(query.dict(by_alias=True), ["symbol"]) + query_str = query_str.replace("start_date", "from").replace("end_date", "to") + url = f"{base_url}historical-price-full/crypto/{query.symbol}?{query_str}&apikey={api_key}" + + return get_data_many(url, "historical", **kwargs) + + @staticmethod + def transform_data(data: List[Dict]) -> List[FMPCryptoHistoricalData]: + """Return the transformed data.""" + return [FMPCryptoHistoricalData(**d) for d in data] diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/forex_historical.py b/openbb_sdk/providers/fmp/openbb_fmp/models/forex_historical.py new file mode 100644 index 00000000000..dc9224b944c --- /dev/null +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/forex_historical.py @@ -0,0 +1,94 @@ +"""FMP Forex end of day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.forex_historical import ( + ForexHistoricalData, + ForexHistoricalQueryParams, +) +from pydantic import Field, validator + +from openbb_fmp.utils.helpers import get_data_many, get_querystring + + +class FMPForexHistoricalQueryParams(ForexHistoricalQueryParams): + """FMP Forex end of day Query. + + Source: https://site.financialmodelingprep.com/developer/docs/#Historical-Forex-Price + """ + + +class FMPForexHistoricalData(ForexHistoricalData): + """FMP Forex end of day Data.""" + + adjClose: float = Field( + description="Adjusted Close Price of the symbol.", alias="adj_close" + ) + unadjustedVolume: float = Field( + description="Unadjusted volume of the symbol.", alias="unadjusted_volume" + ) + change: float = Field( + description="Change in the price of the symbol from the previous day.", + alias="change", + ) + changePercent: float = Field( + description=r"Change \% in the price of the symbol.", alias="change_percent" + ) + label: str = Field(description="Human readable format of the date.") + changeOverTime: float = Field( + description=r"Change \% in the price of the symbol over a period of time.", + alias="change_over_time", + ) + + @validator("date", pre=True) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return datetime.strptime(v, "%Y-%m-%d") + + +class FMPForexHistoricalFetcher( + Fetcher[ + FMPForexHistoricalQueryParams, + List[FMPForexHistoricalData], + ] +): + """Transform the query, extract and transform the data from the FMP endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> FMPForexHistoricalQueryParams: + """Transform the query params. Start and end dates are set to a 1 year interval.""" + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + + return FMPForexHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: FMPForexHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the FMP endpoint.""" + api_key = credentials.get("fmp_api_key") if credentials else "" + + base_url = "https://financialmodelingprep.com/api/v3" + query_str = get_querystring(query.dict(by_alias=True), ["symbol"]) + query_str = query_str.replace("start_date", "from").replace("end_date", "to") + url = f"{base_url}/historical-price-full/forex/{query.symbol}?{query_str}&apikey={api_key}" + + return get_data_many(url, "historical", **kwargs) + + @staticmethod + def transform_data(data: List[Dict]) -> List[FMPForexHistoricalData]: + """Return the transformed data.""" + return [FMPForexHistoricalData(**d) for d in data] diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/income_statement.py b/openbb_sdk/providers/fmp/openbb_fmp/models/income_statement.py index a3a5f600fa9..f6d7952bdb4 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/models/income_statement.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/income_statement.py @@ -1,6 +1,10 @@ """FMP Income Statement Fetcher.""" +from datetime import ( + date as dateType, + datetime, +) from typing import Any, Dict, List, Literal, Optional from openbb_provider.abstract.fetcher import Fetcher @@ -19,13 +23,9 @@ class FMPIncomeStatementQueryParams(IncomeStatementQueryParams): """FMP Income Statement QueryParams. Source: https://financialmodelingprep.com/developer/docs/#Income-Statement - - Either a Symbol or CIK is required. Symbol is preferred over CIK. """ - cik: Optional[str] = Field( - description="The CIK of the company if no symbol is provided." - ) + symbol: str = Field(description="Symbol/CIK of the company.") @root_validator() def check_symbol_or_cik(cls, values): # pylint: disable=no-self-argument @@ -42,13 +42,82 @@ class FMPIncomeStatementData(IncomeStatementData): """Pydantic alias config using fields dict.""" fields = { - "currency": "reportedCurrency", + "cost_of_revenue": "costOfRevenue", + "gross_profit": "grossProfit", + "gross_profit_ratio": "grossProfitRatio", + "research_and_development_expenses": "researchAndDevelopmentExpenses", + "general_and_administrative_expenses": "generalAndAdministrativeExpenses", + "selling_and_marketing_expenses": "sellingAndMarketingExpenses", + "selling_general_and_administrative_expenses": "sellingGeneralAndAdministrativeExpenses", + "other_expenses": "otherExpenses", + "operating_expenses": "operatingExpenses", + "depreciation_and_amortization": "depreciationAndAmortization", "ebitda_ratio": "ebitdaratio", + "operating_income": "operatingIncome", + "operating_income_ratio": "operatingIncomeRatio", + "interest_income": "interestIncome", + "interest_expense": "interestExpense", + "total_other_income_expenses_net": "totalOtherIncomeExpensesNet", + "income_before_tax": "incomeBeforeTax", + "income_before_tax_ratio": "incomeBeforeTaxRatio", + "income_tax_expense": "incomeTaxExpense", + "net_income": "netIncome", + "net_income_ratio": "netIncomeRatio", "eps_diluted": "epsdiluted", "weighted_average_shares_outstanding": "weightedAverageShsOut", "weighted_average_shares_outstanding_dil": "weightedAverageShsOutDil", } + reported_currency: Optional[str] = Field(description="Reporting currency.") + filing_date: Optional[dateType] = Field(description="Filling date.") + accepted_date: Optional[datetime] = Field(description="Accepted date.") + calendar_year: Optional[int] = Field(description="Calendar year.") + + cost_of_revenue: Optional[float] = Field(description="Cost of revenue.") + gross_profit: Optional[float] = Field(description="Gross profit.") + gross_profit_ratio: Optional[float] = Field(description="Gross profit ratio.") + research_and_development_expenses: Optional[float] = Field( + description="Research and development expenses." + ) + general_and_administrative_expenses: Optional[float] = Field( + description="General and administrative expenses." + ) + selling_and_marketing_expenses: Optional[float] = Field( + description="Selling and marketing expenses." + ) + selling_general_and_administrative_expenses: Optional[float] = Field( + description="Selling, general and administrative expenses." + ) + other_expenses: Optional[float] = Field(description="Other expenses.") + + operating_expenses: Optional[float] = Field(description="Operating expenses.") + depreciation_and_amortization: Optional[float] = Field( + description="Depreciation and amortization." + ) + ebitda_ratio: Optional[float] = Field(description="EBIDTA ratio.") + operating_income: Optional[float] = Field(description="Operating income.") + operating_income_ratio: Optional[float] = Field( + description="Operating income ratio." + ) + interest_income: Optional[float] = Field(description="Interest income.") + interest_expense: Optional[float] = Field(description="Interest expense.") + + total_other_income_expenses_net: Optional[float] = Field( + description="Total other income expenses net." + ) + income_before_tax: Optional[float] = Field(description="Income before tax.") + income_before_tax_ratio: Optional[float] = Field( + description="Income before tax ratio." + ) + income_tax_expense: Optional[float] = Field(description="Income tax expense.") + net_income: Optional[float] = Field(description="Net income.") + net_income_ratio: Optional[float] = Field(description="Net income ratio.") + + link: Optional[str] = Field(description="Link to the income statement.") + final_link: Optional[str] = Field( + description="Final link to the income statement." + ) + class FMPIncomeStatementFetcher( Fetcher[ diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/major_indices_historical.py b/openbb_sdk/providers/fmp/openbb_fmp/models/major_indices_historical.py new file mode 100644 index 00000000000..d367f166c8a --- /dev/null +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/major_indices_historical.py @@ -0,0 +1,108 @@ +"""FMP Major Indices end of day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.major_indices_historical import ( + MajorIndicesHistoricalData, + MajorIndicesHistoricalQueryParams, +) +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, NonNegativeInt, validator + +from openbb_fmp.utils.helpers import get_data_many + + +class FMPMajorIndicesHistoricalQueryParams(MajorIndicesHistoricalQueryParams): + """FMP Major Indices end of day Query. + + Source: https://site.financialmodelingprep.com/developer/docs/historical-index-price-api/ + """ + + timeseries: Optional[NonNegativeInt] = Field( + default=None, description="Number of days to look back." + ) + interval: Literal[ + "1min", "5min", "15min", "30min", "1hour", "4hour", "1day" + ] = Field(default="1day", description="Interval of the data to fetch.") + + +class FMPMajorIndicesHistoricalData(MajorIndicesHistoricalData): + """FMP Major Indices end of day Data.""" + + adj_close: Optional[float] = Field( + description="Adjusted Close Price of the symbol.", + default=None, + ) + unadjusted_volume: Optional[float] = Field( + description="Unadjusted volume of the symbol.", + default=None, + ) + change: Optional[float] = Field( + description="Change in the price of the symbol from the previous day.", + default=None, + ) + change_percent: Optional[float] = Field( + description=r"Change \% in the price of the symbol.", + default=None, + ) + label: Optional[str] = Field( + description="Human readable format of the date.", default=None + ) + change_over_time: Optional[float] = Field( + description=r"Change \% in the price of the symbol over a period of time.", + default=None, + ) + + @validator("date", pre=True) + def date_validate(cls, v) -> datetime: # pylint: disable=E0213 + """Return the date as a datetime object.""" + # TODO: Check if this condition is necessary + # if values.get("changeOverTime", None) is not None: + # return datetime.strptime(v, "%Y-%m-%d") + return datetime.strptime(v, "%Y-%m-%d") + + +class FMPMajorIndicesHistoricalFetcher( + Fetcher[ + FMPMajorIndicesHistoricalQueryParams, + List[FMPMajorIndicesHistoricalData], + ] +): + """Transform the query, extract and transform the data from the FMP endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> FMPMajorIndicesHistoricalQueryParams: + """Transform the query params.""" + return FMPMajorIndicesHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: FMPMajorIndicesHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the FMP endpoint.""" + api_key = credentials.get("fmp_api_key") if credentials else "" + + base_url = "https://financialmodelingprep.com/api/v3" + query_str = ( + get_querystring(query.dict(), ["symbol"]) + .replace("start_date", "from") + .replace("end_date", "to") + ) + + url_params = f"{query.symbol}?{query_str}&apikey={api_key}" + url = f"{base_url}/historical-chart/{query.interval}/%5E{url_params}" + + if query.interval == "1day": + url = f"{base_url}/historical-price-full/index/%5E{url_params}" + + return get_data_many(url, "historical", **kwargs) + + @staticmethod + def transform_data(data: List[Dict]) -> List[FMPMajorIndicesHistoricalData]: + """Return the transformed data.""" + return [FMPMajorIndicesHistoricalData(**d) for d in data] diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/stock_historical.py b/openbb_sdk/providers/fmp/openbb_fmp/models/stock_historical.py new file mode 100644 index 00000000000..0191c0c2c23 --- /dev/null +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/stock_historical.py @@ -0,0 +1,111 @@ +"""FMP Stocks end of day fetcher.""" + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_historical import ( + StockHistoricalData, + StockHistoricalQueryParams, +) +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, NonNegativeInt, validator + +from openbb_fmp.utils.helpers import get_data_many + + +class FMPStockHistoricalQueryParams(StockHistoricalQueryParams): + """FMP Stock end of day Query. + + Source: https://financialmodelingprep.com/developer/docs/#Stock-Historical-Price + """ + + timeseries: Optional[NonNegativeInt] = Field( + default=None, description="Number of days to look back." + ) + interval: Literal[ + "1min", "5min", "15min", "30min", "1hour", "4hour", "1day" + ] = Field(default="1day", description="Interval of the data to fetch.") + + +class FMPStockHistoricalData(StockHistoricalData): + """FMP Stock end of day Data.""" + + adjClose: Optional[float] = Field(description="Adjusted Close Price of the symbol.") + unadjustedVolume: Optional[float] = Field( + description="Unadjusted volume of the symbol." + ) + change: Optional[float] = Field( + description="Change in the price of the symbol from the previous day." + ) + changePercent: Optional[float] = Field( + description=r"Change \% in the price of the symbol." + ) + vwap: Optional[float] = Field( + description="Volume Weighted Average Price of the symbol." + ) + label: Optional[str] = Field(description="Human readable format of the date.") + changeOverTime: Optional[float] = Field( + description=r"Change \% in the price of the symbol over a period of time." + ) + + @validator("date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + try: + return datetime.strptime(v, "%Y-%m-%d %H:%M:%S") + except ValueError: + return datetime.strptime(v, "%Y-%m-%d") + + +class FMPStockHistoricalFetcher( + Fetcher[ + FMPStockHistoricalQueryParams, + List[FMPStockHistoricalData], + ] +): + """Transform the query, extract and transform the data from the FMP endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> FMPStockHistoricalQueryParams: + """Transform the query params.""" + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + + return FMPStockHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: FMPStockHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the FMP endpoint.""" + api_key = credentials.get("fmp_api_key") if credentials else "" + + base_url = "https://financialmodelingprep.com/api/v3" + query_str = ( + get_querystring(query.dict(), ["symbol"]) + .replace("start_date", "from") + .replace("end_date", "to") + ) + + url_params = f"{query.symbol}?{query_str}&apikey={api_key}" + url = f"{base_url}/historical-chart/{query.interval}/{url_params}" + + if query.interval == "1day": + url = f"{base_url}/historical-price-full/{url_params}" + + return get_data_many(url, "historical", **kwargs) + + @staticmethod + def transform_data(data: List[Dict]) -> List[FMPStockHistoricalData]: + """Return the transformed data.""" + return [FMPStockHistoricalData(**d) for d in data] diff --git a/openbb_sdk/providers/fmp/openbb_fmp/models/stock_quote.py b/openbb_sdk/providers/fmp/openbb_fmp/models/stock_quote.py index ef2b2d61a27..7f51022c646 100644 --- a/openbb_sdk/providers/fmp/openbb_fmp/models/stock_quote.py +++ b/openbb_sdk/providers/fmp/openbb_fmp/models/stock_quote.py @@ -9,7 +9,7 @@ from openbb_provider.standard_models.stock_quote import ( StockQuoteData, StockQuoteQueryParams, ) -from pydantic import validator +from pydantic import Field, validator from openbb_fmp.utils.helpers import get_data_many, get_querystring @@ -31,6 +31,50 @@ class FMPStockQuoteData(StockQuoteData): "date": "timestamp", } + symbol: Optional[str] = Field(description="Symbol of the company.") + name: Optional[str] = Field(description="Name of the company.") + price: Optional[float] = Field(description="Current trading price of the stock.") + changes_percentage: Optional[float] = Field( + description="Change percentage of the stock price." + ) + change: Optional[float] = Field(description="Change in the stock price.") + year_high: Optional[float] = Field( + description="Highest price of the stock in the last 52 weeks." + ) + year_low: Optional[float] = Field( + description="Lowest price of the stock in the last 52 weeks." + ) + market_cap: Optional[float] = Field(description="Market cap of the company.") + price_avg50: Optional[float] = Field( + description="50 days average price of the stock." + ) + price_avg200: Optional[float] = Field( + description="200 days average price of the stock." + ) + volume: Optional[int] = Field( + description="Volume of the stock in the current trading day." + ) + avg_volume: Optional[int] = Field( + default=None, + description="Average volume of the stock in the last 10 trading days.", + ) + exchange: Optional[str] = Field(description="Exchange the stock is traded on.") + open: Optional[float] = Field( + default=None, + description="Opening price of the stock in the current trading day.", + ) + previous_close: Optional[float] = Field( + description="Previous closing price of the stock." + ) + eps: Optional[float] = Field(description="Earnings per share of the stock.") + pe: Optional[float] = Field(description="Price earnings ratio of the stock.") + earnings_announcement: Optional[str] = Field( + description="Earnings announcement date of the stock." + ) + shares_outstanding: Optional[int] = Field( + description="Number of shares outstanding of the stock." + ) + @validator("timestamp", pre=True, check_fields=False) def date_validate(cls, v): # pylint: disable=E0213 """Return the date as a datetime object.""" diff --git a/openbb_sdk/providers/intrinio/README.md b/openbb_sdk/providers/intrinio/README.md new file mode 100644 index 00000000000..365004a7108 --- /dev/null +++ b/openbb_sdk/providers/intrinio/README.md @@ -0,0 +1,11 @@ +# OpenBB Intrinio Provider + +This extension integrates the Intrinio data provider into the OpenBB SDK. + +## Installation + +To install the extension, run the following command in this folder: + +```bash +pip install . +``` diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/__init__.py b/openbb_sdk/providers/intrinio/openbb_intrinio/__init__.py new file mode 100644 index 00000000000..46665ba868f --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/__init__.py @@ -0,0 +1,33 @@ +"""intrinio provider module.""" + + +from openbb_provider.abstract.provider import Provider + +from openbb_intrinio.models.balance_sheet import IntrinioBalanceSheetFetcher +from openbb_intrinio.models.cash_flow import IntrinioCashFlowStatementFetcher +from openbb_intrinio.models.forex_pairs import IntrinioForexPairsFetcher +from openbb_intrinio.models.global_news import IntrinioGlobalNewsFetcher +from openbb_intrinio.models.income_statement import IntrinioIncomeStatementFetcher +from openbb_intrinio.models.options_chains import IntrinioOptionsChainsFetcher +from openbb_intrinio.models.stock_historical import IntrinioStockHistoricalFetcher +from openbb_intrinio.models.stock_news import IntrinioStockNewsFetcher +from openbb_intrinio.models.stock_quote import IntrinioStockQuoteFetcher + +intrinio_provider = Provider( + name="intrinio", + website="https://intrinio.com/", + description="""Intrinio is a financial data platform that provides real-time and + historical financial market data to businesses and developers through an API.""", + required_credentials=["api_key"], + fetcher_dict={ + "StockHistorical": IntrinioStockHistoricalFetcher, + "ForexPairs": IntrinioForexPairsFetcher, + "StockNews": IntrinioStockNewsFetcher, + "GlobalNews": IntrinioGlobalNewsFetcher, + "StockQuote": IntrinioStockQuoteFetcher, + "OptionsChains": IntrinioOptionsChainsFetcher, + "BalanceSheet": IntrinioBalanceSheetFetcher, + "CashFlowStatement": IntrinioCashFlowStatementFetcher, + "IncomeStatement": IntrinioIncomeStatementFetcher, + }, +) diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/__init__.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/__init__.py new file mode 100644 index 00000000000..57cf91e5d44 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/__init__.py @@ -0,0 +1 @@ +"""yfinance models directory.""" diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/balance_sheet.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/balance_sheet.py new file mode 100644 index 00000000000..e25582d2f0a --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/balance_sheet.py @@ -0,0 +1,127 @@ +"""Intrinio Balance Sheet Fetcher.""" + + +from datetime import date +from typing import Any, Dict, List, Literal, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.balance_sheet import ( + BalanceSheetData, + BalanceSheetQueryParams, +) +from pydantic import Field + +from openbb_intrinio.utils.helpers import get_data_one + + +class IntrinioBalanceSheetQueryParams(BalanceSheetQueryParams): + """Intrinio Balance Sheet QueryParams. + + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_reported_financials_v2 + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 + """ + + type: Literal["reported", "standardized"] = Field( + default="reported", description="Type of the statement to be fetched." + ) + year: Optional[int] = Field( + description="Year of the statement to be fetched.", + ) + + +class IntrinioBalanceSheetData(BalanceSheetData): + """Intrinio Balance Sheet Data.""" + + class Config: + fields = { + "cash_and_cash_equivalents": "cash_and_equivalents", + "marketable_securities": "short_term_investments", + "net_receivables": "note_and_lease_receivable", + "inventory": "inventory_net", + "total_non_current_assets": "total_noncurrent_assets", + "tax_payables": "other_taxes_payables", + "deferred_revenue": "current_deferred_revenue", + "deferred_revenue_non_current": "noncurrent_deferred_revenue", + "deferred_tax_liabilities_non_current": "noncurrent_deferred_and_payable_income_tax_liabilities", + "other_liabilities": "other_long_term_liabilities", + "accumulated_other_comprehensive_income_loss": "accumulated_other_comprehensive_income_loss", + } + + +class IntrinioBalanceSheetFetcher( + Fetcher[ + IntrinioBalanceSheetQueryParams, + List[IntrinioBalanceSheetData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioBalanceSheetQueryParams: + """Transform the query params.""" + transform_params = params + + if not params.get("year"): + transform_params["year"] = date.today().year - 1 + + return IntrinioBalanceSheetQueryParams(**transform_params) + + @staticmethod + def extract_data( + query: IntrinioBalanceSheetQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + url_params = f"{query.symbol}-balance_sheet_statement-{query.year}" + statement_param = f"{query.type}_financials" + + data = [] + + if query.period == "annual": + url = f"{base_url}/fundamentals/{url_params}-FY/{statement_param}?api_key={api_key}" + data.append(get_data_one(url, **kwargs)) + + elif query.period == "quarter": + # TODO: Fix quarter range after Intrinio's response + for quarter in range(1, 4): + url = f"{base_url}/fundamentals/{url_params}-Q{quarter}/{statement_param}?api_key={api_key}" + data.append(get_data_one(url, **kwargs)) + + return data + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioBalanceSheetData]: + """Return the transformed data.""" + + transformed_data = [] + + for item in data: + sub_dict = {} + + if "reported_financials" in item: + key = "reported_financials" + sub_tag = "xbrl_tag" + elif "standardized_financials" in item: + key = "standardized_financials" + sub_tag = "data_tag" + + for sub_item in item[key]: + try: + sub_dict[sub_item[sub_tag]["name"]] = int( + sub_item[sub_tag]["factor"] + str(sub_item["value"]) + ) + except (ValueError, KeyError): + sub_dict[sub_item[sub_tag]["name"]] = int(sub_item["value"]) + + sub_dict["date"] = item["fundamental"]["end_date"] + sub_dict["period"] = item["fundamental"]["fiscal_period"] + sub_dict["cik"] = item["fundamental"]["company"]["cik"] + sub_dict["symbol"] = item["fundamental"]["company"]["ticker"] + + transformed_data.append(IntrinioBalanceSheetData(**sub_dict)) + + return transformed_data diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/cash_flow.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/cash_flow.py new file mode 100644 index 00000000000..9f3c4ee4b4f --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/cash_flow.py @@ -0,0 +1,143 @@ +"""Intrinio Cash Flow Statement Fetcher.""" + + +from datetime import date +from typing import Any, Dict, List, Literal, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.cash_flow import ( + CashFlowStatementData, + CashFlowStatementQueryParams, +) +from pydantic import Field + +from openbb_intrinio.utils.helpers import get_data_one + + +class IntrinioCashFlowStatementQueryParams(CashFlowStatementQueryParams): + """Intrinio Cash Flow Statement QueryParams. + + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_reported_financials_v2 + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 + """ + + type: Literal["reported", "standardized"] = Field( + default="reported", description="Type of the statement to be fetched." + ) + year: Optional[int] = Field( + description="Year of the statement to be fetched.", + ) + + +class IntrinioCashFlowStatementData(CashFlowStatementData): + """Intrinio Cash Flow Statement Data.""" + + class Config: + fields = { + "net_income": "NetIncomeLoss", + "depreciation_and_amortization": "DepreciationDepletionAndAmortization", + "stock_based_compensation": "ShareBasedCompensation", + "deferred_income_tax": "DeferredIncomeTaxExpenseBenefit", + "other_non_cash_items": "OtherNoncashIncomeExpense", + "accounts_receivables": "IncreaseDecreaseInAccountsReceivable", + "inventory": "IncreaseDecreaseInInventories", + "vendor_non_trade_receivables": "IncreaseDecreaseInOtherReceivables", + "other_current_and_non_current_assets": "IncreaseDecreaseInOtherOperatingAssets", + "accounts_payables": "IncreaseDecreaseInAccountsPayable", + "deferred_revenue": "IncreaseDecreaseInContractWithCustomerLiability", + "other_current_and_non_current_liabilities": "IncreaseDecreaseInOtherOperatingLiabilities", + "net_cash_flow_from_operating_activities": "NetCashProvidedByUsedInOperatingActivities", + "purchases_of_marketable_securities": "PaymentsToAcquireAvailableForSaleSecuritiesDebt", + "sales_from_maturities_of_investments": "ProceedsFromSaleOfAvailableForSaleSecuritiesDebt", + "investments_in_property_plant_and_equipment": "ProceedsFromMaturitiesPrepaymentsAndCallsOfAvailableForSaleSecurities", # noqa: E501 + "payments_from_acquisitions": "PaymentsToAcquireBusinessesNetOfCashAcquired", + "other_investing_activities": "PaymentsForProceedsFromOtherInvestingActivities", + "net_cash_flow_from_investing_activities": "NetCashProvidedByUsedInInvestingActivities", + "taxes_paid_on_net_share_settlement": "PaymentsRelatedToTaxWithholdingForShareBasedCompensation", + "dividends_paid": "PaymentsOfDividends", + "common_stock_repurchased": "PaymentsForRepurchaseOfCommonStock", + "debt_proceeds": "ProceedsFromIssuanceOfLongTermDebt", + "debt_repayment": "RepaymentsOfLongTermDebt", + "other_financing_activities": "ProceedsFromPaymentsForOtherFinancingActivities", + "net_cash_flow_from_financing_activities": "NetCashProvidedByUsedInFinancingActivities", + "net_change_in_cash": "CashCashEquivalentsRestrictedCashAndRestrictedCashEquivalentsPeriodIncreaseDecreaseIncludingExchangeRateEffect", # noqa: E501 + } + + +class IntrinioCashFlowStatementFetcher( + Fetcher[ + IntrinioCashFlowStatementQueryParams, + List[IntrinioCashFlowStatementData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioCashFlowStatementQueryParams: + """Transform the query params.""" + transform_params = params + + if not params.get("year"): + transform_params["year"] = date.today().year - 1 + + return IntrinioCashFlowStatementQueryParams(**transform_params) + + @staticmethod + def extract_data( + query: IntrinioCashFlowStatementQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + url_params = f"{query.symbol}-cash_flow_statement-{query.year}" + statement_param = f"{query.type}_financials" + + data = [] + + if query.period == "annual": + url = f"{base_url}/fundamentals/{url_params}-FY/{statement_param}?api_key={api_key}" + data.append(get_data_one(url, **kwargs)) + + elif query.period == "quarter": + # TODO: Fix quarter range after Intrinio's response + for quarter in range(1, 4): + url = f"{base_url}/fundamentals/{url_params}-Q{quarter}/{statement_param}?api_key={api_key}" + data.append(get_data_one(url, **kwargs)) + + return data + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioCashFlowStatementData]: + """Return the transformed data.""" + + transformed_data = [] + + for item in data: + sub_dict = {} + + if "reported_financials" in item: + key = "reported_financials" + sub_tag = "xbrl_tag" + elif "standardized_financials" in item: + key = "standardized_financials" + sub_tag = "data_tag" + + for sub_item in item[key]: + try: + sub_dict[sub_item[sub_tag]["tag"]] = int( + sub_item[sub_tag]["factor"] + str(sub_item["value"]) + ) + except (ValueError, KeyError): + sub_dict[sub_item[sub_tag]["tag"]] = int(sub_item["value"]) + + sub_dict["date"] = item["fundamental"]["end_date"] + sub_dict["period"] = item["fundamental"]["fiscal_period"] + sub_dict["cik"] = item["fundamental"]["company"]["cik"] + sub_dict["symbol"] = item["fundamental"]["company"]["ticker"] + + transformed_data.append(IntrinioCashFlowStatementData(**sub_dict)) + + return transformed_data diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/forex_pairs.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/forex_pairs.py new file mode 100644 index 00000000000..f73bc337f96 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/forex_pairs.py @@ -0,0 +1,73 @@ +"""Intrinio Forex available pairs fetcher.""" + + +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.forex_pairs import ( + ForexPairsData, + ForexPairsQueryParams, +) +from pydantic import Field + +from openbb_intrinio.utils.helpers import get_data_many + + +class IntrinioForexPairsQueryParams(ForexPairsQueryParams): + """Intrinio Forex available pairs Query. + + Source: https://docs.intrinio.com/documentation/web_api/get_forex_pairs_v2 + """ + + +class IntrinioForexPairsData(ForexPairsData): + """Intrinio Forex available pairs Data.""" + + class Config: + fields = { + "name": "code", + } + + code: str = Field(description="Code of the currency pair.") + base_currency: str = Field( + description="ISO 4217 currency code of the base currency." + ) + quote_currency: str = Field( + description="ISO 4217 currency code of the quote currency." + ) + + +class IntrinioForexPairsFetcher( + Fetcher[ + IntrinioForexPairsQueryParams, + List[IntrinioForexPairsData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioForexPairsQueryParams: + """Transform the query params.""" + + return IntrinioForexPairsQueryParams(**params) + + @staticmethod + def extract_data( + query: IntrinioForexPairsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + url = f"{base_url}/forex/pairs?api_key={api_key}" + + return get_data_many(url, "pairs", **kwargs) + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioForexPairsData]: + """Return the transformed data.""" + + return [IntrinioForexPairsData(**d) for d in data] diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/global_news.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/global_news.py new file mode 100644 index 00000000000..913754fc2a6 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/global_news.py @@ -0,0 +1,117 @@ +"""Intrinio Global News fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.global_news import ( + GlobalNewsData, + GlobalNewsQueryParams, +) +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, validator + +from openbb_intrinio.utils.helpers import get_data_one + + +class IntrinioGlobalNewsQueryParams(GlobalNewsQueryParams): + """Intrinio Global News query. + + Source: https://docs.intrinio.com/documentation/web_api/get_all_company_news_v2 + """ + + next_page: str = Field( + default=None, + description="Token to get the next page of data from a previous API call.", + ) + limit: Optional[int] = Field( + default=10, description="The number of data entries to return." + ) + all_pages: Optional[bool] = Field( + default=False, + description="Returns all pages of data from the API call at once.", + ) + + +class IntrinioGlobalNewsData(GlobalNewsData): + """Intrinio Global News Data.""" + + class Config: + """Pydantic alias config using fields dict.""" + + fields = { + "date": "publication_date", + "text": "summary", + } + + id: str = Field(description="Intrinio ID for the news article.") + company: Dict[str, Any] = Field( + description="Company details related to the news article." + ) + + @validator("publication_date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.000Z") + + +class IntrinioGlobalNewsFetcher( + Fetcher[ + IntrinioGlobalNewsQueryParams, + List[IntrinioGlobalNewsData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioGlobalNewsQueryParams: + """Transform the query params.""" + + return IntrinioGlobalNewsQueryParams(**params) + + @staticmethod + def extract_data( + query: IntrinioGlobalNewsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + query_str = get_querystring(query.dict(by_alias=True), ["all_pages", "page"]) + query_str = query_str.replace("limit", "page_size") + url = f"{base_url}/companies/news?{query_str}&api_key={api_key}" + + data = get_data_one(url, **kwargs) + + if query.all_pages: + all_data = data["news"] + next_page = data["next_page"] + + while next_page: + query_str = get_querystring( + query.dict(by_alias=True), ["page", "next_page", "all_pages"] + ) + query_str = query_str.replace("limit", "page_size") + url = ( + f"{base_url}/companies/news?{query_str}&next_page={next_page}" + f"&api_key={api_key}" + ) + + data = get_data_one(url, **kwargs) + all_data.extend(data.get("news", [])) + + next_page = data.get("next_page", None) + + return all_data["news"] + + return data.get("news", []) + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioGlobalNewsData]: + """Return the transformed data.""" + + return [IntrinioGlobalNewsData(**d) for d in data] diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/income_statement.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/income_statement.py new file mode 100644 index 00000000000..cf9fca94413 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/income_statement.py @@ -0,0 +1,123 @@ +"""Intrinio Income Statement Fetcher.""" + + +from datetime import date +from typing import Any, Dict, List, Literal, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.income_statement import ( + IncomeStatementData, + IncomeStatementQueryParams, +) +from pydantic import Field + +from openbb_intrinio.utils.helpers import get_data_one + + +class IntrinioIncomeStatementQueryParams(IncomeStatementQueryParams): + """Intrinio Income Statement QueryParams. + + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_reported_financials_v2 + Source: https://docs.intrinio.com/documentation/web_api/get_fundamental_standardized_financials_v2 + """ + + type: Literal["reported", "standardized"] = Field( + default="reported", description="Type of the statement to be fetched." + ) + year: Optional[int] = Field( + description="Year of the statement to be fetched.", + ) + + +class IntrinioIncomeStatementData(IncomeStatementData): + """Intrinio Income Statement Data.""" + + class Config: + fields = { + "research_and_development_expenses": "ResearchAndDevelopmentExpense", + "selling_general_and_administrative_expenses": "SellingGeneralAndAdministrativeExpense", + "operating_income": "OperatingIncomeLoss", + "income_before_tax": "IncomeLossFromContinuingOperationsBeforeIncomeTaxesExtraordinaryItemsNoncontrollingInterest", # noqa: E501 + "eps_diluted": "EarningsPerShareDiluted", + "weighted_average_shares_outstanding": "WeightedAverageNumberOfSharesOutstandingBasic", + "weighted_average_shares_outstanding_dil": "WeightedAverageNumberOfDilutedSharesOutstanding", + } + + +class IntrinioIncomeStatementFetcher( + Fetcher[ + IntrinioIncomeStatementQueryParams, + List[IntrinioIncomeStatementData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioIncomeStatementQueryParams: + """Transform the query params.""" + transform_params = params + + if not params.get("year"): + transform_params["year"] = date.today().year - 1 + + return IntrinioIncomeStatementQueryParams(**transform_params) + + @staticmethod + def extract_data( + query: IntrinioIncomeStatementQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + url_params = f"{query.symbol}-balance_sheet_statement-{query.year}" + statement_param = f"{query.type}_financials" + + data = [] + + if query.period == "annual": + url = f"{base_url}/fundamentals/{url_params}-FY/{statement_param}?api_key={api_key}" + data.append(get_data_one(url, **kwargs)) + + elif query.period == "quarter": + # TODO: Fix quarter range after Intrinio's response + for quarter in range(1, 4): + url = f"{base_url}/fundamentals/{url_params}-Q{quarter}/{statement_param}?api_key={api_key}" + data.append(get_data_one(url, **kwargs)) + + return data + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioIncomeStatementData]: + """Return the transformed data.""" + + transformed_data = [] + + for item in data: + sub_dict = {} + + if "reported_financials" in item: + key = "reported_financials" + sub_tag = "xbrl_tag" + elif "standardized_financials" in item: + key = "standardized_financials" + sub_tag = "data_tag" + + for sub_item in item[key]: + try: + sub_dict[sub_item[sub_tag]["tag"]] = int( + sub_item[sub_tag]["factor"] + str(sub_item["value"]) + ) + except (ValueError, KeyError): + sub_dict[sub_item[sub_tag]["tag"]] = int(sub_item["value"]) + + sub_dict["date"] = item["fundamental"]["end_date"] + sub_dict["period"] = item["fundamental"]["fiscal_period"] + sub_dict["cik"] = item["fundamental"]["company"]["cik"] + sub_dict["symbol"] = item["fundamental"]["company"]["ticker"] + + transformed_data.append(IntrinioIncomeStatementData(**sub_dict)) + + return transformed_data diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/options_chains.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/options_chains.py new file mode 100644 index 00000000000..b0ed1b96dba --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/options_chains.py @@ -0,0 +1,328 @@ +"""Intrinio Options Chains fetcher.""" + +import concurrent.futures +from datetime import ( + date as dateType, + datetime, + timedelta, +) +from typing import Any, Dict, List, Optional, Union + +import pandas as pd +import requests_cache +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.options_chains import ( + OptionsChainsData, + OptionsChainsQueryParams, +) +from openbb_provider.utils.helpers import make_request +from pydantic import Field, validator + +TICKER_EXCEPTIONS = [ + "SPX", + "XSP", + "XEO", + "NDX", + "XND", + "VIX", + "RUT", + "MRUT", + "DJX", + "XAU", + "OEX", +] + +intrinio_session = requests_cache.CachedSession( + "OpenBB_Intrinio", expire_after=timedelta(days=5), use_cache_dir=True +) + + +def get_options_tickers(api_key: str) -> List[str]: + """Returns all tickers that have existing options contracts. + + Parameters + ---------- + api_key: str + Intrinio API key. + + Returns + ------- + List[str] + List of tickers + """ + + url = f"https://api-v2.intrinio.com/options/tickers?api_key={api_key}" + + r = intrinio_session.get(url, timeout=10) + + return r.json()["tickers"] + + +def get_options_expirations( + symbol: str, + api_key: str, + after: Optional[Union[datetime, str]] = datetime.now().strftime("%Y-%m-%d"), + before: Optional[str] = "", +) -> list: + """Returns a list of all current and upcoming option contract expiration dates for a particular symbol. + + Parameters + ---------- + symbol: str + The options symbol, corresponding to the underlying security. + api_key: str + Intrinio API key. + after: str + Return option contract expiration dates after this date. Format: YYYY-MM-DD + before: str + Return option contract expiration dates before this date. Format: YYYY-MM-DD + """ + + url = f"https://api-v2.intrinio.com/options/expirations/{symbol}/eod?before={before}&after={after}&api_key={api_key}" + + r = make_request(url) + + expirations = pd.DatetimeIndex(sorted(list(r.json()["expirations"]))) + return list(filter(lambda x: x > pd.to_datetime(after), expirations)) + + +def generate_url(symbol, expiration, date, api_key): + return f"https://api-v2.intrinio.com/options/chain/{symbol}/{expiration}/eod?date={date}&api_key={api_key}" + + +def download_json_files(urls): + results = [] # List to store the downloaded JSON data + + def download_single_file(url): + response = make_request(url) + json_data = response.json() + results.append(json_data["chain"]) + + with concurrent.futures.ThreadPoolExecutor() as executor: + executor.map(download_single_file, urls) + + return results + + +def get_historical_chain_with_greeks( + symbol: str, date: Optional[Union[str, dateType]] = "", api_key: str = "" +): + symbol = symbol.upper() + SYMBOLS = get_options_tickers(api_key) + if symbol not in SYMBOLS: + raise RuntimeError(f"{symbol}", "is not supported by Intrinio.") + + if not date: + date = datetime.now().strftime("%Y-%m-%d") + + # If the symbol is an index, it needs to be preceded with, $. + if symbol in TICKER_EXCEPTIONS: + symbol = "$" + symbol + + expirations = get_options_expirations(symbol=symbol, api_key=api_key, after=date) + urls = [] + + for expiration in expirations: + urls.append(generate_url(symbol, expiration, date, api_key)) + + results = download_json_files(urls) + + if len(results) == 0: + date = pd.to_datetime(date) + timedelta(days=-1) + for expiration in expirations: + urls.append(generate_url(symbol, expiration, date, api_key)) + results = download_json_files(urls) + + df = pd.DataFrame() + + for i in range(0, len(results)): + chains = results[i] + + contract_symbol: List[str] = [] + expiry: List[str] = [] + strikes: List[float] = [] + option_type: List[str] = [] + close: List[float] = [] + close_bid: List[float] = [] + close_ask: List[float] = [] + volume: List[int] = [] + open: List[float] = [] + open_bid: List[float] = [] + open_ask: List[float] = [] + open_interest: List[int] = [] + high: List[float] = [] + low: List[float] = [] + mark: List[float] = [] + ask_high: List[float] = [] + ask_low: List[float] = [] + bid_high: List[float] = [] + bid_low: List[float] = [] + implied_volatility: List[float] = [] + delta: List[float] = [] + gamma: List[float] = [] + theta: List[float] = [] + vega: List[float] = [] + eod_date: List[str] = [] + + for item in chains: + contract_symbol.append(item["option"]["code"]) + expiry.append(item["option"]["expiration"]) + strikes.append(item["option"]["strike"]) + option_type.append(item["option"]["type"]) + close.append(item["prices"]["close"]) + close_bid.append(item["prices"]["close_bid"]) + close_ask.append(item["prices"]["close_ask"]) + volume.append(item["prices"]["volume"]) + open.append(item["prices"]["open"]) + open_bid.append(item["prices"]["open_bid"]) + open_ask.append(item["prices"]["open_ask"]) + open_interest.append(item["prices"]["open_interest"]) + high.append(item["prices"]["high"]) + low.append(item["prices"]["low"]) + mark.append(item["prices"]["mark"]) + ask_high.append(item["prices"]["ask_high"]) + ask_low.append(item["prices"]["ask_low"]) + bid_high.append(item["prices"]["bid_high"]) + bid_low.append(item["prices"]["bid_low"]) + implied_volatility.append(item["prices"]["implied_volatility"]) + delta.append(item["prices"]["delta"]) + gamma.append(item["prices"]["gamma"]) + theta.append(item["prices"]["theta"]) + vega.append(item["prices"]["vega"]) + eod_date.append(item["prices"]["date"]) + + data = pd.DataFrame() + data["contract_symbol"] = contract_symbol + data["expiration"] = expiry + data["strike"] = strikes + data["option_type"] = option_type + data["close"] = close + data["close_bid"] = close_bid + data["close_ask"] = close_ask + data["volume"] = volume + data["open"] = open + data["open_bid"] = open_bid + data["open_ask"] = open_ask + data["open_interest"] = open_interest + data["high"] = high + data["low"] = low + data["mark"] = mark + data["bid_high"] = bid_high + data["ask_high"] = ask_high + data["bid_low"] = bid_low + data["ask_low"] = ask_low + data["implied_volatility"] = implied_volatility + data["delta"] = delta + data["gamma"] = gamma + data["theta"] = theta + data["vega"] = vega + data["eod_date"] = eod_date + + data = data.set_index(["expiration", "strike", "option_type"]).sort_index() + + df = pd.concat([df, data]) + + df = df.sort_index().reset_index() + now = pd.DatetimeIndex(df["eod_date"]) + temp = pd.DatetimeIndex(df["expiration"]) + temp_ = (temp - now).days + 1 + df["dte"] = temp_ + + return df + + +class IntrinioOptionsChainsQueryParams(OptionsChainsQueryParams): + """Get the complete options chains (Historical) for a ticker from Intrinio. + + source: https://docs.intrinio.com/documentation/web_api/get_options_chain_eod_v2 + """ + + date: Optional[Union[str, dateType]] = Field( + description="Date for which the options chains are returned.", + default="", + ) + + +class IntrinioOptionsChainsData(OptionsChainsData): + """Intrinio Options Chains Data.""" + + class Config: + fields = { + "bid": "close_bid", + "ask": "close_ask", + } + + mark: Optional[float] = Field( + description="The mid-price between the latest bid-ask spread." + ) + open_bid: Optional[float] = Field( + description="The lowest bid price for the option that day." + ) + open_ask: Optional[float] = Field( + description="The lowest ask price for the option that day." + ) + bid_low: Optional[float] = Field( + description="The lowest bid price for the option that day." + ) + ask_low: Optional[float] = Field( + description="The lowest ask price for the option that day." + ) + bid_high: Optional[float] = Field( + description="The highest bid price for the option that day." + ) + ask_high: Optional[float] = Field( + description="The highest ask price for the option that day." + ) + open: Optional[float] = Field(description="The open price for the option that day.") + high: Optional[float] = Field(description="The high price for the option that day.") + low: Optional[float] = Field(description="The low price for the option that day.") + close: Optional[float] = Field( + description="The close price for the option that day." + ) + implied_volatility: Optional[float] = Field( + description="The implied volatility for the option at the end of day." + ) + delta: Optional[float] = Field(description="The delta value at the end of day.") + gamma: Optional[float] = Field(description="The gamma value at the end of day.") + vega: Optional[float] = Field(description="The vega value at the end of day.") + theta: Optional[float] = Field(description="The theta value at the end of day.") + eod_date: Optional[dateType] = Field( + description="Historical date for which the options chains data is from.", + ) + dte: Optional[int] = Field(description="The number of days until expiry.") + + @validator("expiration", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the datetime object from the date string""" + return datetime.strptime(v, "%Y-%m-%d") + + +class IntrinioOptionsChainsFetcher( + Fetcher[IntrinioOptionsChainsQueryParams, List[IntrinioOptionsChainsData]] +): + """Transform the query, extract and transform the data from the Intrinio endpoints""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioOptionsChainsQueryParams: + """Transform the query""" + return IntrinioOptionsChainsQueryParams(**params) + + @staticmethod + def extract_data( + query: IntrinioOptionsChainsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + data = get_historical_chain_with_greeks( + symbol=query.symbol, date=query.date, api_key=api_key + ) + + return data.to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioOptionsChainsData]: + """Return the transformed data.""" + return [IntrinioOptionsChainsData(**d) for d in data] diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_historical.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_historical.py new file mode 100644 index 00000000000..d178d1f4a02 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_historical.py @@ -0,0 +1,177 @@ +"""Intrinio Stocks end of day fetcher.""" + +from datetime import datetime, time +from typing import Any, Dict, List, Literal, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_historical import ( + StockHistoricalData, + StockHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, NonNegativeInt, validator + +from openbb_intrinio.utils.helpers import get_data_one +from openbb_intrinio.utils.references import INTERVALS, TIMEZONES + + +class IntrinioStockHistoricalQueryParams(StockHistoricalQueryParams): + """Intrinio Stock end of day Query. + + Source: https://docs.intrinio.com/documentation/web_api/get_security_interval_prices_v2 + """ + + symbol: str = Field( + description="A Security identifier (Ticker, FIGI, ISIN, CUSIP, Intrinio ID)." + ) + timezone: Optional[TIMEZONES] = Field( + default="UTC", description="Returns trading times in this timezone." + ) + source: Optional[Literal["realtime", "delayed", "nasdaq_basic"]] = Field( + default="realtime", description="The source of the data." + ) + start_time: Optional[time] = Field( + description="Return intervals starting at the specified time on the `start_date` formatted as 'hh:mm:ss'." + ) + end_time: Optional[time] = Field( + description="Return intervals stopping at the specified time on the `end_date` formatted as 'hh:mm:ss'." + ) + interval_size: Optional[INTERVALS] = Field( + default="60m", description=QUERY_DESCRIPTIONS.get("frequency", "") + ) + limit: Optional[NonNegativeInt] = Field( + default=300, + description=f"{QUERY_DESCRIPTIONS.get('limit', '')}. Max value allowed is 300.", + ) + next_page: Optional[str] = Field( + description="Token to get the next page of data from a previous API call." + ) + all_pages: Optional[bool] = Field( + default=False, + description="Returns all pages of data from the API call at once.", + ) + + @validator("limit", pre=True) + def limit_check(cls, v): # pylint: disable=E0213 + """Set the limit bound to 300.""" + return min(v, 300) + + +class IntrinioStockHistoricalData(StockHistoricalData): + """Intrinio Stock end of day Data.""" + + class Config: + fields = { + "date": "time", + } + + close_time: Optional[datetime] = Field( + description="The timestamp that represents the end of the interval span." + ) + interval: Optional[str] = Field(description="The data time frequency.") + average: Optional[float] = Field( + description="Average trade price of an individual stock during the interval." + ) + change: Optional[float] = Field( + description="Change in the price of the symbol from the previous day.", + alias="change", + ) + + @validator("time", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return ( + datetime.fromisoformat(v.replace("Z", "+00:00")) + if v.endswith(("Z", "+00:00")) + else datetime.fromisoformat(v) + ) + + @validator("close_time", pre=True, check_fields=False) + def close_time_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return ( + datetime.fromisoformat(v.replace("Z", "+00:00")) + if v.endswith(("Z", "+00:00")) + else datetime.fromisoformat(v) + ) + + +class IntrinioStockHistoricalFetcher( + Fetcher[ + IntrinioStockHistoricalQueryParams, + List[IntrinioStockHistoricalData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioStockHistoricalQueryParams: + """Transform the query params.""" + + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + + if params.get("start_time") is None: + transformed_params["start_time"] = time(0, 0, 0) + + if params.get("end_time") is None: + transformed_params["end_time"] = time(23, 59, 59) + + return IntrinioStockHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: IntrinioStockHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + query_str = get_querystring(query.dict(by_alias=True), ["symbol", "all_pages"]) + query_str = query_str.replace("limit", "page_size") + url = ( + f"{base_url}/securities/{query.symbol}/prices/intervals" + f"?{query_str}&api_key={api_key}" + ) + + data = get_data_one(url, **kwargs) + + if query.all_pages: + all_data = data["intervals"] + next_page = data["next_page"] + + while next_page: + query_str = get_querystring( + query.dict(by_alias=True), ["symbol", "next_page", "all_pages"] + ) + query_str = query_str.replace("limit", "page_size") + url = ( + f"{base_url}/securities/{query.symbol}/prices/intervals" + f"?{query_str}&next_page={next_page}&api_key={api_key}" + ) + + data = get_data_one(url, **kwargs) + all_data.extend(data.get("intervals", [])) + + next_page = data.get("next_page", None) + + return all_data + + return data.get("intervals", []) + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioStockHistoricalData]: + """Return the transformed data.""" + + return [IntrinioStockHistoricalData(**d) for d in data] diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_news.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_news.py new file mode 100644 index 00000000000..ae6a99466ee --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_news.py @@ -0,0 +1,99 @@ +"""Intrinio Stock News fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_news import ( + StockNewsData, + StockNewsQueryParams, +) +from openbb_provider.utils.helpers import get_querystring +from pydantic import Field, validator + +from openbb_intrinio.utils.helpers import get_data_many + + +class IntrinioStockNewsQueryParams(StockNewsQueryParams): + """Intrinio Stock News query. + + Source: https://docs.intrinio.com/documentation/web_api/get_company_news_v2 + """ + + class Config: + """Pydantic alias config using fields dict.""" + + fields = { + "symbols": "symbols", + "page": "next_page", + "limit": "page_size", + } + + symbols: str = Field( + description="A Company identifier (Ticker, CIK, LEI, Intrinio ID)." + ) + next_page: Optional[str] = Field( + description="Token to get the next page of data from a previous API call." + ) + # TODO: Add support for all_pages + all_pages: Optional[bool] = Field( + default=False, + description="Returns all pages of data from the API call at once.", + ) + + +class IntrinioStockNewsData(StockNewsData): + """Intrinio Stock News data.""" + + class Config: + """Pydantic alias config using fields dict.""" + + fields = { + "date": "publication_date", + "text": "summary", + } + + id: str = Field(description="Intrinio ID for the news article.") + + @validator("publication_date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S.000Z") + + +class IntrinioStockNewsFetcher( + Fetcher[ + IntrinioStockNewsQueryParams, + List[IntrinioStockNewsData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioStockNewsQueryParams: + """Transform the query params.""" + + return IntrinioStockNewsQueryParams(**params) + + @staticmethod + def extract_data( + query: IntrinioStockNewsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + """Return the raw data from the Intrinio endpoint.""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + query_str = get_querystring(query.dict(by_alias=True), ["symbols", "all_pages"]) + url = f"{base_url}/companies/{query.symbols}/news?{query_str}&api_key={api_key}" + + return get_data_many(url, "news", **kwargs) + + @staticmethod + def transform_data(data: List[Dict]) -> List[IntrinioStockNewsData]: + """Return the transformed data.""" + + return [IntrinioStockNewsData(**d) for d in data] diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_quote.py b/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_quote.py new file mode 100644 index 00000000000..f5509fa8c00 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/models/stock_quote.py @@ -0,0 +1,128 @@ +"""Intrinio Stock Quote fetcher.""" + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_quote import ( + StockQuoteData, + StockQuoteQueryParams, +) +from pydantic import Field, validator + +from openbb_intrinio.utils.helpers import get_data_one +from openbb_intrinio.utils.references import SOURCES + + +class IntrinioStockQuoteQueryParams(StockQuoteQueryParams): + """Intrinio Stock Quote Query. + + Source: https://docs.intrinio.com/documentation/web_api/get_security_realtime_price_v2 + """ + + symbol: str = Field( + description="A Security identifier (Ticker, FIGI, ISIN, CUSIP, Intrinio ID)." + ) + source: SOURCES = Field(default="iex", description="Source of the data.") + + +class IntrinioStockQuoteData(StockQuoteData): + """Intrinio Stock Quote Data.""" + + class Config: + """Pydantic alias config using fields dict.""" + + fields = { + "day_low": "low_price", + "day_high": "high_price", + "date": "last_time", + } + + last_price: float = Field(description="Price of the last trade.") + last_time: datetime = Field( + description="Date and Time when the last trade occurred." + ) + last_size: int = Field(description="Size of the last trade.") + bid_price: float = Field(description="Price of the top bid order.") + bid_size: int = Field(description="Size of the top bid order.") + ask_price: float = Field(description="Price of the top ask order.") + ask_size: int = Field(description="Size of the top ask order.") + open_price: float = Field(description="Open price for the trading day.") + close_price: Optional[float] = Field( + description="Closing price for the trading day (IEX source only)." + ) + high_price: float = Field(description="High Price for the trading day.") + low_price: float = Field(description="Low Price for the trading day.") + exchange_volume: Optional[int] = Field( + description="Number of shares exchanged during the trading day on the exchange." + ) + market_volume: Optional[int] = Field( + description="Number of shares exchanged during the trading day for the whole market." + ) + updated_on: datetime = Field( + description="Date and Time when the data was last updated." + ) + source: str = Field(description="Source of the data.") + listing_venue: Optional[str] = Field( + description="Listing venue where the trade took place (SIP source only)." + ) + sales_conditions: Optional[str] = Field( + description="Indicates any sales condition modifiers associated with the trade." + ) + quote_conditions: Optional[str] = Field( + description="Indicates any quote condition modifiers associated with the trade." + ) + market_center_code: Optional[str] = Field( + description="Market center character code." + ) + is_darkpool: Optional[bool] = Field( + description="Whether or not the current trade is from a darkpool." + ) + + @validator("last_time", "updated_on", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the date as a datetime object.""" + return ( + datetime.fromisoformat(v.replace("Z", "+00:00")) + if v.endswith(("Z", "+00:00")) + else datetime.fromisoformat(v) + ) + + +class IntrinioStockQuoteFetcher( + Fetcher[ + IntrinioStockQuoteQueryParams, + List[IntrinioStockQuoteData], + ] +): + """Transform the query, extract and transform the data from the Intrinio endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> IntrinioStockQuoteQueryParams: + """Transform the query params.""" + + return IntrinioStockQuoteQueryParams(**params) + + @staticmethod + def extract_data( + query: IntrinioStockQuoteQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> Dict: + """Return the raw data from the Intrinio endpoint.""" + + api_key = credentials.get("intrinio_api_key") if credentials else "" + + base_url = "https://api-v2.intrinio.com" + url = f"{base_url}/securities/{query.symbol}/prices/realtime?source={query.source}&api_key={api_key}" + + return get_data_one(url, **kwargs) + + @staticmethod + def transform_data(data: Dict) -> IntrinioStockQuoteData: + """Return the transformed data.""" + + del data["messages"] + del data["security"] + + return IntrinioStockQuoteData(**data) diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/utils/__init__.py b/openbb_sdk/providers/intrinio/openbb_intrinio/utils/__init__.py new file mode 100644 index 00000000000..f46961441f6 --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/utils/__init__.py @@ -0,0 +1 @@ +"""yfinance utils directory.""" diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/utils/helpers.py b/openbb_sdk/providers/intrinio/openbb_intrinio/utils/helpers.py new file mode 100644 index 00000000000..e383194cf4d --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/utils/helpers.py @@ -0,0 +1,171 @@ +"""Intrinio Helpers Module.""" + +import json +from datetime import datetime, timedelta +from io import StringIO +from typing import Any, List, Optional, TypeVar, Union + +import requests +import requests_cache +from openbb_provider import helpers +from openbb_provider.utils.helpers import make_request +from pydantic import BaseModel +from requests.exceptions import SSLError + +T = TypeVar("T", bound=BaseModel) + + +# This will cache the symbol directory requests for 5 days. +intrinio_session = requests_cache.CachedSession( + "OpenBB_Intrinio", expire_after=timedelta(days=5), use_cache_dir=True +) + + +def get_options_tickers(api_key: str = "") -> List[str]: + """Returns all tickers that have existing options contracts. + + Parameters + ---------- + api_key: str + Intrinio API key. + + Returns + ------- + List[str] + List of tickers + """ + url = f"https://api-v2.intrinio.com/options/tickers?api_key={api_key}" + + r = intrinio_session.get(url, timeout=10) + + return r.json()["tickers"] + + +def get_options_expirations( + symbol: str, + after: Optional[str] = datetime.now().date().strftime("%Y-%m-%d"), + before: Optional[str] = "", + api_key: str = "", +) -> list: + """Returns a list of all current and upcoming option contract expiration dates for a particular symbol. + + Parameters + ---------- + symbol: str + The options symbol, corresponding to the underlying security. + after: str + Return option contract expiration dates after this date. Format: YYYY-MM-DD + before: str + Return option contract expiration dates before this date. Format: YYYY-MM-DD + api_key: str + Intrinio API key. + """ + + url = f"https://api-v2.intrinio.com/options/expirations/{symbol}/eod?before={before}&after={after}&api_key={api_key}" + + r = make_request(url) + + return sorted(list(r.json()["expirations"])) + + +class BasicResponse: + """Basic Response class.""" + + def __init__(self, response: StringIO): + """Initialize the BasicResponse class.""" + + # Find a way to get the status code + self.status_code = 200 + response.seek(0) + self.text = response.read() + + def json(self) -> dict: + """Return the response as a dictionary.""" + + return json.loads(self.text) + + +def request(url: str) -> BasicResponse: + """ + Request function for PyScript. Pass in Method and make sure to await! + + Parameters: + ----------- + url: str + URL to make request to + + Return: + ------- + response: BasicRequest + BasicRequest object with status_code and text attributes + """ + # pylint: disable=import-outside-toplevel + from pyodide.http import open_url # type: ignore + + response = open_url(url) + return BasicResponse(response) + + +def get_data(url: str, **kwargs: Any) -> Union[list, dict]: + """Get data from Intrinio endpoint.""" + + try: + r: Union[requests.Response, BasicResponse] = helpers.make_request(url, **kwargs) + except SSLError: + r = request(url) + if r.status_code == 404: + raise RuntimeError("Intrinio endpoint doesn't exist") + + data = r.json() + if r.status_code != 200: + message = data.get("message", "unknown error") + raise RuntimeError(f"Error in Intrinio request -> {message}") + + if "Error Message" in data: + raise RuntimeError("Intrinio Error Message -> " + data["Error Message"]) + + if len(data) == 0: + raise RuntimeError("No results found. Try adjusting the query parameters.") + + return data + + +def get_data_many( + url: str, sub_dict: Optional[str] = None, **kwargs: Any +) -> List[dict]: + """Get data from Intrinio endpoint and convert to list of schemas. + + Parameters: + ----------- + url: str + The URL to get the data from. + sub_dict: Optional[str] + The sub-dictionary to use. + + Returns: + -------- + List[dict] + Dictionary of data. + """ + data = get_data(url, **kwargs) + if sub_dict and isinstance(data, dict): + data = data.get(sub_dict, []) + if isinstance(data, dict): + raise ValueError("Expected list of dicts, got dict") + return data + + +def get_data_one(url: str, **kwargs: Any) -> dict: + """Get data from Intrinio endpoint and convert to schema.""" + + data = get_data(url, **kwargs) + if isinstance(data, list): + if len(data) == 0: + raise ValueError("Expected dict, got empty list") + + try: + data = {i: data[i] for i in range(len(data))} if len(data) > 1 else data[0] + except TypeError as e: + raise ValueError("Expected dict, got list of dicts") from e + + return data diff --git a/openbb_sdk/providers/intrinio/openbb_intrinio/utils/references.py b/openbb_sdk/providers/intrinio/openbb_intrinio/utils/references.py new file mode 100644 index 00000000000..a0479f69c2d --- /dev/null +++ b/openbb_sdk/providers/intrinio/openbb_intrinio/utils/references.py @@ -0,0 +1,168 @@ +from typing import Literal + +SOURCES = Literal[ + "iex", + "bats", + "bats_delayed", + "utp_delayed", + "cta_a_delayed", + "cta_b_delayed", + "intrinio_mx", + "intrinio_mx_plus", + "delayed_sip", +] + +INTERVALS = Literal["1m", "5m", "10m", "15m", "30m", "60m", "1h"] + +TIMEZONES = Literal[ + "Africa/Algiers", + "Africa/Cairo", + "Africa/Casablanca", + "Africa/Harare", + "Africa/Johannesburg", + "Africa/Monrovia", + "Africa/Nairobi", + "America/Argentina/Buenos_Aires", + "America/Bogota", + "America/Caracas", + "America/Chicago", + "America/Chihuahua", + "America/Denver", + "America/Godthab", + "America/Guatemala", + "America/Guyana", + "America/Halifax", + "America/Indiana/Indianapolis", + "America/Juneau", + "America/La_Paz", + "America/Lima", + "America/Lima", + "America/Los_Angeles", + "America/Mazatlan", + "America/Mexico_City", + "America/Mexico_City", + "America/Monterrey", + "America/Montevideo", + "America/New_York", + "America/Phoenix", + "America/Regina", + "America/Santiago", + "America/Sao_Paulo", + "America/St_Johns", + "America/Tijuana", + "Asia/Almaty", + "Asia/Baghdad", + "Asia/Baku", + "Asia/Bangkok", + "Asia/Bangkok", + "Asia/Chongqing", + "Asia/Colombo", + "Asia/Dhaka", + "Asia/Dhaka", + "Asia/Hong_Kong", + "Asia/Irkutsk", + "Asia/Jakarta", + "Asia/Jerusalem", + "Asia/Kabul", + "Asia/Kamchatka", + "Asia/Karachi", + "Asia/Karachi", + "Asia/Kathmandu", + "Asia/Kolkata", + "Asia/Kolkata", + "Asia/Kolkata", + "Asia/Kolkata", + "Asia/Krasnoyarsk", + "Asia/Kuala_Lumpur", + "Asia/Kuwait", + "Asia/Magadan", + "Asia/Muscat", + "Asia/Muscat", + "Asia/Novosibirsk", + "Asia/Rangoon", + "Asia/Riyadh", + "Asia/Seoul", + "Asia/Shanghai", + "Asia/Singapore", + "Asia/Srednekolymsk", + "Asia/Taipei", + "Asia/Tashkent", + "Asia/Tbilisi", + "Asia/Tehran", + "Asia/Tokyo", + "Asia/Tokyo", + "Asia/Tokyo", + "Asia/Ulaanbaatar", + "Asia/Urumqi", + "Asia/Vladivostok", + "Asia/Yakutsk", + "Asia/Yekaterinburg", + "Asia/Yerevan", + "Atlantic/Azores", + "Atlantic/Cape_Verde", + "Atlantic/South_Georgia", + "Australia/Adelaide", + "Australia/Brisbane", + "Australia/Darwin", + "Australia/Hobart", + "Australia/Melbourne", + "Australia/Melbourne", + "Australia/Perth", + "Australia/Sydney", + "Etc/UTC", + "UTC", + "Europe/Amsterdam", + "Europe/Athens", + "Europe/Belgrade", + "Europe/Berlin", + "Europe/Berlin", + "Europe/Bratislava", + "Europe/Brussels", + "Europe/Bucharest", + "Europe/Budapest", + "Europe/Copenhagen", + "Europe/Dublin", + "Europe/Helsinki", + "Europe/Istanbul", + "Europe/Kaliningrad", + "Europe/Kiev", + "Europe/Lisbon", + "Europe/Ljubljana", + "Europe/London", + "Europe/London", + "Europe/Madrid", + "Europe/Minsk", + "Europe/Moscow", + "Europe/Moscow", + "Europe/Paris", + "Europe/Prague", + "Europe/Riga", + "Europe/Rome", + "Europe/Samara", + "Europe/Sarajevo", + "Europe/Skopje", + "Europe/Sofia", + "Europe/Stockholm", + "Europe/Tallinn", + "Europe/Vienna", + "Europe/Vilnius", + "Europe/Volgograd", + "Europe/Warsaw", + "Europe/Zagreb", + "Pacific/Apia", + "Pacific/Auckland", + "Pacific/Auckland", + "Pacific/Chatham", + "Pacific/Fakaofo", + "Pacific/Fiji", + "Pacific/Guadalcanal", + "Pacific/Guam", + "Pacific/Honolulu", + "Pacific/Majuro", + "Pacific/Midway", + "Pacific/Midway", + "Pacific/Noumea", + "Pacific/Pago_Pago", + "Pacific/Port_Moresby", + "Pacific/Tongatapu", +] diff --git a/openbb_sdk/providers/intrinio/poetry.lock b/openbb_sdk/providers/intrinio/poetry.lock new file mode 100644 index 00000000000..bbdeb006281 --- /dev/null +++ b/openbb_sdk/providers/intrinio/poetry.lock @@ -0,0 +1,1144 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.0.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, + {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.22)"] + +[[package]] +name = "attrs" +version = "23.1.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.7" +files = [ + {file = "attrs-23.1.0-py3-none-any.whl", hash = "sha256:1f28b4522cdc2fb4256ac1a020c78acf9cba2c6b461ccd2c126f3aa8e8335d04"}, + {file = "attrs-23.1.0.tar.gz", hash = "sha256:6279836d581513a26f1bf235f9acd333bc9115683f14f7e8fae46c98fc50e015"}, +] + +[package.extras] +cov = ["attrs[tests]", "coverage[toml] (>=5.3)"] +dev = ["attrs[docs,tests]", "pre-commit"] +docs = ["furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier", "zope-interface"] +tests = ["attrs[tests-no-zope]", "zope-interface"] +tests-no-zope = ["cloudpickle", "hypothesis", "mypy (>=1.1.1)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "pytest-xdist[psutil]"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bcrypt" +version = "4.0.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.6" +files = [ + {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e"}, + {file = "bcrypt-4.0.1-cp36-abi3-win32.whl", hash = "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab"}, + {file = "bcrypt-4.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71"}, + {file = "bcrypt-4.0.1.tar.gz", hash = "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + +[[package]] +name = "black" +version = "23.7.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "cattrs" +version = "23.1.2" +description = "Composable complex class support for attrs and dataclasses." +optional = false +python-versions = ">=3.7" +files = [ + {file = "cattrs-23.1.2-py3-none-any.whl", hash = "sha256:b2bb14311ac17bed0d58785e5a60f022e5431aca3932e3fc5cc8ed8639de50a4"}, + {file = "cattrs-23.1.2.tar.gz", hash = "sha256:db1c821b8c537382b2c7c66678c3790091ca0275ac486c76f3c8f3920e83c657"}, +] + +[package.dependencies] +attrs = ">=20" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} +typing_extensions = {version = ">=4.1.0", markers = "python_version < \"3.11\""} + +[package.extras] +bson = ["pymongo (>=4.2.0,<5.0.0)"] +cbor2 = ["cbor2 (>=5.4.6,<6.0.0)"] +msgpack = ["msgpack (>=1.0.2,<2.0.0)"] +orjson = ["orjson (>=3.5.2,<4.0.0)"] +pyyaml = ["PyYAML (>=6.0,<7.0)"] +tomlkit = ["tomlkit (>=0.11.4,<0.12.0)"] +ujson = ["ujson (>=5.4.0,<6.0.0)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.2.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "ecdsa" +version = "0.18.0" +description = "ECDSA cryptographic signature library (pure python)" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"}, + {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"}, +] + +[package.dependencies] +six = ">=1.9.0" + +[package.extras] +gmpy = ["gmpy"] +gmpy2 = ["gmpy2"] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fastapi" +version = "0.100.1" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.7" +files = [ + {file = "fastapi-0.100.1-py3-none-any.whl", hash = "sha256:ec6dd52bfc4eff3063cfcd0713b43c87640fefb2687bbbe3d8a08d94049cdf32"}, + {file = "fastapi-0.100.1.tar.gz", hash = "sha256:522700d7a469e4a973d92321ab93312448fbe20fca9c8da97effc7e7bc56df23"}, +] + +[package.dependencies] +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0" +starlette = ">=0.27.0,<0.28.0" +typing-extensions = ">=4.5.0" + +[package.extras] +all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "html5lib" +version = "1.1" +description = "HTML parser based on the WHATWG HTML specification" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] + +[package.dependencies] +six = ">=1.9" +webencodings = "*" + +[package.extras] +all = ["chardet (>=2.2)", "genshi", "lxml"] +chardet = ["chardet (>=2.2)"] +genshi = ["genshi"] +lxml = ["lxml"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "monotonic" +version = "1.6" +description = "An implementation of time.monotonic() for Python 2 & < 3.3" +optional = false +python-versions = "*" +files = [ + {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, + {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + +[[package]] +name = "numpy" +version = "1.25.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.9" +files = [ + {file = "numpy-1.25.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:db3ccc4e37a6873045580d413fe79b68e47a681af8db2e046f1dacfa11f86eb3"}, + {file = "numpy-1.25.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:90319e4f002795ccfc9050110bbbaa16c944b1c37c0baeea43c5fb881693ae1f"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dfe4a913e29b418d096e696ddd422d8a5d13ffba4ea91f9f60440a3b759b0187"}, + {file = "numpy-1.25.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f08f2e037bba04e707eebf4bc934f1972a315c883a9e0ebfa8a7756eabf9e357"}, + {file = "numpy-1.25.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:bec1e7213c7cb00d67093247f8c4db156fd03075f49876957dca4711306d39c9"}, + {file = "numpy-1.25.2-cp310-cp310-win32.whl", hash = "sha256:7dc869c0c75988e1c693d0e2d5b26034644399dd929bc049db55395b1379e044"}, + {file = "numpy-1.25.2-cp310-cp310-win_amd64.whl", hash = "sha256:834b386f2b8210dca38c71a6e0f4fd6922f7d3fcff935dbe3a570945acb1b545"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c5462d19336db4560041517dbb7759c21d181a67cb01b36ca109b2ae37d32418"}, + {file = "numpy-1.25.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:c5652ea24d33585ea39eb6a6a15dac87a1206a692719ff45d53c5282e66d4a8f"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d60fbae8e0019865fc4784745814cff1c421df5afee233db6d88ab4f14655a2"}, + {file = "numpy-1.25.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:60e7f0f7f6d0eee8364b9a6304c2845b9c491ac706048c7e8cf47b83123b8dbf"}, + {file = "numpy-1.25.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:bb33d5a1cf360304754913a350edda36d5b8c5331a8237268c48f91253c3a364"}, + {file = "numpy-1.25.2-cp311-cp311-win32.whl", hash = "sha256:5883c06bb92f2e6c8181df7b39971a5fb436288db58b5a1c3967702d4278691d"}, + {file = "numpy-1.25.2-cp311-cp311-win_amd64.whl", hash = "sha256:5c97325a0ba6f9d041feb9390924614b60b99209a71a69c876f71052521d42a4"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b79e513d7aac42ae918db3ad1341a015488530d0bb2a6abcbdd10a3a829ccfd3"}, + {file = "numpy-1.25.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:eb942bfb6f84df5ce05dbf4b46673ffed0d3da59f13635ea9b926af3deb76926"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e0746410e73384e70d286f93abf2520035250aad8c5714240b0492a7302fdca"}, + {file = "numpy-1.25.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d7806500e4f5bdd04095e849265e55de20d8cc4b661b038957354327f6d9b295"}, + {file = "numpy-1.25.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8b77775f4b7df768967a7c8b3567e309f617dd5e99aeb886fa14dc1a0791141f"}, + {file = "numpy-1.25.2-cp39-cp39-win32.whl", hash = "sha256:2792d23d62ec51e50ce4d4b7d73de8f67a2fd3ea710dcbc8563a51a03fb07b01"}, + {file = "numpy-1.25.2-cp39-cp39-win_amd64.whl", hash = "sha256:76b4115d42a7dfc5d485d358728cdd8719be33cc5ec6ec08632a5d6fca2ed380"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:1a1329e26f46230bf77b02cc19e900db9b52f398d6722ca853349a782d4cff55"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c3abc71e8b6edba80a01a52e66d83c5d14433cbcd26a40c329ec7ed09f37901"}, + {file = "numpy-1.25.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:1b9735c27cea5d995496f46a8b1cd7b408b3f34b6d50459d9ac8fe3a20cc17bf"}, + {file = "numpy-1.25.2.tar.gz", hash = "sha256:fd608e19c8d7c55021dffd43bfe5492fab8cc105cc8986f813f8c3c048b38760"}, +] + +[[package]] +name = "openbb-core" +version = "0.1.0" +description = "OpenBB package with core functionality" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +bcrypt = "^4.0.1" +black = "^23.7.0" +fastapi = "^0.100.1" +html5lib = "^1.1" +openbb-provider = {path = "../provider"} +pandas = ">=1.5.3" +passlib = "^1.7.4" +posthog = "^3.0.1" +python-jose = "^3.3.0" +python-multipart = "^0.0.6" +ruff = "0.0.256" +uuid7 = "^0.1.0" +uvicorn = "^0.20.0" +websockets = "^10.4" + +[package.source] +type = "directory" +url = "../../sdk/core" + +[[package]] +name = "openbb-provider" +version = "0.1.0" +description = "OpenBB package to execute queries to financial data providers" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +importlib-metadata = "^6.8.0" +pydantic = {version = "^1.10", extras = ["dotenv"]} +requests = "^2.31.0" +urllib3 = "<2.0.0" + +[package.source] +type = "directory" +url = "../../sdk/provider" + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pandas" +version = "2.0.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.1" + +[package.extras] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +aws = ["s3fs (>=2021.08.0)"] +clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] +compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] +computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2021.07.0)"] +gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] +hdf5 = ["tables (>=3.6.1)"] +html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] +mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] +spss = ["pyreadstat (>=1.1.2)"] +sql-other = ["SQLAlchemy (>=1.4.16)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.6.3)"] + +[[package]] +name = "passlib" +version = "1.7.4" +description = "comprehensive password hashing framework supporting over 30 schemes" +optional = false +python-versions = "*" +files = [ + {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, + {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, +] + +[package.extras] +argon2 = ["argon2-cffi (>=18.2.0)"] +bcrypt = ["bcrypt (>=3.1.0)"] +build-docs = ["cloud-sptheme (>=1.10.1)", "sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)"] +totp = ["cryptography"] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "posthog" +version = "3.0.2" +description = "Integrate PostHog into any python application." +optional = false +python-versions = "*" +files = [ + {file = "posthog-3.0.2-py2.py3-none-any.whl", hash = "sha256:a8c0af6f2401fbe50f90e68c4143d0824b54e872de036b1c2f23b5abb39d88ce"}, + {file = "posthog-3.0.2.tar.gz", hash = "sha256:701fba6e446a4de687c6e861b587e7b7741955ad624bf34fe013c06a0fec6fb3"}, +] + +[package.dependencies] +backoff = ">=1.10.0" +monotonic = ">=1.5" +python-dateutil = ">2.1" +requests = ">=2.7,<3.0" +six = ">=1.5" + +[package.extras] +dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"] +sentry = ["django", "sentry-sdk"] +test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest"] + +[[package]] +name = "pyasn1" +version = "0.5.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, + {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"}, +] + +[[package]] +name = "pydantic" +version = "1.10.12" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, + {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, + {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, + {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, + {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, + {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, + {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, + {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, + {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, +] + +[package.dependencies] +python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""} +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "1.0.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-jose" +version = "3.3.0" +description = "JOSE implementation in Python" +optional = false +python-versions = "*" +files = [ + {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, + {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, +] + +[package.dependencies] +ecdsa = "!=0.15" +pyasn1 = "*" +rsa = "*" + +[package.extras] +cryptography = ["cryptography (>=3.4.0)"] +pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"] +pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] + +[[package]] +name = "python-multipart" +version = "0.0.6" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, + {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, +] + +[package.extras] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] + +[[package]] +name = "pytz" +version = "2023.3" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, + {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, +] + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-cache" +version = "1.1.0" +description = "A persistent cache for python requests" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "requests_cache-1.1.0-py3-none-any.whl", hash = "sha256:178282bce704b912c59e7f88f367c42bddd6cde6bf511b2a3e3cfb7e5332a92a"}, + {file = "requests_cache-1.1.0.tar.gz", hash = "sha256:41b79166aa8e300cc4de982f7ab7c52af914a785160be1eda25c6e9265969a67"}, +] + +[package.dependencies] +attrs = ">=21.2" +cattrs = ">=22.2" +platformdirs = ">=2.5" +requests = ">=2.22" +url-normalize = ">=1.4" +urllib3 = ">=1.25.5" + +[package.extras] +all = ["boto3 (>=1.15)", "botocore (>=1.18)", "itsdangerous (>=2.0)", "pymongo (>=3)", "pyyaml (>=5.4)", "redis (>=3)", "ujson (>=5.4)"] +bson = ["bson (>=0.5)"] +docs = ["furo (>=2023.3,<2024.0)", "linkify-it-py (>=2.0,<3.0)", "myst-parser (>=1.0,<2.0)", "sphinx (>=5.0.2,<6.0.0)", "sphinx-autodoc-typehints (>=1.19)", "sphinx-automodapi (>=0.14)", "sphinx-copybutton (>=0.5)", "sphinx-design (>=0.2)", "sphinx-notfound-page (>=0.8)", "sphinxcontrib-apidoc (>=0.3)", "sphinxext-opengraph (>=0.6)"] +dynamodb = ["boto3 (>=1.15)", "botocore (>=1.18)"] +json = ["ujson (>=5.4)"] +mongodb = ["pymongo (>=3)"] +redis = ["redis (>=3)"] +security = ["itsdangerous (>=2.0)"] +yaml = ["pyyaml (>=5.4)"] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "ruff" +version = "0.0.256" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.256-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:eb8e949f6e7fb16f9aa163fcc13318e2b7910577513468417e5b003b984410a1"}, + {file = "ruff-0.0.256-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:48a42f0ec4c5a3c3b062e947b2a5f8f7a4264761653fb0ee656a9b535ae6d8d7"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ca633cfc335869643a13e2006f13a63bc4cb94073aa9508ceb08a1e3afe3af"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:80fa5d3a40dd0b65c6d6adea4f825984d5d3a215a25d90cc6139978cb22ea1cd"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0f88839b886db3577136375865bd080b9ed6f9b85bb990d897780e5a30ca3c2"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe6d77a43b2d52f45ee42f6f682198ed1c34cd0165812e276648981dfd50ad36"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3878593507b281b2615702ece06426e8b27076e8fedf658bf0c5e1e5e2ad1b40"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e052ec4d5c92663caa662b68fe1902ec10eddac2783229b1c5f20f3df62a865"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2116bd67e52ade9f90e5a3a3aa511a9b179c699690221bdd5bb267dbf7e94b22"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3c6e93d7818a75669328e49a0f7070c40e18676ca8e56ca9c566633bef4d8d05"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ebb7de4e62d751b65bb15418a83ac5d555afb3eaa3ad549dea21744da34ae86"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f310bfc76c0404a487759c8904f57bf51653c46e686c800efc1ff1d165a59a04"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:93a0cfec812b2ba57bff22b176901e0ddf44e4d42a9bd7da7ffb5e53df13fd6e"}, + {file = "ruff-0.0.256-py3-none-win32.whl", hash = "sha256:d63e5320bc2d91e94925cd1863e381a48edf087041035967faf2614bb36a6a0d"}, + {file = "ruff-0.0.256-py3-none-win_amd64.whl", hash = "sha256:859c8ffb1801895fe043a2b85a45cd0ff35667ddea4b465ba2a29d275550814a"}, + {file = "ruff-0.0.256-py3-none-win_arm64.whl", hash = "sha256:64b276149e86c3d234608d3fe1da77535865e03debd3a1d5d04576f7f5031bbb"}, + {file = "ruff-0.0.256.tar.gz", hash = "sha256:f9a96b34a4870ee8cf2f3779cd7854620d1788a83b52374771266cf800541bb7"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "starlette" +version = "0.27.0" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.7" +files = [ + {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, + {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "url-normalize" +version = "1.4.3" +description = "URL normalization for Python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "url-normalize-1.4.3.tar.gz", hash = "sha256:d23d3a070ac52a67b83a1c59a0e68f8608d1cd538783b401bc9de2c0fac999b2"}, + {file = "url_normalize-1.4.3-py2.py3-none-any.whl", hash = "sha256:ec3c301f04e5bb676d333a7fa162fa977ad2ca04b7e652bfc9fac4e405728eed"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "urllib3" +version = "1.26.16" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, + {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "uuid7" +version = "0.1.0" +description = "UUID version 7, generating time-sorted UUIDs with 200ns time resolution and 48 bits of randomness" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uuid7-0.1.0-py2.py3-none-any.whl", hash = "sha256:5e259bb63c8cb4aded5927ff41b444a80d0c7124e8a0ced7cf44efa1f5cccf61"}, + {file = "uuid7-0.1.0.tar.gz", hash = "sha256:8c57aa32ee7456d3cc68c95c4530bc571646defac01895cfc73545449894a63c"}, +] + +[[package]] +name = "uvicorn" +version = "0.20.0" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.7" +files = [ + {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"}, + {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "websockets" +version = "10.4" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, + {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, + {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, + {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, + {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, + {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, + {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, + {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, + {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, + {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, + {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, + {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, + {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, + {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, + {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, + {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, + {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, + {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, + {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, + {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, + {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, + {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, + {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, + {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, +] + +[[package]] +name = "zipp" +version = "3.16.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "089b57f47762394a09171ba599366e5a5f0aefc8800032cb1ca4fdaed02fd1f1" diff --git a/openbb_sdk/providers/intrinio/pyproject.toml b/openbb_sdk/providers/intrinio/pyproject.toml new file mode 100644 index 00000000000..e41db6ee99e --- /dev/null +++ b/openbb_sdk/providers/intrinio/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "openbb-intrinio" +version = "0.1.0" +description = "Intrinio extension for OpenBB" +authors = ["OpenBB Team "] +readme = "README.md" +packages = [{ include = "openbb_intrinio" }] + +[tool.poetry.dependencies] +python = "^3.8" +requests-cache = "^1.1.0" +openbb-core = { path = "../../sdk/core" } + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.plugins."openbb_provider_extension"] +intrinio = "openbb_intrinio:intrinio_provider" diff --git a/openbb_sdk/providers/intrinio/tests/.gitkeep b/openbb_sdk/providers/intrinio/tests/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/polygon/openbb_polygon/__init__.py b/openbb_sdk/providers/polygon/openbb_polygon/__init__.py index 042c59d2358..731b554ada9 100644 --- a/openbb_sdk/providers/polygon/openbb_polygon/__init__.py +++ b/openbb_sdk/providers/polygon/openbb_polygon/__init__.py @@ -3,12 +3,14 @@ from openbb_provider.abstract.provider import Provider from openbb_polygon.models.balance_sheet import PolygonBalanceSheetFetcher from openbb_polygon.models.cash_flow import PolygonCashFlowStatementFetcher -from openbb_polygon.models.crypto_eod import PolygonCryptoEODFetcher -from openbb_polygon.models.forex_eod import PolygonForexEODFetcher +from openbb_polygon.models.crypto_historical import PolygonCryptoHistoricalFetcher +from openbb_polygon.models.forex_historical import PolygonForexHistoricalFetcher from openbb_polygon.models.forex_pairs import PolygonForexPairsFetcher from openbb_polygon.models.income_statement import PolygonIncomeStatementFetcher -from openbb_polygon.models.major_indices_eod import PolygonMajorIndicesEODFetcher -from openbb_polygon.models.stock_eod import PolygonStockEODFetcher +from openbb_polygon.models.major_indices_historical import ( + PolygonMajorIndicesHistoricalFetcher, +) +from openbb_polygon.models.stock_historical import PolygonStockHistoricalFetcher from openbb_polygon.models.stock_news import PolygonStockNewsFetcher polygon_provider = Provider( @@ -19,14 +21,14 @@ polygon_provider = Provider( company financials, stock market holidays, corporate actions, and more.""", required_credentials=["api_key"], fetcher_dict={ - "StockEOD": PolygonStockEODFetcher, + "StockHistorical": PolygonStockHistoricalFetcher, "StockNews": PolygonStockNewsFetcher, "BalanceSheet": PolygonBalanceSheetFetcher, "IncomeStatement": PolygonIncomeStatementFetcher, "CashFlowStatement": PolygonCashFlowStatementFetcher, - "CryptoEOD": PolygonCryptoEODFetcher, - "MajorIndicesEOD": PolygonMajorIndicesEODFetcher, - "ForexEOD": PolygonForexEODFetcher, + "CryptoHistorical": PolygonCryptoHistoricalFetcher, + "MajorIndicesHistorical": PolygonMajorIndicesHistoricalFetcher, + "ForexHistorical": PolygonForexHistoricalFetcher, "ForexPairs": PolygonForexPairsFetcher, }, ) diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/balance_sheet.py b/openbb_sdk/providers/polygon/openbb_polygon/models/balance_sheet.py index dd66e0a46e2..2a9b85a7df2 100644 --- a/openbb_sdk/providers/polygon/openbb_polygon/models/balance_sheet.py +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/balance_sheet.py @@ -21,9 +21,20 @@ class PolygonBalanceSheetData(BalanceSheetData): class Config: fields = { - "date": "start_date", - "equity": "total_equity", - "total_liabilities_and_stockholders_equity": "liabilities_and_equity", + "total_current_assets": "current_assets", + "marketable_securities": "fixed_assets", + "property_plant_equipment_net": "public_utilities_property_plant_and_equipment_net", + "other_non_current_assets": "other_noncurrent_assets_of_regulated_entity", + "total_non_current_assets": "noncurrent_assets", + "total_assets": "assets", + "total_current_liabilities": "current_liabilities", + "other_non_current_liabilities": "other _noncurrent_liabilities_of_regulated_entity", + "total_non_current_liabilities": "noncurrent_liabilities", + "total_liabilities": "liabilities", + "preferred_stock": "temporary_equity", + "total_shareholder_equity": "temporary_equity_attributable_to_parent", + "total_equity": "equity", + "total_liabilities_and_shareholders_equity": "liabilities_and_equity", "minority_interest": "equity_attributable_to_noncontrolling_interest", } @@ -66,25 +77,17 @@ class PolygonBalanceSheetFetcher( def transform_data( data: dict, ) -> List[PolygonBalanceSheetData]: - FIELDS = [ - "assets", - "current_assets", - "current_liabilities", - "equity", - "equity_attributable_to_noncontrolling_interest", - "equity_attributable_to_parent", - "liabilities", - "liabilities_and_equity", - "noncurrent_assets", - "noncurrent_liabilities", - ] + transformed_data = [] - to_return = [] for item in data: - new = {"start_date": item["start_date"], "cik": item["cik"]} - if bs := item["financials"]["balance_sheet"]: - for field in FIELDS: - new[field] = bs[field].get("value", 0) + sub_data = { + key: value["value"] + for key, value in item["financials"]["balance_sheet"].items() + } + sub_data["date"] = item["start_date"] + sub_data["cik"] = item["cik"] + sub_data["symbol"] = item["tickers"] + sub_data["period"] = item["fiscal_period"] + transformed_data.append(PolygonBalanceSheetData(**sub_data)) - to_return.append(PolygonBalanceSheetData(**new)) - return to_return + return transformed_data diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/cash_flow.py b/openbb_sdk/providers/polygon/openbb_polygon/models/cash_flow.py index d467ab9eae4..7b4ced4fbda 100644 --- a/openbb_sdk/providers/polygon/openbb_polygon/models/cash_flow.py +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/cash_flow.py @@ -1,28 +1,26 @@ from typing import Any, Dict, List, Optional from openbb_provider.abstract.fetcher import Fetcher -from openbb_provider.standard_models.cash_flows import CashFlowStatementData +from openbb_provider.standard_models.cash_flow import CashFlowStatementData from openbb_provider.utils.helpers import get_querystring from pydantic import validator from openbb_polygon.utils.helpers import get_data from openbb_polygon.utils.types import PolygonFundamentalQueryParams -# noqa: E501 - class PolygonCashFlowStatementQueryParams(PolygonFundamentalQueryParams): - __doc__ = PolygonFundamentalQueryParams.__doc__ + """Polygon Fundamental QueryParams. + + Source: https://polygon.io/docs/stocks#!/get_vx_reference_financials + """ class PolygonCashFlowStatementData(CashFlowStatementData): - """Cash Flow Statement Data.""" - - class Config: - fields = {"date": "start_date"} + """Return Balance Sheet Data.""" @validator("symbol", pre=True, check_fields=False) - def symbol_from_tickers(cls, v): + def symbol_from_tickers(cls, v): # pylint: disable=no-self-argument if isinstance(v, list): return ",".join(v) return v @@ -52,7 +50,7 @@ class PolygonCashFlowStatementFetcher( data = get_data(request_url, **kwargs)["results"] if len(data) == 0: - raise RuntimeError("No Cash Flow Statement found") + raise RuntimeError("No balance sheet found") return data @@ -60,23 +58,17 @@ class PolygonCashFlowStatementFetcher( def transform_data( data: dict, ) -> List[PolygonCashFlowStatementData]: - FIELDS = [ - "net_cash_flow_from_financing_activities", - "net_cash_flow_from_investing_activities", - "net_cash_flow_from_operating_activities", - "net_cash_flow_continuing", - "net_cash_flow_from_financing_activities_continuing", - "net_cash_flow_from_investing_activities_continuing", - "net_cash_flow_from_operating_activities_continuing", - "net_cash_flow", - ] + transformed_data = [] - to_return = [] for item in data: - new = {"start_date": item["start_date"], "cik": item["cik"]} - if cf := item["financials"]["cash_flow_statement"]: - for field in FIELDS: - new[field] = cf[field].get("value", 0) + sub_data = { + key: value["value"] + for key, value in item["financials"]["cash_flow_statement"].items() + } + sub_data["date"] = item["start_date"] + sub_data["cik"] = item["cik"] + sub_data["symbol"] = item["tickers"] + sub_data["period"] = item["fiscal_period"] + transformed_data.append(PolygonCashFlowStatementData(**sub_data)) - to_return.append(PolygonCashFlowStatementData(**new)) - return to_return + return transformed_data diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/crypto_historical.py b/openbb_sdk/providers/polygon/openbb_polygon/models/crypto_historical.py new file mode 100644 index 00000000000..5b2720df672 --- /dev/null +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/crypto_historical.py @@ -0,0 +1,112 @@ +"""Polygon crypto end of day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.crypto_historical import ( + CryptoHistoricalData, + CryptoHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, PositiveInt, validator + +from openbb_polygon.utils.helpers import get_data + + +class PolygonCryptoHistoricalQueryParams(CryptoHistoricalQueryParams): + """Polygon crypto end of day Query. + + Source: https://polygon.io/docs/crypto/get_v2_aggs_ticker__cryptoticker__range__multiplier___timespan___from___to + """ + + timespan: Literal[ + "minute", "hour", "day", "week", "month", "quarter", "year" + ] = Field(default="day", description="Timespan of the data.") + sort: Literal["asc", "desc"] = Field( + default="desc", description="Sort order of the data." + ) + limit: PositiveInt = Field( + default=49999, description=QUERY_DESCRIPTIONS.get("limit", "") + ) + adjusted: bool = Field(default=True, description="Whether the data is adjusted.") + multiplier: PositiveInt = Field( + default=1, description="Multiplier of the timespan." + ) + + +class PolygonCryptoHistoricalData(CryptoHistoricalData): + """Polygon crypto end of day Data.""" + + class Config: + fields = { + "date": "t", + "open": "o", + "high": "h", + "low": "l", + "close": "c", + "volume": "v", + "vwap": "vw", + } + + n: PositiveInt = Field( + description="Number of transactions for the symbol in the time period." + ) + + @validator("t", pre=True, check_fields=False) + def time_validate(cls, v): # pylint: disable=E0213 + return datetime.fromtimestamp(v / 1000) + + +class PolygonCryptoHistoricalFetcher( + Fetcher[ + PolygonCryptoHistoricalQueryParams, + List[PolygonCryptoHistoricalData], + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> PolygonCryptoHistoricalQueryParams: + now = datetime.now().date() + transformed_params = params + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + + if params.get("symbol"): + transformed_params["symbol"] = params["symbol"].replace("-", "") + + return PolygonCryptoHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: PolygonCryptoHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + api_key = credentials.get("polygon_api_key") if credentials else "" + + request_url = ( + f"https://api.polygon.io/v2/aggs/ticker/" + f"X:{query.symbol}/range/{query.multiplier}/{query.timespan}/" + f"{query.start_date}/{query.end_date}?adjusted={query.adjusted}" + f"&sort={query.sort}&limit={query.limit}&apiKey={api_key}" + ) + + data = get_data(request_url, **kwargs) + if isinstance(data, list): + raise ValueError("Expected a dict, got a list") + + if "results" not in data or len(data["results"]) == 0: + raise RuntimeError("No results found. Please change your query parameters.") + + return data + + @staticmethod + def transform_data(data: dict) -> List[PolygonCryptoHistoricalData]: + return [ + PolygonCryptoHistoricalData.parse_obj(d) for d in data.get("results", []) + ] diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/forex_historical.py b/openbb_sdk/providers/polygon/openbb_polygon/models/forex_historical.py new file mode 100644 index 00000000000..6965f075f11 --- /dev/null +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/forex_historical.py @@ -0,0 +1,109 @@ +"""Polygon forex end of day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.forex_historical import ( + ForexHistoricalData, + ForexHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, PositiveInt, validator + +from openbb_polygon.utils.helpers import get_data + + +class PolygonForexHistoricalQueryParams(ForexHistoricalQueryParams): + """Polygon forex end of day Query. + + Source: https://polygon.io/docs/forex/get_v2_aggs_ticker__forexticker__range__multiplier___timespan___from___to + """ + + timespan: Literal[ + "minute", "hour", "day", "week", "month", "quarter", "year" + ] = Field(default="day", description="Timespan of the data.") + sort: Literal["asc", "desc"] = Field( + default="desc", description="Sort order of the data." + ) + limit: PositiveInt = Field( + default=49999, description=QUERY_DESCRIPTIONS.get("limit", "") + ) + adjusted: bool = Field(default=True, description="Whether the data is adjusted.") + multiplier: PositiveInt = Field( + default=1, description="Multiplier of the timespan." + ) + + +class PolygonForexHistoricalData(ForexHistoricalData): + """Polygon forex end of day Data.""" + + class Config: + fields = { + "date": "t", + "open": "o", + "high": "h", + "low": "l", + "close": "c", + "volume": "v", + "vwap": "vw", + } + + n: PositiveInt = Field( + description="Number of transactions for the symbol in the time period." + ) + + @validator("t", pre=True, check_fields=False) + def time_validate(cls, v): # pylint: disable=E0213 + return datetime.fromtimestamp(v / 1000) + + +class PolygonForexHistoricalFetcher( + Fetcher[ + PolygonForexHistoricalQueryParams, + List[PolygonForexHistoricalData], + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> PolygonForexHistoricalQueryParams: + now = datetime.now().date() + transformed_params = params + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + + return PolygonForexHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: PolygonForexHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + api_key = credentials.get("polygon_api_key") if credentials else "" + + request_url = ( + f"https://api.polygon.io/v2/aggs/ticker/" + f"C:{query.symbol}/range/{query.multiplier}/{query.timespan}/" + f"{query.start_date}/{query.end_date}?adjusted={query.adjusted}" + f"&sort={query.sort}&limit={query.limit}&apiKey={api_key}" + ) + + data = get_data(request_url, **kwargs) + if isinstance(data, list): + raise ValueError("Expected a dict, got a list") + + if "results" not in data or len(data["results"]) == 0: + raise RuntimeError("No results found. Please change your query parameters.") + + return data + + @staticmethod + def transform_data(data: dict) -> List[PolygonForexHistoricalData]: + return [ + PolygonForexHistoricalData.parse_obj(d) for d in data.get("results", []) + ] diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/income_statement.py b/openbb_sdk/providers/polygon/openbb_polygon/models/income_statement.py index 043b2023e8b..137c562e4e4 100644 --- a/openbb_sdk/providers/polygon/openbb_polygon/models/income_statement.py +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/income_statement.py @@ -1,10 +1,9 @@ -from datetime import date as dateType from typing import Any, Dict, List, Optional from openbb_provider.abstract.fetcher import Fetcher from openbb_provider.standard_models.income_statement import IncomeStatementData from openbb_provider.utils.helpers import get_querystring -from pydantic import validator +from pydantic import Field, validator from openbb_polygon.utils.helpers import get_data from openbb_polygon.utils.types import PolygonFundamentalQueryParams @@ -17,35 +16,51 @@ class PolygonIncomeStatementQueryParams(PolygonFundamentalQueryParams): class PolygonIncomeStatementData(IncomeStatementData): class Config: fields = { - "date": "start_date", - "accepted_date": "acceptance_datetime", - "period": "fiscal_period", - "revenue": "revenues", - "operating_income": "operating_income_loss", - "income_before_tax": "income_loss_from_continuing_operations_before_tax", - "income_tax_expense": "income_tax_expense_benefit", - "net_income": "net_income_loss", - "eps": "basic_earnings_per_share", - "eps_diluted": "diluted_earnings_per_share", - "interest_expense": "interest_expense_operating", - "symbol": "tickers", + "revenue": "Revenues", + "cost_of_revenue": "Cost Of Revenue", + "gross_profit": "Gross Profit", + "cost_and_expenses": "Costs And Expenses", + "operating_expenses": "Operating Expenses", + "operating_income": "Operating Income/Loss", + "interest_expense": "Interest Expense, Operating", + "income_tax_expense": "Income Tax Expense/Benefit", + "net_income": "Net Income/Loss", + "eps": "Basic Earnings Per Share", + "eps_diluted": "Diluted Earnings Per Share", } - # tickers: Optional[List[str]] - cik: Optional[str] - filing_date: Optional[dateType] - cost_of_revenue: Optional[int] - gross_profit: Optional[int] - operating_expenses: Optional[int] - income_loss_from_continuing_operations_after_tax: Optional[float] - benefits_costs_expenses: Optional[float] - net_income_loss_attributable_to_noncontrolling_interest: Optional[int] - net_income_loss_attributable_to_parent: Optional[float] - net_income_loss_available_to_common_stockholders_basic: Optional[float] + income_loss_from_continuing_operations_before_tax: Optional[float] = Field( + description="Income/Loss From Continuing Operations After Tax" + ) + income_loss_from_continuing_operations_after_tax: Optional[float] = Field( + description="Income/Loss From Continuing Operations After Tax" + ) + benefits_costs_expenses: Optional[float] = Field( + description="Benefits, Costs And Expenses" + ) + net_income_loss_attributable_to_noncontrolling_interest: Optional[float] = Field( + description="Net Income/Loss Attributable To Noncontrolling Interest" + ) + net_income_loss_attributable_to_parent: Optional[float] = Field( + description="Net Income/Loss Attributable To Parent" + ) + income_tax_expense_benefit_deferred: Optional[float] = Field( + description="Income Tax Expense/Benefit Deferred" + ) participating_securities_distributed_and_undistributed_earnings_loss_basic: Optional[ float - ] - preferred_stock_dividends_and_other_adjustments: Optional[float] + ] = Field( + description="Participating Securities Distributed And Undistributed Earnings Loss Basic" + ) + net_income_loss_available_to_common_stockholders_basic: Optional[float] = Field( + description="Net Income/Loss Available To Common Stockholders Basic" + ) + nonoperating_income_loss: Optional[float] = Field( + description="Nonoperating Income Loss" + ) + preferred_stock_dividends_and_other_adjustments: Optional[float] = Field( + description="Preferred Stock Dividends And Other Adjustments" + ) @validator("symbol", pre=True, check_fields=False) def symbol_from_tickers(cls, v): # pylint: disable=E0213 @@ -86,39 +101,17 @@ class PolygonIncomeStatementFetcher( def transform_data( data: dict, ) -> List[PolygonIncomeStatementData]: - FIELDS = [ - "revenues", - "cost_of_revenue", - "gross_profit", - "operating_expenses" "income_loss_from_continuing_operations_before_tax", - "income_tax_expense_benefit", - "net_income_loss", - "basic_earnings_per_share", - "diluted_earnings_per_share", - "net_income_loss_attributable_to_noncontrolling_interest", - "net_income_loss_attributable_to_parent", - "net_income_loss_available_to_common_stockholders_basic", - "operating_income_loss", - "participating_securities_distributed_and_undistributed_earnings_loss_basic", - "preferred_stock_dividends_and_other_adjustments", - "income_loss_from_continuing_operations_after_tax", - "benefits_costs_expenses", - "interest_expense_operating", - ] + transformed_data = [] - to_return = [] for item in data: - new = {"acceptance_datetime": item.get("acceptance_datetime")} - new["start_date"] = item["start_date"] - new["filing_date"] = item.get("filing_date") - new["fiscal_period"] = item["fiscal_period"] - new["tickers"] = item["tickers"] - new["cik"] = item["cik"] - incs = item["financials"].get("income_statement", {}) + sub_data = { + key: value["value"] + for key, value in item["financials"]["income_statement"].items() + } + sub_data["date"] = item["start_date"] + sub_data["cik"] = item["cik"] + sub_data["symbol"] = item["tickers"] + sub_data["period"] = item["fiscal_period"] + transformed_data.append(PolygonIncomeStatementData(**sub_data)) - if incs: - for field in FIELDS: - new[field] = incs.get(field, {}).get("value", 0) - - to_return.append(PolygonIncomeStatementData(**new)) - return to_return + return transformed_data diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/major_indices_historical.py b/openbb_sdk/providers/polygon/openbb_polygon/models/major_indices_historical.py new file mode 100644 index 00000000000..cae8fe1fe35 --- /dev/null +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/major_indices_historical.py @@ -0,0 +1,107 @@ +"""Polygon major indices end of day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Literal, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.major_indices_historical import ( + MajorIndicesHistoricalData, + MajorIndicesHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, PositiveInt, validator + +from openbb_polygon.utils.helpers import get_data + + +class PolygonMajorIndicesHistoricalQueryParams(MajorIndicesHistoricalQueryParams): + """Polygon major indices end of day Query. + + Source: https://polygon.io/docs/indices/getting-started + """ + + timespan: Literal[ + "minute", "hour", "day", "week", "month", "quarter", "year" + ] = Field(default="day", description="Timespan of the data.") + sort: Literal["asc", "desc"] = Field( + default="desc", description="Sort order of the data." + ) + limit: PositiveInt = Field( + default=49999, description=QUERY_DESCRIPTIONS.get("limit", "") + ) + adjusted: bool = Field(default=True, description="Whether the data is adjusted.") + multiplier: PositiveInt = Field( + default=1, description="Multiplier of the timespan." + ) + + +class PolygonMajorIndicesHistoricalData(MajorIndicesHistoricalData): + """Polygon major indices end of day Data.""" + + class Config: + fields = { + "date": "t", + "open": "o", + "high": "h", + "low": "l", + "close": "c", + } + + @validator("t", pre=True, check_fields=False) + def time_validate(cls, v): # pylint: disable=E0213 + return datetime.fromtimestamp(v / 1000) + + +class PolygonMajorIndicesHistoricalFetcher( + Fetcher[ + PolygonMajorIndicesHistoricalQueryParams, + List[PolygonMajorIndicesHistoricalData], + ] +): + @staticmethod + def transform_query( + params: Dict[str, Any] + ) -> PolygonMajorIndicesHistoricalQueryParams: + now = datetime.now().date() + transformed_params = params + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return PolygonMajorIndicesHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: PolygonMajorIndicesHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + api_key = credentials.get("polygon_api_key") if credentials else "" + + request_url = ( + f"https://api.polygon.io/v2/aggs/ticker/" + f"I:{query.symbol}/range/{query.multiplier}/{query.timespan}/" + f"{query.start_date}/{query.end_date}?adjusted={query.adjusted}" + f"&sort={query.sort}&limit={query.limit}&apiKey={api_key}" + ) + + data = get_data(request_url, **kwargs) + if isinstance(data, list): + raise ValueError("Expected a dict, got a list") + + if "results" not in data or len(data["results"]) == 0: + raise RuntimeError("No results found. Please change your query parameters.") + + return data + + @staticmethod + def transform_data( + data: dict, + ) -> List[PolygonMajorIndicesHistoricalData]: + return [ + PolygonMajorIndicesHistoricalData.parse_obj(d) + for d in data.get("results", []) + ] diff --git a/openbb_sdk/providers/polygon/openbb_polygon/models/stock_historical.py b/openbb_sdk/providers/polygon/openbb_polygon/models/stock_historical.py new file mode 100644 index 00000000000..83467765fb6 --- /dev/null +++ b/openbb_sdk/providers/polygon/openbb_polygon/models/stock_historical.py @@ -0,0 +1,120 @@ +"""Polygon stocks end of day fetcher.""" + + +from concurrent.futures import ThreadPoolExecutor +from datetime import datetime +from itertools import repeat +from typing import Any, Dict, List, Literal, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_historical import ( + StockHistoricalData, + StockHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, PositiveInt, validator + +from openbb_polygon.utils.helpers import get_data + + +class PolygonStockHistoricalQueryParams(StockHistoricalQueryParams): + """Polygon stocks end of day Query. + + Source: https://polygon.io/docs/stocks/getting-started + """ + + timespan: Literal[ + "minute", "hour", "day", "week", "month", "quarter", "year" + ] = Field(default="day", description="Timespan of the data.") + sort: Literal["asc", "desc"] = Field( + default="desc", description="Sort order of the data." + ) + limit: PositiveInt = Field( + default=49999, description=QUERY_DESCRIPTIONS.get("limit", "") + ) + adjusted: bool = Field(default=True, description="Whether the data is adjusted.") + multiplier: PositiveInt = Field( + default=1, description="Multiplier of the timespan." + ) + + +class PolygonStockHistoricalData(StockHistoricalData): + """Polygon stocks end of day Data.""" + + class Config: + fields = { + "date": "t", + "open": "o", + "high": "h", + "low": "l", + "close": "c", + "volume": "v", + } + + vwap: Optional[float] = Field(description="The volume weighted average price.") + transactions: Optional[PositiveInt] = Field( + description="Number of transactions for the symbol in the time period.", + alias="n", + ) + + @validator("t", pre=True, check_fields=False) + def time_validate(cls, v): # pylint: disable=E0213 + return datetime.fromtimestamp(v / 1000) + + +class PolygonStockHistoricalFetcher( + Fetcher[ + PolygonStockHistoricalQueryParams, + List[PolygonStockHistoricalData], + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> PolygonStockHistoricalQueryParams: + now = datetime.now().date() + transformed_params = params + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return PolygonStockHistoricalQueryParams(**transformed_params) + + @staticmethod + def extract_data( + query: PolygonStockHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[dict]: + api_key = credentials.get("polygon_api_key") if credentials else "" + + data: list = [] + + def multiple_symbols( + symbol: str, data: List[PolygonStockHistoricalData] + ) -> None: + request_url = ( + f"https://api.polygon.io/v2/aggs/ticker/" + f"{symbol.upper()}/range/{query.multiplier}/{query.timespan}/" + f"{query.start_date}/{query.end_date}?adjusted={query.adjusted}" + f"&sort={query.sort}&limit={query.limit}&apiKey={api_key}" + ) + results = get_data(request_url, **kwargs).get("results", []) + + if "," in query.symbol: + results = [dict(symbol=symbol, **d) for d in results] + + return data.extend( + [PolygonStockHistoricalData.parse_obj(d) for d in results] + ) + + with ThreadPoolExecutor() as executor: + executor.map(multiple_symbols, query.symbol.split(","), repeat(data)) + + data.sort(key=lambda x: x.date) + + return data + + @staticmethod + def transform_data(data: List[dict]) -> List[PolygonStockHistoricalData]: + return [PolygonStockHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/quandl/README.md b/openbb_sdk/providers/quandl/README.md new file mode 100644 index 00000000000..3847a42c4df --- /dev/null +++ b/openbb_sdk/providers/quandl/README.md @@ -0,0 +1,11 @@ +# OpenBB Quandl Provider + +This extension integrates the Quandl data provider into the OpenBB SDK. + +## Installation + +To install the extension, run the following command in this folder: + +```bash +pip install . +``` diff --git a/openbb_sdk/providers/quandl/openbb_quandl/__init__.py b/openbb_sdk/providers/quandl/openbb_quandl/__init__.py new file mode 100644 index 00000000000..0b4101e7ad7 --- /dev/null +++ b/openbb_sdk/providers/quandl/openbb_quandl/__init__.py @@ -0,0 +1,23 @@ +"""quandl provider module.""" +from openbb_provider.abstract.provider import Provider + +from openbb_quandl.models.cot import QuandlCotFetcher +from openbb_quandl.models.cot_search import QuandlCotSearchFetcher +from openbb_quandl.models.sp500_multiples import QuandlSP500MultiplesFetcher + +quandl_provider = Provider( + name="quandl", + website="data.nasdaq.com/publishers/qdl", + description="""Quandl is a premier publisher of alternative data for institutional investors. + A dedicated team of data scientists, quants and engineers combine uncompromising curation, + high quality standards and experienced data science application to provide some of the most powerful data available + today. Quandl also publishes free data, scraped from the web and delivered via Nasdaq Data Link's + industry-leading data delivery platform. + """, + required_credentials=["api_key"], + fetcher_dict={ + "SP500Multiples": QuandlSP500MultiplesFetcher, + "COT": QuandlCotFetcher, + "COTSearch": QuandlCotSearchFetcher, + }, +) diff --git a/openbb_sdk/providers/quandl/openbb_quandl/models/__init__.py b/openbb_sdk/providers/quandl/openbb_quandl/models/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/quandl/openbb_quandl/models/cot.py b/openbb_sdk/providers/quandl/openbb_quandl/models/cot.py new file mode 100644 index 00000000000..280e74bb62b --- /dev/null +++ b/openbb_sdk/providers/quandl/openbb_quandl/models/cot.py @@ -0,0 +1,192 @@ +"""CFTC Commitment of Traders Reports fetcher.""" + +from datetime import ( + date as dateType, + datetime, +) +from typing import Any, Dict, List, Literal, Optional + +import pandas as pd +import quandl +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.utils.helpers import to_snake_case +from pydantic import Field, validator + +from openbb_quandl.utils.series_ids import CFTC + + +class QuandlCotQueryParams(QueryParams): + """Get CFTC Commitment of Traders Report. + + Source: https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports/documentation + + Not all combinations of parameters and underlying assets are valid, bad combinations will return an error. + """ + + code: str = Field( + description=""" + CFTC series code. Use search_cot() to find the code. + Codes not listed in the curated list, but are published by on the Nasdaq Data Link website, are valid. + Certain symbols, such as "ES=F", or exact names are also valid. + Default report is: S&P 500 Consolidated (CME)) + """, + default="13874P", + ) + data_type: Optional[Literal["F", "FO", "CITS"]] = Field( + description=""" + The type of data to reuturn. Default is "FO". + + F = Futures only + + FO = Futures and Options + + CITS = Commodity Index Trader Supplemental. Only valid for commodities. + """, + default="FO", + ) + legacy_format: Optional[bool] = Field( + description="Returns the legacy format of report. Default is False.", + default=False, + ) + report_type: Optional[Literal["ALL", "CHG", "OLD", "OTR"]] = Field( + description=""" + The type of report to return. Default is "ALL". + + ALL = All + + CHG = Change in Positions + + OLD = Old Crop Years + + OTR = Other Crop Years + """, + default="ALL", + ) + measure: Optional[Literal["CR", "NT", "OI", "CHG"]] = Field( + description=""" + The measure to return. Default is None. + + CR = Concentration Ratios + + NT = Number of Traders + + OI = Percent of Open Interest + + CHG = Change in Positions. Only valid when data_type is "CITS". + """, + default=None, + ) + start_date: Optional[dateType] = Field( + description="The start date of the time series. Defaults to all.", default=None + ) + end_date: Optional[dateType] = Field( + description="The end date of the time series. Defaults to the most recent data.", + default=None, + ) + transform: Optional[Literal["diff", "rdiff", "cumul", "normalize"]] = Field( + description="Transform the data as w/w difference, percent change, cumulative, or normalize.", + default=None, + ) + + +class QuandlCotData(Data): + """Quandl CFTC Commitment of Traders Reports data. + + Returns + ------- + List[Dict] + Columns in the response object will change according to the parameters and underlying asset. + """ + + @validator("date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return the datetime object from the date string""" + + return datetime.strptime(v, "%Y-%m-%d").date() + + +class QuandlCotFetcher(Fetcher[QuandlCotQueryParams, List[QuandlCotData]]): + """Quandl CFTC Commitment of Traders Reports Fetcher.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> QuandlCotQueryParams: + return QuandlCotQueryParams(**params) + + @staticmethod + def extract_data( + query: QuandlCotQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + api_key = credentials.get("quandl_api_key") if credentials else "" + + # The "code" can be an exact name, a symbol, or a CFTC series code. + series_id: str = "" + series_ids = pd.DataFrame(CFTC).transpose().reset_index(drop=True) + series_ids.columns = series_ids.columns.str.lower() + + if query.code in series_ids["code"].values: + series_id = query.code + + if query.code not in series_ids["code"].values: + if query.code in series_ids["symbol"].values: + series_id = series_ids.loc[ + series_ids["symbol"] == query.code, "code" + ].values[0] + if query.code in series_ids["name"].values: + series_id = series_ids.loc[ + series_ids["name"] == query.code, "code" + ].values[0] + # Allows for strings not found in the curated list. + if ( + query.code not in series_ids["code"].values + and query.code not in series_ids["symbol"].values + and query.code not in series_ids["name"].values + ): + series_id = query.code + + # The "quandl_code" gets parsed conditionally for the parameters. + quandl_code = f"CFTC/{series_id}" + + if query.data_type: + quandl_code = f"{quandl_code}_{query.data_type}" + + if query.legacy_format is False and query.data_type != "CITS": + quandl_code = f"{quandl_code}_L" + + if query.report_type: + quandl_code = f"{quandl_code}_{query.report_type}" + + if query.measure is not None: + quandl_code = f"{quandl_code}_{query.measure}" + + try: + data = quandl.get( + quandl_code, + start_date=query.start_date, + end_date=query.end_date, + transform=query.transform, + api_key=api_key, + ).reset_index() + data.columns = [ + to_snake_case(c) + .replace(" ", "") + .replace("-", "") + .replace("%", "_%_") + .replace("o_i", "oi") + .replace(";", "") + for c in data.columns + ] + data["date"] = data["date"].astype(str) + return data.to_dict("records") + + except Exception as e: + raise RuntimeError(e) + + @staticmethod + def transform_data( + data: List[Dict], + ) -> List[QuandlCotData]: + return [QuandlCotData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/quandl/openbb_quandl/models/cot_search.py b/openbb_sdk/providers/quandl/openbb_quandl/models/cot_search.py new file mode 100644 index 00000000000..805c45b90f5 --- /dev/null +++ b/openbb_sdk/providers/quandl/openbb_quandl/models/cot_search.py @@ -0,0 +1,58 @@ +"""CFTC Commitment of Traders Reports Search fetcher.""" + +from typing import Any, Dict, List, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.cot_search import ( + CotSearchData, + CotSearchQueryParams, +) + +from openbb_quandl.utils.series_ids import CFTC + + +class QuandlCotSearchQueryParams(CotSearchQueryParams): + """CFTC Commitment of Traders Reports Search query parameters. + + Source: https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports/documentation + """ + + +class QuandlCotSearchData(CotSearchData): + """Quandl CFTC Commitment of Traders Reports Search data.""" + + +class QuandlCotSearchFetcher(Fetcher[CotSearchQueryParams, List[QuandlCotSearchData]]): + """Quandl CFTC Commitment of Traders Reports Search Fetcher.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> QuandlCotSearchQueryParams: + return QuandlCotSearchQueryParams(**params) + + @staticmethod + def extract_data( + query: QuandlCotSearchQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any + ) -> List[Dict]: + """Search a curated list of CFTC Commitment of Traders Reports.""" + query_string = query.query # noqa + available_cot = pd.DataFrame(CFTC).transpose() + available_cot.columns = available_cot.columns.str.lower() + return ( + available_cot.query( + "name.str.contains(@query_string, case=False)" + "| category.str.contains(@query_string, case=False)" + "| subcategory.str.contains(@query_string, case=False)" + "| symbol.str.contains(@query_string, case=False)" + ) + .reset_index(drop=True) + .to_dict("records") + ) + + @staticmethod + def transform_data( + data: List[Dict], + ) -> List[QuandlCotSearchData]: + return [QuandlCotSearchData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/quandl/openbb_quandl/models/sp500_multiples.py b/openbb_sdk/providers/quandl/openbb_quandl/models/sp500_multiples.py new file mode 100644 index 00000000000..5354c585d4c --- /dev/null +++ b/openbb_sdk/providers/quandl/openbb_quandl/models/sp500_multiples.py @@ -0,0 +1,69 @@ +"""Quandl SP500 Multiples Fetcher.""" + +from typing import Any, Dict, List, Optional + +import quandl +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.sp500_multiples import ( + SP500MultiplesData, + SP500MultiplesQueryParams, +) + +from openbb_quandl.utils.series_ids import SP500MULTIPLES + + +class QuandlSP500MultiplesQueryParams(SP500MultiplesQueryParams): + """SP500 Multiples query.""" + + +class QuandlSP500MultiplesData(SP500MultiplesData): + """SP500 Multiples data.""" + + +class QuandlSP500MultiplesFetcher( + Fetcher[SP500MultiplesQueryParams, SP500MultiplesData] +): + """Quandl SP500 Multiples Fetcher.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> QuandlSP500MultiplesQueryParams: + return QuandlSP500MultiplesQueryParams(**params) + + @staticmethod + def extract_data( + query: QuandlSP500MultiplesQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any + ) -> List[QuandlSP500MultiplesData]: + """Gets the raw Quandl Data.""" + + api_key = credentials.get("quandl_api_key") if credentials else "" + + if "Year" in query.series_name: + query.collapse = "annual" + if "Quarter" in query.series_name: + query.collapse = "quarterly" + + data = ( + quandl.get( + SP500MULTIPLES[query.series_name], + start_date=query.start_date, + end_date=query.end_date, + collapse=query.collapse, + transform=query.transform, + api_key=api_key, + **kwargs, + ) + .reset_index() + .rename(columns={"Date": "date", "Value": "value"}) + ) + data["date"] = data["date"].dt.strftime("%Y-%m-%d") + + return data.to_dict("records") + + @staticmethod + def transform_data( + data: List[Dict], + ) -> List[QuandlSP500MultiplesData]: + """Parse data into the QuandlSP500MultiplesData format.""" + return [QuandlSP500MultiplesData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/quandl/openbb_quandl/utils/__init__.py b/openbb_sdk/providers/quandl/openbb_quandl/utils/__init__.py new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/quandl/openbb_quandl/utils/series_ids.py b/openbb_sdk/providers/quandl/openbb_quandl/utils/series_ids.py new file mode 100644 index 00000000000..802dbdba6a1 --- /dev/null +++ b/openbb_sdk/providers/quandl/openbb_quandl/utils/series_ids.py @@ -0,0 +1,1044 @@ +"""Series ID Dictionaries for Quandl Provider.""" + +SP500MULTIPLES = { + "Shiller PE Ratio by Month": "MULTPL/SHILLER_PE_RATIO_MONTH", + "Shiller PE Ratio by Year": "MULTPL/SHILLER_PE_RATIO_YEAR", + "PE Ratio by Year": "MULTPL/SP500_PE_RATIO_YEAR", + "PE Ratio by Month": "MULTPL/SP500_PE_RATIO_MONTH", + "Dividend by Year": "MULTPL/SP500_DIV_YEAR", + "Dividend by Month": "MULTPL/SP500_DIV_MONTH", + "Dividend Growth by Quarter": "MULTPL/SP500_DIV_GROWTH_QUARTER", + "Dividend Growth by Year": "MULTPL/SP500_DIV_GROWTH_YEAR", + "Dividend Yield by Year": "MULTPL/SP500_DIV_YIELD_YEAR", + "Dividend Yield by Month": "MULTPL/SP500_DIV_YIELD_MONTH", + "Earnings by Year": "MULTPL/SP500_EARNINGS_YEAR", + "Earnings by Month": "MULTPL/SP500_EARNINGS_MONTH", + "Earnings Growth by Year": "MULTPL/SP500_EARNINGS_GROWTH_YEAR", + "Earnings Growth by Quarter": "MULTPL/SP500_EARNINGS_GROWTH_QUARTER", + "Real Earnings Growth by Year": "MULTPL/SP500_REAL_EARNINGS_GROWTH_YEAR", + "Real Earnings Growth by Quarter": "MULTPL/SP500_REAL_EARNINGS_GROWTH_QUARTER", + "Earnings Yield by Year": "MULTPL/SP500_EARNINGS_YIELD_YEAR", + "Earnings Yield by Month": "MULTPL/SP500_EARNINGS_YIELD_MONTH", + "Real Price by Year": "MULTPL/SP500_REAL_PRICE_YEAR", + "Real Price by Month": "MULTPL/SP500_REAL_PRICE_MONTH", + "Inflation Adjusted Price by Year": "MULTPL/SP500_INFLADJ_YEAR", + "Inflation Adjusted Price by Month": "MULTPL/SP500_INFLADJ_MONTH", + "Sales by Year": "MULTPL/SP500_SALES_YEAR", + "Sales by Quarter": "MULTPL/SP500_SALES_QUARTER", + "Sales Growth by Year": "MULTPL/SP500_SALES_GROWTH_YEAR", + "Sales Growth by Quarter": "MULTPL/SP500_SALES_GROWTH_Quarter", + "Real Sales by Year": "MULTPL/SP500_REAL_SALES_YEAR", + "Real Sales by Quarter": "MULTPL/SP500_REAL_SALES_QUARTER", + "Real Sales Growth by Year": "MULTPL/SP500_REAL_SALES_GROWTH_YEAR", + "Real Sales Growth by Quarter": "MULTPL/SP500_REAL_SALES_GROWTH_QUARTER", + "Price to Sales Ratio by Year": "MULTPL/SP500_PSR_YEAR", + "Price to Sales Ratio by Quarter": "MULTPL/SP500_PSR_QUARTER", + "Price to Book Value Ratio by Year": "MULTPL/SP500_PBV_RATIO_YEAR", + "Price to Book Value Ratio by Quarter": "MULTPL/SP500_PBV_RATIO_QUARTER", + "Book Value per Share by Year": "MULTPL/SP500_BVPS_YEAR", + "Book Value per Share by Quarter": "MULTPL/SP500_BVPS_QUARTER", +} + + +CFTC = { + "098662": { + "Name": "USD Index (ICUS)", + "Category": "Currencies", + "Subcategory": "US Dollar Index", + "Units": "U.S. Dollar Index x $1000", + "Code": "098662", + "Symbol": "DX=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=098662", + "Specs": "https://www.theice.com/products/194/US-Dollar-Index-Futures", + }, + "045601": { + "Name": "Fed Funds (CBT)", + "Category": "Interest", + "Subcategory": "Treasuries", + "Units": "Contracts of $5,000,000", + "Code": "045601", + "Symbol": "ZQ=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=045601", + "Specs": "https://www.cmegroup.com/markets/interest-rates/stirs/30-day-federal-fund.contractSpecs.html", + }, + "020604": { + "Name": "Ultra US Treasury Bond (CBT)", + "Category": "Interest", + "Subcategory": "Treasuries", + "Units": "Contracts of $100,000", + "Code": "020604", + "Symbol": "UB=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=020604", + "Specs": "https://www.cmegroup.com/markets/interest-rates/us-treasury/ultra-t-bond.contractSpecs.options.html", + }, + "042601": { + "Name": "Two-Year Treasury Note Futures (CBT)", + "Category": "Interest", + "Subcategory": "Treasuries", + "Units": "Contracts of $200,000 Face Value", + "Code": "042601", + "Symbol": "ZT=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=042601", + "Specs": "https://www.cmegroup.com/markets/interest-rates/us-treasury/2-year-us-treasury-note.contractSpecs.html", + }, + "044601": { + "Name": "Five-Year Treasury Note Futures (CBT)", + "Category": "Interest", + "Subcategory": "Treasuries", + "Units": "Contracts of $100,000 Face Value", + "Code": "044601", + "Symbol": "ZF=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=044601", + "Specs": "https://www.cmegroup.com/markets/interest-rates/us-treasury/5-year-us-treasury-note.contractSpecs.html", + }, + "043602": { + "Name": "Ten-Year Treasury Note Futures (CBT)", + "Category": "Interest", + "Subcategory": "Treasuries", + "Units": "Contracts of $100,000 Face Value", + "Code": "043602", + "Symbol": "ZN=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=043602", + "Specs": "https://www.cmegroup.com/markets/interest-rates/us-treasury/10-year-us-treasury-note.contractSpecs.html", # noqa + }, + "043607": { + "Name": "Ultra Ten-Year US Treasury Note (CBT)", + "Category": "Interest", + "Subcategory": "Treasuries", + "Units": "Contracts of $100,000 Face Value", + "Code": "043607", + "Symbol": "TN=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=043607", + "Specs": "https://www.cmegroup.com/markets/interest-rates/us-treasury/ultra-10-year-us-treasury-note.contractSpecs.html", # noqa + }, + "13874P": { + "Name": "S&P 500 Consolidated (CME)", + "Category": "Index", + "Subcategory": "S&P 500", + "Units": "S&P 500 Index X $250", + "Code": "13874P", + "Symbol": "^GSPC", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=13874P", + "Specs": "https://www.cmegroup.com/trading/equity-index/us-index/sp-index-futures-and-options.html", + }, + "13874N": { + "Name": "S&P 500 Total Return Index (CME)", + "Category": "Index", + "Subcategory": "S&P 500", + "Units": "S&P 500 Index X $25", + "Code": "13874N", + "Symbol": "^SP500TR", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=13874N", + "Specs": "https://www.cmegroup.com/markets/equities/sp/sp-500-total-return.contractSpecs.html", + }, + "13874W": { + "Name": "AIR S&P 500 Total Return Index (CME)", + "Category": "Index", + "Subcategory": "S&P 500", + "Units": "AIR S&P 500 Index X $25", + "Code": "13874W", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=13874W", + "Specs": "https://www.cmegroup.com/markets/equities/sp/adjusted-interest-rate-sp500-total-return.contractSpecs.html", # noqa + }, + "13874A": { + "Name": "E-Mini S&P 500 Index (CME)", + "Category": "Index", + "Subcategory": "S&P 500", + "Units": "S&P 500 Index X $50", + "Code": "13874A", + "Symbol": "ES=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=13874A", + "Specs": "https://www.cmegroup.com/markets/equities/sp/e-mini-sandp500.contractSpecs.html", + }, + "13874U": { + "Name": "Micro E-Mini S&P 500 Index (CME)", + "Category": "Index", + "Subcategory": "S&P 500", + "Units": "S&P 500 Index X $5", + "Code": "13874U", + "Symbol": "MES=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=13874U", + "Specs": "https://www.cmegroup.com/markets/equities/sp/e-mini-sandp500.contractSpecs.html", + }, + "20974P": { + "Name": "NASDAQ 100 Consolidated (CME)", + "Category": "Index", + "Subcategory": "NASDAQ", + "Units": "NASDAQ 100 Index X $100", + "Code": "20974P", + "Symbol": "^NDX", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=20974P", + "Specs": "https://www.cmegroup.com/trading/equity-index/nasdaq-index-futures-and-options.html", + }, + "209742": { + "Name": "E-Mini NASDAQ 100 Index (CME)", + "Category": "Index", + "Subcategory": "NASDAQ", + "Units": "NASDAQ 100 Index X $20", + "Code": "209742", + "Symbol": "NQ=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=209742", + "Specs": "https://www.cmegroup.com/markets/equities/nasdaq/e-mini-nasdaq-100.contractSpecs.html", + }, + "209747": { + "Name": "Micro E-Mini NASDAQ 100 Index (CME)", + "Category": "Index", + "Subcategory": "NASDAQ", + "Units": "NASDAQ 100 Index X $2", + "Code": "209747", + "Symbol": "MNQ=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=209747", + "Specs": "https://www.cmegroup.com/markets/equities/nasdaq/micro-e-mini-nasdaq-100.contractSpecs.html", + }, + "12460P": { + "Name": "DJIA Consolidated (CBT)", + "Category": "Index", + "Subcategory": "Dow Jones", + "Units": "Dow Jones Index X $10", + "Code": "12460P", + "Symbol": "^DJI", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=12460P", + "Specs": "https://www.cmegroup.com/markets/products.html#assetClass=4&search=dow%20jones", + }, + "124603": { + "Name": "E-Mini Dow Jones (CBT)", + "Category": "Index", + "Subcategory": "Dow Jones", + "Units": "Dow Jones Index X $5", + "Code": "124603", + "Symbol": "YM=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=124603", + "Specs": "https://www.cmegroup.com/markets/equities/dow-jones/e-mini-dow.contractSpecs.html", + }, + "124606": { + "Name": "Dow Jones U.S. Real Estate Index (CBT)", + "Category": "Index", + "Subcategory": "Dow Jones", + "Units": "DJ US Real Estate Index X $100", + "Code": "124606", + "Symbol": "RX=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=124606", + "Specs": "https://www.cmegroup.com/markets/equities/dow-jones/dow-jones-rei.contractSpecs.html", + }, + "239742": { + "Name": "E-Mini Russell 2000 Index (CME)", + "Category": "Index", + "Subcategory": "Russell", + "Units": "Russell 2000 Index X $50", + "Code": "239742", + "Symbol": "RTY=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=239742", + "Specs": "https://www.cmegroup.com/markets/equities/russell/e-mini-russell-2000.contractSpecs.html", + }, + "239744": { + "Name": "E-Mini Russell 1000 Value Index (CME)", + "Category": "Index", + "Subcategory": "Russell", + "Units": "Russell 1000 Value Index X $50", + "Code": "239744", + "Symbol": "RSV=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=239744", + "Specs": "https://www.cmegroup.com/markets/equities/russell/e-mini-russell-1000-value-index.contractSpecs.html", + }, + "1170E1": { + "Name": "VIX Futures (CBOE)", + "Category": "Index", + "Subcategory": "VIX", + "Units": "VIX Index X $1000", + "Code": "1170E1", + "Symbol": "^VIX", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=1170E1", + "Specs": "https://www.cboe.com/tradable_products/vix/vix_futures/specifications/", + }, + "221602": { + "Name": "Bloomberg Commodity Index (CBT)", + "Category": "Index", + "Subcategory": "Commodities", + "Units": "Index X $100", + "Code": "221602", + "Symbol": "AW=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=221602", + "Specs": "https://www.cmegroup.com/markets/agriculture/commodity-indices/bloomberg-commodity-index.contractSpecs.html", # noqa + }, + "0233AN": { + "Name": "Michon Financial Index", + "Category": "Index", + "Subcategory": "Commodities", + "Units": "Contract size: 2500 MMBTus", + "Code": "0233AN", + "Symbol": "NGT=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=0233AN", + "Specs": "https://www.theice.com/products/6590188/Michcon-Index-Future", + }, + "02339Q": { + "Name": "Chicago Citygate Index", + "Category": "Energy", + "Subcategory": "Natural Gas", + "Units": "Contract size: 2500 MMBTus", + "Code": "02339Q", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=02339Q", + "Specs": "https://www.theice.com/products/6590179/Chicago-Index-Future", + }, + "02339U": { + "Name": "CIG Rockies Basis", + "Category": "Energy", + "Subcategory": "Natural Gas", + "Units": "Contract size: 2500 MMBTus", + "Code": "02339U", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=02339U", + "Specs": "https://www.theice.com/products/6590129/CIG-Rockies-Basis-Future", + }, + "0233A2": { + "Name": "DOMINION SOUTH POINT", + "Category": "Energy", + "Subcategory": "Natural Gas", + "Units": "Contract size: 2500 MMBTus", + "Code": "0233A2", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=0233A2", + "Specs": "https://www.theice.com/products/6590181/Eastern-Gas-South-Index-Future", + }, + "244041": { + "Name": "MSCI EAFE (ICUS)", + "Category": "Index", + "Subcategory": "MSCI", + "Units": "MSCI EAFE Index Level X $50 USD", + "Code": "244041", + "Symbol": "MFS=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=244041", + "Specs": "https://www.theice.com/products/31196848/MSCI-EAFE-Index-Future", + }, + "244042": { + "Name": "MSCI EM Index (ICUS)", + "Category": "Index", + "Subcategory": "MSCI", + "Units": "MSCI Emerging Markets Index X $50 USD", + "Code": "244042", + "Symbol": "MME=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=244042", + "Specs": "https://www.theice.com/products/31196851/MSCI-Emerging-Markets-Index-Future", + }, + "0063DA": { + "Name": "PA Solar Alternative Energy Credit Future (IFED)", + "Category": "Energy", + "Subcategory": "Renewables", + "Units": "10 MWh representing 10 Qualifying SRECs", + "Code": "0063DA", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=0063DA", + "Specs": "https://www.theice.com/products/65898879/Pennsylvania-Solar-Alternative-Energy-Credit-Future", + }, + "075651": { + "Name": "Palladium Futures (NYME)", + "Category": "Metals", + "Subcategory": "Palladium", + "Units": "Contracts of 100 Troy Ounces", + "Code": "075651", + "Symbol": "PA=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=075651", + "Specs": "https://www.cmegroup.com/trading/metals/precious/palladium_contractSpecs_futures.html", + }, + "076651": { + "Name": "Platinum Futures (NYME)", + "Category": "Metals", + "Subcategory": "Platinum", + "Units": "Contracts of 50 Troy Ounces", + "Code": "076651", + "Symbol": "PL=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=076651", + "Specs": "https://www.cmegroup.com/trading/metals/precious/platinum_contractSpecs_futures.html", + }, + "085692": { + "Name": "Copper #1 Futures (CMX)", + "Category": "Metals", + "Subcategory": "Copper", + "Units": "Contracts of 25,000 pounds", + "Code": "085692", + "Symbol": "HG=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=085692", + "Specs": "https://www.cmegroup.com/markets/metals/base/copper.contractSpecs.html", + }, + "191693": { + "Name": "Aluminum MWP Futures (CMX)", + "Category": "Metals", + "Subcategory": "Aluminum", + "Units": "Contracts of 25 Metric Tonnes (55,116 pounds)", + "Code": "191693", + "Symbol": "ALI=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=191693", + "Specs": "https://www.cmegroup.com/markets/metals/base/aluminum.contractSpecs.html", + }, + "088691": { + "Name": "Gold Futures (CMX)", + "Category": "Metals", + "Subcategory": "Gold", + "Units": "Contracts of 100 Troy Ounces", + "Code": "088691", + "Symbol": "GC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=088691", + "Specs": "https://www.cmegroup.com/markets/metals/precious/gold.contractSpecs.html", + }, + "088695": { + "Name": "Micro Gold Futures (CMX)", + "Category": "Metals", + "Subcategory": "Gold", + "Units": "Contracts of 10 Troy Ounces", + "Code": "088695", + "Symbol": "MGC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=088695", + "Specs": "https://www.cmegroup.com/markets/metals/precious/e-micro-gold.contractSpecs.html", + }, + "084691": { + "Name": "Silver Futures (CMX)", + "Category": "Metals", + "Subcategory": "Silver", + "Units": "Contracts of 5,000 Troy Ounces", + "Code": "084691", + "Symbol": "SI=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=084691", + "Specs": "https://www.cmegroup.com/markets/metals/precious/silver.contractSpecs.html", + }, + "00665T": { + "Name": "Mini-Silver Futures (ICUS)", + "Category": "Metals", + "Subcategory": "Silver", + "Units": "Contracts of 1,000 Troy Ounces", + "Code": "00665T", + "Symbol": "YI=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=00665T", + "Specs": "https://www.theice.com/products/31500923/Mini-Silver-Future", + }, + "073732": { + "Name": "Cocoa Futures (ICUS)", + "Category": "Agriculture", + "Subcategory": "Cocoa", + "Units": "Contracts of 10 Metric Tonnes", + "Code": "073732", + "Symbol": "CC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=073732", + "Specs": "https://www.theice.com/products/7/Cocoa-Futures", + }, + "135731": { + "Name": "Canola Futures (ICUS)", + "Category": "Agriculture", + "Subcategory": "Canola", + "Units": "Contracts of 20 Metric Tonnes", + "Code": "135731", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=135731", + "Specs": "https://www.theice.com/products/251/Canola-Futures", + }, + "058643": { + "Name": "Random Length Lumber Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Lumber", + "Units": "Contracts of 110,000 Board Feet", + "Code": "058643", + "Symbol": "LBS=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=058643", + "Specs": "https://www.cmegroup.com/markets/agriculture/lumber-and-softs/random-length-lumber.contractSpecs.html", + }, + "033661": { + "Name": "Cotton #2 Futures (ICUS)", + "Category": "Agriculture", + "Subcategory": "Cotton", + "Units": "Contracts of 50,000 pounds", + "Code": "033661", + "Symbol": "CT=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=033661", + "Specs": "https://www.theice.com/products/254/Cotton-No-2-Futures", + }, + "040701": { + "Name": "Frozen Concentrated Orange Juice Futures (ICUS)", + "Category": "Agriculture", + "Subcategory": "OJ", + "Units": "Contracts of 15,000 pounds", + "Code": "040701", + "Symbol": "OJ=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=040701", + "Specs": "https://www.theice.com/products/30/FCOJ-A-Futures", + }, + "083731": { + "Name": "Coffee Futures (ICUS)", + "Category": "Agriculture", + "Subcategory": "Coffee", + "Units": "Contracts of 37,500 pounds", + "Code": "083731", + "Symbol": "KC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=083731", + "Specs": "https://www.theice.com/products/15/Coffee-C-Futures", + }, + "083736": { + "Name": "Coffee Calendar Spread Options (ICUS)", + "Category": "Agriculture", + "Subcategory": "Coffee", + "Units": "Contracts of 37,500 pounds", + "Code": "083736", + "Symbol": "KC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=083736", + "Specs": "https://www.theice.com/products/67445363/Coffee-C-1-Month-Calendar-Spread-Option", + }, + "080732": { + "Name": "Sugar #11 Futures (ICUS)", + "Category": "Agriculture", + "Subcategory": "Sugar", + "Units": "Contracts of 112,000 pounds", + "Code": "080732", + "Symbol": "SF=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=080732", + "Specs": "https://www.theice.com/products/23/Sugar-No-11-Futures", + }, + "052645": { + "Name": "Dry Whey Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Dairy", + "Units": "Contracts of 44,000 pounds", + "Code": "052645", + "Symbol": "DY=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=052645", + "Specs": "https://www.cmegroup.com/markets/agriculture/dairy/dry-whey.contractSpecs.html", + }, + "005602": { + "Name": "Soybeans Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Soy", + "Units": "Contracts of 5,000 bushels", + "Code": "005602", + "Symbol": "ZS=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=005602", + "Specs": "https://www.cmegroup.com/markets/agriculture/oilseeds/soybean.contractSpecs.html", + }, + "005603": { + "Name": "Mini Soybeans Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Soy", + "Units": "Contracts of 1,000 bushels", + "Code": "005603", + "Symbol": "XK=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=005603", + "Specs": "https://www.cmegroup.com/markets/agriculture/oilseeds/mini-sized-soybean.contractSpecs.html", + }, + "026603": { + "Name": "Soybean Meal Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Soy", + "Units": "Contracts of 100 short tons", + "Code": "026603", + "Symbol": "ZM=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=026603", + "Specs": "https://www.cmegroup.com/markets/agriculture/oilseeds/soybean-meal.contractSpecs.html", + }, + "256741": { + "Name": "S&P GSCI Commodity Index Futures (CBT)", + "Category": "Index", + "Subcategory": "Commodities", + "Units": "GSCI X $250", + "Code": "256741", + "Symbol": "GD=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=256741", + "Specs": "https://www.cmegroup.com/markets/agriculture/commodity-indices/gsci.contractSpecs.html", + }, + "007601": { + "Name": "Soybean Oil Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Soy", + "Units": "Contracts of 60,000 pounds", + "Code": "007601", + "Symbol": "ZL=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=007601", + "Specs": "https://www.cmegroup.com/markets/agriculture/oilseeds/soybean-oil.contractSpecs.html", + }, + "001612": { + "Name": "Commitment of Traders - KC HRW Wheat Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Grains", + "Units": "Contracts of 5,000 Bushels", + "Code": "001612", + "Symbol": "KE=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=001612", + "Specs": "https://www.cmegroup.com/markets/agriculture/grains/kc-wheat.contractSpecs.html", + }, + "001626": { + "Name": "Commitment of Traders - KC HRSpring Wheat Futures (MGE)", + "Category": "Agriculture", + "Subcategory": "Grains", + "Units": "Contracts of 5,000 Bushels", + "Code": "001626", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=001626", + "Specs": "https://www.mgex.com/quotes.html?j1_module=futureDetail&j1_symbol=MW%2A1&j1_region=US&j1_selected=futureProfile", # noqa + }, + "001602": { + "Name": "Commitment of Traders - Chicago SRW Wheat Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Grains", + "Units": "Contracts of 5,000 Bushels", + "Code": "001602", + "Symbol": "ZW=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=001602", + "Specs": "https://www.cmegroup.com/markets/agriculture/grains/wheat.contractSpecs.html", + }, + "004603": { + "Name": "Oats Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Grains", + "Units": "Contracts of 5,000 Bushels", + "Code": "004603", + "Symbol": "ZO=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=004603", + "Specs": "https://www.cmegroup.com/markets/agriculture/grains/oats.contractSpecs.html", + }, + "039601": { + "Name": "Rought Rice Futures (CBT)", + "Category": "Agriculture", + "Subcategory": "Grains", + "Units": "Contracts of 200,000 pounds", + "Code": "039601", + "Symbol": "ZR=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=039601", + "Specs": "https://www.cmegroup.com/markets/agriculture/grains/rough-rice.contractSpecs.html", + }, + "054642": { + "Name": "Lean Hog Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Meats", + "Units": "Contracts of 40,000 Pounds", + "Code": "054642", + "Symbol": "HE=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=054642", + "Specs": "https://www.cmegroup.com/markets/agriculture/livestock/lean-hogs.contractSpecs.html", + }, + "057642": { + "Name": "Live Cattle (CME)", + "Category": "Agriculture", + "Subcategory": "Meats", + "Units": "Contracts of 40,000 Pounds", + "Code": "057642", + "Symbol": "LE=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=057642", + "Specs": "https://www.cmegroup.com/markets/agriculture/livestock/live-cattle.contractSpecs.html", + }, + "061641": { + "Name": "Feeder Cattle (CME)", + "Category": "Agriculture", + "Subcategory": "Meats", + "Units": "Contracts of 50,000 Pounds", + "Code": "061641", + "Symbol": "GF=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=061641", + "Specs": "https://www.cmegroup.com/markets/agriculture/livestock/feeder-cattle.contractSpecs.html", + }, + "063642": { + "Name": "Cash-Settled Cheese Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Dairy", + "Units": "Contracts of 20,000 Pounds", + "Code": "063642", + "Symbol": "CSC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=", + "Specs": "https://www.cmegroup.com/markets/agriculture/dairy/cheese.contractSpecs.html", + }, + "052641": { + "Name": "Class III Milk Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Dairy", + "Units": "Contracts of 200,000 Pounds", + "Code": "052641", + "Symbol": "DC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=052641", + "Specs": "https://www.cmegroup.com/markets/agriculture/dairy/class-iii-milk.contractSpecs.html", + }, + "052644": { + "Name": "Class IV Milk Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Dairy", + "Units": "Contracts of 200,000 Pounds", + "Code": "052644", + "Symbol": "GDK=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=052644", + "Specs": "https://www.cmegroup.com/markets/agriculture/dairy/class-iv-milk.contractSpecs.html", + }, + "052642": { + "Name": "Non Fat Dry Milk Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Dairy", + "Units": "Contracts of 44,000 Pounds", + "Code": "052642", + "Symbol": "GNF=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=052642", + "Specs": "https://www.cmegroup.com/markets/agriculture/dairy/nonfat-dry-milk.contractSpecs.html", + }, + "050642": { + "Name": "Cash-Settled Butter (CME)", + "Category": "Agriculture", + "Subcategory": "Dairy", + "Units": "Contracts of 20,000 Pounds", + "Code": "050642", + "Symbol": "CB=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=050642", + "Specs": "https://www.cmegroup.com/markets/agriculture/dairy/nonfat-dry-milk.contractSpecs.html", + }, + "002602": { + "Name": "Corn Futures (CME)", + "Category": "Agriculture", + "Subcategory": "Corn", + "Units": "Contracts of 5,000 Bushels", + "Code": "002602", + "Symbol": "ZC=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=002602", + "Specs": "https://www.cmegroup.com/markets/agriculture/grains/corn.contractSpecs.futures.html", + }, + "03565B": { + "Name": "Henry Hub Natural Gas Futures (NYM)", + "Category": "Energy", + "Subcategory": "Natural Gas", + "Units": "Contracts of 2,500 MMBTU's", + "Code": "03565B", + "Symbol": "NG=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=03565B", + "Specs": "https://www.cmegroup.com/markets/energy/natural-gas/natural-gas.contractSpecs.html", + }, + "022651": { + "Name": "NY Harbor ULSD Heating Oil Futures (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 42,000 Gallons", + "Code": "022651", + "Symbol": "HO=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=022651", + "Specs": "https://www.cmegroup.com/markets/energy/refined-products/heating-oil.contractSpecs.html", + }, + "111659": { + "Name": "RBOB Gasoline Futures (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 42,000 Gallons", + "Code": "111659", + "Symbol": "RB=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=111659", + "Specs": "https://www.cmegroup.com/markets/energy/refined-products/rbob-gasoline.contractSpecs.html", + }, + "86665A": { + "Name": "Naphta Crack Spread Futures (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 1,000 Barrels ", + "Code": "86665A", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=86665A", + "Specs": "https://www.cmegroup.com/markets/energy/refined-products/european-naphtha-crack-spread-swap.contractSpecs.html", # noqa + }, + "06665T": { + "Name": "Conway Propane Swap (OPIS) (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 42,000 Gallons", + "Code": "06665T", + "Symbol": "A8K", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06665T", + "Specs": "https://www.cmegroup.com/markets/energy/petrochemicals/conway-propane-opis-swap.contractSpecs.html", + }, + "067A71": { + "Name": "WTI Midland (Argus) vs. WTI Trade Month Futures (NYM)", + "Category": "Energy", + "Subcategory": "Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "067A71", + "Symbol": "WTT", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=067A71", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/wti-midland-argus-vs-wti-trade-month.contractSpecs.html", # noqa + }, + "0676A5": { + "Name": "WTI Houston (Argus) vs. WTI Trade Month Futures (NYM)", + "Category": "Energy", + "Subcategory": "Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "0676A5", + "Symbol": "HTT", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=0676A5", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/wti-houston-argus-vs-wti-trade-month.contractSpecs.html", # noqa + }, + "06765A": { + "Name": "WTI Crude Oil Financial Futures (NYM)", + "Category": "Energy", + "Subcategory": "Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "06765A", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06765A", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/west-texas-intermediate-wti-crude-oil-calendar-swap-futures.contractSpecs.html", # noqa + }, + "067651": { + "Name": "WTI Physical Settlement Futures (NYM)", + "Category": "Energy", + "Subcategory": "Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "067651", + "Symbol": "CL=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=067651", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/light-sweet-crude.contractSpecs.html", + }, + "06765T": { + "Name": "Brent Last Day Financial Futures (NYM)", + "Category": "Energy", + "Subcategory": "Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "06765T", + "Symbol": "BZ=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06765T", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/brent-crude-oil-last-day.contractSpecs.html", + }, + "06765Z": { + "Name": "WTI-Brent Spread Option Futures (NYM)", + "Category": "Energy", + "Subcategory": "Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "06765Z", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06765Z", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/wti-brent-ice-bullet-swap-futures.contractSpecs.html", + }, + "299741": { + "Name": "Euro FX/British Pound XRate Futures (CME)", + "Category": "Currencies", + "Subcategory": "EUR/GBP", + "Units": "Contracts of EUR 125,000", + "Code": "299741", + "Symbol": "RP=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=299741", + "Specs": "https://www.cmegroup.com/markets/fx/cross-rates/euro-fx-british-pound.contractSpecs.html", + }, + "097741": { + "Name": "Japanese Yen Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/JPY", + "Units": "Contracts of Contracts of JPY 12,500,000", + "Code": "097741", + "Symbol": "6J=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=097741", + "Specs": "https://www.cmegroup.com/markets/fx/g10/japanese-yen.contractSpecs.html", + }, + "099741": { + "Name": "Euro FX Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/EUR", + "Units": "Contracts of EUR 125,000", + "Code": "099741", + "Symbol": "6E=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=099741", + "Specs": "https://www.cmegroup.com/markets/fx/g10/euro-fx.contractSpecs.html", + }, + "090741": { + "Name": "Canadian Dollar Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/CAD", + "Units": "Contracts of CAD 100,000", + "Code": "090741", + "Symbol": "6C=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=090741", + "Specs": "https://www.cmegroup.com/markets/fx/g10/canadian-dollar.contractSpecs.html", + }, + "096742": { + "Name": "British Pound Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/GBP", + "Units": "Contracts of GBP 62,500", + "Code": "096742", + "Symbol": "6B=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=096742", + "Specs": "https://www.cmegroup.com/markets/fx/g10/british-pound.contractSpecs.html", + }, + "232741": { + "Name": "Australian Dollar Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/AUD", + "Units": "Contracts of AUD 100,000", + "Code": "232741", + "Symbol": "6A=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=232741", + "Specs": "https://www.cmegroup.com/markets/fx/g10/australian-dollar.contractSpecs.html", + }, + "095741": { + "Name": "Mexican Peso Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/MXY", + "Units": "Contracts of 500,000 Mexican Pesos", + "Code": "095741", + "Symbol": "6M=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=095741", + "Specs": "https://www.cmegroup.com/markets/fx/emerging-market/mexican-peso.contractSpecs.html", + }, + "112741": { + "Name": "New Zealand Dollar Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/NZD", + "Units": "Contracts of NZD 100,000", + "Code": "112741", + "Symbol": "6N=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=112741", + "Specs": "https://www.cmegroup.com/markets/fx/g10/new-zealand-dollar.contractSpecs.html", + }, + "092741": { + "Name": "Swiss Franc Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/CHF", + "Units": "Contracts of CHF 125,000", + "Code": "092741", + "Symbol": "6S=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=092741", + "Specs": "https://www.cmegroup.com/markets/fx/g10/swiss-franc.contractSpecs.html", + }, + "102741": { + "Name": "Brazilian Real Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/BRL", + "Units": "Contracts of BRL 100,000", + "Code": "102741", + "Symbol": "6L=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=102741", + "Specs": "https://www.cmegroup.com/markets/fx/emerging-market/brazilian-real.contractSpecs.html", + }, + "122741": { + "Name": "South African Rand Futures (CME)", + "Category": "Currencies", + "Subcategory": "USD/ZAR", + "Units": "Contracts of ZAR 500,000", + "Code": "122741", + "Symbol": "6Z=F", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=122741", + "Specs": "https://www.cmegroup.com/markets/fx/emerging-market/south-african-rand.contractSpecs.html", + }, + "021397": { + "Name": "Marine Fuel Oil 0.5% FOB USGC Futures (IFED)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 1,000 Barrels", + "Code": "021397", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=021397", + "Specs": "https://www.theice.com/products/71085678/Fuel-Oil-Outright-Marine-Fuel-05-FOB-USGC-Barges-Platts-Future", # noqa + }, + "02141C": { + "Name": "Fuel Oil -3% USGC vs. 3.5% FOB RDAM (IFED)", + "Category": "Energy", + "Subcategory": "Spread", + "Units": "Contracts of 1,000 Barrels", + "Code": "02141B", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=02141C", + "Specs": "https://www.theice.com/products/6753390/Fuel-Oil-Diff-USGC-HSFO-Platts-vs-Fuel-Oil-35-FOB-Rotterdam-Barges-Platts-Future-in-bbls", # noqa + }, + "02141B": { + "Name": "USGC HSFO (Platts) Futures (IFED)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 1,000 Barrels", + "Code": "02141B", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=02141B", + "Specs": "https://www.theice.com/products/6753543/Fuel-Oil-Outright-USGC-HSFO-Platts-Future", + }, + "02141R": { + "Name": "USGC HSFO (Platts) vs. Brent 1st Line (IFED)", + "Category": "Energy", + "Subcategory": "Spread", + "Units": "Contracts of 1,000 Barrels", + "Code": "02141R", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=02141R", + "Specs": "https://www.theice.com/products/6753290/Fuel-Oil-Crack-USGC-HSFO-Platts-vs-Brent-1st-Line-Future", + }, + "02165A": { + "Name": "Gulf #6 Fuel 3.0% Sulfur Futures (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 1,000 Barrels", + "Code": "02165A", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=02165A", + "Specs": "https://www.cmegroup.com/markets/energy/refined-products/gulf-coast-no-6-fuel-oil-30pct-sulfur-platts-swap.contractSpecs.html", # noqa + }, + "025608": { + "Name": "Ethanol T2 FOB Futures Including Duty (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 100 Cubic Meters (EUR)", + "Code": "025608", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=025608", + "Specs": "https://www.cmegroup.com/markets/energy/biofuels/ethanol-platts-t2-fob-rotterdam-including-duty-swap-futures.contractSpecs.html", # noqa + }, + "025651": { + "Name": "Ethanol Futures (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 42,000 Gallons", + "Code": "025651", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=025651", + "Specs": "https://www.cmegroup.com/markets/energy/biofuels/new-york-ethanol-platts-swap.contractSpecs.html", + }, + "03265J": { + "Name": "Mini European Naphtha CIF NWE (Platts) Futures (NYM)", + "Category": "Energy", + "Subcategory": "Petroleum Products", + "Units": "Contracts of 100 Metric Tons", + "Code": "03265J", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=03265J", + "Specs": "https://www.cmegroup.com/markets/energy/refined-products/mini-european-naphtha-platts-cif-nwe-swap-futures.contractSpecs.html", # noqa + }, + "06739C": { + "Name": "Crude Diff Argus WCS vs. WTI 1st (IFED)", + "Category": "Energy", + "Subcategory": "Crude Oil", + "Units": "Contracts of 42,000 Gallons", + "Code": "06739C", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06739C", + "Specs": "https://www.theice.com/products/67689141/Crude-Diff-Argus-WCS-Houston-Crude-Oil-Trade-Month-Future", + }, + "067411": { + "Name": "Light Sweet WTI Futures (ICEU)", + "Category": "Energy", + "Subcategory": "Crude Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "067411", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=067411", + "Specs": "https://www.theice.com/products/213/WTI-Crude-Futures", + }, + "06742T": { + "Name": "Crude Diff - ICE SW 1A Index Futures (IFED)", + "Category": "Energy", + "Subcategory": "Crude Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "06742T", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06742T", + "Specs": "https://www.theice.com/products/31687075/Crude-Diff-ICE-SW-1a-Index-Future", + }, + "06742G": { + "Name": "Crude Diff - ICE WCS 1A Index Futures (IFED)", + "Category": "Energy", + "Subcategory": "Crude Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "06742G", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06742G", + "Specs": "https://www.theice.com/products/27066814/Crude-Diff-ICE-WCS-1A-Index-Future", + }, + "06765C": { + "Name": "Crude Oil Average Price Options Futres (NYM)", + "Category": "Energy", + "Subcategory": "Crude Oil", + "Units": "Contracts of 1,000 Barrels", + "Code": "06765C", + "Symbol": "", + "Permalink": "https://data.nasdaq.com/data/CFTC-commodity-futures-trading-commission-reports?keyword=06765C", + "Specs": "https://www.cmegroup.com/markets/energy/crude-oil/west-texas-intermediate-wti-crude-oil-calendar-swap-futures.contractSpecs.options.html#optionProductId=2767", # noqa + }, +} diff --git a/openbb_sdk/providers/quandl/poetry.lock b/openbb_sdk/providers/quandl/poetry.lock new file mode 100644 index 00000000000..7e8a14e9d5d --- /dev/null +++ b/openbb_sdk/providers/quandl/poetry.lock @@ -0,0 +1,1065 @@ +# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand. + +[[package]] +name = "anyio" +version = "4.0.0" +description = "High level compatibility layer for multiple asynchronous event loop implementations" +optional = false +python-versions = ">=3.8" +files = [ + {file = "anyio-4.0.0-py3-none-any.whl", hash = "sha256:cfdb2b588b9fc25ede96d8db56ed50848b0b649dca3dd1df0b11f683bb9e0b5f"}, + {file = "anyio-4.0.0.tar.gz", hash = "sha256:f7ed51751b2c2add651e5747c891b47e26d2a21be5d32d9311dfe9692f3e5d7a"}, +] + +[package.dependencies] +exceptiongroup = {version = ">=1.0.2", markers = "python_version < \"3.11\""} +idna = ">=2.8" +sniffio = ">=1.1" + +[package.extras] +doc = ["Sphinx (>=7)", "packaging", "sphinx-autodoc-typehints (>=1.2.0)"] +test = ["anyio[trio]", "coverage[toml] (>=7)", "hypothesis (>=4.0)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"] +trio = ["trio (>=0.22)"] + +[[package]] +name = "backoff" +version = "2.2.1" +description = "Function decoration for backoff and retry" +optional = false +python-versions = ">=3.7,<4.0" +files = [ + {file = "backoff-2.2.1-py3-none-any.whl", hash = "sha256:63579f9a0628e06278f7e47b7d7d5b6ce20dc65c5e96a6f3ca99a6adca0396e8"}, + {file = "backoff-2.2.1.tar.gz", hash = "sha256:03f829f5bb1923180821643f8753b0502c3b682293992485b0eef2807afa5cba"}, +] + +[[package]] +name = "bcrypt" +version = "4.0.1" +description = "Modern password hashing for your software and your servers" +optional = false +python-versions = ">=3.6" +files = [ + {file = "bcrypt-4.0.1-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:b1023030aec778185a6c16cf70f359cbb6e0c289fd564a7cfa29e727a1c38f8f"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:08d2947c490093a11416df18043c27abe3921558d2c03e2076ccb28a116cb6d0"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0eaa47d4661c326bfc9d08d16debbc4edf78778e6aaba29c1bc7ce67214d4410"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae88eca3024bb34bb3430f964beab71226e761f51b912de5133470b649d82344"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_24_x86_64.whl", hash = "sha256:a522427293d77e1c29e303fc282e2d71864579527a04ddcfda6d4f8396c6c36a"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:fbdaec13c5105f0c4e5c52614d04f0bca5f5af007910daa8b6b12095edaa67b3"}, + {file = "bcrypt-4.0.1-cp36-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:ca3204d00d3cb2dfed07f2d74a25f12fc12f73e606fcaa6975d1f7ae69cacbb2"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:089098effa1bc35dc055366740a067a2fc76987e8ec75349eb9484061c54f535"}, + {file = "bcrypt-4.0.1-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:e9a51bbfe7e9802b5f3508687758b564069ba937748ad7b9e890086290d2f79e"}, + {file = "bcrypt-4.0.1-cp36-abi3-win32.whl", hash = "sha256:2caffdae059e06ac23fce178d31b4a702f2a3264c20bfb5ff541b338194d8fab"}, + {file = "bcrypt-4.0.1-cp36-abi3-win_amd64.whl", hash = "sha256:8a68f4341daf7522fe8d73874de8906f3a339048ba406be6ddc1b3ccb16fc0d9"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf4fa8b2ca74381bb5442c089350f09a3f17797829d958fad058d6e44d9eb83c"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:67a97e1c405b24f19d08890e7ae0c4f7ce1e56a712a016746c8b2d7732d65d4b"}, + {file = "bcrypt-4.0.1-pp37-pypy37_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b3b85202d95dd568efcb35b53936c5e3b3600c7cdcc6115ba461df3a8e89f38d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbb03eec97496166b704ed663a53680ab57c5084b2fc98ef23291987b525cb7d"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:5ad4d32a28b80c5fa6671ccfb43676e8c1cc232887759d1cd7b6f56ea4355215"}, + {file = "bcrypt-4.0.1-pp38-pypy38_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:b57adba8a1444faf784394de3436233728a1ecaeb6e07e8c22c8848f179b893c"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:705b2cea8a9ed3d55b4491887ceadb0106acf7c6387699fca771af56b1cdeeda"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_24_x86_64.whl", hash = "sha256:2b3ac11cf45161628f1f3733263e63194f22664bf4d0c0f3ab34099c02134665"}, + {file = "bcrypt-4.0.1-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:3100851841186c25f127731b9fa11909ab7b1df6fc4b9f8353f4f1fd952fbf71"}, + {file = "bcrypt-4.0.1.tar.gz", hash = "sha256:27d375903ac8261cfe4047f6709d16f7d18d39b1ec92aaf72af989552a650ebd"}, +] + +[package.extras] +tests = ["pytest (>=3.2.1,!=3.3.0)"] +typecheck = ["mypy"] + +[[package]] +name = "black" +version = "23.7.0" +description = "The uncompromising code formatter." +optional = false +python-versions = ">=3.8" +files = [ + {file = "black-23.7.0-cp310-cp310-macosx_10_16_arm64.whl", hash = "sha256:5c4bc552ab52f6c1c506ccae05681fab58c3f72d59ae6e6639e8885e94fe2587"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_universal2.whl", hash = "sha256:552513d5cd5694590d7ef6f46e1767a4df9af168d449ff767b13b084c020e63f"}, + {file = "black-23.7.0-cp310-cp310-macosx_10_16_x86_64.whl", hash = "sha256:86cee259349b4448adb4ef9b204bb4467aae74a386bce85d56ba4f5dc0da27be"}, + {file = "black-23.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:501387a9edcb75d7ae8a4412bb8749900386eaef258f1aefab18adddea1936bc"}, + {file = "black-23.7.0-cp310-cp310-win_amd64.whl", hash = "sha256:fb074d8b213749fa1d077d630db0d5f8cc3b2ae63587ad4116e8a436e9bbe995"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_arm64.whl", hash = "sha256:b5b0ee6d96b345a8b420100b7d71ebfdd19fab5e8301aff48ec270042cd40ac2"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_universal2.whl", hash = "sha256:893695a76b140881531062d48476ebe4a48f5d1e9388177e175d76234ca247cd"}, + {file = "black-23.7.0-cp311-cp311-macosx_10_16_x86_64.whl", hash = "sha256:c333286dc3ddca6fdff74670b911cccedacb4ef0a60b34e491b8a67c833b343a"}, + {file = "black-23.7.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:831d8f54c3a8c8cf55f64d0422ee875eecac26f5f649fb6c1df65316b67c8926"}, + {file = "black-23.7.0-cp311-cp311-win_amd64.whl", hash = "sha256:7f3bf2dec7d541b4619b8ce526bda74a6b0bffc480a163fed32eb8b3c9aed8ad"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_arm64.whl", hash = "sha256:f9062af71c59c004cd519e2fb8f5d25d39e46d3af011b41ab43b9c74e27e236f"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_universal2.whl", hash = "sha256:01ede61aac8c154b55f35301fac3e730baf0c9cf8120f65a9cd61a81cfb4a0c3"}, + {file = "black-23.7.0-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:327a8c2550ddc573b51e2c352adb88143464bb9d92c10416feb86b0f5aee5ff6"}, + {file = "black-23.7.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6d1c6022b86f83b632d06f2b02774134def5d4d4f1dac8bef16d90cda18ba28a"}, + {file = "black-23.7.0-cp38-cp38-win_amd64.whl", hash = "sha256:27eb7a0c71604d5de083757fbdb245b1a4fae60e9596514c6ec497eb63f95320"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_arm64.whl", hash = "sha256:8417dbd2f57b5701492cd46edcecc4f9208dc75529bcf76c514864e48da867d9"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_universal2.whl", hash = "sha256:47e56d83aad53ca140da0af87678fb38e44fd6bc0af71eebab2d1f59b1acf1d3"}, + {file = "black-23.7.0-cp39-cp39-macosx_10_16_x86_64.whl", hash = "sha256:25cc308838fe71f7065df53aedd20327969d05671bac95b38fdf37ebe70ac087"}, + {file = "black-23.7.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:642496b675095d423f9b8448243336f8ec71c9d4d57ec17bf795b67f08132a91"}, + {file = "black-23.7.0-cp39-cp39-win_amd64.whl", hash = "sha256:ad0014efc7acf0bd745792bd0d8857413652979200ab924fbf239062adc12491"}, + {file = "black-23.7.0-py3-none-any.whl", hash = "sha256:9fd59d418c60c0348505f2ddf9609c1e1de8e7493eab96198fc89d9f865e7a96"}, + {file = "black-23.7.0.tar.gz", hash = "sha256:022a582720b0d9480ed82576c920a8c1dde97cc38ff11d8d8859b3bd6ca9eedb"}, +] + +[package.dependencies] +click = ">=8.0.0" +mypy-extensions = ">=0.4.3" +packaging = ">=22.0" +pathspec = ">=0.9.0" +platformdirs = ">=2" +tomli = {version = ">=1.1.0", markers = "python_version < \"3.11\""} +typing-extensions = {version = ">=3.10.0.0", markers = "python_version < \"3.10\""} + +[package.extras] +colorama = ["colorama (>=0.4.3)"] +d = ["aiohttp (>=3.7.4)"] +jupyter = ["ipython (>=7.8.0)", "tokenize-rt (>=3.2.0)"] +uvloop = ["uvloop (>=0.15.2)"] + +[[package]] +name = "certifi" +version = "2023.7.22" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.6" +files = [ + {file = "certifi-2023.7.22-py3-none-any.whl", hash = "sha256:92d6037539857d8206b8f6ae472e8b77db8058fec5937a1ef3f54304089edbb9"}, + {file = "certifi-2023.7.22.tar.gz", hash = "sha256:539cc1d13202e33ca466e88b2807e29f4c13049d6d87031a3c110744495cb082"}, +] + +[[package]] +name = "charset-normalizer" +version = "3.2.0" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7.0" +files = [ + {file = "charset-normalizer-3.2.0.tar.gz", hash = "sha256:3bb3d25a8e6c0aedd251753a79ae98a093c7e7b471faa3aa9a93a81431987ace"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b87549028f680ca955556e3bd57013ab47474c3124dc069faa0b6545b6c9710"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7c70087bfee18a42b4040bb9ec1ca15a08242cf5867c58726530bdf3945672ed"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a103b3a7069b62f5d4890ae1b8f0597618f628b286b03d4bc9195230b154bfa9"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:94aea8eff76ee6d1cdacb07dd2123a68283cb5569e0250feab1240058f53b623"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:db901e2ac34c931d73054d9797383d0f8009991e723dab15109740a63e7f902a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0dac0ff919ba34d4df1b6131f59ce95b08b9065233446be7e459f95554c0dc8"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:193cbc708ea3aca45e7221ae58f0fd63f933753a9bfb498a3b474878f12caaad"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09393e1b2a9461950b1c9a45d5fd251dc7c6f228acab64da1c9c0165d9c7765c"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:baacc6aee0b2ef6f3d308e197b5d7a81c0e70b06beae1f1fcacffdbd124fe0e3"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:bf420121d4c8dce6b889f0e8e4ec0ca34b7f40186203f06a946fa0276ba54029"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:c04a46716adde8d927adb9457bbe39cf473e1e2c2f5d0a16ceb837e5d841ad4f"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:aaf63899c94de41fe3cf934601b0f7ccb6b428c6e4eeb80da72c58eab077b19a"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:d62e51710986674142526ab9f78663ca2b0726066ae26b78b22e0f5e571238dd"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win32.whl", hash = "sha256:04e57ab9fbf9607b77f7d057974694b4f6b142da9ed4a199859d9d4d5c63fe96"}, + {file = "charset_normalizer-3.2.0-cp310-cp310-win_amd64.whl", hash = "sha256:48021783bdf96e3d6de03a6e39a1171ed5bd7e8bb93fc84cc649d11490f87cea"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:4957669ef390f0e6719db3613ab3a7631e68424604a7b448f079bee145da6e09"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:46fb8c61d794b78ec7134a715a3e564aafc8f6b5e338417cb19fe9f57a5a9bf2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:f779d3ad205f108d14e99bb3859aa7dd8e9c68874617c72354d7ecaec2a054ac"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f25c229a6ba38a35ae6e25ca1264621cc25d4d38dca2942a7fce0b67a4efe918"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2efb1bd13885392adfda4614c33d3b68dee4921fd0ac1d3988f8cbb7d589e72a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1f30b48dd7fa1474554b0b0f3fdfdd4c13b5c737a3c6284d3cdc424ec0ffff3a"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:246de67b99b6851627d945db38147d1b209a899311b1305dd84916f2b88526c6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bd9b3b31adcb054116447ea22caa61a285d92e94d710aa5ec97992ff5eb7cf3"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:8c2f5e83493748286002f9369f3e6607c565a6a90425a3a1fef5ae32a36d749d"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:3170c9399da12c9dc66366e9d14da8bf7147e1e9d9ea566067bbce7bb74bd9c2"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7a4826ad2bd6b07ca615c74ab91f32f6c96d08f6fcc3902ceeedaec8cdc3bcd6"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:3b1613dd5aee995ec6d4c69f00378bbd07614702a315a2cf6c1d21461fe17c23"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9e608aafdb55eb9f255034709e20d5a83b6d60c054df0802fa9c9883d0a937aa"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win32.whl", hash = "sha256:f2a1d0fd4242bd8643ce6f98927cf9c04540af6efa92323e9d3124f57727bfc1"}, + {file = "charset_normalizer-3.2.0-cp311-cp311-win_amd64.whl", hash = "sha256:681eb3d7e02e3c3655d1b16059fbfb605ac464c834a0c629048a30fad2b27489"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:c57921cda3a80d0f2b8aec7e25c8aa14479ea92b5b51b6876d975d925a2ea346"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41b25eaa7d15909cf3ac4c96088c1f266a9a93ec44f87f1d13d4a0e86c81b982"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f058f6963fd82eb143c692cecdc89e075fa0828db2e5b291070485390b2f1c9c"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a7647ebdfb9682b7bb97e2a5e7cb6ae735b1c25008a70b906aecca294ee96cf4"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eef9df1eefada2c09a5e7a40991b9fc6ac6ef20b1372abd48d2794a316dc0449"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e03b8895a6990c9ab2cdcd0f2fe44088ca1c65ae592b8f795c3294af00a461c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ee4006268ed33370957f55bf2e6f4d263eaf4dc3cfc473d1d90baff6ed36ce4a"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c4983bf937209c57240cff65906b18bb35e64ae872da6a0db937d7b4af845dd7"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:3bb7fda7260735efe66d5107fb7e6af6a7c04c7fce9b2514e04b7a74b06bf5dd"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:72814c01533f51d68702802d74f77ea026b5ec52793c791e2da806a3844a46c3"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:70c610f6cbe4b9fce272c407dd9d07e33e6bf7b4aa1b7ffb6f6ded8e634e3592"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win32.whl", hash = "sha256:a401b4598e5d3f4a9a811f3daf42ee2291790c7f9d74b18d75d6e21dda98a1a1"}, + {file = "charset_normalizer-3.2.0-cp37-cp37m-win_amd64.whl", hash = "sha256:c0b21078a4b56965e2b12f247467b234734491897e99c1d51cee628da9786959"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:95eb302ff792e12aba9a8b8f8474ab229a83c103d74a750ec0bd1c1eea32e669"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1a100c6d595a7f316f1b6f01d20815d916e75ff98c27a01ae817439ea7726329"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6339d047dab2780cc6220f46306628e04d9750f02f983ddb37439ca47ced7149"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b749b9cc6ee664a3300bb3a273c1ca8068c46be705b6c31cf5d276f8628a94"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a38856a971c602f98472050165cea2cdc97709240373041b69030be15047691f"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f87f746ee241d30d6ed93969de31e5ffd09a2961a051e60ae6bddde9ec3583aa"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89f1b185a01fe560bc8ae5f619e924407efca2191b56ce749ec84982fc59a32a"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e1c8a2f4c69e08e89632defbfabec2feb8a8d99edc9f89ce33c4b9e36ab63037"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:2f4ac36d8e2b4cc1aa71df3dd84ff8efbe3bfb97ac41242fbcfc053c67434f46"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a386ebe437176aab38c041de1260cd3ea459c6ce5263594399880bbc398225b2"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ccd16eb18a849fd8dcb23e23380e2f0a354e8daa0c984b8a732d9cfaba3a776d"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:e6a5bf2cba5ae1bb80b154ed68a3cfa2fa00fde979a7f50d6598d3e17d9ac20c"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:45de3f87179c1823e6d9e32156fb14c1927fcc9aba21433f088fdfb555b77c10"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win32.whl", hash = "sha256:1000fba1057b92a65daec275aec30586c3de2401ccdcd41f8a5c1e2c87078706"}, + {file = "charset_normalizer-3.2.0-cp38-cp38-win_amd64.whl", hash = "sha256:8b2c760cfc7042b27ebdb4a43a4453bd829a5742503599144d54a032c5dc7e9e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:855eafa5d5a2034b4621c74925d89c5efef61418570e5ef9b37717d9c796419c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:203f0c8871d5a7987be20c72442488a0b8cfd0f43b7973771640fc593f56321f"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:e857a2232ba53ae940d3456f7533ce6ca98b81917d47adc3c7fd55dad8fab858"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5e86d77b090dbddbe78867a0275cb4df08ea195e660f1f7f13435a4649e954e5"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fb39a81950ec280984b3a44f5bd12819953dc5fa3a7e6fa7a80db5ee853952"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2dee8e57f052ef5353cf608e0b4c871aee320dd1b87d351c28764fc0ca55f9f4"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8700f06d0ce6f128de3ccdbc1acaea1ee264d2caa9ca05daaf492fde7c2a7200"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1920d4ff15ce893210c1f0c0e9d19bfbecb7983c76b33f046c13a8ffbd570252"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:c1c76a1743432b4b60ab3358c937a3fe1341c828ae6194108a94c69028247f22"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f7560358a6811e52e9c4d142d497f1a6e10103d3a6881f18d04dbce3729c0e2c"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:c8063cf17b19661471ecbdb3df1c84f24ad2e389e326ccaf89e3fb2484d8dd7e"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:cd6dbe0238f7743d0efe563ab46294f54f9bc8f4b9bcf57c3c666cc5bc9d1299"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1249cbbf3d3b04902ff081ffbb33ce3377fa6e4c7356f759f3cd076cc138d020"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win32.whl", hash = "sha256:6c409c0deba34f147f77efaa67b8e4bb83d2f11c8806405f76397ae5b8c0d1c9"}, + {file = "charset_normalizer-3.2.0-cp39-cp39-win_amd64.whl", hash = "sha256:7095f6fbfaa55defb6b733cfeb14efaae7a29f0b59d8cf213be4e7ca0b857b80"}, + {file = "charset_normalizer-3.2.0-py3-none-any.whl", hash = "sha256:8e098148dd37b4ce3baca71fb394c81dc5d9c7728c95df695d2dca218edf40e6"}, +] + +[[package]] +name = "click" +version = "8.1.7" +description = "Composable command line interface toolkit" +optional = false +python-versions = ">=3.7" +files = [ + {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"}, + {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "platform_system == \"Windows\""} + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "ecdsa" +version = "0.18.0" +description = "ECDSA cryptographic signature library (pure python)" +optional = false +python-versions = ">=2.6, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "ecdsa-0.18.0-py2.py3-none-any.whl", hash = "sha256:80600258e7ed2f16b9aa1d7c295bd70194109ad5a30fdee0eaeefef1d4c559dd"}, + {file = "ecdsa-0.18.0.tar.gz", hash = "sha256:190348041559e21b22a1d65cee485282ca11a6f81d503fddb84d5017e9ed1e49"}, +] + +[package.dependencies] +six = ">=1.9.0" + +[package.extras] +gmpy = ["gmpy"] +gmpy2 = ["gmpy2"] + +[[package]] +name = "exceptiongroup" +version = "1.1.3" +description = "Backport of PEP 654 (exception groups)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "exceptiongroup-1.1.3-py3-none-any.whl", hash = "sha256:343280667a4585d195ca1cf9cef84a4e178c4b6cf2274caef9859782b567d5e3"}, + {file = "exceptiongroup-1.1.3.tar.gz", hash = "sha256:097acd85d473d75af5bb98e41b61ff7fe35efe6675e4f9370ec6ec5126d160e9"}, +] + +[package.extras] +test = ["pytest (>=6)"] + +[[package]] +name = "fastapi" +version = "0.100.1" +description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" +optional = false +python-versions = ">=3.7" +files = [ + {file = "fastapi-0.100.1-py3-none-any.whl", hash = "sha256:ec6dd52bfc4eff3063cfcd0713b43c87640fefb2687bbbe3d8a08d94049cdf32"}, + {file = "fastapi-0.100.1.tar.gz", hash = "sha256:522700d7a469e4a973d92321ab93312448fbe20fca9c8da97effc7e7bc56df23"}, +] + +[package.dependencies] +pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<3.0.0" +starlette = ">=0.27.0,<0.28.0" +typing-extensions = ">=4.5.0" + +[package.extras] +all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] + +[[package]] +name = "h11" +version = "0.14.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.7" +files = [ + {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"}, + {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"}, +] + +[[package]] +name = "html5lib" +version = "1.1" +description = "HTML parser based on the WHATWG HTML specification" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +files = [ + {file = "html5lib-1.1-py2.py3-none-any.whl", hash = "sha256:0d78f8fde1c230e99fe37986a60526d7049ed4bf8a9fadbad5f00e22e58e041d"}, + {file = "html5lib-1.1.tar.gz", hash = "sha256:b2e5b40261e20f354d198eae92afc10d750afb487ed5e50f9c4eaf07c184146f"}, +] + +[package.dependencies] +six = ">=1.9" +webencodings = "*" + +[package.extras] +all = ["chardet (>=2.2)", "genshi", "lxml"] +chardet = ["chardet (>=2.2)"] +genshi = ["genshi"] +lxml = ["lxml"] + +[[package]] +name = "idna" +version = "3.4" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.5" +files = [ + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, +] + +[[package]] +name = "importlib-metadata" +version = "6.8.0" +description = "Read metadata from Python packages" +optional = false +python-versions = ">=3.8" +files = [ + {file = "importlib_metadata-6.8.0-py3-none-any.whl", hash = "sha256:3ebb78df84a805d7698245025b975d9d67053cd94c79245ba4b3eb694abe68bb"}, + {file = "importlib_metadata-6.8.0.tar.gz", hash = "sha256:dbace7892d8c0c4ac1ad096662232f831d4e64f4c4545bd53016a3e9d4654743"}, +] + +[package.dependencies] +zipp = ">=0.5" + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +perf = ["ipython"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] + +[[package]] +name = "inflection" +version = "0.5.1" +description = "A port of Ruby on Rails inflector to Python" +optional = false +python-versions = ">=3.5" +files = [ + {file = "inflection-0.5.1-py2.py3-none-any.whl", hash = "sha256:f38b2b640938a4f35ade69ac3d053042959b62a0f1076a5bbaa1b9526605a8a2"}, + {file = "inflection-0.5.1.tar.gz", hash = "sha256:1a29730d366e996aaacffb2f1f1cb9593dc38e2ddd30c91250c6dde09ea9b417"}, +] + +[[package]] +name = "monotonic" +version = "1.6" +description = "An implementation of time.monotonic() for Python 2 & < 3.3" +optional = false +python-versions = "*" +files = [ + {file = "monotonic-1.6-py2.py3-none-any.whl", hash = "sha256:68687e19a14f11f26d140dd5c86f3dba4bf5df58003000ed467e0e2a69bca96c"}, + {file = "monotonic-1.6.tar.gz", hash = "sha256:3a55207bcfed53ddd5c5bae174524062935efed17792e9de2ad0205ce9ad63f7"}, +] + +[[package]] +name = "more-itertools" +version = "10.1.0" +description = "More routines for operating on iterables, beyond itertools" +optional = false +python-versions = ">=3.8" +files = [ + {file = "more-itertools-10.1.0.tar.gz", hash = "sha256:626c369fa0eb37bac0291bce8259b332fd59ac792fa5497b59837309cd5b114a"}, + {file = "more_itertools-10.1.0-py3-none-any.whl", hash = "sha256:64e0735fcfdc6f3464ea133afe8ea4483b1c5fe3a3d69852e6503b43a0b222e6"}, +] + +[[package]] +name = "mypy-extensions" +version = "1.0.0" +description = "Type system extensions for programs checked with the mypy type checker." +optional = false +python-versions = ">=3.5" +files = [ + {file = "mypy_extensions-1.0.0-py3-none-any.whl", hash = "sha256:4392f6c0eb8a5668a69e23d168ffa70f0be9ccfd32b5cc2d26a34ae5b844552d"}, + {file = "mypy_extensions-1.0.0.tar.gz", hash = "sha256:75dbf8955dc00442a438fc4d0666508a9a97b6bd41aa2f0ffe9d2f2725af0782"}, +] + +[[package]] +name = "numpy" +version = "1.24.4" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.8" +files = [ + {file = "numpy-1.24.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c0bfb52d2169d58c1cdb8cc1f16989101639b34c7d3ce60ed70b19c63eba0b64"}, + {file = "numpy-1.24.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ed094d4f0c177b1b8e7aa9cba7d6ceed51c0e569a5318ac0ca9a090680a6a1b1"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79fc682a374c4a8ed08b331bef9c5f582585d1048fa6d80bc6c35bc384eee9b4"}, + {file = "numpy-1.24.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ffe43c74893dbf38c2b0a1f5428760a1a9c98285553c89e12d70a96a7f3a4d6"}, + {file = "numpy-1.24.4-cp310-cp310-win32.whl", hash = "sha256:4c21decb6ea94057331e111a5bed9a79d335658c27ce2adb580fb4d54f2ad9bc"}, + {file = "numpy-1.24.4-cp310-cp310-win_amd64.whl", hash = "sha256:b4bea75e47d9586d31e892a7401f76e909712a0fd510f58f5337bea9572c571e"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f136bab9c2cfd8da131132c2cf6cc27331dd6fae65f95f69dcd4ae3c3639c810"}, + {file = "numpy-1.24.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e2926dac25b313635e4d6cf4dc4e51c8c0ebfed60b801c799ffc4c32bf3d1254"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:222e40d0e2548690405b0b3c7b21d1169117391c2e82c378467ef9ab4c8f0da7"}, + {file = "numpy-1.24.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7215847ce88a85ce39baf9e89070cb860c98fdddacbaa6c0da3ffb31b3350bd5"}, + {file = "numpy-1.24.4-cp311-cp311-win32.whl", hash = "sha256:4979217d7de511a8d57f4b4b5b2b965f707768440c17cb70fbf254c4b225238d"}, + {file = "numpy-1.24.4-cp311-cp311-win_amd64.whl", hash = "sha256:b7b1fc9864d7d39e28f41d089bfd6353cb5f27ecd9905348c24187a768c79694"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1452241c290f3e2a312c137a9999cdbf63f78864d63c79039bda65ee86943f61"}, + {file = "numpy-1.24.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:04640dab83f7c6c85abf9cd729c5b65f1ebd0ccf9de90b270cd61935eef0197f"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5425b114831d1e77e4b5d812b69d11d962e104095a5b9c3b641a218abcc050e"}, + {file = "numpy-1.24.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd80e219fd4c71fc3699fc1dadac5dcf4fd882bfc6f7ec53d30fa197b8ee22dc"}, + {file = "numpy-1.24.4-cp38-cp38-win32.whl", hash = "sha256:4602244f345453db537be5314d3983dbf5834a9701b7723ec28923e2889e0bb2"}, + {file = "numpy-1.24.4-cp38-cp38-win_amd64.whl", hash = "sha256:692f2e0f55794943c5bfff12b3f56f99af76f902fc47487bdfe97856de51a706"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2541312fbf09977f3b3ad449c4e5f4bb55d0dbf79226d7724211acc905049400"}, + {file = "numpy-1.24.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9667575fb6d13c95f1b36aca12c5ee3356bf001b714fc354eb5465ce1609e62f"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f3a86ed21e4f87050382c7bc96571755193c4c1392490744ac73d660e8f564a9"}, + {file = "numpy-1.24.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d11efb4dbecbdf22508d55e48d9c8384db795e1b7b51ea735289ff96613ff74d"}, + {file = "numpy-1.24.4-cp39-cp39-win32.whl", hash = "sha256:6620c0acd41dbcb368610bb2f4d83145674040025e5536954782467100aa8835"}, + {file = "numpy-1.24.4-cp39-cp39-win_amd64.whl", hash = "sha256:befe2bf740fd8373cf56149a5c23a0f601e82869598d41f8e188a0e9869926f8"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:31f13e25b4e304632a4619d0e0777662c2ffea99fcae2029556b17d8ff958aef"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95f7ac6540e95bc440ad77f56e520da5bf877f87dca58bd095288dce8940532a"}, + {file = "numpy-1.24.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:e98f220aa76ca2a977fe435f5b04d7b3470c0a2e6312907b37ba6068f26787f2"}, + {file = "numpy-1.24.4.tar.gz", hash = "sha256:80f5e3a4e498641401868df4208b74581206afbee7cf7b8329daae82676d9463"}, +] + +[[package]] +name = "openbb-core" +version = "0.1.0" +description = "OpenBB package with core functionality" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +bcrypt = "^4.0.1" +black = "^23.7.0" +fastapi = "^0.100.1" +html5lib = "^1.1" +openbb-provider = {path = "../provider"} +pandas = ">=1.5.3" +passlib = "^1.7.4" +posthog = "^3.0.1" +python-jose = "^3.3.0" +python-multipart = "^0.0.6" +ruff = "0.0.256" +uuid7 = "^0.1.0" +uvicorn = "^0.20.0" +websockets = "^10.4" + +[package.source] +type = "directory" +url = "../../sdk/core" + +[[package]] +name = "openbb-provider" +version = "0.1.0" +description = "OpenBB package to execute queries to financial data providers" +optional = false +python-versions = "^3.8" +files = [] +develop = false + +[package.dependencies] +importlib-metadata = "^6.8.0" +pydantic = {version = "^1.10", extras = ["dotenv"]} +requests = "^2.31.0" +urllib3 = "<2.0.0" + +[package.source] +type = "directory" +url = "../../sdk/provider" + +[[package]] +name = "packaging" +version = "23.1" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.7" +files = [ + {file = "packaging-23.1-py3-none-any.whl", hash = "sha256:994793af429502c4ea2ebf6bf664629d07c1a9fe974af92966e4b8d2df7edc61"}, + {file = "packaging-23.1.tar.gz", hash = "sha256:a392980d2b6cffa644431898be54b0045151319d1e7ec34f0cfed48767dd334f"}, +] + +[[package]] +name = "pandas" +version = "2.0.3" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.8" +files = [ + {file = "pandas-2.0.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e4c7c9f27a4185304c7caf96dc7d91bc60bc162221152de697c98eb0b2648dd8"}, + {file = "pandas-2.0.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f167beed68918d62bffb6ec64f2e1d8a7d297a038f86d4aed056b9493fca407f"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ce0c6f76a0f1ba361551f3e6dceaff06bde7514a374aa43e33b588ec10420183"}, + {file = "pandas-2.0.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ba619e410a21d8c387a1ea6e8a0e49bb42216474436245718d7f2e88a2f8d7c0"}, + {file = "pandas-2.0.3-cp310-cp310-win32.whl", hash = "sha256:3ef285093b4fe5058eefd756100a367f27029913760773c8bf1d2d8bebe5d210"}, + {file = "pandas-2.0.3-cp310-cp310-win_amd64.whl", hash = "sha256:9ee1a69328d5c36c98d8e74db06f4ad518a1840e8ccb94a4ba86920986bb617e"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b084b91d8d66ab19f5bb3256cbd5ea661848338301940e17f4492b2ce0801fe8"}, + {file = "pandas-2.0.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:37673e3bdf1551b95bf5d4ce372b37770f9529743d2498032439371fc7b7eb26"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b9cb1e14fdb546396b7e1b923ffaeeac24e4cedd14266c3497216dd4448e4f2d"}, + {file = "pandas-2.0.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d9cd88488cceb7635aebb84809d087468eb33551097d600c6dad13602029c2df"}, + {file = "pandas-2.0.3-cp311-cp311-win32.whl", hash = "sha256:694888a81198786f0e164ee3a581df7d505024fbb1f15202fc7db88a71d84ebd"}, + {file = "pandas-2.0.3-cp311-cp311-win_amd64.whl", hash = "sha256:6a21ab5c89dcbd57f78d0ae16630b090eec626360085a4148693def5452d8a6b"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9e4da0d45e7f34c069fe4d522359df7d23badf83abc1d1cef398895822d11061"}, + {file = "pandas-2.0.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:32fca2ee1b0d93dd71d979726b12b61faa06aeb93cf77468776287f41ff8fdc5"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:258d3624b3ae734490e4d63c430256e716f488c4fcb7c8e9bde2d3aa46c29089"}, + {file = "pandas-2.0.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9eae3dc34fa1aa7772dd3fc60270d13ced7346fcbcfee017d3132ec625e23bb0"}, + {file = "pandas-2.0.3-cp38-cp38-win32.whl", hash = "sha256:f3421a7afb1a43f7e38e82e844e2bca9a6d793d66c1a7f9f0ff39a795bbc5e02"}, + {file = "pandas-2.0.3-cp38-cp38-win_amd64.whl", hash = "sha256:69d7f3884c95da3a31ef82b7618af5710dba95bb885ffab339aad925c3e8ce78"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5247fb1ba347c1261cbbf0fcfba4a3121fbb4029d95d9ef4dc45406620b25c8b"}, + {file = "pandas-2.0.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:81af086f4543c9d8bb128328b5d32e9986e0c84d3ee673a2ac6fb57fd14f755e"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1994c789bf12a7c5098277fb43836ce090f1073858c10f9220998ac74f37c69b"}, + {file = "pandas-2.0.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5ec591c48e29226bcbb316e0c1e9423622bc7a4eaf1ef7c3c9fa1a3981f89641"}, + {file = "pandas-2.0.3-cp39-cp39-win32.whl", hash = "sha256:04dbdbaf2e4d46ca8da896e1805bc04eb85caa9a82e259e8eed00254d5e0c682"}, + {file = "pandas-2.0.3-cp39-cp39-win_amd64.whl", hash = "sha256:1168574b036cd8b93abc746171c9b4f1b83467438a5e45909fed645cf8692dbc"}, + {file = "pandas-2.0.3.tar.gz", hash = "sha256:c02f372a88e0d17f36d3093a644c73cfc1788e876a7c4bcb4020a77512e2043c"}, +] + +[package.dependencies] +numpy = [ + {version = ">=1.20.3", markers = "python_version < \"3.10\""}, + {version = ">=1.21.0", markers = "python_version >= \"3.10\" and python_version < \"3.11\""}, + {version = ">=1.23.2", markers = "python_version >= \"3.11\""}, +] +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.1" + +[package.extras] +all = ["PyQt5 (>=5.15.1)", "SQLAlchemy (>=1.4.16)", "beautifulsoup4 (>=4.9.3)", "bottleneck (>=1.3.2)", "brotlipy (>=0.7.0)", "fastparquet (>=0.6.3)", "fsspec (>=2021.07.0)", "gcsfs (>=2021.07.0)", "html5lib (>=1.1)", "hypothesis (>=6.34.2)", "jinja2 (>=3.0.0)", "lxml (>=4.6.3)", "matplotlib (>=3.6.1)", "numba (>=0.53.1)", "numexpr (>=2.7.3)", "odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pandas-gbq (>=0.15.0)", "psycopg2 (>=2.8.6)", "pyarrow (>=7.0.0)", "pymysql (>=1.0.2)", "pyreadstat (>=1.1.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)", "python-snappy (>=0.6.0)", "pyxlsb (>=1.0.8)", "qtpy (>=2.2.0)", "s3fs (>=2021.08.0)", "scipy (>=1.7.1)", "tables (>=3.6.1)", "tabulate (>=0.8.9)", "xarray (>=0.21.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)", "zstandard (>=0.15.2)"] +aws = ["s3fs (>=2021.08.0)"] +clipboard = ["PyQt5 (>=5.15.1)", "qtpy (>=2.2.0)"] +compression = ["brotlipy (>=0.7.0)", "python-snappy (>=0.6.0)", "zstandard (>=0.15.2)"] +computation = ["scipy (>=1.7.1)", "xarray (>=0.21.0)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.0.7)", "pyxlsb (>=1.0.8)", "xlrd (>=2.0.1)", "xlsxwriter (>=1.4.3)"] +feather = ["pyarrow (>=7.0.0)"] +fss = ["fsspec (>=2021.07.0)"] +gcp = ["gcsfs (>=2021.07.0)", "pandas-gbq (>=0.15.0)"] +hdf5 = ["tables (>=3.6.1)"] +html = ["beautifulsoup4 (>=4.9.3)", "html5lib (>=1.1)", "lxml (>=4.6.3)"] +mysql = ["SQLAlchemy (>=1.4.16)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.0.0)", "tabulate (>=0.8.9)"] +parquet = ["pyarrow (>=7.0.0)"] +performance = ["bottleneck (>=1.3.2)", "numba (>=0.53.1)", "numexpr (>=2.7.1)"] +plot = ["matplotlib (>=3.6.1)"] +postgresql = ["SQLAlchemy (>=1.4.16)", "psycopg2 (>=2.8.6)"] +spss = ["pyreadstat (>=1.1.2)"] +sql-other = ["SQLAlchemy (>=1.4.16)"] +test = ["hypothesis (>=6.34.2)", "pytest (>=7.3.2)", "pytest-asyncio (>=0.17.0)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.6.3)"] + +[[package]] +name = "passlib" +version = "1.7.4" +description = "comprehensive password hashing framework supporting over 30 schemes" +optional = false +python-versions = "*" +files = [ + {file = "passlib-1.7.4-py2.py3-none-any.whl", hash = "sha256:aa6bca462b8d8bda89c70b382f0c298a20b5560af6cbfa2dce410c0a2fb669f1"}, + {file = "passlib-1.7.4.tar.gz", hash = "sha256:defd50f72b65c5402ab2c573830a6978e5f202ad0d984793c8dde2c4152ebe04"}, +] + +[package.extras] +argon2 = ["argon2-cffi (>=18.2.0)"] +bcrypt = ["bcrypt (>=3.1.0)"] +build-docs = ["cloud-sptheme (>=1.10.1)", "sphinx (>=1.6)", "sphinxcontrib-fulltoc (>=1.2.0)"] +totp = ["cryptography"] + +[[package]] +name = "pathspec" +version = "0.11.2" +description = "Utility library for gitignore style pattern matching of file paths." +optional = false +python-versions = ">=3.7" +files = [ + {file = "pathspec-0.11.2-py3-none-any.whl", hash = "sha256:1d6ed233af05e679efb96b1851550ea95bbb64b7c490b0f5aa52996c11e92a20"}, + {file = "pathspec-0.11.2.tar.gz", hash = "sha256:e0d8d0ac2f12da61956eb2306b69f9469b42f4deb0f3cb6ed47b9cce9996ced3"}, +] + +[[package]] +name = "platformdirs" +version = "3.10.0" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +optional = false +python-versions = ">=3.7" +files = [ + {file = "platformdirs-3.10.0-py3-none-any.whl", hash = "sha256:d7c24979f292f916dc9cbf8648319032f551ea8c49a4c9bf2fb556a02070ec1d"}, + {file = "platformdirs-3.10.0.tar.gz", hash = "sha256:b45696dab2d7cc691a3226759c0d3b00c47c8b6e293d96f6436f733303f77f6d"}, +] + +[package.extras] +docs = ["furo (>=2023.7.26)", "proselint (>=0.13)", "sphinx (>=7.1.1)", "sphinx-autodoc-typehints (>=1.24)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-cov (>=4.1)", "pytest-mock (>=3.11.1)"] + +[[package]] +name = "posthog" +version = "3.0.2" +description = "Integrate PostHog into any python application." +optional = false +python-versions = "*" +files = [ + {file = "posthog-3.0.2-py2.py3-none-any.whl", hash = "sha256:a8c0af6f2401fbe50f90e68c4143d0824b54e872de036b1c2f23b5abb39d88ce"}, + {file = "posthog-3.0.2.tar.gz", hash = "sha256:701fba6e446a4de687c6e861b587e7b7741955ad624bf34fe013c06a0fec6fb3"}, +] + +[package.dependencies] +backoff = ">=1.10.0" +monotonic = ">=1.5" +python-dateutil = ">2.1" +requests = ">=2.7,<3.0" +six = ">=1.5" + +[package.extras] +dev = ["black", "flake8", "flake8-print", "isort", "pre-commit"] +sentry = ["django", "sentry-sdk"] +test = ["coverage", "flake8", "freezegun (==0.3.15)", "mock (>=2.0.0)", "pylint", "pytest"] + +[[package]] +name = "pyasn1" +version = "0.5.0" +description = "Pure-Python implementation of ASN.1 types and DER/BER/CER codecs (X.208)" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "pyasn1-0.5.0-py2.py3-none-any.whl", hash = "sha256:87a2121042a1ac9358cabcaf1d07680ff97ee6404333bacca15f76aa8ad01a57"}, + {file = "pyasn1-0.5.0.tar.gz", hash = "sha256:97b7290ca68e62a832558ec3976f15cbf911bf5d7c7039d8b861c2a0ece69fde"}, +] + +[[package]] +name = "pydantic" +version = "1.10.12" +description = "Data validation and settings management using python type hints" +optional = false +python-versions = ">=3.7" +files = [ + {file = "pydantic-1.10.12-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a1fcb59f2f355ec350073af41d927bf83a63b50e640f4dbaa01053a28b7a7718"}, + {file = "pydantic-1.10.12-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:b7ccf02d7eb340b216ec33e53a3a629856afe1c6e0ef91d84a4e6f2fb2ca70fe"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8fb2aa3ab3728d950bcc885a2e9eff6c8fc40bc0b7bb434e555c215491bcf48b"}, + {file = "pydantic-1.10.12-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:771735dc43cf8383959dc9b90aa281f0b6092321ca98677c5fb6125a6f56d58d"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ca48477862372ac3770969b9d75f1bf66131d386dba79506c46d75e6b48c1e09"}, + {file = "pydantic-1.10.12-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a5e7add47a5b5a40c49b3036d464e3c7802f8ae0d1e66035ea16aa5b7a3923ed"}, + {file = "pydantic-1.10.12-cp310-cp310-win_amd64.whl", hash = "sha256:e4129b528c6baa99a429f97ce733fff478ec955513630e61b49804b6cf9b224a"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b0d191db0f92dfcb1dec210ca244fdae5cbe918c6050b342d619c09d31eea0cc"}, + {file = "pydantic-1.10.12-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:795e34e6cc065f8f498c89b894a3c6da294a936ee71e644e4bd44de048af1405"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:69328e15cfda2c392da4e713443c7dbffa1505bc9d566e71e55abe14c97ddc62"}, + {file = "pydantic-1.10.12-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2031de0967c279df0d8a1c72b4ffc411ecd06bac607a212892757db7462fc494"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:ba5b2e6fe6ca2b7e013398bc7d7b170e21cce322d266ffcd57cca313e54fb246"}, + {file = "pydantic-1.10.12-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:2a7bac939fa326db1ab741c9d7f44c565a1d1e80908b3797f7f81a4f86bc8d33"}, + {file = "pydantic-1.10.12-cp311-cp311-win_amd64.whl", hash = "sha256:87afda5539d5140cb8ba9e8b8c8865cb5b1463924d38490d73d3ccfd80896b3f"}, + {file = "pydantic-1.10.12-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:549a8e3d81df0a85226963611950b12d2d334f214436a19537b2efed61b7639a"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:598da88dfa127b666852bef6d0d796573a8cf5009ffd62104094a4fe39599565"}, + {file = "pydantic-1.10.12-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ba5c4a8552bff16c61882db58544116d021d0b31ee7c66958d14cf386a5b5350"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:c79e6a11a07da7374f46970410b41d5e266f7f38f6a17a9c4823db80dadf4303"}, + {file = "pydantic-1.10.12-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab26038b8375581dc832a63c948f261ae0aa21f1d34c1293469f135fa92972a5"}, + {file = "pydantic-1.10.12-cp37-cp37m-win_amd64.whl", hash = "sha256:e0a16d274b588767602b7646fa05af2782576a6cf1022f4ba74cbb4db66f6ca8"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6a9dfa722316f4acf4460afdf5d41d5246a80e249c7ff475c43a3a1e9d75cf62"}, + {file = "pydantic-1.10.12-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a73f489aebd0c2121ed974054cb2759af8a9f747de120acd2c3394cf84176ccb"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bcb8cbfccfcf02acb8f1a261143fab622831d9c0989707e0e659f77a18e0"}, + {file = "pydantic-1.10.12-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:2fcfb5296d7877af406ba1547dfde9943b1256d8928732267e2653c26938cd9c"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:2f9a6fab5f82ada41d56b0602606a5506aab165ca54e52bc4545028382ef1c5d"}, + {file = "pydantic-1.10.12-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dea7adcc33d5d105896401a1f37d56b47d443a2b2605ff8a969a0ed5543f7e33"}, + {file = "pydantic-1.10.12-cp38-cp38-win_amd64.whl", hash = "sha256:1eb2085c13bce1612da8537b2d90f549c8cbb05c67e8f22854e201bde5d98a47"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ef6c96b2baa2100ec91a4b428f80d8f28a3c9e53568219b6c298c1125572ebc6"}, + {file = "pydantic-1.10.12-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6c076be61cd0177a8433c0adcb03475baf4ee91edf5a4e550161ad57fc90f523"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d5a58feb9a39f481eda4d5ca220aa8b9d4f21a41274760b9bc66bfd72595b86"}, + {file = "pydantic-1.10.12-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5f805d2d5d0a41633651a73fa4ecdd0b3d7a49de4ec3fadf062fe16501ddbf1"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:1289c180abd4bd4555bb927c42ee42abc3aee02b0fb2d1223fb7c6e5bef87dbe"}, + {file = "pydantic-1.10.12-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:5d1197e462e0364906cbc19681605cb7c036f2475c899b6f296104ad42b9f5fb"}, + {file = "pydantic-1.10.12-cp39-cp39-win_amd64.whl", hash = "sha256:fdbdd1d630195689f325c9ef1a12900524dceb503b00a987663ff4f58669b93d"}, + {file = "pydantic-1.10.12-py3-none-any.whl", hash = "sha256:b749a43aa51e32839c9d71dc67eb1e4221bb04af1033a32e3923d46f9effa942"}, + {file = "pydantic-1.10.12.tar.gz", hash = "sha256:0fe8a415cea8f340e7a9af9c54fc71a649b43e8ca3cc732986116b3cb135d303"}, +] + +[package.dependencies] +python-dotenv = {version = ">=0.10.4", optional = true, markers = "extra == \"dotenv\""} +typing-extensions = ">=4.2.0" + +[package.extras] +dotenv = ["python-dotenv (>=0.10.4)"] +email = ["email-validator (>=1.0.3)"] + +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "1.0.0" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.8" +files = [ + {file = "python-dotenv-1.0.0.tar.gz", hash = "sha256:a8df96034aae6d2d50a4ebe8216326c61c3eb64836776504fcca410e5937a3ba"}, + {file = "python_dotenv-1.0.0-py3-none-any.whl", hash = "sha256:f5971a9226b701070a4bf2c38c89e5a3f0d64de8debda981d1db98583009122a"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-jose" +version = "3.3.0" +description = "JOSE implementation in Python" +optional = false +python-versions = "*" +files = [ + {file = "python-jose-3.3.0.tar.gz", hash = "sha256:55779b5e6ad599c6336191246e95eb2293a9ddebd555f796a65f838f07e5d78a"}, + {file = "python_jose-3.3.0-py2.py3-none-any.whl", hash = "sha256:9b1376b023f8b298536eedd47ae1089bcdb848f1535ab30555cd92002d78923a"}, +] + +[package.dependencies] +ecdsa = "!=0.15" +pyasn1 = "*" +rsa = "*" + +[package.extras] +cryptography = ["cryptography (>=3.4.0)"] +pycrypto = ["pyasn1", "pycrypto (>=2.6.0,<2.7.0)"] +pycryptodome = ["pyasn1", "pycryptodome (>=3.3.1,<4.0.0)"] + +[[package]] +name = "python-multipart" +version = "0.0.6" +description = "A streaming multipart parser for Python" +optional = false +python-versions = ">=3.7" +files = [ + {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, + {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, +] + +[package.extras] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] + +[[package]] +name = "pytz" +version = "2023.3" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +files = [ + {file = "pytz-2023.3-py2.py3-none-any.whl", hash = "sha256:a151b3abb88eda1d4e34a9814df37de2a80e301e68ba0fd856fb9b46bfbbbffb"}, + {file = "pytz-2023.3.tar.gz", hash = "sha256:1d8ce29db189191fb55338ee6d0387d82ab59f3d00eac103412d64e0ebd0c588"}, +] + +[[package]] +name = "quandl" +version = "3.7.0" +description = "Package for quandl API access" +optional = false +python-versions = ">= 3.6" +files = [ + {file = "Quandl-3.7.0-py2.py3-none-any.whl", hash = "sha256:0e3e5dc60fd057c73c67380b1b0f2e3dc0e4c500fb5e6e146ac3a3c0d992cd1d"}, + {file = "Quandl-3.7.0.tar.gz", hash = "sha256:6e0b82fbc7861610b3577c5397277c4220e065eee0fed4e46cd6b6021655b64c"}, +] + +[package.dependencies] +inflection = ">=0.3.1" +more-itertools = "*" +numpy = ">=1.8" +pandas = ">=0.14" +python-dateutil = "*" +requests = ">=2.7.0" +six = "*" + +[[package]] +name = "requests" +version = "2.31.0" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.7" +files = [ + {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, + {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset-normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "rsa" +version = "4.9" +description = "Pure-Python RSA implementation" +optional = false +python-versions = ">=3.6,<4" +files = [ + {file = "rsa-4.9-py3-none-any.whl", hash = "sha256:90260d9058e514786967344d0ef75fa8727eed8a7d2e43ce9f4bcf1b536174f7"}, + {file = "rsa-4.9.tar.gz", hash = "sha256:e38464a49c6c85d7f1351b0126661487a7e0a14a50f1675ec50eb34d4f20ef21"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.3" + +[[package]] +name = "ruff" +version = "0.0.256" +description = "An extremely fast Python linter, written in Rust." +optional = false +python-versions = ">=3.7" +files = [ + {file = "ruff-0.0.256-py3-none-macosx_10_7_x86_64.whl", hash = "sha256:eb8e949f6e7fb16f9aa163fcc13318e2b7910577513468417e5b003b984410a1"}, + {file = "ruff-0.0.256-py3-none-macosx_10_9_x86_64.macosx_11_0_arm64.macosx_10_9_universal2.whl", hash = "sha256:48a42f0ec4c5a3c3b062e947b2a5f8f7a4264761653fb0ee656a9b535ae6d8d7"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36ca633cfc335869643a13e2006f13a63bc4cb94073aa9508ceb08a1e3afe3af"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:80fa5d3a40dd0b65c6d6adea4f825984d5d3a215a25d90cc6139978cb22ea1cd"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a0f88839b886db3577136375865bd080b9ed6f9b85bb990d897780e5a30ca3c2"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:fe6d77a43b2d52f45ee42f6f682198ed1c34cd0165812e276648981dfd50ad36"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3878593507b281b2615702ece06426e8b27076e8fedf658bf0c5e1e5e2ad1b40"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9e052ec4d5c92663caa662b68fe1902ec10eddac2783229b1c5f20f3df62a865"}, + {file = "ruff-0.0.256-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2116bd67e52ade9f90e5a3a3aa511a9b179c699690221bdd5bb267dbf7e94b22"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3c6e93d7818a75669328e49a0f7070c40e18676ca8e56ca9c566633bef4d8d05"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:7ebb7de4e62d751b65bb15418a83ac5d555afb3eaa3ad549dea21744da34ae86"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_i686.whl", hash = "sha256:f310bfc76c0404a487759c8904f57bf51653c46e686c800efc1ff1d165a59a04"}, + {file = "ruff-0.0.256-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:93a0cfec812b2ba57bff22b176901e0ddf44e4d42a9bd7da7ffb5e53df13fd6e"}, + {file = "ruff-0.0.256-py3-none-win32.whl", hash = "sha256:d63e5320bc2d91e94925cd1863e381a48edf087041035967faf2614bb36a6a0d"}, + {file = "ruff-0.0.256-py3-none-win_amd64.whl", hash = "sha256:859c8ffb1801895fe043a2b85a45cd0ff35667ddea4b465ba2a29d275550814a"}, + {file = "ruff-0.0.256-py3-none-win_arm64.whl", hash = "sha256:64b276149e86c3d234608d3fe1da77535865e03debd3a1d5d04576f7f5031bbb"}, + {file = "ruff-0.0.256.tar.gz", hash = "sha256:f9a96b34a4870ee8cf2f3779cd7854620d1788a83b52374771266cf800541bb7"}, +] + +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + +[[package]] +name = "sniffio" +version = "1.3.0" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +files = [ + {file = "sniffio-1.3.0-py3-none-any.whl", hash = "sha256:eecefdce1e5bbfb7ad2eeaabf7c1eeb404d7757c379bd1f7e5cce9d8bf425384"}, + {file = "sniffio-1.3.0.tar.gz", hash = "sha256:e60305c5e5d314f5389259b7f22aaa33d8f7dee49763119234af3755c55b9101"}, +] + +[[package]] +name = "starlette" +version = "0.27.0" +description = "The little ASGI library that shines." +optional = false +python-versions = ">=3.7" +files = [ + {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"}, + {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"}, +] + +[package.dependencies] +anyio = ">=3.4.0,<5" +typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} + +[package.extras] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] + +[[package]] +name = "tomli" +version = "2.0.1" +description = "A lil' TOML parser" +optional = false +python-versions = ">=3.7" +files = [ + {file = "tomli-2.0.1-py3-none-any.whl", hash = "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc"}, + {file = "tomli-2.0.1.tar.gz", hash = "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"}, +] + +[[package]] +name = "typing-extensions" +version = "4.7.1" +description = "Backported and Experimental Type Hints for Python 3.7+" +optional = false +python-versions = ">=3.7" +files = [ + {file = "typing_extensions-4.7.1-py3-none-any.whl", hash = "sha256:440d5dd3af93b060174bf433bccd69b0babc3b15b1a8dca43789fd7f61514b36"}, + {file = "typing_extensions-4.7.1.tar.gz", hash = "sha256:b75ddc264f0ba5615db7ba217daeb99701ad295353c45f9e95963337ceeeffb2"}, +] + +[[package]] +name = "tzdata" +version = "2023.3" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +files = [ + {file = "tzdata-2023.3-py2.py3-none-any.whl", hash = "sha256:7e65763eef3120314099b6939b5546db7adce1e7d6f2e179e3df563c70511eda"}, + {file = "tzdata-2023.3.tar.gz", hash = "sha256:11ef1e08e54acb0d4f95bdb1be05da659673de4acbd21bf9c69e94cc5e907a3a"}, +] + +[[package]] +name = "urllib3" +version = "1.26.16" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +files = [ + {file = "urllib3-1.26.16-py2.py3-none-any.whl", hash = "sha256:8d36afa7616d8ab714608411b4a3b13e58f463aee519024578e062e141dce20f"}, + {file = "urllib3-1.26.16.tar.gz", hash = "sha256:8f135f6502756bde6b2a9b28989df5fbe87c9970cecaa69041edcce7f0589b14"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] +socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] + +[[package]] +name = "uuid7" +version = "0.1.0" +description = "UUID version 7, generating time-sorted UUIDs with 200ns time resolution and 48 bits of randomness" +optional = false +python-versions = ">=3.7" +files = [ + {file = "uuid7-0.1.0-py2.py3-none-any.whl", hash = "sha256:5e259bb63c8cb4aded5927ff41b444a80d0c7124e8a0ced7cf44efa1f5cccf61"}, + {file = "uuid7-0.1.0.tar.gz", hash = "sha256:8c57aa32ee7456d3cc68c95c4530bc571646defac01895cfc73545449894a63c"}, +] + +[[package]] +name = "uvicorn" +version = "0.20.0" +description = "The lightning-fast ASGI server." +optional = false +python-versions = ">=3.7" +files = [ + {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"}, + {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"}, +] + +[package.dependencies] +click = ">=7.0" +h11 = ">=0.8" + +[package.extras] +standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "websockets" +version = "10.4" +description = "An implementation of the WebSocket Protocol (RFC 6455 & 7692)" +optional = false +python-versions = ">=3.7" +files = [ + {file = "websockets-10.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d58804e996d7d2307173d56c297cf7bc132c52df27a3efaac5e8d43e36c21c48"}, + {file = "websockets-10.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:bc0b82d728fe21a0d03e65f81980abbbcb13b5387f733a1a870672c5be26edab"}, + {file = "websockets-10.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ba089c499e1f4155d2a3c2a05d2878a3428cf321c848f2b5a45ce55f0d7d310c"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:33d69ca7612f0ddff3316b0c7b33ca180d464ecac2d115805c044bf0a3b0d032"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62e627f6b6d4aed919a2052efc408da7a545c606268d5ab5bfab4432734b82b4"}, + {file = "websockets-10.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:38ea7b82bfcae927eeffc55d2ffa31665dc7fec7b8dc654506b8e5a518eb4d50"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e0cb5cc6ece6ffa75baccfd5c02cffe776f3f5c8bf486811f9d3ea3453676ce8"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ae5e95cfb53ab1da62185e23b3130e11d64431179debac6dc3c6acf08760e9b1"}, + {file = "websockets-10.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c584f366f46ba667cfa66020344886cf47088e79c9b9d39c84ce9ea98aaa331"}, + {file = "websockets-10.4-cp310-cp310-win32.whl", hash = "sha256:b029fb2032ae4724d8ae8d4f6b363f2cc39e4c7b12454df8df7f0f563ed3e61a"}, + {file = "websockets-10.4-cp310-cp310-win_amd64.whl", hash = "sha256:8dc96f64ae43dde92530775e9cb169979f414dcf5cff670455d81a6823b42089"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:47a2964021f2110116cc1125b3e6d87ab5ad16dea161949e7244ec583b905bb4"}, + {file = "websockets-10.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e789376b52c295c4946403bd0efecf27ab98f05319df4583d3c48e43c7342c2f"}, + {file = "websockets-10.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7d3f0b61c45c3fa9a349cf484962c559a8a1d80dae6977276df8fd1fa5e3cb8c"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f55b5905705725af31ccef50e55391621532cd64fbf0bc6f4bac935f0fccec46"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:00c870522cdb69cd625b93f002961ffb0c095394f06ba8c48f17eef7c1541f96"}, + {file = "websockets-10.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f38706e0b15d3c20ef6259fd4bc1700cd133b06c3c1bb108ffe3f8947be15fa"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f2c38d588887a609191d30e902df2a32711f708abfd85d318ca9b367258cfd0c"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:fe10ddc59b304cb19a1bdf5bd0a7719cbbc9fbdd57ac80ed436b709fcf889106"}, + {file = "websockets-10.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:90fcf8929836d4a0e964d799a58823547df5a5e9afa83081761630553be731f9"}, + {file = "websockets-10.4-cp311-cp311-win32.whl", hash = "sha256:b9968694c5f467bf67ef97ae7ad4d56d14be2751000c1207d31bf3bb8860bae8"}, + {file = "websockets-10.4-cp311-cp311-win_amd64.whl", hash = "sha256:a7a240d7a74bf8d5cb3bfe6be7f21697a28ec4b1a437607bae08ac7acf5b4882"}, + {file = "websockets-10.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:74de2b894b47f1d21cbd0b37a5e2b2392ad95d17ae983e64727e18eb281fe7cb"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3a686ecb4aa0d64ae60c9c9f1a7d5d46cab9bfb5d91a2d303d00e2cd4c4c5cc"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0d15c968ea7a65211e084f523151dbf8ae44634de03c801b8bd070b74e85033"}, + {file = "websockets-10.4-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:00213676a2e46b6ebf6045bc11d0f529d9120baa6f58d122b4021ad92adabd41"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:e23173580d740bf8822fd0379e4bf30aa1d5a92a4f252d34e893070c081050df"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:dd500e0a5e11969cdd3320935ca2ff1e936f2358f9c2e61f100a1660933320ea"}, + {file = "websockets-10.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:4239b6027e3d66a89446908ff3027d2737afc1a375f8fd3eea630a4842ec9a0c"}, + {file = "websockets-10.4-cp37-cp37m-win32.whl", hash = "sha256:8a5cc00546e0a701da4639aa0bbcb0ae2bb678c87f46da01ac2d789e1f2d2038"}, + {file = "websockets-10.4-cp37-cp37m-win_amd64.whl", hash = "sha256:a9f9a735deaf9a0cadc2d8c50d1a5bcdbae8b6e539c6e08237bc4082d7c13f28"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5c1289596042fad2cdceb05e1ebf7aadf9995c928e0da2b7a4e99494953b1b94"}, + {file = "websockets-10.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:0cff816f51fb33c26d6e2b16b5c7d48eaa31dae5488ace6aae468b361f422b63"}, + {file = "websockets-10.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:dd9becd5fe29773d140d68d607d66a38f60e31b86df75332703757ee645b6faf"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45ec8e75b7dbc9539cbfafa570742fe4f676eb8b0d3694b67dabe2f2ceed8aa6"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4f72e5cd0f18f262f5da20efa9e241699e0cf3a766317a17392550c9ad7b37d8"}, + {file = "websockets-10.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:185929b4808b36a79c65b7865783b87b6841e852ef5407a2fb0c03381092fa3b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7d27a7e34c313b3a7f91adcd05134315002aaf8540d7b4f90336beafaea6217c"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:884be66c76a444c59f801ac13f40c76f176f1bfa815ef5b8ed44321e74f1600b"}, + {file = "websockets-10.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:931c039af54fc195fe6ad536fde4b0de04da9d5916e78e55405436348cfb0e56"}, + {file = "websockets-10.4-cp38-cp38-win32.whl", hash = "sha256:db3c336f9eda2532ec0fd8ea49fef7a8df8f6c804cdf4f39e5c5c0d4a4ad9a7a"}, + {file = "websockets-10.4-cp38-cp38-win_amd64.whl", hash = "sha256:48c08473563323f9c9debac781ecf66f94ad5a3680a38fe84dee5388cf5acaf6"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:40e826de3085721dabc7cf9bfd41682dadc02286d8cf149b3ad05bff89311e4f"}, + {file = "websockets-10.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:56029457f219ade1f2fc12a6504ea61e14ee227a815531f9738e41203a429112"}, + {file = "websockets-10.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fc088b7a32f244c519a048c170f14cf2251b849ef0e20cbbb0fdf0fdaf556f"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fc8709c00704194213d45e455adc106ff9e87658297f72d544220e32029cd3d"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0154f7691e4fe6c2b2bc275b5701e8b158dae92a1ab229e2b940efe11905dff4"}, + {file = "websockets-10.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4c6d2264f485f0b53adf22697ac11e261ce84805c232ed5dbe6b1bcb84b00ff0"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9bc42e8402dc5e9905fb8b9649f57efcb2056693b7e88faa8fb029256ba9c68c"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:edc344de4dac1d89300a053ac973299e82d3db56330f3494905643bb68801269"}, + {file = "websockets-10.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:84bc2a7d075f32f6ed98652db3a680a17a4edb21ca7f80fe42e38753a58ee02b"}, + {file = "websockets-10.4-cp39-cp39-win32.whl", hash = "sha256:c94ae4faf2d09f7c81847c63843f84fe47bf6253c9d60b20f25edfd30fb12588"}, + {file = "websockets-10.4-cp39-cp39-win_amd64.whl", hash = "sha256:bbccd847aa0c3a69b5f691a84d2341a4f8a629c6922558f2a70611305f902d74"}, + {file = "websockets-10.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:82ff5e1cae4e855147fd57a2863376ed7454134c2bf49ec604dfe71e446e2193"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d210abe51b5da0ffdbf7b43eed0cfdff8a55a1ab17abbec4301c9ff077dd0342"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:942de28af58f352a6f588bc72490ae0f4ccd6dfc2bd3de5945b882a078e4e179"}, + {file = "websockets-10.4-pp37-pypy37_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9b27d6c1c6cd53dc93614967e9ce00ae7f864a2d9f99fe5ed86706e1ecbf485"}, + {file = "websockets-10.4-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:3d3cac3e32b2c8414f4f87c1b2ab686fa6284a980ba283617404377cd448f631"}, + {file = "websockets-10.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:da39dd03d130162deb63da51f6e66ed73032ae62e74aaccc4236e30edccddbb0"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:389f8dbb5c489e305fb113ca1b6bdcdaa130923f77485db5b189de343a179393"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:09a1814bb15eff7069e51fed0826df0bc0702652b5cb8f87697d469d79c23576"}, + {file = "websockets-10.4-pp38-pypy38_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ff64a1d38d156d429404aaa84b27305e957fd10c30e5880d1765c9480bea490f"}, + {file = "websockets-10.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:b343f521b047493dc4022dd338fc6db9d9282658862756b4f6fd0e996c1380e1"}, + {file = "websockets-10.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:932af322458da7e4e35df32f050389e13d3d96b09d274b22a7aa1808f292fee4"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d6a4162139374a49eb18ef5b2f4da1dd95c994588f5033d64e0bbfda4b6b6fcf"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c57e4c1349fbe0e446c9fa7b19ed2f8a4417233b6984277cce392819123142d3"}, + {file = "websockets-10.4-pp39-pypy39_pp73-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b627c266f295de9dea86bd1112ed3d5fafb69a348af30a2422e16590a8ecba13"}, + {file = "websockets-10.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:05a7233089f8bd355e8cbe127c2e8ca0b4ea55467861906b80d2ebc7db4d6b72"}, + {file = "websockets-10.4.tar.gz", hash = "sha256:eef610b23933c54d5d921c92578ae5f89813438fded840c2e9809d378dc765d3"}, +] + +[[package]] +name = "zipp" +version = "3.16.2" +description = "Backport of pathlib-compatible object wrapper for zip files" +optional = false +python-versions = ">=3.8" +files = [ + {file = "zipp-3.16.2-py3-none-any.whl", hash = "sha256:679e51dd4403591b2d6838a48de3d283f3d188412a9782faadf845f298736ba0"}, + {file = "zipp-3.16.2.tar.gz", hash = "sha256:ebc15946aa78bd63458992fc81ec3b6f7b1e92d51c35e6de1c3804e73b799147"}, +] + +[package.extras] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy (>=0.9.1)", "pytest-ruff"] + +[metadata] +lock-version = "2.0" +python-versions = "^3.8" +content-hash = "beb9403ccbf64a92b997c341935d6fc18aa9702093ed6a289585a58d035d513e" diff --git a/openbb_sdk/providers/quandl/pyproject.toml b/openbb_sdk/providers/quandl/pyproject.toml new file mode 100644 index 00000000000..d4c1eda8293 --- /dev/null +++ b/openbb_sdk/providers/quandl/pyproject.toml @@ -0,0 +1,19 @@ +[tool.poetry] +name = "openbb-quandl" +version = "0.1.0" +description = "" +authors = ["OpenBB Team "] +readme = "README.md" +packages = [{ include = "openbb_quandl" }] + +[tool.poetry.dependencies] +python = "^3.8" +quandl = ">=3.7.0" +openbb-core = { path = "../../sdk/core" } + +[build-system] +requires = ["poetry-core"] +build-backend = "poetry.core.masonry.api" + +[tool.poetry.plugins."openbb_provider_extension"] +quandl = "openbb_quandl:quandl_provider" diff --git a/openbb_sdk/providers/quandl/tests/.gitkeep b/openbb_sdk/providers/quandl/tests/.gitkeep new file mode 100644 index 00000000000..e69de29bb2d diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/__init__.py b/openbb_sdk/providers/yfinance/openbb_yfinance/__init__.py index e687e8ff01e..2a5181dc3ce 100644 --- a/openbb_sdk/providers/yfinance/openbb_yfinance/__init__.py +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/__init__.py @@ -3,12 +3,19 @@ from openbb_provider.abstract.provider import Provider -from openbb_yfinance.models.crypto_eod import YFinanceCryptoEODFetcher -from openbb_yfinance.models.forex_eod import YFinanceForexEODFetcher +from openbb_yfinance.models.available_indices import YFinanceAvailableIndicesFetcher +from openbb_yfinance.models.balance_sheet import YFinanceBalanceSheetFetcher +from openbb_yfinance.models.cash_flow import YFinanceCashFlowStatementFetcher +from openbb_yfinance.models.crypto_historical import YFinanceCryptoHistoricalFetcher +from openbb_yfinance.models.forex_historical import YFinanceForexHistoricalFetcher from openbb_yfinance.models.futures_curve import YFinanceFuturesCurveFetcher -from openbb_yfinance.models.futures_eod import YFinanceFuturesEODFetcher -from openbb_yfinance.models.major_indices_eod import YFinanceMajorIndicesEODFetcher -from openbb_yfinance.models.stock_eod import YFinanceStockEODFetcher +from openbb_yfinance.models.futures_historical import YFinanceFuturesHistoricalFetcher +from openbb_yfinance.models.income_statement import YFinanceIncomeStatementFetcher +from openbb_yfinance.models.major_indices_historical import ( + YFinanceMajorIndicesHistoricalFetcher, +) +from openbb_yfinance.models.stock_historical import YFinanceStockHistoricalFetcher +from openbb_yfinance.models.stock_news import YFinanceStockNewsFetcher yfinance_provider = Provider( name="yfinance", @@ -16,13 +23,17 @@ yfinance_provider = Provider( description="""Yahoo! Finance is a web-based platform that offers financial news, data, and tools for investors and individuals interested in tracking and analyzing financial markets and assets.""", - required_credentials=None, fetcher_dict={ - "CryptoEOD": YFinanceCryptoEODFetcher, - "ForexEOD": YFinanceForexEODFetcher, - "MajorIndicesEOD": YFinanceMajorIndicesEODFetcher, - "StockEOD": YFinanceStockEODFetcher, - "FuturesEOD": YFinanceFuturesEODFetcher, + "CryptoHistorical": YFinanceCryptoHistoricalFetcher, + "ForexHistorical": YFinanceForexHistoricalFetcher, + "MajorIndicesHistorical": YFinanceMajorIndicesHistoricalFetcher, + "StockHistorical": YFinanceStockHistoricalFetcher, + "FuturesHistorical": YFinanceFuturesHistoricalFetcher, "FuturesCurve": YFinanceFuturesCurveFetcher, + "StockNews": YFinanceStockNewsFetcher, + "BalanceSheet": YFinanceBalanceSheetFetcher, + "CashFlowStatement": YFinanceCashFlowStatementFetcher, + "IncomeStatement": YFinanceIncomeStatementFetcher, + "AvailableIndices": YFinanceAvailableIndicesFetcher, }, ) diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/available_indices.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/available_indices.py new file mode 100644 index 00000000000..690b2766305 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/available_indices.py @@ -0,0 +1,58 @@ +"""Available Indices Fetcher for YFinance.""" + +from typing import Any, Dict, List, Optional + +import pandas as pd +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.available_indices import ( + AvailableIndicesData, + AvailableIndicesQueryParams, +) +from pydantic import Field + +from openbb_yfinance.utils.references import INDICES + + +class YFinanceAvailableIndicesQueryParams(AvailableIndicesQueryParams): + """Available Indices query for YFinance.""" + + +class YFinanceAvailableIndicesData(AvailableIndicesData): + """Available Indices data for YFinance.""" + + code: str = Field( + description="ID code for keying the index in the OpenBB Terminal." + ) + symbol: str = Field( + description="yFinance ticker symbol for the index.", alias="ticker" + ) + + +class YFinanceAvailableIndicesFetcher( + Fetcher[ + YFinanceAvailableIndicesQueryParams, + List[YFinanceAvailableIndicesData], + ] +): + """Transform the query, extract and transform the data.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceAvailableIndicesQueryParams: + """Transform the query params.""" + return YFinanceAvailableIndicesQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceAvailableIndicesQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[Dict]: + indices = pd.DataFrame(INDICES).transpose().reset_index() + indices.columns = ["code", "name", "ticker"] + + return indices.to_dict("records") + + @staticmethod + def transform_data(data: List[Dict]) -> List[YFinanceAvailableIndicesData]: + """Return the transformed data.""" + return [YFinanceAvailableIndicesData(**d) for d in data] diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/balance_sheet.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/balance_sheet.py new file mode 100644 index 00000000000..e547f929752 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/balance_sheet.py @@ -0,0 +1,63 @@ +"""yfinance Balance Sheet Fetcher.""" + + +import json +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.balance_sheet import ( + BalanceSheetData, + BalanceSheetQueryParams, +) +from pydantic import validator +from yfinance import Ticker + + +class YFinanceBalanceSheetQueryParams(BalanceSheetQueryParams): + """yfinance Balance Sheet QueryParams. + + Source: https://finance.yahoo.com/ + """ + + +class YFinanceBalanceSheetData(BalanceSheetData): + """yfinance Balance Sheet Data.""" + + # TODO: Standardize the fields + + @validator("date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + return datetime.strptime(v, "%Y-%m-%d %H:%M:%S").date() + + +class YFinanceBalanceSheetFetcher( + Fetcher[ + YFinanceBalanceSheetQueryParams, + YFinanceBalanceSheetData, + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceBalanceSheetQueryParams: + return YFinanceBalanceSheetQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceBalanceSheetQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[YFinanceBalanceSheetData]: + query.period = "yearly" if query.period == "annually" else "quarterly" + data = Ticker(query.symbol).get_balance_sheet( + as_dict=True, pretty=False, freq=query.period + ) + data = [{"date": str(key), **value} for key, value in data.items()] + data = json.loads(json.dumps(data)) + + return [YFinanceBalanceSheetData.parse_obj(d) for d in data] + + @staticmethod + def transform_data( + data: List[YFinanceBalanceSheetData], + ) -> List[YFinanceBalanceSheetData]: + return data diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/cash_flow.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/cash_flow.py new file mode 100644 index 00000000000..3d531aefd36 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/cash_flow.py @@ -0,0 +1,63 @@ +"""yfinance Cash Flow Statement Fetcher.""" + + +import json +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.cash_flow import ( + CashFlowStatementData, + CashFlowStatementQueryParams, +) +from pydantic import validator +from yfinance import Ticker + + +class YFinanceCashFlowStatementQueryParams(CashFlowStatementQueryParams): + """yfinance Cash Flow Statement QueryParams. + + Source: https://finance.yahoo.com/ + """ + + +class YFinanceCashFlowStatementData(CashFlowStatementData): + """yfinance Cash Flow Statement Data.""" + + # TODO: Standardize the fields + + @validator("date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + return datetime.strptime(v, "%Y-%m-%d %H:%M:%S").date() + + +class YFinanceCashFlowStatementFetcher( + Fetcher[ + YFinanceCashFlowStatementQueryParams, + YFinanceCashFlowStatementData, + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceCashFlowStatementQueryParams: + return YFinanceCashFlowStatementQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceCashFlowStatementQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[YFinanceCashFlowStatementData]: + query.period = "yearly" if query.period == "annually" else "quarterly" + data = Ticker(query.symbol).get_cash_flow( + as_dict=True, pretty=False, freq=query.period + ) + data = [{"date": str(key), **value} for key, value in data.items()] + data = json.loads(json.dumps(data)) + + return [YFinanceCashFlowStatementData.parse_obj(d) for d in data] + + @staticmethod + def transform_data( + data: List[YFinanceCashFlowStatementData], + ) -> List[YFinanceCashFlowStatementData]: + return data diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/crypto_historical.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/crypto_historical.py new file mode 100644 index 00000000000..1aa761d7f50 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/crypto_historical.py @@ -0,0 +1,112 @@ +"""yfinance Crypto End of Day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.crypto_historical import ( + CryptoHistoricalData, + CryptoHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, validator +from yfinance import Ticker + +from openbb_yfinance.utils.references import INTERVALS, PERIODS + + +class YFinanceCryptoHistoricalQueryParams(CryptoHistoricalQueryParams): + """YFinance Crypto End of Day Query. + + Source: https://finance.yahoo.com/crypto/ + """ + + interval: Optional[INTERVALS] = Field(default="1d", description="Data granularity.") + period: Optional[PERIODS] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("period", "") + ) + prepost: bool = Field( + default=False, description="Include Pre and Post market data." + ) + adjust: bool = Field(default=True, description="Adjust all the data automatically.") + back_adjust: bool = Field( + default=False, description="Back-adjusted data to mimic true historical prices." + ) + + +class YFinanceCryptoHistoricalData(CryptoHistoricalData): + """YFinance Crypto End of Day Data.""" + + @validator("Date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return datetime object from string.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S") + + +class YFinanceCryptoHistoricalFetcher( + Fetcher[ + YFinanceCryptoHistoricalQueryParams, + List[YFinanceCryptoHistoricalData], + ] +): + """Transform the query, extract and transform the data from the yfinance endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceCryptoHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + if params.get("period") is None: + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return YFinanceCryptoHistoricalQueryParams(**transformed_params) + + return YFinanceCryptoHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceCryptoHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the yfinance endpoint.""" + if query.period: + data = Ticker(query.symbol).history( + interval=query.interval, + period=query.period, + actions=False, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + raise_errors=True, + ) + else: + data = Ticker(query.symbol).history( + interval=query.interval, + start=query.start_date, + end=query.end_date, + actions=False, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + raise_errors=True, + ) + + data = data.reset_index() + data["Date"] = ( + data["Date"].dt.tz_localize(None).dt.strftime("%Y-%m-%dT%H:%M:%S") + ) + return data.to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[YFinanceCryptoHistoricalData]: + """Transform the data to the standard format.""" + return [YFinanceCryptoHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/forex_historical.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/forex_historical.py new file mode 100644 index 00000000000..24aef6c6b1f --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/forex_historical.py @@ -0,0 +1,116 @@ +"""yfinance Forex End of Day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.forex_historical import ( + ForexHistoricalData, + ForexHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, validator +from yfinance import Ticker + +from openbb_yfinance.utils.references import INTERVALS, PERIODS + + +class YFinanceForexHistoricalQueryParams(ForexHistoricalQueryParams): + """YFinance Forex End of Day Query. + + Source: https://finance.yahoo.com/currencies/ + """ + + interval: Optional[INTERVALS] = Field(default="1d", description="Data granularity.") + period: Optional[PERIODS] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("period", "") + ) + prepost: bool = Field( + default=False, description="Include Pre and Post market data." + ) + adjust: bool = Field(default=True, description="Adjust all the data automatically.") + back_adjust: bool = Field( + default=False, description="Back-adjusted data to mimic true historical prices." + ) + + +class YFinanceForexHistoricalData(ForexHistoricalData): + """YFinance Forex End of Day Data.""" + + @validator("Date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return datetime object from string.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S") + + +class YFinanceForexHistoricalFetcher( + Fetcher[ + YFinanceForexHistoricalQueryParams, + List[YFinanceForexHistoricalData], + ] +): + """Transform the query, extract and transform the data from the yfinance endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceForexHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + if params.get("period") is None: + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return YFinanceForexHistoricalQueryParams(**transformed_params) + + return YFinanceForexHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceForexHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the yfinance endpoint.""" + query.symbol = f"{query.symbol}=X" + + if query.period: + data = Ticker(query.symbol).history( + interval=query.interval, + period=query.period, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + + else: + data = Ticker(query.symbol).history( + interval=query.interval, + start=query.start_date, + end=query.end_date, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + + data = data.reset_index() + data["Date"] = ( + data["Date"].dt.tz_localize(None).dt.strftime("%Y-%m-%dT%H:%M:%S") + ) + + return data.to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[YFinanceForexHistoricalData]: + """Transform the data to the standard format.""" + return [YFinanceForexHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/futures_historical.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/futures_historical.py new file mode 100644 index 00000000000..7233edaea53 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/futures_historical.py @@ -0,0 +1,125 @@ +"""yfinance Futures End of Day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.futures_historical import ( + FuturesHistoricalData, + FuturesHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, validator +from yfinance import Ticker + +from openbb_yfinance.utils.helpers import get_futures_data +from openbb_yfinance.utils.references import INTERVALS, MONTHS, PERIODS + + +class YFinanceFuturesHistoricalQueryParams(FuturesHistoricalQueryParams): + """YFinance Futures End of Day Query. + + Source: https://finance.yahoo.com/crypto/ + """ + + interval: Optional[INTERVALS] = Field(default="1d", description="Data granularity.") + period: Optional[PERIODS] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("period", "") + ) + prepost: bool = Field( + default=False, description="Include Pre and Post market data." + ) + adjust: bool = Field(default=True, description="Adjust all the data automatically.") + back_adjust: bool = Field( + default=False, description="Back-adjusted data to mimic true historical prices." + ) + + +class YFinanceFuturesHistoricalData(FuturesHistoricalData): + """YFinance Futures End of Day Data.""" + + @validator("Date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return datetime object from string.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S") + + +class YFinanceFuturesHistoricalFetcher( + Fetcher[ + YFinanceFuturesHistoricalQueryParams, + List[YFinanceFuturesHistoricalData], + ] +): + """Transform the query, extract and transform the data from the yfinance endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceFuturesHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + if params.get("period") is None: + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return YFinanceFuturesHistoricalQueryParams(**transformed_params) + + return YFinanceFuturesHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceFuturesHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the yfinance endpoint.""" + symbol = "" + + if query.expiration: + expiry_date = datetime.strptime(query.expiration, "%Y-%m") + futures_data = get_futures_data() + exchange = futures_data[futures_data["Ticker"] == query.symbol][ + "Exchange" + ].values[0] + symbol = f"{query.symbol}{MONTHS[expiry_date.month]}{str(expiry_date.year)[-2:]}.{exchange}" + + query_symbol = symbol if symbol else f"{query.symbol}=F" + + if query.period: + data = Ticker(query_symbol).history( + interval=query.interval, + period=query.period, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + else: + data = Ticker(query_symbol).history( + interval=query.interval, + start=query.start_date, + end=query.end_date, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + + data = data.reset_index() + data["Date"] = ( + data["Date"].dt.tz_localize(None).dt.strftime("%Y-%m-%dT%H:%M:%S") + ) + return data.to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[YFinanceFuturesHistoricalData]: + """Transform the data to the standard format.""" + return [YFinanceFuturesHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/income_statement.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/income_statement.py new file mode 100644 index 00000000000..adce92c41a2 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/income_statement.py @@ -0,0 +1,63 @@ +"""yfinance Income Statement Fetcher.""" + + +import json +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.income_statement import ( + IncomeStatementData, + IncomeStatementQueryParams, +) +from pydantic import validator +from yfinance import Ticker + + +class YFinanceIncomeStatementQueryParams(IncomeStatementQueryParams): + """yfinance Income Statement QueryParams. + + Source: https://finance.yahoo.com/ + """ + + +class YFinanceIncomeStatementData(IncomeStatementData): + """yfinance Income Statement Data.""" + + # TODO: Standardize the fields + + @validator("date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + return datetime.strptime(v, "%Y-%m-%d %H:%M:%S").date() + + +class YFinanceIncomeStatementFetcher( + Fetcher[ + YFinanceIncomeStatementQueryParams, + YFinanceIncomeStatementData, + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceIncomeStatementQueryParams: + return YFinanceIncomeStatementQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceIncomeStatementQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[YFinanceIncomeStatementData]: + query.period = "yearly" if query.period == "annually" else "quarterly" + data = Ticker(query.symbol).get_income_stmt( + as_dict=True, pretty=False, freq=query.period + ) + data = [{"date": str(key), **value} for key, value in data.items()] + data = json.loads(json.dumps(data)) + + return [YFinanceIncomeStatementData.parse_obj(d) for d in data] + + @staticmethod + def transform_data( + data: List[YFinanceIncomeStatementData], + ) -> List[YFinanceIncomeStatementData]: + return data diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/major_indices_historical.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/major_indices_historical.py new file mode 100644 index 00000000000..00c6626c4c4 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/major_indices_historical.py @@ -0,0 +1,116 @@ +"""yfinance Major Indices End of Day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.major_indices_historical import ( + MajorIndicesHistoricalData, + MajorIndicesHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, validator +from yfinance import Ticker + +from openbb_yfinance.utils.references import INTERVALS, PERIODS + + +class YFinanceMajorIndicesHistoricalQueryParams(MajorIndicesHistoricalQueryParams): + """YFinance Major Indices End of Day Query. + + Source: https://finance.yahoo.com/world-indices + """ + + interval: Optional[INTERVALS] = Field(default="1d", description="Data granularity.") + period: Optional[PERIODS] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("period", "") + ) + prepost: bool = Field( + default=False, description="Include Pre and Post market data." + ) + adjust: bool = Field(default=True, description="Adjust all the data automatically.") + back_adjust: bool = Field( + default=False, description="Back-adjusted data to mimic true historical prices." + ) + + +class YFinanceMajorIndicesHistoricalData(MajorIndicesHistoricalData): + """YFinance Major Indices End of Day Data.""" + + @validator("Date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return datetime object from string.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S") + + +class YFinanceMajorIndicesHistoricalFetcher( + Fetcher[ + YFinanceMajorIndicesHistoricalQueryParams, + List[YFinanceMajorIndicesHistoricalData], + ] +): + """Transform the query, extract and transform the data from the yfinance endpoints.""" + + @staticmethod + def transform_query( + params: Dict[str, Any] + ) -> YFinanceMajorIndicesHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + if params.get("period") is None: + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return YFinanceMajorIndicesHistoricalQueryParams(**transformed_params) + + return YFinanceMajorIndicesHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceMajorIndicesHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the yfinance endpoint.""" + query.symbol = f"^{query.symbol}" + + if query.period: + data = Ticker(query.symbol).history( + interval=query.interval, + period=query.period, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + else: + data = Ticker(query.symbol).history( + interval=query.interval, + start=query.start_date, + end=query.end_date, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + + data = data.reset_index() + data["Date"] = ( + data["Date"].dt.tz_localize(None).dt.strftime("%Y-%m-%dT%H:%M:%S") + ) + return data.to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[YFinanceMajorIndicesHistoricalData]: + """Transform the data to the standard format.""" + return [YFinanceMajorIndicesHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/stock_historical.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/stock_historical.py new file mode 100644 index 00000000000..7902f6ffc8f --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/stock_historical.py @@ -0,0 +1,112 @@ +"""yfinance Stock End of Day fetcher.""" + + +from datetime import datetime +from typing import Any, Dict, List, Optional + +from dateutil.relativedelta import relativedelta +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_historical import ( + StockHistoricalData, + StockHistoricalQueryParams, +) +from openbb_provider.utils.descriptions import QUERY_DESCRIPTIONS +from pydantic import Field, validator +from yfinance import Ticker + +from openbb_yfinance.utils.references import INTERVALS, PERIODS + + +class YFinanceStockHistoricalQueryParams(StockHistoricalQueryParams): + """YFinance Stock End of Day Query. + + Source: https://finance.yahoo.com/ + """ + + interval: Optional[INTERVALS] = Field(default="1d", description="Data granularity.") + period: Optional[PERIODS] = Field( + default=None, description=QUERY_DESCRIPTIONS.get("period", "") + ) + prepost: bool = Field( + default=False, description="Include Pre and Post market data." + ) + adjust: bool = Field(default=True, description="Adjust all the data automatically.") + back_adjust: bool = Field( + default=False, description="Back-adjusted data to mimic true historical prices." + ) + + +class YFinanceStockHistoricalData(StockHistoricalData): + """YFinance Stock End of Day Data.""" + + @validator("Date", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + """Return datetime object from string.""" + return datetime.strptime(v, "%Y-%m-%dT%H:%M:%S") + + +class YFinanceStockHistoricalFetcher( + Fetcher[ + YFinanceStockHistoricalQueryParams, + List[YFinanceStockHistoricalData], + ] +): + """Transform the query, extract and transform the data from the yfinance endpoints.""" + + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceStockHistoricalQueryParams: + """Transform the query. Setting the start and end dates for a 1 year period.""" + if params.get("period") is None: + transformed_params = params + + now = datetime.now().date() + if params.get("start_date") is None: + transformed_params["start_date"] = now - relativedelta(years=1) + + if params.get("end_date") is None: + transformed_params["end_date"] = now + return YFinanceStockHistoricalQueryParams(**transformed_params) + + return YFinanceStockHistoricalQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceStockHistoricalQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> dict: + """Return the raw data from the yfinance endpoint.""" + if query.period: + data = Ticker(query.symbol).history( + interval=query.interval, + period=query.period, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + else: + data = Ticker(query.symbol).history( + interval=query.interval, + start=query.start_date, + end=query.end_date, + prepost=query.prepost, + auto_adjust=query.adjust, + back_adjust=query.back_adjust, + actions=False, + raise_errors=True, + ) + + data = data.reset_index() + data["Date"] = ( + data["Date"].dt.tz_localize(None).dt.strftime("%Y-%m-%dT%H:%M:%S") + ) + return data.to_dict("records") + + @staticmethod + def transform_data( + data: dict, + ) -> List[YFinanceStockHistoricalData]: + """Transform the data to the standard format.""" + return [YFinanceStockHistoricalData.parse_obj(d) for d in data] diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/models/stock_news.py b/openbb_sdk/providers/yfinance/openbb_yfinance/models/stock_news.py new file mode 100644 index 00000000000..ad587b32da4 --- /dev/null +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/models/stock_news.py @@ -0,0 +1,72 @@ +"""yfinance Stock News fetcher.""" + + +import json +from datetime import datetime +from typing import Any, Dict, List, Optional + +from openbb_provider.abstract.fetcher import Fetcher +from openbb_provider.standard_models.stock_news import ( + StockNewsData, + StockNewsQueryParams, +) +from pydantic import Field, validator +from yfinance import Ticker + + +class YFinanceStockNewsQueryParams(StockNewsQueryParams): + """YFinance Stock News Query. + + Source: https://finance.yahoo.com/news/ + """ + + +class YFinanceStockNewsData(StockNewsData): + """YFinance Stock News Data.""" + + class Config: + fields = { + "date": "providerPublishTime", + "url": "link", + } + + uuid: str = Field(description="Unique identifier for the news article") + publisher: str = Field(description="Publisher of the news article") + type: str = Field(description="Type of the news article") + thumbnail: Dict[str, Any] = Field( + description="Thumbnail related data to the ticker news article." + ) + relatedTickers: str = Field(description="Tickers related to the news article.") + + @validator("providerPublishTime", pre=True, check_fields=False) + def date_validate(cls, v): # pylint: disable=E0213 + return datetime.fromtimestamp(v) + + +class YFinanceStockNewsFetcher( + Fetcher[ + YFinanceStockNewsQueryParams, + YFinanceStockNewsData, + ] +): + @staticmethod + def transform_query(params: Dict[str, Any]) -> YFinanceStockNewsQueryParams: + return YFinanceStockNewsQueryParams(**params) + + @staticmethod + def extract_data( + query: YFinanceStockNewsQueryParams, + credentials: Optional[Dict[str, str]], + **kwargs: Any, + ) -> List[YFinanceStockNewsData]: + data = Ticker(query.symbols).get_news() + data = json.loads(json.dumps(data)) + data = [{**d, "relatedTickers": ",".join(d["relatedTickers"])} for d in data] + + return [YFinanceStockNewsData.parse_obj(d) for d in data] + + @staticmethod + def transform_data( + data: List[YFinanceStockNewsData], + ) -> List[YFinanceStockNewsData]: + return data diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/utils/helpers.py b/openbb_sdk/providers/yfinance/openbb_yfinance/utils/helpers.py index a77751a185a..089cb081e7c 100644 --- a/openbb_sdk/providers/yfinance/openbb_yfinance/utils/helpers.py +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/utils/helpers.py @@ -6,7 +6,7 @@ from datetime import ( datetime, ) from pathlib import Path -from typing import Optional +from typing import Any, Literal, Optional, Union import pandas as pd import yfinance as yf @@ -77,3 +77,98 @@ def get_futures_curve(symbol: str, date: Optional[dateType]) -> pd.DataFrame: {"Last Price": historical_curve, "expiration": futures_index} ) return pd.DataFrame({"Last Price": futures_curve, "expiration": futures_index}) + + +def yf_download( + symbol: str, + start_date: Optional[Union[str, dateType]] = None, + end_date: Optional[Union[str, dateType]] = None, + interval: str = "1d", + period: str = "max", + prepost: bool = False, + actions: bool = False, + auto_adjust: bool = False, + back_adjust: bool = False, + progress: bool = False, + ignore_tz: bool = True, + keepna: bool = False, + repair: bool = False, + rounding: bool = False, + group_by: Literal["symbol", "column"] = "column", + **kwargs: Any, +) -> pd.DataFrame: + """Base level yFinance OHLC helper function for returning any ticker and interval available.""" + + symbol = symbol.upper() + _start_date = start_date + + if interval in ["60m", "1h"]: + period = "2y" if period in ["5y", "10y", "max"] else period + _start_date = None + + if interval in ["2m", "5m", "15m", "30m", "90m"]: + _start_date = (datetime.now().date() - relativedelta(days=59)).strftime( + "%Y-%m-%d" + ) + + if interval == "1m": + period = "5d" + _start_date = None + + data = yf.download( + tickers=symbol, + start=_start_date, + end=None, + interval=interval, + period=period, + prepost=prepost, + auto_adjust=auto_adjust, + back_adjust=back_adjust, + actions=actions, + progress=progress, + ignore_tz=ignore_tz, + keepna=keepna, + repair=repair, + rounding=rounding, + group_by=group_by, + ) + if not data.empty: + data = data.reset_index() + data = data.rename(columns={"Date": "date", "Datetime": "date"}) + data["date"] = pd.to_datetime(data["date"]) + data = data[data["Open"] > 0] + + if start_date is not None: + data = data[data["date"] >= pd.to_datetime(start_date)] + if end_date is not None and pd.to_datetime(end_date) > pd.to_datetime( + start_date + ): + data = data[ + data["date"] <= (pd.to_datetime(end_date) + relativedelta(days=1)) + ] + + if period not in [ + "max", + "1d", + "5d", + "1wk", + "1mo", + "3mo", + "6mo", + "1y", + "2y", + "5y", + "10y", + ]: + data["date"] = ( + data["date"].dt.tz_localize(None).dt.strftime("%Y-%m-%d %H:%M:%S") + ) + if interval not in ["1m", "2m", "5m", "15m", "30m", "90m", "60m", "1h"]: + data["date"] = data["date"].dt.tz_localize(None).dt.strftime("%Y-%m-%d") + + if actions is False: + data = data.drop(columns=["Adj Close"]) + + data.columns = data.columns.str.lower().to_list() + + return data diff --git a/openbb_sdk/providers/yfinance/openbb_yfinance/utils/references.py b/openbb_sdk/providers/yfinance/openbb_yfinance/utils/references.py index d6139a338e3..5c75a1f29c9 100644 --- a/openbb_sdk/providers/yfinance/openbb_yfinance/utils/references.py +++ b/openbb_sdk/providers/yfinance/openbb_yfinance/utils/references.py @@ -24,3 +24,589 @@ MONTHS = { 11: "X", 12: "Z", } + +INDICES = { + "sp500": {"name": "S&P 500 Index", "ticker": "^GSPC"}, + "spx": {"name": "S&P 500 Index", "ticker": "^SPX"}, + "sp400": {"name": "S&P 400 Mid Cap Index", "ticker": "^SP400"}, + "sp600": {"name": "S&P 600 Small Cap Index", "ticker": "^SP600"}, + "sp500tr": {"name": "S&P 500 TR Index", "ticker": "^SP500TR"}, + "sp_xsp": {"name": "S&P 500 Mini SPX Options Index", "ticker": "^XSP"}, + "nyse_ny": {"name": "NYSE US 100 Index", "ticker": "^NY"}, + "dow_djus": {"name": "Dow Jones US Index", "ticker": "^DJUS"}, + "nyse": {"name": "NYSE Composite Index", "ticker": "^NYA"}, + "amex": {"name": "NYSE-AMEX Composite Index", "ticker": "^XAX"}, + "nasdaq": {"name": "Nasdaq Composite Index", "ticker": "^IXIC"}, + "nasdaq100": {"name": "NASDAQ 100", "ticker": "^NDX"}, + "nasdaq100_ew": {"name": "NASDAQ 100 Equal Weighted Index", "ticker": "^NDXE"}, + "nasdaq50": {"name": "NASDAQ Q50 Index", "ticker": "^NXTQ"}, + "russell1000": {"name": "Russell 1000 Index", "ticker": "^RUI"}, + "russell2000": {"name": "Russell 2000 Index", "ticker": "^RUT"}, + "cboe_bxr": {"name": "CBOE Russell 2000 Buy-Write Index", "ticker": "^BXR"}, + "cboe_bxrt": { + "name": "CBOE Russell 2000 30-Delta Buy-Write Index", + "ticker": "^BXRT", + }, + "russell3000": {"name": "Russell 3000 Index", "ticker": "^RUA"}, + "russellvalue": {"name": "Russell 2000 Value Index", "ticker": "^RUJ"}, + "russellgrowth": {"name": "Russell 2000 Growth Index", "ticker": "^RUO"}, + "w5000": {"name": "Wilshire 5000", "ticker": "^W5000"}, + "w5000flt": {"name": "Wilshire 5000 Float Adjusted Index", "ticker": "^W5000FLT"}, + "dow_dja": {"name": "Dow Jones Composite Average Index", "ticker": "^DJA"}, + "dow_dji": {"name": "Dow Jones Industrial Average Index", "ticker": "^DJI"}, + "ca_tsx": {"name": "TSX Composite Index (CAD)", "ticker": "^GSPTSE"}, + "ca_banks": {"name": "S&P/TSX Composite Banks Index (CAD)", "ticker": "TXBA.TS"}, + "mx_ipc": {"name": "IPC Mexico Index (MXN)", "ticker": "^MXX"}, + "arca_mxy": {"name": "NYSE ARCA Mexico Index (USD)", "ticker": "^MXY"}, + "br_bvsp": {"name": "IBOVESPA Sao Paulo Brazil Index (BRL)", "ticker": "^BVSP"}, + "br_ivbx": {"name": "IVBX2 Indice Valour (BRL)", "ticker": "^IVBX"}, + "ar_mervel": {"name": "S&P MERVAL TR Index (USD)", "ticker": "M.BA"}, + "eu_fteu1": {"name": "FTSE Eurotop 100 Index (EUR)", "ticker": "^FTEU1"}, + "eu_speup": {"name": "S&P Europe 350 Index (EUR)", "ticker": "^SPEUP"}, + "eu_n100": {"name": "Euronext 100 Index (EUR)", "ticker": "^N100"}, + "ftse100": {"name": "FTSE Global 100 Index (GBP)", "ticker": "^FTSE"}, + "ftse250": {"name": "FTSE Global 250 Index (GBP)", "ticker": "^FTMC"}, + "ftse350": {"name": "FTSE Global 350 Index (GBP)", "ticker": "^FTLC"}, + "ftai": {"name": "FTSE AIM All-Share Global Index (GBP)", "ticker": "^FTAI"}, + "uk_ftas": {"name": "UK FTSE All-Share Index (GBP)", "ticker": "^FTAS"}, + "uk_spuk": {"name": "S&P United Kingdom Index (PDS)", "ticker": "^SPUK"}, + "uk_100": {"name": "CBOE UK 100 Index (GBP)", "ticker": "^BUK100P"}, + "ie_iseq": {"name": "ISEQ Irish All Shares Index (EUR)", "ticker": "^ISEQ"}, + "nl_aex": {"name": "Euronext Dutch 25 Index (EUR)", "ticker": "^AEX"}, + "nl_amx": {"name": "Euronext Dutch Mid Cap Index (EUR)", "ticker": "^AMX"}, + "at_atx": {"name": "Wiener Börse Austrian 20 Index (EUR)", "ticker": "^ATX"}, + "at_atx5": {"name": "Vienna ATX Five Index (EUR)", "ticker": "^ATX5"}, + "at_prime": {"name": "Vienna ATX Prime Index (EUR)", "ticker": "^ATXPRIME"}, + "ch_stoxx": {"name": "Zurich STXE 600 PR Index (EUR)", "ticker": "^STOXX"}, + "ch_stoxx50e": {"name": "Zurich ESTX 50 PR Index (EUR)", "ticker": "^STOXX50E"}, + "se_omx30": {"name": "OMX Stockholm 30 Index (SEK)", "ticker": "^OMX"}, + "se_omxspi": {"name": "OMX Stockholm All Share PI (SEK)", "ticker": "^OMXSPI"}, + "se_benchmark": {"name": "OMX Stockholm Benchmark GI (SEK)", "ticker": "^OMXSBGI"}, + "dk_benchmark": {"name": "OMX Copenhagen Benchmark GI (DKK)", "ticker": "^OMXCBGI"}, + "dk_omxc25": {"name": "OMX Copenhagen 25 Index (DKK)", "ticker": "^OMXC25"}, + "fi_omxh25": {"name": "OMX Helsinki 25 (EUR)", "ticker": "^OMXH25"}, + "de_dax40": {"name": "DAX Performance Index (EUR)", "ticker": "^GDAXI"}, + "de_mdax60": {"name": "DAX Mid Cap Performance Index (EUR)", "ticker": "^MDAXI"}, + "de_sdax70": {"name": "DAX Small Cap Performance Index (EUR)", "ticker": "^SDAXI"}, + "de_tecdax30": {"name": "DAX Tech Sector TR Index (EUR)", "ticker": "^TECDAX"}, + "fr_cac40": {"name": "CAC 40 PR Index (EUR)", "ticker": "^FCHI"}, + "fr_next20": {"name": "CAC Next 20 Index (EUR)", "ticker": "^CN20"}, + "it_mib40": {"name": "FTSE MIB 40 Index (EUR)", "ticker": "FTSEMIB.MI"}, + "be_bel20": {"name": "BEL 20 Brussels Index (EUR)", "ticker": "^BFX"}, + "pt_bvlg": { + "name": "Lisbon PSI All-Share Index GR (EUR)", + "ticker": "^BVLG", + }, + "es_ibex35": {"name": "IBEX 35 - Madrid CATS (EUR)", "ticker": "^IBEX"}, + "in_bse": {"name": "S&P Bombay SENSEX (INR)", "ticker": "^BSESN"}, + "in_bse500": { + "name": "S&P BSE 500 Index (INR)", + "ticker": "BSE-500.BO", + }, + "in_bse200": { + "name": "S&P BSE 200 Index (INR)", + "ticker": "BSE-200.BO", + }, + "in_bse100": { + "name": "S&P BSE 100 Index (INR)", + "ticker": "BSE-100.BO", + }, + "in_bse_mcap": { + "name": "S&P Bombay Mid Cap Index (INR)", + "ticker": "BSE-MIDCAP.BO", + }, + "in_bse_scap": { + "name": "S&P Bombay Small Cap Index (INR)", + "ticker": "BSE-SMLCAP.BO", + }, + "in_nse50": {"name": "NSE Nifty 50 Index (INR)", "ticker": "^NSEI"}, + "in_nse_mcap": {"name": "NSE Nifty 50 Mid Cap Index (INR)", "ticker": "^NSEMDCP50"}, + "in_nse_bank": { + "name": "NSE Nifty Bank Industry Index (INR)", + "ticker": "^NSEBANK", + }, + "in_nse500": {"name": "NSE Nifty 500 Index (INR)", "ticker": "^CRSLDX"}, + "il_ta125": {"name": "Tel-Aviv 125 Index (ILS)", "ticker": "^TA125.TA"}, + "za_shariah": { + "name": "Johannesburg Shariah All Share Index (ZAR)", + "ticker": "^J143.JO", + }, + "za_jo": {"name": "Johannesburg All Share Index (ZAR)", "ticker": "^J203.JO"}, + "za_jo_mcap": { + "name": "Johannesburg Large and Mid Cap Index (ZAR)", + "ticker": "^J206.JO", + }, + "za_jo_altex": { + "name": "Johannesburg Alt Exchange Index (ZAR)", + "ticker": "^J232.JO", + }, + "ru_moex": {"name": "MOEX Russia Index (RUB)", "ticker": "IMOEX.ME"}, + "au_aord": {"name": "Australia All Ordinary Share Index (AUD)", "ticker": "^AORD"}, + "au_small": {"name": "S&P/ASX Small Ordinaries Index (AUD)", "ticker": "^AXSO"}, + "au_asx20": { + "name": "S&P/ASX 20 Index (AUD)", + "ticker": "^ATLI", + }, + "au_asx50": { + "name": "S&P/ASX 50 Index (AUD)", + "ticker": "^AFLI", + }, + "au_asx50_mid": { + "name": "S&P/ASX Mid Cap 50 Index (AUD)", + "ticker": "^AXMD", + }, + "au_asx100": { + "name": "S&P/ASX 100 Index (AUD)", + "ticker": "^ATOI", + }, + "au_asx200": {"name": "S&P/ASX 200 Index (AUD)", "ticker": "^AXJO"}, + "au_asx300": { + "name": "S&P/ASX 300 Index (AUD)", + "ticker": "^AXKO", + }, + "au_energy": { + "name": "S&P/ASX 200 Energy Sector Index (AUD)", + "ticker": "^AXEJ", + }, + "au_resources": { + "name": "S&P/ASX 200 Resources Sector Index (AUD)", + "ticker": "^AXJR", + }, + "au_materials": { + "name": "S&P/ASX 200 Materials Sector Index (AUD)", + "ticker": "^AXMJ", + }, + "au_mining": { + "name": "S&P/ASX 300 Metals and Mining Sector Index (AUD)", + "ticker": "^AXMM", + }, + "au_industrials": { + "name": "S&P/ASX 200 Industrials Sector Index (AUD)", + "ticker": "^AXNJ", + }, + "au_discretionary": { + "name": "S&P/ASX 200 Consumer Discretionary Sector Index (AUD)", + "ticker": "^AXDJ", + }, + "au_staples": { + "name": "S&P/ASX 200 Consumer Staples Sector Index (AUD)", + "ticker": "^AXSJ", + }, + "au_health": { + "name": "S&P/ASX 200 Health Care Sector Index (AUD)", + "ticker": "^AXHJ", + }, + "au_financials": { + "name": "S&P/ASX 200 Financials Sector Index (AUD)", + "ticker": "^AXFJ", + }, + "au_reit": {"name": "S&P/ASX 200 A-REIT Industry Index (AUD)", "ticker": "^AXPJ"}, + "au_tech": {"name": "S&P/ASX 200 Info Tech Sector Index (AUD)", "ticker": "^AXIJ"}, + "au_communications": { + "name": "S&P/ASX 200 Communications Sector Index (AUD)", + "ticker": "^AXTJ", + }, + "au_utilities": { + "name": "S&P/ASX 200 Utilities Sector Index (AUD)", + "ticker": "^AXUJ", + }, + "nz50": {"name": "S&P New Zealand 50 Index (NZD)", "ticker": "^nz50"}, + "nz_small": {"name": "S&P/NZX Small Cap Index (NZD)", "ticker": "^NZSC"}, + "kr_kospi": {"name": "KOSPI Composite Index (KRW)", "ticker": "^KS11"}, + "jp_arca": {"name": "NYSE ARCA Japan Index (JPY)", "ticker": "^JPN"}, + "jp_n225": {"name": "Nikkei 255 Index (JPY)", "ticker": "^N225"}, + "jp_n300": {"name": "Nikkei 300 Index (JPY)", "ticker": "^N300"}, + "jp_nknr": {"name": "Nikkei Avg Net TR Index (JPY)", "ticker": "^NKVI.OS"}, + "jp_nkrc": {"name": "Nikkei Avg Risk Control Index (JPY)", "ticker": "^NKRC.OS"}, + "jp_nklv": {"name": "Nikkei Avg Leverage Index (JPY)", "ticker": "^NKLV.OS"}, + "jp_nkcc": {"name": "Nikkei Avg Covered Call Index (JPY)", "ticker": "^NKCC.OS"}, + "jp_nkhd": { + "name": "Nikkei Avg High Dividend Yield Index (JPY)", + "ticker": "^NKHD.OS", + }, + "jp_auto": { + "name": "Nikkei 500 Auto & Auto Parts Index (JPY)", + "ticker": "^NG17.OS", + }, + "jp_fintech": { + "name": "Global Fintech Japan Hedged Index (JPY)", + "ticker": "^FDSFTPRJPY", + }, + "jp_nkdh": {"name": "Nikkei Average USD Hedge Index (JPY)", "ticker": "^NKDH.OS"}, + "jp_nkeh": {"name": "Nikkei Average EUR Hedge Index (JPY)", "ticker": "^NKEH.OS"}, + "jp_ndiv": { + "name": "Nikkei Average Double Inverse Index (JPY)", + "ticker": "^NDIV.OS", + }, + "cn_csi300": {"name": "China CSI 300 Index (CNY)", "ticker": "000300.SS"}, + "cn_sse_comp": {"name": "SSE Composite Index (CNY)", "ticker": "000001.SS"}, + "cn_sse_a": {"name": "SSE A Share Index (CNY)", "ticker": "000002.SS"}, + "cn_szse_comp": {"name": "SZSE Component Index (CNY)", "ticker": "399001.SZ"}, + "cn_szse_a": {"name": "SZSE A-Shares Index (CNY)", "ticker": "399107.SZ"}, + "tw_twii": {"name": "TSEC Weighted Index (TWD)", "ticker": "^TWII"}, + "tw_tcii": {"name": "TSEC Cement and Ceramics Subindex (TWD)", "ticker": "^TCII"}, + "tw_tfii": {"name": "TSEC Foods Subindex (TWD)", "ticker": "^TFII"}, + "tw_tfni": {"name": "TSEC Finance Subindex (TWD)", "ticker": "^TFNI"}, + "tw_tpai": {"name": "TSEC Paper and Pulp Subindex (TWD)", "ticker": "^TPAI"}, + "hk_hsi": {"name": "Hang Seng Index (HKD)", "ticker": "^HSI"}, + "hk_utilities": { + "name": "Hang Seng Utilities Sector Index (HKD)", + "ticker": "^HSNU", + }, + "hk_china": { + "name": "Hang Seng China-Affiliated Corporations Index (HKD)", + "ticker": "^HSCC", + }, + "hk_finance": {"name": "Hang Seng Finance Sector Index (HKD)", "ticker": "^HSNF"}, + "hk_properties": { + "name": "Hang Seng Properties Sector Index (HKD)", + "ticker": "^HSNP", + }, + "hk_hko": {"name": "NYSE ARCA Hong Kong Options Index (USD)", "ticker": "^HKO"}, + "hk_titans30": { + "name": "Dow Jones Hong Kong Titans 30 Index (HKD)", + "ticker": "^XLHK", + }, + "id_jkse": {"name": "Jakarta Composite Index (IDR)", "ticker": "^JKSE"}, + "id_lq45": { + "name": "Indonesia Stock Exchange LQ45 Index (IDR)", + "ticker": "^JKLQ45", + }, + "my_klci": {"name": "FTSE Kuala Lumpur Composite Index (MYR)", "ticker": "^KLSE"}, + "ph_psei": {"name": "Philippine Stock Exchange Index (PHP)", "ticker": "PSEI.PS"}, + "sg_sti": {"name": "STI Singapore Index (SGD)", "ticker": "^STI"}, + "th_set": {"name": "Thailand SET Index (THB)", "ticker": "^SET.BK"}, + "sp_energy_ig": { + "name": "S&P 500 Energy (Industry Group) Index", + "ticker": "^SP500-1010", + }, + "sp_energy_equipment": { + "name": "S&P 500 Energy Equipment & Services Industry Index", + "ticker": "^SP500-101010", + }, + "sp_energy_oil": { + "name": "S&P 500 Oil, Gas & Consumable Fuels Industry Index", + "ticker": "^SP500-101020", + }, + "sp_materials_sector": { + "name": "S&P 500 Materials Sector Index", + "ticker": "^SP500-15", + }, + "sp_materials_ig": { + "name": "S&P 500 Materials (Industry Group) Index", + "ticker": "^SP500-1510", + }, + "sp_materials_construction": { + "name": "S&P 500 Construction Materials Industry Index", + "ticker": "^SP500-151020", + }, + "sp_materials_metals": { + "name": "S&P 500 Mining & Metals Industry Index", + "ticker": "^SP500-151040", + }, + "sp_industrials_sector": { + "name": "S&P 500 Industrials Sector Index", + "ticker": "^SP500-20", + }, + "sp_industrials_goods_ig": { + "name": "S&P 500 Capital Goods (Industry Group) Index", + "ticker": "^SP500-2010", + }, + "sp_industrials_aerospace": { + "name": "S&P 500 Aerospace & Defense Industry Index", + "ticker": "^SP500-201010", + }, + "sp_industrials_building": { + "name": "S&P 500 Building Products Industry Index", + "ticker": "^SP500-201020", + }, + "sp_industrials_construction": { + "name": "S&P 500 Construction & Engineering Industry Index", + "ticker": "^SP500-201030", + }, + "sp_industrials_electrical": { + "name": "S&P 500 Electrical Equipment Industry Index", + "ticker": "^SP500-201040", + }, + "sp_industrials_conglomerates": { + "name": "S&P 500 Industrial Conglomerates Industry Index", + "ticker": "^SP500-201050", + }, + "sp_industrials_machinery": { + "name": "S&P 500 Machinery Industry Index", + "ticker": "^SP500-201060", + }, + "sp_industrials_distributors": { + "name": "S&P 500 Trading Companies & Distributors Industry Index", + "ticker": "^SP500-201070", + }, + "sp_industrials_services_ig": { + "name": "S&P 500 Commercial & Professional Services (Industry Group) Index", + "ticker": "^SP500-2020", + }, + "sp_industrials_services_supplies": { + "name": "S&P 500 Commercial Services & Supplies Industry Index", + "ticker": "^SP500-202010", + }, + "sp_industrials_transport_ig": { + "name": "S&P 500 Transportation (Industry Group) Index", + "ticker": "^SP500-2030", + }, + "sp_industrials_transport_air": { + "name": "S&P 500 Air Freight & Logistics Industry", + "ticker": "^SP500-203010", + }, + "sp_industrials_transport_airlines": { + "name": "S&P 500 Airlines Industry Index", + "ticker": "^SP500-203020", + }, + "sp_industrials_transport_ground": { + "name": "S&P 500 Road & Rail Industry Index", + "ticker": "^SP500-203040", + }, + "sp_discretionary_sector": { + "name": "S&P 500 Consumer Discretionary Index", + "ticker": "^SP500-25", + }, + "sp_discretionary_autos-ig": { + "name": "S&P 500 Automobiles and Components (Industry Group) Index", + "ticker": "^SP500-2510", + }, + "sp_discretionary_auto_components": { + "name": "S&P 500 Auto Components Industry Index", + "ticker": "^SP500-251010", + }, + "sp_discretionary_autos": { + "name": "S&P 500 Automobiles Industry Index", + "ticker": "^SP500-251020", + }, + "sp_discretionary_durables_ig": { + "name": "S&P 500 Consumer Durables & Apparel (Industry Group) Index", + "ticker": "^SP500-2520", + }, + "sp_discretionary_durables_household": { + "name": "S&P 500 Household Durables Industry Index", + "ticker": "^SP500-252010", + }, + "sp_discretionary_leisure": { + "name": "S&P 500 Leisure Products Industry Index", + "ticker": "^SP500-252020", + }, + "sp_discretionary_textiles": { + "name": "S&P 500 Textiles, Apparel & Luxury Goods Industry Index", + "ticker": "^SP500-252030", + }, + "sp_discretionary_services_consumer": { + "name": "S&P 500 Consumer Services (Industry Group) Index", + "ticker": "^SP500-2530", + }, + "sp_staples_sector": { + "name": "S&P 500 Consumer Staples Sector Index", + "ticker": "^SP500-30", + }, + "sp_staples_retail_ig": { + "name": "S&P 500 Food & Staples Retailing (Industry Group) Index", + "ticker": "^SP500-3010", + }, + "sp_staples_food_ig": { + "name": "S&P 500 Food Beverage & Tobacco (Industry Group) Index", + "ticker": "^SP500-3020", + }, + "sp_staples_beverages": { + "name": "S&P 500 Beverages Industry Index", + "ticker": "^SP500-302010", + }, + "sp_staples_products_food": { + "name": "S&P 500 Food Products Industry Index", + "ticker": "^SP500-302020", + }, + "sp_staples_tobacco": { + "name": "S&P 500 Tobacco Industry Index", + "ticker": "^SP500-302030", + }, + "sp_staples_household_ig": { + "name": "S&P 500 Household & Personal Products (Industry Group) Index", + "ticker": "^SP500-3030", + }, + "sp_staples_products_household": { + "name": "S&P 500 Household Products Industry Index", + "ticker": "^SP500-303010", + }, + "sp_staples_products_personal": { + "name": "S&P 500 Personal Products Industry Index", + "ticker": "^SP500-303020", + }, + "sp_health_sector": { + "name": "S&P 500 Health Care Sector Index", + "ticker": "^SP500-35", + }, + "sp_health_equipment": { + "name": "S&P 500 Health Care Equipment & Services (Industry Group) Index", + "ticker": "^SP500-3510", + }, + "sp_health_supplies": { + "name": "S&P 500 Health Care Equipment & Supplies Industry Index", + "ticker": "^SP500-351010", + }, + "sp_health_providers": { + "name": "S&P 500 Health Care Providers & Services Industry Index", + "ticker": "^SP500-351020", + }, + "sp_health_sciences": { + "name": "S&P 500 Pharmaceuticals, Biotechnology & Life Sciences (Industry Group) Index", + "ticker": "^SP500-3520", + }, + "sp_health_biotech": { + "name": "S&P 500 Biotechnology Industry Index", + "ticker": "^SP500-352010", + }, + "sp_health_pharma": { + "name": "S&P 500 Pharmaceuticals Industry Index", + "ticker": "^SP500-352020", + }, + "sp_financials_sector": { + "name": "S&P 500 Financials Sector Index", + "ticker": "^SP500-40", + }, + "sp_financials_diversified_ig": { + "name": "S&P 500 Diversified Financials (Industry Group) Index", + "ticker": "^SP500-4020", + }, + "sp_financials_services": { + "name": "S&P 500 Diversified Financial Services Industry Index", + "ticker": "^SP500-402010", + }, + "sp_financials_consumer": { + "name": "S&P 500 Consumer Finance Industry Index", + "ticker": "^SP500-402020", + }, + "sp_financials_capital": { + "name": "S&P 500 Capital Markets Industry Index", + "ticker": "^SP500-402030", + }, + "sp_it_sector": { + "name": "S&P 500 IT Sector Index", + "ticker": "^SP500-45", + }, + "sp_it_saas_ig": { + "name": "S&P 500 Software and Services (Industry Group) Index", + "ticker": "^SP500-4510", + }, + "sp_it_software": { + "name": "S&P 500 Software Industry Index", + "ticker": "^SP500-451030", + }, + "sp_it_hardware": { + "name": "S&P 500 Technology Hardware Equipment (Industry Group) Index", + "ticker": "^SP500-4520", + }, + "sp_it_semi": { + "name": "S&P 500 Semiconductor & Semiconductor Equipment Industry", + "ticker": "^SP500-453010", + }, + "sp_communications_sector": { + "name": "S&P 500 Communications Sector Index", + "ticker": "^SP500-50", + }, + "sp_communications_telecom": { + "name": "S&P 500 Diversified Telecommunications Services Industry Index", + "ticker": "^SP500-501010", + }, + "sp_utilities_sector": { + "name": "S&P 500 Utilities Sector Index", + "ticker": "^SP500-55", + }, + "sp_utilities_electricity": { + "name": "S&P 500 Electric Utilities Index", + "ticker": "^SP500-551010", + }, + "sp_utilities_multis": { + "name": "S&P 500 Multi-Utilities Industry Index", + "ticker": "^SP500-551030", + }, + "sp_re_sector": { + "name": "S&P 500 Real Estate Sector Index", + "ticker": "^SP500-60", + }, + "sp_re_ig": { + "name": "S&P 500 Real Estate (Industry Group) Index", + "ticker": "^SP500-6010", + }, + "sphyda": {"name": "S&P High Yield Aristocrats Index", "ticker": "^SPHYDA"}, + "dow_djt": {"name": "Dow Jones Transportation Average Index", "ticker": "^DJT"}, + "dow_dju": {"name": "Dow Jones Utility Average Index", "ticker": "^DJU"}, + "dow_rci": {"name": "Dow Jones Composite All REIT Index", "ticker": "^RCI"}, + "reit_fnar": {"name": "FTSE Nareit All Equity REITs Index", "ticker": "^FNAR"}, + "nq_ixch": {"name": "NASDAQ Health Care Index", "ticker": "^IXCH"}, + "nq_nbi": {"name": "NASDAQ Biotech Index", "ticker": "^NBI"}, + "nq_tech": {"name": "NASDAQ 100 Technology Sector Index", "ticker": "^NDXT"}, + "nq_ex_tech": {"name": "NASDAQ 100 Ex-Tech Sector Index", "ticker": "^NDXX"}, + "nq_ixtc": {"name": "NASDAQ Telecommunications Index", "ticker": "^IXTC"}, + "nq_inds": {"name": "NASDAQ Industrial Index", "ticker": "^INDS"}, + "nq_ixco": {"name": "NASDAQ Computer Index", "ticker": "^INCO"}, + "nq_bank": {"name": "NASDAQ Bank Index", "ticker": "^BANK"}, + "nq_bkx": {"name": "KBW NASDAQ Bank Index", "ticker": "^BKX"}, + "nq_krx": {"name": "KBW NASDAQ Regional Bank Index", "ticker": "^KRX"}, + "nq_kix": {"name": "KBW NASDAQ Insurance Index", "ticker": "^KIX"}, + "nq_ksx": {"name": "KBW NASDAQ Capital Markets Index", "ticker": "^KSX"}, + "nq_tran": {"name": "NASDAQ Transportation Index", "ticker": "^TRAN"}, + "ice_auto": {"name": "ICE FactSet Global NextGen Auto Index", "ticker": "^ICEFSNA"}, + "ice_comm": { + "name": "ICE FactSet Global NextGen Communications Index", + "ticker": "^ICEFSNC", + }, + "nyse_nyl": {"name": "NYSE World Leaders Index", "ticker": "^NYL"}, + "nyse_nyi": {"name": "NYSE International 100 Index", "ticker": "^NYI"}, + "nyse_nyy": {"name": "NYSE TMT Index", "ticker": "^NYY"}, + "nyse_fang": {"name": "NYSE FANG+TM index", "ticker": "^NYFANG"}, + "arca_xmi": {"name": "NYSE ARCA Major Market Index", "ticker": "^XMI"}, + "arca_xbd": {"name": "NYSE ARCA Securities Broker/Dealer Index", "ticker": "^XBD"}, + "arca_xii": {"name": "NYSE ARCA Institutional Index", "ticker": "^XII"}, + "arca_xoi": {"name": "NYSE ARCA Oil and Gas Index", "ticker": "^XOI"}, + "arca_xng": {"name": "NYSE ARCA Natural Gas Index", "ticker": "^XNG"}, + "arca_hui": {"name": "NYSE ARCA Gold Bugs Index", "ticker": "^HUI"}, + "arca_ixb": {"name": "NYSE Materials Select Sector Index", "ticker": "^IXB"}, + "arca_drg": {"name": "NYSE ARCA Phramaceutical Index", "ticker": "^DRG"}, + "arca_btk": {"name": "NYSE ARCA Biotech Index", "ticker": "^BKT"}, + "arca_pse": {"name": "NYSE ARCA Tech 100 Index", "ticker": "^PSE"}, + "arca_nwx": {"name": "NYSE ARCA Networking Index", "ticker": "^NWX"}, + "arca_xci": {"name": "NYSE ARCA Computer Tech Index", "ticker": "^XCI"}, + "arca_xal": {"name": "NYSE ARCA Airline Index", "ticker": "^XAL"}, + "arca_xtc": {"name": "NYSE ARCA N.A. Telecom Industry Index", "ticker": "^XTC"}, + "phlx_sox": {"name": "PHLX Semiconductor Index", "ticker": "^SOX"}, + "phlx_xau": {"name": "PHLX Gold/Silver Index", "ticker": "^XAU"}, + "phlx_hgx": {"name": "PHLX Housing Sector Index", "ticker": "^HGX"}, + "phlx_osx": {"name": "PHLX Oil Services Sector Index", "ticker": "^OSX"}, + "phlx_uty": {"name": "PHLX Utility Sector Index", "ticker": "^UTY"}, + "w5klcg": {"name": "Wilshire US Large Cap Growth Index", "ticker": "^W5KLCG"}, + "w5klcv": {"name": "Wilshire US Large Cap Value Index", "ticker": "^W5KLCV"}, + "reit_wgreit": {"name": "Wilshire Global REIT Index", "ticker": "^WGREIT"}, + "reit_wgresi": { + "name": "Wilshire Global Real Estate Sector Index", + "ticker": "^WGRESI", + }, + "reit_wilreit": {"name": "Wilshire US REIT Index", "ticker": "^WILREIT"}, + "reit_wilresi": { + "name": "Wilshire US Real Estate Security Index", + "ticker": "^WILRESI", + }, + "cboe_bxm": {"name": "CBOE Buy-Write Monthly Index", "ticker": "^BXM"}, + "cboe_vix": {"name": "CBOE S&P 500 Volatility Index", "ticker": "^VIX"}, + "cboe_vix9d": {"name": "CBOE S&P 500 9-Day Volatility Index", "ticker": "^VIX9D"}, + "cboe_vix3m": {"name": "CBOE S&P 500 3-Month Volatility Index", "ticker": "^VIX3M"}, + "cboe_vin": {"name": "CBOE Near-Term VIX Index", "ticker": "^VIN"}, + "cboe_vvix": {"name": "CBOE VIX Volatility Index", "ticker": "^VVIX"}, + "cboe_shortvol": {"name": "CBOE Short VIX Futures Index", "ticker": "^SHORTVOL"}, + "cboe_skew": {"name": "CBOE Skew Index", "ticker": "^SKEW"}, + "cboe_vxn": {"name": "CBOE NASDAQ 100 Volatility Index", "ticker": "^VXN"}, + "cboe_gvz": {"name": "CBOE Gold Volatility Index", "ticker": "^GVZ"}, + "cboe_ovx": {"name": "CBOE Crude Oil Volatility Index", "ticker": "^OVX"}, + "cboe_tnx": {"name": "CBOE Interest Rate 10 Year T-Note", "ticker": "^TNX"}, + "cboe_tyx": {"name": "CBOE 30 year Treasury Yields", "ticker": "^TYX"}, + "cboe_irx": {"name": "CBOE 13 Week Treasury Bill", "ticker": "^IRX"}, + "cboe_evz": {"name": "CBOE Euro Currency Volatility Index", "ticker": "^EVZ"}, + "cboe_rvx": {"name": "CBOE Russell 2000 Volatility Index", "ticker": "^RVX"}, + "move": {"name": "ICE BofAML Move Index", "ticker": "^MOVE"}, + "dxy": {"name": "US Dollar Index", "ticker": "DX-Y.NYB"}, + "crypto200": {"name": "CMC Crypto 200 Index by Solacti", "ticker": "^CMC200"}, +} diff --git a/openbb_sdk/pyproject.toml b/openbb_sdk/pyproject.toml index cbedd4fb8f8..573fc94e1b2 100644 --- a/openbb_sdk/pyproject.toml +++ b/openbb_sdk/pyproject.toml @@ -13,6 +13,7 @@ openbb-core = { path = "./sdk/core" } openbb-benzinga = { path = "./providers/benzinga" } openbb-fmp = { path = "./providers/fmp" } openbb-fred = { path = "./providers/fred" } +openbb-intrinio = { path = "./providers/intrinio" } openbb-polygon = { path = "./providers/polygon" } openbb-crypto = { path = "./extensions/crypto" } @@ -23,7 +24,9 @@ openbb-news = { path = "./extensions/news" } openbb-stocks = { path = "./extensions/stocks" } # Community dependencies +openbb-alpha-vantage = { path = "./providers/alpha_vantage", optional = true } openbb-cboe = { path = "./providers/cboe", optional = true } +openbb-quandl = { path = "./providers/quandl", optional = true } openbb-yfinance = { path = "./providers/yfinance", optional = true } openbb-charting = { path = "./extensions/charting", optional = true } @@ -32,7 +35,9 @@ openbb-qa = { path = "./extensions/qa", optional = true } openbb-ta = { path = "./extensions/ta", optional = true } [tool.poetry.extras] +alpha_vantage = ["openbb-alpha-vantage"] cboe = ["openbb-cboe"] +quandl = ["openbb-quandl"] yfinance = ["openbb-yfinance"] charting = ["openbb-charting"] futures = ["openbb-futures"] @@ -40,7 +45,9 @@ qa = ["openbb-qa"] ta = ["openbb-ta"] all = [ + "openbb-alpha-vantage", "openbb-cboe", + "openbb-quandl", "openbb-yfinance", "openbb-charting", "openbb-futures", diff --git a/openbb_sdk/sdk/core/README.md b/openbb_sdk/sdk/core/README.md index d11536c8e3a..7ad9515c4c7 100644 --- a/openbb_sdk/sdk/core/README.md +++ b/openbb_sdk/sdk/core/README.md @@ -78,10 +78,10 @@ def some_command( If your command only makes use of a standard model defined inside `openbb_provider/standard_models` directory, there is no need to repeat its structure in the parameters. Just pass the model name as an argument. -This is an example how we do it for `stocks.load` which only depends on `StockEOD` model defined in `openbb-provider`: +This is an example how we do it for `stocks.load` which only depends on `StockHistorical` model defined in `openbb-provider`: ```python -@router.command(model="StockEOD") +@router.command(model="StockHistorical") def load( cc: CommandContext, # user settings inside provider_choices: ProviderChoices, # available providers diff --git a/openbb_sdk/sdk/core/openbb_core/app/provider_interface.py b/openbb_sdk/sdk/core/openbb_core/app/provider_interface.py index 706acebde38..e142f8ef732 100644 --- a/openbb_sdk/sdk/core/openbb_core/app/provider_interface.py +++ b/openbb_sdk/sdk/core/openbb_core/app/provider_interface.py @@ -390,7 +390,7 @@ class ProviderInterface(metaclass=SingletonMeta): Example: ------- - class StockEODData(StandardData): + class StockHistoricalData(StandardData): date: date open: PositiveFloat high: PositiveFloat diff --git a/openbb_sdk/sdk/core/tests/app/test_provider_interface.py b/openbb_sdk/sdk/core/tests/app/test_provider_interface.py index 0e11fbf5a92..070a743bfdf 100644 --- a/openbb_sdk/sdk/core/tests/app/test_provider_interface.py +++ b/openbb_sdk/sdk/core/tests/app/test_provider_interface.py @@ -24,7 +24,7 @@ def test_map(provider_interface): provider_interface_map = provider_interface.map assert isinstance(provider_interface_map, dict) assert len(provider_interface_map) > 0 - assert "StockEOD" in provider_interface_map + assert "StockHistorical" in provider_interface_map def test_required_credentials(provider_interface): @@ -46,7 +46,7 @@ def test_params(provider_interface): params = provider_interface.params assert isinstance(params, dict) assert len(params) > 0 - assert "StockEOD" in params + assert "StockHistorical" in params def test_data(provider_interface): @@ -54,7 +54,7 @@ def test_data(provider_interface): data = provider_interface.data assert isinstance(data, dict) assert len(data) > 0 - assert "StockEOD" in data + assert "StockHistorical" in data def test_available_providers(provider_interface): @@ -76,4 +76,4 @@ def test_models(provider_interface): models = provider_interface.models assert isinstance(models, list) assert len(models) > 0 - assert "StockEOD" in models + assert "StockHistorical" in models diff --git a/openbb_sdk/sdk/core/tests/app/test_query.py b/openbb_sdk/sdk/core/tests/app/test_query.py index ef32c0b048a..1aa692634f4 100644 --- a/openbb_sdk/sdk/core/tests/app/test_query.py +++ b/openbb_sdk/sdk/core/tests/app/test_query.py @@ -18,26 +18,26 @@ from pydantic import BaseModel def create_mock_query(): """Mock query.""" - class StockEOD: - """Mock StockEOD class.""" + class StockHistorical: + """Mock StockHistorical class.""" start_date = "2020-01-01" end_date = "2020-01-05" symbol = "AAPL" - return StockEOD() + return StockHistorical() def create_mock_extra_params(): """Mock ExtraParams dataclass.""" @dataclass - class StockEOD: + class StockHistorical: """Mock ExtraParams dataclass.""" sort: str = "desc" - return StockEOD() + return StockHistorical() @pytest.fixture(scope="module") @@ -69,13 +69,13 @@ def test_filter_extra_params_wrong_param(query): """Test filter_extra_params.""" @dataclass - class StockEOD: + class StockHistorical: """Mock ExtraParams dataclass.""" sort: str = "desc" limit: int = 4 - extra_params = StockEOD() + extra_params = StockHistorical() assert not query.filter_extra_params(extra_params, "fmp") diff --git a/openbb_sdk/sdk/core/tests/app/test_router.py b/openbb_sdk/sdk/core/tests/app/test_router.py index 56f68538f92..aef94bfdcd5 100644 --- a/openbb_sdk/sdk/core/tests/app/test_router.py +++ b/openbb_sdk/sdk/core/tests/app/test_router.py @@ -187,7 +187,7 @@ def test_complete_signature(signature_inspector): ) -> OBBject: pass - model = "StockEOD" + model = "StockHistorical" assert signature_inspector.complete_signature(sample_function, model) diff --git a/openbb_sdk/sdk/core/tests/test_query.py b/openbb_sdk/sdk/core/tests/test_query.py index ef32c0b048a..1aa692634f4 100644 --- a/openbb_sdk/sdk/core/tests/test_query.py +++ b/openbb_sdk/sdk/core/tests/test_query.py @@ -18,26 +18,26 @@ from pydantic import BaseModel def create_mock_query(): """Mock query.""" - class StockEOD: - """Mock StockEOD class.""" + class StockHistorical: + """Mock StockHistorical class.""" start_date = "2020-01-01" end_date = "2020-01-05" symbol = "AAPL" - return StockEOD() + return StockHistorical() def create_mock_extra_params(): """Mock ExtraParams dataclass.""" @dataclass - class StockEOD: + class StockHistorical: """Mock ExtraParams dataclass.""" sort: str = "desc" - return StockEOD() + return StockHistorical() @pytest.fixture(scope="module") @@ -69,13 +69,13 @@ def test_filter_extra_params_wrong_param(query): """Test filter_extra_params.""" @dataclass - class StockEOD: + class StockHistorical: """Mock ExtraParams dataclass.""" sort: str = "desc" limit: int = 4 - extra_params = StockEOD() + extra_params = StockHistorical() assert not query.filter_extra_params(extra_params, "fmp") diff --git a/openbb_sdk/sdk/provider/openbb_provider/query_executor.py b/openbb_sdk/sdk/provider/openbb_provider/query_executor.py index cb77cd653b7..9bb97fb5340 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/query_executor.py +++ b/openbb_sdk/sdk/provider/openbb_provider/query_executor.py @@ -61,7 +61,7 @@ class QueryExecutor: provider_name : str Name of the provider, for example: "fmp". model_name : str - Name of the model, for example: "StockEOD". + Name of the model, for example: "StockHistorical". params : Dict[str, Any] Query parameters, for example: {"symbol": "AAPL"} credentials : Optional[Dict[str, str]], optional diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/available_indices.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/available_indices.py index a199adf0ef9..728c937b7b9 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/standard_models/available_indices.py +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/available_indices.py @@ -7,22 +7,17 @@ from pydantic import Field from openbb_provider.abstract.data import Data from openbb_provider.abstract.query_params import QueryParams -from openbb_provider.standard_models.base import BaseSymbol class AvailableIndicesQueryParams(QueryParams): """Available Indices Query.""" -class AvailableIndicesData(Data, BaseSymbol): +class AvailableIndicesData(Data): """Available Indices Data. - Returns the major indices from Dow Jones, Nasdaq and, S&P 500. + Returns the list of available indices from a provider. """ name: Optional[str] = Field(description="Name of the index.") currency: Optional[str] = Field(description="Currency the index is traded in.") - stock_exchange: str = Field(description="Stock exchange where the index is listed.") - exchange_short_name: str = Field( - description="Short name of the stock exchange where the index is listed." - ) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/balance_sheet.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/balance_sheet.py index 8093cad0043..787f6949534 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/standard_models/balance_sheet.py +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/balance_sheet.py @@ -1,93 +1,108 @@ """Balance Sheet Data Model.""" -from datetime import ( - date as dateType, - datetime, -) +from datetime import date as dateType from typing import Optional from pydantic import Field from openbb_provider.abstract.data import Data -from openbb_provider.standard_models.base import FinancialStatementQueryParams - -# IMPORT THIRD PARTY +from openbb_provider.standard_models.base import ( + BaseSymbol, + FinancialStatementQueryParams, +) class BalanceSheetQueryParams(FinancialStatementQueryParams): """Balance Sheet query.""" -class BalanceSheetData(Data): +class BalanceSheetData(Data, BaseSymbol): """Balance Sheet Data.""" date: dateType = Field(description="Date of the fetched statement.") - symbol: Optional[str] = Field(description="Symbol of the company.") - cik: Optional[int] = Field(description="Central Index Key.") - currency: Optional[str] = Field(description="Reporting currency.") - filing_date: Optional[dateType] = Field(description="Filling date.") - accepted_date: Optional[datetime] = Field(description="Accepted date.") period: Optional[str] = Field(description="Reporting period of the statement.") + cik: Optional[int] = Field(description="Central Index Key (CIK) of the company.") cash_and_cash_equivalents: Optional[int] = Field( description="Cash and cash equivalents" ) short_term_investments: Optional[int] = Field(description="Short-term investments") - inventory: Optional[int] = Field(description="Inventory") net_receivables: Optional[int] = Field(description="Receivables, net") + inventory: Optional[int] = Field(description="Inventory") other_current_assets: Optional[int] = Field(description="Other current assets") - current_assets: Optional[int] = Field(description="Total current assets") + total_current_assets: Optional[int] = Field(description="Total current assets") - long_term_investments: Optional[int] = Field(description="Long-term investments") + marketable_securities: Optional[int] = Field(description="Marketable securities") property_plant_equipment_net: Optional[int] = Field( description="Property, plant and equipment, net" ) goodwill: Optional[int] = Field(description="Goodwill") intangible_assets: Optional[int] = Field(description="Intangible assets") + tax_assets: Optional[int] = Field(description="Accrued income taxes") other_non_current_assets: Optional[int] = Field( description="Other non-current assets" ) - tax_assets: Optional[int] = Field(description="Accrued income taxes") - other_assets: Optional[int] = Field(description="Other assets") - noncurrent_assets: Optional[int] - assets: Optional[int] - - account_payables: Optional[int] - other_current_liabilities: Optional[int] - tax_payables: Optional[int] = Field(description="Accrued income taxes") - deferred_revenue: Optional[int] = Field( - description="Accrued income taxes, other deferred revenue" + total_non_current_assets: Optional[int] = Field( + description="Total non-current assets" ) + other_assets: Optional[int] = Field(description="Other assets") + total_assets: Optional[int] = Field(description="Total assets") + + account_payables: Optional[int] = Field(description="Accounts payables") short_term_debt: Optional[int] = Field( description="Short-term borrowings, Long-term debt due within one year, " "Operating lease obligations due within one year, " "Finance lease obligations due within one year" ) - current_liabilities: Optional[int] + tax_payables: Optional[int] = Field(description="Accrued income taxes") + deferred_revenue: Optional[int] = Field( + description="Accrued income taxes, other deferred revenue" + ) + other_current_liabilities: Optional[int] = Field( + description="Other current liabilities" + ) + total_current_liabilities: Optional[int] = Field( + description="Total current liabilities" + ) long_term_debt: Optional[int] = Field( - description="Long-term debt, Operating lease obligations, Long-term finance lease obligations" + description="Long-term debt, Operating lease obligations, " + "Long-term finance lease obligations" + ) + deferred_revenue_non_current: Optional[int] = Field( + description="Deferred revenue, non-current" + ) + deferred_tax_liabilities_non_current: Optional[int] = Field( + description="Deferred income taxes and other" ) other_non_current_liabilities: Optional[int] = Field( description="Deferred income taxes and other" ) - other_liabilities: Optional[int] - noncurrent_liabilities: Optional[int] - liabilities: Optional[int] - - common_stock: Optional[int] - other_stockholder_equity: Optional[int] = Field( - description="Capital in excess of par value" + total_non_current_liabilities: Optional[int] = Field( + description="Total non-current liabilities" ) + other_liabilities: Optional[int] = Field(description="Other liabilities") + total_liabilities: Optional[int] = Field(description="Total liabilities") + preferred_stock: Optional[int] = Field(description="Preferred stock") + common_stock: Optional[int] = Field(description="Common stock") + retained_earnings: Optional[int] = Field(description="Retained earnings") accumulated_other_comprehensive_income_loss: Optional[int] = Field( description="Accumulated other comprehensive income (loss)" ) - preferred_stock: Optional[int] = Field(description="Preferred stock") - retained_earnings: Optional[int] = Field(description="Retained earnings") + other_shareholder_equity: Optional[int] = Field( + description="Other shareholder's equity" + ) + total_shareholder_equity: Optional[int] = Field( + description="Total shareholder's equity" + ) + + total_equity: Optional[int] = Field(description="Total equity") + total_liabilities_and_shareholders_equity: Optional[int] = Field( + description="Total liabilities and shareholder's equity" + ) minority_interest: Optional[int] = Field(description="Minority interest") - total_stockholders_equity: Optional[int] - total_equity: Optional[int] - total_liabilities_and_stockholders_equity: Optional[int] - total_liabilities_and_total_equity: Optional[int] + total_liabilities_and_total_equity: Optional[int] = Field( + description="Total liabilities and total equity" + ) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/cash_flow.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/cash_flow.py new file mode 100644 index 00000000000..33834ad03c4 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/cash_flow.py @@ -0,0 +1,98 @@ +"""Cash Flow Statement Data Model.""" + + +from datetime import date as dateType +from typing import Optional + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.standard_models.base import ( + BaseSymbol, + FinancialStatementQueryParams, +) + + +class CashFlowStatementQueryParams(FinancialStatementQueryParams): + """Cash Flow Statement Query.""" + + +class CashFlowStatementData(Data, BaseSymbol): + """Cash Flow Statement Data.""" + + date: dateType = Field(description="Date of the fetched statement.") + period: Optional[str] = Field(description="Reporting period of the statement.") + cik: Optional[int] = Field(description="Central Index Key (CIK) of the company.") + + net_income: Optional[int] = Field(description="Net income.") + + depreciation_and_amortization: Optional[int] = Field( + description="Depreciation and amortization." + ) + stock_based_compensation: Optional[int] = Field( + description="Stock based compensation." + ) + deferred_income_tax: Optional[int] = Field(description="Deferred income tax.") + other_non_cash_items: Optional[int] = Field(description="Other non-cash items.") + changes_in_operating_assets_and_liabilities: Optional[int] = Field( + description="Changes in operating assets and liabilities." + ) + + accounts_receivables: Optional[int] = Field(description="Accounts receivables.") + inventory: Optional[int] = Field(description="Inventory.") + vendor_non_trade_receivables: Optional[int] = Field( + description="Vendor non-trade receivables." + ) + other_current_and_non_current_assets: Optional[int] = Field( + description="Other current and non-current assets." + ) + accounts_payables: Optional[int] = Field(description="Accounts payables.") + deferred_revenue: Optional[int] = Field(description="Deferred revenue.") + other_current_and_non_current_liabilities: Optional[int] = Field( + description="Other current and non-current liabilities." + ) + net_cash_flow_from_operating_activities: Optional[int] = Field( + description="Net cash flow from operating activities." + ) + + purchases_of_marketable_securities: Optional[int] = Field( + description="Purchases of investments." + ) + sales_from_maturities_of_investments: Optional[int] = Field( + description="Sales and maturities of investments." + ) + investments_in_property_plant_and_equipment: Optional[int] = Field( + description="Investments in property, plant, and equipment." + ) + payments_from_acquisitions: Optional[int] = Field( + description="Acquisitions, net of cash acquired, and other" + ) + other_investing_activities: Optional[int] = Field( + description="Other investing activities" + ) + net_cash_flow_from_investing_activities: Optional[int] = Field( + description="Net cash used for investing activities." + ) + + taxes_paid_on_net_share_settlement: Optional[int] = Field( + description="Taxes paid on net share settlement of equity awards." + ) + dividends_paid: Optional[int] = Field( + description="Payments for dividends and dividend equivalents" + ) + common_stock_repurchased: Optional[int] = Field( + description="Payments related to repurchase of common stock" + ) + debt_proceeds: Optional[int] = Field( + description="Proceeds from issuance of term debt" + ) + debt_repayment: Optional[int] = Field(description="Payments of long-term debt") + other_financing_activities: Optional[int] = Field( + description="Other financing activities, net" + ) + net_cash_flow_from_financing_activities: Optional[int] = Field( + description="Net cash flow from financing activities." + ) + net_change_in_cash: Optional[int] = Field( + description="Net increase (decrease) in cash, cash equivalents, and restricted cash" + ) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/cot_search.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/cot_search.py new file mode 100644 index 00000000000..474a1909365 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/cot_search.py @@ -0,0 +1,29 @@ +"""Commitment of Traders Reports Search data model.""" + +from typing import Optional + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams + + +class CotSearchQueryParams(QueryParams): + """Commitment of Traders Reports Search Query Params""" + + query: str = Field(description="Search query.", default="") + + +class CotSearchData(Data): + """Commitment of Traders Reports Search Data.""" + + code: str = Field(description="CFTC Code of the report.") + name: str = Field(description="Name of the underlying asset.") + category: Optional[str] = Field(description="Category of the underlying asset.") + subcategory: Optional[str] = Field( + description="Subcategory of the underlying asset." + ) + units: Optional[str] = Field(description="The units for one contract.") + symbol: Optional[str] = Field( + description="Trading symbol representing the underlying asset." + ) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/crypto_historical.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/crypto_historical.py new file mode 100644 index 00000000000..6113e3f4820 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/crypto_historical.py @@ -0,0 +1,37 @@ +"""Crypto aggregate end of day price data model.""" + + +from datetime import date, datetime +from typing import Optional + +from pydantic import Field, PositiveFloat + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS + + +class CryptoHistoricalQueryParams(QueryParams, BaseSymbol): + """Crypto end of day Query.""" + + start_date: Optional[date] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("start_date", ""), + ) + end_date: Optional[date] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("end_date", ""), + ) + + +class CryptoHistoricalData(Data): + """Crypto end of day price Data.""" + + date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", "")) + open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", "")) + high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", "")) + low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", "")) + close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", "")) + volume: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("volume", "")) + vwap: Optional[PositiveFloat] = Field(description=DATA_DESCRIPTIONS.get("vwap", "")) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/european_index_constituents.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/european_index_constituents.py new file mode 100644 index 00000000000..754005e0b2c --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/european_index_constituents.py @@ -0,0 +1,27 @@ +"""European Index Constituents data model.""" + + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS + + +class EuropeanIndexConstituentsQueryParams(QueryParams, BaseSymbol): + """European Index Constituents Query.""" + + +class EuropeanIndexConstituentsData(Data): + """European Index Constituents data.""" + + symbol: str = Field(description="Symbol of the constituent company in the index.") + price: float = Field( + description="Current price of the constituent company in the index." + ) + open: float = Field(description=DATA_DESCRIPTIONS.get("open", "")) + high: float = Field(description=DATA_DESCRIPTIONS.get("high", "")) + low: float = Field(description=DATA_DESCRIPTIONS.get("low", "")) + close: float = Field(description=DATA_DESCRIPTIONS.get("close", "")) + volume: float = Field(description=DATA_DESCRIPTIONS.get("volume", "")) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/european_index_historical.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/european_index_historical.py new file mode 100644 index 00000000000..4d28832308b --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/european_index_historical.py @@ -0,0 +1,33 @@ +"""European Indices End of Day data model.""" + + +from datetime import ( + date as dateType, + datetime, +) +from typing import Optional + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS + + +class EuropeanIndexHistoricalQueryParams(QueryParams, BaseSymbol): + """European Indices end of day Query.""" + + start_date: Optional[dateType] = Field( + description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None + ) + end_date: Optional[dateType] = Field( + description=QUERY_DESCRIPTIONS.get("end_date", ""), default=None + ) + + +class EuropeanIndexHistoricalData(Data): + """European Indices end of day price data.""" + + date: dateType | datetime = Field(description=DATA_DESCRIPTIONS.get("date", "")) + close: float = Field(description=DATA_DESCRIPTIONS.get("close", "")) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/forex_historical.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/forex_historical.py new file mode 100644 index 00000000000..175f7db1d66 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/forex_historical.py @@ -0,0 +1,37 @@ +"""Forex aggregate end of day price data model.""" + + +from datetime import date, datetime +from typing import Optional + +from pydantic import Field, NonNegativeFloat, PositiveFloat + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS + + +class ForexHistoricalQueryParams(QueryParams, BaseSymbol): + """Forex end of day Query.""" + + start_date: Optional[date] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("start_date", ""), + ) + end_date: Optional[date] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("end_date", ""), + ) + + +class ForexHistoricalData(Data): + """Forex end of day price Data.""" + + date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", "")) + open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", "")) + high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", "")) + low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", "")) + close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", "")) + volume: NonNegativeFloat = Field(description=DATA_DESCRIPTIONS.get("volume", "")) + vwap: Optional[PositiveFloat] = Field(description=DATA_DESCRIPTIONS.get("vwap", "")) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/futures_historical.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/futures_historical.py new file mode 100644 index 00000000000..f353a575081 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/futures_historical.py @@ -0,0 +1,40 @@ +"""Futures aggregate end of day price data model.""" + + +from datetime import date, datetime +from typing import Optional + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS + + +class FuturesHistoricalQueryParams(QueryParams, BaseSymbol): + """Futures end of day Query.""" + + start_date: Optional[date] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("start_date", ""), + ) + end_date: Optional[date] = Field( + default=None, + description=QUERY_DESCRIPTIONS.get("end_date", ""), + ) + expiration: Optional[str] = Field( + default=None, + description="Future expiry date with format YYYY-MM", + ) + + +class FuturesHistoricalData(Data): + """Futures end of day price Data.""" + + date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", "")) + open: float = Field(description=DATA_DESCRIPTIONS.get("open", "")) + high: float = Field(description=DATA_DESCRIPTIONS.get("high", "")) + low: float = Field(description=DATA_DESCRIPTIONS.get("low", "")) + close: float = Field(description=DATA_DESCRIPTIONS.get("close", "")) + volume: float = Field(description=DATA_DESCRIPTIONS.get("volume", "")) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/income_statement.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/income_statement.py index 4501ea886b9..d897712f4c5 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/standard_models/income_statement.py +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/income_statement.py @@ -1,34 +1,28 @@ """Income Statement Data Model.""" -from datetime import ( - date as dateType, - datetime, -) +from datetime import date as dateType from typing import Optional from pydantic import Field from openbb_provider.abstract.data import Data -from openbb_provider.standard_models.base import FinancialStatementQueryParams +from openbb_provider.standard_models.base import ( + BaseSymbol, + FinancialStatementQueryParams, +) class IncomeStatementQueryParams(FinancialStatementQueryParams): """Income Statement Query.""" -class IncomeStatementData(Data): +class IncomeStatementData(Data, BaseSymbol): """Income Statement Data.""" date: dateType = Field(description="Date of the income statement.") - symbol: str = Field(description="Symbol of the company.") - cik: Optional[str] = Field(description="Central Index Key.") - - currency: Optional[str] = Field(description="Reporting currency.") - filing_date: Optional[dateType] = Field(description="Filling date.") - accepted_date: Optional[datetime] = Field(description="Accepted date.") - calendar_year: Optional[int] = Field(description="Calendar year.") - period: Optional[str] = Field(description="Period of the income statement.") + period: str = Field(description="Period of the income statement.") + cik: str = Field(description="Central Index Key.") revenue: Optional[int] = Field(description="Revenue.") cost_of_revenue: Optional[int] = Field(description="Cost of revenue.") @@ -87,5 +81,3 @@ class IncomeStatementData(Data): weighted_average_shares_outstanding_dil: Optional[int] = Field( description="Weighted average shares outstanding diluted." ) - link: Optional[str] = Field(description="Link to the income statement.") - final_link: Optional[str] = Field(description="Final link to the income statement.") diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/index_search.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/index_search.py new file mode 100644 index 00000000000..14ae4cc4702 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/index_search.py @@ -0,0 +1,22 @@ +"""Index Search data model.""" + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams + + +class IndexSearchQueryParams(QueryParams): + """Index Search Query Params""" + + query: str = Field(description="Search query.", default="") + symbol: bool = Field( + description="Whether to search by ticker symbol.", default=False + ) + + +class IndexSearchData(Data): + """Company Search Data.""" + + symbol: str = Field(description="Symbol of the index.") + name: str = Field(description="Name of the index.") diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/index_snapshots.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/index_snapshots.py new file mode 100644 index 00000000000..23c556e3406 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/index_snapshots.py @@ -0,0 +1,34 @@ +"""Index Snapshots data model.""" + +from typing import Literal, Optional + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams + + +class IndexSnapshotsQueryParams(QueryParams): + """Index Search Query Params""" + + region: Optional[Literal["US", "EU"]] = Field( + description="The region to return. Currently supports US and EU.", default="US" + ) + + +class IndexSnapshotsData(Data): + """Index Snapshot Data.""" + + symbol: str = Field(description="Symbol of the index.") + name: Optional[str] = Field(description="Name of the index.") + currency: Optional[str] = Field(description="Currency of the index.") + price: Optional[float] = Field(description="Current price of the index.") + open: Optional[float] = Field(description="Opening price of the index.") + high: Optional[float] = Field(description="Highest price of the index.") + low: Optional[float] = Field(description="Lowest price of the index.") + close: Optional[float] = Field(description="Closing price of the index.") + prev_close: Optional[float] = Field( + description="Previous closing price of the index." + ) + change: Optional[float] = Field(description="Change of the index.") + change_percent: Optional[float] = Field(description="Change percent of the index.") diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/major_indices_historical.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/major_indices_historical.py new file mode 100644 index 00000000000..e209ec3eb15 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/major_indices_historical.py @@ -0,0 +1,39 @@ +"""Major indices aggregate end of day price data model.""" + + +from datetime import ( + date as dateType, + datetime, +) +from typing import Optional + +from pydantic import Field, NonNegativeInt, PositiveFloat + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS + + +class MajorIndicesHistoricalQueryParams(QueryParams, BaseSymbol): + """Major Indices end of day Query.""" + + start_date: Optional[dateType] = Field( + description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None + ) + end_date: Optional[dateType] = Field( + description=QUERY_DESCRIPTIONS.get("end_date", ""), default=None + ) + + +class MajorIndicesHistoricalData(Data): + """Major Indices end of day price data.""" + + date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", "")) + open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", "")) + high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", "")) + low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", "")) + close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", "")) + volume: Optional[NonNegativeInt] = Field( + description=DATA_DESCRIPTIONS.get("volume", "") + ) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/options_chains.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/options_chains.py index f39c252c745..105ea8fe977 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/standard_models/options_chains.py +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/options_chains.py @@ -19,6 +19,7 @@ class OptionsChainsData(Data): expiration: datetime = Field(description="Expiration date of the contract.") strike: float = Field(description="Strike price of the contract.") option_type: str = Field(description="Call or Put.") + contract_symbol: str = Field(description="Contract symbol for the option.") bid: float = Field(description="Bid price of the contract.") ask: float = Field(description="Ask price of the contract.") open_interest: float = Field(description="Open interest on the contract.") diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/sp500_multiples.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/sp500_multiples.py new file mode 100644 index 00000000000..d17309c3aac --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/sp500_multiples.py @@ -0,0 +1,77 @@ +"""SP500 Multiples Data model.""" + +from typing import Literal, Optional + +from pydantic import Field + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams + + +class SP500MultiplesQueryParams(QueryParams): + """Gets historical S&P 500 levels, ratios, and multiples.""" + + series_name: Literal[ + "Shiller PE Ratio by Month", + "Shiller PE Ratio by Year", + "PE Ratio by Year", + "PE Ratio by Month", + "Dividend by Year", + "Dividend by Month", + "Dividend Growth by Quarter", + "Dividend Growth by Year", + "Dividend Yield by Year", + "Dividend Yield by Month", + "Earnings by Year", + "Earnings by Month", + "Earnings Growth by Year", + "Earnings Growth by Quarter", + "Real Earnings Growth by Year", + "Real Earnings Growth by Quarter", + "Earnings Yield by Year", + "Earnings Yield by Month", + "Real Price by Year", + "Real Price by Month", + "Inflation Adjusted Price by Year", + "Inflation Adjusted Price by Month", + "Sales by Year", + "Sales by Quarter", + "Sales Growth by Year", + "Sales Growth by Quarter", + "Real Sales by Year", + "Real Sales by Quarter", + "Real Sales Growth by Year", + "Real Sales Growth by Quarter", + "Price to Sales Ratio by Year", + "Price to Sales Ratio by Quarter", + "Price to Book Value Ratio by Year", + "Price to Book Value Ratio by Quarter", + "Book Value per Share by Year", + "Book Value per Share by Quarter", + ] = Field( + description="The name of the series. Defaults to 'PE Ratio by Month'.", + default="PE Ratio by Month", + ) + start_date: Optional[str] = Field( + description="The start date of the time series. Format: YYYY-MM-DD", default="" + ) + end_date: Optional[str] = Field( + description="The end date of the time series. Format: YYYY-MM-DD", default="" + ) + collapse: Optional[ + Literal["daily", "weekly", "monthly", "quarterly", "annual"] + ] = Field( + description="Collapse the frequency of the time series.", + default="monthly", + ) + transform: Optional[Literal["diff", "rdiff", "cumul", "normalize"]] = Field( + description="The transformation of the time series.", + default=None, + ) + + +class SP500MultiplesData(Data): + """SP500 Multiples Data.""" + + date: str = Field(description="The date data for the time series.") + value: float = Field(description="The data value for the time series.") diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_historical.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_historical.py new file mode 100644 index 00000000000..2d8832a5b12 --- /dev/null +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_historical.py @@ -0,0 +1,38 @@ +"""Stock aggregate end of day price data model.""" + + +from datetime import ( + date as dateType, + datetime, +) +from typing import Optional + +from pydantic import Field, NonNegativeInt, PositiveFloat + +from openbb_provider.abstract.data import Data +from openbb_provider.abstract.query_params import QueryParams +from openbb_provider.standard_models.base import BaseSymbol +from openbb_provider.utils.descriptions import DATA_DESCRIPTIONS, QUERY_DESCRIPTIONS + + +class StockHistoricalQueryParams(QueryParams, BaseSymbol): + """Stock end of day Query.""" + + start_date: Optional[dateType] = Field( + description=QUERY_DESCRIPTIONS.get("start_date", ""), default=None + ) + end_date: Optional[dateType] = Field( + description=QUERY_DESCRIPTIONS.get("end_date", ""), default=None + ) + + +class StockHistoricalData(Data): + """Stock end of day price Data.""" + + date: datetime = Field(description=DATA_DESCRIPTIONS.get("date", "")) + open: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("open", "")) + high: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("high", "")) + low: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("low", "")) + close: PositiveFloat = Field(description=DATA_DESCRIPTIONS.get("close", "")) + volume: NonNegativeInt = Field(description=DATA_DESCRIPTIONS.get("volume", "")) + vwap: Optional[PositiveFloat] = Field(description=DATA_DESCRIPTIONS.get("vwap", "")) diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_info.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_info.py index 44cf141dfc4..c91583f90c0 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_info.py +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_info.py @@ -17,17 +17,15 @@ class StockInfoData(Data, BaseSymbol): """Stock Info Data.""" name: str = Field(description="Name associated with the ticker symbol.") - price: float = Field(description="Last price of the stock.") - open: Optional[float] = Field(description="Opening price of the stock.") - high: Optional[float] = Field(description="High price of the current trading day.") - low: Optional[float] = Field(description="Low price of the current trading day.") - close: Optional[float] = Field(description="Closing price of the stock.") + price: float = Field(description="Last transaction price.") + open: float = Field(description="Opening price of the stock.") + high: float = Field(description="High price of the current trading day.") + low: float = Field(description="Low price of the current trading day.") + close: float = Field(description="Closing price of the most recent trading day.") change: Optional[float] = Field( description="Change in price over the current trading period." ) change_percent: Optional[float] = Field( - description="% change in price over the current trading period." - ) - previous_close: Optional[float] = Field( - description="Previous closing price of the stock." + description="Percent change in price over the current trading period." ) + prev_close: Optional[float] = Field(description="Previous closing price.") diff --git a/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_quote.py b/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_quote.py index 81a5394ac16..e558edef441 100644 --- a/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_quote.py +++ b/openbb_sdk/sdk/provider/openbb_provider/standard_models/stock_quote.py @@ -27,13 +27,6 @@ class StockQuoteQueryParams(QueryParams, BaseSymbol): class StockQuoteData(Data): """Stock Quote data.""" - symbol: str = Field(description="Symbol of the company.") - name: Optional[str] = Field(description="Name of the company.") - price: Optional[float] = Field(description="Current trading price of the stock.") - changes_percentage: Optional[float] = Field( - description="Change percentage of the stock price." - ) - change: Optional[float] = Field(description="Change of the stock price.") day_low: Optional[float] = Field( default=None, description="Lowest price of the stock in the current trading day.", @@ -42,42 +35,6 @@ class StockQuoteData(Data): default=None, description="Highest price of the stock in the current trading day.", ) - year_high: Optional[float] = Field( - description="Highest price of the stock in the last 52 weeks." - ) - year_low: Optional[float] = Field( - description="Lowest price of the stock in the last 52 weeks." - ) - market_cap: Optional[float] = Field(description="Market cap of the company.") - price_avg50: Optional[float] = Field( - description="50 days average price of the stock." - ) - price_avg200: Optional[float] = Field( - description="200 days average price of the stock." - ) - volume: Optional[int] = Field( - description="Volume of the stock in the current trading day." - ) - avg_volume: Optional[int] = Field( - default=None, - description="Average volume of the stock in the last 10 trading days.", - ) - exchange: Optional[str] = Field(description="Exchange the stock is traded on.") - open: Optional[float] = Field( - default=None, - description="Opening price of the stock in the current trading day.", - ) - previous_close: Optional[float] = Field( - description="Previous closing price of the stock." - ) - eps: Optional[float] = Field(description="Earnings per share of the stock.") - pe: Optional[float] = Field(description="Price earnings ratio of the stock.") - earnings_announcement: Optional[str] = Field( - description="Earnings announcement date of the stock." - ) - shares_outstanding: Optional[int] = Field( - description="Number of shares outstanding of the stock." - ) date: Optional[datetime] = Field( description="Timestamp of the stock quote.", alias="timestamp" )