Commit Graph

27 Commits

Author SHA1 Message Date
7c71a047bc fix: update position queries to use new trading_days schema
Changes:
- Update get_today_init_position_from_db to query trading_days table
- Remove obsolete add_no_trade_record_to_db calls from BaseAgent
- Simplify _handle_trading_result (trading_day record handles both scenarios)

Root Cause:
- Code was still querying old positions table after schema migration
- The add_no_trade_record_to_db function is obsolete in new schema

New Schema Behavior:
- trading_day record created at session start (regardless of trading)
- trading_day record updated at session end with final results
- No separate "no-trade" record needed

Impact:
- Fixes: "no such table: positions" error in get_today_init_position_from_db
- Removes unnecessary database writes for no-trade scenarios
- Simplifies codebase by removing obsolete function calls

Related: tools/price_tools.py:340-364, agent/base_agent/base_agent.py:661-673
2025-11-04 22:49:01 -05:00
e7fe0ab51b fix: add TRADING_DAY_ID write to runtime config and improve test coverage
Changes:
- Write TRADING_DAY_ID to runtime config after creating trading_day record in BaseAgent
- Fix datetime deprecation warnings by replacing datetime.utcnow() with datetime.now(timezone.utc)
- Add test for trading_day_id=None fallback path to verify runtime config lookup works correctly

This ensures trade tools can access trading_day_id from runtime config when not explicitly passed.
2025-11-04 09:32:07 -05:00
7d9d093d6c feat: migrate trade tools to write to actions table (new schema)
This commit implements Task 1 from the schema migration plan:
- Trade tools (buy/sell) now write to actions table instead of old positions table
- Added trading_day_id parameter to buy/sell functions
- Updated ContextInjector to inject trading_day_id
- Updated RuntimeConfigManager to include TRADING_DAY_ID in config
- Removed P&L calculation from trade functions (now done at trading_days level)
- Added tests verifying correct behavior with new schema

Changes:
- agent_tools/tool_trade.py: Modified _buy_impl and _sell_impl to write to actions table
- agent/context_injector.py: Added trading_day_id parameter and injection logic
- api/model_day_executor.py: Updated to read trading_day_id from runtime config
- api/runtime_manager.py: Added trading_day_id to config initialization
- tests/unit/test_trade_tools_new_schema.py: New tests for new schema compliance

All tests passing.
2025-11-04 09:18:35 -05:00
f770a2fe84 fix: resolve critical integration issues in BaseAgent P&L calculation
Critical fixes:
1. Fixed api/database.py import - use get_db_path() instead of non-existent get_database_path()
2. Fixed state management - use database queries instead of reading from position.jsonl file
3. Fixed action counting - track during trading loop execution instead of retroactively from conversation history
4. Completed integration test to verify P&L calculation works correctly

Changes:
- agent/base_agent/base_agent.py:
  * Updated _get_current_portfolio_state() to query database via get_current_position_from_db()
  * Added today_date and job_id parameters to method signature
  * Count trade actions during trading loop instead of post-processing conversation history
  * Removed obsolete action counting logic

- api/database.py:
  * Fixed import to use get_db_path() from deployment_config
  * Pass correct default database path "data/trading.db"

- tests/integration/test_agent_pnl_integration.py:
  * Added proper mocks for dev mode and MCP client
  * Mocked get_current_position_from_db to return test data
  * Added comprehensive assertions to verify trading_day record fields
  * Test now actually validates P&L calculation integration

Test results:
- All unit tests passing (252 passed)
- All P&L integration tests passing (8 passed)
- No regressions detected
2025-11-03 23:34:10 -05:00
cd7e056120 feat: integrate P&L calculation and reasoning summary into BaseAgent
This implements Task 5 from the daily P&L results API refactor plan, bringing
together P&L calculation and reasoning summary into the BaseAgent trading session.

Changes:
- Add DailyPnLCalculator and ReasoningSummarizer to BaseAgent.__init__
- Modify run_trading_session() to:
  * Calculate P&L at start of day using current market prices
  * Create trading_day record with P&L metrics
  * Generate reasoning summary after trading using AI model
  * Save final holdings to database
  * Update trading_day with completion data (cash, portfolio value, summary, actions)
- Add helper methods:
  * _get_current_prices() - Get market prices for P&L calculation
  * _get_current_portfolio_state() - Read current state from position.jsonl
  * _calculate_portfolio_value() - Calculate total portfolio value

Integration test verifies:
- P&L calculation components exist and are importable
- DailyPnLCalculator correctly calculates zero P&L on first day
- ReasoningSummarizer can be instantiated with AI model

This maintains backward compatibility with position.jsonl while adding
comprehensive database tracking for the new results API.

Generated with Claude Code

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 23:24:00 -05:00
197d3b7bf9 feat: add AI reasoning summary generator with fallback
- Implement ReasoningSummarizer class for generating 2-3 sentence AI summaries
- Add fallback to statistical summary when AI generation fails
- Format reasoning logs for summary prompt with truncation
- Handle empty reasoning logs with default message
- Add comprehensive unit tests with async mocking
2025-11-03 23:16:15 -05:00
5c19410f71 feat: add daily P&L calculator with weekend gap handling
Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-03 23:12:49 -05:00
6c395f740d fix: always override context parameters in ContextInjector
Root cause: AI models were hallucinating signature/job_id/today_date values
and passing them in tool calls. The ContextInjector was checking
"if param not in request.args" before injecting, which failed when AI
provided (incorrect) values.

Fix: Always override context parameters, never trust AI-provided values.

Evidence from logs:
- ContextInjector had correct values (self.signature=gpt-5, job_id=6dabd9e6...)
- But AI was passing signature=None or hallucinated values like "fundamental-bot-v1"
- After injection, args showed the AI's (wrong) values, not the interceptor's

This ensures runtime context is ALWAYS injected regardless of what the AI sends.

Fixes #TBD
2025-11-02 23:30:49 -05:00
618943b278 debug: add self attribute logging to ContextInjector.__call__
Log ContextInjector instance ID and attribute values at entry to __call__()
to diagnose why attributes appear as None during tool invocation despite
being set correctly during set_context().

This will reveal whether:
- Multiple ContextInjector instances exist
- Attributes are being overwritten/cleared
- Wrong instance is being invoked
2025-11-02 23:17:52 -05:00
1c19eea29a debug: add comprehensive diagnostic logging for ContextInjector flow
Add instrumentation at component boundaries to trace where ContextInjector values become None:
- ModelDayExecutor: Log ContextInjector creation and set_context() invocation
- BaseAgent.set_context(): Log entry, client creation, tool reload, completion
- Includes object IDs to verify instance identity across boundaries

Part of systematic debugging investigation for issue #TBD.
2025-11-02 23:05:40 -05:00
e968434062 fix: reload tools after context injection and prevent database locking
Critical fixes for ContextInjector and database concurrency:

1. ContextInjector Not Working:
   - Made set_context() async to reload tools after recreating MCP client
   - Tools from old client (without interceptor) were still being used
   - Now tools are reloaded from new client with interceptor active
   - This ensures buy/sell calls properly receive injected parameters

2. Database Locking:
   - Closed main connection before _write_results_to_db() opens new one
   - SQLite doesn't handle concurrent write connections well
   - Prevents "database is locked" error during position writes

Changes:
- agent/base_agent/base_agent.py:
  - async def set_context() instead of def set_context()
  - Added: self.tools = await self.client.get_tools()
- api/model_day_executor.py:
  - await agent.set_context(context_injector)
  - conn.close() before _write_results_to_db()

Root Cause:
When recreating the MCP client with tool_interceptors, the old tools
were still cached in self.tools and being passed to the AI agent.
The interceptor was never invoked, so job_id/signature/date were missing.
2025-11-02 22:42:17 -05:00
027b4bd8e4 refactor: implement database-only position tracking with lazy context injection
This commit migrates the system to database-only position storage,
eliminating file-based position.jsonl dependencies and fixing
ContextInjector initialization timing issues.

Key Changes:

1. ContextInjector Lifecycle Refactor:
   - Remove ContextInjector creation from BaseAgent.__init__()
   - Add BaseAgent.set_context() method for post-initialization injection
   - Update ModelDayExecutor to create ContextInjector with correct trading day date
   - Ensures ContextInjector receives actual trading date instead of init_date
   - Includes session_id injection for proper database linking

2. Database Position Functions:
   - Implement get_today_init_position_from_db() for querying previous positions
   - Implement add_no_trade_record_to_db() for no-trade day handling
   - Both functions query SQLite directly (positions + holdings tables)
   - Handle first trading day case with initial cash return
   - Include comprehensive error handling and logging

3. System Integration:
   - Update get_agent_system_prompt() to use database queries
   - Update _handle_trading_result() to write no-trade records to database
   - Remove dependencies on position.jsonl file reading/writing
   - Use deployment_config for automatic prod/dev database resolution

Data Flow:
- ModelDayExecutor creates runtime config and trading session
- Agent initialized without context
- ContextInjector created with (signature, date, job_id, session_id)
- Context injected via set_context()
- System prompt queries database for yesterday's position
- Trade tools write directly to database
- No-trade handler creates database records

Fixes:
- ContextInjector no longer receives None values
- No FileNotFoundError for missing position.jsonl files
- Database is single source of truth for position tracking
- Session linking maintained across all position records

Design: docs/plans/2025-02-11-database-position-tracking-design.md
2025-11-02 22:20:01 -05:00
019c84fca8 refactor: migrate trade tools from file-based to SQLite position storage
Complete rewrite of position management in MCP trade tools:

**Trade Tools (agent_tools/tool_trade.py)**
- Replace file-based position.jsonl reads with SQLite queries
- Add get_current_position_from_db() to query positions and holdings tables
- Rewrite buy() and sell() to write directly to database
- Calculate portfolio value and P&L metrics in tools
- Accept job_id and session_id parameters via ContextInjector
- Return errors with proper context for debugging
- Use deployment-aware database path resolution

**Context Injection (agent/context_injector.py)**
- Add job_id and session_id to constructor
- Inject job_id and session_id into buy/sell tool calls
- Support optional parameters (None in standalone mode)

**BaseAgent (agent/base_agent/base_agent.py)**
- Read JOB_ID from runtime config
- Pass job_id to ContextInjector during initialization
- Enable automatic context injection for API mode

**ModelDayExecutor (api/model_day_executor.py)**
- Add _initialize_starting_position() method
- Create initial position record before agent runs
- Load initial_cash from config
- Update context_injector.session_id after session creation
- Link positions to sessions automatically

**Architecture Changes:**
- Eliminates file-based position tracking entirely
- Single source of truth: SQLite database
- Positions automatically linked to trading sessions
- Concurrent execution safe (no file system conflicts)
- Deployment mode aware (prod vs dev databases)

This completes the migration to database-only position storage.
File-based position.jsonl is no longer used or created.

Fixes context injection errors in concurrent simulations.
2025-11-02 21:36:57 -05:00
bf12e981fe debug: add logging to trace parameter injection 2025-11-02 20:29:35 -05:00
a16bac5d08 fix: use 'args' instead of 'arguments' in MCPToolCallRequest
MCPToolCallRequest has 'args' attribute, not 'arguments'. Fixed
attribute name to match the actual API.
2025-11-02 20:21:43 -05:00
81b92e293a fix: make ContextInjector async to match ToolCallInterceptor protocol
The interceptor __call__ method must be async and follow the proper
signature: async __call__(request, handler) -> result

Previous implementation was synchronous and had wrong signature, causing
'object function can't be used in await expression' error.
2025-11-02 20:11:20 -05:00
b1b486dcc4 fix: inject signature and today_date into trade tool calls for concurrent simulations
Resolves issue where MCP trade tools couldn't access SIGNATURE and TODAY_DATE
during concurrent API simulations, causing "SIGNATURE environment variable is
not set" errors.

Problem:
- MCP services run as separate HTTP processes
- Multiple simulations execute concurrently via ThreadPoolExecutor
- Environment variables from executor process not accessible to MCP services

Solution:
- Add ContextInjector that implements ToolCallInterceptor
- Automatically injects signature and today_date into buy/sell tool calls
- Trade tools accept optional parameters, falling back to config/env
- BaseAgent creates interceptor and updates today_date per session

Changes:
- agent/context_injector.py: New interceptor for context injection
- agent/base_agent/base_agent.py: Create and use ContextInjector
- agent_tools/tool_trade.py: Add optional signature/today_date parameters

Benefits:
- Supports concurrent multi-model simulations
- Maintains backward compatibility with CLI mode
- AI model unaware of injected parameters
2025-11-02 20:01:32 -05:00
2f05418f42 refactor: remove JSONL logging code from BaseAgent
- Remove _log_message() and _setup_logging() methods
- Remove all calls to logging methods in run_trading_session()
- Update log_path parameter docstring for clarity
- Update integration test to verify conversation history instead of JSONL files
- Reasoning logs now stored exclusively in database via model_day_executor
- Conversation history tracking preserved in memory

Related: Task 6 of reasoning logs API feature
2025-11-02 18:16:06 -05:00
f83e4caf41 feat: add AI-powered summary generation to BaseAgent 2025-11-02 17:59:56 -05:00
837504aa17 feat: add conversation history tracking to BaseAgent
- Add conversation_history instance variable to BaseAgent.__init__
- Create _capture_message() method to capture messages with timestamps
- Create get_conversation_history() method to retrieve conversation
- Create clear_conversation_history() method to reset history
- Modify run_trading_session() to capture user prompts and AI responses
- Add comprehensive unit tests for conversation tracking
- Fix datetime deprecation warning by using timezone-aware datetime

All tests pass successfully.
2025-11-02 17:55:05 -05:00
b09e1b0b11 feat: integrate mock AI provider in BaseAgent for DEV mode
Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 11:25:49 -04:00
ab085e5545 fix: suppress unused parameter warnings in mock LangChain model 2025-11-01 11:16:51 -04:00
9ffd42481a feat: add LangChain-compatible mock chat model wrapper
🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-01 11:15:59 -04:00
b6867c9c16 feat: add mock AI provider for dev mode with stock rotation 2025-11-01 11:07:46 -04:00
Mirza Samad
3e9cd5f35b changes 2025-10-29 09:42:37 +03:00
tianyufan
eaf9379c21 support multi url and key 2025-10-27 21:37:46 +08:00
tianyufan
df5c25c98d init update 2025-10-24 00:35:21 +08:00