mirror of
https://github.com/Xe138/AI-Trader.git
synced 2026-04-02 01:27:24 -04:00
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.
135 lines
4.1 KiB
Python
135 lines
4.1 KiB
Python
"""
|
|
Runtime configuration manager for isolated model-day execution.
|
|
|
|
This module provides:
|
|
- Isolated runtime config file creation per model-day
|
|
- Prevention of state collisions between concurrent executions
|
|
- Automatic cleanup of temporary config files
|
|
"""
|
|
|
|
import os
|
|
import json
|
|
from pathlib import Path
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class RuntimeConfigManager:
|
|
"""
|
|
Manages isolated runtime configuration files for concurrent model execution.
|
|
|
|
Problem:
|
|
Multiple models running concurrently need separate runtime_env.json files
|
|
to avoid race conditions on TODAY_DATE, SIGNATURE, IF_TRADE values.
|
|
|
|
Solution:
|
|
Create temporary runtime config file per model-day execution:
|
|
- /app/data/runtime_env_{job_id}_{model}_{date}.json
|
|
|
|
Lifecycle:
|
|
1. create_runtime_config() → Creates temp file
|
|
2. Executor sets RUNTIME_ENV_PATH env var
|
|
3. Agent uses isolated config via get_config_value/write_config_value
|
|
4. cleanup_runtime_config() → Deletes temp file
|
|
"""
|
|
|
|
def __init__(self, data_dir: str = "data"):
|
|
"""
|
|
Initialize RuntimeConfigManager.
|
|
|
|
Args:
|
|
data_dir: Directory for runtime config files (default: "data")
|
|
"""
|
|
self.data_dir = Path(data_dir)
|
|
self.data_dir.mkdir(parents=True, exist_ok=True)
|
|
|
|
def create_runtime_config(
|
|
self,
|
|
job_id: str,
|
|
model_sig: str,
|
|
date: str,
|
|
trading_day_id: int = None
|
|
) -> str:
|
|
"""
|
|
Create isolated runtime config file for this execution.
|
|
|
|
Args:
|
|
job_id: Job UUID
|
|
model_sig: Model signature
|
|
date: Trading date (YYYY-MM-DD)
|
|
trading_day_id: Trading day record ID (optional, can be set later)
|
|
|
|
Returns:
|
|
Path to created runtime config file
|
|
|
|
Example:
|
|
config_path = manager.create_runtime_config(
|
|
"abc123...",
|
|
"gpt-5",
|
|
"2025-01-16"
|
|
)
|
|
# Returns: "data/runtime_env_abc123_gpt-5_2025-01-16.json"
|
|
"""
|
|
# Generate unique filename (use first 8 chars of job_id for brevity)
|
|
job_id_short = job_id[:8] if len(job_id) > 8 else job_id
|
|
filename = f"runtime_env_{job_id_short}_{model_sig}_{date}.json"
|
|
config_path = self.data_dir / filename
|
|
|
|
# Initialize with default values
|
|
initial_config = {
|
|
"TODAY_DATE": date,
|
|
"SIGNATURE": model_sig,
|
|
"IF_TRADE": False,
|
|
"JOB_ID": job_id,
|
|
"TRADING_DAY_ID": trading_day_id
|
|
}
|
|
|
|
with open(config_path, "w", encoding="utf-8") as f:
|
|
json.dump(initial_config, f, indent=4)
|
|
|
|
logger.debug(f"Created runtime config: {config_path}")
|
|
return str(config_path)
|
|
|
|
def cleanup_runtime_config(self, config_path: str) -> None:
|
|
"""
|
|
Delete runtime config file after execution.
|
|
|
|
Args:
|
|
config_path: Path to runtime config file
|
|
|
|
Note:
|
|
Silently ignores if file doesn't exist (already cleaned up)
|
|
"""
|
|
try:
|
|
if os.path.exists(config_path):
|
|
os.unlink(config_path)
|
|
logger.debug(f"Cleaned up runtime config: {config_path}")
|
|
except Exception as e:
|
|
logger.warning(f"Failed to cleanup runtime config {config_path}: {e}")
|
|
|
|
def cleanup_all_runtime_configs(self) -> int:
|
|
"""
|
|
Cleanup all runtime config files (for maintenance/startup).
|
|
|
|
Returns:
|
|
Number of files deleted
|
|
|
|
Use case:
|
|
- On API startup to clean stale configs from previous runs
|
|
- Periodic maintenance
|
|
"""
|
|
count = 0
|
|
for config_file in self.data_dir.glob("runtime_env_*.json"):
|
|
try:
|
|
config_file.unlink()
|
|
count += 1
|
|
logger.debug(f"Deleted stale runtime config: {config_file}")
|
|
except Exception as e:
|
|
logger.warning(f"Failed to delete {config_file}: {e}")
|
|
|
|
if count > 0:
|
|
logger.info(f"Cleaned up {count} stale runtime config files")
|
|
|
|
return count
|