mirror of
https://github.com/NicolasBohn/NexQuant.git
synced 2026-08-01 01:27:42 +00:00
feat: R&D loop fixes + new price-action research loop
Loop 1 (Factor R&D): - Auto-fixer: composite normalization prevents single-factor variance collapse - Caps entry_thresh 0.7, exit_thresh 0.3, window 20, rolling smoothing 2 - Adds unit-variance normalization for any factor count Loop 2 (Price-Action R&D): - New research loop for technical indicators (no LLM, no Docker) - 7 indicators: MACD, Donchian, RSI, SMA, Bollinger, ATR, MA-Envelope - 3 strategy types: single-TF, multi-TF majority-vote, portfolio - Random hypothesis generation + backtest_signal evaluation - 11/20 strategies profitable in first test run - Top: MACD(12,15,3) 15min — Sharpe +14.01, +10.4%/month
This commit is contained in:
@@ -68,6 +68,7 @@ class FactorAutoFixer:
|
||||
self._fix_inf_nan_handling, # Tenth: add inf/nan handling
|
||||
self._fix_data_range_processing, # Eleventh: ensure full data range
|
||||
self._fix_multiindex_groupby, # Twelfth: ensure groupby on MultiIndex
|
||||
self._fix_composite_normalization, # Thirteenth: normalize thresholds + composite variance
|
||||
]
|
||||
|
||||
for fix_method in fix_methods:
|
||||
@@ -85,6 +86,24 @@ class FactorAutoFixer:
|
||||
|
||||
return fixed_code
|
||||
|
||||
def _fix_composite_normalization(self, code: str) -> str:
|
||||
"""Normalize strategy code: cap thresholds, limit windows, normalize composite."""
|
||||
code = re.sub(r'\bentry_thresh\s*=\s*([0-9.]+)',
|
||||
lambda m: f'entry_thresh = {min(float(m.group(1)), 0.7):.1f}', code)
|
||||
code = re.sub(r'\bexit_thresh\s*=\s*([0-9.]+)',
|
||||
lambda m: f'exit_thresh = {min(float(m.group(1)), 0.3):.1f}', code)
|
||||
code = re.sub(r'\bwindow\s*=\s*(\d+)',
|
||||
lambda m: f'window = {min(int(m.group(1)), 20)}', code)
|
||||
code = re.sub(r'(signal\s*=\s*signal\s*\.\s*rolling\s*\()(\d+)',
|
||||
lambda m: f'{m.group(1)}{min(int(m.group(2)), 2)}', code)
|
||||
if 'composite' in code and 'composite = (composite' not in code:
|
||||
code = re.sub(
|
||||
r'\n(signal\s*=\s*pd\.Series)',
|
||||
r'\ncomposite = (composite - composite.rolling(20).mean()) / (composite.rolling(20).std() + 1e-8)\n\n\1',
|
||||
code, count=1,
|
||||
)
|
||||
return code
|
||||
|
||||
def _fix_instrument_column_access(self, code: str) -> str:
|
||||
"""
|
||||
Fix: df['instrument'] raises KeyError on a MultiIndex DataFrame because
|
||||
|
||||
Reference in New Issue
Block a user