Changed action_type from 'init' to 'no_trade' in _initialize_starting_position()
to comply with database CHECK constraint that only allows 'buy', 'sell', or 'no_trade'.
Fixes sqlite3.IntegrityError during position initialization.
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.
Add proper exception handling around get_latest_position() calls in both
buy() and sell() functions. Previously, exceptions were caught but code
continued execution with undefined variables, causing "variable referenced
before assignment" errors.
Now returns error dict with context when position lookup fails.
Related to context injection implementation for concurrent simulations.
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
4 changed files with 379 additions and 177 deletions
# Check if cash balance is sufficient for purchase
ifcash_left<0:
# Insufficient cash, return error message
return{"error":"Insufficient cash! This action will not be allowed.","required_cash":this_symbol_price*amount,"cash_available":current_position.get("CASH",0),"symbol":symbol,"date":today_date}
else:
# Step 5: Execute buy operation, update position
# Create a copy of current position to avoid directly modifying original data
# Write JSON format transaction record, containing date, operation ID, transaction details and updated position
print(f"Writing to position.jsonl: {json.dumps({'date':today_date,'id':current_action_id+1,'this_action':{'action':'buy','symbol':symbol,'amount':amount},'positions':new_position})}")
return{"error":f"No position for {symbol}! This action will not be allowed.","symbol":symbol,"date":today_date}
# Step 2: Validate position exists
ifsymbolnotincurrent_position:
return{"error":f"No position for {symbol}","symbol":symbol,"date":today_date}
# Check if position quantity is sufficient for selling
ifcurrent_position[symbol]<amount:
return{"error":"Insufficient shares! This action will not be allowed.","have":current_position.get(symbol,0),"want_to_sell":amount,"symbol":symbol,"date":today_date}
ifcurrent_position[symbol]<amount:
return{
"error":"Insufficient shares",
"have":current_position[symbol],
"want_to_sell":amount,
"symbol":symbol,
"date":today_date
}
# Step 5: Execute sell operation, update position
# Create a copy of current position to avoid directly modifying original data
# Write JSON format transaction record, containing date, operation ID and updated position
print(f"Writing to position.jsonl: {json.dumps({'date':today_date,'id':current_action_id+1,'this_action':{'action':'sell','symbol':symbol,'amount':amount},'positions':new_position})}")
logger.info(f"Initialized starting position for {self.model_sig} with ${initial_cash}")
asyncdef_store_reasoning_logs(
self,
cursor,
Reference in New Issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.