Stock Analysis Example
Stock Analysis Example
└── ./
└── src
└── stock_analysis
├── config
│ ├── agents.yaml
│ └── tasks.yaml
├── tools
│ ├── __init__.py
│ ├── calculator_tool.py
│ └── sec_tools.py
├── __init__.py
├── crew.py
└── main.py
---
File: /src/stock_analysis/config/agents.yaml
---
financial_analyst:
role: >
The Best Financial Analyst
goal: >
Impress all customers with your financial data and market trends analysis
backstory: >
The most seasoned financial analyst with lots of expertise in stock market
analysis and investment
strategies that is working for a super important customer.
research_analyst:
role: >
Staff Research Analyst
goal: >
Being the best at gathering, interpreting data and amazing
your customer with it
backstory: >
Known as the BEST research analyst, you're skilled in sifting through news,
company announcements,
and market sentiments. Now you're working on a super important customer.
investment_advisor:
role: >
Private Investment Advisor
goal: >
Impress your customers with full analyses over stocks
and complete investment recommendations
backstory: >
You're the most experienced investment advisor
and you combine various analytical insights to formulate
strategic investment advice. You are now working for
a super important customer you need to impress.
---
File: /src/stock_analysis/config/tasks.yaml
---
financial_analysis:
description: >
Conduct a thorough analysis of {company_stock}'s stock financial health and
market performance. This includes examining key financial metrics such as
P/E ratio, EPS growth, revenue trends, and debt-to-equity ratio. Also, analyze
the stock's performance in comparison
to its industry peers and overall market trends.
expected_output: >
The final report must expand on the summary provided but now
including a clear assessment of the stock's financial standing, its strengths
and weaknesses,
and how it fares against its competitors in the current market scenario.
Make sure to use the most recent data possible.
research:
description: >
Collect and summarize recent news articles, press
releases, and market analyses related to the {company_stock} stock and its
industry.
Pay special attention to any significant events, market sentiments, and
analysts' opinions.
Also include upcoming events like earnings and others.
expected_output: >
A report that includes a comprehensive summary of the latest news,
any notable shifts in market sentiment, and potential impacts on the stock.
Also make sure to return the stock ticker as {company_stock}.
Make sure to use the most recent data as possible.
filings_analysis:
description: >
Analyze the latest 10-Q and 10-K filings from EDGAR for the stock
{company_stock} in question.
Focus on key sections like Management's Discussion and analysis, financial
statements, insider trading activity,
and any disclosed risks. Extract relevant data and insights that could
influence
the stock's future performance.
expected_output: >
Final answer must be an expanded report that now also highlights significant
findings
from these filings including any red flags or positive indicators for your
customer.
recommend:
description: >
Review and synthesize the analyses provided by the
Financial Analyst and the Research Analyst.
Combine these insights to form a comprehensive
investment recommendation. You MUST Consider all aspects, including financial
health, market sentiment, and qualitative data from
EDGAR filings.
---
File: /src/stock_analysis/tools/__init__.py
---
---
File: /src/stock_analysis/tools/calculator_tool.py
---
class CalculatorTool(BaseTool):
name: str = "Calculator tool"
description: str = (
"Useful to perform any mathematical calculations, like sum, minus,
multiplication, division, etc. The input to this tool should be a mathematical
expression, a couple examples are `200*7` or `5000/2*10."
)
---
File: /src/stock_analysis/tools/sec_tools.py
---
import os
from typing import Any, Optional, Type
from pydantic.v1 import BaseModel, Field
from crewai_tools import RagTool
from sec_api import QueryApi # Make sure to have sec_api installed
from embedchain.models.data_type import DataType
import requests
import html2text
import re
class FixedSEC10KToolSchema(BaseModel):
"""Input for SEC10KTool."""
search_query: str = Field(
...,
description="Mandatory query you would like to search from the 10-K
report",
)
class SEC10KToolSchema(FixedSEC10KToolSchema):
"""Input for SEC10KTool."""
stock_name: str = Field(
..., description="Mandatory valid stock name you would like to search"
)
class SEC10KTool(RagTool):
name: str = "Search in the specified 10-K form"
description: str = "A tool that can be used to semantic search a query from a
10-K form for a specified company."
args_schema: Type[BaseModel] = SEC10KToolSchema
url = filings[0]['linkToFilingDetails']
headers = {
"User-Agent": "crewai.com bisan@crewai.com",
"Accept-Encoding": "gzip, deflate",
"Host": "www.sec.gov"
}
response = requests.get(url, headers=headers)
response.raise_for_status()
h = html2text.HTML2Text()
h.ignore_links = False
text = h.handle(response.content.decode("utf-8"))
text = re.sub(r"[^a-zA-Z$0-9\s\n]", "", text)
return text
except requests.exceptions.HTTPError as e:
print(f"HTTP error occurred: {e}")
return None
except Exception as e:
print(f"Error fetching 10-K URL: {e}")
return None
class FixedSEC10QToolSchema(BaseModel):
"""Input for SEC10QTool."""
search_query: str = Field(
...,
description="Mandatory query you would like to search from the 10-Q
report",
)
class SEC10QToolSchema(FixedSEC10QToolSchema):
"""Input for SEC10QTool."""
stock_name: str = Field(
..., description="Mandatory valid stock name you would like to search"
)
class SEC10QTool(RagTool):
name: str = "Search in the specified 10-Q form"
description: str = "A tool that can be used to semantic search a query from a
10-Q form for a specified company."
args_schema: Type[BaseModel] = SEC10QToolSchema
url = filings[0]['linkToFilingDetails']
headers = {
"User-Agent": "crewai.com bisan@crewai.com",
"Accept-Encoding": "gzip, deflate",
"Host": "www.sec.gov"
}
response = requests.get(url, headers=headers)
response.raise_for_status() # Raise an exception for HTTP errors
h = html2text.HTML2Text()
h.ignore_links = False
text = h.handle(response.content.decode("utf-8"))
---
File: /src/stock_analysis/__init__.py
---
---
File: /src/stock_analysis/crew.py
---
@CrewBase
class StockAnalysisCrew:
agents_config = 'config/agents.yaml'
tasks_config = 'config/tasks.yaml'
@agent
def financial_agent(self) -> Agent:
return Agent(
config=self.agents_config['financial_analyst'],
verbose=True,
tools=[
ScrapeWebsiteTool(),
WebsiteSearchTool(),
CalculatorTool(),
SEC10QTool("AMZN"),
SEC10KTool("AMZN"),
]
)
@task
def financial_analysis(self) -> Task:
return Task(
config=self.tasks_config['financial_analysis'],
agent=self.financial_agent(),
)
@agent
def research_analyst_agent(self) -> Agent:
return Agent(
config=self.agents_config['research_analyst'],
verbose=True,
tools=[
ScrapeWebsiteTool(),
# WebsiteSearchTool(),
SEC10QTool("AMZN"),
SEC10KTool("AMZN"),
]
)
@task
def research(self) -> Task:
return Task(
config=self.tasks_config['research'],
agent=self.research_analyst_agent(),
)
@agent
def financial_analyst_agent(self) -> Agent:
return Agent(
config=self.agents_config['financial_analyst'],
verbose=True,
tools=[
ScrapeWebsiteTool(),
WebsiteSearchTool(),
CalculatorTool(),
SEC10QTool(),
SEC10KTool(),
]
)
@task
def financial_analysis(self) -> Task:
return Task(
config=self.tasks_config['financial_analysis'],
agent=self.financial_analyst_agent(),
)
@task
def filings_analysis(self) -> Task:
return Task(
config=self.tasks_config['filings_analysis'],
agent=self.financial_analyst_agent(),
)
@agent
def investment_advisor_agent(self) -> Agent:
return Agent(
config=self.agents_config['investment_advisor'],
verbose=True,
tools=[
ScrapeWebsiteTool(),
WebsiteSearchTool(),
CalculatorTool(),
]
)
@task
def recommend(self) -> Task:
return Task(
config=self.tasks_config['recommend'],
agent=self.investment_advisor_agent(),
)
@crew
def crew(self) -> Crew:
"""Creates the Stock Analysis"""
return Crew(
agents=self.agents,
tasks=self.tasks,
process=Process.sequential,
verbose=2,
)
---
File: /src/stock_analysis/main.py
---
import sys
from stock_analysis.crew import StockAnalysisCrew
def run():
inputs = {
'query': 'What is the best running shoe for beginner',
'company_stock': 'AMZN',
}
StockAnalysisCrew().crew().kickoff(inputs=inputs)
def train():
"""
Train the crew for a given number of iterations.
"""
inputs = {
'query': 'What is last years revenue',
'company_stock': 'AMZN',
}
try:
StockAnalysisCrew().crew().train(n_iterations=int(sys.argv[1]),
inputs=inputs)
except Exception as e:
raise Exception(f"An error occurred while training the crew: {e}")