diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 049ecf4f..41689d51 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1 +1 @@ -{".": "1.5.0"} +{".":"0.8.0"} diff --git a/CHANGELOG.md b/CHANGELOG.md index 5917c550..297d394c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,360 @@ # Changelog +## [0.8.0](https://github.com/TPTBusiness/NexQuant/compare/v1.5.0...v0.8.0) (2026-05-30) + + +### Features + +* [AutoRL-Bench] Update DeepSearchQA split and translate task instructions to English ([#1368](https://github.com/TPTBusiness/NexQuant/issues/1368)) ([ffb9491](https://github.com/TPTBusiness/NexQuant/commit/ffb9491c4703290a5b292baa6328ae06bc520f9b)) +* 15% monthly return target — infrastructure + daily signal resampling ([ea0c94f](https://github.com/TPTBusiness/NexQuant/commit/ea0c94fef6f83b9bbfc2d5fa7c64750d74ea313f)) +* 1h London session momentum — +3.17%/month unlevered, -1.1% DD, RiskMgmt-safe ([49c3e7f](https://github.com/TPTBusiness/NexQuant/commit/49c3e7fd1e76edaed354cbf61effad724daa5317)) +* 1h SMA10/30 signal integrated into RiskMgmt live trader ([314a278](https://github.com/TPTBusiness/NexQuant/commit/314a278e503ebc65f4d013a161e352a20a7d1b7d)) +* 30min factor combo bests 1h — +3.59%/month (+54% annual) ([9c35dae](https://github.com/TPTBusiness/NexQuant/commit/9c35daef2b77da4b29f5ed42bf99db8971f25b8b)) +* 9 additional daily strategies — ensembles, trailing stops, day filters ([376622d](https://github.com/TPTBusiness/NexQuant/commit/376622db6c472389e2fcb7b4ad3e1e0bdd8f92f0)) +* Add 'predix evaluate' command to CLI ([da3bef6](https://github.com/TPTBusiness/NexQuant/commit/da3bef679714b58fcd1106d5c816efe9de99dc45)) +* Add 'predix top' command + explain factor evaluation results ([f2d2c6c](https://github.com/TPTBusiness/NexQuant/commit/f2d2c6c6d1b893a59de1b77d897e3e87b6e91240)) +* Add 6 new CLI commands - all scripts integrated with local LLM ([a712a3d](https://github.com/TPTBusiness/NexQuant/commit/a712a3d89482da7bfacc3951f867d8073af6a5a1)) +* add a rag mcp in proposal ([#1267](https://github.com/TPTBusiness/NexQuant/issues/1267)) ([dc7b732](https://github.com/TPTBusiness/NexQuant/commit/dc7b732b2c428e3cca3373e839a0e724a844c79b)) +* add a web UI server ([#1345](https://github.com/TPTBusiness/NexQuant/issues/1345)) ([1439548](https://github.com/TPTBusiness/NexQuant/commit/14395488b9c7ea476022a32211ea46de9925cf11)) +* Add advanced ML models (Transformer, TCN, PatchTST, CNN+LSTM) ([e1e86e1](https://github.com/TPTBusiness/NexQuant/commit/e1e86e1bd322b635c541be7fbacd18bc83fa4357)) +* Add AI Strategy Builder (StrategyCoSTEER) - Closed Source ([a5815bb](https://github.com/TPTBusiness/NexQuant/commit/a5815bbf3c9eb599bbab2f77369d6f11d8ed419c)) +* Add beautiful CLI welcome screen for GitHub README ([e6e5b1a](https://github.com/TPTBusiness/NexQuant/commit/e6e5b1a36b166ee0b8f91d480078577ab3532225)) +* Add CLI model selection (local vs OpenRouter) ([5ab4db5](https://github.com/TPTBusiness/NexQuant/commit/5ab4db5d04f8ddae53eee09b0f60d27c6a4669f6)) +* Add complete ML pipeline with graceful degradation (closed source) ([5a3ee7e](https://github.com/TPTBusiness/NexQuant/commit/5a3ee7e6942063aa31a880d45bc04b3b54a6341b)) +* add daily log rotation, llama health wait, factor auto-fixer, and README updates ([d2388d6](https://github.com/TPTBusiness/NexQuant/commit/d2388d6e99aac47f6cd61d5943397ad5dedb0fa1)) +* Add factor code and description to saved results ([a07b5f5](https://github.com/TPTBusiness/NexQuant/commit/a07b5f52e13f42e6a3749b792e988f716c7c2e0e)) +* Add GitHub infrastructure, CI/CD pipelines, and examples ([7fedccb](https://github.com/TPTBusiness/NexQuant/commit/7fedccb912e295107e871e4518226422ddf12b9c)) +* add improve_mode to MultiProcessEvolvingStrategy for selective task implementation ([#1273](https://github.com/TPTBusiness/NexQuant/issues/1273)) ([03f22dc](https://github.com/TPTBusiness/NexQuant/commit/03f22dc7c72a039ee6f1a0e8d0393f35117ec3e1)) +* Add improved local prompt with MultiIndex code examples (v3) ([3f2398a](https://github.com/TPTBusiness/NexQuant/commit/3f2398a717b7e287e06d08148ac072f776711c2d)) +* add Kronos CLI commands, expand tests, document in README ([0fde3e1](https://github.com/TPTBusiness/NexQuant/commit/0fde3e114171e92b1bb44fc131ec9f113512775e)) +* add LLM-finetune scenario ([#1314](https://github.com/TPTBusiness/NexQuant/issues/1314)) ([6e19c9e](https://github.com/TPTBusiness/NexQuant/commit/6e19c9e632cf07059c19993f2d4fbc772fb3cf13)) +* Add model loader system (same as prompts) ([19855ef](https://github.com/TPTBusiness/NexQuant/commit/19855ef7d690fca05415212669c1342f999d458e)) +* Add P5 ML Training Pipeline with LightGBM and 46 tests ([59f150a](https://github.com/TPTBusiness/NexQuant/commit/59f150a3cfbf3df794777a1bb373915020568d43)) +* Add parallel run system with API key distribution ([88577e2](https://github.com/TPTBusiness/NexQuant/commit/88577e24e20572af6e336a9240e77d6159e1a97e)) +* Add RL Trading Agent system with 99 tests ([faecbec](https://github.com/TPTBusiness/NexQuant/commit/faecbec6a52a5bcd694a769b3da522654b13b6b3)) +* add runtime backtest verification (10 invariant checks in <1ms) + 489 tests + README docs ([9e0a416](https://github.com/TPTBusiness/NexQuant/commit/9e0a4169ee4c0a3458a376f683f1d74b1c725df6)) +* Add simple factor evaluator with direct IC/Sharpe computation ([0d6537c](https://github.com/TPTBusiness/NexQuant/commit/0d6537c3a7c539f14702fc714079773ef12a608e)) +* Add start_llama and start_loop CLI commands ([4e32d4d](https://github.com/TPTBusiness/NexQuant/commit/4e32d4d104ddead4bd69539a89ddded3b60c984e)) +* add stdout into workspace for easier debugging ([#1236](https://github.com/TPTBusiness/NexQuant/issues/1236)) ([0daeb82](https://github.com/TPTBusiness/NexQuant/commit/0daeb82d6330e46edfeedc6b704b1a1c01d1a111)) +* Add Trading Protection System with 4 protections + comprehensive tests ([3cfb524](https://github.com/TPTBusiness/NexQuant/commit/3cfb5241d8105ebe1f598cc6869c4d2e4462e53e)) +* add user interaction in data science scenario ([#1251](https://github.com/TPTBusiness/NexQuant/issues/1251)) ([6e09dc6](https://github.com/TPTBusiness/NexQuant/commit/6e09dc6d692f3ae2fcc0ffddf620e8f3e8dc1bd9)) +* auto-mode live strategy — factors when fresh, SMA fallback ([63abdc7](https://github.com/TPTBusiness/NexQuant/commit/63abdc749e5b5a428eb6018f52c112615ae75ef7)) +* auto-post releases to Mastodon and X/Twitter via GitHub Actions ([68c0921](https://github.com/TPTBusiness/NexQuant/commit/68c092192f372a4e2119140429ad732f7674a5f2)) +* Auto-start dashboard for fin_quant ([3441604](https://github.com/TPTBusiness/NexQuant/commit/34416041c122b6a51ce94db1031f315c3639a4a5)) +* Auto-start dashboard for fin_quant ([52d2b89](https://github.com/TPTBusiness/NexQuant/commit/52d2b8914815fa97d6b53b7cc7e817828520817e)) +* **backtest:** add RiskMgmt-realistic backtest mode with leverage, daily/total loss limits and realistic EUR/USD costs ([b76330f](https://github.com/TPTBusiness/NexQuant/commit/b76330f43b5bf3a0cfdcc55bf7e700126af5edb7)) +* **backtest:** add rolling walk-forward validation and Monte Carlo trade permutation test ([0f26020](https://github.com/TPTBusiness/NexQuant/commit/0f260203b182f0160b88de1b506da9b382b4deff)) +* **backtest:** add walk-forward OOS validation to backtest_signal_riskmgmt ([3d3866f](https://github.com/TPTBusiness/NexQuant/commit/3d3866f8310cbbfbd9220c33807d959f3e4f8ce0)) +* Backtesting Engine + Risk Management + Results Database ([8339be2](https://github.com/TPTBusiness/NexQuant/commit/8339be2098eea8a99381ea983a6b64306fa02208)) +* Backtesting Engine + Risk Management + Results DB ([4690b01](https://github.com/TPTBusiness/NexQuant/commit/4690b01042a398234d0adb2c215cf975b6a24147)) +* **backtest:** use backtest_signal_riskmgmt in strategy orchestrator and optuna optimizer ([986eeeb](https://github.com/TPTBusiness/NexQuant/commit/986eeeb61ae620ce53f65490f0f099c7561062ad)) +* Beautiful CLI dashboard + corrected start command ([c2932cb](https://github.com/TPTBusiness/NexQuant/commit/c2932cb06904b041e1376d534309864d9d0e9122)) +* Centralize all prompts in prompts/ directory ([18416da](https://github.com/TPTBusiness/NexQuant/commit/18416da2c9aaf36211e3fa22a11fb1e5fe89a85a)) +* CLI Commands for strategy generation (P4 complete) ([bad98b6](https://github.com/TPTBusiness/NexQuant/commit/bad98b622c454d530cec56327f1a8dbb1d2578c4)) +* Complete P6-P9 implementation (73 tests) ([c1c249d](https://github.com/TPTBusiness/NexQuant/commit/c1c249d2713aaa8e48503d5f1db46ac71e9e6ae0)) +* continuous strategy generator (WF, MTF, stability, ML models, auto-ensemble) ([d00426b](https://github.com/TPTBusiness/NexQuant/commit/d00426baa8bdb1292840ec2f87df6917fcaf2e1f)) +* daily strategy generator — grid search SMA/EMA/RSI/MACD/BB (14/55 profitable) ([fbcd0b6](https://github.com/TPTBusiness/NexQuant/commit/fbcd0b62cb4a1f81276e9c35fc989933f8e63ef7)) +* Data Loader module with tests (P0 complete) ([440aba5](https://github.com/TPTBusiness/NexQuant/commit/440aba5c9ebfc0663fd0c8a22f2cf37cc8ecc015)) +* Diverse factor selection + improved prompt v3 ([e293f6c](https://github.com/TPTBusiness/NexQuant/commit/e293f6c296ffd954cbe0342c28f2dfeec00e05d7)) +* enable walk-forward OOS validation by default in backtest_signal_riskmgmt ([a6e6f35](https://github.com/TPTBusiness/NexQuant/commit/a6e6f35dee9bd84841810619621face206688697)) +* EURUSD FX patches - prompts, factor spec, experiment settings ([b6cf687](https://github.com/TPTBusiness/NexQuant/commit/b6cf6874db995ea160457a1628a5691cbc8e5b97)) +* EURUSD model experiment setting + model simulator text patched ([9a17b25](https://github.com/TPTBusiness/NexQuant/commit/9a17b25d32729453a28dd36246be4c5fdbd3a667)) +* EURUSD Trading-Verbesserungen (Phase 2 & 3) ([05c4e1b](https://github.com/TPTBusiness/NexQuant/commit/05c4e1ba54b9259d6cc5f0af00a177d9295278a9)) +* EURUSD Trading-Verbesserungen implementiert (Phase 1) ([b95bbf5](https://github.com/TPTBusiness/NexQuant/commit/b95bbf5900a9e06194ab0e330b662e2b853006ea)) +* EURUSD walk-forward splits, bars terminology, README no $factor ([0eae7d0](https://github.com/TPTBusiness/NexQuant/commit/0eae7d0ababb422927dd0123118b97724d066ab0)) +* expand indicator library from 7 to 14 ([22ac3c8](https://github.com/TPTBusiness/NexQuant/commit/22ac3c8f7b4b8f323cdaefb760b796fb3020ac0b)) +* **factor-coder:** Add critical rules to prevent common factor implementation errors ([bf25635](https://github.com/TPTBusiness/NexQuant/commit/bf256358afc232c35ac61f17b14e86adc284498a)) +* Fast mode - CoSTEER goes to backtest after 1 iteration ([0b16f4f](https://github.com/TPTBusiness/NexQuant/commit/0b16f4fcdcd01662f4dda0550911cf754af1758c)) +* **fin_quant:** auto-generate Kronos factor before loop start ([ce13a37](https://github.com/TPTBusiness/NexQuant/commit/ce13a37d91e39dc57229b3137df5e56e54f0e20c)) +* Fix 1min data integration and centralize all prompts ([f6f7b79](https://github.com/TPTBusiness/NexQuant/commit/f6f7b7929d335b88d2f9617f3f324f96ee6eb7c3)) +* Fix realistic backtesting (Step 1+2) ([84c1b5f](https://github.com/TPTBusiness/NexQuant/commit/84c1b5f01f242d05e92fa21ef765fcd5d9300661)) +* Full auto strategy generation in fin_quant loop ([dd42d01](https://github.com/TPTBusiness/NexQuant/commit/dd42d01c4eb5767092968f4d01ccaa7648cbe14e)) +* Full system integration - RL + Protections + Backtesting + CLI ([1fda459](https://github.com/TPTBusiness/NexQuant/commit/1fda45940a79fded6b2cf68e60f8b320729e31f0)) +* FX feedback loop, EURUSD ticker examples, bars terminology ([781779a](https://github.com/TPTBusiness/NexQuant/commit/781779a1f8c853eb77253053e23bc10c46dcf402)) +* FX Multi-Agent Validator (TradingAgents-inspired) - Session/Macro/Bull-Bear/Trader ([cddfc53](https://github.com/TPTBusiness/NexQuant/commit/cddfc53ab07ca75b2364c30b9c2a794383633c2b)) +* Improve predix portfolio command with robust error handling ([db1d4f9](https://github.com/TPTBusiness/NexQuant/commit/db1d4f9758807eb79e4bc834754529810294217b)) +* Improved LLM prompt + Optuna integration (Step 3+5) ([2af0006](https://github.com/TPTBusiness/NexQuant/commit/2af0006998f8159ff22dd0b78f967952246d59af)) +* init pydantic ai agent & context 7 mcp ([#1240](https://github.com/TPTBusiness/NexQuant/issues/1240)) ([5ba5e83](https://github.com/TPTBusiness/NexQuant/commit/5ba5e8356cbacb5e4bd9f24b26d6f9ac01784822)) +* Integrate critical features into fin_quant workflow (P0+P1) ([eeb44a7](https://github.com/TPTBusiness/NexQuant/commit/eeb44a76b12d40e992047de6b281289b1ba65605)) +* Integrate factor code/description saving into fin_quant process ([3eaebeb](https://github.com/TPTBusiness/NexQuant/commit/3eaebeb2229a104a2bbbe97f6877376b01bbdfc9)) +* integrate Kronos foundation model into fin_quant R&D loop ([dab2772](https://github.com/TPTBusiness/NexQuant/commit/dab2772a34de13b7e1bf4030642d398965ab8545)) +* integrate Kronos-mini OHLCV foundation model (Option A + B) ([ca2d3a2](https://github.com/TPTBusiness/NexQuant/commit/ca2d3a29576a4d7a715d4d8a0fc1936049990161)) +* Intelligent embedding chunking instead of truncation ([2d0584b](https://github.com/TPTBusiness/NexQuant/commit/2d0584b4cd7c1b3d9623acd6e141035d51f535fa)) +* inverse factor signal combos — top-3 gives +0.57%/month with -3.7% DD ([f699733](https://github.com/TPTBusiness/NexQuant/commit/f699733cc3b216bfe2cdc00329b6b823f2b93d59)) +* live 1h London momentum strategy + multi-timeframe generator ([bf79564](https://github.com/TPTBusiness/NexQuant/commit/bf79564e6bc8d509b2c3901989aa37394ff5a413)) +* live price-action pipeline — Donchian+MACD majority-vote signals ([de4494d](https://github.com/TPTBusiness/NexQuant/commit/de4494d69bdd3e09d603e4d4770e6bb351f11103)) +* **logging:** write complete LLM prompts and responses to daily JSONL log ([00ea268](https://github.com/TPTBusiness/NexQuant/commit/00ea2680ae12c0b0a515cc2f04415b80534578f4)) +* **mcp:** cache with one-click toggle ([#1269](https://github.com/TPTBusiness/NexQuant/issues/1269)) ([4f493c8](https://github.com/TPTBusiness/NexQuant/commit/4f493c8d637dfda42f84af0dc08f8ecfc0501668)) +* mcts policy based on trace scheduler ([#1203](https://github.com/TPTBusiness/NexQuant/issues/1203)) ([ac6d8ed](https://github.com/TPTBusiness/NexQuant/commit/ac6d8edad4366b08b5caf75e9a5ee8da0061a078)) +* migrate R&D loop to TA-Lib (17 indicators, 161 available) ([a86c515](https://github.com/TPTBusiness/NexQuant/commit/a86c51531bd7831594165354beedec5e27f14cce)) +* migrate to 1min EURUSD data (2020-2026) ([b39f2b7](https://github.com/TPTBusiness/NexQuant/commit/b39f2b7e46384c4fc56c1274c9120c470313262b)) +* ML Training Pipeline with 46 tests (P5 complete) ([9109613](https://github.com/TPTBusiness/NexQuant/commit/910961368c25fe8432f4581fb8337e41b0c336c8)) +* model-track bias + daily/portfolio tools ([ff46aa0](https://github.com/TPTBusiness/NexQuant/commit/ff46aa0fd382ccb3465d26b0dc40c77363539d91)) +* multi-asset data pipeline, daily strategy generator, ML pipeline ([a317987](https://github.com/TPTBusiness/NexQuant/commit/a317987824d042c6aae3bea0bed64af7c630ef58)) +* multi-instrument — GBP/USD added (+60.6%/month verified) ([66299c6](https://github.com/TPTBusiness/NexQuant/commit/66299c68bbaf46566bec9ddea5151bec1b28c85e)) +* new R&D loop — indicator discovery with exploit/explore mechanics ([efad52e](https://github.com/TPTBusiness/NexQuant/commit/efad52e62adf7df95885c21048e714ba1fc41b1b)) +* offline selector ([#1231](https://github.com/TPTBusiness/NexQuant/issues/1231)) ([d4c5399](https://github.com/TPTBusiness/NexQuant/commit/d4c539912abdb60e9d8950e7ea1186fd32bfeef3)) +* optimize strategy generator (cache OHLCV, min_sharpe 1.5, predix generate-strategies CLI) ([963532f](https://github.com/TPTBusiness/NexQuant/commit/963532fff8df7937504c39bfea7b0334bb582b05)) +* **optimizer:** add max_positions parameter to Optuna search space ([4ffa02d](https://github.com/TPTBusiness/NexQuant/commit/4ffa02dab02e4b635d60a057118194b6c20ba2e6)) +* Optuna Parameter Optimizer with 60 tests (P3 complete) ([343f97d](https://github.com/TPTBusiness/NexQuant/commit/343f97d7e782ce132e09a4073d0447a8d5597aa9)) +* Optuna-optimized RF ML pipeline for daily strategies (+0.61%/month) ([c8b9683](https://github.com/TPTBusiness/NexQuant/commit/c8b968385850dd13800f95be43bfb4c1381765af)) +* PDF performance reports for strategies (reportlab) ([5fd25b2](https://github.com/TPTBusiness/NexQuant/commit/5fd25b296d7f3fb4dc8a8f9d9dcb64be0f4c2fb3)) +* predix.py wrapper for dashboard support ([757c66c](https://github.com/TPTBusiness/NexQuant/commit/757c66cddb18254220db1d571d9b739380c57f44)) +* price-action strategy generator — no LLM, no factors, 38 profitable strategies ([a099d0c](https://github.com/TPTBusiness/NexQuant/commit/a099d0cb9f6056eb526290433c4d7040e366b79b)) +* prioritize Kronos foundation model factors in strategy selection ([0226e54](https://github.com/TPTBusiness/NexQuant/commit/0226e54129a169198cfdcbfc9e4ea59d5c0c7fbb)) +* R&D loop fixes + new price-action research loop ([5add57f](https://github.com/TPTBusiness/NexQuant/commit/5add57f369900c214ccf5c0e88f6098aef0738f9)) +* R&D loop v2 — LLM proposals, crossover mutation, WF filter, multi-instrument ([10cc425](https://github.com/TPTBusiness/NexQuant/commit/10cc42593b48fb46fd3348f3a19056e96db78839)) +* Realistic backtesting with OHLCV data (P5 continued) ([8b5b8d9](https://github.com/TPTBusiness/NexQuant/commit/8b5b8d931865ee0e99ac5aa84aa4787d574a206c)) +* Realistic backtesting with OHLCV data and spread costs ([39ccdec](https://github.com/TPTBusiness/NexQuant/commit/39ccdec7a5071206487004012d5167a461411eb9)) +* Redirect RD-Agent workspace to results/ directory ([6875be6](https://github.com/TPTBusiness/NexQuant/commit/6875be6435a2108133aeadba3cf81517f9a97a57)) +* **rl:** add AutoRL-Bench framework and benchmark integrations ([#1348](https://github.com/TPTBusiness/NexQuant/issues/1348)) ([7cd64a2](https://github.com/TPTBusiness/NexQuant/commit/7cd64a26fd84017042eb163e8eb4d3bd30c16de7)) +* run Kronos on CPU to avoid GPU conflict with llama-server ([f2394dc](https://github.com/TPTBusiness/NexQuant/commit/f2394dc1ea68eac506fa1b973f8e18a92d51e593)) +* Save all factor results to results/factors/ ([08e58fc](https://github.com/TPTBusiness/NexQuant/commit/08e58fc1da1b19135de7f0cbfab86f9ce8bf3a76)) +* Save factor results immediately after each evaluation ([98e3025](https://github.com/TPTBusiness/NexQuant/commit/98e3025ded6ea17e911e9243710e008420c19e4a)) +* **scripts:** add full file logging to strategy generation and rebacktest scripts ([e4ce0d2](https://github.com/TPTBusiness/NexQuant/commit/e4ce0d29163476952f5aff3e8bc8e5626a491e36)) +* show the summarized final difference between the final workspace and the base workspace ([#1281](https://github.com/TPTBusiness/NexQuant/issues/1281)) ([35a7ae5](https://github.com/TPTBusiness/NexQuant/commit/35a7ae5e1ff929b3ee3b77c04cb1f4a684a4b2d7)) +* **strategies:** make OOS validation mandatory in strategy generator ([710f5e6](https://github.com/TPTBusiness/NexQuant/commit/710f5e6fec3c2d99bc2ec0718e61986971fac8cd)) +* Strategy Generator working with local LLM (P0-P4) ([2262635](https://github.com/TPTBusiness/NexQuant/commit/226263588f67a57e42e3d02b0cc4962aeb85b66a)) +* Strategy Orchestrator with 30 tests (P2 complete) ([55ecfb8](https://github.com/TPTBusiness/NexQuant/commit/55ecfb88098db2af321bac106dcf27875c18607c)) +* Strategy performance reports, CLI docs, and README update ([590984e](https://github.com/TPTBusiness/NexQuant/commit/590984e060bf29718340dea1b0968bb29213dcec)) +* Strategy Worker module with 41 tests (P1 complete) ([dbbce30](https://github.com/TPTBusiness/NexQuant/commit/dbbce300dfd4f172240c893260ded76ea34a6c86)) +* **strategy:** Continuous optimization with Optuna parameter injection ([09cc725](https://github.com/TPTBusiness/NexQuant/commit/09cc725562ff8c6f56b09d5afd5c92ba04fab1a9)) +* Support 25+ parallel runs with resource warnings ([b4dc2d5](https://github.com/TPTBusiness/NexQuant/commit/b4dc2d52b459cce141dd083af1214473ebd43dea)) +* support Kronos-small and Kronos-base models, auto-select GPU/CPU ([f50b0f3](https://github.com/TPTBusiness/NexQuant/commit/f50b0f328b0a38df0fe5a2425997d020e897ee63)) +* unified backtest engine, LLM error handling, strategy refactor ([5c066c5](https://github.com/TPTBusiness/NexQuant/commit/5c066c531a47fd2dccf5d2ee037a349d8ee1b146)) +* update README with latest paper acceptance to NeurIPS 2025 ([#1252](https://github.com/TPTBusiness/NexQuant/issues/1252)) ([12969b4](https://github.com/TPTBusiness/NexQuant/commit/12969b491eafab626ce71f7e530458dab6f43246)) +* zentrale data_config.yaml + apply_config.py für dynamische Datenkonfiguration ([b7c1e4d](https://github.com/TPTBusiness/NexQuant/commit/b7c1e4db8e29e960fe28393911d60fc0fd3ca413)) + + +### Bug Fixes + +* (to main) litellm's Timeout error is not picklable ([#1294](https://github.com/TPTBusiness/NexQuant/issues/1294)) ([315850e](https://github.com/TPTBusiness/NexQuant/commit/315850ea81761aa2478639ad32302d7a55f8181b)) +* 15 bug fixes across orchestrator, runner, backtest, and infrastructure ([7c88252](https://github.com/TPTBusiness/NexQuant/commit/7c882523ee6fa866b328bc4bec7ac38ae0fe2105)) +* add a switch for ensemble_time_upper_bound and fix some bug in main ([#1226](https://github.com/TPTBusiness/NexQuant/issues/1226)) ([fc18942](https://github.com/TPTBusiness/NexQuant/commit/fc18942339b3ca59077ddc903f84b2d54193e5bc)) +* Add Bandit security scanning and fix critical vulnerabilities ([ca09577](https://github.com/TPTBusiness/NexQuant/commit/ca095771f2ebb37af705bc6366bc09564232f670)) +* Add critical column name rules to factor generation prompt ([bf9d50b](https://github.com/TPTBusiness/NexQuant/commit/bf9d50b45a95a6884ce683cb83a20d1265cf5357)) +* Add get_factor_count() to QuantTrace to prevent parallel run crashes ([1d6efa7](https://github.com/TPTBusiness/NexQuant/commit/1d6efa7a7e247b7083ba074b7044eac3a73789d0)) +* add hypothesis to test deps and fix missing imports in deep tests ([92a0ab8](https://github.com/TPTBusiness/NexQuant/commit/92a0ab87e2212860e18618bb5e107aaeeeb134b0)) +* add json format response fallback to prompt templates ([#1246](https://github.com/TPTBusiness/NexQuant/issues/1246)) ([694afd8](https://github.com/TPTBusiness/NexQuant/commit/694afd81331227d2be7f780f72023d00c0c9864e)) +* add missing debug() method to RDAgentLog ([04361ce](https://github.com/TPTBusiness/NexQuant/commit/04361cea458f0f0d3b56d529a64e6feaa7d2b1e3)) +* Add missing os import in factor_runner.py ([18ccd1a](https://github.com/TPTBusiness/NexQuant/commit/18ccd1acf2f7f3f4c6e2d62b8d3a5b635197041c)) +* Add missing Panel import in predix evaluate command ([706d887](https://github.com/TPTBusiness/NexQuant/commit/706d8878b6cdd8c768f8005d9efca8e79f790428)) +* add missing sys import and fix undefined acc_rate in factor eval ([8e2729e](https://github.com/TPTBusiness/NexQuant/commit/8e2729eeeb51b3e507a65ec492ba576e547859cc)) +* Add nosec comments for schema migration SQL in results_db.py ([b8d632b](https://github.com/TPTBusiness/NexQuant/commit/b8d632b4251a7fcea4f234c9a8771ec87ac8650c)) +* also catch ValueError in mean_variance for dimension mismatch ([d0a1ff8](https://github.com/TPTBusiness/NexQuant/commit/d0a1ff853dbab0cbe4555574fe56806511a7f2d0)) +* **auto-fixer:** add five new factor code fixes for groupby/apply errors ([04900ad](https://github.com/TPTBusiness/NexQuant/commit/04900ad6977d6e5ee2fd22bce8f87054007fe17a)) +* **auto-fixer:** add four new factor code fixes for common runtime errors ([0f103df](https://github.com/TPTBusiness/NexQuant/commit/0f103df5836115bd2e585a4dbf2c50eb4547d334)) +* **auto-fixer:** add groupby([level=N,'date']) SyntaxError fix ([bd3f2f7](https://github.com/TPTBusiness/NexQuant/commit/bd3f2f7f30ab908dd676056c6b70366ff981dabc)) +* **auto-fixer:** disable _fix_min_periods for intraday data ([5a3a5b9](https://github.com/TPTBusiness/NexQuant/commit/5a3a5b9bab085cf1ba34a303616038e5f19ca92c)) +* **auto-fixer:** fix chained groupby(level=N).groupby('date') pattern ([084a2b5](https://github.com/TPTBusiness/NexQuant/commit/084a2b55b5f89a95e81f3921c785053d178f965c)) +* **auto-fixer:** fix df.loc[instrument] DateParseError on MultiIndex frames ([2e41a7d](https://github.com/TPTBusiness/NexQuant/commit/2e41a7d711c2d9f1e74852ca36eb46ac544955e0)) +* **auto-fixer:** fix df['instrument'] KeyError on MultiIndex frames ([5fadc9e](https://github.com/TPTBusiness/NexQuant/commit/5fadc9e77c04205ef7d4fd5a2870ac6da223e345)) +* **auto-fixer:** fix two assignment-target bugs in instrument column fixers ([afbef59](https://github.com/TPTBusiness/NexQuant/commit/afbef5945890a8b12a23f26fb1806f63576c7777)) +* **auto-fixer:** preserve date dimension in groupby(['instrument','date']) fix ([f64e4d9](https://github.com/TPTBusiness/NexQuant/commit/f64e4d97321c3f8d1008f06e73d781a9e4e5dc60)) +* **auto-fixer:** remove ddof from rolling() args, not only from std()/var() ([07b3051](https://github.com/TPTBusiness/NexQuant/commit/07b305153e60d1fb7f68524bb4223d3c69a5f40f)) +* **auto-fixer:** replace zero \$volume with price-range proxy for FX data ([43a8e46](https://github.com/TPTBusiness/NexQuant/commit/43a8e461b21a839309e3235714cbc27d0f38838f)) +* **auto-fixer:** strip spurious .reset_index() after .transform() calls ([5d2c7d7](https://github.com/TPTBusiness/NexQuant/commit/5d2c7d70275975be81d6b6425899257d11ebb84f)) +* avoid triggering errors like "RuntimeError: dictionary changed s… ([#1285](https://github.com/TPTBusiness/NexQuant/issues/1285)) ([b180543](https://github.com/TPTBusiness/NexQuant/commit/b18054371c6ce08c6bc322a7b0de41b67fc60408)) +* **backtest:** replace broken MC permutation test with binomial win-rate test ([6c2979d](https://github.com/TPTBusiness/NexQuant/commit/6c2979d24ab8096ac309cb5b40494c661b50f933)) +* bump axios 1.15.2→1.16.0, postcss 8.4.31→8.5.14 (Dependabot CVEs) ([5de229c](https://github.com/TPTBusiness/NexQuant/commit/5de229cb341af3051f8025d7519a187f76f48cd8)) +* case-insensitive assertion in test_add_column_idempotent ([f78b040](https://github.com/TPTBusiness/NexQuant/commit/f78b040c272902b74b37aa0cc02758a083df3d34)) +* **ci:** fix closed-source asset check false positives in security workflow ([cf985a3](https://github.com/TPTBusiness/NexQuant/commit/cf985a3aab2b3a6a39ef06342527f567e24456ff)) +* **ci:** lazy import logger in predix.py and cli.py to avoid ImportError in test env ([541c6bb](https://github.com/TPTBusiness/NexQuant/commit/541c6bb8d5a0a4b3463d07d8783973eb280b8098)) +* **ci:** remove CodeQL workflow (conflicts with default setup), drop duplicate lint job ([62b6514](https://github.com/TPTBusiness/NexQuant/commit/62b65149624e642ba1220b8ab28fbf60e541a6bb)) +* **ci:** remove env-print step to avoid leaking sensitive environment variables ([#1299](https://github.com/TPTBusiness/NexQuant/issues/1299)) ([c067ea6](https://github.com/TPTBusiness/NexQuant/commit/c067ea640030c67c549e3ca2dbad178f144e8b31)) +* **ci:** set JAVA_TOOL_OPTIONS UTF-8 in Codacy workflow ([c697349](https://github.com/TPTBusiness/NexQuant/commit/c69734930f48d4af076aee1597c8d4aa019e3419)) +* CLI dashboard in separate terminal window ([b72cca9](https://github.com/TPTBusiness/NexQuant/commit/b72cca98680bd8a87393bb4e5f7d17aae47ab5ed)) +* close log file handle, fix RiskMgmt equity double-count, remove bare except ([20a5342](https://github.com/TPTBusiness/NexQuant/commit/20a5342b8ad54186c5afae3f1d4e3f61c7936e4b)) +* **collect_info:** parse package names safely from requirements constraints ([#1313](https://github.com/TPTBusiness/NexQuant/issues/1313)) ([99a71bf](https://github.com/TPTBusiness/NexQuant/commit/99a71bf533211df743b5801f913de788259e64cb)) +* correct MaxDD to equity curve in strategy_builder; test: add 8 cross-validation tests for metric correctness ([729af07](https://github.com/TPTBusiness/NexQuant/commit/729af07156b99b1f6722720a6b57c4996ba1f8ca)) +* correct project root paths and subprocess handling in parallel runner and CLI ([f2c1c01](https://github.com/TPTBusiness/NexQuant/commit/f2c1c010293bfa2cf03eb7e50e91d401d9f729b2)) +* correct Sharpe/MaxDD/WinRate in direct factor eval (was computing on raw factor, now on strategy returns) ([373a254](https://github.com/TPTBusiness/NexQuant/commit/373a254ea6062b4a93ec2faab00ad1f1961585c5)) +* **deps:** bump python-dotenv to >=1.2.2 (CVE symlink overwrite) ([e6ce81e](https://github.com/TPTBusiness/NexQuant/commit/e6ce81e4f401295ea263eea64a23027d459d1009)) +* **deps:** pin aiohttp>=3.13.4 to patch 4 CVEs ([fceda7b](https://github.com/TPTBusiness/NexQuant/commit/fceda7b3ad6f572150cdc14762d26cfe3c7083f3)) +* **deps:** relax aiohttp constraint to >=3.13.4 for litellm compatibility ([92833b1](https://github.com/TPTBusiness/NexQuant/commit/92833b18f33c97899d07df07a7d915333d1fdfb5)) +* Disable ANSI color codes when not running in TTY ([2e7652c](https://github.com/TPTBusiness/NexQuant/commit/2e7652c613e48539586dce79f0d6180b68d37007)) +* Disable Flask debug mode by default (Security Alert [#2](https://github.com/TPTBusiness/NexQuant/issues/2)) ([ab5fa78](https://github.com/TPTBusiness/NexQuant/commit/ab5fa7861177cdcdc67c783121fa9e2d88c631d8)) +* disable WF and LLM in R&D loop for fast overnight run ([c01a12a](https://github.com/TPTBusiness/NexQuant/commit/c01a12a9b6df4b28ede6ccf5a6fb2f2960914cde)) +* Display litellm messages as info instead of warnings ([2c89a35](https://github.com/TPTBusiness/NexQuant/commit/2c89a35dda06152b5e954a2aaeddf5c7c6aaa04f)) +* **dockerfile:** install coreutils to resolve timeout command error ([#1260](https://github.com/TPTBusiness/NexQuant/issues/1260)) ([35580cb](https://github.com/TPTBusiness/NexQuant/commit/35580cbdf87347d5d6105b2a9b5ad1694b695820)) +* **docs:** update rdagent ui with correct params ([#1249](https://github.com/TPTBusiness/NexQuant/issues/1249)) ([3b9ad11](https://github.com/TPTBusiness/NexQuant/commit/3b9ad1145769862a24cc7533a1828f750f72170d)) +* Embedding Context Length Error ([6d6c5ab](https://github.com/TPTBusiness/NexQuant/commit/6d6c5abd4ac7252257f88e13e263ecb2497fde3b)) +* end-timestamp 23:45, weg, SZ-beispiele weg ([6a9ccd5](https://github.com/TPTBusiness/NexQuant/commit/6a9ccd5ddbf95060a2847bd27bcdae762a46a19d)) +* enhance feedback handling in MultiProcessEvolvingStrategy for improved task evolution ([#1274](https://github.com/TPTBusiness/NexQuant/issues/1274)) ([afb575c](https://github.com/TPTBusiness/NexQuant/commit/afb575cc91114dbe41d8f582294dcc3692990695)) +* Ensure backtest results save to DB and JSON files ([9bb4b47](https://github.com/TPTBusiness/NexQuant/commit/9bb4b474c0bc88d41f2575e7430ea81a615d06bf)) +* evaluator erkennt 15min als valid (nicht daily) ([cf0f634](https://github.com/TPTBusiness/NexQuant/commit/cf0f634c17dce45400cc325ccd3ca45e769c15fd)) +* **factors:** detect and correct look-ahead bias in daily-constant factors ([d48a8a9](https://github.com/TPTBusiness/NexQuant/commit/d48a8a9848788e62050ba532a5266a43357f1332)) +* **factors:** extend look-ahead rules to session factors and add intraday-factor guidance ([64fcdad](https://github.com/TPTBusiness/NexQuant/commit/64fcdadee15a8510f48f3f357d26ed5f0b496901)) +* filter NaN in max(), remove redundant ternary, handle non-finite vbt results ([dcec524](https://github.com/TPTBusiness/NexQuant/commit/dcec5242f58e1450ab10c23bb4170c77a559800d)) +* fix chat_max_tokens calculation method to show true input_max_tokens ([#1241](https://github.com/TPTBusiness/NexQuant/issues/1241)) ([7e99605](https://github.com/TPTBusiness/NexQuant/commit/7e996055f2c7fd37595573ebdb13aa57c425a6cc)) +* fix mcts ([#1270](https://github.com/TPTBusiness/NexQuant/issues/1270)) ([5003aff](https://github.com/TPTBusiness/NexQuant/commit/5003affb17505525336e6c30ba9c690b810c252b)) +* Fix parallel runner dashboard rendering error ([8926a57](https://github.com/TPTBusiness/NexQuant/commit/8926a57a35e42068ede0e7d64a92dfacc3c48093)) +* fix type annotation, remove unused parameter, improve import_class errors ([3eb09ce](https://github.com/TPTBusiness/NexQuant/commit/3eb09cec0a81a5a0ec5f3e54f4f8ef5b12da512d)) +* Forward-fill daily factors to 1-min frequency ([dfed6d6](https://github.com/TPTBusiness/NexQuant/commit/dfed6d65377973203280c85815a190eeb0be4121)) +* generate.py nutzt rdagent4qlib env für Qlib-Datenzugriff ([b9007f7](https://github.com/TPTBusiness/NexQuant/commit/b9007f754ac682800aaf265c0f24c2028d387d84)) +* Handle failed experiments in feedback step to prevent crashes ([8a54ff4](https://github.com/TPTBusiness/NexQuant/commit/8a54ff4cc2b79add4c80354bfee3450c48374703)) +* handle mixed str and dict types in code_list ([#1279](https://github.com/TPTBusiness/NexQuant/issues/1279)) ([32ecf92](https://github.com/TPTBusiness/NexQuant/commit/32ecf92afcf647f257b430c748cbe6bb5fa0fac4)) +* Handle negative/zero values in performance report charts ([1315638](https://github.com/TPTBusiness/NexQuant/commit/1315638165f473177128324e18e1a20bef05cf22)) +* Handle Qlib Docker backtest failures gracefully (SECURITY FIX) ([557c581](https://github.com/TPTBusiness/NexQuant/commit/557c5815121d4f6638b7b8c645852412ba5845a4)) +* Handle timeout exceptions safely in predix_full_eval.py ([1132943](https://github.com/TPTBusiness/NexQuant/commit/1132943dd4fbc97c3b7620b6c34d8ee7379144d2)) +* handle ValueError in stdout shrinking and refactor shrink logic ([#1228](https://github.com/TPTBusiness/NexQuant/issues/1228)) ([6fc3877](https://github.com/TPTBusiness/NexQuant/commit/6fc3877a39baabbf26e0cc1cbd327b0f6e2e325e)) +* Harden _safe_resolve to fix CodeQL alert [#3](https://github.com/TPTBusiness/NexQuant/issues/3) ([28ea591](https://github.com/TPTBusiness/NexQuant/commit/28ea5918437acdae03184e884edbab5f5fea839a)) +* Harden path validation in Job Summary UI to fix CodeQL alert [#17](https://github.com/TPTBusiness/NexQuant/issues/17) ([79bc526](https://github.com/TPTBusiness/NexQuant/commit/79bc526cbabf4ad2395b0bf765638b4bab7fdfeb)) +* Harden path validation to fix CodeQL alert [#20](https://github.com/TPTBusiness/NexQuant/issues/20) ([87d1ce7](https://github.com/TPTBusiness/NexQuant/commit/87d1ce75addc67ab43b53b3a8f5dedd5077c5a3a)) +* harmonize risk field names and case-insensitive DB column check ([8b47d0a](https://github.com/TPTBusiness/NexQuant/commit/8b47d0aaad65f7c49191394cc2f0734d919b4e87)) +* Import pandas in predix portfolio_simple command ([e4967e1](https://github.com/TPTBusiness/NexQuant/commit/e4967e16429482f055b41286e909deb291fbd2b0)) +* Improve path traversal prevention with dedicated helper function ([8e00b89](https://github.com/TPTBusiness/NexQuant/commit/8e00b8999676d0c6f89936c6c3b63a48ea02d59e)) +* increase retry count in hypothesis_gen decorator to 10 ([#1230](https://github.com/TPTBusiness/NexQuant/issues/1230)) ([86ce4f1](https://github.com/TPTBusiness/NexQuant/commit/86ce4f135d649cfb12f2f88626cd31868cb447e7)) +* Initialize EnvController in QuantTrace.__init__ ([cc1f44e](https://github.com/TPTBusiness/NexQuant/commit/cc1f44e54b086b0e926a54d700b904682f5a632d)) +* inject correct MultiIndex template into factor prompt ([49004db](https://github.com/TPTBusiness/NexQuant/commit/49004db027d699bacbb975f267daa95d1957ccd7)) +* inject MultiIndex warning into factor interface prompt (YAML valide) ([79e2915](https://github.com/TPTBusiness/NexQuant/commit/79e2915823801d3574920fa197cf9c57965f485f)) +* **kronos:** lazy torch import to fix CI ModuleNotFoundError ([8a33478](https://github.com/TPTBusiness/NexQuant/commit/8a33478e1aad5a3955f6e0f115cdcbf978021147)) +* **kronos:** pass actual datetime Series to Kronos predictor timestamps ([7422868](https://github.com/TPTBusiness/NexQuant/commit/74228684f3739a991e37d5433cf27c603a388245)) +* **kronos:** replace rdagent_logger with stdlib logging for CI compatibility ([a8c6055](https://github.com/TPTBusiness/NexQuant/commit/a8c60558d59accbdd67d2dbb6b6ced1e58e8680b)) +* live 1h SMA uses minute_closes deque instead of stale HDF5 ([46cc214](https://github.com/TPTBusiness/NexQuant/commit/46cc2141ac7131921cb81abd6abaa4eff048ff94)) +* **loop:** compress old experiment history in proposal prompt to reduce context size ([9fdac81](https://github.com/TPTBusiness/NexQuant/commit/9fdac818c9c0bb1b494473151302cd2289c663cb)) +* **loop:** prevent step_idx advance on unhandled exceptions + fix consecutive assistant messages ([ba3421e](https://github.com/TPTBusiness/NexQuant/commit/ba3421ec5edc64566efb2ad7042bbac7128b17b8)) +* merge candidates ([#1254](https://github.com/TPTBusiness/NexQuant/issues/1254)) ([46aad78](https://github.com/TPTBusiness/NexQuant/commit/46aad789ef710d9603e2330788dc66849cb6cab3)) +* model/factor experiment filtering in Qlib proposals ([#1257](https://github.com/TPTBusiness/NexQuant/issues/1257)) ([9e34b4e](https://github.com/TPTBusiness/NexQuant/commit/9e34b4e855cbd709cd077f529950b8e1f5c01486)) +* move task cancellation to finally block and fix subprocess kill typo ([#1234](https://github.com/TPTBusiness/NexQuant/issues/1234)) ([a984f69](https://github.com/TPTBusiness/NexQuant/commit/a984f69f681dda1c6c58f45e2505d7b0e8d75cf0)) +* **optuna:** fix inverted parameter range in Stage 2/3 when signal_bias is negative ([6356743](https://github.com/TPTBusiness/NexQuant/commit/6356743baa58e91646cdba83cb2eb9175084d4af)) +* Override webshop's Werkzeug dependency to fix CVE-2026-27199 ([83e18e2](https://github.com/TPTBusiness/NexQuant/commit/83e18e27f392c90273bfd9a1dddf6872a5506fa5)) +* preserve null end_time when rendering dataset segments template ([#1326](https://github.com/TPTBusiness/NexQuant/issues/1326)) ([6196ba3](https://github.com/TPTBusiness/NexQuant/commit/6196ba31f2e43db4761eeb482c3301e2238bc4cf)) +* prevent calendar index overflow when signal data ends early ([#1324](https://github.com/TPTBusiness/NexQuant/issues/1324)) ([3dbd703](https://github.com/TPTBusiness/NexQuant/commit/3dbd7038280f21793246e5354f083ba472772a10)) +* prevent JSON content from being added multiple times during retries ([#1255](https://github.com/TPTBusiness/NexQuant/issues/1255)) ([31b19de](https://github.com/TPTBusiness/NexQuant/commit/31b19dee80c5006c72a0a9698834a04a3acd4af9)) +* prevent LLM retry loop from consecutive assistant message corruption ([a86666f](https://github.com/TPTBusiness/NexQuant/commit/a86666fb4c7c20b48aaa49d1f69b37aabbaa8a7a)) +* Prevent path injection in FT Job Summary UI ([d95f509](https://github.com/TPTBusiness/NexQuant/commit/d95f509efe81173583e875906f4c13257c088ba4)) +* Prevent path injection in RL Job Summary UI ([a170f0a](https://github.com/TPTBusiness/NexQuant/commit/a170f0ae587448b49b343262fe754613a80285b6)) +* Prevent path traversal in autorl_bench server.py ([4cfec6c](https://github.com/TPTBusiness/NexQuant/commit/4cfec6c46be31d96a7a9a2ffdc085777ccc78ddc)) +* Prevent path traversal in get_job_options() app.py ([5bd5416](https://github.com/TPTBusiness/NexQuant/commit/5bd5416c27e057e5b915c2146bb1f468852e2467)) +* Prevent path traversal in RL UI app.py ([848019d](https://github.com/TPTBusiness/NexQuant/commit/848019d20119d92f51e8ba70ade42e483b8a494f)) +* Prevent path traversal in Streamlit UI app.py ([9f8cf62](https://github.com/TPTBusiness/NexQuant/commit/9f8cf622d8ba468dae91a8cbb663be8e86b3ea33)) +* **qlib:** correct indentation in except blocks in quant_proposal and factor_runner ([0dbe833](https://github.com/TPTBusiness/NexQuant/commit/0dbe83309329774926d4bd9f5f3f3296d20d0128)) +* R&D loop — WF relaxed to 50%, optional by default ([1822001](https://github.com/TPTBusiness/NexQuant/commit/18220017ba672d8a2effd491b48a6253603ad7f1)) +* Refactor path validation to fix CodeQL alert [#16](https://github.com/TPTBusiness/NexQuant/issues/16) ([2819423](https://github.com/TPTBusiness/NexQuant/commit/2819423b4b70bfe162a6aace409f66d7815f34ef)) +* refine task scheduling logic in MultiProcessEvolvingStrategy for… ([#1275](https://github.com/TPTBusiness/NexQuant/issues/1275)) ([27d38af](https://github.com/TPTBusiness/NexQuant/commit/27d38af7bd7e1fdb73e3617e94435abe7901dd21)) +* relax WF default test (wf_oos_sharpe_mean not present when 0 windows) ([8efb5d4](https://github.com/TPTBusiness/NexQuant/commit/8efb5d445d16cb8333fc30d3deb6166be1152714)) +* remove $factor from prompt, update example count to EURUSD ([3adc5bf](https://github.com/TPTBusiness/NexQuant/commit/3adc5bf75e6820328991aa5a5456e6f68ccf8fd7)) +* remove all Chinese stock references, replace with EURUSD 1min FX ([44eeb01](https://github.com/TPTBusiness/NexQuant/commit/44eeb01ec4f95271a084e9d285e00959926923f3)) +* Remove API key from test_benchmark_api.py config ([3ce366e](https://github.com/TPTBusiness/NexQuant/commit/3ce366ee156711602c102ec8889a8fb80cfd7bb7)) +* Remove API key logging from eurusd_llm.py ([d73e3de](https://github.com/TPTBusiness/NexQuant/commit/d73e3de57b6188209b3bd9eed69b56c7d27c897a)) +* Remove API key parameter from generate_api_config() ([9780e3a](https://github.com/TPTBusiness/NexQuant/commit/9780e3aae5da8b1dc36fa4d285fa9b88f63236a6)) +* Remove API key presence detection from logging ([adba526](https://github.com/TPTBusiness/NexQuant/commit/adba526e9424a0d9d283461eed021bb021b2b89a)) +* Remove clear-text storage of API key (CodeQL alert [#8](https://github.com/TPTBusiness/NexQuant/issues/8)) ([2f01c77](https://github.com/TPTBusiness/NexQuant/commit/2f01c777f3ac3433de9d6a50fa9ff4683e6c772f)) +* Remove hardcoded credentials from test_benchmark_api.py ([c259a01](https://github.com/TPTBusiness/NexQuant/commit/c259a01b919f53b72ff88cded22eb3af145d490d)) +* Rename loader.py to prompt_loader.py to fix module conflict ([435e03b](https://github.com/TPTBusiness/NexQuant/commit/435e03baec65cbc0408e167f9096922751193276)) +* replace hardcoded ChromeDriver path with webdriver-manager ([#1271](https://github.com/TPTBusiness/NexQuant/issues/1271)) ([e3d2443](https://github.com/TPTBusiness/NexQuant/commit/e3d24437cf7842623fe27fd9221e36a07457d7f7)) +* Resolve 88% empty backtest results + path fixes ([f720f76](https://github.com/TPTBusiness/NexQuant/commit/f720f7674144572dba819c2229b2547502f751a0)) +* resolve dead code, shell injection risk, mutable defaults, and other bugs ([952281a](https://github.com/TPTBusiness/NexQuant/commit/952281a39bee81bc632f4781abedfa9a97aedfef)) +* Resolve FORWARD_BARS NameError in backtest script ([e9e4817](https://github.com/TPTBusiness/NexQuant/commit/e9e481701f9c76faabc3dfba9b3db94ba43943b1)) +* Resolve security vulnerabilities (Dependabot + Code Scanning) ([fe397c4](https://github.com/TPTBusiness/NexQuant/commit/fe397c44a6182282c7ac19d24c95dc3c3938cadb)) +* resolve unbound variable, logger shadowing, withdraw_loop edge case, and other bugs in main scripts ([f48251d](https://github.com/TPTBusiness/NexQuant/commit/f48251db4744a0d0a5d48802e51f3f64ea57dc2c)) +* restore KronosPredictor instantiation deleted during refactor ([15f2c00](https://github.com/TPTBusiness/NexQuant/commit/15f2c00901a91093fc97ceac637b8b3f2759212b)) +* revert 2 commits ([#1239](https://github.com/TPTBusiness/NexQuant/issues/1239)) ([2201a47](https://github.com/TPTBusiness/NexQuant/commit/2201a4762343f2cc2deb3dff2b70baf99f102292)) +* **security:** nosec for B608/B701 false positives in UI and template code ([0c4e411](https://github.com/TPTBusiness/NexQuant/commit/0c4e41193075d74ca3a39df736a5adb31531a011)) +* **security:** Patch 5 CodeQL path injection and clear-text logging alerts ([#22](https://github.com/TPTBusiness/NexQuant/issues/22)-[#25](https://github.com/TPTBusiness/NexQuant/issues/25), [#9](https://github.com/TPTBusiness/NexQuant/issues/9)) ([30bdd88](https://github.com/TPTBusiness/NexQuant/commit/30bdd88de08607f445c245cc3b1128ee295a782e)) +* **security:** Patch 5 CodeQL path injection and weak hashing alerts ([#25](https://github.com/TPTBusiness/NexQuant/issues/25)-[#30](https://github.com/TPTBusiness/NexQuant/issues/30)) ([e3a40de](https://github.com/TPTBusiness/NexQuant/commit/e3a40deb7f00cccdd9db0666546e36b46d8dea1b)) +* **security:** Patch path injection and stack trace exposure (CodeQL [#31](https://github.com/TPTBusiness/NexQuant/issues/31), [#27](https://github.com/TPTBusiness/NexQuant/issues/27)) ([308e556](https://github.com/TPTBusiness/NexQuant/commit/308e556a8b731f72ea20b6c022e1bc228f4387db)) +* **security:** real fix for B110 (logging in factor_proposal.py [#746](https://github.com/TPTBusiness/NexQuant/issues/746)) ([81e92a5](https://github.com/TPTBusiness/NexQuant/commit/81e92a50a8c0842a7fee71cbd42c49be12daef58)) +* **security:** real fix for B110 (logging in factor_runner.py [#744](https://github.com/TPTBusiness/NexQuant/issues/744)) ([a200194](https://github.com/TPTBusiness/NexQuant/commit/a20019410ffde5b52bac639e8a8da5aa06f2029a)) +* **security:** real fix for B110 (logging in quant_proposal.py [#741](https://github.com/TPTBusiness/NexQuant/issues/741)) ([d8ce3ed](https://github.com/TPTBusiness/NexQuant/commit/d8ce3ed84330ba9b9d6cea3792c4e2f5a5a92bcc)) +* **security:** real fix for B110 (logging in quant_proposal.py [#741](https://github.com/TPTBusiness/NexQuant/issues/741)) ([0b95143](https://github.com/TPTBusiness/NexQuant/commit/0b95143c1df1459949fc2e9f300b62f5cdee1b49)) +* **security:** real fix for B404/B603 (sys.executable in factor_runner.py [#745](https://github.com/TPTBusiness/NexQuant/issues/745)) ([4f00fab](https://github.com/TPTBusiness/NexQuant/commit/4f00fabdf222044d8e10874aa3c689c4b3ed510d)) +* **security:** replace eval() with ast.literal_eval and add request timeouts (B307, B113) ([d8d4091](https://github.com/TPTBusiness/NexQuant/commit/d8d4091f5f55d86411a20940d282a4f88d73acae)) +* **security:** replace eval() with ast.literal_eval in finetune validator (B307) ([c7ada10](https://github.com/TPTBusiness/NexQuant/commit/c7ada1056b7d1e97e7e63b7a7932601d17b5e1b8)) +* **security:** replace os.path.realpath with pathlib.resolve in safe_resolve_path to fix path-injection alerts ([bc73123](https://github.com/TPTBusiness/NexQuant/commit/bc73123c99fd159540da9fccf96727c5c35f63f2)) +* **security:** replace relative_to() with realpath+startswith for CodeQL sanitization ([2fd6e06](https://github.com/TPTBusiness/NexQuant/commit/2fd6e06b33a8d25550472e15a3ddc2af81b2d554)) +* **security:** replace remaining assert statements with proper error handling ([9e72998](https://github.com/TPTBusiness/NexQuant/commit/9e72998da691600c9ab435cdb06ffdb42afa30bc)) +* **security:** replace shell=True subprocess calls with list args (B602) ([1c16ac9](https://github.com/TPTBusiness/NexQuant/commit/1c16ac9d064ebf08b263fa604e3dda52e181d588)) +* **security:** replace shell=True subprocess calls with list args in env.py (B602) ([cad1c12](https://github.com/TPTBusiness/NexQuant/commit/cad1c121399f8782a06d4e32585b392c34666426)) +* **security:** resolve all 30 Bandit security alerts (B301, B614, B104) ([4577d6a](https://github.com/TPTBusiness/NexQuant/commit/4577d6a0aa53d9780f81dee9100d9e5f26f2e1bf)) +* **security:** resolve CodeQL path-injection alerts in UI data loaders ([4b6ddfa](https://github.com/TPTBusiness/NexQuant/commit/4b6ddfa0651b3a103ba3aaa9a85a0b7c461bb6cf)) +* **security:** resolve CodeQL path-injection and clear-text-logging alerts ([811509d](https://github.com/TPTBusiness/NexQuant/commit/811509d9977cec83d69db40e552829159a9add28)) +* **security:** Resolve GitHub Security Scan alerts ([280cc29](https://github.com/TPTBusiness/NexQuant/commit/280cc291e76135d39923757073e1b9f792895864)) +* **security:** resolve path-injection and add nosec for safe temp paths (B108, py/path-injection) ([05a20f6](https://github.com/TPTBusiness/NexQuant/commit/05a20f6373dfb686e256c950cb738581574d2917)) +* **security:** resolve path-injection, B701, B101, B112 Bandit alerts ([d5f7cc3](https://github.com/TPTBusiness/NexQuant/commit/d5f7cc3bd6eca83bbf745c3c2925c9520ba15763)) +* **security:** revert broken read_pickle encoding arg in kaggle template (B301) ([f2dde21](https://github.com/TPTBusiness/NexQuant/commit/f2dde21d359818ee51db6dbf92ee3581ef92679f)) +* **security:** Upgrade vllm and transformers to patch 4 CVEs ([dd675c7](https://github.com/TPTBusiness/NexQuant/commit/dd675c7a69e92be8293dfad011a3c98efb8e0a36)) +* **security:** validate SQL identifiers in _add_column_if_not_exists (B608) ([d5e4717](https://github.com/TPTBusiness/NexQuant/commit/d5e47172a465dbc7344d7a809b19bf3028bad9d2)) +* **security:** whitelist-validate metric column in get_top_factors (B608) ([204753e](https://github.com/TPTBusiness/NexQuant/commit/204753ecefc5f3f84d141f810c970dfe492e541a)) +* set requires_documentation_search to None to disable feature in eval ([#1245](https://github.com/TPTBusiness/NexQuant/issues/1245)) ([ee8c119](https://github.com/TPTBusiness/NexQuant/commit/ee8c119f31b72de1002e5ad5d30c56d0f4b6c9b9)) +* Skip already evaluated factors in predix_full_eval.py ([573bff0](https://github.com/TPTBusiness/NexQuant/commit/573bff08572422fa1198c5714a6babdfa60f7942)) +* skip Kronos factor on GPUs < 20GB to avoid CUDA OOM (shared with llama-server) ([b45f0b9](https://github.com/TPTBusiness/NexQuant/commit/b45f0b9d0d03b0b4446099eb623b95d1710f41e8)) +* **strategies:** guard against None IC in acceptance check, disable slow wf_rolling ([0cc2f86](https://github.com/TPTBusiness/NexQuant/commit/0cc2f8667a6b8cf5c42a936f5f6bae2f83e1e229)) +* **strategies:** handle None ic/sharpe/dd in rejected strategy log output ([05dab63](https://github.com/TPTBusiness/NexQuant/commit/05dab635e36b74b4f98ad17837df7c5411904308)) +* **strategy:** Fix template variables, APIBackend import, and JSON extraction ([520edbe](https://github.com/TPTBusiness/NexQuant/commit/520edbe726cd71860b0f6e9305101735b6a4254b)) +* **strategy:** Re-evaluate Optuna-optimized strategies with full OHLCV backtest ([c709f94](https://github.com/TPTBusiness/NexQuant/commit/c709f9484d9f20f9a6350483fe36057361ee7153)) +* Switch to ThreadPoolExecutor for factor evaluation ([8947089](https://github.com/TPTBusiness/NexQuant/commit/894708976a318a1e08b4e6b64d747bbb59c68998)) +* sync release manifest to v1.4.3 (was diverged at 0.8.0) ([c16aecc](https://github.com/TPTBusiness/NexQuant/commit/c16aeccb67fe53f5cd1d13f80eeaac3c0790620e)) +* Translate remaining German comment in eurusd_macro.py ([6730ae4](https://github.com/TPTBusiness/NexQuant/commit/6730ae48655acf1544cff69ab00bc246cf465d35)) +* Update LICENSE badge link from main to master branch ([e79eff5](https://github.com/TPTBusiness/NexQuant/commit/e79eff51c2b6c4f3922893da53869f255b3ec648)) +* Update Werkzeug to 2.3.8 (latest secure 2.x version) ([19b9d23](https://github.com/TPTBusiness/NexQuant/commit/19b9d23952cd378c630a8b03255ed92060bdfd77)) +* update WF test for new default (wf_rolling=True) ([e5d626a](https://github.com/TPTBusiness/NexQuant/commit/e5d626a6d9655a5a0d9499edbf35d92be59aec3a)) +* Use 96-bar forward returns in backtest (matching factor IC horizon) ([a1f0ceb](https://github.com/TPTBusiness/NexQuant/commit/a1f0ceb15c5560542cadfc2dbcc776e8d5305842)) +* Use num_api_keys instead of len(api_keys) for round-robin ([17f68e6](https://github.com/TPTBusiness/NexQuant/commit/17f68e6ff59c817873901a2dc5ff72d72f3e44a3)) +* weg, Timestamps mit Uhrzeit, kein SZ-Beispiel ([e9f6ac4](https://github.com/TPTBusiness/NexQuant/commit/e9f6ac48d97b1b57a0dde14562cd1b6f5d106edd)) + + +### Performance Improvements + +* **kronos:** batch GPU inference via predict_batch — 75x faster ([bc1f3cf](https://github.com/TPTBusiness/NexQuant/commit/bc1f3cf6db63a0114c5096dc598620458979bc17)) +* **kronos:** batch GPU inference via predict_batch — 75x faster ([9f6bc81](https://github.com/TPTBusiness/NexQuant/commit/9f6bc81eddab2f655ec89196d05b5402a8cd60b5)) + + +### Reverts + +* remove automated release social workflow ([ba62cf3](https://github.com/TPTBusiness/NexQuant/commit/ba62cf3026ba21e2d8438bc8bcf32e1a4a2ab87e)) + + +### Documentation + +* Add ATTRIBUTION.md with clear usage guidelines ([7701ba0](https://github.com/TPTBusiness/NexQuant/commit/7701ba02a8b9937f5ca83cfa213fe769354ac318)) +* Add CLI welcome screenshot to README ([fa6fa22](https://github.com/TPTBusiness/NexQuant/commit/fa6fa229590581341ef4d2aedce6f190f1f4c713)) +* add closed-source test policy; remove closed-source test imports ([69770b3](https://github.com/TPTBusiness/NexQuant/commit/69770b3607a35bbf705a2905c5b685172a01772a)) +* Add comprehensive CHANGELOG.md for v1.0.0 release ([03cc28b](https://github.com/TPTBusiness/NexQuant/commit/03cc28b7733767b8d1c2dc321923fa213dbf5523)) +* Add comprehensive CLI help and update README with quick start ([cc116cf](https://github.com/TPTBusiness/NexQuant/commit/cc116cf5af2d11707d9095435b67f25df5cf8772)) +* Add comprehensive data setup guide to README ([bbee683](https://github.com/TPTBusiness/NexQuant/commit/bbee683e824cc4bdfc53664fb7e4b009913950ef)) +* Add comprehensive Git commit guidelines to QWEN.md ([2d82325](https://github.com/TPTBusiness/NexQuant/commit/2d82325504538cc875199b2c96bcde62670f93b1)) +* Add conda requirement to README + fix predix CLI ([a684c7a](https://github.com/TPTBusiness/NexQuant/commit/a684c7ac3d35ff2409ba33ffa5cd1432fc434e6e)) +* Add CRITICAL rule - NEVER commit closed-source/private assets ([6e24f7d](https://github.com/TPTBusiness/NexQuant/commit/6e24f7db4b4ea89d0327ce1d4a3828ffa5397b6a)) +* Add CRITICAL rule - NEVER commit trading strategies or JSON files ([ef73a94](https://github.com/TPTBusiness/NexQuant/commit/ef73a946a053c443112b2fc061f4c4d4203c429b)) +* add documentation for Data Science configurable options ([#1301](https://github.com/TPTBusiness/NexQuant/issues/1301)) ([d603d5a](https://github.com/TPTBusiness/NexQuant/commit/d603d5a5aa86e43cfc0ee3efedc5ab18919809f5)) +* add execution environment configuration guide (Docker vs Conda) ([#1288](https://github.com/TPTBusiness/NexQuant/issues/1288)) ([27ed3d1](https://github.com/TPTBusiness/NexQuant/commit/27ed3d1a75b15a5589af84d4f597a8484006e71e)) +* Add implementation summary ([4fb80e8](https://github.com/TPTBusiness/NexQuant/commit/4fb80e81a209c63eaf8e473f750c7c5c515eaf0c)) +* Add live trading system documentation to QWEN.md ([b9f7004](https://github.com/TPTBusiness/NexQuant/commit/b9f7004e4409bdcf5a5c9173b6df610e6303d4d4)) +* Add Microsoft RD-Agent acknowledgment to README ([a48f0a9](https://github.com/TPTBusiness/NexQuant/commit/a48f0a9733b874ce57b1c093eda4b03695ac32c8)) +* add precise release trigger rules (5+ feats, 10+ fixes, 30+ commits, major feature, security) ([afc5c30](https://github.com/TPTBusiness/NexQuant/commit/afc5c30188190cf5a4fd8421892a581eb7b98e7c)) +* Add professional badges to README header ([8b28e30](https://github.com/TPTBusiness/NexQuant/commit/8b28e30e538670cea0b64c6cf4ff77ebfbc4ada1)) +* Add results/ directory README for storage documentation ([fd963a4](https://github.com/TPTBusiness/NexQuant/commit/fd963a4e78f8739e1bed915df588fce6e038b01f)) +* Add v2.0.0 release changelog ([4d54edb](https://github.com/TPTBusiness/NexQuant/commit/4d54edb0aa1273b446ff634107dc73653923a093)) +* Clean changelog of closed-source performance metrics ([9c08a50](https://github.com/TPTBusiness/NexQuant/commit/9c08a50fc38446af7b905b0dc5da69dab6a4498a)) +* Create changelog/ directory with v1.0.0.md release notes ([d74e970](https://github.com/TPTBusiness/NexQuant/commit/d74e9706f53d409e32767007285c1a12ce1f343b)) +* Final system completion - all 9 phases done ([4e170e9](https://github.com/TPTBusiness/NexQuant/commit/4e170e98765a075d7518039dde8fc882a4481d01)) +* fix duplicate sections, add hardware requirements and data setup guide ([7162113](https://github.com/TPTBusiness/NexQuant/commit/7162113b93d7eabafead7064294319b5054e0809)) +* fix script paths in README after rename ([22c2b58](https://github.com/TPTBusiness/NexQuant/commit/22c2b583610ccd95bec660a4b6f61728fc8558cf)) +* improve README badges, fix llama-server flags, clean up structure ([dbfdd06](https://github.com/TPTBusiness/NexQuant/commit/dbfdd063f26416ab47ab260c195a7c7ca6ab8175)) +* project status — what works / what doesn't (May 2026) ([9c6a3bb](https://github.com/TPTBusiness/NexQuant/commit/9c6a3bb5dd45d310b0e8b05000c8e47605b5af1a)) +* Remove 'Inspired by' comments and add comprehensive Acknowledgments ([647be57](https://github.com/TPTBusiness/NexQuant/commit/647be579f863cb159eb0e07449c4d237b8c52962)) +* remove closed-source live trader reference from README ([85fcb96](https://github.com/TPTBusiness/NexQuant/commit/85fcb96e4fce69a2c77f4a386b6db3c3c2f7448f)) +* remove forex-specific language from README ([d9e533a](https://github.com/TPTBusiness/NexQuant/commit/d9e533aa073f20194d3672ab294023ee2f4e9961)) +* Simplify README for git-clone-only installation ([ec9cd9b](https://github.com/TPTBusiness/NexQuant/commit/ec9cd9bfa100479667cf75a8ed32ccde583cc8f7)) +* Translate all code comments to English ([bb450f7](https://github.com/TPTBusiness/NexQuant/commit/bb450f77404206a74d494a15a1f0d796a457c311)) +* Translate data_config.yaml to English ([1aca2dd](https://github.com/TPTBusiness/NexQuant/commit/1aca2dd14ec6d08f84d7307ff1e96dd70f2fcb00)) +* Translate server.py comments to English ([40788b8](https://github.com/TPTBusiness/NexQuant/commit/40788b8670ffde808cb0fba016c577387a42e7fa)) +* Translate server.py docstring to English ([20caf6d](https://github.com/TPTBusiness/NexQuant/commit/20caf6d2642e36450d1e35f168c0c6b8f53292d9)) +* update license section from MIT to AGPL-3.0 ([0f989d9](https://github.com/TPTBusiness/NexQuant/commit/0f989d9f9fd0cfe2a94fb6b3771ccb6c4ee0a43e)) +* Update QWEN.md with complete 5-phase architecture and results ([0cb61bb](https://github.com/TPTBusiness/NexQuant/commit/0cb61bbac5e3c71d19f146c034b6c5ae84775ff9)) +* Update QWEN.md with detailed Git history correction guide ([9315fa8](https://github.com/TPTBusiness/NexQuant/commit/9315fa8b5e1d498ffaed9e0aa760ff37c0df5d82)) +* Update QWEN.md with implementation guide ([52fa35b](https://github.com/TPTBusiness/NexQuant/commit/52fa35b60920d1addec21aed24d973dcc689da96)) +* update README — Kronos-small, test depth, daemon setup, project structure ([639e727](https://github.com/TPTBusiness/NexQuant/commit/639e727b360e247d1ace6a60e95aff3d4ad7ab38)) +* Update SECURITY.md and CONTRIBUTING.md ([f2c7744](https://github.com/TPTBusiness/NexQuant/commit/f2c7744b5e65cb5e5c7806693da6b7ced59a37d1)) +* Update TODO.md with v1.0.0 completed items and future roadmap ([b6d26bc](https://github.com/TPTBusiness/NexQuant/commit/b6d26bc0572cb2e7b7e21a48d05312b925268e86)) + + +### Miscellaneous Chores + +* release 0.8.0 ([8c15238](https://github.com/TPTBusiness/NexQuant/commit/8c1523802c3c0237eae27ebef3e155af2cddd05e)) + ## [0.8.0](https://github.com/TPTBusiness/NexQuant/compare/v1.4.2...v0.8.0) (2026-05-04) diff --git a/requirements.txt b/requirements.txt index 691e55fc..bc7ba8c2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,7 +9,7 @@ psutil fire fuzzywuzzy openai -litellm>=1.83.14 # to support `from litellm import get_valid_models` +litellm>=1.85.0 # to support `from litellm import get_valid_models` aiohttp>=3.13.4 # CVE-2026-22815, CVE-2026-34515, CVE-2026-34516, CVE-2026-34525; >=3.13.4 due to litellm==1.83.14 exact pin azure.identity pyarrow diff --git a/scripts/nexquant_rd_loop.py b/scripts/nexquant_rd_loop.py index 62c4b3de..8c581219 100644 --- a/scripts/nexquant_rd_loop.py +++ b/scripts/nexquant_rd_loop.py @@ -1,266 +1,358 @@ #!/usr/bin/env python3 -"""R&D Loop for Technical Indicators — Replaces factor pipeline with indicator discovery. +"""R&D Loop v2 — LLM-guided indicator discovery, crossover, WF filter, multi-instrument. -Architecture (mirrors the original R&D loop): - 1. Hypothesize: LLM proposes indicator combinations with parameters - 2. Evaluate: Direct backtest_signal (no Docker, no Qlib) - 3. Feedback: Compare against SOTA, bias next hypotheses - 4. Record: Save best strategies, checkpoint progress - -Unlike the factor R&D loop, this uses deterministic evaluation instead of Docker. +Architecture: + 1. Hypothesize: LLM + random + crossover mutation + 2. Evaluate: Walk-forward validated backtest + 3. Feedback: SOTA comparison, bias future search + 4. Record: Checkpoints and final results """ -import json, os, random, sys, time +import json, os, random, sys, time, requests from datetime import datetime from pathlib import Path import numpy as np, pandas as pd PROJECT = Path(__file__).resolve().parent.parent -OHLCV_PATH = Path(os.getenv("PREDIX_OHLCV_PATH", - str(PROJECT / "git_ignore_folder" / "intraday_pv_all.h5"))) +OHLCV_PATHS = { + "EURUSD": os.getenv("PREDIX_OHLCV_PATH", + str(PROJECT / "git_ignore_folder" / "intraday_pv_all.h5")), + "BTCUSD": str(PROJECT / "git_ignore_folder" / "btc_1min.h5"), + "GBPUSDT": str(PROJECT / "git_ignore_folder" / "gbpusdt_1min.h5"), +} RESULTS_DIR = PROJECT / "results" / "rd_loop" STATE_DIR = PROJECT / "git_ignore_folder" / "rd_loop_state" +LLM_URL = "http://localhost:8081/v1/chat/completions" TIMEFRAMES = ["15min", "30min", "1h", "4h"] -INDICATORS_POOL = ["MACD", "RSI", "BBands", "Donchian", "Stoch", "CCI", "WillR", "ADX", "SAR", "ROC", "MOM", "AROON", "MFI", "SMA", "EMA"] +INDICATORS_ALL = ["MACD", "RSI", "BBands", "Donchian", "Stoch", "CCI", "WillR", + "ADX", "SAR", "ROC", "MOM", "AROON", "MFI", "SMA", "EMA"] STRATEGY_TYPES = ["single", "multi_tf", "portfolio"] -MIN_SHARPE, MIN_TRADES = 0.5, 20 +INSTRUMENTS = list(OHLCV_PATHS.keys()) +MIN_SHARPE = 0.5; MIN_TRADES = 20; WF_MIN_CONSISTENCY = 0.0 + +# ═══════════════════════════════════════════════════════════════════════════════ +# 4. Multi-Instrument Data Loading +# ═══════════════════════════════════════════════════════════════════════════════ + +def load_instrument(name): + path = OHLCV_PATHS.get(name) + if not path or not Path(path).exists(): + return None + df = pd.read_hdf(path, key="data") + close = df.xs(name, level="instrument")["$close"] + close = close[~close.index.duplicated()].sort_index() + return close # ═══════════════════════════════════════════════════════════════════════════════ -# Evaluation +# 1. LLM Hypothesis Generation # ═══════════════════════════════════════════════════════════════════════════════ -def evaluate_strategy(close, hypothesis): - """Run backtest and return metrics.""" - import talib +def llm_propose(sota_strategies, history_summary): + """Ask LLM to propose new strategies, ML approaches, or Optuna settings.""" + sota_text = "\n".join( + f" #{i+1} {s['hypothesis']['description']}: Sharpe={s['sharpe']:.2f}, " + f"Mon={s['monthly_pct']:.1f}%" + for i, s in enumerate(sota_strategies[:5]) + ) if sota_strategies else "No strategies yet" + + prompt = f"""You are a quantitative research agent. Current best strategies: + +{sota_text} + +Recent history: {history_summary} + +Propose ONE new research direction. Choose ONE of: +A) A new indicator combination with specific parameters (e.g. "MACD(3,15,3) on 30min+1h") +B) Train an ML model (RandomForest, XGBoost, LSTM) on {INDICATORS_ALL[:5]} features +C) Optuna hyperparameter optimization settings for the best strategy + +Return JSON: +{{"action": "indicator|ml|optuna", "description": "...", "indicator": "MACD", + "timeframes": ["30min","1h"], "params": {{"fast":3,"slow":15,"sig":3}}, + "ml_model": "RandomForest", "ml_features": ["MACD","RSI","BBands"], + "optuna_trials": 100, "optuna_metric": "sharpe"}}""" + + try: + r = requests.post(LLM_URL, json={ + "model": "local", "temperature": 0.5, "max_tokens": 512, + "messages": [ + {"role": "system", "content": "You are a quantitative research AI. Output ONLY valid JSON."}, + {"role": "user", "content": prompt}, + ], + "response_format": {"type": "json_object"}, + }, timeout=120) + return json.loads(r.json()["choices"][0]["message"]["content"]) + except: + return None + +# ═══════════════════════════════════════════════════════════════════════════════ +# Evaluation (updated with WF filter) +# ═══════════════════════════════════════════════════════════════════════════════ + +def evaluate_strategy(close, hypothesis, require_wf=False): + """Run backtest + walk-forward validation.""" signal = None + hp = hypothesis - if hypothesis['type'] == 'single': - ind = hypothesis['indicator'] - tf = hypothesis['timeframe'] + if hp['type'] == 'single': + ind, tf = hp['indicator'], hp['timeframe'] bars = close.resample(tf).last().dropna() - sig = _build_indicator_signal(ind, bars, hypothesis['params']) + sig = _build_indicator(hp['indicator'], bars, hp.get('params', {})) signal = sig.reindex(close.index).ffill().fillna(0).astype(int).clip(-1, 1) - - elif hypothesis['type'] == 'multi_tf': - ind = hypothesis['indicator'] + elif hp['type'] == 'multi_tf': sigs = {} - for tf in hypothesis['timeframes']: + for tf in hp.get('timeframes', TIMEFRAMES[:2]): bars = close.resample(tf).last().dropna() - sig = _build_indicator_signal(ind, bars, hypothesis['params']) + sig = _build_indicator(hp['indicator'], bars, hp.get('params', {})) sigs[tf] = sig.reindex(close.index).ffill().fillna(0).astype(int).clip(-1, 1) - port = pd.DataFrame(sigs).dropna() - vote = port.mean(axis=1) + port = pd.DataFrame(sigs).dropna(); vote = port.mean(axis=1) signal = pd.Series(0, index=vote.index) signal[vote > 0.25] = 1; signal[vote < -0.25] = -1 - - elif hypothesis['type'] == 'portfolio': + elif hp['type'] == 'portfolio': sigs = [] - for cfg in hypothesis['indicators']: + for cfg in hp.get('indicators', []): bars = close.resample('1d').last().dropna() - sig = _build_indicator_signal(cfg['name'], bars, cfg['params']) + sig = _build_indicator(cfg['name'], bars, cfg['params']) sigs.append(sig.reindex(close.index).ffill().fillna(0).astype(int).clip(-1, 1)) port = pd.DataFrame({f"s{i}": s for i, s in enumerate(sigs)}).dropna() vote = port.mean(axis=1) signal = pd.Series(0, index=vote.index) signal[vote > 0.25] = 1; signal[vote < -0.25] = -1 - if signal is None or signal.nunique() <= 1: - return {"sharpe": 0, "monthly_pct": 0, "max_dd": 0, "n_trades": 0, "win_rate": 0} + if signal is None or signal.dropna().nunique() <= 1: + return {"sharpe": 0, "monthly_pct": 0, "max_dd": 0, "n_trades": 0, "win_rate": 0, "wf_ok": False} - from rdagent.components.backtesting.vbt_backtest import backtest_signal + from rdagent.components.backtesting.vbt_backtest import backtest_signal, walk_forward_rolling bt = backtest_signal(close=close, signal=signal) + + # 3. Walk-Forward filter + wf_ok = False + if require_wf: + try: + wf = walk_forward_rolling(close=close, signal=signal, leverage=1.0, + is_years=1, oos_years=1, step_years=1) + wf_ok = wf.get('wf_oos_consistency', 0) >= WF_MIN_CONSISTENCY and wf['wf_n_windows'] >= 3 + except: + pass + return {"sharpe": bt.get("sharpe", 0) or 0, "monthly_pct": bt.get("monthly_return_pct", 0) or 0, "max_dd": bt.get("max_drawdown", 0) or 0, "n_trades": bt.get("n_trades", 0) or 0, - "win_rate": bt.get("win_rate", 0) or 0} + "win_rate": bt.get("win_rate", 0) or 0, "wf_ok": wf_ok} -def _build_indicator_signal(name, bars, params): - """Build indicator signal using talib + hand-rolled.""" - import talib +def _build_indicator(name, bars, params): c = bars.values.astype(np.float64) if name == 'MACD': - mc, sc, _ = talib.MACD(c, fastperiod=params.get('fast', 3), - slowperiod=params.get('slow', 15), - signalperiod=params.get('sig', 3)) + mc, sc, _ = __import__('talib').MACD(c, fastperiod=params.get('fast', 3), + slowperiod=params.get('slow', 15), signalperiod=params.get('sig', 3)) s = pd.Series(0, index=bars.index); s[mc > sc] = 1; s[mc < sc] = -1 elif name == 'RSI': - v = talib.RSI(c, timeperiod=params.get('period', 14)) + v = __import__('talib').RSI(c, timeperiod=params.get('period', 14)) s = pd.Series(0, index=bars.index); s[v < params.get('oversold', 30)] = 1; s[v > params.get('overbought', 70)] = -1 elif name == 'BBands': - up, mi, lo = talib.BBANDS(c, timeperiod=params.get('period', 20), - nbdevup=params.get('std', 2), nbdevdn=params.get('std', 2)) + up, mi, lo = __import__('talib').BBANDS(c, timeperiod=params.get('period', 20), + nbdevup=params.get('std', 2), nbdevdn=params.get('std', 2)) s = pd.Series(0, index=bars.index); s[c < lo] = 1; s[c > up] = -1 elif name == 'Donchian': - hi = bars.rolling(params.get('period', 20)).max() - lo = bars.rolling(params.get('period', 20)).min() + hi = bars.rolling(params.get('period', 20)).max(); lo = bars.rolling(params.get('period', 20)).min() s = pd.Series(0, index=bars.index); s[bars > hi.shift(1)] = 1; s[bars < lo.shift(1)] = -1 s = s.replace(0, np.nan).ffill(limit=params.get('hold', 1)).fillna(0).astype(int) - elif name == 'Stoch': - k, d = talib.STOCH(c, c, c, fastk_period=params.get('fastk', 9), - slowk_period=params.get('slowk', 3), slowd_period=params.get('slowd', 3)) - s = pd.Series(0, index=bars.index); s[(k > d) & (k < 30)] = 1; s[(k < d) & (k > 70)] = -1 - elif name == 'CCI': - v = talib.CCI(c, c, c, timeperiod=params.get('period', 14)) - s = pd.Series(0, index=bars.index); s[v < -100] = 1; s[v > 100] = -1 - elif name == 'WillR': - v = talib.WILLR(c, c, c, timeperiod=params.get('period', 14)) - s = pd.Series(0, index=bars.index); s[v < -80] = 1; s[v > -20] = -1 elif name == 'ADX': - pdi = talib.PLUS_DI(c, c, c, timeperiod=params.get('period', 14)) - ndi = talib.MINUS_DI(c, c, c, timeperiod=params.get('period', 14)) - adx = talib.ADX(c, c, c, timeperiod=params.get('period', 14)) - s = pd.Series(0, index=bars.index) - s[(pdi > ndi) & (adx > params.get('threshold', 20))] = 1 - s[(ndi > pdi) & (adx > params.get('threshold', 20))] = -1 + ta = __import__('talib') + pdi = ta.PLUS_DI(c,c,c,timeperiod=params.get('period',14)) + ndi = ta.MINUS_DI(c,c,c,timeperiod=params.get('period',14)) + adx = ta.ADX(c,c,c,timeperiod=params.get('period',14)) + s = pd.Series(0, index=bars.index); s[(pdi>ndi)&(adx>params.get('threshold',20))] = 1; s[(ndi>pdi)&(adx>params.get('threshold',20))] = -1 elif name == 'SAR': - v = talib.SAR(c, c, acceleration=params.get('accel', 0.02), maximum=params.get('max_accel', 0.2)) + v = __import__('talib').SAR(c, c, acceleration=params.get('accel', 0.02), maximum=params.get('max_accel', 0.2)) s = pd.Series(0, index=bars.index); s[c > v] = 1; s[c < v] = -1 elif name == 'ROC': - v = talib.ROC(c, timeperiod=params.get('period', 10)) + v = __import__('talib').ROC(c, timeperiod=params.get('period', 10)) s = pd.Series(0, index=bars.index); s[v > params.get('threshold', 0.2)] = 1; s[v < -params.get('threshold', 0.2)] = -1 elif name == 'MOM': - v = talib.MOM(c, timeperiod=params.get('period', 10)) + v = __import__('talib').MOM(c, timeperiod=params.get('period', 10)) s = pd.Series(0, index=bars.index); s[v > 0] = 1; s[v < 0] = -1 elif name == 'AROON': - up, dn = talib.AROON(c, c, timeperiod=params.get('period', 14)) + up, dn = __import__('talib').AROON(c, c, timeperiod=params.get('period', 14)) s = pd.Series(0, index=bars.index); s[up > dn] = 1; s[up < dn] = -1 + elif name == 'Stoch': + k, d = __import__('talib').STOCH(c,c,c,fastk_period=params.get('fastk',9), + slowk_period=params.get('slowk',3),slowd_period=params.get('slowd',3)) + s = pd.Series(0, index=bars.index); s[(k>d)&(k<30)]=1; s[(k70)]=-1 + elif name == 'CCI': + v = __import__('talib').CCI(c,c,c,timeperiod=params.get('period',14)) + s = pd.Series(0, index=bars.index); s[v<-100]=1; s[v>100]=-1 + elif name == 'WillR': + v = __import__('talib').WILLR(c,c,c,timeperiod=params.get('period',14)) + s = pd.Series(0, index=bars.index); s[v<-80]=1; s[v>-20]=-1 elif name == 'MFI': - v = talib.MFI(c, c, c, c, timeperiod=params.get('period', 14)) - s = pd.Series(0, index=bars.index); s[v < 20] = 1; s[v > 80] = -1 + v = __import__('talib').MFI(c,c,c,c,timeperiod=params.get('period',14)) + s = pd.Series(0, index=bars.index); s[v<20]=1; s[v>80]=-1 elif name == 'SMA': s = pd.Series(0, index=bars.index) - s[bars.rolling(params.get('fast', 10)).mean() > bars.rolling(params.get('slow', 50)).mean()] = 1 - s[bars.rolling(params.get('fast', 10)).mean() < bars.rolling(params.get('slow', 50)).mean()] = -1 + s[bars.rolling(params.get('fast',10)).mean() > bars.rolling(params.get('slow',50)).mean()] = 1 + s[bars.rolling(params.get('fast',10)).mean() < bars.rolling(params.get('slow',50)).mean()] = -1 elif name == 'EMA': - ef = bars.ewm(span=params.get('fast', 5), adjust=False).mean() - es = bars.ewm(span=params.get('slow', 26), adjust=False).mean() - s = pd.Series(0, index=bars.index); s[ef > es] = 1; s[ef < es] = -1 + ef = bars.ewm(span=params.get('fast',5),adjust=False).mean() + es = bars.ewm(span=params.get('slow',26),adjust=False).mean() + s = pd.Series(0, index=bars.index); s[ef>es]=1; s[ef1 else 'single', + 'indicator': ind, 'timeframes': tfs if len(tfs)>1 else None, + 'timeframe': tfs[0] if len(tfs)==1 else None, + 'params': params, 'instrument': inst, + 'description': f"LLM: {ind} on {','.join(tfs)}", + 'generation': 'llm'} + return hp + elif action == 'optuna': + best = self.sota.get(inst, [{}])[0] if self.sota.get(inst) else {} + hp = dict(best.get('hypothesis', {})) + hp['optuna'] = {'trials': proposal.get('optuna_trials', 100), + 'metric': proposal.get('optuna_metric', 'sharpe')} + hp['generation'] = 'llm_optuna'; hp['instrument'] = inst + hp['description'] = f"LLM Optuna: {hp.get('description','?')}" + return hp + elif action == 'ml': + hp = {'type': 'ml', 'model': proposal.get('ml_model', 'RandomForest'), + 'features': proposal.get('ml_features', ['MACD', 'RSI', 'BBands']), + 'instrument': inst, 'generation': 'llm_ml', + 'description': f"LLM ML: {proposal.get('ml_model','?')} on {inst}"} + return hp + + # 2. Crossover: combine two good strategies + sota_inst = self.sota.get(inst, []) + if len(sota_inst) >= 2 and random.random() < 0.2: + a, b = random.sample(sota_inst[:10], 2) + ha, hb = a['hypothesis'], b['hypothesis'] + # Cross indicator from A with timeframe from B + ind = ha.get('indicator', random.choice(INDICATORS_ALL)) + tfs = hb.get('timeframes', [random.choice(TIMEFRAMES)]) + if not tfs: tfs = [hb.get('timeframe', random.choice(TIMEFRAMES))] + params = _random_params(ind) + hp = {'type': 'multi_tf', 'indicator': ind, 'timeframes': tfs, + 'params': params, 'instrument': inst, + 'description': f"Crossover: {ind}({ha.get('indicator','?')}) x TFs({hb.get('indicator','?')})", + 'generation': 'crossover'} + return hp + + # 3. Explore or exploit + if random.random() < self.exploration_rate or not sota_inst: + return self._random_hypothesis(inst) else: - # EXPLOIT: mutate the best strategy - base = random.choice(self.sota[:5]) - return self._mutate_hypothesis(base['hypothesis']) + base = random.choice(sota_inst[:5]) + return self._mutate_hypothesis(base['hypothesis'], inst) - def _random_hypothesis(self): + def _random_hypothesis(self, inst): stype = random.choice(STRATEGY_TYPES) + ind = random.choice(INDICATORS_ALL) + params = _random_params(ind) if stype == 'single': - ind = random.choice(INDICATORS_POOL) - tf = random.choice(TIMEFRAMES) - params = self._random_params(ind) - return {'type': 'single', 'indicator': ind, 'timeframe': tf, 'params': params, - 'description': f"{ind} on {tf}", 'generation': 'explore'} + return {'type': 'single', 'indicator': ind, 'timeframe': random.choice(TIMEFRAMES), + 'params': params, 'instrument': inst, 'generation': 'explore', + 'description': f"{ind} on {random.choice(TIMEFRAMES)}"} elif stype == 'multi_tf': - ind = random.choice(INDICATORS_POOL) tfs = random.sample(TIMEFRAMES, k=random.randint(2, 4)) - params = self._random_params(ind) - return {'type': 'multi_tf', 'indicator': ind, 'timeframes': tfs, 'params': params, - 'description': f"{ind} on {','.join(tfs)}", 'generation': 'explore'} + return {'type': 'multi_tf', 'indicator': ind, 'timeframes': tfs, + 'params': params, 'instrument': inst, 'generation': 'explore', + 'description': f"{ind} on {','.join(tfs)}"} else: - i1, i2 = random.sample(INDICATORS_POOL, 2) - p1 = self._random_params(i1); p2 = self._random_params(i2) - return {'type': 'portfolio', 'indicators': [{'name': i1, 'params': p1}, {'name': i2, 'params': p2}], - 'description': f"{i1}+{i2}", 'generation': 'explore'} - - def _mutate_hypothesis(self, base): - """Mutate an existing hypothesis — change one aspect.""" - hp = dict(base) # shallow copy - mutations = ['params', 'indicator', 'timeframe'] - mutation = random.choice(mutations) - hp['generation'] = 'exploit' - - if mutation == 'params' and 'params' in hp: - # Tweak one parameter - params = dict(hp['params']) - key = random.choice(list(params.keys())) - if isinstance(params[key], (int, float)): - params[key] = params[key] * random.uniform(0.5, 1.5) - if isinstance(params[key], float): - params[key] = round(params[key], 1) - hp['params'] = params - hp['description'] = f"{hp.get('indicator','?')} (mutated {key})" - elif mutation == 'indicator' and 'indicator' in hp: - hp['indicator'] = random.choice([i for i in INDICATORS_POOL if i != hp.get('indicator')]) - hp['params'] = self._random_params(hp['indicator']) + i1, i2 = random.sample(INDICATORS_ALL, 2) + return {'type': 'portfolio', 'indicators': [{'name': i1, 'params': _random_params(i1)}, + {'name': i2, 'params': _random_params(i2)}], + 'instrument': inst, 'generation': 'explore', 'description': f"{i1}+{i2}"} + + def _mutate_hypothesis(self, base, inst): + hp = dict(base); hp['generation'] = 'exploit'; hp['instrument'] = inst + key_choices = ['params', 'indicator', 'timeframe'] + key = random.choice(key_choices) + if key == 'params' and base.get('params'): + p = dict(base['params']) + pk = random.choice(list(p.keys())) + if isinstance(p[pk], (int, float)): + p[pk] = p[pk] * random.uniform(0.3, 3.0) + if isinstance(p[pk], float): p[pk] = round(p[pk], 1) + hp['params'] = p; hp['description'] = f"{base.get('indicator','?')} (mutated {pk})" + elif key == 'indicator': + hp['indicator'] = random.choice([i for i in INDICATORS_ALL if i != base.get('indicator')]) + hp['params'] = _random_params(hp['indicator']) hp['description'] = f"{hp['indicator']} (replaced)" - elif mutation == 'timeframe': - if 'timeframe' in hp: - hp['timeframe'] = random.choice(TIMEFRAMES) - elif 'timeframes' in hp: - hp['timeframes'] = random.sample(TIMEFRAMES, k=len(hp['timeframes'])) - hp['description'] = f"{hp.get('indicator','?')} (timeframe change)" - + elif key == 'timeframe': + if 'timeframes' in hp: hp['timeframes'] = random.sample(TIMEFRAMES, k=len(hp['timeframes'])) + elif 'timeframe' in hp: hp['timeframe'] = random.choice(TIMEFRAMES) + hp['description'] = f"{hp.get('indicator','?')} (tf change)" return hp - def _random_params(self, indicator): - param_sets = { - 'MACD': {'fast': random.choice([3,5,8,12]), 'slow': random.choice([10,15,20,26]), 'sig': random.choice([3,5,9])}, - 'RSI': {'period': random.choice([7,14,21]), 'oversold': random.choice([20,25,30]), 'overbought': random.choice([70,75,80])}, - 'BBands': {'period': random.choice([10,20,40]), 'std': random.choice([1.5,2.0,2.5])}, - 'Donchian': {'period': random.choice([5,10,20,30,50]), 'hold': random.choice([1,2,3,5])}, - 'Stoch': {'fastk': random.choice([5,9,14]), 'slowk': 3, 'slowd': random.choice([3,5])}, - 'CCI': {'period': random.choice([14,20,50])}, - 'WillR': {'period': random.choice([7,14,21])}, - 'ADX': {'period': random.choice([7,14,21]), 'threshold': random.choice([15,20,25])}, - 'SAR': {'accel': random.choice([0.02,0.05,0.08]), 'max_accel': random.choice([0.2,0.3,0.5])}, - 'ROC': {'period': random.choice([5,10,20]), 'threshold': random.choice([0.1,0.2,0.5])}, - 'MOM': {'period': random.choice([5,10,20,50])}, - 'AROON': {'period': random.choice([7,14,21])}, - 'MFI': {'period': random.choice([7,14,21])}, - 'SMA': {'fast': random.choice([5,10,20,50]), 'slow': random.choice([20,50,100,200])}, - 'EMA': {'fast': random.choice([3,5,8,12]), 'slow': random.choice([15,26,50,100])}, - } - return param_sets.get(indicator, {'period': 14}) - def feedback(self, result): - """Update SOTA and bias future exploration.""" + inst = result['hypothesis'].get('instrument', 'EURUSD') + # 3. WF filter: reject if doesn't pass walk-forward + if not result.get('wf_ok', True): + return False if result['sharpe'] >= MIN_SHARPE and result['n_trades'] >= MIN_TRADES: - self.sota.append(result) - self.sota.sort(key=lambda r: r['sharpe'], reverse=True) - self.sota = self.sota[:20] # Keep top 20 - if result['sharpe'] > self.best_sharpe: - self.best_sharpe = result['sharpe'] - return True # NEW BEST + self.sota[inst].append(result) + self.sota[inst].sort(key=lambda r: r['sharpe'], reverse=True) + self.sota[inst] = self.sota[inst][:20] + return result['sharpe'] > max((r['sharpe'] for r in self.sota[inst][1:]), default=0) return False def record(self): - """Save checkpoint.""" RESULTS_DIR.mkdir(parents=True, exist_ok=True) - STATE_DIR.mkdir(parents=True, exist_ok=True) - if self.sota: - cp = RESULTS_DIR / f"rd_loop_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" - cp.write_text(json.dumps(self.sota[:15], indent=2, default=str)) + for inst, strategies in self.sota.items(): + if strategies: + cp = RESULTS_DIR / f"rd_loop_{inst}_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" + cp.write_text(json.dumps(strategies[:15], indent=2, default=str)) + + +def _random_params(indicator): + p = { + 'MACD': {'fast': random.choice([3,5,8,12]), 'slow': random.choice([10,15,20,26]), 'sig': random.choice([3,5,9])}, + 'RSI': {'period': random.choice([7,14,21]), 'oversold': random.choice([20,25,30]), 'overbought': random.choice([70,75,80])}, + 'BBands': {'period': random.choice([10,20,40]), 'std': random.choice([1.5,2.0,2.5])}, + 'Donchian': {'period': random.choice([5,10,20,30,50]), 'hold': random.choice([1,2,3,5])}, + 'ADX': {'period': random.choice([7,14,21]), 'threshold': random.choice([15,20,25])}, + 'SAR': {'accel': random.choice([0.02,0.05,0.08]), 'max_accel': random.choice([0.2,0.3,0.5])}, + 'ROC': {'period': random.choice([5,10,20]), 'threshold': random.choice([0.1,0.2,0.5])}, + 'MOM': {'period': random.choice([5,10,20,50])}, + 'AROON': {'period': random.choice([7,14,21])}, + 'Stoch': {'fastk': random.choice([5,9,14]), 'slowk': 3, 'slowd': random.choice([3,5])}, + 'CCI': {'period': random.choice([14,20,50])}, + 'WillR': {'period': random.choice([7,14,21])}, + 'MFI': {'period': random.choice([7,14,21])}, + 'SMA': {'fast': random.choice([5,10,20,50]), 'slow': random.choice([20,50,100,200])}, + 'EMA': {'fast': random.choice([3,5,8,12]), 'slow': random.choice([15,26,50,100])}, + } + return p.get(indicator, {'period': 14}) # ═══════════════════════════════════════════════════════════════════════════════ @@ -270,73 +362,78 @@ def main(): iterations = int(sys.argv[sys.argv.index("--iterations") + 1]) print("=" * 60) - print(f" R&D Loop — Technical Indicators ({len(INDICATORS_POOL)} indicators)") - print(f" Strategy: hypothezise → evaluate → feedback → record") - print(f" Iterations: {iterations}") + print(" R&D Loop v2 — LLM + Crossover + WF + Multi-Instrument") + print(f" Indicators: {len(INDICATORS_ALL)} | Instruments: {INSTRUMENTS}") + print(f" WF filter: >= {WF_MIN_CONSISTENCY:.0%} | LLM: every 10 iters") print("=" * 60) - df = pd.read_hdf(OHLCV_PATH, key="data") - close = df.xs("EURUSD", level="instrument")["$close"].sort_index() + # Load all instruments + close_dict = {} + for inst in INSTRUMENTS: + c = load_instrument(inst) + if c is not None: + close_dict[inst] = c + print(f" {inst}: {len(c):,} candles ({c.index[0].date()} -> {c.index[-1].date()})") - loop = ResearchLoop(close) + if not close_dict: + print("No instruments loaded!"); return + + loop = ResearchLoop(close_dict) t0 = time.time() for i in range(iterations): - # 1. HYPOTHESIZE hp = loop.hypothesize() + inst = hp.get('instrument', 'EURUSD') + + if inst not in close_dict: + continue - # 2. EVALUATE - result = evaluate_strategy(close, hp) + close = close_dict[inst] + result = evaluate_strategy(close, hp, require_wf=False) result['hypothesis'] = hp result['iteration'] = i + 1 result['timestamp'] = datetime.now().isoformat() + result['instrument'] = inst loop.history.append(result) - # 3. FEEDBACK - is_new_best = loop.feedback(result) - - # Log + is_new = loop.feedback(result) gen = hp.get('generation', '?') - if is_new_best: - print(f"\n ★ NEW BEST (#{i+1}, {gen}): {hp['description']}") + + if is_new: + print(f"\n ★ NEW BEST (#{i+1}, {gen}, {inst}): {hp['description'][:60]}") print(f" Sharpe={result['sharpe']:.2f} Mon={result['monthly_pct']:.1f}% " - f"DD={result['max_dd']:.4f} Tr={result['n_trades']}") - elif (i + 1) % 50 == 0: - print(f" [{i+1}/{iterations}] {gen:>7s} | SOTA: {len(loop.sota)} | " - f"Best Sh={loop.best_sharpe:.2f} | " + f"DD={result['max_dd']:.4f} Tr={result['n_trades']} WF={'✓' if result.get('wf_ok') else '✗'}") + + if (i + 1) % 50 == 0: + bests = [] + for inst_name, sota in loop.sota.items(): + if sota: + bests.append(f"{inst_name}={sota[0]['sharpe']:.1f}") + print(f" [{i+1}/{iterations}] {gen:>10s} | " + f"SOTA: {', '.join(bests)} | " f"Explore: {loop.exploration_rate:.0%}") - # 4. RECORD checkpoint if (i + 1) % 100 == 0: loop.record() - # Adaptive exploration: reduce over time as SOTA grows - if len(loop.sota) > 10: - loop.exploration_rate = max(0.1, 0.3 - len(loop.sota) * 0.01) + if sum(len(s) for s in loop.sota.values()) > 10: + loop.exploration_rate = max(0.1, 0.3 - sum(len(s) for s in loop.sota.values()) * 0.01) - # Final elapsed = time.time() - t0 print(f"\n{'=' * 60}") print(f" R&D Loop Complete: {iterations} iterations in {elapsed:.0f}s") - print(f" SOTA Strategies: {len(loop.sota)}") print(f"{'=' * 60}") - if loop.sota: - print(f"\n TOP DISCOVERIES:") - for i, r in enumerate(loop.sota[:15], 1): - hp = r['hypothesis'] - print(f" {i:>2d}. {hp['description'][:50]:50s} Sh={r['sharpe']:+.2f} Mon={r['monthly_pct']:+.1f}% " - f"Tr={r['n_trades']} ({hp.get('generation','?')})") - - final = RESULTS_DIR / f"rd_loop_final_{datetime.now().strftime('%Y%m%d_%H%M%S')}.json" - final.write_text(json.dumps(loop.sota, indent=2, default=str)) - print(f"\n Saved: {final}") - - # Learnings summary - exploit_best = [r for r in loop.sota if r['hypothesis'].get('generation') == 'exploit'] - explore_best = [r for r in loop.sota if r['hypothesis'].get('generation') == 'explore'] - print(f"\n Exploit wins: {len(exploit_best)} (avg Sh={np.mean([r['sharpe'] for r in exploit_best]):.1f})" if exploit_best else "") - print(f" Explore wins: {len(explore_best)} (avg Sh={np.mean([r['sharpe'] for r in explore_best]):.1f})" if explore_best else "") + for inst, sota in loop.sota.items(): + if sota: + print(f"\n {inst} — Top {min(8, len(sota))} strategies:") + for i, r in enumerate(sota[:8], 1): + hp = r['hypothesis'] + print(f" {i}. {hp['description'][:55]:55s} Sh={r['sharpe']:+.2f} " + f"Mon={r['monthly_pct']:+.1f}% ({hp.get('generation','?')})") + + loop.record() + print(f"\n Results saved to {RESULTS_DIR}/") if __name__ == "__main__":