Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# OpenAI Configuration
OPENAI_API_KEY=your_openai_api_key_here

# Anthropic Configuration
ANTHROPIC_API_KEY=your_anthropic_api_key_here

# X (Twitter) API Configuration
X_BEARER_TOKEN=your_x_bearer_token_here
X_API_KEY=your_x_api_key_here
X_API_SECRET=your_x_api_secret_here
X_ACCESS_TOKEN=your_x_access_token_here
X_ACCESS_SECRET=your_x_access_secret_here

# Bloomberg API Configuration
BLOOMBERG_API_KEY=your_bloomberg_api_key_here

# Reuters API Configuration
REUTERS_API_KEY=your_reuters_api_key_here

# Reddit Configuration
REDDIT_CLIENT_ID=your_reddit_client_id_here
REDDIT_CLIENT_SECRET=your_reddit_client_secret_here
REDDIT_USER_AGENT=TradingAgents/1.0

# FinnHub Configuration
FINNHUB_API_KEY=your_finnhub_api_key_here

# Alpha Vantage Configuration
ALPHA_VANTAGE_API_KEY=your_alpha_vantage_api_key_here

# Polygon.io Configuration
POLYGON_API_KEY=your_polygon_api_key_here

# ChromaDB Configuration
CHROMA_DB_PATH=./chroma_data

# Trading Configuration
TRADINGAGENTS_RESULTS_DIR=./results
60 changes: 34 additions & 26 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,26 +1,34 @@
typing-extensions
langchain-openai
langchain-experimental
pandas
yfinance
praw
feedparser
stockstats
eodhd
langgraph
chromadb
setuptools
backtrader
akshare
tushare
finnhub-python
parsel
requests
tqdm
pytz
redis
chainlit
rich
questionary
langchain_anthropic
langchain-google-genai
# Essential dependencies with compatible versions

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

critical

This file is missing critical dependencies required for the application to function correctly. The praw library, which is necessary for Reddit integration, has been removed. Additionally, reuterspy is used as a fallback in tradingagents/dataflows/reuters_utils.py but is not listed as a dependency. These omissions will lead to ImportError exceptions at runtime.

Please add the missing dependencies to this file. For example:

praw>=7.0.0
reuterspy>=0.1.6

pandas>=2.0.0
numpy>=1.24.0
requests>=2.28.0

# LangChain ecosystem - compatible versions
langchain-core>=0.3.75
langchain-openai>=0.3.0
langchain-experimental>=0.3.0
langchain_anthropic>=0.3.0
langgraph>=0.6.0
langgraph-checkpoint>=2.1.0

# Financial data - minimal set
yfinance>=0.2.28
stockstats>=0.6.2
finnhub-python>=2.4.20

# Data storage
chromadb>=0.5.0

# Web scraping - essential only
feedparser>=6.0.11
python-dotenv>=1.0.1

# Text processing
textblob>=0.18.0

# Utilities
tqdm>=4.66.0
setuptools>=70.0.0

# UI
rich>=13.7.0
45 changes: 27 additions & 18 deletions tradingagents/agents/analysts/fundamentals_analyst.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,10 @@
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
import time
import json


def create_fundamentals_analyst(llm, toolkit):
def fundamentals_analyst_node(state):
current_date = state["trade_date"]
ticker = state["company_of_interest"]
company_name = state["company_of_interest"]

if toolkit.config["online_tools"]:
tools = [toolkit.get_fundamentals_openai]
Expand All @@ -21,40 +18,52 @@ def fundamentals_analyst_node(state):
]

system_message = (
"You are a researcher tasked with analyzing fundamental information over the past week about a company. Please write a comprehensive report of the company's fundamental information such as financial documents, company profile, basic company financials, company financial history, insider sentiment and insider transactions to gain a full view of the company's fundamental information to inform traders. Make sure to include as much detail as possible. Do not simply state the trends are mixed, provide detailed and finegrained analysis and insights that may help traders make decisions."
+ " Make sure to append a Markdown table at the end of the report to organize key points in the report, organized and easy to read.",
"You are a researcher tasked with analyzing fundamental "
"information over the past week about a company. Please write "
"a comprehensive report of the company's fundamental information "
"such as financial documents, company profile, basic company "
"financials, company financial history, insider sentiment and "
"insider transactions to gain a full view of the company's "
"fundamental information to inform traders. Make sure to include "
"as much detail as possible. Do not simply state the trends are "
"mixed, provide detailed and finegrained analysis and insights "
"that may help traders make decisions. Make sure to append a "
"Markdown table at the end of the report to organize key points "
"in the report, organized and easy to read."
)

prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a helpful AI assistant, collaborating with other assistants."
" Use the provided tools to progress towards answering the question."
" If you are unable to fully answer, that's OK; another assistant with different tools"
" will help where you left off. Execute what you can to make progress."
" If you or any other assistant has the FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** or deliverable,"
" prefix your response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** so the team knows to stop."
" You have access to the following tools: {tool_names}.\n{system_message}"
"For your reference, the current date is {current_date}. The company we want to look at is {ticker}",
"You are a helpful AI assistant, collaborating with other "
"assistants. Use the provided tools to progress towards "
"answering the question. If you are unable to fully answer, "
"that's OK; another assistant with different tools will help "
"where you left off. Execute what you can to make progress. "
"If you or any other assistant has the FINAL TRANSACTION "
"PROPOSAL: **BUY/HOLD/SELL** or deliverable, prefix your "
"response with FINAL TRANSACTION PROPOSAL: **BUY/HOLD/SELL** "
"so the team knows to stop. You have access to the following "
"tools: {tool_names}.\n{system_message}For your reference, "
"the current date is {current_date}. The company we want to "
"look at is {ticker}",
),
MessagesPlaceholder(variable_name="messages"),
]
)

prompt = prompt.partial(system_message=system_message)
prompt = prompt.partial(tool_names=", ".join([tool.name for tool in tools]))
tool_names = ", ".join([tool.name for tool in tools])
prompt = prompt.partial(tool_names=tool_names)
prompt = prompt.partial(current_date=current_date)
prompt = prompt.partial(ticker=ticker)

chain = prompt | llm.bind_tools(tools)

result = chain.invoke(state["messages"])

report = ""

if len(result.tool_calls) == 0:
report = result.content
report = result.content if result.content else ""

return {
"messages": [result],
Expand Down
8 changes: 1 addition & 7 deletions tradingagents/agents/analysts/market_analyst.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,11 @@
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
import time
import json


def create_market_analyst(llm, toolkit):

def market_analyst_node(state):
current_date = state["trade_date"]
ticker = state["company_of_interest"]
company_name = state["company_of_interest"]

if toolkit.config["online_tools"]:
tools = [
Expand Down Expand Up @@ -76,11 +73,8 @@ def market_analyst_node(state):

result = chain.invoke(state["messages"])

report = ""
report = result.content if result.content else ""

if len(result.tool_calls) == 0:
report = result.content

return {
"messages": [result],
"market_report": report,
Expand Down
30 changes: 16 additions & 14 deletions tradingagents/agents/managers/research_manager.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,25 @@
import time
import json


def create_research_manager(llm, memory):
def research_manager_node(state) -> dict:
history = state["investment_debate_state"].get("history", "")
market_research_report = state["market_report"]
sentiment_report = state["sentiment_report"]
news_report = state["news_report"]
fundamentals_report = state["fundamentals_report"]
if not state or not isinstance(state, dict):
raise ValueError("Invalid state provided to research_manager")

investment_debate_state = state["investment_debate_state"]
investment_debate_state = state.get("investment_debate_state", {})
history = investment_debate_state.get("history", "")
market_research_report = state.get("market_report", "")
sentiment_report = state.get("sentiment_report", "")
news_report = state.get("news_report", "")
fundamentals_report = state.get("fundamentals_report", "")

curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=2)
curr_situation = f"Market: {market_research_report}\nSentiment: {sentiment_report}\nNews: {news_report}\nFundamentals: {fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=3, min_similarity=0.8)

past_memory_str = ""
for i, rec in enumerate(past_memories, 1):
past_memory_str += rec["recommendation"] + "\n\n"
if past_memories:
for i, rec in enumerate(past_memories, 1):
similarity = rec.get("similarity_score", 0)
past_memory_str += f"Research Memory {i} (similarity: {similarity:.3f}): {rec['recommendation']}\n\n"
else:
past_memory_str = "No statistically significant research memories found (similarity < 80%)."

prompt = f"""As the portfolio manager and debate facilitator, your role is to critically evaluate this round of debate and make a definitive decision: align with the bear analyst, the bull analyst, or choose Hold only if it is strongly justified based on the arguments presented.

Expand Down
16 changes: 9 additions & 7 deletions tradingagents/agents/managers/risk_manager.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import time
import json


def create_risk_manager(llm, memory):
Expand All @@ -11,16 +9,20 @@ def risk_manager_node(state) -> dict:
risk_debate_state = state["risk_debate_state"]
market_research_report = state["market_report"]
news_report = state["news_report"]
fundamentals_report = state["news_report"]
fundamentals_report = state["fundamentals_report"]
sentiment_report = state["sentiment_report"]
trader_plan = state["investment_plan"]

curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=2)
curr_situation = f"Market: {market_research_report}\nSentiment: {sentiment_report}\nNews: {news_report}\nFundamentals: {fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=3, min_similarity=0.8)

past_memory_str = ""
for i, rec in enumerate(past_memories, 1):
past_memory_str += rec["recommendation"] + "\n\n"
if past_memories:
for i, rec in enumerate(past_memories, 1):
similarity = rec.get("similarity_score", 0)
past_memory_str += f"Risk Memory {i} (similarity: {similarity:.3f}): {rec['recommendation']}\n\n"
else:
past_memory_str = "No statistically significant risk memories found (similarity < 80%)."

prompt = f"""As the Risk Management Judge and Debate Facilitator, your goal is to evaluate the debate between three risk analysts—Risky, Neutral, and Safe/Conservative—and determine the best course of action for the trader. Your decision must result in a clear recommendation: Buy, Sell, or Hold. Choose Hold only if strongly justified by specific arguments, not as a fallback when all sides seem valid. Strive for clarity and decisiveness.

Expand Down
29 changes: 17 additions & 12 deletions tradingagents/agents/researchers/bear_researcher.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
from langchain_core.messages import AIMessage
import time
import json
import functools

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The functools module is imported but not used in this file. Please remove it to keep the code clean.



def create_bear_researcher(llm, memory):
def bear_node(state) -> dict:
investment_debate_state = state["investment_debate_state"]
if not state or not isinstance(state, dict):
raise ValueError("Invalid state provided to bear_researcher")

investment_debate_state = state.get("investment_debate_state", {})
history = investment_debate_state.get("history", "")
bear_history = investment_debate_state.get("bear_history", "")

current_response = investment_debate_state.get("current_response", "")
market_research_report = state["market_report"]
sentiment_report = state["sentiment_report"]
news_report = state["news_report"]
fundamentals_report = state["fundamentals_report"]
market_research_report = state.get("market_report", "")
sentiment_report = state.get("sentiment_report", "")
news_report = state.get("news_report", "")
fundamentals_report = state.get("fundamentals_report", "")

curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=2)
curr_situation = f"Market: {market_research_report}\nSentiment: {sentiment_report}\nNews: {news_report}\nFundamentals: {fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=3, min_similarity=0.8)

past_memory_str = ""
for i, rec in enumerate(past_memories, 1):
past_memory_str += rec["recommendation"] + "\n\n"
if past_memories:
for i, rec in enumerate(past_memories, 1):
similarity = rec.get("similarity_score", 0)
past_memory_str += f"Bear Memory {i} (similarity: {similarity:.3f}): {rec['recommendation']}\n\n"
else:
past_memory_str = "No statistically significant bear memories found (similarity < 80%)."

prompt = f"""You are a Bear Analyst making the case against investing in the stock. Your goal is to present a well-reasoned argument emphasizing risks, challenges, and negative indicators. Leverage the provided research and data to highlight potential downsides and counter bullish arguments effectively.
Expand Down
29 changes: 17 additions & 12 deletions tradingagents/agents/researchers/bull_researcher.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,31 @@
from langchain_core.messages import AIMessage
import time
import json
import functools

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The functools module is imported but not used in this file. Please remove it to improve code clarity.



def create_bull_researcher(llm, memory):
def bull_node(state) -> dict:
investment_debate_state = state["investment_debate_state"]
if not state or not isinstance(state, dict):
raise ValueError("Invalid state provided to bull_researcher")

investment_debate_state = state.get("investment_debate_state", {})
history = investment_debate_state.get("history", "")
bull_history = investment_debate_state.get("bull_history", "")

current_response = investment_debate_state.get("current_response", "")
market_research_report = state["market_report"]
sentiment_report = state["sentiment_report"]
news_report = state["news_report"]
fundamentals_report = state["fundamentals_report"]
market_research_report = state.get("market_report", "")
sentiment_report = state.get("sentiment_report", "")
news_report = state.get("news_report", "")
fundamentals_report = state.get("fundamentals_report", "")

curr_situation = f"{market_research_report}\n\n{sentiment_report}\n\n{news_report}\n\n{fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=2)
curr_situation = f"Market: {market_research_report}\nSentiment: {sentiment_report}\nNews: {news_report}\nFundamentals: {fundamentals_report}"
past_memories = memory.get_memories(curr_situation, n_matches=3, min_similarity=0.8)

past_memory_str = ""
for i, rec in enumerate(past_memories, 1):
past_memory_str += rec["recommendation"] + "\n\n"
if past_memories:
for i, rec in enumerate(past_memories, 1):
similarity = rec.get("similarity_score", 0)
past_memory_str += f"Bull Memory {i} (similarity: {similarity:.3f}): {rec['recommendation']}\n\n"
else:
past_memory_str = "No statistically significant bull memories found (similarity < 80%)."

prompt = f"""You are a Bull Analyst advocating for investing in the stock. Your task is to build a strong, evidence-based case emphasizing growth potential, competitive advantages, and positive market indicators. Leverage the provided research and data to address concerns and counter bearish arguments effectively.
Expand Down
Loading