add commodity news fallback
This commit is contained in:
parent
0c917f01d1
commit
f26d168239
|
|
@ -0,0 +1,17 @@
|
|||
"""Configuration for trading agents."""
|
||||
|
||||
from .analyst_config import AnalystConfig, get_analyst_config
|
||||
from .prompt_builder import (
|
||||
build_market_analyst_prompt,
|
||||
build_news_analyst_prompt,
|
||||
build_social_media_analyst_prompt,
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
"AnalystConfig",
|
||||
"get_analyst_config",
|
||||
"build_market_analyst_prompt",
|
||||
"build_news_analyst_prompt",
|
||||
"build_social_media_analyst_prompt",
|
||||
]
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
"""Centralized configuration for analyst tools and prompts based on asset class."""
|
||||
|
||||
from typing import List, Dict, Any
|
||||
from langchain_core.tools import BaseTool
|
||||
|
||||
|
||||
class AnalystConfig:
|
||||
"""Configuration for analysts based on asset class."""
|
||||
|
||||
def __init__(self, asset_class: str = "equity"):
|
||||
self.asset_class = asset_class.lower()
|
||||
|
||||
def get_tools_for_analyst(self, analyst_type: str) -> List[BaseTool]:
|
||||
"""Get the appropriate tools for a given analyst based on asset class.
|
||||
|
||||
Args:
|
||||
analyst_type: One of 'market', 'news', 'social', 'fundamentals'
|
||||
|
||||
Returns:
|
||||
List of tools for that analyst
|
||||
"""
|
||||
# Import here to avoid circular dependencies
|
||||
from tradingagents.agents.utils.agent_utils import (
|
||||
get_stock_data,
|
||||
get_indicators,
|
||||
get_news,
|
||||
get_commodity_news,
|
||||
get_global_news,
|
||||
get_insider_sentiment,
|
||||
get_insider_transactions,
|
||||
get_fundamentals,
|
||||
get_balance_sheet,
|
||||
get_cashflow,
|
||||
get_income_statement,
|
||||
)
|
||||
from tradingagents.agents.utils.commodity_data_tools import get_commodity_data
|
||||
|
||||
tools_map = {
|
||||
"equity": {
|
||||
"market": [get_stock_data, get_indicators],
|
||||
"news": [get_news, get_global_news, get_insider_sentiment, get_insider_transactions],
|
||||
"social": [get_news, get_global_news],
|
||||
"fundamentals": [get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement],
|
||||
},
|
||||
"commodity": {
|
||||
"market": [get_commodity_data],
|
||||
"news": [get_commodity_news, get_global_news],
|
||||
"social": [get_commodity_news, get_global_news],
|
||||
"fundamentals": [], # Not applicable for commodities
|
||||
}
|
||||
}
|
||||
|
||||
return tools_map.get(self.asset_class, tools_map["equity"]).get(analyst_type, [])
|
||||
|
||||
def get_prompt_config(self, analyst_type: str) -> Dict[str, str]:
|
||||
"""Get prompt configuration for a given analyst based on asset class.
|
||||
|
||||
Returns a dict with prompt templates and asset-specific terminology.
|
||||
"""
|
||||
if self.asset_class == "commodity":
|
||||
return {
|
||||
"asset_term": "commodity",
|
||||
"asset_name_var": "ticker", # Still use ticker variable name for compatibility
|
||||
"market": {
|
||||
"focus": "supply/demand factors, geopolitical events, weather impacts (for agriculture), and macroeconomic trends",
|
||||
"data_tool": "get_commodity_data",
|
||||
"instructions": "call get_commodity_data to retrieve commodity price data",
|
||||
},
|
||||
"news": {
|
||||
"focus": "supply/demand factors, geopolitical events, weather impacts (for agriculture), and macroeconomic trends",
|
||||
"primary_tool": "get_commodity_news(commodity, start_date, end_date)",
|
||||
"primary_note": "searches by topic like 'energy' for oil, 'economy_macro' for agriculture",
|
||||
"fallback_note": "If get_commodity_news returns limited results, make sure to use get_global_news to provide additional market context.",
|
||||
},
|
||||
"social": {
|
||||
"focus": "trader sentiment, supply/demand expectations, geopolitical concerns, and market psychology",
|
||||
"primary_tool": "get_commodity_news(commodity, start_date, end_date)",
|
||||
"primary_note": "searches by topic like 'energy' for oil",
|
||||
"fallback_note": "If get_commodity_news returns limited results, supplement with get_global_news(curr_date, look_back_days, limit) for broader market context.",
|
||||
}
|
||||
}
|
||||
else: # equity
|
||||
return {
|
||||
"asset_term": "company",
|
||||
"asset_name_var": "ticker",
|
||||
"market": {
|
||||
"focus": "price trends, volume, volatility, and technical indicators",
|
||||
"data_tool": "get_stock_data and get_indicators",
|
||||
"instructions": "call get_stock_data first to retrieve historical price data, then get_indicators for technical analysis",
|
||||
},
|
||||
"news": {
|
||||
"focus": "company-specific events, earnings, product launches, and market sentiment",
|
||||
"primary_tool": "get_news(ticker, start_date, end_date)",
|
||||
"primary_note": "for company-specific or targeted news searches",
|
||||
"fallback_note": "Use get_global_news(curr_date, look_back_days, limit) for broader macroeconomic context.",
|
||||
},
|
||||
"social": {
|
||||
"focus": "social media discussions, public sentiment, and community perception",
|
||||
"primary_tool": "get_news(ticker, start_date, end_date)",
|
||||
"primary_note": "to search for company-specific news and social media discussions",
|
||||
"fallback_note": "If needed, use get_global_news(curr_date, look_back_days, limit) for broader market context.",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Singleton instance can be created per graph
|
||||
_config_instance = None
|
||||
|
||||
|
||||
def get_analyst_config(asset_class: str = "equity") -> AnalystConfig:
|
||||
"""Get or create analyst configuration for the given asset class."""
|
||||
return AnalystConfig(asset_class)
|
||||
|
||||
|
|
@ -0,0 +1,80 @@
|
|||
"""Build analyst prompts dynamically based on asset class configuration."""
|
||||
|
||||
|
||||
def build_market_analyst_prompt(asset_class: str, ticker: str) -> str:
|
||||
"""Build system message for market analyst based on asset class."""
|
||||
from .analyst_config import get_analyst_config
|
||||
|
||||
config = get_analyst_config(asset_class)
|
||||
prompt_cfg = config.get_prompt_config("market")
|
||||
|
||||
return (
|
||||
f"You are a market analyst specializing in {prompt_cfg['asset_term']} analysis. "
|
||||
f"Your task is to analyze {ticker} and provide comprehensive technical analysis. "
|
||||
f"Focus on {prompt_cfg['focus']}. "
|
||||
f"\n\nIMPORTANT: First, {prompt_cfg['instructions']}. "
|
||||
"After retrieving the data, provide detailed analysis with specific numbers, dates, and trends. "
|
||||
"Do not simply state the trends are mixed, provide detailed and fine-grained 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."
|
||||
)
|
||||
|
||||
|
||||
def build_news_analyst_prompt(asset_class: str, ticker: str) -> str:
|
||||
"""Build system message for news analyst based on asset class."""
|
||||
from .analyst_config import get_analyst_config
|
||||
|
||||
config = get_analyst_config(asset_class)
|
||||
prompt_cfg = config.get_prompt_config("news")
|
||||
asset_term = prompt_cfg["asset_term"]
|
||||
|
||||
if asset_class.lower() == "commodity":
|
||||
return (
|
||||
f"You are a news researcher tasked with analyzing recent news and trends for the commodity {ticker}. "
|
||||
"Please write a comprehensive report of relevant news over the past week that impacts this commodity's price. "
|
||||
f"Use the available tools: {prompt_cfg['primary_tool']} for commodity-specific news ({prompt_cfg['primary_note']}), "
|
||||
f"and get_global_news(curr_date, look_back_days, limit) for broader macroeconomic context. "
|
||||
f"IMPORTANT: {prompt_cfg['fallback_note']} "
|
||||
f"Focus on {prompt_cfg['focus']}. "
|
||||
"Do not simply state the trends are mixed, provide detailed and fine-grained analysis."
|
||||
" Make sure to append a Markdown table at the end of the report to organize key points."
|
||||
)
|
||||
else:
|
||||
return (
|
||||
"You are a news researcher tasked with analyzing recent news and trends over the past week. "
|
||||
"Please write a comprehensive report of the current state of the world that is relevant for trading and macroeconomics. "
|
||||
f"Use the available tools: {prompt_cfg['primary_tool']} {prompt_cfg['primary_note']}, "
|
||||
f"and get_global_news(curr_date, look_back_days, limit) for broader macroeconomic news. "
|
||||
"Do not simply state the trends are mixed, provide detailed and fine-grained 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."
|
||||
)
|
||||
|
||||
|
||||
def build_social_media_analyst_prompt(asset_class: str, ticker: str) -> str:
|
||||
"""Build system message for social media analyst based on asset class."""
|
||||
from .analyst_config import get_analyst_config
|
||||
|
||||
config = get_analyst_config(asset_class)
|
||||
prompt_cfg = config.get_prompt_config("social")
|
||||
asset_term = prompt_cfg["asset_term"]
|
||||
|
||||
if asset_class.lower() == "commodity":
|
||||
return (
|
||||
f"You are a social media and news researcher/analyst tasked with analyzing recent discussions and sentiment for the commodity {ticker}. "
|
||||
"Your objective is to write a comprehensive report detailing market sentiment, trader discussions, and public perception over the past week. "
|
||||
f"Use {prompt_cfg['primary_tool']} to search for commodity-related news and discussions ({prompt_cfg['primary_note']}). "
|
||||
f"IMPORTANT: {prompt_cfg['fallback_note']} "
|
||||
f"Focus on {prompt_cfg['focus']}. "
|
||||
"Do not simply state the trends are mixed, provide detailed and fine-grained analysis."
|
||||
" Make sure to append a Markdown table at the end of the report to organize key points."
|
||||
)
|
||||
else:
|
||||
return (
|
||||
f"You are a social media and {asset_term} specific news researcher/analyst tasked with analyzing social media posts, recent {asset_term} news, and public sentiment for a specific {asset_term} over the past week. "
|
||||
f"Your objective is to write a comprehensive long report detailing your analysis, insights, and implications for traders and investors on this {asset_term}'s current state after looking at social media and what people are saying about that {asset_term}, "
|
||||
f"analyzing sentiment data of what people feel each day about the {asset_term}, and looking at recent {asset_term} news. "
|
||||
f"Use the {prompt_cfg['primary_tool']} tool {prompt_cfg['primary_note']}. "
|
||||
f"{prompt_cfg['fallback_note']} "
|
||||
"Try to look at all sources possible from social media to sentiment to news. Do not simply state the trends are mixed, provide detailed and fine-grained 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."
|
||||
)
|
||||
|
||||
|
|
@ -31,6 +31,7 @@ from tradingagents.agents.utils.agent_utils import (
|
|||
get_cashflow,
|
||||
get_income_statement,
|
||||
get_news,
|
||||
get_commodity_news,
|
||||
get_insider_sentiment,
|
||||
get_insider_transactions,
|
||||
get_global_news
|
||||
|
|
@ -122,47 +123,16 @@ class TradingAgentsGraph:
|
|||
self.graph = self.graph_setup.setup_graph(selected_analysts)
|
||||
|
||||
def _create_tool_nodes(self) -> Dict[str, ToolNode]:
|
||||
"""Create tool nodes for different data sources using abstract methods."""
|
||||
is_commodity = self.config.get("asset_class", "equity").lower() == "commodity"
|
||||
|
||||
market_tools = []
|
||||
if is_commodity:
|
||||
# Only expose commodity tool to prevent LLM from selecting stock data
|
||||
market_tools = [
|
||||
get_commodity_data,
|
||||
]
|
||||
else:
|
||||
market_tools = [
|
||||
get_stock_data,
|
||||
get_indicators,
|
||||
]
|
||||
|
||||
"""Create tool nodes for different data sources using centralized config."""
|
||||
from tradingagents.agents.config import get_analyst_config
|
||||
|
||||
analyst_config = get_analyst_config(self.config.get("asset_class", "equity"))
|
||||
|
||||
return {
|
||||
"market": ToolNode(market_tools),
|
||||
"social": ToolNode(
|
||||
[
|
||||
# News tools for social media analysis
|
||||
get_news,
|
||||
]
|
||||
),
|
||||
"news": ToolNode(
|
||||
[
|
||||
# News and insider information
|
||||
get_news,
|
||||
get_global_news,
|
||||
get_insider_sentiment,
|
||||
get_insider_transactions,
|
||||
]
|
||||
),
|
||||
"fundamentals": ToolNode(
|
||||
[
|
||||
# Fundamental analysis tools
|
||||
get_fundamentals,
|
||||
get_balance_sheet,
|
||||
get_cashflow,
|
||||
get_income_statement,
|
||||
]
|
||||
),
|
||||
"market": ToolNode(analyst_config.get_tools_for_analyst("market")),
|
||||
"social": ToolNode(analyst_config.get_tools_for_analyst("social")),
|
||||
"news": ToolNode(analyst_config.get_tools_for_analyst("news")),
|
||||
"fundamentals": ToolNode(analyst_config.get_tools_for_analyst("fundamentals")),
|
||||
}
|
||||
|
||||
def propagate(self, company_name, trade_date):
|
||||
|
|
|
|||
Loading…
Reference in New Issue