From cd926ac3dd9bb28500926f39e50f8a5c0cb01d37 Mon Sep 17 00:00:00 2001 From: Virat Singh Date: Thu, 29 Feb 2024 13:56:05 -0500 Subject: [PATCH] community: Add PolygonFinancials Tool (#18324) **Description:** In this PR, I am adding a `PolygonFinancials` tool, which can be used to get financials data for a given ticker. The financials data is the fundamental data that is found in income statements, balance sheets, and cash flow statements of public US companies. **Twitter**: [@virattt](https://twitter.com/virattt) --- docs/docs/integrations/tools/polygon.ipynb | 178 +++++++++++++++--- .../agent_toolkits/polygon/toolkit.py | 9 +- .../langchain_community/tools/__init__.py | 9 + .../tools/polygon/__init__.py | 2 + .../tools/polygon/financials.py | 38 ++++ .../langchain_community/utilities/polygon.py | 23 ++- .../tests/unit_tests/tools/test_imports.py | 1 + .../tests/unit_tests/tools/test_public_api.py | 1 + 8 files changed, 232 insertions(+), 29 deletions(-) create mode 100644 libs/community/langchain_community/tools/polygon/financials.py diff --git a/docs/docs/integrations/tools/polygon.ipynb b/docs/docs/integrations/tools/polygon.ipynb index 0349ac67f7..151791254e 100644 --- a/docs/docs/integrations/tools/polygon.ipynb +++ b/docs/docs/integrations/tools/polygon.ipynb @@ -16,14 +16,22 @@ }, { "cell_type": "code", - "execution_count": null, + "execution_count": 1, "id": "34bb5968", "metadata": { "id": "34bb5968", "is_executing": true, "scrolled": true }, - "outputs": [], + "outputs": [ + { + "name": "stdin", + "output_type": "stream", + "text": [ + " ········\n" + ] + } + ], "source": [ "import getpass\n", "import os\n", @@ -33,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 11, "id": "ac4910f8", "metadata": { "id": "ac4910f8", @@ -41,6 +49,7 @@ }, "outputs": [], "source": [ + "from langchain_community.tools.polygon.financials import PolygonFinancials\n", "from langchain_community.tools.polygon.last_quote import PolygonLastQuote\n", "from langchain_community.tools.polygon.ticker_news import PolygonTickerNews\n", "from langchain_community.utilities.polygon import PolygonAPIWrapper" @@ -48,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 3, "id": "8660b910-905b-46f3-9541-920b9fc3d4d6", "metadata": {}, "outputs": [], @@ -67,7 +76,7 @@ }, { "cell_type": "code", - "execution_count": 55, + "execution_count": 4, "id": "84b8f773", "metadata": { "id": "84b8f773" @@ -77,7 +86,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Tool output: {\"P\": 180.99, \"S\": 5, \"T\": \"AAPL\", \"X\": 11, \"i\": [604], \"p\": 180.98, \"q\": 31662815, \"s\": 2, \"t\": 1708445246516556649, \"x\": 21, \"y\": 1708445246516369924, \"z\": 3}\n" + "Tool output: {\"P\": 181.18, \"S\": 7, \"T\": \"AAPL\", \"X\": 11, \"i\": [604], \"p\": 181.13, \"q\": 704855, \"s\": 3, \"t\": 1709213573791533513, \"x\": 8, \"y\": 1709213573791191178, \"z\": 3}\n" ] } ], @@ -90,7 +99,7 @@ }, { "cell_type": "code", - "execution_count": 29, + "execution_count": 5, "id": "068991a6", "metadata": { "id": "068991a6", @@ -107,7 +116,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 7, "id": "174e2556-eb3e-48a4-bde6-9a3309fae9c9", "metadata": {}, "outputs": [ @@ -115,7 +124,7 @@ "name": "stdout", "output_type": "stream", "text": [ - "Latest price for AAPL is $180.74\n" + "Latest price for AAPL is $181.13\n" ] } ], @@ -135,27 +144,18 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": null, "id": "024982db-1402-4bd7-9788-6cb369a9565d", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Tool output: [{\"id\": \"RckckqTS-K2zI6WRyycBB0HonfGLc2MPTQROWsbpKSA\", \"publisher\": {\"name\": \"The Motley Fool\", \"homepage_url\": \"https://www.fool.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/themotleyfool.svg\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/themotleyfool.ico\"}, \"title\": \"Should You Worry About Apple's Slowdown in China?\", \"author\": \"newsfeedback@fool.com (Adria Cimino)\", \"published_utc\": \"2024-02-20T15:10:00Z\", \"article_url\": \"https://www.fool.com/investing/2024/02/20/should-you-worry-about-apples-slowdown-in-china/\", \"tickers\": [\"AAPL\"], \"image_url\": \"https://g.foolcdn.com/editorial/images/765910/aapl.png\", \"description\": \"A local smartphone giant is gaining market share.\", \"keywords\": [\"investing\"]}, {\"id\": \"5goYCKw3ZsHlJYwN1XX8AJCyybZuvfJeoUz38SzlYBM\", \"publisher\": {\"name\": \"The Motley Fool\", \"homepage_url\": \"https://www.fool.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/themotleyfool.svg\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/themotleyfool.ico\"}, \"title\": \"Vanguard Total Stock Market ETF: Buy, Sell, or Hold?\", \"author\": \"newsfeedback@fool.com (Justin Pope)\", \"published_utc\": \"2024-02-20T12:30:00Z\", \"article_url\": \"https://www.fool.com/investing/2024/02/20/vanguard-total-stock-market-etf-buy-sell-or-hold/\", \"tickers\": [\"VTI\", \"AAPL\", \"MSFT\", \"GOOGL\", \"AMZN\", \"NVDA\", \"META\", \"TSLA\", \"GOOG\"], \"image_url\": \"https://g.foolcdn.com/editorial/images/765208/getty-buy-sell-hold-stocks-decide-ratings-analysts.jpg\", \"description\": \"This is the ultimate tool to diversify your portfolio.\", \"keywords\": [\"investing\"]}, {\"id\": \"F2nshszd6rBX-JJMHtbPuA325ZBizcq7iIJ7PBK_114\", \"publisher\": {\"name\": \"MarketWatch\", \"homepage_url\": \"https://www.marketwatch.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/marketwatch.svg\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/marketwatch.ico\"}, \"title\": \"Wall Street\\u2019s \\u2018mob psychology\\u2019 could fuel a dangerous stock meltup, warns top strategist\", \"author\": \"MarketWatch\", \"published_utc\": \"2024-02-20T12:20:00Z\", \"article_url\": \"https://www.marketwatch.com/story/wall-streets-mob-psychology-could-fuel-a-dangerous-stock-meltup-warns-top-strategist-fc8647c6\", \"tickers\": [\"NVDA\", \"GOOGL\", \"AMZN\", \"AAPL\", \"META\", \"MSFT\", \"NFLX\", \"TSLA\", \"COF\", \"DFS\", \"WMT\", \"VZIO\", \"HD\", \"PANW\", \"CZR\", \"SMCI\", \"OCGN\", \"NIO\", \"MARA\", \"AMD\", \"COIN\"], \"amp_url\": \"https://www.marketwatch.com/amp/story/wall-streets-mob-psychology-could-fuel-a-dangerous-stock-meltup-warns-top-strategist-fc8647c6\", \"image_url\": \"https://images.mktw.net/im-59050122/social\", \"description\": \"Ed Yardeni says giddy Wall Street analysts could be the undoing of this stock market.\"}, {\"id\": \"uvUtqCvuVV-wyCECL0DTIbHdqAtEgviJqSrPurvrqEQ\", \"publisher\": {\"name\": \"Zacks Investment Research\", \"homepage_url\": \"https://www.zacks.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/zacks.png\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/zacks.ico\"}, \"title\": \"Should Vanguard Mega Cap ETF (MGC) Be on Your Investing Radar?\", \"author\": \"Zacks Equity Research\", \"published_utc\": \"2024-02-20T11:20:07Z\", \"article_url\": \"https://www.zacks.com/stock/news/2228257/should-vanguard-mega-cap-etf-mgc-be-on-your-investing-radar\", \"tickers\": [\"MGC\", \"AMZN\", \"AAPL\", \"MSFT\", \"SPY\", \"IVV\"], \"amp_url\": \"https://www.zacks.com/amp/stock/news/2228257/should-vanguard-mega-cap-etf-mgc-be-on-your-investing-radar\", \"image_url\": \"https://staticx-tuner.zacks.com/images/default_article_images/default17.jpg\", \"description\": \"Style Box ETF report for MGC\"}, {\"id\": \"RRxHgtvw7_7Ql0QhUphMlzXdUjWhJbpZVjHqR7N5TCg\", \"publisher\": {\"name\": \"Zacks Investment Research\", \"homepage_url\": \"https://www.zacks.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/zacks.png\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/zacks.ico\"}, \"title\": \"Should Vanguard S&P 500 ETF (VOO) Be on Your Investing Radar?\", \"author\": \"Zacks Equity Research\", \"published_utc\": \"2024-02-20T11:20:06Z\", \"article_url\": \"https://www.zacks.com/stock/news/2228264/should-vanguard-sp-500-etf-voo-be-on-your-investing-radar\", \"tickers\": [\"VOO\", \"AMZN\", \"AAPL\", \"MSFT\", \"SPY\", \"IVV\"], \"amp_url\": \"https://www.zacks.com/amp/stock/news/2228264/should-vanguard-sp-500-etf-voo-be-on-your-investing-radar\", \"image_url\": \"https://staticx-tuner.zacks.com/images/default_article_images/default24.jpg\", \"description\": \"Style Box ETF report for VOO\"}, {\"id\": \"QBaNxnCVlXTHlVAChWRdM5RrWCD9f20qp6aUxfdxrEI\", \"publisher\": {\"name\": \"Zacks Investment Research\", \"homepage_url\": \"https://www.zacks.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/zacks.png\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/zacks.ico\"}, \"title\": \"Should Fidelity Nasdaq Composite Index ETF (ONEQ) Be on Your Investing Radar?\", \"author\": \"Zacks Equity Research\", \"published_utc\": \"2024-02-20T11:20:05Z\", \"article_url\": \"https://www.zacks.com/stock/news/2228269/should-fidelity-nasdaq-composite-index-etf-oneq-be-on-your-investing-radar\", \"tickers\": [\"ONEQ\", \"AMZN\", \"AAPL\", \"MSFT\", \"QQQ\", \"VUG\"], \"amp_url\": \"https://www.zacks.com/amp/stock/news/2228269/should-fidelity-nasdaq-composite-index-etf-oneq-be-on-your-investing-radar\", \"image_url\": \"https://staticx-tuner.zacks.com/images/default_article_images/default29.jpg\", \"description\": \"Style Box ETF report for ONEQ\"}, {\"id\": \"aVYhWKzOHm1Y8k8z9ka0xrCCI-tiUWYDdsrPuDFzG_g\", \"publisher\": {\"name\": \"The Motley Fool\", \"homepage_url\": \"https://www.fool.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/themotleyfool.svg\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/themotleyfool.ico\"}, \"title\": \"Apple Is Synonymous With iPhones, But Its Largest Gross Margin Comes From Somewhere Else Entirely\", \"author\": \"newsfeedback@fool.com (Neil Patel)\", \"published_utc\": \"2024-02-20T11:07:00Z\", \"article_url\": \"https://www.fool.com/investing/2024/02/20/apple-synonymous-iphones-devices-gross-margin/\", \"tickers\": [\"AAPL\"], \"image_url\": \"https://g.foolcdn.com/editorial/images/765917/aapl_revenue_bar.png\", \"description\": \"Investors need to pay attention to a budding segment.\", \"keywords\": [\"investing\"]}, {\"id\": \"6uW_52HjWOj3sKeCdPrqN4ZHmIbJAZxXV5naPVzjaHw\", \"publisher\": {\"name\": \"The Motley Fool\", \"homepage_url\": \"https://www.fool.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/themotleyfool.svg\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/themotleyfool.ico\"}, \"title\": \"Warren Buffett Has 51% of Berkshire Hathaway's $370 Billion Portfolio Invested in 2 Stocks\", \"author\": \"newsfeedback@fool.com (Trevor Jennewine)\", \"published_utc\": \"2024-02-20T10:45:00Z\", \"article_url\": \"https://www.fool.com/investing/2024/02/20/warren-buffett-51-portfolio-invested-in-2-stocks/\", \"tickers\": [\"AAPL\", \"KO\", \"BRK.A\", \"BRK.B\"], \"image_url\": \"https://g.foolcdn.com/editorial/images/765625/market-3.jpg\", \"description\": \"Warren Buffett's Berkshire Hathaway has more than half of its stock portfolio invested in Apple and Coca-Cola.\", \"keywords\": [\"investing\"]}, {\"id\": \"aE6I7jULkhZEsKWnVsRNUaPYNfsHBC89wARk4mf6iPQ\", \"publisher\": {\"name\": \"Investing.com\", \"homepage_url\": \"https://www.investing.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/investing.png\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/investing.ico\"}, \"title\": \"20-Year High Bullish Sentiment Meets Record Tech Allocation: Recipe for Disaster?\", \"author\": \"Investing.com\", \"published_utc\": \"2024-02-20T10:24:00Z\", \"article_url\": \"https://www.investing.com/analysis/20year-high-bullish-sentiment-meets-record-tech-allocation-recipe-for-disaster-200646188\", \"tickers\": [\"MSFT\", \"AAPL\", \"NVDA\", \"AMZN\", \"GOOGL\", \"META\"], \"amp_url\": \"https://m.investing.com/analysis/20year-high-bullish-sentiment-meets-record-tech-allocation-recipe-for-disaster-200646188?ampMode=1\", \"image_url\": \"https://i-invdn-com.investing.com/redesign/images/seo/investingcom_analysis_og.jpg\"}, {\"id\": \"EJIIij7T9dEbvogmzWS_P_1cLvVskocSSLrM3p2V_qE\", \"publisher\": {\"name\": \"Investing.com\", \"homepage_url\": \"https://www.investing.com/\", \"logo_url\": \"https://s3.polygon.io/public/assets/news/logos/investing.png\", \"favicon_url\": \"https://s3.polygon.io/public/assets/news/favicons/investing.ico\"}, \"title\": \"3 Wide-Moat Stocks Worth Buying in 2024\", \"author\": \"The Tokenist\", \"published_utc\": \"2024-02-20T07:09:00Z\", \"article_url\": \"https://www.investing.com/analysis/3-widemoat-stocks-worth-buying-in-2024-200646181\", \"tickers\": [\"KO\", \"GOOGL\", \"AAPL\", \"META\", \"AMZN\", \"MSFT\", \"NVDA\", \"AX\", \"QTWO\", \"ADBE\", \"CRM\"], \"amp_url\": \"https://m.investing.com/analysis/3-widemoat-stocks-worth-buying-in-2024-200646181?ampMode=1\", \"image_url\": \"https://i-invdn-com.investing.com/redesign/images/seo/investingcom_analysis_og.jpg\"}]\n" - ] - } - ], + "outputs": [], "source": [ "ticker_news_tool = PolygonTickerNews(api_wrapper=api_wrapper)\n", - "ticker_news = ticker_news_tool.run(ticker)\n", - "print(f\"Tool output: {ticker_news}\")" + "ticker_news = ticker_news_tool.run(ticker)" ] }, { "cell_type": "code", - "execution_count": 57, + "execution_count": 9, "id": "dfd26ef6-2d92-483e-9780-484091bd3774", "metadata": {}, "outputs": [ @@ -175,7 +175,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 10, "id": "dbbb4b43-1096-45f3-8000-45538b3c73ee", "metadata": {}, "outputs": [ @@ -183,10 +183,10 @@ "name": "stdout", "output_type": "stream", "text": [ - "Title: Should You Worry About Apple's Slowdown in China?\n", - "Description: A local smartphone giant is gaining market share.\n", - "Publisher: The Motley Fool\n", - "URL: https://www.fool.com/investing/2024/02/20/should-you-worry-about-apples-slowdown-in-china/\n" + "Title: An AI surprise could fuel a 20% rally for the S&P 500 in 2024, says UBS\n", + "Description: If Gen AI causes a big productivity boost, stocks could see an unexpected rally this year, say UBS strategists.\n", + "Publisher: MarketWatch\n", + "URL: https://www.marketwatch.com/story/an-ai-surprise-could-fuel-a-20-rally-for-the-s-p-500-in-2024-says-ubs-1044d716\n" ] } ], @@ -198,6 +198,130 @@ "print(f\"Publisher: {news_item['publisher']['name']}\")\n", "print(f\"URL: {news_item['article_url']}\")" ] + }, + { + "cell_type": "markdown", + "id": "675cbae0-a754-45b0-be01-738333c3255e", + "metadata": {}, + "source": [ + "### Get financials for ticker" + ] + }, + { + "cell_type": "code", + "execution_count": 28, + "id": "f46a8c88-8793-470d-8fce-31e8d4b1f77c", + "metadata": {}, + "outputs": [], + "source": [ + "financials_tool = PolygonFinancials(api_wrapper=api_wrapper)\n", + "financials = financials_tool.run(ticker)" + ] + }, + { + "cell_type": "code", + "execution_count": 30, + "id": "3495021c-a31b-4dba-8daf-811c43e24bd9", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Total reporting periods: 10\n" + ] + } + ], + "source": [ + "# Convert the financials response to JSON\n", + "financials_json = json.loads(financials)\n", + "print(f\"Total reporting periods: {len(financials_json)}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "id": "86215a03-a927-4334-a82b-54cb9574ed05", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Company name: APPLE INC\n", + "CIK: 0000320193\n", + "Fiscal period: TTM\n", + "End date: 2023-12-30\n", + "Start date: 2022-12-31\n" + ] + } + ], + "source": [ + "# Print the latest reporting period's financials metadata\n", + "financial_data = financials_json[0]\n", + "print(f\"Company name: {financial_data['company_name']}\")\n", + "print(f\"CIK: {financial_data['cik']}\")\n", + "print(f\"Fiscal period: {financial_data['fiscal_period']}\")\n", + "print(f\"End date: {financial_data['end_date']}\")\n", + "print(f\"Start date: {financial_data['start_date']}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "id": "2665d48b-fd44-4279-a2fe-e42836d3acdb", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Income statement: {'diluted_earnings_per_share': {'value': 6.42, 'unit': 'USD / shares', 'label': 'Diluted Earnings Per Share', 'order': 4300}, 'costs_and_expenses': {'value': 267270000000.0, 'unit': 'USD', 'label': 'Costs And Expenses', 'order': 600}, 'net_income_loss_attributable_to_noncontrolling_interest': {'value': 0, 'unit': 'USD', 'label': 'Net Income/Loss Attributable To Noncontrolling Interest', 'order': 3300}, 'net_income_loss_attributable_to_parent': {'value': 100913000000.0, 'unit': 'USD', 'label': 'Net Income/Loss Attributable To Parent', 'order': 3500}, 'income_tax_expense_benefit': {'value': 17523000000.0, 'unit': 'USD', 'label': 'Income Tax Expense/Benefit', 'order': 2200}, 'income_loss_from_continuing_operations_before_tax': {'value': 118436000000.0, 'unit': 'USD', 'label': 'Income/Loss From Continuing Operations Before Tax', 'order': 1500}, 'operating_expenses': {'value': 55013000000.0, 'unit': 'USD', 'label': 'Operating Expenses', 'order': 1000}, 'benefits_costs_expenses': {'value': 267270000000.0, 'unit': 'USD', 'label': 'Benefits Costs and Expenses', 'order': 200}, 'diluted_average_shares': {'value': 47151996000.0, 'unit': 'shares', 'label': 'Diluted Average Shares', 'order': 4500}, 'cost_of_revenue': {'value': 212035000000.0, 'unit': 'USD', 'label': 'Cost Of Revenue', 'order': 300}, 'operating_income_loss': {'value': 118658000000.0, 'unit': 'USD', 'label': 'Operating Income/Loss', 'order': 1100}, 'net_income_loss_available_to_common_stockholders_basic': {'value': 100913000000.0, 'unit': 'USD', 'label': 'Net Income/Loss Available To Common Stockholders, Basic', 'order': 3700}, 'preferred_stock_dividends_and_other_adjustments': {'value': 0, 'unit': 'USD', 'label': 'Preferred Stock Dividends And Other Adjustments', 'order': 3900}, 'research_and_development': {'value': 29902000000.0, 'unit': 'USD', 'label': 'Research and Development', 'order': 1030}, 'revenues': {'value': 385706000000.0, 'unit': 'USD', 'label': 'Revenues', 'order': 100}, 'participating_securities_distributed_and_undistributed_earnings_loss_basic': {'value': 0, 'unit': 'USD', 'label': 'Participating Securities, Distributed And Undistributed Earnings/Loss, Basic', 'order': 3800}, 'selling_general_and_administrative_expenses': {'value': 25111000000.0, 'unit': 'USD', 'label': 'Selling, General, and Administrative Expenses', 'order': 1010}, 'nonoperating_income_loss': {'value': -222000000.0, 'unit': 'USD', 'label': 'Nonoperating Income/Loss', 'order': 900}, 'income_loss_from_continuing_operations_after_tax': {'value': 100913000000.0, 'unit': 'USD', 'label': 'Income/Loss From Continuing Operations After Tax', 'order': 1400}, 'basic_earnings_per_share': {'value': 6.46, 'unit': 'USD / shares', 'label': 'Basic Earnings Per Share', 'order': 4200}, 'basic_average_shares': {'value': 46946265000.0, 'unit': 'shares', 'label': 'Basic Average Shares', 'order': 4400}, 'gross_profit': {'value': 173671000000.0, 'unit': 'USD', 'label': 'Gross Profit', 'order': 800}, 'net_income_loss': {'value': 100913000000.0, 'unit': 'USD', 'label': 'Net Income/Loss', 'order': 3200}}\n" + ] + } + ], + "source": [ + "# Print the latest reporting period's income statement\n", + "print(f\"Income statement: {financial_data['financials']['income_statement']}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "id": "9e24d339-c0d5-4b6a-9ba6-3f97e46ff6df", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Balance sheet: {'equity_attributable_to_noncontrolling_interest': {'value': 0, 'unit': 'USD', 'label': 'Equity Attributable To Noncontrolling Interest', 'order': 1500}, 'other_noncurrent_liabilities': {'value': 39441000000.0, 'unit': 'USD', 'label': 'Other Non-current Liabilities', 'order': 820}, 'equity': {'value': 74100000000.0, 'unit': 'USD', 'label': 'Equity', 'order': 1400}, 'liabilities': {'value': 279414000000.0, 'unit': 'USD', 'label': 'Liabilities', 'order': 600}, 'noncurrent_assets': {'value': 209822000000.0, 'unit': 'USD', 'label': 'Noncurrent Assets', 'order': 300}, 'equity_attributable_to_parent': {'value': 74100000000.0, 'unit': 'USD', 'label': 'Equity Attributable To Parent', 'order': 1600}, 'liabilities_and_equity': {'value': 353514000000.0, 'unit': 'USD', 'label': 'Liabilities And Equity', 'order': 1900}, 'other_current_liabilities': {'value': 75827000000.0, 'unit': 'USD', 'label': 'Other Current Liabilities', 'order': 740}, 'inventory': {'value': 6511000000.0, 'unit': 'USD', 'label': 'Inventory', 'order': 230}, 'other_noncurrent_assets': {'value': 166156000000.0, 'unit': 'USD', 'label': 'Other Non-current Assets', 'order': 350}, 'other_current_assets': {'value': 137181000000.0, 'unit': 'USD', 'label': 'Other Current Assets', 'order': 250}, 'current_liabilities': {'value': 133973000000.0, 'unit': 'USD', 'label': 'Current Liabilities', 'order': 700}, 'noncurrent_liabilities': {'value': 145441000000.0, 'unit': 'USD', 'label': 'Noncurrent Liabilities', 'order': 800}, 'fixed_assets': {'value': 43666000000.0, 'unit': 'USD', 'label': 'Fixed Assets', 'order': 320}, 'long_term_debt': {'value': 106000000000.0, 'unit': 'USD', 'label': 'Long-term Debt', 'order': 810}, 'current_assets': {'value': 143692000000.0, 'unit': 'USD', 'label': 'Current Assets', 'order': 200}, 'assets': {'value': 353514000000.0, 'unit': 'USD', 'label': 'Assets', 'order': 100}, 'accounts_payable': {'value': 58146000000.0, 'unit': 'USD', 'label': 'Accounts Payable', 'order': 710}}\n" + ] + } + ], + "source": [ + "# Print the latest reporting period's balance sheet\n", + "print(f\"Balance sheet: {financial_data['financials']['balance_sheet']}\")" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "id": "4bfb47f1-8b9e-4293-be18-c4e9ab945d51", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Cash flow statement: {'net_cash_flow_continuing': {'value': 20000000000.0, 'unit': 'USD', 'label': 'Net Cash Flow, Continuing', 'order': 1200}, 'net_cash_flow_from_investing_activities_continuing': {'value': 7077000000.0, 'unit': 'USD', 'label': 'Net Cash Flow From Investing Activities, Continuing', 'order': 500}, 'net_cash_flow_from_investing_activities': {'value': 7077000000.0, 'unit': 'USD', 'label': 'Net Cash Flow From Investing Activities', 'order': 400}, 'net_cash_flow_from_financing_activities_continuing': {'value': -103510000000.0, 'unit': 'USD', 'label': 'Net Cash Flow From Financing Activities, Continuing', 'order': 800}, 'net_cash_flow_from_operating_activities': {'value': 116433000000.0, 'unit': 'USD', 'label': 'Net Cash Flow From Operating Activities', 'order': 100}, 'net_cash_flow_from_financing_activities': {'value': -103510000000.0, 'unit': 'USD', 'label': 'Net Cash Flow From Financing Activities', 'order': 700}, 'net_cash_flow_from_operating_activities_continuing': {'value': 116433000000.0, 'unit': 'USD', 'label': 'Net Cash Flow From Operating Activities, Continuing', 'order': 200}, 'net_cash_flow': {'value': 20000000000.0, 'unit': 'USD', 'label': 'Net Cash Flow', 'order': 1100}}\n" + ] + } + ], + "source": [ + "# Print the latest reporting period's cash flow statement\n", + "print(f\"Cash flow statement: {financial_data['financials']['cash_flow_statement']}\")" + ] } ], "metadata": { diff --git a/libs/community/langchain_community/agent_toolkits/polygon/toolkit.py b/libs/community/langchain_community/agent_toolkits/polygon/toolkit.py index 73cf95f684..a9d39b3fb6 100644 --- a/libs/community/langchain_community/agent_toolkits/polygon/toolkit.py +++ b/libs/community/langchain_community/agent_toolkits/polygon/toolkit.py @@ -2,7 +2,11 @@ from typing import List from langchain_community.agent_toolkits.base import BaseToolkit from langchain_community.tools import BaseTool -from langchain_community.tools.polygon import PolygonLastQuote, PolygonTickerNews +from langchain_community.tools.polygon import ( + PolygonFinancials, + PolygonLastQuote, + PolygonTickerNews, +) from langchain_community.utilities.polygon import PolygonAPIWrapper @@ -22,6 +26,9 @@ class PolygonToolkit(BaseToolkit): PolygonTickerNews( api_wrapper=polygon_api_wrapper, ), + PolygonFinancials( + api_wrapper=polygon_api_wrapper, + ), ] return cls(tools=tools) diff --git a/libs/community/langchain_community/tools/__init__.py b/libs/community/langchain_community/tools/__init__.py index 58af2e95ac..57f999309f 100644 --- a/libs/community/langchain_community/tools/__init__.py +++ b/libs/community/langchain_community/tools/__init__.py @@ -504,6 +504,12 @@ def _import_plugin() -> Any: return AIPluginTool +def _import_polygon_tool_PolygonFinancials() -> Any: + from langchain_community.tools.polygon.financials import PolygonFinancials + + return PolygonFinancials + + def _import_polygon_tool_PolygonLastQuote() -> Any: from langchain_community.tools.polygon.last_quote import PolygonLastQuote @@ -961,6 +967,8 @@ def __getattr__(name: str) -> Any: return _import_playwright_NavigateTool() elif name == "AIPluginTool": return _import_plugin() + elif name == "PolygonFinancials": + return _import_polygon_tool_PolygonFinancials() elif name == "PolygonLastQuote": return _import_polygon_tool_PolygonLastQuote() elif name == "PolygonTickerNews": @@ -1148,6 +1156,7 @@ __all__ = [ "OpenAPISpec", "OpenWeatherMapQueryRun", "PubmedQueryRun", + "PolygonFinancials", "PolygonLastQuote", "PolygonTickerNews", "RedditSearchRun", diff --git a/libs/community/langchain_community/tools/polygon/__init__.py b/libs/community/langchain_community/tools/polygon/__init__.py index b61740a8a2..c748968a20 100644 --- a/libs/community/langchain_community/tools/polygon/__init__.py +++ b/libs/community/langchain_community/tools/polygon/__init__.py @@ -1,9 +1,11 @@ """Polygon IO tools.""" +from langchain_community.tools.polygon.financials import PolygonFinancials from langchain_community.tools.polygon.last_quote import PolygonLastQuote from langchain_community.tools.polygon.ticker_news import PolygonTickerNews __all__ = [ + "PolygonFinancials", "PolygonLastQuote", "PolygonTickerNews", ] diff --git a/libs/community/langchain_community/tools/polygon/financials.py b/libs/community/langchain_community/tools/polygon/financials.py new file mode 100644 index 0000000000..aae19cad06 --- /dev/null +++ b/libs/community/langchain_community/tools/polygon/financials.py @@ -0,0 +1,38 @@ +from typing import Optional, Type + +from langchain_core.callbacks import CallbackManagerForToolRun +from langchain_core.pydantic_v1 import BaseModel +from langchain_core.tools import BaseTool + +from langchain_community.utilities.polygon import PolygonAPIWrapper + + +class Inputs(BaseModel): + """Inputs for Polygon's Financials API""" + + query: str + + +class PolygonFinancials(BaseTool): + """Tool that gets the financials of a ticker from Polygon""" + + mode: str = "get_financials" + name: str = "polygon_financials" + description: str = ( + "A wrapper around Polygon's Stock Financials API. " + "This tool is useful for fetching fundamental financials from " + "balance sheets, income statements, and cash flow statements " + "for a stock ticker. The input should be the ticker that you want " + "to get the latest fundamental financial data for." + ) + args_schema: Type[BaseModel] = Inputs + + api_wrapper: PolygonAPIWrapper + + def _run( + self, + query: str, + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + """Use the Polygon API tool.""" + return self.api_wrapper.run(self.mode, ticker=query) diff --git a/libs/community/langchain_community/utilities/polygon.py b/libs/community/langchain_community/utilities/polygon.py index 9c6c3e7511..a9ddb43a4b 100644 --- a/libs/community/langchain_community/utilities/polygon.py +++ b/libs/community/langchain_community/utilities/polygon.py @@ -27,6 +27,25 @@ class PolygonAPIWrapper(BaseModel): return values + def get_financials(self, ticker: str) -> Optional[dict]: + """ + Get fundamental financial data, which is found in balance sheets, + income statements, and cash flow statements for a given ticker. + """ + url = ( + f"{POLYGON_BASE_URL}vX/reference/financials?" + f"ticker={ticker}&" + f"apiKey={self.polygon_api_key}" + ) + response = requests.get(url) + data = response.json() + + status = data.get("status", None) + if status != "OK": + raise ValueError(f"API Error: {data}") + + return data.get("results", None) + def get_last_quote(self, ticker: str) -> Optional[dict]: """Get the most recent National Best Bid and Offer (Quote) for a ticker.""" url = f"{POLYGON_BASE_URL}v2/last/nbbo/{ticker}?apiKey={self.polygon_api_key}" @@ -59,7 +78,9 @@ class PolygonAPIWrapper(BaseModel): return data.get("results", None) def run(self, mode: str, ticker: str) -> str: - if mode == "get_last_quote": + if mode == "get_financials": + return json.dumps(self.get_financials(ticker)) + elif mode == "get_last_quote": return json.dumps(self.get_last_quote(ticker)) elif mode == "get_ticker_news": return json.dumps(self.get_ticker_news(ticker)) diff --git a/libs/community/tests/unit_tests/tools/test_imports.py b/libs/community/tests/unit_tests/tools/test_imports.py index 09e73983ef..0c1b4a9c6d 100644 --- a/libs/community/tests/unit_tests/tools/test_imports.py +++ b/libs/community/tests/unit_tests/tools/test_imports.py @@ -84,6 +84,7 @@ EXPECTED_ALL = [ "OpenAPISpec", "OpenWeatherMapQueryRun", "PubmedQueryRun", + "PolygonFinancials", "PolygonLastQuote", "PolygonTickerNews", "RedditSearchRun", diff --git a/libs/community/tests/unit_tests/tools/test_public_api.py b/libs/community/tests/unit_tests/tools/test_public_api.py index 2758300011..870abc5975 100644 --- a/libs/community/tests/unit_tests/tools/test_public_api.py +++ b/libs/community/tests/unit_tests/tools/test_public_api.py @@ -86,6 +86,7 @@ _EXPECTED = [ "OpenAPISpec", "OpenWeatherMapQueryRun", "PubmedQueryRun", + "PolygonFinancials", "PolygonLastQuote", "PolygonTickerNews", "RedditSearchRun",