Replace supabase-py stubs with working psycopg2 implementation using
Supabase pooler connection string. Implement full business logic in
repository (avg cost basis, cash accounting, trade recording, snapshots).
Add 12 unit tests + 4 integration tests (51 total portfolio tests pass).
Fix cash_pct bug in models.py, update docs for psycopg2 + pooler pattern.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Implement integration tests for scanner vendor routing, ensuring correct routing to Alpha Vantage and fallback to yfinance.
- Create comprehensive unit tests for TTM analysis, covering metrics computation and report formatting.
- Introduce fail-fast vendor routing tests to verify immediate failure for methods not in FALLBACK_ALLOWED.
- Develop extensive integration tests for the yfinance data layer, mocking external calls to validate functionality across various financial data retrieval methods.
Collapsed 9 sequential phases into 5 core + 2 optional phases. The agent
was spending all its turns reading memory files, ADRs, and conventions
before ever spawning implementation agents. Now it caps initial context
gathering at 3 tool calls, skips memory-reader skill invocation (CLAUDE.md
already has conventions), writes plans as plain text instead of using
EnterPlanMode, and makes cleanup/memory-update phases optional.
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: daily digest consolidation and NotebookLM sync
- Add tradingagents/daily_digest.py: appends timestamped entries from
analyze and scan runs into a single reports/daily/{date}/daily_digest.md
- Add tradingagents/notebook_sync.py: uploads digest to Google NotebookLM
via nlm CLI, deleting the previous version before uploading (opt-in,
skips silently if NOTEBOOK_ID is not set)
- Add get_digest_path() helper to report_paths.py
- Hook both analyze and scan CLI commands to append + sync after each run
- Add NOTEBOOK_ID to .env.example
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* docs: update agent memory for daily digest + NotebookLM sync
Update CURRENT_STATE, ARCHITECTURE, and COMPONENTS context files to
reflect the feat/daily-digest-notebooklm implementation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix: correct nlm CLI commands and env var name for NotebookLM sync
- Use nlm note list/create/update instead of source list/add/delete
- Parse notes from {"notes": [...]} response structure
- Rename NOTEBOOK_ID -> NOTEBOOKLM_ID in both code and .env.example
- Auto-discover nlm at ~/.local/bin/nlm when not in PATH
- Tested: create on first run, update on subsequent runs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* gitignore
* feat: unify report paths under reports/daily/{date}/ hierarchy
All generated artifacts now land under a single reports/ tree:
- reports/daily/{date}/market/ for scan results (was results/macro_scan/)
- reports/daily/{date}/{TICKER}/ for per-ticker analysis (was reports/{TICKER}_{timestamp}/)
- reports/daily/{date}/{TICKER}/eval/ for eval logs (was eval_results/{TICKER}/...)
Adds tradingagents/report_paths.py with centralized path helpers used by
CLI commands, trading graph, and pipeline.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: structured observability logging for LLM, tool, and vendor calls
Add RunLogger (tradingagents/observability.py) that emits JSON-lines events
for every LLM call (model, agent, tokens in/out, latency), tool invocation
(tool name, args, success, latency), data vendor call (method, vendor,
success/failure, latency), and report save.
Integration points:
- route_to_vendor: log_vendor_call() on every try/catch
- run_tool_loop: log_tool_call() on every tool invoke
- ScannerGraph: new callbacks param, passes RunLogger.callback to all LLM tiers
- pipeline/macro_bridge: picks up RunLogger from thread-local, passes to TradingAgentsGraph
- cli/main.py: one RunLogger per command (analyze/scan/pipeline), write_log()
at end, summary line printed to console
Log files co-located with reports:
reports/daily/{date}/{TICKER}/run_log.jsonl (analyze)
reports/daily/{date}/market/run_log.jsonl (scan)
reports/daily/{date}/run_log.jsonl (pipeline)
Also fix test_long_response_no_nudge: update "A"*600 → "A"*2100 to match
MIN_REPORT_LENGTH=2000 threshold set in an earlier commit.
Update memory system context files (ARCHITECTURE, COMPONENTS, CONVENTIONS,
GLOSSARY, CURRENT_STATE) to document observability and report path systems.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* feat: add extract_json() utility for robust LLM JSON parsing
Handles DeepSeek R1 <think> blocks, markdown code fences, and
preamble/postamble text that LLMs wrap around JSON output.
Applied to macro_synthesis, macro_bridge, and CLI scan output.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: opt-in vendor fallback — fail-fast by default (ADR 011)
Silent cross-vendor fallback corrupts signal quality when data contracts
differ (e.g., AV news has sentiment scores yfinance lacks). Only methods
with fungible data contracts (OHLCV, indices, sector/industry perf,
market movers) now get fallback. All others raise immediately.
- Add FALLBACK_ALLOWED whitelist to interface.py
- Rewrite route_to_vendor() with fail-fast/fallback branching
- Improve error messages with method name, vendors tried, and exception chaining
- Add 11 new tests in test_vendor_failfast.py
- Update ADRs 002 (superseded), 008, 010; create ADR 011
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Also unblock docs/agent/plans/ from .gitignore — the plans/ rule was
intended for generated scan-result plans, not design documents.
- 011-opt-in-vendor-fallback.md: fail-fast-by-default with FALLBACK_ALLOWED
whitelist for fungible data tools (OHLCV, indices, sector/industry perf,
market movers); 4-phase plan covering interface.py change, new tests,
ADR docs, and verification
- 012-fix-preexisting-test-failures.md: root-cause analysis and exact fixes
for all 12 pre-existing failures across 5 test files (now implemented)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Root causes fixed:
- test_config_wiring.py: `callable()` returns False on LangChain @tool
objects — replaced with `hasattr(x, "invoke")` check
- test_env_override.py: `load_dotenv()` in default_config.py re-reads
.env on importlib.reload(), leaking user's TRADINGAGENTS_* env vars
into isolation tests — mock env vars before reload
- test_scanner_comprehensive.py: LLM-calling test was not marked
@pytest.mark.integration — added marker so offline runs skip it
- test_scanner_fallback.py: assertions used stale `_output_files` list
from a previous run when output dir already existed — clear dir in
setUp; also fixed tool-availability check using hasattr(x, "invoke")
- test_scanner_graph.py: output-file path assertions used hardcoded
date string instead of fixture date; graph node assertions checked
for removed node names
Full offline suite: 388 passed, 70 deselected, 0 failures.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* chore: remove unused chainlit dependency (CVE-2026-22218)
* fix: pass debate round config to ConditionalLogic (#361)
* fix: pass max_debate_rounds and max_risk_discuss_rounds config to ConditionalLogic
* use config values
* 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
* 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.
* 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.
* fix: add missing console import to cli/utils.py
Seven error-handling paths used console.print() but console was never
imported, causing NameError on invalid user input.
* 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.
* 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)
* docs: add v0.2.1 release note to README
* 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
* Initial plan
---------
Co-authored-by: Yijia-Xiao <yijia-xiao@outlook.com>
Co-authored-by: makk9 <117951691+makk9@users.noreply.github.com>
Co-authored-by: 阳虎 <yanghu@yanghudeMacBook-Pro.local>
Co-authored-by: Yijia Xiao <48253104+Yijia-Xiao@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: ahmet guzererler <guzererler@gmail.com>
* Initial plan
* docs: add all environment variables to .env.example
Comprehensively document all 28 TRADINGAGENTS_* config overrides and 6 API
keys used by the framework, organized into logical sections with inline
comments showing defaults and valid options.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* Update .env.example
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Co-authored-by: ahmet guzererler <guzererler@gmail.com>
* docs: add implementation plan for medium-term positioning upgrade
Covers 4 objectives: increased debate rounds, 8-quarter TTM fundamentals,
sector/peer relative performance, and macro regime classification.
https://claude.ai/code/session_01TuPpssTo83whKkNgSu57HH
* feat: medium-term positioning upgrade (debate rounds, TTM, peer comparison, macro regime)
## Changes
### Step 1: Agentic Debate Depth
- Increase `max_debate_rounds` and `max_risk_discuss_rounds` from 1 → 2 in `default_config.py`
- Fix bug in `trading_graph.py`: wire config values into `ConditionalLogic()` (was ignoring config, using hardcoded defaults)
### Step 2: 8-Quarter TTM Fundamental Analysis
- New `tradingagents/dataflows/ttm_analysis.py`: parses quarterly income/balance/cashflow CSV strings, computes TTM (sum of last 4 quarters), QoQ/YoY growth rates, margin trends across 8 quarters
- New `@tool get_ttm_analysis` in `fundamental_data_tools.py`
- Wire into fundamentals ToolNode; register in `TOOLS_CATEGORIES`
- Update fundamentals analyst prompt: "last 8 quarters (2 years)" focus
### Step 3: Sector & Peer Relative Performance
- New `tradingagents/dataflows/peer_comparison.py`: sector peer lookup, 1W/1M/3M/6M/YTD return ranking, alpha vs sector ETF
- New `@tool get_peer_comparison` and `@tool get_sector_relative`
- Wire into fundamentals ToolNode
### Step 4: Macro Regime Flag
- New `tradingagents/dataflows/macro_regime.py`: 6-signal classifier (VIX level/trend, credit spread HYG/LQD, yield curve TLT/SHY, market breadth SPX vs 200-SMA, sector rotation) → risk-on / transition / risk-off
- New `@tool get_macro_regime`; add `macro_regime_report` field to AgentState
- Wire into market ToolNode; feed into research_manager and risk_manager prompts
### Step 5: Tests (88 new unit tests, 0 integration)
- `tests/test_debate_rounds.py` (17 tests)
- `tests/test_ttm_analysis.py` (18 tests)
- `tests/test_peer_comparison.py` (11 tests)
- `tests/test_macro_regime.py` (16 tests)
- `tests/test_config_wiring.py` (12 tests)
All 88 new unit tests pass; no regressions in existing tests.
https://claude.ai/code/session_01TuPpssTo83whKkNgSu57HH
* test: mark live yfinance network tests as integration
TestYfinanceIndustryPerformance, TestRouteToVendorFallback, and TestFallbackRouting
all make live HTTP calls to yfinance (yfinance.Sector / market movers). Mark them
@pytest.mark.integration so they're skipped in standard offline runs.
https://claude.ai/code/session_01TuPpssTo83whKkNgSu57HH
* docs: update memory files for medium-term positioning upgrade
- PROGRESS.md: add milestone section with all new files and changes
- DECISIONS.md: add decisions 008-010 (macro regime, TTM data source, peer comparison)
- MISTAKES.md: add mistakes 10-11 (Python 3.11 f-string, mock data precision)
https://claude.ai/code/session_01TuPpssTo83whKkNgSu57HH
* docs: document git remote setup (origin = aguzererler fork)
origin points to aguzererler/TradingAgents which IS the fork.
No upstream remote configured. All feature branches push to origin.
https://claude.ai/code/session_01TuPpssTo83whKkNgSu57HH
* docs: redirect tracking files to memory system
Replace DECISIONS.md/MISTAKES.md/PROGRESS.md references in CLAUDE.md
with instructions to use /remember memory system. A PreToolUse hook
in ~/.claude/settings.json enforces this by blocking writes to those files.
https://claude.ai/code/session_01TuPpssTo83whKkNgSu57HH
* Initial plan
* Add integration tests for yfinance and Alpha Vantage APIs (78 tests, all passing)
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* Initial plan
* fix: allow .env variables to override DEFAULT_CONFIG values
Merged origin/main and resolved all 8 conflicting files:
- CLAUDE.md: merged MISTAKES.md ref + Project Tracking section + env override docs
- cli/main.py: kept top-level json import, kept try/except in run_pipeline
- tool_runner.py: kept descriptive comments for MAX_TOOL_ROUNDS
- alpha_vantage_common.py: kept thread-safe rate limiter, robust error handling
- interface.py: kept broader exception catch (AlphaVantageError + ConnectionError + TimeoutError)
- default_config.py: kept _env()/_env_int() env var overrides with load_dotenv() at module level
- scanner_graph.py: kept debug mode fix (stream for debug, invoke for result)
- macro_bridge.py: kept get_running_loop() over deprecated get_event_loop()
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* fix: move rate limiter sleep outside lock to avoid blocking threads
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* docs: update PROGRESS, DECISIONS, MISTAKES, CLAUDE with env override implementation
- PROGRESS.md: added env override milestone, updated test count (38 total),
marked Mistake #9 as resolved, added all new/modified files from PR #9
- DECISIONS.md: added Decision 008 (env var config overrides),
Decision 009 (thread-safe rate limiter), Decision 010 (broader
vendor fallback exceptions), updated Decision 007 status to superseded
- MISTAKES.md: updated Mistake #9 status to RESOLVED, added Mistake #10
(rate limiter held lock during sleep)
- CLAUDE.md: added env var override convention docs, updated critical
patterns with rate limiter and config fallback key lessons, updated
mistake count to 10
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* merge main into branch (-X theirs) and fix tests to pass against current main code
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* feat: add scanner tests, global demo key in conftest, remove 48 inline key patches
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* feat: add agentic memory scaffold and migrate tracking files to docs/agent/
Migrate DECISIONS.md, MISTAKES.md, PROGRESS.md, agents/, plans/, and
tradingagents/llm_clients/TODO.md into a structured docs/agent/ scaffold
with ADR-style decisions, plans, templates, and a live state tracker.
This gives agent workflows a standard memory structure for decisions,
plans, logs, and session continuity via CURRENT_STATE.md.
Agent-Ref: docs/agent/plans/global-macro-scanner.md
State-Updated: Yes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: improve Industry Deep Dive report quality with enriched data, sector routing, and tool-call nudge
* Initial plan
* Improve Industry Deep Dive quality: enrich tool data, explicit sector keys, tool-call nudge
- Enrich get_industry_performance_yfinance with 1-day/1-week/1-month price returns
via batched yf.download() for top 10 tickers (Step 1)
- Add VALID_SECTOR_KEYS, _DISPLAY_TO_KEY, _extract_top_sectors() to industry_deep_dive.py
to pre-extract top sectors from Phase 1 report and inject them into the prompt (Step 2)
- Add tool-call nudge to run_tool_loop: if first LLM response has no tool calls and is
under 500 chars, re-prompt with explicit instruction to call tools (Step 3)
- Update scanner_tools.py get_industry_performance docstring to list all valid sector keys (Step 4)
- Add 15 unit tests covering _extract_top_sectors, tool_runner nudge, and enriched output (Step 5)
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* Address code review: move cols[3] access into try block for IndexError safety
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* fix: align display row count with download count in get_industry_performance_yfinance
The enriched function downloads price data for top 10 tickers but displayed
20 rows, causing rows 11-20 to show N/A in all price columns. This broke
test_industry_perf_falls_back_to_yfinance which asserts N/A count < 5.
Now both download and display use head(10) for consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Co-authored-by: Ahmet Guzererler <guzererler@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update memory files after PR #13 (Industry Deep Dive quality fix)
- CURRENT_STATE.md: remove Industry Deep Dive blocker (resolved), update
test count 38 → 53, add PR #13 to Recent Progress, update milestone focus
- decisions/009-industry-deep-dive-quality.md: new ADR documenting the
three-pronged fix (enriched data, explicit sector routing, tool-call nudge)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat: add architecture-coordinator skill for mandatory ADR reading protocol
New Claude Code skill that enforces reading docs/agent/CURRENT_STATE.md,
decisions/, and plans/ before any code changes. Includes conflict resolution
protocol that stops work and quotes the violated ADR rule when user requests
conflict with established architectural decisions.
Files:
- .claude/skills/architecture-coordinator/SKILL.md
- .claude/skills/architecture-coordinator/references/adr-template.md
- .claude/skills/architecture-coordinator/references/reading-checklist.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
---------
Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
New Claude Code skill that enforces reading docs/agent/CURRENT_STATE.md,
decisions/, and plans/ before any code changes. Includes conflict resolution
protocol that stops work and quotes the violated ADR rule when user requests
conflict with established architectural decisions.
Files:
- .claude/skills/architecture-coordinator/SKILL.md
- .claude/skills/architecture-coordinator/references/adr-template.md
- .claude/skills/architecture-coordinator/references/reading-checklist.md
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
* Initial plan
* Improve Industry Deep Dive quality: enrich tool data, explicit sector keys, tool-call nudge
- Enrich get_industry_performance_yfinance with 1-day/1-week/1-month price returns
via batched yf.download() for top 10 tickers (Step 1)
- Add VALID_SECTOR_KEYS, _DISPLAY_TO_KEY, _extract_top_sectors() to industry_deep_dive.py
to pre-extract top sectors from Phase 1 report and inject them into the prompt (Step 2)
- Add tool-call nudge to run_tool_loop: if first LLM response has no tool calls and is
under 500 chars, re-prompt with explicit instruction to call tools (Step 3)
- Update scanner_tools.py get_industry_performance docstring to list all valid sector keys (Step 4)
- Add 15 unit tests covering _extract_top_sectors, tool_runner nudge, and enriched output (Step 5)
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* Address code review: move cols[3] access into try block for IndexError safety
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
* fix: align display row count with download count in get_industry_performance_yfinance
The enriched function downloads price data for top 10 tickers but displayed
20 rows, causing rows 11-20 to show N/A in all price columns. This broke
test_industry_perf_falls_back_to_yfinance which asserts N/A count < 5.
Now both download and display use head(10) for consistency.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Co-authored-by: Ahmet Guzererler <guzererler@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Migrate DECISIONS.md, MISTAKES.md, PROGRESS.md, agents/, plans/, and
tradingagents/llm_clients/TODO.md into a structured docs/agent/ scaffold
with ADR-style decisions, plans, templates, and a live state tracker.
This gives agent workflows a standard memory structure for decisions,
plans, logs, and session continuity via CURRENT_STATE.md.
Agent-Ref: docs/agent/plans/global-macro-scanner.md
State-Updated: Yes
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
All 6 conflicts resolved by keeping this branch's implementations:
- alpha_vantage_scanner.py, interface.py, yfinance_scanner.py (data layer)
- scanner_graph.py, scanner_setup.py (graph orchestration)
- test_scanner_graph.py (deleted — replaced by focused test files)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>