83 Commits

Author SHA1 Message Date
Yijia-Xiao 7c37249f80 chore: release v0.2.4 — structured agents, checkpoint, memory log, providers
This release bundles substantial work since v0.2.3:

- Structured-output Research Manager, Trader, and Portfolio Manager
  (canonical with_structured_output pattern, single LLM call per agent,
  rendered markdown preserves the existing report shape).
- LangGraph checkpoint resume for crash recovery (--checkpoint flag).
- Persistent decision log replacing the per-agent BM25 memory, with
  deferred reflection driven by yfinance returns + alpha vs SPY.
- DeepSeek, Qwen, GLM, and Azure OpenAI provider support; dynamic
  OpenRouter model selection.
- Docker support; cache and logs moved to ~/.tradingagents/ to fix
  Docker permission issues.
- Windows UTF-8 encoding fix on every file I/O site.
- 5-tier rating consistency (Buy / Overweight / Hold / Underweight / Sell)
  across Research Manager, Portfolio Manager, signal processor, memory log.

Plus the small quality items in this commit:

1. Suppress noisy Pydantic serializer warnings from OpenAI Responses-API
   parse path by defaulting structured-output to method="function_calling"
   (root-cause fix, not a warnings filter — same typed result, no warnings).
2. Ship scripts/smoke_structured_output.py so contributors can verify
   their provider's structured-output path with one command.
3. Add opt-in memory_log_max_entries config — when set, oldest resolved
   memory log entries are pruned once the cap is exceeded; pending
   entries (unresolved) are never pruned.
4. backend_url default changed from the OpenAI URL to None so the
   per-provider client falls back to its native endpoint instead of
   leaking OpenAI's URL into Gemini / other clients.

CHANGELOG.md added with the full v0.2.4 entry. 92 tests pass without API keys.
2026-04-25 22:16:09 +00:00
Yijia-Xiao 4016fd4efa fix: stop leaking OpenAI base_url into non-OpenAI provider clients
Default config had backend_url='https://api.openai.com/v1' which was
forwarded to every provider client, including Google. ChatGoogleGenerativeAI
constructed requests against that base, producing malformed URLs like
https://api.openai.com/v1/v1beta/models/gemini-2.5-flash:generateContent
that 404 with empty body.

Discovered while running propagate() against Gemini end-to-end. The
structured-output smoke worked because that path constructed the LLM
without going through the factory and without forwarding backend_url;
propagate() goes through TradingAgentsGraph.__init__ which forwards
config['backend_url'] to every provider.

Fix: default to None. Each provider client falls back to its own
endpoint (api.openai.com for OpenAI via _PROVIDER_CONFIG, Gemini's
default for Google, and so on). The CLI flow already sets backend_url
explicitly per provider when the user picks one, so that path is
unchanged.

Verified: full propagate() now passes end-to-end on both
OpenAI gpt-5.4-mini and Gemini gemini-3-flash-preview, with all nine
structure/log/signal checks green for each.
2026-04-25 20:54:19 +00:00
Yijia-Xiao bba147798f feat: structured-output Trader and Research Manager (#434, finishes the trio)
Extends the canonical structured-output pattern from the Portfolio Manager
to the other two decision-making agents.  Each of the three agents now
returns a typed Pydantic instance via llm.with_structured_output() in a
single primary call, and a render helper turns the result into the same
markdown shape downstream agents and saved reports already consume.

- ResearchPlan: 5-tier recommendation, conversational rationale, concrete
  strategic actions for the trader.
- TraderProposal: 3-tier action (transaction direction is naturally Buy /
  Hold / Sell — position sizing happens later at the Portfolio Manager),
  reasoning, and optional entry_price / stop_loss / position_sizing.
  Rendered output preserves the trailing "FINAL TRANSACTION PROPOSAL:
  **BUY/HOLD/SELL**" line for backward compatibility with the analyst
  stop-signal text.
- PortfolioDecision: 5-tier rating, executive summary, investment thesis,
  optional price_target / time_horizon (unchanged).

The shared try-structured-then-fallback pattern is extracted into
tradingagents/agents/utils/structured.py (bind_structured +
invoke_structured_or_freetext) so all three agents go through the same
code path and log the same warning when a provider lacks structured
output and the agent falls back to free-text generation.

Net effect for users: every saved markdown report (research/manager.md,
trading/trader.md, portfolio/decision.md) now has consistent section
headers across runs and providers, easier to scan.

Net effect for the runtime: the rating extraction round-trip is gone —
the rating comes from the structured response itself, not a second
LLM call. SignalProcessor was already simplified to a heuristic adapter
in the previous commit.

11 new tests in tests/test_structured_agents.py cover the Trader and
Research Manager render functions, structured-output happy paths, and
free-text fallback. Full suite: 88 tests pass in ~2s without API keys.
2026-04-25 20:27:23 +00:00
Yijia-Xiao 0fda24515f feat: structured-output Portfolio Manager + 5-tier rating consistency (#434)
Three related changes that take the rating pipeline from heuristic-only
to type-safe at the source.

1) Research Manager prompt now uses the same 5-tier scale (Buy /
   Overweight / Hold / Underweight / Sell) as the Portfolio Manager,
   signal_processing, and the memory log.  The prior 3-tier wording
   (Buy / Sell / Hold) was the only remaining inconsistency in the
   pipeline.

2) Centralise the 5-tier vocabulary and the heuristic prose-rating
   parser into tradingagents/agents/utils/rating.py.  Both the memory
   log and the signal processor now share the same parser instead of
   duplicating regex and word-walker logic.

3) Make structured output a first-class part of the Portfolio Manager's
   primary call.  The PM uses llm.with_structured_output(PortfolioDecision)
   so each provider's native structured-output mode (json_schema for
   OpenAI/xAI, response_schema for Gemini, tool-use for Anthropic,
   function_calling for OpenAI-compatible providers) yields a typed
   Pydantic instance directly.  A render helper turns that instance back
   into the same markdown shape downstream consumers (memory log, CLI
   display, saved reports) already expect, so no other code has to know
   the PM now produces structured output.  Providers without structured
   support fall back gracefully to free-text + the deterministic
   heuristic.

   The previous SignalProcessor had been making a second LLM call to
   re-extract the rating from the PM's prose; that round-trip is now
   eliminated.  SignalProcessor is a thin adapter over parse_rating(),
   makes zero LLM calls, and stays for backwards compatibility with
   process_signal() callers.

Schema (PortfolioDecision) captures rating + executive_summary +
investment_thesis + optional price_target + time_horizon, with field
descriptions doubling as output instructions.  Agent prose remains the
primary artifact; structured output is layered onto the PM only because
it is the one agent whose output has machine-readable downstream
consumers.

15 new tests cover the heuristic parser (markdown-bold edge cases that
had no coverage before), the structured PM happy path, the free-text
fallback path, and that SignalProcessor never invokes the LLM.  Full
suite: 77 tests pass in ~2s without API keys.
2026-04-25 19:57:26 +00:00
Yijia-Xiao 4cbd4b086f feat: add LangGraph checkpoint resume for crash recovery (#594)
Long analyses can take many minutes; a crash or interruption forced users
to re-run from scratch and re-pay every LLM call.  This adds an opt-in
checkpoint layer backed by per-ticker SQLite databases so the graph
resumes from the last successful node.

How to use:
- CLI:    tradingagents analyze --checkpoint
- CLI:    tradingagents analyze --clear-checkpoints
- Python: config["checkpoint_enabled"] = True

Lifecycle:
- propagate() recompiles the graph with a SqliteSaver when enabled and
  injects a deterministic thread_id derived from ticker+date so the
  same ticker+date resumes while a different date starts fresh.
- On successful completion the per-thread checkpoint rows are cleared.
- The context manager is closed in a try/finally so a crash never
  leaks the SQLite connection or leaves the graph in checkpoint mode.

Storage: ~/.tradingagents/cache/checkpoints/<TICKER>.db
(override via TRADINGAGENTS_CACHE_DIR).

The checkpointer module is new (tradingagents/graph/checkpointer.py)
and the GraphSetup now returns the uncompiled workflow so it can be
recompiled with a saver when needed.

Adds langgraph-checkpoint-sqlite>=2.0.0 dependency. 3 new tests verify
the crash/resume cycle and that a different date starts fresh.
2026-04-25 08:47:15 +00:00
Yijia-Xiao ebd2e12e67 feat: replace per-agent BM25 memory with persistent decision log (#578, #563, #564, #579)
The previous per-agent BM25 memory was effectively dead code — its only
caller was a commented-out line in main.py. Replace it with a single
append-only markdown decision log driven by the propagate() lifecycle.

Lifecycle:
- store_decision() appends a pending entry at the end of every run
- _resolve_pending_entries() runs at the start of the next same-ticker
  run, fetches yfinance returns + alpha vs SPY, and writes one LLM
  reflection per resolved entry through an atomic temp-file rename
- Portfolio Manager consumes state["past_context"] (5 most recent
  same-ticker entries plus 3 cross-ticker reflection-only excerpts)

Storage at ~/.tradingagents/memory/trading_memory.md
(override: TRADINGAGENTS_MEMORY_LOG_PATH).

Tag schema:
- Pending:  [YYYY-MM-DD | TICKER | Rating | pending]
- Resolved: [YYYY-MM-DD | TICKER | Rating | +X.X% | +Y.Y% | Nd]

Removes rank-bm25 dependency and the legacy reflect_and_remember()
plumbing across reflection.py, trading_graph.py, and the agent factories.

49 new tests in tests/test_memory_log.py cover the storage, deferred
reflection, prompt injection, and legacy-removal paths. Full suite
(58 tests) passes in under 2 seconds without API keys.
2026-04-25 08:24:03 +00:00
Yijia-Xiao f85f5d9f5d test: lazy-load LLM provider clients and add API-key fixtures so the test suite runs cleanly without credentials (#588) 2026-04-25 07:41:36 +00:00
Yijia-Xiao 8e7654f0df fix: drop past-memory directive and placeholder from agent prompts when memory is empty (#572) 2026-04-25 07:41:36 +00:00
Yijia-Xiao 872b063e69 fix: use explicit encoding="utf-8" for all file I/O so Windows users avoid cp1252 crashes (#543, #550, #576) 2026-04-25 07:25:32 +00:00
Zhigong Liu 6abc768c1d feat: replace per-agent BM25 memory with persistent append-only decision log
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-04-19 22:43:14 -04:00
Yijia-Xiao fa4d01c23a fix: process all chunk messages for tool call logging, harden memory score normalization (#534, #531) 2026-04-13 07:21:33 +00:00
Yijia-Xiao b0f6058299 feat: add DeepSeek, Qwen, GLM, and Azure OpenAI provider support 2026-04-13 07:12:07 +00:00
Yijia-Xiao 59d6b2152d fix: use ~/.tradingagents/ for cache and logs, resolving Docker permission issue (#519) 2026-04-13 05:26:04 +00:00
Yijia-Xiao 4f965bf46a feat: dynamic OpenRouter model selection with search (#482, #337) 2026-04-04 07:56:44 +00:00
Yijia-Xiao bdb9c29d44 refactor: remove stale imports, use configurable results path (#499) 2026-04-04 07:35:35 +00:00
Yijia-Xiao 78fb66aed1 fix: normalize indicator names to lowercase (#490) 2026-04-04 07:23:31 +00:00
Yijia-Xiao 7269f877c1 fix: portfolio manager reads trader's proposal and research plan (#503) 2026-04-04 07:22:01 +00:00
Yijia-Xiao 28d5cc661f fix: add missing pandas import in y_finance.py (#488) 2026-04-04 07:14:10 +00:00
Yijia-Xiao e75d17bc51 chore: update model lists and defaults to GPT-5.4 family 2026-03-29 19:45:36 +00:00
Yijia-Xiao 6cddd26d6e feat: multi-language output support for analyst reports and final decision (#472) 2026-03-29 19:19:01 +00:00
Yijia Xiao c61242a28c Merge pull request #464 from CadeYu/sync-validator-models
sync model validation with cli catalog
2026-03-29 11:07:51 -07:00
Yijia-Xiao 58e99421bd fix: pass base_url to Google and Anthropic clients for proxy support (#427) 2026-03-29 17:59:52 +00:00
Yijia Xiao 46e1b600b8 Merge pull request #453 from javierdejesusda/fix/standardize-google-api-key
fix(llm_clients): standardize Google API key to unified api_key param
2026-03-29 10:54:28 -07:00
Yijia-Xiao ae8c8aebe8 fix: gracefully handle invalid indicator names in tool calls (#429) 2026-03-29 17:50:30 +00:00
Yijia-Xiao f3f58bdbdc fix: add yf_retry to yfinance news fetchers (#445) 2026-03-29 17:42:24 +00:00
Yijia-Xiao e1113880a1 fix: prevent look-ahead bias in backtesting data fetchers (#475) 2026-03-29 17:34:35 +00:00
CadeYu bd6a5b75b5 fix model catalog typing and known-model helper 2026-03-25 21:46:56 +08:00
CadeYu 8793336dad sync model validation with cli catalog 2026-03-25 21:23:02 +08:00
javierdejesusda 047b38971c refactor: simplify api_key mapping and consolidate tests
Apply review suggestions: use concise `or` pattern for API key
resolution, consolidate tests into parameterized subTest, move
import to module level per PEP 8.
2026-03-24 14:52:51 +01:00
javierdejesusda f5026009f9 fix(llm_clients): standardize Google API key to unified api_key param
GoogleClient now accepts the unified `api_key` parameter used by
OpenAI and Anthropic clients, mapping it to the provider-specific
`google_api_key` that ChatGoogleGenerativeAI expects. Legacy
`google_api_key` still works for backward compatibility.

Resolves TODO.md item #2 (inconsistent parameter handling).
2026-03-24 14:35:02 +01:00
Yijia-Xiao 6c9c9ce1fd fix: set process-level UTF-8 default for cross-platform consistency 2026-03-22 23:42:37 +00:00
Yijia-Xiao b8b2825783 refactor: standardize portfolio manager, five-tier rating scale, fix analyst status tracking 2026-03-22 23:30:29 +00:00
Yijia-Xiao 318adda0c6 refactor: five-tier rating scale and streamlined agent prompts 2026-03-22 23:07:20 +00:00
Yijia Xiao c3ba3bf428 Merge pull request #413 from CadeYu/codex/exchange-qualified-tickers
fix: preserve exchange-qualified tickers across agent prompts
2026-03-22 15:36:14 -07:00
Yijia-Xiao 7cca9c924e fix: add exponential backoff retry for yfinance rate limits (#426) 2026-03-22 22:11:08 +00:00
Yijia-Xiao bd9b1e5efa feat: add Anthropic effort level support for Claude models
Add effort parameter (high/medium/low) for Claude 4.5+ and 4.6 models,
consistent with OpenAI reasoning_effort and Google thinking_level.
Also add content normalization for Anthropic responses.
2026-03-22 21:57:05 +00:00
Yijia-Xiao 77755f0431 chore: consolidate install, fix CLI portability, normalize LLM responses
- Point requirements.txt to pyproject.toml as single source of truth
- Resolve welcome.txt path relative to module for CLI portability
- Include cli/static files in package build
- Extract shared normalize_content for OpenAI Responses API and
  Gemini 3 list-format responses into base_client.py
- Update README install and CLI usage instructions
2026-03-22 21:38:01 +00:00
Yijia-Xiao 3ff28f3559 fix: use OpenAI Responses API for native models
Enable use_responses_api for native OpenAI provider, which supports
reasoning_effort with function tools across all model families.
Removes the UnifiedChatOpenAI subclass workaround.

Closes #403
2026-03-22 20:34:03 +00:00
CadeYu 7d200d834a style: inline single-use instrument context vars 2026-03-21 21:31:38 +08:00
CadeYu 08bfe70a69 fix: preserve exchange-qualified tickers across agent prompts 2026-03-21 21:10:13 +08:00
阳虎 64f07671b9 fix: add http_client support for SSL certificate customization
- Add http_client and http_async_client parameters to all LLM clients
- OpenAIClient, GoogleClient, AnthropicClient now support custom httpx clients
- Fixes SSL certificate verification errors on Windows Conda environments
- Users can now pass custom httpx.Client with verify=False or custom certs

Fixes #369
2026-03-16 07:41:20 +08:00
Yijia-Xiao 551fd7f074 chore: update model lists, bump to v0.2.1, fix package build
- OpenAI: add GPT-5.4, GPT-5.4 Pro; remove o-series and legacy GPT-4o
- Anthropic: add Claude Opus 4.6, Sonnet 4.6; remove legacy 4.1/4.0/3.x
- Google: add Gemini 3.1 Pro, 3.1 Flash Lite; remove deprecated
  gemini-3-pro-preview and Gemini 2.0 series
- xAI: clean up model list to match current API
- Simplify UnifiedChatOpenAI GPT-5 temperature handling
- Add missing tradingagents/__init__.py (fixes pip install building)
2026-03-15 23:34:50 +00:00
Yijia-Xiao b0f9d180f9 fix: harden stock data parsing against malformed CSV and NaN values
Add _clean_dataframe() to normalize stock DataFrames before stockstats:
coerce invalid dates/prices, drop rows missing Close, fill price gaps.
Also add on_bad_lines="skip" to all cached CSV reads.
2026-03-15 18:29:43 +00:00
Yijia-Xiao fe9c8d5d31 fix: handle comma-separated indicators in get_indicators tool
LLMs (especially smaller models) sometimes pass multiple indicator
names as a single comma-separated string instead of making separate
tool calls. Split and process each individually at the tool boundary.
2026-03-15 18:05:36 +00:00
Yijia-Xiao eec6ca4b53 fix: initialize all debate state fields in propagation.py
InvestDebateState was missing bull_history, bear_history, judge_decision.
RiskDebateState was missing aggressive_history, conservative_history,
neutral_history, latest_speaker, judge_decision. This caused KeyError
in _log_state() and reflection, especially with edge-case config values.
2026-03-15 17:54:32 +00:00
Yijia-Xiao 3642f5917c fix: add explicit UTF-8 encoding to all file open() calls
Prevents UnicodeEncodeError on Windows where the default encoding
(cp1252/gbk) cannot handle Unicode characters in LLM output.

Closes #77, closes #114, closes #126, closes #215, closes #332
2026-03-15 16:44:23 +00:00
makk9 907bc8022a fix: pass debate round config to ConditionalLogic (#361)
* fix: pass max_debate_rounds and max_risk_discuss_rounds config to ConditionalLogic

* use config values
2026-03-15 09:31:59 -07:00
Ljx-007 35856ff33e fix(risk_manager): 修复基本面报告数据源错误
- 修正了fundamentals_report从news_report获取数据的问题
- 确保fundamentals_report正确使用fundamentals_report数据源
2026-02-09 18:21:21 +08:00
Yijia Xiao 6cd35179fa chore: clean up dependencies and fix Ollama auth
- Remove unused packages: praw, feedparser, eodhd, akshare, tushare, finnhub
- Fix Ollama requiring API key
2026-02-03 23:08:12 +00:00
Yijia Xiao 102b026d23 refactor: clean up codebase and streamline documentation
- Remove debug prints from vendor routing (interface.py)
- Simplify vendor fallback to only handle rate limits
- Reorder CLI provider menu: OpenAI, Google, Anthropic, xAI, OpenRouter, Ollama
- Remove dead files: local.py, reddit_utils.py, openai.py, google.py, googlenews_utils.py, yfin_utils.py
2026-02-03 22:27:20 +00:00