Files
OpenBB/examples/openbb_vs_langchain.ipynb
mmistroni 3c519ee924 langchain agent using openbb functions (#7131)
* 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>
2025-06-14 16:56:49 +00:00

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
}