Backend:
- Replace bare print() with structured logging module
- Include LLM prompt snippets and response content in streamed events
- Extract proper node names from LangGraph metadata (langgraph_node)
- Add latency tracking (start/end time per node)
- Add tool input/output content in events
- Add system log event type for informational messages
- Stream on_tool_end events for tool results
Frontend:
- Fix node disappearing/reappearing: use useNodesState/useEdgesState + useEffect
for incremental updates instead of useMemo that rebuilt all nodes on each event
- Fix duplicate node creation: use useRef to track seen node IDs persistently
- Fix useAgentStream reconnection loop: remove stale `status` from connect deps
- Use statusRef to avoid stale closure in onclose handler
- Add auto-scroll to terminal, event count, type labels/colors
- Show prompt snippets, tool I/O, and response content in terminal
- Handle 'log' event type
Packages:
- Update all npm deps to latest compatible minor versions
- Remove node_modules from git tracking, add to .gitignore
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Agent-Logs-Url: https://github.com/aguzererler/TradingAgents/sessions/5c511c4e-5172-4eda-b6de-aefa1859e8ac
- add root agent_os/README.md with system architecture and setup guides
- update DESIGN.md with port 8088 migration and network configurations
- document real-time DAG rendering and high-fidelity risk metrics
- move backend port from 8001 to 8088
- update frontend to use 127.0.0.1 explicitly instead of localhost
- add request/response logging middleware to backend
- fix explicit CORS origin matching for browser compatibility
- update portfolio summary route to check 'summary/' directory for scan results
- enhance LangGraph event mapping to extract functional node names from metadata
- fix initial state keys for ScannerGraph to match TradingAgents internals
- add /api/portfolios/{id}/summary endpoint to backend
- parse Sharpe and Drawdown from latest portfolio snapshots
- parse Market Regime from macro_scan/scan_summary.json
- update MetricHeader to fetch real-time metrics with polling
- pass portfolio_id to dashboard and trigger methods
- scaffold Vite + React + TypeScript frontend with Chakra UI and React Flow
- implement AgentGraph, MetricHeader, and Dashboard components
- connect FastAPI to live LangGraph events via astream_events
- implement real-time event mapping for 'scan' and 'pipeline'
- refactor run storage for shared access between REST and WebSockets
- implement FastAPI backend with REST and WebSocket streaming
- add node-level metrics (tokens, latency) to event protocol
- design literal graph and top 3 metrics (Sharpe, Regime, Drawdown)
- scaffold React frontend with Chakra UI and useAgentStream hook
- add DESIGN.md and .env.example
In langchain_core >=1.0 plain Generation no longer stores a .message
attribute - that only exists on ChatGeneration. Tests were constructing
Generation(message=AIMessage(...)) which silently dropped the message,
making hasattr(generation, "message") return False and skipping the
token-counting path (all usage assertions failed with 0).
- Replace Generation(message=...) with ChatGeneration(message=AIMessage(...))
in test_stats_handler_on_llm_end_with_usage and thread_safety test
- Use UsageMetadata(input_tokens=N, output_tokens=N, total_tokens=N)
instead of bare dict (total_tokens is required in langchain_core 1.2+)
- Pass usage_metadata via AIMessage constructor instead of post-init
attribute assignment (avoids pydantic validation bypass)
- Keep Generation(text=...) in test_stats_handler_on_llm_end_no_usage
(correctly tests the "no usage" branch — plain Generation has no .message)
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Agent-Logs-Url: https://github.com/aguzererler/TradingAgents/sessions/ce079791-08ef-4f2e-9f31-a1ae6a26b4cb
Before this change, the pipeline showed a generic 'Analyzing...' spinner
for the entire multi-ticker run with no way to know which ticker was
processing or whether anything was actually working.
Changes:
- macro_bridge.py:
- run_ticker_analysis: logs '▶ Starting', '✓ complete in Xs', '✗ FAILED'
with elapsed time per ticker using logger.info/logger.error
- run_all_tickers: replaced asyncio.gather (swallows all progress) with
asyncio.as_completed + optional on_ticker_done(result, done, total)
callback; uses asyncio.Semaphore for max_concurrent control
- Added time and Callable imports
- cli/main.py run_pipeline:
- Replaced Live(Spinner) with Rich Progress bar (spinner + bar + counter
+ elapsed time)
- Prints '▷ Queued: TICKER' before analysis starts for each ticker
- on_ticker_done callback prints '✓ TICKER (N/M, Xs elapsed) → decision'
or '✗ TICKER failed ...' immediately as each ticker finishes
- Prints total elapsed time when all tickers complete
The pipeline was emitting hundreds of errors:
'Invalid number of return arguments after parsing column name: Date'
Root cause: after _clean_dataframe() lowercases all columns, stockstats.wrap()
promotes 'date' to the DataFrame index. Subsequent df['Date'] access caused
stockstats to try parsing 'Date' as a technical indicator name.
- stockstats_utils.py + y_finance.py: use df.index.strftime() instead of
df['Date'] after wrap()
- Eliminates duplicated 30-line download+cache boilerplate in two places
- Cache filename is always derived from today's date — hardcoded stale date
'2015-01-01-2025-03-25' in local mode is gone
- Corruption/truncation detection: files <50 rows or unparseable are deleted
and re-fetched rather than silently returning bad data
- Drops on_bad_lines='skip' — malformed CSVs now raise instead of silently
dropping rows that would distort indicator calculations
- Defined in stockstats_utils.py; raised instead of print()+return ''
- get_stockstats_indicator now raises YFinanceError on failure so errors
surface to callers rather than delivering empty strings to LLM agents
- interface.py route_to_vendor now catches YFinanceError alongside
AlphaVantageError and FinnhubError — failures appear in observability
telemetry and can trigger vendor fallback
- _filter_csv_by_date_range: replaced df.columns[0] positional assumption
with explicit search for 'time'/'timestamp'/'date' column
- ValueError re-raised (not swallowed) so bad API response shape is visible
- Replaced all print() calls in changed files with logging.getLogger()
- Added logging import + logger to alpha_vantage_common
- tests/unit/test_incident_fixes.py: 12 new unit tests covering all fixes
(dynamic cache filename, corruption re-fetch, YFinanceError propagation,
explicit column lookup, empty download raises)
- tests/integration/test_stockstats_live.py: 11 live tests against real
yfinance API (all major indicators, weekend N/A, regression guard)
- All 70 tests pass (59 unit + 11 live integration)
- y_finance.py: replace print() with logger.warning() in bulk-stats fallback
- macro_bridge.py: add elapsed_seconds field to TickerResult, populate in
run_ticker_analysis (success + error paths)
- cli/main.py: move inline 'import time as _time' and rich.progress imports
to module level; use result.elapsed_seconds for accurate per-ticker timing
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Agent-Logs-Url: https://github.com/aguzererler/TradingAgents/sessions/68fcf34c-8d55-4436-b743-f79fff68713f
Before this change, the pipeline showed a generic 'Analyzing...' spinner
for the entire multi-ticker run with no way to know which ticker was
processing or whether anything was actually working.
Changes:
- macro_bridge.py:
- run_ticker_analysis: logs '▶ Starting', '✓ complete in Xs', '✗ FAILED'
with elapsed time per ticker using logger.info/logger.error
- run_all_tickers: replaced asyncio.gather (swallows all progress) with
asyncio.as_completed + optional on_ticker_done(result, done, total)
callback; uses asyncio.Semaphore for max_concurrent control
- Added time and Callable imports
- cli/main.py run_pipeline:
- Replaced Live(Spinner) with Rich Progress bar (spinner + bar + counter
+ elapsed time)
- Prints '▷ Queued: TICKER' before analysis starts for each ticker
- on_ticker_done callback prints '✓ TICKER (N/M, Xs elapsed) → decision'
or '✗ TICKER failed ...' immediately as each ticker finishes
- Prints total elapsed time when all tickers complete
## Problem (Incident Post-mortem)
The pipeline was emitting hundreds of errors:
'Invalid number of return arguments after parsing column name: Date'
Root cause: after _clean_dataframe() lowercases all columns, stockstats.wrap()
promotes 'date' to the DataFrame index. Subsequent df['Date'] access caused
stockstats to try parsing 'Date' as a technical indicator name.
## Fixes
### 1. Fix df['Date'] stockstats bug (already shipped in prior commit)
- stockstats_utils.py + y_finance.py: use df.index.strftime() instead of
df['Date'] after wrap()
### 2. Extract _load_or_fetch_ohlcv() — single OHLCV authority
- Eliminates duplicated 30-line download+cache boilerplate in two places
- Cache filename is always derived from today's date — hardcoded stale date
'2015-01-01-2025-03-25' in local mode is gone
- Corruption/truncation detection: files <50 rows or unparseable are deleted
and re-fetched rather than silently returning bad data
- Drops on_bad_lines='skip' — malformed CSVs now raise instead of silently
dropping rows that would distort indicator calculations
### 3. YFinanceError typed exception
- Defined in stockstats_utils.py; raised instead of print()+return ''
- get_stockstats_indicator now raises YFinanceError on failure so errors
surface to callers rather than delivering empty strings to LLM agents
- interface.py route_to_vendor now catches YFinanceError alongside
AlphaVantageError and FinnhubError — failures appear in observability
telemetry and can trigger vendor fallback
### 4. Explicit date column discovery in alpha_vantage_common
- _filter_csv_by_date_range: replaced df.columns[0] positional assumption
with explicit search for 'time'/'timestamp'/'date' column
- ValueError re-raised (not swallowed) so bad API response shape is visible
### 5. Structured logging
- Replaced all print() calls in changed files with logging.getLogger()
- Added logging import + logger to alpha_vantage_common
## Tests
- tests/unit/test_incident_fixes.py: 12 new unit tests covering all fixes
(dynamic cache filename, corruption re-fetch, YFinanceError propagation,
explicit column lookup, empty download raises)
- tests/integration/test_stockstats_live.py: 11 live tests against real
yfinance API (all major indicators, weekend N/A, regression guard)
- All 70 tests pass (59 unit + 11 live integration)
- Removed unused `import time` from `tradingagents/agents/analysts/news_analyst.py`
- Verified file syntax with `py_compile`
- Confirmed that the import was successfully removed
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Implement comprehensive unit tests for the `_safe_fmt` utility function
to ensure robust handling of numeric formatting and edge cases.
- Test None values and custom fallbacks
- Test various numeric types (int, float, string)
- Test custom format strings
- Test error handling for invalid types
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Replaced the inefficient `iterrows()` loop with vectorized operations:
`df.set_index("Date")[indicator].fillna("N/A").astype(str).to_dict()`
This change improves performance while maintaining the exact original behavior for NaN values and string conversion.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Removed the unused `json` import in `tradingagents/agents/analysts/market_analyst.py` to reduce visual clutter and namespace pollution.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Adds a comprehensive test suite for the StatsCallbackHandler in cli/stats_handler.py,
covering call counting, token usage extraction, and thread safety.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
- Use `--file` instead of `--text` for adding sources to avoid ARG_MAX issues and argument injection.
- Add `--` separator to prevent positional arguments from being misinterpreted as flags.
- Reorder arguments to place options before positional ones.
- Update unit tests and add new security-focused tests.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Replaces the O(N) database operations in the `TradeExecutor`'s
`execute_decisions` SELL loop with a single `batch_remove_holdings`
call to the repository. The new repository method calculates updates
in memory, resolves duplicate operations on the same ticker, and issues
the updates via newly implemented `psycopg2.extras.execute_batch`
routines on the `SupabaseClient`.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>
Optimize the _percentile calculation to use heapq.nsmallest or heapq.nlargest when requesting small extreme percentiles (like 5% VaR) from large lists, falling back to sorted() only when necessary. This avoids fully sorting the entire array.
Co-authored-by: aguzererler <6199053+aguzererler@users.noreply.github.com>