From 264ab96980e643f52e628294966c4d9df35c0f2e Mon Sep 17 00:00:00 2001 From: Virat Singh Date: Tue, 6 Aug 2024 14:28:12 -0400 Subject: [PATCH] community: Add stock market tools from financialdatasets.ai (#25025) **Description:** In this PR, I am adding three stock market tools from financialdatasets.ai (my API!): - get balance sheets - get cash flow statements - get income statements Twitter handle: [@virattt](https://twitter.com/virattt) --------- Co-authored-by: Erick Friis --- .../toolkits/financial_datasets.ipynb | 313 ++++++++++++++++++ .../financial_datasets/__init__.py | 1 + .../financial_datasets/toolkit.py | 45 +++ .../langchain_community/tools/__init__.py | 15 + .../tools/financial_datasets/__init__.py | 17 + .../financial_datasets/balance_sheets.py | 62 ++++ .../cash_flow_statements.py | 62 ++++ .../financial_datasets/income_statements.py | 62 ++++ .../utilities/financial_datasets.py | 135 ++++++++ .../tests/unit_tests/tools/test_imports.py | 3 + 10 files changed, 715 insertions(+) create mode 100644 docs/docs/integrations/toolkits/financial_datasets.ipynb create mode 100644 libs/community/langchain_community/agent_toolkits/financial_datasets/__init__.py create mode 100644 libs/community/langchain_community/agent_toolkits/financial_datasets/toolkit.py create mode 100644 libs/community/langchain_community/tools/financial_datasets/__init__.py create mode 100644 libs/community/langchain_community/tools/financial_datasets/balance_sheets.py create mode 100644 libs/community/langchain_community/tools/financial_datasets/cash_flow_statements.py create mode 100644 libs/community/langchain_community/tools/financial_datasets/income_statements.py create mode 100644 libs/community/langchain_community/utilities/financial_datasets.py diff --git a/docs/docs/integrations/toolkits/financial_datasets.ipynb b/docs/docs/integrations/toolkits/financial_datasets.ipynb new file mode 100644 index 0000000000..db060b4480 --- /dev/null +++ b/docs/docs/integrations/toolkits/financial_datasets.ipynb @@ -0,0 +1,313 @@ +{ + "cells": [ + { + "cell_type": "raw", + "id": "afaf8039", + "metadata": {}, + "source": [ + "---\n", + "sidebar_label: financial datasets\n", + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# FinancialDatasetsToolkit\n", + "\n", + "The [financial datasets](https://financialdatasets.ai/) stock market API provides REST endpoints that let you get financial data for 16,000+ tickers spanning 30+ years.\n", + "\n", + "## Setup\n", + "\n", + "To use this toolkit, you need two API keys:\n", + "\n", + "`FINANCIAL_DATASETS_API_KEY`: Get it from [financialdatasets.ai](https://financialdatasets.ai/).\n", + "`OPENAI_API_KEY`: Get it from [OpenAI](https://platform.openai.com/)." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "import getpass\n", + "import os\n", + "\n", + "os.environ[\"FINANCIAL_DATASETS_API_KEY\"] = getpass.getpass()" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "os.environ[\"OPENAI_API_KEY\"] = getpass.getpass()" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "### Installation\n", + "\n", + "This toolkit lives in the `langchain-community` package." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "id": "652d6238-1f87-422a-b135-f5abbb8652fc", + "metadata": {}, + "outputs": [], + "source": [ + "%pip install -qU langchain-community" + ] + }, + { + "cell_type": "markdown", + "id": "a38cde65-254d-4219-a441-068766c0d4b5", + "metadata": {}, + "source": [ + "## Instantiation\n", + "\n", + "Now we can instantiate our toolkit:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "cb09c344-1836-4e0c-acf8-11d13ac1dbae", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_community.agent_toolkits.financial_datasets.toolkit import (\n", + " FinancialDatasetsToolkit,\n", + ")\n", + "from langchain_community.utilities.financial_datasets import FinancialDatasetsAPIWrapper\n", + "\n", + "api_wrapper = FinancialDatasetsAPIWrapper(\n", + " financial_datasets_api_key=os.environ[\"FINANCIAL_DATASETS_API_KEY\"]\n", + ")\n", + "toolkit = FinancialDatasetsToolkit(api_wrapper=api_wrapper)" + ] + }, + { + "cell_type": "markdown", + "id": "5c5f2839-4020-424e-9fc9-07777eede442", + "metadata": {}, + "source": [ + "## Tools\n", + "\n", + "View available tools:" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "51a60dbe-9f2e-4e04-bb62-23968f17164a", + "metadata": {}, + "outputs": [], + "source": [ + "tools = toolkit.get_tools()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Use within an agent\n", + "\n", + "Let's equip our agent with the FinancialDatasetsToolkit and ask financial questions." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "system_prompt = \"\"\"\n", + "You are an advanced financial analysis AI assistant equipped with specialized tools\n", + "to access and analyze financial data. Your primary function is to help users with\n", + "financial analysis by retrieving and interpreting income statements, balance sheets,\n", + "and cash flow statements for publicly traded companies.\n", + "\n", + "You have access to the following tools from the FinancialDatasetsToolkit:\n", + "\n", + "1. Balance Sheets: Retrieves balance sheet data for a given ticker symbol.\n", + "2. Income Statements: Fetches income statement data for a specified company.\n", + "3. Cash Flow Statements: Accesses cash flow statement information for a particular ticker.\n", + "\n", + "Your capabilities include:\n", + "\n", + "1. Retrieving financial statements for any publicly traded company using its ticker symbol.\n", + "2. Analyzing financial ratios and metrics based on the data from these statements.\n", + "3. Comparing financial performance across different time periods (e.g., year-over-year or quarter-over-quarter).\n", + "4. Identifying trends in a company's financial health and performance.\n", + "5. Providing insights on a company's liquidity, solvency, profitability, and efficiency.\n", + "6. Explaining complex financial concepts in simple terms.\n", + "\n", + "When responding to queries:\n", + "\n", + "1. Always specify which financial statement(s) you're using for your analysis.\n", + "2. Provide context for the numbers you're referencing (e.g., fiscal year, quarter).\n", + "3. Explain your reasoning and calculations clearly.\n", + "4. If you need more information to provide a complete answer, ask for clarification.\n", + "5. When appropriate, suggest additional analyses that might be helpful.\n", + "\n", + "Remember, your goal is to provide accurate, insightful financial analysis to\n", + "help users make informed decisions. Always maintain a professional and objective tone in your responses.\n", + "\"\"\"" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Instantiate the LLM." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "id": "310bf18e-6c9a-4072-b86e-47bc1fcca29d", + "metadata": {}, + "outputs": [], + "source": [ + "from langchain_core.tools import tool\n", + "from langchain_openai import ChatOpenAI\n", + "\n", + "model = ChatOpenAI(model=\"gpt-4o\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Define a user query." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "id": "23e11cc9-abd6-4855-a7eb-799f45ca01ae", + "metadata": {}, + "outputs": [], + "source": [ + "query = \"What was AAPL's revenue in 2023? What about it's total debt in Q1 2024?\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Create the agent." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "from langchain.agents import AgentExecutor, create_tool_calling_agent\n", + "from langchain_core.prompts import ChatPromptTemplate\n", + "\n", + "prompt = ChatPromptTemplate.from_messages(\n", + " [\n", + " (\"system\", system_prompt),\n", + " (\"human\", \"{input}\"),\n", + " # Placeholders fill up a **list** of messages\n", + " (\"placeholder\", \"{agent_scratchpad}\"),\n", + " ]\n", + ")\n", + "\n", + "\n", + "agent = create_tool_calling_agent(model, tools, prompt)\n", + "agent_executor = AgentExecutor(agent=agent, tools=tools)" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "Query the agent." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "code", + "execution_count": null, + "outputs": [], + "source": [ + "agent_executor.invoke({\"input\": query})" + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [ + "## API reference\n", + "\n", + "For detailed documentation of all `FinancialDatasetsToolkit` features and configurations head to the [API reference](https://api.python.langchain.com/en/latest/agent_toolkits/langchain_community.agent_toolkits.financial_datasets.toolkit.FinancialDatasetsToolkit.html)." + ], + "metadata": { + "collapsed": false + } + }, + { + "cell_type": "markdown", + "source": [], + "metadata": { + "collapsed": false + } + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3 (ipykernel)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/libs/community/langchain_community/agent_toolkits/financial_datasets/__init__.py b/libs/community/langchain_community/agent_toolkits/financial_datasets/__init__.py new file mode 100644 index 0000000000..7121e6ee32 --- /dev/null +++ b/libs/community/langchain_community/agent_toolkits/financial_datasets/__init__.py @@ -0,0 +1 @@ +"""financial datasets toolkit.""" diff --git a/libs/community/langchain_community/agent_toolkits/financial_datasets/toolkit.py b/libs/community/langchain_community/agent_toolkits/financial_datasets/toolkit.py new file mode 100644 index 0000000000..4412823b14 --- /dev/null +++ b/libs/community/langchain_community/agent_toolkits/financial_datasets/toolkit.py @@ -0,0 +1,45 @@ +from __future__ import annotations + +from typing import List + +from langchain_core.pydantic_v1 import Field +from langchain_core.tools import BaseToolkit + +from langchain_community.tools import BaseTool +from langchain_community.tools.financial_datasets.balance_sheets import BalanceSheets +from langchain_community.tools.financial_datasets.cash_flow_statements import ( + CashFlowStatements, +) +from langchain_community.tools.financial_datasets.income_statements import ( + IncomeStatements, +) +from langchain_community.utilities.financial_datasets import FinancialDatasetsAPIWrapper + + +class FinancialDatasetsToolkit(BaseToolkit): + """Toolkit for interacting with financialdatasets.ai. + + Parameters: + api_wrapper: The FinancialDatasets API Wrapper. + """ + + api_wrapper: FinancialDatasetsAPIWrapper = Field( + default_factory=FinancialDatasetsAPIWrapper + ) + + def __init__(self, api_wrapper: FinancialDatasetsAPIWrapper): + super().__init__() + self.api_wrapper = api_wrapper + + class Config: + """Pydantic config.""" + + arbitrary_types_allowed = True + + def get_tools(self) -> List[BaseTool]: + """Get the tools in the toolkit.""" + return [ + BalanceSheets(api_wrapper=self.api_wrapper), + CashFlowStatements(api_wrapper=self.api_wrapper), + IncomeStatements(api_wrapper=self.api_wrapper), + ] diff --git a/libs/community/langchain_community/tools/__init__.py b/libs/community/langchain_community/tools/__init__.py index c3754c94ed..7cc65da7d7 100644 --- a/libs/community/langchain_community/tools/__init__.py +++ b/libs/community/langchain_community/tools/__init__.py @@ -120,6 +120,15 @@ if TYPE_CHECKING: ReadFileTool, WriteFileTool, ) + from langchain_community.tools.financial_datasets.balance_sheets import ( + BalanceSheets, + ) + from langchain_community.tools.financial_datasets.cash_flow_statements import ( + CashFlowStatements, + ) + from langchain_community.tools.financial_datasets.income_statements import ( + IncomeStatements, + ) from langchain_community.tools.gmail import ( GmailCreateDraft, GmailGetMessage, @@ -348,6 +357,7 @@ __all__ = [ "AzureCogsSpeech2TextTool", "AzureCogsText2SpeechTool", "AzureCogsTextAnalyticsHealthTool", + "BalanceSheets", "BaseGraphQLTool", "BaseRequestsTool", "BaseSQLDatabaseTool", @@ -357,6 +367,7 @@ __all__ = [ "BingSearchResults", "BingSearchRun", "BraveSearch", + "CashFlowStatements", "ClickTool", "CogniswitchKnowledgeRequest", "CogniswitchKnowledgeSourceFile", @@ -396,6 +407,7 @@ __all__ = [ "GoogleSerperRun", "HumanInputRun", "IFTTTWebhook", + "IncomeStatements", "InfoPowerBITool", "InfoSQLDatabaseTool", "InfoSparkSQLTool", @@ -498,6 +510,7 @@ _module_lookup = { "AzureCogsSpeech2TextTool": "langchain_community.tools.azure_cognitive_services", "AzureCogsText2SpeechTool": "langchain_community.tools.azure_cognitive_services", "AzureCogsTextAnalyticsHealthTool": "langchain_community.tools.azure_cognitive_services", # noqa: E501 + "BalanceSheets": "langchain_community.tools.financial_datasets.balance_sheets", "BaseGraphQLTool": "langchain_community.tools.graphql.tool", "BaseRequestsTool": "langchain_community.tools.requests.tool", "BaseSQLDatabaseTool": "langchain_community.tools.sql_database.tool", @@ -507,6 +520,7 @@ _module_lookup = { "BingSearchResults": "langchain_community.tools.bing_search.tool", "BingSearchRun": "langchain_community.tools.bing_search.tool", "BraveSearch": "langchain_community.tools.brave_search.tool", + "CashFlowStatements": "langchain_community.tools.financial_datasets.cash_flow_statements", # noqa: E501 "ClickTool": "langchain_community.tools.playwright", "CogniswitchKnowledgeRequest": "langchain_community.tools.cogniswitch.tool", "CogniswitchKnowledgeSourceFile": "langchain_community.tools.cogniswitch.tool", @@ -547,6 +561,7 @@ _module_lookup = { "GoogleSerperRun": "langchain_community.tools.google_serper.tool", "HumanInputRun": "langchain_community.tools.human.tool", "IFTTTWebhook": "langchain_community.tools.ifttt", + "IncomeStatements": "langchain_community.tools.financial_datasets.income_statements", # noqa: E501 "InfoPowerBITool": "langchain_community.tools.powerbi.tool", "InfoSQLDatabaseTool": "langchain_community.tools.sql_database.tool", "InfoSparkSQLTool": "langchain_community.tools.spark_sql.tool", diff --git a/libs/community/langchain_community/tools/financial_datasets/__init__.py b/libs/community/langchain_community/tools/financial_datasets/__init__.py new file mode 100644 index 0000000000..c9deb30d83 --- /dev/null +++ b/libs/community/langchain_community/tools/financial_datasets/__init__.py @@ -0,0 +1,17 @@ +"""financial datasets tools.""" + +from langchain_community.tools.financial_datasets.balance_sheets import ( + BalanceSheets, +) +from langchain_community.tools.financial_datasets.cash_flow_statements import ( + CashFlowStatements, +) +from langchain_community.tools.financial_datasets.income_statements import ( + IncomeStatements, +) + +__all__ = [ + "BalanceSheets", + "CashFlowStatements", + "IncomeStatements", +] diff --git a/libs/community/langchain_community/tools/financial_datasets/balance_sheets.py b/libs/community/langchain_community/tools/financial_datasets/balance_sheets.py new file mode 100644 index 0000000000..5bbc9093dc --- /dev/null +++ b/libs/community/langchain_community/tools/financial_datasets/balance_sheets.py @@ -0,0 +1,62 @@ +from typing import Optional, Type + +from langchain_core.callbacks import CallbackManagerForToolRun +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_core.tools import BaseTool + +from langchain_community.utilities.financial_datasets import FinancialDatasetsAPIWrapper + + +class BalanceSheetsSchema(BaseModel): + """Input for BalanceSheets.""" + + ticker: str = Field( + description="The ticker symbol to fetch balance sheets for.", + ) + period: str = Field( + description="The period of the balance sheets. " + "Possible values are: " + "annual, quarterly, ttm. " + "Default is 'annual'.", + ) + limit: int = Field( + description="The number of balance sheets to return. " "Default is 10.", + ) + + +class BalanceSheets(BaseTool): + """ + Tool that gets balance sheets for a given ticker over a given period. + """ + + mode: str = "get_balance_sheets" + name: str = "balance_sheets" + description: str = ( + "A wrapper around financial datasets's Balance Sheets API. " + "This tool is useful for fetching balance sheets for a given ticker." + "The tool fetches balance sheets for a given ticker over a given period." + "The period can be annual, quarterly, or trailing twelve months (ttm)." + "The number of balance sheets to return can also be " + "specified using the limit parameter." + ) + args_schema: Type[BalanceSheetsSchema] = BalanceSheetsSchema + + api_wrapper: FinancialDatasetsAPIWrapper = Field(..., exclude=True) + + def __init__(self, api_wrapper: FinancialDatasetsAPIWrapper): + super().__init__(api_wrapper=api_wrapper) + + def _run( + self, + ticker: str, + period: str, + limit: Optional[int], + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + """Use the Balance Sheets API tool.""" + return self.api_wrapper.run( + mode=self.mode, + ticker=ticker, + period=period, + limit=limit, + ) diff --git a/libs/community/langchain_community/tools/financial_datasets/cash_flow_statements.py b/libs/community/langchain_community/tools/financial_datasets/cash_flow_statements.py new file mode 100644 index 0000000000..65f95a3e0c --- /dev/null +++ b/libs/community/langchain_community/tools/financial_datasets/cash_flow_statements.py @@ -0,0 +1,62 @@ +from typing import Optional, Type + +from langchain_core.callbacks import CallbackManagerForToolRun +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_core.tools import BaseTool + +from langchain_community.utilities.financial_datasets import FinancialDatasetsAPIWrapper + + +class CashFlowStatementsSchema(BaseModel): + """Input for CashFlowStatements.""" + + ticker: str = Field( + description="The ticker symbol to fetch cash flow statements for.", + ) + period: str = Field( + description="The period of the cash flow statement. " + "Possible values are: " + "annual, quarterly, ttm. " + "Default is 'annual'.", + ) + limit: int = Field( + description="The number of cash flow statements to return. " "Default is 10.", + ) + + +class CashFlowStatements(BaseTool): + """ + Tool that gets cash flow statements for a given ticker over a given period. + """ + + mode: str = "get_cash_flow_statements" + name: str = "cash_flow_statements" + description: str = ( + "A wrapper around financial datasets's Cash Flow Statements API. " + "This tool is useful for fetching cash flow statements for a given ticker." + "The tool fetches cash flow statements for a given ticker over a given period." + "The period can be annual, quarterly, or trailing twelve months (ttm)." + "The number of cash flow statements to return can also be " + "specified using the limit parameter." + ) + args_schema: Type[CashFlowStatementsSchema] = CashFlowStatementsSchema + + api_wrapper: FinancialDatasetsAPIWrapper = Field(..., exclude=True) + + def __init__(self, api_wrapper: FinancialDatasetsAPIWrapper): + super().__init__(api_wrapper=api_wrapper) + + def _run( + self, + ticker: str, + period: str, + limit: Optional[int], + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + """Use the Cash Flow Statements API tool.""" + return self.api_wrapper.run( + mode=self.mode, + ticker=ticker, + period=period, + limit=limit, + ) diff --git a/libs/community/langchain_community/tools/financial_datasets/income_statements.py b/libs/community/langchain_community/tools/financial_datasets/income_statements.py new file mode 100644 index 0000000000..8e4f197d52 --- /dev/null +++ b/libs/community/langchain_community/tools/financial_datasets/income_statements.py @@ -0,0 +1,62 @@ +from typing import Optional, Type + +from langchain_core.callbacks import CallbackManagerForToolRun +from langchain_core.pydantic_v1 import BaseModel, Field +from langchain_core.tools import BaseTool + +from langchain_community.utilities.financial_datasets import FinancialDatasetsAPIWrapper + + +class IncomeStatementsSchema(BaseModel): + """Input for IncomeStatements.""" + + ticker: str = Field( + description="The ticker symbol to fetch income statements for.", + ) + period: str = Field( + description="The period of the income statement. " + "Possible values are: " + "annual, quarterly, ttm. " + "Default is 'annual'.", + ) + limit: int = Field( + description="The number of income statements to return. " "Default is 10.", + ) + + +class IncomeStatements(BaseTool): + """ + Tool that gets income statements for a given ticker over a given period. + """ + + mode: str = "get_income_statements" + name: str = "income_statements" + description: str = ( + "A wrapper around financial datasets's Income Statements API. " + "This tool is useful for fetching income statements for a given ticker." + "The tool fetches income statements for a given ticker over a given period." + "The period can be annual, quarterly, or trailing twelve months (ttm)." + "The number of income statements to return can also be " + "specified using the limit parameter." + ) + args_schema: Type[IncomeStatementsSchema] = IncomeStatementsSchema + + api_wrapper: FinancialDatasetsAPIWrapper = Field(..., exclude=True) + + def __init__(self, api_wrapper: FinancialDatasetsAPIWrapper): + super().__init__(api_wrapper=api_wrapper) + + def _run( + self, + ticker: str, + period: str, + limit: Optional[int], + run_manager: Optional[CallbackManagerForToolRun] = None, + ) -> str: + """Use the Income Statements API tool.""" + return self.api_wrapper.run( + mode=self.mode, + ticker=ticker, + period=period, + limit=limit, + ) diff --git a/libs/community/langchain_community/utilities/financial_datasets.py b/libs/community/langchain_community/utilities/financial_datasets.py new file mode 100644 index 0000000000..d8e769442e --- /dev/null +++ b/libs/community/langchain_community/utilities/financial_datasets.py @@ -0,0 +1,135 @@ +""" +Util that calls several of financial datasets stock market REST APIs. +Docs: https://docs.financialdatasets.ai/ +""" + +import json +from typing import Any, List, Optional + +import requests +from langchain_core.pydantic_v1 import BaseModel +from langchain_core.utils import get_from_dict_or_env + +FINANCIAL_DATASETS_BASE_URL = "https://api.financialdatasets.ai/" + + +class FinancialDatasetsAPIWrapper(BaseModel): + """Wrapper for financial datasets API.""" + + financial_datasets_api_key: Optional[str] = None + + def __init__(self, **data: Any): + super().__init__(**data) + self.financial_datasets_api_key = get_from_dict_or_env( + data, "financial_datasets_api_key", "FINANCIAL_DATASETS_API_KEY" + ) + + def get_income_statements( + self, + ticker: str, + period: str, + limit: Optional[int], + ) -> Optional[dict]: + """ + Get the income statements for a stock `ticker` over a `period` of time. + + :param ticker: the stock ticker + :param period: the period of time to get the balance sheets for. + Possible values are: annual, quarterly, ttm. + :param limit: the number of results to return, default is 10 + :return: a list of income statements + """ + url = ( + f"{FINANCIAL_DATASETS_BASE_URL}financials/income-statements/" + f"?ticker={ticker}" + f"&period={period}" + f"&limit={limit if limit else 10}" + ) + + # Add the api key to the headers + headers = {"X-API-KEY": self.financial_datasets_api_key} + + # Execute the request + response = requests.get(url, headers=headers) + data = response.json() + + return data.get("income_statements", None) + + def get_balance_sheets( + self, + ticker: str, + period: str, + limit: Optional[int], + ) -> List[dict]: + """ + Get the balance sheets for a stock `ticker` over a `period` of time. + + :param ticker: the stock ticker + :param period: the period of time to get the balance sheets for. + Possible values are: annual, quarterly, ttm. + :param limit: the number of results to return, default is 10 + :return: a list of balance sheets + """ + url = ( + f"{FINANCIAL_DATASETS_BASE_URL}financials/balance-sheets/" + f"?ticker={ticker}" + f"&period={period}" + f"&limit={limit if limit else 10}" + ) + + # Add the api key to the headers + headers = {"X-API-KEY": self.financial_datasets_api_key} + + # Execute the request + response = requests.get(url, headers=headers) + data = response.json() + + return data.get("balance_sheets", None) + + def get_cash_flow_statements( + self, + ticker: str, + period: str, + limit: Optional[int], + ) -> List[dict]: + """ + Get the cash flow statements for a stock `ticker` over a `period` of time. + + :param ticker: the stock ticker + :param period: the period of time to get the balance sheets for. + Possible values are: annual, quarterly, ttm. + :param limit: the number of results to return, default is 10 + :return: a list of cash flow statements + """ + + url = ( + f"{FINANCIAL_DATASETS_BASE_URL}financials/cash-flow-statements/" + f"?ticker={ticker}" + f"&period={period}" + f"&limit={limit if limit else 10}" + ) + + # Add the api key to the headers + headers = {"X-API-KEY": self.financial_datasets_api_key} + + # Execute the request + response = requests.get(url, headers=headers) + data = response.json() + + return data.get("cash_flow_statements", None) + + def run(self, mode: str, ticker: str, **kwargs: Any) -> str: + if mode == "get_income_statements": + period = kwargs.get("period", "annual") + limit = kwargs.get("limit", 10) + return json.dumps(self.get_income_statements(ticker, period, limit)) + elif mode == "get_balance_sheets": + period = kwargs.get("period", "annual") + limit = kwargs.get("limit", 10) + return json.dumps(self.get_balance_sheets(ticker, period, limit)) + elif mode == "get_cash_flow_statements": + period = kwargs.get("period", "annual") + limit = kwargs.get("limit", 10) + return json.dumps(self.get_cash_flow_statements(ticker, period, limit)) + else: + raise ValueError(f"Invalid mode {mode} for financial datasets API.") diff --git a/libs/community/tests/unit_tests/tools/test_imports.py b/libs/community/tests/unit_tests/tools/test_imports.py index a67eddbea5..5b6b4ec996 100644 --- a/libs/community/tests/unit_tests/tools/test_imports.py +++ b/libs/community/tests/unit_tests/tools/test_imports.py @@ -20,6 +20,7 @@ EXPECTED_ALL = [ "AzureCogsSpeech2TextTool", "AzureCogsText2SpeechTool", "AzureCogsTextAnalyticsHealthTool", + "BalanceSheets", "BaseGraphQLTool", "BaseRequestsTool", "BaseSQLDatabaseTool", @@ -29,6 +30,7 @@ EXPECTED_ALL = [ "BingSearchResults", "BingSearchRun", "BraveSearch", + "CashFlowStatements", "ClickTool", "CogniswitchKnowledgeSourceFile", "CogniswitchKnowledgeSourceURL", @@ -68,6 +70,7 @@ EXPECTED_ALL = [ "GoogleSerperRun", "HumanInputRun", "IFTTTWebhook", + "IncomeStatements", "InfoPowerBITool", "InfoSQLDatabaseTool", "InfoSparkSQLTool",