fix: 15 bug fixes across orchestrator, runner, backtest, and infrastructure

Critical:
- strategy_orchestrator: fix IndentationError that prevented import (line 764)
- factor_runner: fix literal 'sys.executable' string → variable (line 966)

High (path bugs causing wrong directories):
- backtest_engine: fix results_path depth (3→4 .parent hops)
- results_db: fix factors_dir/failed_dir depth (3→4 .parent hops)
- factor_runner: eliminate run_id variable shadowing (parallel_run_id/db_run_id)
- model_runner: fix DB connection leak on add_backtest exception
- optuna_optimizer: fix imported logger shadowed by module-level reassignment

Medium:
- env: handle non-UTF-8 Docker build output with errors='replace'
- env: guard conda env list parsing against empty lines
- factor_runner: add check=False + stderr logging for full-data subprocess
- strategy_orchestrator: log exec() exceptions at ERROR level with traceback
- strategy_orchestrator: warn on unreplaced {{template}} variables in prompts

Low:
- factor_runner: guard IC_max.index access against scalar (AttributeError)
- predix_parallel: close log file handle on Popen failure
- predix_rebacktest_strategies: replace 4 bare except: with except Exception:
This commit is contained in:
TPTBusiness
2026-05-03 09:37:00 +02:00
parent 571c902c2d
commit 5bf84ff835
10 changed files with 348 additions and 38 deletions
+1 -1
View File
@@ -23,7 +23,7 @@ import pandas as pd
from rdagent.log import rdagent_logger as logger
logger = logging.getLogger(__name__)
_optuna_logger = logging.getLogger(__name__)
try:
import optuna
@@ -337,6 +337,12 @@ class StrategyOrchestrator:
user_prompt = user_prompt.replace("{{ additional_context }}", f"Strategy name: {strategy_name}")
user_prompt = user_prompt.replace("{{ trading_style }}", self.trading_style)
user_prompt = user_prompt.replace("{{ min_sharpe }}", str(self.min_sharpe))
if "{{" in user_prompt:
unreplaced = [w for w in user_prompt.split() if "{{" in w]
logger.warning(
f"Unreplaced template variables in prompt for '{strategy_name}': {unreplaced}"
)
user_prompt = user_prompt.replace("{{ max_drawdown }}", str(self.max_drawdown))
system_prompt = self.strategy_prompt.get("system", "")
else:
@@ -758,11 +764,11 @@ signal = signal.rolling(window=3, min_periods=1).mean().round().astype(int)
common_idx = common_idx.intersection(s.index)
if common_idx is not None and len(common_idx) > 100:
df_factors = pd.DataFrame({
name: s.reindex(common_idx) for name, s in factor_values.items()
}).dropna()
else:
df_factors = pd.DataFrame()
df_factors = pd.DataFrame({
name: s.reindex(common_idx) for name, s in factor_values.items()
}).dropna()
else:
df_factors = pd.DataFrame()
if len(df_factors) < 100:
return {
@@ -816,6 +822,11 @@ signal = signal.rolling(window=3, min_periods=1).mean().round().astype(int)
try:
exec(strategy_code, {"np": np, "pd": pd, "numpy": np}, local_vars)
except Exception as e:
import traceback
logger.error(
f"Strategy code execution failed for '{strategy_name}': {e}\n"
f"{traceback.format_exc()[-2000:]}"
)
return {
"strategy_name": strategy_name,
"status": "rejected",