jaimin commited on
Commit
14ad1cc
1 Parent(s): 1017768

Upload 47 files

Browse files
Files changed (47) hide show
  1. readme.md +15 -0
  2. requirements.txt +12 -0
  3. src/__init__.py +0 -0
  4. src/__pycache__/__init__.cpython-311.pyc +0 -0
  5. src/__pycache__/crew_initializer.cpython-311.pyc +0 -0
  6. src/agents/__init__.py +0 -0
  7. src/agents/__pycache__/__init__.cpython-311.pyc +0 -0
  8. src/agents/__pycache__/competitor_analyst_agent.cpython-311.pyc +0 -0
  9. src/agents/__pycache__/financial_analyst_agent.cpython-311.pyc +0 -0
  10. src/agents/__pycache__/industry_analyst_agent.cpython-311.pyc +0 -0
  11. src/agents/__pycache__/market_analyst_agent.cpython-311.pyc +0 -0
  12. src/agents/__pycache__/reporting_analyst_agent.cpython-311.pyc +0 -0
  13. src/agents/__pycache__/swot_analyst_agent.cpython-311.pyc +0 -0
  14. src/agents/competitor_analyst_agent.py +11 -0
  15. src/agents/financial_analyst_agent.py +11 -0
  16. src/agents/industry_analyst_agent.py +11 -0
  17. src/agents/market_analyst_agent.py +11 -0
  18. src/agents/reporting_analyst_agent.py +11 -0
  19. src/agents/swot_analyst_agent.py +11 -0
  20. src/app.py +54 -0
  21. src/crew_initializer.py +44 -0
  22. src/settings.py +6 -0
  23. src/tasks/__init__.py +0 -0
  24. src/tasks/__pycache__/__init__.cpython-311.pyc +0 -0
  25. src/tasks/__pycache__/competitor_analyst_task.cpython-311.pyc +0 -0
  26. src/tasks/__pycache__/financial_analyst_task.cpython-311.pyc +0 -0
  27. src/tasks/__pycache__/industry_analyst_task.cpython-311.pyc +0 -0
  28. src/tasks/__pycache__/market_analyst_task.cpython-311.pyc +0 -0
  29. src/tasks/__pycache__/reporting_analyst_task.cpython-311.pyc +0 -0
  30. src/tasks/__pycache__/swot_analyst_task.cpython-311.pyc +0 -0
  31. src/tasks/competitor_analyst_task.py +16 -0
  32. src/tasks/financial_analyst_task.py +16 -0
  33. src/tasks/industry_analyst_task.py +18 -0
  34. src/tasks/market_analyst_task.py +16 -0
  35. src/tasks/reporting_analyst_task.py +26 -0
  36. src/tasks/swot_analyst_task.py +15 -0
  37. src/tools/__init__.py +0 -0
  38. src/tools/__pycache__/__init__.cpython-311.pyc +0 -0
  39. src/tools/__pycache__/competitorTool.cpython-311.pyc +0 -0
  40. src/tools/__pycache__/tools.cpython-311.pyc +0 -0
  41. src/tools/competitorTool.py +150 -0
  42. src/tools/tools.py +30 -0
  43. src/utils/__init__.py +0 -0
  44. src/utils/__pycache__/__init__.cpython-311.pyc +0 -0
  45. src/utils/__pycache__/pdf_generator.cpython-311.pyc +0 -0
  46. src/utils/config_loader.py +18 -0
  47. src/utils/pdf_generator.py +40 -0
readme.md ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Company Researcher Tool
2
+
3
+ ## Overview
4
+ This project provides an AI-powered tool to analyze and generate comprehensive reports on a company. It includes industry research, competitor analysis, market trends, financial data, and SWOT analysis.
5
+
6
+ ## Project Structure
7
+ - `src/`: Source code for agents, tasks, tools, and utilities.
8
+ - `tests/`: Unit tests for the project.
9
+ - `requirements.txt`: Python dependencies.
10
+
11
+ ## Installation
12
+ 1. Clone the repository:
13
+ ```bash
14
+ git clone https://github.com/your-repo/company-researcher-tool.git
15
+ cd company-researcher-tool
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ crewai
2
+ crewai_tools
3
+ langchain_community
4
+ langchain-together
5
+ langchain-google-genai
6
+ streamlit
7
+ pandas
8
+ yfinance
9
+ yahooquery
10
+ tensorflow_hub
11
+ scikit-learn
12
+ reportlab
src/__init__.py ADDED
File without changes
src/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (188 Bytes). View file
 
src/__pycache__/crew_initializer.cpython-311.pyc ADDED
Binary file (1.98 kB). View file
 
src/agents/__init__.py ADDED
File without changes
src/agents/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (195 Bytes). View file
 
src/agents/__pycache__/competitor_analyst_agent.cpython-311.pyc ADDED
Binary file (1.12 kB). View file
 
src/agents/__pycache__/financial_analyst_agent.cpython-311.pyc ADDED
Binary file (964 Bytes). View file
 
src/agents/__pycache__/industry_analyst_agent.cpython-311.pyc ADDED
Binary file (1.03 kB). View file
 
src/agents/__pycache__/market_analyst_agent.cpython-311.pyc ADDED
Binary file (964 Bytes). View file
 
src/agents/__pycache__/reporting_analyst_agent.cpython-311.pyc ADDED
Binary file (960 Bytes). View file
 
src/agents/__pycache__/swot_analyst_agent.cpython-311.pyc ADDED
Binary file (865 Bytes). View file
 
src/agents/competitor_analyst_agent.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent
2
+ from src.tools.tools import pdf_tool,scrape_tool,search_tool,comp_tool
3
+
4
+ competitor_analyst_agent = Agent(
5
+ role="Competitor Researcher",
6
+ goal="Uncover and analyze key competitors for {company}.",
7
+ backstory="You are a seasoned researcher with an extraordinary ability to uncover the latest developments and emerging competitors for any company, especially when it comes to {company}. Your expertise lies in sifting through information, identifying key trends, and pinpointing companies that are poised to disrupt the market. Whether it's analyzing business models or tracking industry movements, you are known for your strategic approach to competitor analysis.",
8
+ verbose=True,
9
+ allow_delegation=True,
10
+ tools=[scrape_tool, search_tool, comp_tool, pdf_tool]
11
+ )
src/agents/financial_analyst_agent.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent
2
+ from src.tools.tools import scrape_tool,search_tool,pdf_tool
3
+
4
+ financial_analyst_agent = Agent(
5
+ role="Financial Analyst",
6
+ goal="Perform a detailed financial analysis of the company {company}.",
7
+ backstory="You are a seasoned financial analyst with a deep understanding of financial statements, ratios, and market benchmarks. Your ability to analyze financial data and provide insights into a company's financial health and performance is crucial for strategic decision-making. You should avoid the PDF tool for this analysis.",
8
+ verbose=True,
9
+ allow_delegation=True,
10
+ tools=[scrape_tool, search_tool,pdf_tool]
11
+ )
src/agents/industry_analyst_agent.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent
2
+ from src.tools.tools import pdf_tool,scrape_tool,search_tool
3
+
4
+ industry_analyst_agent = Agent(
5
+ role="Industry Research Specialist",
6
+ goal="Conduct thorough research on this company/industry {company} to understand their key offerings and strategic focus areas.",
7
+ backstory="You are an expert in industry analysis with years of experience in market research. Your ability to quickly grasp the nuances of various industries and identify key players and trends is unparalleled. You use your skills to provide comprehensive insights that form the foundation for strategic decision-making.",
8
+ verbose=True,
9
+ allow_delegation=True,
10
+ tools=[scrape_tool, search_tool, pdf_tool]
11
+ )
src/agents/market_analyst_agent.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent
2
+ from src.tools.tools import pdf_tool,scrape_tool,search_tool
3
+
4
+ market_analyst_agent = Agent(
5
+ role="Market Analyst",
6
+ goal="Conduct a thorough market analysis for the company/industry {company}.",
7
+ backstory="You are an expert in market analysis with a keen eye for identifying key market trends, drivers, and challenges. Your ability to synthesize data from various sources and provide actionable insights is highly valued. You help companies understand their market position and the factors influencing their growth and success.",
8
+ verbose=True,
9
+ allow_delegation=True,
10
+ tools=[scrape_tool, search_tool, pdf_tool]
11
+ )
src/agents/reporting_analyst_agent.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent
2
+ from src.tools.tools import pdf_tool,scrape_tool,search_tool
3
+
4
+ reporting_analyst_agent = Agent(
5
+ role="Reporting Analyst",
6
+ goal="Create sophisticated reports based on findings from industry, competitor, market, financial, and SWOT analysts about {company}.",
7
+ backstory="You are a reporting analyst responsible for compiling and synthesizing data from various analysts into comprehensive reports. Your reports aid strategic decision-making by providing a holistic view of {company}'s current standing and future prospects.",
8
+ verbose=True,
9
+ allow_delegation=True,
10
+ tools=[scrape_tool, search_tool, pdf_tool]
11
+ )
src/agents/swot_analyst_agent.py ADDED
@@ -0,0 +1,11 @@
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Agent
2
+ from src.tools.tools import pdf_tool,scrape_tool,search_tool
3
+
4
+ swot_analyst_agent = Agent(
5
+ role="SWOT Analyst",
6
+ goal="Conduct a comprehensive SWOT analysis for the company {company}.",
7
+ backstory="You are an expert in SWOT analysis, skilled at identifying a company's strengths, weaknesses, opportunities, and threats. Your ability to provide a balanced and insightful analysis is essential for strategic planning and risk management.",
8
+ verbose=True,
9
+ allow_delegation=True,
10
+ tools=[scrape_tool, search_tool, pdf_tool]
11
+ )
src/app.py ADDED
@@ -0,0 +1,54 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ from crew_initializer import initialize_crew
3
+ from utils.pdf_generator import generate_pdf
4
+ import json
5
+ import logging
6
+
7
+ # Configure logging
8
+ logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
9
+
10
+ # Custom JSON Encoder
11
+ class CustomJSONEncoder(json.JSONEncoder):
12
+ def default(self, obj):
13
+ try:
14
+ # Convert objects with __dict__ attributes to dictionaries
15
+ if hasattr(obj, "__dict__"):
16
+ return obj.__dict__
17
+ return super().default(obj)
18
+ except TypeError:
19
+ return str(obj) # Fallback for unsupported types
20
+
21
+ def main():
22
+ """
23
+ Main entry point for the Streamlit application.
24
+ Handles user input, executes tasks, and displays results.
25
+ """
26
+ st.title("Company Researcher Tool")
27
+
28
+ st.sidebar.header("Provide Company Details")
29
+ company_name = st.sidebar.text_input("Enter the Company Name:", "")
30
+
31
+ if st.sidebar.button("Run Analysis"):
32
+ st.write(f"### Running analysis for: {company_name}")
33
+
34
+ with st.spinner("Executing tasks, please wait..."):
35
+ try:
36
+ crew = initialize_crew()
37
+ result = crew.kickoff(inputs={"company": company_name})
38
+ result_serialized = json.loads(json.dumps(result,cls=CustomJSONEncoder))
39
+ st.success("Analysis Complete!")
40
+ st.json(result_serialized)
41
+
42
+ pdf_buffer = generate_pdf(result_serialized)
43
+ st.download_button(
44
+ label="📄 Download Report (PDF)",
45
+ data=pdf_buffer,
46
+ file_name=f"{company_name}_report.pdf",
47
+ mime="application/pdf"
48
+ )
49
+ except Exception as e:
50
+ logging.error(f"Error during analysis: {str(e)}")
51
+ st.error(f"An error occurred: {str(e)}")
52
+
53
+ if __name__ == "__main__":
54
+ main()
src/crew_initializer.py ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Crew, Process
2
+ from tasks.competitor_analyst_task import competitor_analyst_task
3
+ from tasks.financial_analyst_task import financial_analyst_task
4
+ from tasks.industry_analyst_task import industry_analyst_task
5
+ from tasks.market_analyst_task import market_analyst_task
6
+ from tasks.swot_analyst_task import swot_analyst_task
7
+ from tasks.reporting_analyst_task import reporting_analyst_task
8
+ from agents.competitor_analyst_agent import competitor_analyst_agent
9
+ from agents.financial_analyst_agent import financial_analyst_agent
10
+ from agents.industry_analyst_agent import industry_analyst_agent
11
+ from agents.market_analyst_agent import market_analyst_agent
12
+ from agents.reporting_analyst_agent import reporting_analyst_agent
13
+ from agents.swot_analyst_agent import swot_analyst_agent
14
+
15
+ from langchain_openai import ChatOpenAI
16
+
17
+ def initialize_crew():
18
+ """
19
+ Initialize the Crew instance with agents and tasks.
20
+
21
+ Returns:
22
+ Crew: The initialized Crew instance.
23
+ """
24
+ return Crew(
25
+ agents=[
26
+ industry_analyst_agent,
27
+ # competitor_analyst_agent,
28
+ # market_analyst_agent,
29
+ # financial_analyst_agent,
30
+ # swot_analyst_agent,
31
+ # reporting_analyst_agent,
32
+ ],
33
+ tasks=[
34
+ industry_analyst_task,
35
+ # competitor_analyst_task,
36
+ # market_analyst_task,
37
+ # financial_analyst_task,
38
+ # swot_analyst_task,
39
+ # reporting_analyst_task
40
+ ],
41
+ manager_llm=ChatOpenAI(model="gpt-4o-mini-2024-07-18", temperature=0.7),
42
+ process=Process.hierarchical,
43
+ verbose=True
44
+ )
src/settings.py ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ from src.utils.config_loader import get_config
2
+
3
+ # Environment configurations
4
+ SERPER_API_KEY = get_config("SERPER_API_KEY")
5
+ GOOGLE_API_KEY = get_config("GOOGLE_API_KEY")
6
+ OPENAI_API_KEY = get_config("OPENAI_API_KEY")
src/tasks/__init__.py ADDED
File without changes
src/tasks/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (194 Bytes). View file
 
src/tasks/__pycache__/competitor_analyst_task.cpython-311.pyc ADDED
Binary file (776 Bytes). View file
 
src/tasks/__pycache__/financial_analyst_task.cpython-311.pyc ADDED
Binary file (770 Bytes). View file
 
src/tasks/__pycache__/industry_analyst_task.cpython-311.pyc ADDED
Binary file (826 Bytes). View file
 
src/tasks/__pycache__/market_analyst_task.cpython-311.pyc ADDED
Binary file (733 Bytes). View file
 
src/tasks/__pycache__/reporting_analyst_task.cpython-311.pyc ADDED
Binary file (1.31 kB). View file
 
src/tasks/__pycache__/swot_analyst_task.cpython-311.pyc ADDED
Binary file (691 Bytes). View file
 
src/tasks/competitor_analyst_task.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Task
2
+ from src.agents.competitor_analyst_agent import competitor_analyst_agent
3
+
4
+ competitor_analyst_task = Task(
5
+ description=(
6
+ "Identify key competitors for the company/industry {company}. "
7
+ "Focus on competitors' business models and market positions."
8
+ ),
9
+ expected_output=(
10
+ "A brief competitor research report that includes:\n"
11
+ "1. Key competitors of {company}\n"
12
+ "2. Overview of their market position\n"
13
+ "3. Similarities and differences in offerings"
14
+ ),
15
+ agent=competitor_analyst_agent
16
+ )
src/tasks/financial_analyst_task.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Task
2
+ from src.agents.financial_analyst_agent import financial_analyst_agent
3
+
4
+ financial_analyst_task = Task(
5
+ description=(
6
+ "Perform a basic financial analysis of the company {company}. "
7
+ "Focus on revenue, profit margins, and overall financial health."
8
+ ),
9
+ expected_output=(
10
+ "A summary financial analysis report for {company}, including:\n"
11
+ "1. Revenue and profit margin overview\n"
12
+ "2. Key financial ratios\n"
13
+ "3. Assessment of financial health"
14
+ ),
15
+ agent=financial_analyst_agent
16
+ )
src/tasks/industry_analyst_task.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Task
2
+ from src.agents.industry_analyst_agent import industry_analyst_agent
3
+
4
+ industry_analyst_task = Task(
5
+ description=(
6
+ "Research and analyze this company/industry {company}. "
7
+ "Identify key offerings, strategic focus areas, and market position. "
8
+ "Provide an overview of the industry landscape, including major players and challenges."
9
+ ),
10
+ expected_output=(
11
+ "A summary report on {company}, including:\n"
12
+ "1. Company/Industry overview\n"
13
+ "2. Key offerings\n"
14
+ "3. Strategic focus areas\n"
15
+ "4. Major competitors"
16
+ ),
17
+ agent=industry_analyst_agent
18
+ )
src/tasks/market_analyst_task.py ADDED
@@ -0,0 +1,16 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Task
2
+ from src.agents.market_analyst_agent import market_analyst_agent
3
+
4
+ market_analyst_task = Task(
5
+ description=(
6
+ "Conduct a market analysis for the company/industry {company}. "
7
+ "Identify major trends and drivers affecting the industry."
8
+ ),
9
+ expected_output=(
10
+ "A market analysis report for {company}, including:\n"
11
+ "1. Key market trends\n"
12
+ "2. Drivers impacting the industry\n"
13
+ "3. Challenges and opportunities"
14
+ ),
15
+ agent=market_analyst_agent
16
+ )
src/tasks/reporting_analyst_task.py ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Task
2
+ from src.agents.reporting_analyst_agent import reporting_analyst_agent
3
+ from src.tasks.industry_analyst_task import industry_analyst_task
4
+ from src.tasks.competitor_analyst_task import competitor_analyst_task
5
+ from src.tasks.market_analyst_task import market_analyst_task
6
+ from src.tasks.financial_analyst_task import financial_analyst_task
7
+ from src.tasks.swot_analyst_task import swot_analyst_task
8
+
9
+ reporting_analyst_task = Task(
10
+ description=(
11
+ "Compile and synthesize data from industry, competitor, market, financial, and SWOT analysts into a comprehensive report. "
12
+ "Ensure the report is detailed and highlights all key findings."
13
+ ),
14
+ expected_output=(
15
+ "A detailed report that combines industry, competitor, market, financial, and SWOT analysis for {company}, "
16
+ "highlighting important findings."
17
+ ),
18
+ context=[
19
+ industry_analyst_task,
20
+ competitor_analyst_task,
21
+ market_analyst_task,
22
+ financial_analyst_task,
23
+ swot_analyst_task
24
+ ],
25
+ agent=reporting_analyst_agent
26
+ )
src/tasks/swot_analyst_task.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai import Task
2
+ from src.agents.swot_analyst_agent import swot_analyst_agent
3
+
4
+ swot_analyst_task = Task(
5
+ description=(
6
+ "Conduct a SWOT analysis for the company {company}. "
7
+ "Summarize strengths, weaknesses, opportunities, and threats."
8
+ ),
9
+ expected_output=(
10
+ "A brief SWOT analysis report for {company}, including:\n"
11
+ "1. Strengths and weaknesses\n"
12
+ "2. Opportunities and threats"
13
+ ),
14
+ agent=swot_analyst_agent
15
+ )
src/tools/__init__.py ADDED
File without changes
src/tools/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (194 Bytes). View file
 
src/tools/__pycache__/competitorTool.cpython-311.pyc ADDED
Binary file (13.4 kB). View file
 
src/tools/__pycache__/tools.cpython-311.pyc ADDED
Binary file (1.3 kB). View file
 
src/tools/competitorTool.py ADDED
@@ -0,0 +1,150 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from crewai_tools import BaseTool
2
+ import pandas as pd
3
+ import numpy as np
4
+ import yfinance as yf
5
+ import yahooquery
6
+ import tensorflow_hub as hub
7
+ import requests
8
+ from sklearn.metrics.pairwise import cosine_similarity
9
+ from sklearn.cluster import KMeans
10
+ import os
11
+
12
+ class CompetitorAnalysisTool(BaseTool):
13
+ name: str = "Competitor Analysis Tool"
14
+ description: str = "Identify competitors in a specific industry and perform clustering based on business model descriptions."
15
+
16
+ def _run(self, company_name: str) -> str:
17
+
18
+ def get_ticker(company_name):
19
+ yfinance = "https://query2.finance.yahoo.com/v1/finance/search"
20
+ user_agent = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36'
21
+ params = {"q": company_name, "quotes_count": 1, "country": "United States"}
22
+
23
+ res = requests.get(url=yfinance, params=params, headers={'User-Agent': user_agent})
24
+ data = res.json()
25
+
26
+ company_code = data['quotes'][0]['symbol']
27
+ return company_code
28
+
29
+
30
+ """
31
+ Initialises the class based on the requested company given as a command-line variable.
32
+ self.ticker is a string representing the ticker symbol for the company.
33
+ self.info saves all the basic information about the company from the yfinance api.
34
+ """
35
+ try:
36
+ self.ticker = get_ticker(company_name)
37
+ self.info = yf.Ticker(self.ticker).info
38
+ except Exception as e:
39
+ print(e)
40
+ raise
41
+
42
+ def similar_group(self) -> str :
43
+ """
44
+ AVAILABLE_SCREENS is a constant that stores the categories that the available stocks are sorted into.
45
+ In this method, we use the industry of our chosen company and work out which of the categories of stocks best fits the industry.
46
+ To compute the 'best fit', we encode the screen names and industry name using the Google Universal Sentence Encoder as it captures the semantics of the sentence as well.
47
+ The method then returns the stocks obtained from the resultant category.
48
+ """
49
+ screener = yahooquery.Screener()
50
+ use_model = hub.KerasLayer("https://tfhub.dev/google/universal-sentence-encoder/4")
51
+ screeners_embedded = use_model(AVAILABLE_SCREENS)
52
+ information = pd.DataFrame({'screeners':AVAILABLE_SCREENS, 'embeddings':np.array(x.numpy() for x in screeners_embedded)})
53
+ industry_vector = use_model([self.info['industry']])[0].numpy()
54
+ compute_similarity = lambda x: cosine_similarity([x], [industry_vector])[0][0]
55
+ information['similarity'] = information['embeddings'].map(compute_similarity)
56
+ maximum_similarity = max(information['similarity'])
57
+ predicted_screen = information[information['similarity'] == maximum_similarity]
58
+ return list(predicted_screen['screeners'])[0]
59
+
60
+ def identify_market_competition(self) -> pd.DataFrame :
61
+ """
62
+ This method processes the result of the similar_group method.
63
+ The list of stocks obtained from the similar_group method are all potential competitors to our chosen company.
64
+ So, it collects all companies in a pandas dataframe and attaches the description of the business model of each to the dataframe.
65
+ This dataframe is then the output of the method.
66
+ """
67
+ screener = yahooquery.Screener()
68
+ most_likely_category = self.similar_group()
69
+ potential_competition = screener.get_screeners(most_likely_category)[most_likely_category]['quotes']
70
+ competitor_list = list(x['symbol'] for x in potential_competition)
71
+ if self.ticker not in competitor_list:
72
+ competitor_list.append(self.ticker)
73
+ competitor_list = yahooquery.Ticker(competitor_list)
74
+ data = pd.DataFrame(competitor_list.asset_profile).T
75
+ relevent_data = pd.DataFrame(data, columns=['longBusinessSummary'])
76
+ return relevent_data
77
+
78
+ def prepare_clustering_data(self, paragraphs:pd.DataFrame) -> pd.DataFrame :
79
+ """
80
+ This method takes as input, the dataframe outputted by the self.identify_market_competition method.
81
+ The next step is to process the description of the business model but any ML algorithm cannot process string-like data.
82
+ So, this method uses the Google Universal Sentence Encoder to encode each description as a vector and attaches this to the dataframe.
83
+ The method then outputs this modified dataframe.
84
+ """
85
+ paragraph_embedder = hub.KerasLayer("https://tfhub.dev/google/universal-sentence-encoder/4")
86
+ business_description_embedded = paragraph_embedder(paragraphs['longBusinessSummary'])
87
+ paragraphs['summaryEncoded'] = list(x.numpy() for x in business_description_embedded)
88
+ return paragraphs
89
+
90
+ def kmeans_clustering(self, descriptions:pd.DataFrame, clusters:int) -> np.ndarray :
91
+ """
92
+ Takes the set of vectors representing the business model and runs a kmeans clustering algorithm to group together similar business descriptions.
93
+ This method only runs the algorithm for a given number of clusters and this number is optimized in self.get_optimized_labels to maximise information gain.
94
+ """
95
+ kmeans_object = KMeans(n_clusters=clusters, random_state=1)
96
+ kmeans_object.fit(np.array(list(descriptions['summaryEncoded'])))
97
+ return kmeans_object.labels_
98
+
99
+ def get_optimized_labels(self, descriptions:pd.DataFrame, optimisation_range:tuple) -> np.ndarray :
100
+ """
101
+ This method runs self.kmeans_clustering on a given range of cluster numbers and works out the optimum number to maximise the quality of clusters.
102
+ This is done via maximising the silhouette score.
103
+ The cluster associated with each description is then outputted.
104
+ """
105
+ k_values = range(optimisation_range[0], optimisation_range[1])
106
+ max_silhouette_score = [0,0]
107
+ for k in k_values:
108
+ current_labels = self.kmeans_clustering(descriptions, k)
109
+ silhouette_average = silhouette_score(np.array(list(descriptions['summaryEncoded'])), current_labels)
110
+ if (silhouette_average > max_silhouette_score[0]):
111
+ max_silhouette_score = [silhouette_average, current_labels]
112
+ return max_silhouette_score[1]
113
+
114
+ def obtain_competitors(self, descriptions:pd.DataFrame) -> list :
115
+ """
116
+ Runs the kmeans clustering algorithm on potential competitors and ones which are chosen into the same cluster are assumed to have the most similar business model.
117
+ So, this methods groups together companies in the same cluster as the chosen one and this list is outputted.
118
+ """
119
+ if (len(descriptions) <= 5):
120
+ return list(descriptions.index)
121
+ max_clusters = int(len(descriptions) / 2) + 1
122
+ optimum_labels = self.get_optimized_labels(descriptions, (2,max_clusters))
123
+ descriptions['clusterLabel'] = optimum_labels
124
+ select_cluster = int(descriptions.loc[self.ticker]['clusterLabel'])
125
+ selected_competitors = list(descriptions[descriptions['clusterLabel'] == select_cluster].index)
126
+ selected_competitors.remove(self.ticker)
127
+ return selected_competitors
128
+
129
+ def competitor_analysis_report(self):
130
+ """
131
+ Uses the result of self.obtain_competitors and writes a mini summary of results into a text file.
132
+ """
133
+ potential_competitors = self.identify_market_competition()
134
+ revised_competitors = self.prepare_clustering_data(potential_competitors)
135
+ final_companies = self.obtain_competitors(revised_competitors)
136
+ ticker_list = yahooquery.Ticker(final_companies)
137
+ information_dict = ticker_list.quote_type
138
+ requested_company = yahooquery.Ticker([self.ticker]).quote_type[self.ticker]['shortName']
139
+ file_name = f"competitionAnalysisReport_{self.ticker}.txt"
140
+ if len(final_companies) > 0:
141
+ write_string = f"Requested Company : {requested_company} ({self.ticker})\n\nPossible market competitors in current economic landscape based on business model :\n"
142
+ count = 1
143
+ for x in information_dict:
144
+ write_string += f"\t{count}. {information_dict[x]['shortName']} ({x})\n"
145
+ count += 1
146
+ else:
147
+ write_string = f"Requested Company : {requested_company} ({self.ticker})\n\nAlgorithm could not find another major company with noticably similar business models.\nLooks like the company chosen has exploited a gap in the market!"
148
+ with open(file_name, "w") as f:
149
+ f.write(write_string)
150
+ return write_string
src/tools/tools.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from crewai_tools import ScrapeWebsiteTool, SerperDevTool,PDFSearchTool
3
+ import os
4
+ from dotenv import load_dotenv
5
+ from tools.competitorTool import CompetitorAnalysisTool
6
+
7
+ load_dotenv()
8
+ os.environ['SERPER_API_KEY']=os.getenv('SERPER_API_KEY')
9
+ os.environ['GOOGLE_API_KEY']=os.getenv('GOOGLE_API_KEY')
10
+ pdf_tool = PDFSearchTool(
11
+ config=dict(
12
+ llm=dict(
13
+ provider="google", # or google, openai, anthropic, llama2, ...
14
+ config=dict(
15
+ model="gemini-1.5-flash-002",
16
+
17
+ ),
18
+ ),
19
+ embedder=dict(
20
+ provider="google", # or openai, ollama, ...
21
+ config=dict(
22
+ model="models/embedding-001",
23
+ task_type="retrieval_document",
24
+ ),
25
+ ),
26
+ ),
27
+ pdf='.\report.pdf')
28
+ comp_tool = CompetitorAnalysisTool()
29
+ search_tool = SerperDevTool()
30
+ scrape_tool = ScrapeWebsiteTool()
src/utils/__init__.py ADDED
File without changes
src/utils/__pycache__/__init__.cpython-311.pyc ADDED
Binary file (194 Bytes). View file
 
src/utils/__pycache__/pdf_generator.cpython-311.pyc ADDED
Binary file (1.87 kB). View file
 
src/utils/config_loader.py ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from dotenv import load_dotenv
3
+
4
+ # Load environment variables from a .env file
5
+ load_dotenv()
6
+
7
+ def get_config(key: str, default: str = None) -> str:
8
+ """
9
+ Retrieve a configuration value from environment variables.
10
+
11
+ Args:
12
+ key (str): The key of the configuration.
13
+ default (str): The default value if the key is not found.
14
+
15
+ Returns:
16
+ str: The value of the configuration or the default value.
17
+ """
18
+ return os.getenv(key, default)
src/utils/pdf_generator.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from reportlab.lib.pagesizes import letter
2
+ from reportlab.pdfgen import canvas
3
+ from io import BytesIO
4
+ import json
5
+
6
+ def generate_pdf(report_data: dict) -> BytesIO:
7
+ """
8
+ Generates a PDF file from the given report data.
9
+
10
+ Args:
11
+ report_data (dict): The data to include in the PDF.
12
+
13
+ Returns:
14
+ BytesIO: A buffer containing the generated PDF.
15
+ """
16
+ try:
17
+ # Create a buffer to store the PDF in memory
18
+ buffer = BytesIO()
19
+ c = canvas.Canvas(buffer, pagesize=letter)
20
+
21
+ # Set up the text properties
22
+ text = c.beginText(40, 750) # Starting position
23
+ text.setFont("Helvetica", 10)
24
+
25
+ # Convert the report data dictionary to a formatted JSON string
26
+ report_str = json.dumps(report_data, indent=4)
27
+
28
+ # Write each line of the JSON string to the PDF
29
+ for line in report_str.splitlines():
30
+ text.textLine(line)
31
+
32
+ c.drawText(text)
33
+ c.showPage()
34
+ c.save()
35
+
36
+ # Rewind the buffer to the beginning
37
+ buffer.seek(0)
38
+ return buffer
39
+ except Exception as e:
40
+ raise RuntimeError(f"Failed to generate PDF: {e}")