mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-05-07 06:23:26 +08:00
* langchain agent using openbb functions A simple notebook that shows how to leverage openbb functions by building an agent via langchain * added prompt for strong buy in utilities * added prompt for strong buy in utilities * Simplified notebook --------- Co-authored-by: Danglewood <85772166+deeleeramone@users.noreply.github.com> Co-authored-by: Theodore Aptekarev <aptekarev@gmail.com>
384 lines
14 KiB
Plaintext
Vendored
384 lines
14 KiB
Plaintext
Vendored
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "0PSrErguxVcn"
|
|
},
|
|
"source": [
|
|
"### Brief Description\n",
|
|
"\n",
|
|
"This notebook shows few examples on how to leverage OpenBB functionality via an Agent built with Langchain.\n",
|
|
"It requires the user to have\n",
|
|
"- an OpenAI Key. This is required as OpenAI is used as LLM\n",
|
|
"\n",
|
|
"\n",
|
|
"For help on how to configure Colab Secrets, please refer to this article\n",
|
|
"https://margaretmz.medium.com/use-colab-secrets-to-store-kaggle-api-key-b57c7464f9fa\n",
|
|
"\n",
|
|
"This work was inspired by examples from this repo https://github.com/AlgoTrading101/Magentic-AlgoTrading101\n",
|
|
"\n",
|
|
"Functionality shown in this notebook is purely an example of what can be done.\n",
|
|
"\n",
|
|
"### Author\n",
|
|
"Marco Mistroni"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### Installing dependencies"
|
|
],
|
|
"metadata": {
|
|
"id": "pw_DrWCXVijQ"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"!pip install openbb\n",
|
|
"!pip install openbb-yfinance\n",
|
|
"!pip install openbb-finviz\n",
|
|
"!pip install langchain\n",
|
|
"!pip install langchain_core\n",
|
|
"!pip install langchain_openai\n"
|
|
],
|
|
"metadata": {
|
|
"id": "sNhm_dyvVlI1"
|
|
},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"source": [
|
|
"### Getting keys"
|
|
],
|
|
"metadata": {
|
|
"id": "Ua8Hmj2lWI6R"
|
|
}
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"from google.colab import userdata\n",
|
|
"OPENAI_KEY = userdata.get('OPENAI_KEY')"
|
|
],
|
|
"metadata": {
|
|
"id": "fTUdeQpdWL81"
|
|
},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "TEBnI33fxVcr"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os\n",
|
|
"from openbb import obb\n",
|
|
"from langchain_openai import ChatOpenAI\n",
|
|
"import logging\n",
|
|
"from langchain.agents import tool\n",
|
|
"from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder\n",
|
|
"\n",
|
|
"llm = ChatOpenAI(model=\"gpt-4.1\", temperature=0, openai_api_key=OPENAI_KEY)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "6zNCxSmOxVct"
|
|
},
|
|
"source": [
|
|
"### OpenBB Useful functions"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "28N-T7aIxVcu"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"@tool\n",
|
|
"def get_industry_performance() -> list:\n",
|
|
" \"\"\" Return performance by industry for last week, last month, last quarter, last half year and last year\"\"\"\n",
|
|
" return obb.equity.compare.groups(group='industry', metric='performance').to_llm()\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_strong_buy_for_sector(sector : str) -> list :\n",
|
|
" \"\"\" Return the strong buy recommendation for a given sector\"\"\"\n",
|
|
" new_sector = '_'.join(sector.lower().split()).lower()\n",
|
|
" data = obb.equity.screener(provider='finviz', sector=new_sector, recommendation='buy')\n",
|
|
" return data.to_llm()\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_strong_buy_for_industry(industry : str) -> list :\n",
|
|
" \"\"\" Return the strong buy recommendation for a given industry\"\"\"\n",
|
|
" data = obb.equity.screener(provider='finviz', industry=industry, recommendation='buy')\n",
|
|
" return data.to_llm()\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_best_stock_performers_for_sector(sector:str) -> list :\n",
|
|
" \"\"\" Return the best 5 stock performers for last week and last month for a given sector\"\"\"\n",
|
|
" data = obb.equity.screener(provider='finviz', filters_dict={'Sector' : sector, 'Performance' : 'Week Up', 'Performance 2' : 'Month Up'}, limit=5)\n",
|
|
" return data.to_llm()\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_best_stock_performers_for_industry(industry:str) -> list :\n",
|
|
" \"\"\" Return the best 5 stock performers for last week and last month for an industry\"\"\"\n",
|
|
" data = obb.equity.screener(provider='finviz', filters_dict={'Industry' : industry, 'Performance' : 'Week Up', 'Performance 2' : 'Month Up'}, limit=3)\n",
|
|
" return data.to_llm()\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_candidate_stocks_to_invest_relaxed(industry:str) -> list:\n",
|
|
" ''' Use relaxed criteria to find best companies in an industry which are worth investing into'''\n",
|
|
" desc_filters = {\n",
|
|
" 'Market Cap.': '+Small (over $300mln)',\n",
|
|
" 'Average Volume': 'Over 200K',\n",
|
|
" }\n",
|
|
" fund_filters = {\n",
|
|
" 'InstitutionalOwnership': 'Under 60%',\n",
|
|
" 'Current Ratio' : 'Over 1.5',\n",
|
|
" 'Debt/Equity' : 'Over 0.3',\n",
|
|
" #'EPS growthnext 5 years' : 'Positive (>0%)',\n",
|
|
" }\n",
|
|
"\n",
|
|
" desc_filters.update(fund_filters)\n",
|
|
"\n",
|
|
" try:\n",
|
|
" data = obb.equity.screener(provider='finviz', industry='semiconductors',\n",
|
|
" filters_dict=desc_filters\n",
|
|
" )\n",
|
|
" return data.to_llm()\n",
|
|
" except Exception as e:\n",
|
|
" logging.info(f'No data found:{str(e)}')\n",
|
|
" return []\n",
|
|
"\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_valuation_for_industries(input:str) -> list:\n",
|
|
" \"\"\" Return valuation metrics for the industry provided as input\"\"\"\n",
|
|
" data = obb.equity.compare.groups(group='industry', metric='valuation', provider='finviz').to_df()\n",
|
|
" filtered = data[data.name == input]\n",
|
|
" return filtered.to_json(\n",
|
|
" orient=\"records\",\n",
|
|
" date_format=\"iso\",\n",
|
|
" date_unit=\"s\",\n",
|
|
" )\n",
|
|
"\n",
|
|
"@tool\n",
|
|
"def get_consensus(ticker:str) -> list:\n",
|
|
" \"\"\" Return analyst consensus for the ticker provided\n",
|
|
" It returns the following fields:\n",
|
|
" - target_high: float, High target of the price target consensus.\n",
|
|
" - target_low: float Low target of the price target consensus.\n",
|
|
" - target_consensus: float Consensus target of the price target consensus.\n",
|
|
" - target_median: float Median target of the price target consensus\n",
|
|
"\n",
|
|
"\n",
|
|
" \"\"\"\n",
|
|
" data = obb.equity.estimates.consensus(symbol=ticker, limit=3, provider='yfinance').to_df()\n",
|
|
" return data.to_json(\n",
|
|
" orient=\"records\",\n",
|
|
" date_format=\"iso\",\n",
|
|
" date_unit=\"s\",\n",
|
|
" )\n",
|
|
"\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "1hXQnSGFxVcv"
|
|
},
|
|
"source": [
|
|
"### Chat Memory"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "YBF6S6DxxVcv"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"from langchain_core.prompts import MessagesPlaceholder\n",
|
|
"from langchain.memory import ConversationTokenBufferMemory\n",
|
|
"from langchain.agents.format_scratchpad.openai_tools import (\n",
|
|
" format_to_openai_tool_messages,\n",
|
|
")\n",
|
|
"from langchain.agents.output_parsers.openai_tools import OpenAIToolsAgentOutputParser\n",
|
|
"from langchain_core.output_parsers import StrOutputParser, CommaSeparatedListOutputParser\n",
|
|
"from langchain.agents import AgentExecutor\n",
|
|
"from langchain_core.messages import AIMessage, HumanMessage\n",
|
|
"\n",
|
|
"MEMORY_KEY = \"chat_history\"\n",
|
|
"prompt = ChatPromptTemplate.from_messages(\n",
|
|
" [\n",
|
|
" (\n",
|
|
" \"system\",\n",
|
|
" \"\"\" You are very powerful stock financial researcher.\n",
|
|
" You will take the user questions and answer using the tools available.\n",
|
|
" Once you have the information you need, you will answer user's questions using the data returned.\n",
|
|
" Use the following tools to answer user queries:\n",
|
|
" - get_strong_buy_for_sector to find strong buy recommendations for a sector\n",
|
|
" - get_strong_buy_for_industry to find strong buy recommendations for an industry\n",
|
|
" - get_industry_performance to find the performance for an industry\n",
|
|
" - get_valuation_for_industries to find valuation metrics for industries\n",
|
|
" - get_candidate_stocks_to_invest_relaxed to fetch all companies using relaxed criteria\n",
|
|
" - def get_consensus(ticker:str) - to find analyst consensus for a company\n",
|
|
" You should call each function only once, and you should not call the function if you already have the information you need.\n",
|
|
" \"\"\",\n",
|
|
" ),\n",
|
|
" MessagesPlaceholder(variable_name=MEMORY_KEY),\n",
|
|
" (\"user\", \"{input}\"),\n",
|
|
" MessagesPlaceholder(variable_name=\"agent_scratchpad\"),\n",
|
|
" ]\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "1yrlv9jUxVcw"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"tools = [get_industry_performance, get_strong_buy_for_sector, get_strong_buy_for_industry, get_best_stock_performers_for_industry, get_valuation_for_industries,\n",
|
|
" get_candidate_stocks_to_invest_relaxed, get_consensus]\n",
|
|
"llm_with_tools = llm.bind_tools(tools)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "ToVLUWZfxVcw"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"chat_history = []\n",
|
|
"chat_history.append(HumanMessage(content=\"Your question here\"))\n",
|
|
"chat_history.append(AIMessage(content=\"AI response here\"))\n",
|
|
"memory = ConversationTokenBufferMemory(\n",
|
|
" llm=llm, # Required for token counting\n",
|
|
" max_token_limit=16000, # Leave buffer for functions + responses\n",
|
|
" memory_key=\"chat_history\", # Must match your prompt's key\n",
|
|
" return_messages=True\n",
|
|
")\n",
|
|
"\n",
|
|
"agent = (\n",
|
|
" {\n",
|
|
" \"input\": lambda x: x[\"input\"],\n",
|
|
" \"agent_scratchpad\": lambda x: format_to_openai_tool_messages(\n",
|
|
" x[\"intermediate_steps\"]\n",
|
|
" ),\n",
|
|
" \"chat_history\": lambda x: memory.load_memory_variables(x)[\"chat_history\"],\n",
|
|
" }\n",
|
|
" | prompt\n",
|
|
" | llm_with_tools\n",
|
|
" | OpenAIToolsAgentOutputParser()\n",
|
|
")\n",
|
|
"agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "kbFXeyMUxVcy"
|
|
},
|
|
"source": [
|
|
"### Let's try a chain of thought approach. We start with the industry with best performance.\n",
|
|
"Then find the best performing company and check some metrics"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"metadata": {
|
|
"id": "MlAvYHU0xVcy"
|
|
},
|
|
"outputs": [],
|
|
"source": [
|
|
"input1 = '''\n",
|
|
"First, find an industry that has consistently shown positive performance across quarterly, monthly, and weekly timeframes.\n",
|
|
"Second, once you have identified the industry, extract its relevant valuation metrics (e.g., P/E, P/B, EV/EBITDA).\n",
|
|
"Third, extract companies from the selected industry using relaxed criteria.\n",
|
|
"Fourth, for the best performing companies get the analyst consensus\n",
|
|
"Finally, summarize your findings in no more than 80 words detailing:\n",
|
|
"- Best performing industry\n",
|
|
"- Best performing companies in industry\n",
|
|
"- A table displaying the analyst consensus for each of the companies you found at previous step'''\n",
|
|
"result = agent_executor.invoke({\"input\": input1, \"chat_history\": chat_history})\n",
|
|
"print(result['output'])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {
|
|
"id": "au-Qbu9KxVcy"
|
|
},
|
|
"source": [
|
|
"### Finding strong buys in the Utilities sector "
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [
|
|
"input1 = '''\n",
|
|
"First, find the stocks recommended fro strong buy in the Utilities Sector\n",
|
|
"Second, find the valuation metrics for this stock.\n",
|
|
"Third, summarize your findings in a short paragraph.\n",
|
|
"'''\n",
|
|
"result = agent_executor.invoke({\"input\": input1, \"chat_history\": chat_history})\n",
|
|
"print(result['output'])"
|
|
],
|
|
"metadata": {
|
|
"id": "doUw61HPU6fR"
|
|
},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"source": [],
|
|
"metadata": {
|
|
"id": "rc7X4Ep4VNbS"
|
|
},
|
|
"execution_count": null,
|
|
"outputs": []
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "myenv",
|
|
"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.12.1"
|
|
},
|
|
"colab": {
|
|
"provenance": []
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 0
|
|
} |