Merge d751fa3d4b into 59d6b2152d
This commit is contained in:
commit
0daa97a4ba
|
|
@ -0,0 +1,17 @@
|
||||||
|
name: Lint
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches: [main]
|
||||||
|
pull_request:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
lint:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: astral-sh/setup-uv@v5
|
||||||
|
- run: uv python install 3.10
|
||||||
|
- run: uv pip install ruff
|
||||||
|
- run: uv run ruff check .
|
||||||
|
- run: uv run ruff format --check .
|
||||||
|
|
@ -0,0 +1,7 @@
|
||||||
|
repos:
|
||||||
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||||
|
rev: v0.12.2
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [--fix]
|
||||||
|
- id: ruff-format
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
import getpass
|
import getpass
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
from rich.panel import Panel
|
from rich.panel import Panel
|
||||||
|
|
|
||||||
81
cli/main.py
81
cli/main.py
|
|
@ -1,34 +1,41 @@
|
||||||
from typing import Optional
|
|
||||||
import datetime
|
import datetime
|
||||||
import typer
|
import time
|
||||||
from pathlib import Path
|
from collections import deque
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
from rich.console import Console
|
from pathlib import Path
|
||||||
|
|
||||||
|
import typer
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
from rich import box
|
||||||
|
from rich.align import Align
|
||||||
|
from rich.console import Console
|
||||||
|
from rich.layout import Layout
|
||||||
|
from rich.live import Live
|
||||||
|
from rich.markdown import Markdown
|
||||||
|
from rich.panel import Panel
|
||||||
|
from rich.rule import Rule
|
||||||
|
from rich.spinner import Spinner
|
||||||
|
from rich.table import Table
|
||||||
|
from rich.text import Text
|
||||||
|
|
||||||
|
from cli.announcements import display_announcements, fetch_announcements
|
||||||
|
from cli.stats_handler import StatsCallbackHandler
|
||||||
|
from cli.utils import (
|
||||||
|
ask_anthropic_effort,
|
||||||
|
ask_gemini_thinking_config,
|
||||||
|
ask_openai_reasoning_effort,
|
||||||
|
ask_output_language,
|
||||||
|
select_analysts,
|
||||||
|
select_deep_thinking_agent,
|
||||||
|
select_llm_provider,
|
||||||
|
select_research_depth,
|
||||||
|
select_shallow_thinking_agent,
|
||||||
|
)
|
||||||
|
from tradingagents.default_config import DEFAULT_CONFIG
|
||||||
|
from tradingagents.graph.trading_graph import TradingAgentsGraph
|
||||||
|
|
||||||
# Load environment variables from .env file
|
# Load environment variables from .env file
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
from rich.panel import Panel
|
|
||||||
from rich.spinner import Spinner
|
|
||||||
from rich.live import Live
|
|
||||||
from rich.columns import Columns
|
|
||||||
from rich.markdown import Markdown
|
|
||||||
from rich.layout import Layout
|
|
||||||
from rich.text import Text
|
|
||||||
from rich.table import Table
|
|
||||||
from collections import deque
|
|
||||||
import time
|
|
||||||
from rich.tree import Tree
|
|
||||||
from rich import box
|
|
||||||
from rich.align import Align
|
|
||||||
from rich.rule import Rule
|
|
||||||
|
|
||||||
from tradingagents.graph.trading_graph import TradingAgentsGraph
|
|
||||||
from tradingagents.default_config import DEFAULT_CONFIG
|
|
||||||
from cli.models import AnalystType
|
|
||||||
from cli.utils import *
|
|
||||||
from cli.announcements import fetch_announcements, display_announcements
|
|
||||||
from cli.stats_handler import StatsCallbackHandler
|
|
||||||
|
|
||||||
console = Console()
|
console = Console()
|
||||||
|
|
||||||
|
|
@ -469,7 +476,9 @@ def get_user_selections():
|
||||||
welcome_content = f"{welcome_ascii}\n"
|
welcome_content = f"{welcome_ascii}\n"
|
||||||
welcome_content += "[bold green]TradingAgents: Multi-Agents LLM Financial Trading Framework - CLI[/bold green]\n\n"
|
welcome_content += "[bold green]TradingAgents: Multi-Agents LLM Financial Trading Framework - CLI[/bold green]\n\n"
|
||||||
welcome_content += "[bold]Workflow Steps:[/bold]\n"
|
welcome_content += "[bold]Workflow Steps:[/bold]\n"
|
||||||
welcome_content += "I. Analyst Team → II. Research Team → III. Trader → IV. Risk Management → V. Portfolio Management\n\n"
|
welcome_content += (
|
||||||
|
"I. Analyst Team → II. Research Team → III. Trader → IV. Risk Management → V. Portfolio Management\n\n"
|
||||||
|
)
|
||||||
welcome_content += (
|
welcome_content += (
|
||||||
"[dim]Built by [Tauric Research](https://github.com/TauricResearch)[/dim]"
|
"[dim]Built by [Tauric Research](https://github.com/TauricResearch)[/dim]"
|
||||||
)
|
)
|
||||||
|
|
@ -502,7 +511,8 @@ def get_user_selections():
|
||||||
console.print(
|
console.print(
|
||||||
create_question_box(
|
create_question_box(
|
||||||
"Step 1: Ticker Symbol",
|
"Step 1: Ticker Symbol",
|
||||||
"Enter the exact ticker symbol to analyze, including exchange suffix when needed (examples: SPY, CNC.TO, 7203.T, 0700.HK)",
|
"Enter the exact ticker symbol to analyze, including exchange suffix when needed"
|
||||||
|
" (examples: SPY, CNC.TO, 7203.T, 0700.HK)",
|
||||||
"SPY",
|
"SPY",
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
@ -720,7 +730,8 @@ def save_report_to_disk(final_state, ticker: str, save_path: Path):
|
||||||
sections.append(f"## V. Portfolio Manager Decision\n\n### Portfolio Manager\n{risk['judge_decision']}")
|
sections.append(f"## V. Portfolio Manager Decision\n\n### Portfolio Manager\n{risk['judge_decision']}")
|
||||||
|
|
||||||
# Write consolidated report
|
# Write consolidated report
|
||||||
header = f"# Trading Analysis Report: {ticker}\n\nGenerated: {datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
|
generated = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
header = f"# Trading Analysis Report: {ticker}\n\nGenerated: {generated}\n\n"
|
||||||
(save_path / "complete_report.md").write_text(header + "\n\n".join(sections))
|
(save_path / "complete_report.md").write_text(header + "\n\n".join(sections))
|
||||||
return save_path / "complete_report.md"
|
return save_path / "complete_report.md"
|
||||||
|
|
||||||
|
|
@ -763,7 +774,10 @@ def display_complete_report(final_state):
|
||||||
# III. Trading Team
|
# III. Trading Team
|
||||||
if final_state.get("trader_investment_plan"):
|
if final_state.get("trader_investment_plan"):
|
||||||
console.print(Panel("[bold]III. Trading Team Plan[/bold]", border_style="yellow"))
|
console.print(Panel("[bold]III. Trading Team Plan[/bold]", border_style="yellow"))
|
||||||
console.print(Panel(Markdown(final_state["trader_investment_plan"]), title="Trader", border_style="blue", padding=(1, 2)))
|
console.print(Panel(
|
||||||
|
Markdown(final_state["trader_investment_plan"]),
|
||||||
|
title="Trader", border_style="blue", padding=(1, 2),
|
||||||
|
))
|
||||||
|
|
||||||
# IV. Risk Management Team
|
# IV. Risk Management Team
|
||||||
if final_state.get("risk_debate_state"):
|
if final_state.get("risk_debate_state"):
|
||||||
|
|
@ -783,7 +797,10 @@ def display_complete_report(final_state):
|
||||||
# V. Portfolio Manager Decision
|
# V. Portfolio Manager Decision
|
||||||
if risk.get("judge_decision"):
|
if risk.get("judge_decision"):
|
||||||
console.print(Panel("[bold]V. Portfolio Manager Decision[/bold]", border_style="green"))
|
console.print(Panel("[bold]V. Portfolio Manager Decision[/bold]", border_style="green"))
|
||||||
console.print(Panel(Markdown(risk["judge_decision"]), title="Portfolio Manager", border_style="blue", padding=(1, 2)))
|
console.print(Panel(
|
||||||
|
Markdown(risk["judge_decision"]),
|
||||||
|
title="Portfolio Manager", border_style="blue", padding=(1, 2),
|
||||||
|
))
|
||||||
|
|
||||||
|
|
||||||
def update_research_team_status(status):
|
def update_research_team_status(status):
|
||||||
|
|
@ -1015,7 +1032,7 @@ def run_analysis():
|
||||||
# Now start the display layout
|
# Now start the display layout
|
||||||
layout = create_layout()
|
layout = create_layout()
|
||||||
|
|
||||||
with Live(layout, refresh_per_second=4) as live:
|
with Live(layout, refresh_per_second=4):
|
||||||
# Initial display
|
# Initial display
|
||||||
update_display(layout, stats_handler=stats_handler, start_time=start_time)
|
update_display(layout, stats_handler=stats_handler, start_time=start_time)
|
||||||
|
|
||||||
|
|
@ -1154,9 +1171,7 @@ def run_analysis():
|
||||||
|
|
||||||
trace.append(chunk)
|
trace.append(chunk)
|
||||||
|
|
||||||
# Get final state and decision
|
|
||||||
final_state = trace[-1]
|
final_state = trace[-1]
|
||||||
decision = graph.process_signal(final_state["final_trade_decision"])
|
|
||||||
|
|
||||||
# Update all agent statuses to completed
|
# Update all agent statuses to completed
|
||||||
for agent in message_buffer.agent_status:
|
for agent in message_buffer.agent_status:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,4 @@
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from typing import List, Optional, Dict
|
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
|
||||||
class AnalystType(str, Enum):
|
class AnalystType(str, Enum):
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
import threading
|
import threading
|
||||||
from typing import Any, Dict, List, Union
|
from typing import Any, Dict, List
|
||||||
|
|
||||||
from langchain_core.callbacks import BaseCallbackHandler
|
from langchain_core.callbacks import BaseCallbackHandler
|
||||||
from langchain_core.outputs import LLMResult
|
|
||||||
from langchain_core.messages import AIMessage
|
from langchain_core.messages import AIMessage
|
||||||
|
from langchain_core.outputs import LLMResult
|
||||||
|
|
||||||
|
|
||||||
class StatsCallbackHandler(BaseCallbackHandler):
|
class StatsCallbackHandler(BaseCallbackHandler):
|
||||||
|
|
|
||||||
10
cli/utils.py
10
cli/utils.py
|
|
@ -1,6 +1,6 @@
|
||||||
import questionary
|
from typing import List, Tuple
|
||||||
from typing import List, Optional, Tuple, Dict
|
|
||||||
|
|
||||||
|
import questionary
|
||||||
from rich.console import Console
|
from rich.console import Console
|
||||||
|
|
||||||
from cli.models import AnalystType
|
from cli.models import AnalystType
|
||||||
|
|
@ -83,7 +83,11 @@ def select_analysts() -> List[AnalystType]:
|
||||||
choices=[
|
choices=[
|
||||||
questionary.Choice(display, value=value) for display, value in ANALYST_ORDER
|
questionary.Choice(display, value=value) for display, value in ANALYST_ORDER
|
||||||
],
|
],
|
||||||
instruction="\n- Press Space to select/unselect analysts\n- Press 'a' to select/unselect all\n- Press Enter when done",
|
instruction=(
|
||||||
|
"\n- Press Space to select/unselect analysts"
|
||||||
|
"\n- Press 'a' to select/unselect all"
|
||||||
|
"\n- Press Enter when done"
|
||||||
|
),
|
||||||
validate=lambda x: len(x) > 0 or "You must select at least one analyst.",
|
validate=lambda x: len(x) > 0 or "You must select at least one analyst.",
|
||||||
style=questionary.Style(
|
style=questionary.Style(
|
||||||
[
|
[
|
||||||
|
|
|
||||||
6
main.py
6
main.py
|
|
@ -1,8 +1,8 @@
|
||||||
from tradingagents.graph.trading_graph import TradingAgentsGraph
|
|
||||||
from tradingagents.default_config import DEFAULT_CONFIG
|
|
||||||
|
|
||||||
from dotenv import load_dotenv
|
from dotenv import load_dotenv
|
||||||
|
|
||||||
|
from tradingagents.default_config import DEFAULT_CONFIG
|
||||||
|
from tradingagents.graph.trading_graph import TradingAgentsGraph
|
||||||
|
|
||||||
# Load environment variables from .env file
|
# Load environment variables from .env file
|
||||||
load_dotenv()
|
load_dotenv()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,3 +40,32 @@ include = ["tradingagents*", "cli*"]
|
||||||
|
|
||||||
[tool.setuptools.package-data]
|
[tool.setuptools.package-data]
|
||||||
cli = ["static/*"]
|
cli = ["static/*"]
|
||||||
|
|
||||||
|
[tool.ruff]
|
||||||
|
line-length = 120
|
||||||
|
|
||||||
|
[tool.ruff.lint]
|
||||||
|
select = ["E", "F", "I"]
|
||||||
|
ignore = ["E731"]
|
||||||
|
|
||||||
|
[tool.ruff.lint.isort]
|
||||||
|
combine-as-imports = true
|
||||||
|
|
||||||
|
[tool.ruff.lint.per-file-ignores]
|
||||||
|
"__init__.py" = ["F401"]
|
||||||
|
# Agent files contain LLM system prompt strings that are intentionally long.
|
||||||
|
"tradingagents/agents/**/*.py" = ["E501"]
|
||||||
|
# These dataflow files contain long indicator/tool description strings, not logic code.
|
||||||
|
"tradingagents/dataflows/alpha_vantage_indicator.py" = ["E501"]
|
||||||
|
"tradingagents/dataflows/y_finance.py" = ["E501"]
|
||||||
|
# Reflection module contains a multi-line LLM prompt defined as a string constant.
|
||||||
|
"tradingagents/graph/reflection.py" = ["E501"]
|
||||||
|
|
||||||
|
[tool.uv]
|
||||||
|
|
||||||
|
[dependency-groups]
|
||||||
|
dev = [
|
||||||
|
"pytest>=8.3.0",
|
||||||
|
"ruff>=0.9.0",
|
||||||
|
]
|
||||||
|
# Install with: uv sync
|
||||||
|
|
|
||||||
3
test.py
3
test.py
|
|
@ -1,5 +1,6 @@
|
||||||
import time
|
import time
|
||||||
from tradingagents.dataflows.y_finance import get_YFin_data_online, get_stock_stats_indicators_window, get_balance_sheet as get_yfinance_balance_sheet, get_cashflow as get_yfinance_cashflow, get_income_statement as get_yfinance_income_statement, get_insider_transactions as get_yfinance_insider_transactions
|
|
||||||
|
from tradingagents.dataflows.y_finance import get_stock_stats_indicators_window
|
||||||
|
|
||||||
print("Testing optimized implementation with 30-day lookback:")
|
print("Testing optimized implementation with 30-day lookback:")
|
||||||
start_time = time.time()
|
start_time = time.time()
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,3 @@
|
||||||
import os
|
import os
|
||||||
|
|
||||||
os.environ.setdefault("PYTHONUTF8", "1")
|
os.environ.setdefault("PYTHONUTF8", "1")
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,18 @@
|
||||||
from .utils.agent_utils import create_msg_delete
|
|
||||||
from .utils.agent_states import AgentState, InvestDebateState, RiskDebateState
|
|
||||||
from .utils.memory import FinancialSituationMemory
|
|
||||||
|
|
||||||
from .analysts.fundamentals_analyst import create_fundamentals_analyst
|
from .analysts.fundamentals_analyst import create_fundamentals_analyst
|
||||||
from .analysts.market_analyst import create_market_analyst
|
from .analysts.market_analyst import create_market_analyst
|
||||||
from .analysts.news_analyst import create_news_analyst
|
from .analysts.news_analyst import create_news_analyst
|
||||||
from .analysts.social_media_analyst import create_social_media_analyst
|
from .analysts.social_media_analyst import create_social_media_analyst
|
||||||
|
from .managers.portfolio_manager import create_portfolio_manager
|
||||||
|
from .managers.research_manager import create_research_manager
|
||||||
from .researchers.bear_researcher import create_bear_researcher
|
from .researchers.bear_researcher import create_bear_researcher
|
||||||
from .researchers.bull_researcher import create_bull_researcher
|
from .researchers.bull_researcher import create_bull_researcher
|
||||||
|
|
||||||
from .risk_mgmt.aggressive_debator import create_aggressive_debator
|
from .risk_mgmt.aggressive_debator import create_aggressive_debator
|
||||||
from .risk_mgmt.conservative_debator import create_conservative_debator
|
from .risk_mgmt.conservative_debator import create_conservative_debator
|
||||||
from .risk_mgmt.neutral_debator import create_neutral_debator
|
from .risk_mgmt.neutral_debator import create_neutral_debator
|
||||||
|
|
||||||
from .managers.research_manager import create_research_manager
|
|
||||||
from .managers.portfolio_manager import create_portfolio_manager
|
|
||||||
|
|
||||||
from .trader.trader import create_trader
|
from .trader.trader import create_trader
|
||||||
|
from .utils.agent_states import AgentState, InvestDebateState, RiskDebateState
|
||||||
|
from .utils.agent_utils import create_msg_delete
|
||||||
|
from .utils.memory import FinancialSituationMemory
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"FinancialSituationMemory",
|
"FinancialSituationMemory",
|
||||||
|
|
|
||||||
|
|
@ -1,14 +1,13 @@
|
||||||
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import (
|
from tradingagents.agents.utils.agent_utils import (
|
||||||
build_instrument_context,
|
build_instrument_context,
|
||||||
get_balance_sheet,
|
get_balance_sheet,
|
||||||
get_cashflow,
|
get_cashflow,
|
||||||
get_fundamentals,
|
get_fundamentals,
|
||||||
get_income_statement,
|
get_income_statement,
|
||||||
get_insider_transactions,
|
|
||||||
get_language_instruction,
|
get_language_instruction,
|
||||||
)
|
)
|
||||||
from tradingagents.dataflows.config import get_config
|
|
||||||
|
|
||||||
|
|
||||||
def create_fundamentals_analyst(llm):
|
def create_fundamentals_analyst(llm):
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import (
|
from tradingagents.agents.utils.agent_utils import (
|
||||||
build_instrument_context,
|
build_instrument_context,
|
||||||
get_indicators,
|
get_indicators,
|
||||||
get_language_instruction,
|
get_language_instruction,
|
||||||
get_stock_data,
|
get_stock_data,
|
||||||
)
|
)
|
||||||
from tradingagents.dataflows.config import get_config
|
|
||||||
|
|
||||||
|
|
||||||
def create_market_analyst(llm):
|
def create_market_analyst(llm):
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import (
|
from tradingagents.agents.utils.agent_utils import (
|
||||||
build_instrument_context,
|
build_instrument_context,
|
||||||
get_global_news,
|
get_global_news,
|
||||||
get_language_instruction,
|
get_language_instruction,
|
||||||
get_news,
|
get_news,
|
||||||
)
|
)
|
||||||
from tradingagents.dataflows.config import get_config
|
|
||||||
|
|
||||||
|
|
||||||
def create_news_analyst(llm):
|
def create_news_analyst(llm):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction, get_news
|
from tradingagents.agents.utils.agent_utils import build_instrument_context, get_language_instruction, get_news
|
||||||
from tradingagents.dataflows.config import get_config
|
|
||||||
|
|
||||||
|
|
||||||
def create_social_media_analyst(llm):
|
def create_social_media_analyst(llm):
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
from typing_extensions import TypedDict
|
|
||||||
from langgraph.graph import MessagesState
|
from langgraph.graph import MessagesState
|
||||||
|
from typing_extensions import TypedDict
|
||||||
|
|
||||||
|
|
||||||
# Researcher team state
|
# Researcher team state
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,34 @@
|
||||||
from langchain_core.messages import HumanMessage, RemoveMessage
|
from langchain_core.messages import HumanMessage, RemoveMessage
|
||||||
|
|
||||||
# Import tools from separate utility files
|
# Re-export tool functions so agent modules can import from a single location.
|
||||||
from tradingagents.agents.utils.core_stock_tools import (
|
from tradingagents.agents.utils.core_stock_tools import get_stock_data
|
||||||
get_stock_data
|
|
||||||
)
|
|
||||||
from tradingagents.agents.utils.technical_indicators_tools import (
|
|
||||||
get_indicators
|
|
||||||
)
|
|
||||||
from tradingagents.agents.utils.fundamental_data_tools import (
|
from tradingagents.agents.utils.fundamental_data_tools import (
|
||||||
get_fundamentals,
|
|
||||||
get_balance_sheet,
|
get_balance_sheet,
|
||||||
get_cashflow,
|
get_cashflow,
|
||||||
get_income_statement
|
get_fundamentals,
|
||||||
|
get_income_statement,
|
||||||
)
|
)
|
||||||
from tradingagents.agents.utils.news_data_tools import (
|
from tradingagents.agents.utils.news_data_tools import (
|
||||||
get_news,
|
get_global_news,
|
||||||
get_insider_transactions,
|
get_insider_transactions,
|
||||||
get_global_news
|
get_news,
|
||||||
)
|
)
|
||||||
|
from tradingagents.agents.utils.technical_indicators_tools import get_indicators
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"get_stock_data",
|
||||||
|
"get_indicators",
|
||||||
|
"get_fundamentals",
|
||||||
|
"get_balance_sheet",
|
||||||
|
"get_cashflow",
|
||||||
|
"get_income_statement",
|
||||||
|
"get_news",
|
||||||
|
"get_insider_transactions",
|
||||||
|
"get_global_news",
|
||||||
|
"get_language_instruction",
|
||||||
|
"build_instrument_context",
|
||||||
|
"create_msg_delete",
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def get_language_instruction() -> str:
|
def get_language_instruction() -> str:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from langchain_core.tools import tool
|
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
|
||||||
from tradingagents.dataflows.interface import route_to_vendor
|
from tradingagents.dataflows.interface import route_to_vendor
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from langchain_core.tools import tool
|
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
|
||||||
from tradingagents.dataflows.interface import route_to_vendor
|
from tradingagents.dataflows.interface import route_to_vendor
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,9 +4,10 @@ Uses BM25 (Best Matching 25) algorithm for retrieval - no API calls,
|
||||||
no token limits, works offline with any LLM provider.
|
no token limits, works offline with any LLM provider.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from rank_bm25 import BM25Okapi
|
|
||||||
from typing import List, Tuple
|
|
||||||
import re
|
import re
|
||||||
|
from typing import List, Tuple
|
||||||
|
|
||||||
|
from rank_bm25 import BM25Okapi
|
||||||
|
|
||||||
|
|
||||||
class FinancialSituationMemory:
|
class FinancialSituationMemory:
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
from langchain_core.tools import tool
|
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
|
||||||
from tradingagents.dataflows.interface import route_to_vendor
|
from tradingagents.dataflows.interface import route_to_vendor
|
||||||
|
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
def get_news(
|
def get_news(
|
||||||
ticker: Annotated[str, "Ticker symbol"],
|
ticker: Annotated[str, "Ticker symbol"],
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,10 @@
|
||||||
from langchain_core.tools import tool
|
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
|
from langchain_core.tools import tool
|
||||||
|
|
||||||
from tradingagents.dataflows.interface import route_to_vendor
|
from tradingagents.dataflows.interface import route_to_vendor
|
||||||
|
|
||||||
|
|
||||||
@tool
|
@tool
|
||||||
def get_indicators(
|
def get_indicators(
|
||||||
symbol: Annotated[str, "ticker symbol of the company"],
|
symbol: Annotated[str, "ticker symbol of the company"],
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,26 @@
|
||||||
# Import functions from specialized modules
|
# Import functions from specialized modules
|
||||||
from .alpha_vantage_stock import get_stock
|
from .alpha_vantage_fundamentals import (
|
||||||
|
get_balance_sheet,
|
||||||
|
get_cashflow,
|
||||||
|
get_fundamentals,
|
||||||
|
get_income_statement,
|
||||||
|
)
|
||||||
from .alpha_vantage_indicator import get_indicator
|
from .alpha_vantage_indicator import get_indicator
|
||||||
from .alpha_vantage_fundamentals import get_fundamentals, get_balance_sheet, get_cashflow, get_income_statement
|
from .alpha_vantage_news import (
|
||||||
from .alpha_vantage_news import get_news, get_global_news, get_insider_transactions
|
get_global_news,
|
||||||
|
get_insider_transactions,
|
||||||
|
get_news,
|
||||||
|
)
|
||||||
|
from .alpha_vantage_stock import get_stock
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"get_stock",
|
||||||
|
"get_indicator",
|
||||||
|
"get_fundamentals",
|
||||||
|
"get_balance_sheet",
|
||||||
|
"get_cashflow",
|
||||||
|
"get_income_statement",
|
||||||
|
"get_news",
|
||||||
|
"get_global_news",
|
||||||
|
"get_insider_transactions",
|
||||||
|
]
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,11 @@
|
||||||
import os
|
|
||||||
import requests
|
|
||||||
import pandas as pd
|
|
||||||
import json
|
import json
|
||||||
|
import os
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
import requests
|
||||||
|
|
||||||
API_BASE_URL = "https://www.alphavantage.co/query"
|
API_BASE_URL = "https://www.alphavantage.co/query"
|
||||||
|
|
||||||
def get_api_key() -> str:
|
def get_api_key() -> str:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from .alpha_vantage_common import _make_api_request
|
from .alpha_vantage_common import _make_api_request
|
||||||
|
|
||||||
|
|
||||||
def get_indicator(
|
def get_indicator(
|
||||||
symbol: str,
|
symbol: str,
|
||||||
indicator: str,
|
indicator: str,
|
||||||
|
|
@ -25,6 +26,7 @@ def get_indicator(
|
||||||
String containing indicator values and description
|
String containing indicator values and description
|
||||||
"""
|
"""
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
supported_indicators = {
|
supported_indicators = {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
from .alpha_vantage_common import _make_api_request, format_datetime_for_api
|
from .alpha_vantage_common import _make_api_request, format_datetime_for_api
|
||||||
|
|
||||||
|
|
||||||
def get_news(ticker, start_date, end_date) -> dict[str, str] | str:
|
def get_news(ticker, start_date, end_date) -> dict[str, str] | str:
|
||||||
"""Returns live and historical market news & sentiment data from premier news outlets worldwide.
|
"""Returns live and historical market news & sentiment data from premier news outlets worldwide.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from .alpha_vantage_common import _make_api_request, _filter_csv_by_date_range
|
|
||||||
|
from .alpha_vantage_common import _filter_csv_by_date_range, _make_api_request
|
||||||
|
|
||||||
|
|
||||||
def get_stock(
|
def get_stock(
|
||||||
symbol: str,
|
symbol: str,
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
import tradingagents.default_config as default_config
|
|
||||||
from typing import Dict, Optional
|
from typing import Dict, Optional
|
||||||
|
|
||||||
|
import tradingagents.default_config as default_config
|
||||||
|
|
||||||
# Use default config but allow it to be overridden
|
# Use default config but allow it to be overridden
|
||||||
_config: Optional[Dict] = None
|
_config: Optional[Dict] = None
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,31 +1,30 @@
|
||||||
from typing import Annotated
|
|
||||||
|
|
||||||
# Import from vendor-specific modules
|
# Import from vendor-specific modules
|
||||||
from .y_finance import (
|
|
||||||
get_YFin_data_online,
|
|
||||||
get_stock_stats_indicators_window,
|
|
||||||
get_fundamentals as get_yfinance_fundamentals,
|
|
||||||
get_balance_sheet as get_yfinance_balance_sheet,
|
|
||||||
get_cashflow as get_yfinance_cashflow,
|
|
||||||
get_income_statement as get_yfinance_income_statement,
|
|
||||||
get_insider_transactions as get_yfinance_insider_transactions,
|
|
||||||
)
|
|
||||||
from .yfinance_news import get_news_yfinance, get_global_news_yfinance
|
|
||||||
from .alpha_vantage import (
|
from .alpha_vantage import (
|
||||||
get_stock as get_alpha_vantage_stock,
|
|
||||||
get_indicator as get_alpha_vantage_indicator,
|
|
||||||
get_fundamentals as get_alpha_vantage_fundamentals,
|
|
||||||
get_balance_sheet as get_alpha_vantage_balance_sheet,
|
get_balance_sheet as get_alpha_vantage_balance_sheet,
|
||||||
get_cashflow as get_alpha_vantage_cashflow,
|
get_cashflow as get_alpha_vantage_cashflow,
|
||||||
|
get_fundamentals as get_alpha_vantage_fundamentals,
|
||||||
|
get_global_news as get_alpha_vantage_global_news,
|
||||||
get_income_statement as get_alpha_vantage_income_statement,
|
get_income_statement as get_alpha_vantage_income_statement,
|
||||||
|
get_indicator as get_alpha_vantage_indicator,
|
||||||
get_insider_transactions as get_alpha_vantage_insider_transactions,
|
get_insider_transactions as get_alpha_vantage_insider_transactions,
|
||||||
get_news as get_alpha_vantage_news,
|
get_news as get_alpha_vantage_news,
|
||||||
get_global_news as get_alpha_vantage_global_news,
|
get_stock as get_alpha_vantage_stock,
|
||||||
)
|
)
|
||||||
from .alpha_vantage_common import AlphaVantageRateLimitError
|
from .alpha_vantage_common import AlphaVantageRateLimitError
|
||||||
|
|
||||||
# Configuration and routing logic
|
# Configuration and routing logic
|
||||||
from .config import get_config
|
from .config import get_config
|
||||||
|
from .y_finance import (
|
||||||
|
get_balance_sheet as get_yfinance_balance_sheet,
|
||||||
|
get_cashflow as get_yfinance_cashflow,
|
||||||
|
get_fundamentals as get_yfinance_fundamentals,
|
||||||
|
get_income_statement as get_yfinance_income_statement,
|
||||||
|
get_insider_transactions as get_yfinance_insider_transactions,
|
||||||
|
get_stock_stats_indicators_window,
|
||||||
|
get_YFin_data_online,
|
||||||
|
)
|
||||||
|
from .yfinance_news import get_global_news_yfinance, get_news_yfinance
|
||||||
|
|
||||||
# Tools organized by category
|
# Tools organized by category
|
||||||
TOOLS_CATEGORIES = {
|
TOOLS_CATEGORIES = {
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,13 @@
|
||||||
import time
|
|
||||||
import logging
|
import logging
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import yfinance as yf
|
import yfinance as yf
|
||||||
from yfinance.exceptions import YFRateLimitError
|
|
||||||
from stockstats import wrap
|
from stockstats import wrap
|
||||||
from typing import Annotated
|
from yfinance.exceptions import YFRateLimitError
|
||||||
import os
|
|
||||||
from .config import get_config
|
from .config import get_config
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
@ -25,7 +26,10 @@ def yf_retry(func, max_retries=3, base_delay=2.0):
|
||||||
except YFRateLimitError:
|
except YFRateLimitError:
|
||||||
if attempt < max_retries:
|
if attempt < max_retries:
|
||||||
delay = base_delay * (2 ** attempt)
|
delay = base_delay * (2 ** attempt)
|
||||||
logger.warning(f"Yahoo Finance rate limited, retrying in {delay:.0f}s (attempt {attempt + 1}/{max_retries})")
|
logger.warning(
|
||||||
|
f"Yahoo Finance rate limited, retrying in {delay:.0f}s"
|
||||||
|
f" (attempt {attempt + 1}/{max_retries})"
|
||||||
|
)
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,8 @@
|
||||||
import os
|
from datetime import date, datetime, timedelta
|
||||||
import json
|
|
||||||
import pandas as pd
|
|
||||||
from datetime import date, timedelta, datetime
|
|
||||||
from typing import Annotated
|
from typing import Annotated
|
||||||
|
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
SavePathType = Annotated[str, "File path to save data. If None, data is not saved."]
|
SavePathType = Annotated[str, "File path to save data. If None, data is not saved."]
|
||||||
|
|
||||||
def save_output(data: pd.DataFrame, tag: str, save_path: SavePathType = None) -> None:
|
def save_output(data: pd.DataFrame, tag: str, save_path: SavePathType = None) -> None:
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,12 @@
|
||||||
from typing import Annotated
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from dateutil.relativedelta import relativedelta
|
from typing import Annotated
|
||||||
|
|
||||||
import pandas as pd
|
import pandas as pd
|
||||||
import yfinance as yf
|
import yfinance as yf
|
||||||
import os
|
from dateutil.relativedelta import relativedelta
|
||||||
from .stockstats_utils import StockstatsUtils, _clean_dataframe, yf_retry, load_ohlcv, filter_financials_by_date
|
|
||||||
|
from .stockstats_utils import StockstatsUtils, filter_financials_by_date, load_ohlcv, yf_retry
|
||||||
|
|
||||||
|
|
||||||
def get_YFin_data_online(
|
def get_YFin_data_online(
|
||||||
symbol: Annotated[str, "ticker symbol of the company"],
|
symbol: Annotated[str, "ticker symbol of the company"],
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
"""yfinance-based news data fetching functions."""
|
"""yfinance-based news data fetching functions."""
|
||||||
|
|
||||||
import yfinance as yf
|
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import yfinance as yf
|
||||||
from dateutil.relativedelta import relativedelta
|
from dateutil.relativedelta import relativedelta
|
||||||
|
|
||||||
from .stockstats_utils import yf_retry
|
from .stockstats_utils import yf_retry
|
||||||
|
|
@ -171,7 +172,11 @@ def get_global_news_yfinance(
|
||||||
data = _extract_article_data(article)
|
data = _extract_article_data(article)
|
||||||
# Skip articles published after curr_date (look-ahead guard)
|
# Skip articles published after curr_date (look-ahead guard)
|
||||||
if data.get("pub_date"):
|
if data.get("pub_date"):
|
||||||
pub_naive = data["pub_date"].replace(tzinfo=None) if hasattr(data["pub_date"], "replace") else data["pub_date"]
|
pub_naive = (
|
||||||
|
data["pub_date"].replace(tzinfo=None)
|
||||||
|
if hasattr(data["pub_date"], "replace")
|
||||||
|
else data["pub_date"]
|
||||||
|
)
|
||||||
if pub_naive > curr_dt + relativedelta(days=1):
|
if pub_naive > curr_dt + relativedelta(days=1):
|
||||||
continue
|
continue
|
||||||
title = data["title"]
|
title = data["title"]
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,11 @@
|
||||||
# TradingAgents/graph/__init__.py
|
# TradingAgents/graph/__init__.py
|
||||||
|
|
||||||
from .trading_graph import TradingAgentsGraph
|
|
||||||
from .conditional_logic import ConditionalLogic
|
from .conditional_logic import ConditionalLogic
|
||||||
from .setup import GraphSetup
|
|
||||||
from .propagation import Propagator
|
from .propagation import Propagator
|
||||||
from .reflection import Reflector
|
from .reflection import Reflector
|
||||||
|
from .setup import GraphSetup
|
||||||
from .signal_processing import SignalProcessor
|
from .signal_processing import SignalProcessor
|
||||||
|
from .trading_graph import TradingAgentsGraph
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
"TradingAgentsGraph",
|
"TradingAgentsGraph",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
# TradingAgents/graph/propagation.py
|
# TradingAgents/graph/propagation.py
|
||||||
|
|
||||||
from typing import Dict, Any, List, Optional
|
from typing import Any, Dict, List, Optional
|
||||||
|
|
||||||
from tradingagents.agents.utils.agent_states import (
|
from tradingagents.agents.utils.agent_states import (
|
||||||
AgentState,
|
|
||||||
InvestDebateState,
|
InvestDebateState,
|
||||||
RiskDebateState,
|
RiskDebateState,
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,25 @@
|
||||||
# TradingAgents/graph/setup.py
|
# TradingAgents/graph/setup.py
|
||||||
|
|
||||||
from typing import Any, Dict
|
from typing import Any, Dict
|
||||||
|
|
||||||
from langgraph.graph import END, START, StateGraph
|
from langgraph.graph import END, START, StateGraph
|
||||||
from langgraph.prebuilt import ToolNode
|
from langgraph.prebuilt import ToolNode
|
||||||
|
|
||||||
from tradingagents.agents import *
|
from tradingagents.agents import (
|
||||||
|
create_aggressive_debator,
|
||||||
|
create_bear_researcher,
|
||||||
|
create_bull_researcher,
|
||||||
|
create_conservative_debator,
|
||||||
|
create_fundamentals_analyst,
|
||||||
|
create_market_analyst,
|
||||||
|
create_msg_delete,
|
||||||
|
create_neutral_debator,
|
||||||
|
create_news_analyst,
|
||||||
|
create_portfolio_manager,
|
||||||
|
create_research_manager,
|
||||||
|
create_social_media_analyst,
|
||||||
|
create_trader,
|
||||||
|
)
|
||||||
from tradingagents.agents.utils.agent_states import AgentState
|
from tradingagents.agents.utils.agent_states import AgentState
|
||||||
|
|
||||||
from .conditional_logic import ConditionalLogic
|
from .conditional_logic import ConditionalLogic
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,33 @@
|
||||||
# TradingAgents/graph/trading_graph.py
|
# TradingAgents/graph/trading_graph.py
|
||||||
|
|
||||||
|
import json
|
||||||
import os
|
import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
import json
|
from typing import Any, Dict, List, Optional
|
||||||
from datetime import date
|
|
||||||
from typing import Dict, Any, Tuple, List, Optional
|
|
||||||
|
|
||||||
from langgraph.prebuilt import ToolNode
|
from langgraph.prebuilt import ToolNode
|
||||||
|
|
||||||
from tradingagents.llm_clients import create_llm_client
|
|
||||||
|
|
||||||
from tradingagents.agents import *
|
|
||||||
from tradingagents.default_config import DEFAULT_CONFIG
|
|
||||||
from tradingagents.agents.utils.memory import FinancialSituationMemory
|
|
||||||
from tradingagents.agents.utils.agent_states import (
|
|
||||||
AgentState,
|
|
||||||
InvestDebateState,
|
|
||||||
RiskDebateState,
|
|
||||||
)
|
|
||||||
from tradingagents.dataflows.config import set_config
|
|
||||||
|
|
||||||
# Import the new abstract tool methods from agent_utils
|
# Import the new abstract tool methods from agent_utils
|
||||||
from tradingagents.agents.utils.agent_utils import (
|
from tradingagents.agents.utils.agent_utils import (
|
||||||
get_stock_data,
|
|
||||||
get_indicators,
|
|
||||||
get_fundamentals,
|
|
||||||
get_balance_sheet,
|
get_balance_sheet,
|
||||||
get_cashflow,
|
get_cashflow,
|
||||||
|
get_fundamentals,
|
||||||
|
get_global_news,
|
||||||
get_income_statement,
|
get_income_statement,
|
||||||
get_news,
|
get_indicators,
|
||||||
get_insider_transactions,
|
get_insider_transactions,
|
||||||
get_global_news
|
get_news,
|
||||||
|
get_stock_data,
|
||||||
)
|
)
|
||||||
|
from tradingagents.agents.utils.memory import FinancialSituationMemory
|
||||||
|
from tradingagents.dataflows.config import set_config
|
||||||
|
from tradingagents.default_config import DEFAULT_CONFIG
|
||||||
|
from tradingagents.llm_clients import create_llm_client
|
||||||
|
|
||||||
from .conditional_logic import ConditionalLogic
|
from .conditional_logic import ConditionalLogic
|
||||||
from .setup import GraphSetup
|
|
||||||
from .propagation import Propagator
|
from .propagation import Propagator
|
||||||
from .reflection import Reflector
|
from .reflection import Reflector
|
||||||
|
from .setup import GraphSetup
|
||||||
from .signal_processing import SignalProcessor
|
from .signal_processing import SignalProcessor
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
|
import warnings
|
||||||
from abc import ABC, abstractmethod
|
from abc import ABC, abstractmethod
|
||||||
from typing import Any, Optional
|
from typing import Any, Optional
|
||||||
import warnings
|
|
||||||
|
|
||||||
|
|
||||||
def normalize_content(response):
|
def normalize_content(response):
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,9 @@
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
from .base_client import BaseLLMClient
|
|
||||||
from .openai_client import OpenAIClient
|
|
||||||
from .anthropic_client import AnthropicClient
|
from .anthropic_client import AnthropicClient
|
||||||
|
from .base_client import BaseLLMClient
|
||||||
from .google_client import GoogleClient
|
from .google_client import GoogleClient
|
||||||
|
from .openai_client import OpenAIClient
|
||||||
|
|
||||||
|
|
||||||
def create_llm_client(
|
def create_llm_client(
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
from .model_catalog import get_known_models
|
from .model_catalog import get_known_models
|
||||||
|
|
||||||
|
|
||||||
VALID_MODELS = {
|
VALID_MODELS = {
|
||||||
provider: models
|
provider: models
|
||||||
for provider, models in get_known_models().items()
|
for provider, models in get_known_models().items()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue