The log_states_dict is meant to accumulate per-ticker state logs.
Restoring it after propagate_portfolio() was discarding all the
detailed logs generated during the portfolio run.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Only include full tracebacks in error messages when debug=True.
In non-debug mode, return clean error messages without internal
implementation details.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
OSError only covers file I/O errors; json.dump can also raise
TypeError on non-serializable data. Use Exception to ensure logging
failures never discard analysis results.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Wrap _log_portfolio file I/O in try/except so a write failure
doesn't discard the analysis results
- Preserve and restore self.log_states_dict in propagate_portfolio()
alongside ticker and curr_state
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Required by the configurable log directory and config passthrough
from TradingAgentsGraph that were applied via GitHub suggestions.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Preserve and restore self.ticker and self.curr_state in
propagate_portfolio() using try/finally to prevent side effects
- Use pathlib.Path for log file construction in _log_portfolio()
- Move traceback import to module level
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add PortfolioAnalyzer class that runs the full agent pipeline on multiple
stocks and produces a comparative KEEP/REDUCE/EXIT recommendation using
the deep thinking LLM. Includes per-ticker error handling, graceful
degradation on LLM failure, and result logging.
Addresses #60 and partially #406.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
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.
- 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
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
- 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
- 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)
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.
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.
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.
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