mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-08-02 01:47:43 +00:00
feat: Improved LLM prompt + Optuna integration (Step 3+5)
Step 3 - LLM Prompt verbessert: - Created prompts/strategy_generation_v2.yaml - IC-guided factor selection instructions - |IC| > 0.10: PRIORITIZE, |IC| > 0.05: USE, |IC| < 0.05: AVOID - IC-weighted factor combinations - Better examples with IC weights - Added 'close' Series to available scope Step 5 - Optuna-Optimierung aktiviert: - Added use_optuna=True, optuna_trials=20 to __init__ - Integrated OptunaOptimizer in _generate_and_evaluate_single - Added _prepare_factor_values method for Optuna - Auto-optimizes accepted strategies with 20 trials - Updates results if Optuna improves Sharpe Test results (MomentumDivergenceZScore with forward-fill): - Status: accepted - Sharpe: 6.04 - Max DD: -1.57% - Win Rate: 49.19% - Ann Return: 21.88% - Periods: 823,450 (2.27 years) Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
@@ -32,6 +32,7 @@ import numpy as np
|
||||
import pandas as pd
|
||||
|
||||
from rdagent.components.prompt_loader import load_prompt
|
||||
from rdagent.components.coder.optuna_optimizer import OptunaOptimizer
|
||||
|
||||
# OHLCV data path
|
||||
OHLCV_PATH = Path(os.getenv(
|
||||
@@ -59,6 +60,8 @@ class StrategyOrchestrator:
|
||||
max_drawdown: float = -0.20,
|
||||
min_win_rate: float = 0.50,
|
||||
results_dir: Optional[str] = None,
|
||||
use_optuna: bool = True,
|
||||
optuna_trials: int = 20,
|
||||
):
|
||||
"""
|
||||
Parameters
|
||||
@@ -81,6 +84,8 @@ class StrategyOrchestrator:
|
||||
self.min_sharpe = min_sharpe
|
||||
self.max_drawdown = max_drawdown
|
||||
self.min_win_rate = min_win_rate
|
||||
self.use_optuna = use_optuna
|
||||
self.optuna_trials = optuna_trials
|
||||
|
||||
if results_dir is None:
|
||||
project_root = Path(__file__).parent.parent.parent.parent
|
||||
@@ -909,9 +914,42 @@ signal = signal.rolling(window=3, min_periods=1).mean().round().astype(int)
|
||||
# Evaluate
|
||||
result = self.evaluate_strategy(code, strategy_name, factors)
|
||||
result["code"] = code
|
||||
|
||||
|
||||
# Optimize with Optuna if enabled and accepted
|
||||
if result.get("status") == "accepted" and self.use_optuna:
|
||||
logger.info(f"Running Optuna optimization for {strategy_name}...")
|
||||
optimizer = OptunaOptimizer(n_trials=self.optuna_trials)
|
||||
|
||||
# Prepare factor values for optimization
|
||||
factor_values = self._prepare_factor_values(factors)
|
||||
|
||||
if factor_values is not None:
|
||||
optimized = optimizer.optimize_strategy(result, factor_values)
|
||||
if optimized.get("best_value", float('-inf')) > result.get("sharpe_ratio", 0):
|
||||
logger.info(f"Optuna improved {strategy_name}: {optimized.get('best_value', 0):.2f}")
|
||||
result.update(optimized)
|
||||
|
||||
return result
|
||||
|
||||
def _prepare_factor_values(self, factors: List[Dict]) -> Optional[pd.DataFrame]:
|
||||
"""Prepare factor values DataFrame for Optuna optimization."""
|
||||
factor_values = {}
|
||||
for f in factors:
|
||||
fname = f.get("factor_name", "")
|
||||
if fname:
|
||||
series = self.load_factor_values(fname)
|
||||
if series is not None:
|
||||
factor_values[fname] = series
|
||||
|
||||
if factor_values:
|
||||
df = pd.DataFrame(factor_values)
|
||||
# Forward-fill to OHLCV index
|
||||
close = self.load_ohlcv_close()
|
||||
if close is not None:
|
||||
df = df.reindex(close.index).ffill()
|
||||
return df.dropna()
|
||||
return None
|
||||
|
||||
def _save_strategy(self, result: Dict[str, Any]) -> None:
|
||||
"""Save accepted strategy to JSON file."""
|
||||
timestamp = int(time.time())
|
||||
|
||||
Reference in New Issue
Block a user