]> Piment Noir Git Repositories - freqai-strategies.git/log
freqai-strategies.git
5 days agochore: remove stop_grace_period from docker-compose files
Jérôme Benoit [Fri, 1 May 2026 19:55:04 +0000 (21:55 +0200)] 
chore: remove stop_grace_period from docker-compose files

5 days agofix: pin pandas>=3.0 in Dockerfile and bump version to 3.11.7
Jérôme Benoit [Fri, 1 May 2026 19:03:15 +0000 (21:03 +0200)] 
fix: pin pandas>=3.0 in Dockerfile and bump version to 3.11.7

Prevent silent pandas downgrade to 2.x during pip install, which
causes dtype mismatches with freqtrade 2026.4 date handling code.
Includes epoch-ms range validation in ensure_datetime_series.

5 days agofix: ensure_datetime_series raises ValueError on None instead of silent corruption
Jérôme Benoit [Fri, 1 May 2026 17:20:24 +0000 (19:20 +0200)] 
fix: ensure_datetime_series raises ValueError on None instead of silent corruption

5 days agochore: bump strategy and model version to 3.11.6
Jérôme Benoit [Fri, 1 May 2026 16:09:02 +0000 (18:09 +0200)] 
chore: bump strategy and model version to 3.11.6

5 days agochore: remove unused json imports and fix line length formatting
Jérôme Benoit [Fri, 1 May 2026 16:02:23 +0000 (18:02 +0200)] 
chore: remove unused json imports and fix line length formatting

5 days agorefactor: replace lru_cache with cached_property for timeframe_minutes
Jérôme Benoit [Fri, 1 May 2026 15:53:59 +0000 (17:53 +0200)] 
refactor: replace lru_cache with cached_property for timeframe_minutes

5 days agorefactor: rename prepared to seeded in smma() for clarity
Jérôme Benoit [Fri, 1 May 2026 15:48:20 +0000 (17:48 +0200)] 
refactor: rename prepared to seeded in smma() for clarity

5 days agoperf: vectorize smma() using SMA-seeded ewm (no Python loop)
Jérôme Benoit [Fri, 1 May 2026 15:42:42 +0000 (17:42 +0200)] 
perf: vectorize smma() using SMA-seeded ewm (no Python loop)

5 days agofix: narrow bare except to specific types in statistical helpers
Jérôme Benoit [Fri, 1 May 2026 15:29:28 +0000 (17:29 +0200)] 
fix: narrow bare except to specific types in statistical helpers

5 days agorefactor: extract optuna_load/save_best_params to shared Utils
Jérôme Benoit [Fri, 1 May 2026 15:25:13 +0000 (17:25 +0200)] 
refactor: extract optuna_load/save_best_params to shared Utils

5 days agofix: validate epoch-ms range before converting int64 date columns
Jérôme Benoit [Fri, 1 May 2026 14:03:12 +0000 (16:03 +0200)] 
fix: validate epoch-ms range before converting int64 date columns

Reject int64 values outside [2010, 2035] epoch-ms range to fail fast
on corrupted data instead of silently producing wrong dates. Catches
nanosecond/microsecond values that would pass the int64 dtype check
but produce garbage timestamps if interpreted as milliseconds.

5 days agofix: add 30min stop_grace_period to prevent data corruption on shutdown
Jérôme Benoit [Fri, 1 May 2026 13:46:19 +0000 (15:46 +0200)] 
fix: add 30min stop_grace_period to prevent data corruption on shutdown

FreqAI training can take minutes to hours. Docker's default 10s grace
period causes SIGKILL mid-write, corrupting feather/pickle files.
Give freqtrade up to 30 minutes to finish training and flush data
before Docker sends SIGKILL.

5 days agofix: align ensure_datetime_series with freqtrade data handler pattern
Jérôme Benoit [Fri, 1 May 2026 10:32:33 +0000 (12:32 +0200)] 
fix: align ensure_datetime_series with freqtrade data handler pattern

Chain .dt.as_unit("ms") to guarantee datetime64[ms, UTC] output
resolution regardless of pandas version, matching the contract
established in freqtrade commit 2c5dc72.

Ref: freqtrade/freqtrade#13107

6 days agorefactor: extract ensure_datetime_series helper for date dtype workaround
Jérôme Benoit [Thu, 30 Apr 2026 22:51:29 +0000 (00:51 +0200)] 
refactor: extract ensure_datetime_series helper for date dtype workaround

Centralizes the int64 epoch-ms vs datetime detection logic into a shared
helper. Handles both formats correctly: unit='ms' for int64, passthrough
for existing datetime columns.

Ref: https://github.com/freqtrade/freqtrade/issues/13107

6 days agofix: workaround date dtype regression in FreqAI model training log
Jérôme Benoit [Thu, 30 Apr 2026 22:34:02 +0000 (00:34 +0200)] 
fix: workaround date dtype regression in FreqAI model training log

Same freqtrade 2026.4 regression (2c5dc72): unfiltered_df["date"] may
be int64 during training, causing .strftime() to fail.

Ref: https://github.com/freqtrade/freqtrade/issues/13107

6 days agochore: update serena project config template comments
Jérôme Benoit [Thu, 30 Apr 2026 22:15:38 +0000 (00:15 +0200)] 
chore: update serena project config template comments

6 days agofix: workaround freqtrade 2026.4 date column dtype regression
Jérôme Benoit [Thu, 30 Apr 2026 22:14:55 +0000 (00:14 +0200)] 
fix: workaround freqtrade 2026.4 date column dtype regression

Freqtrade 2026.4 (commit 2c5dc72) changed feather/parquet handlers to
use .dt.as_unit("ms") instead of to_datetime(col, unit="ms", utc=True).
This breaks when data files store dates as int64 epoch-ms, causing
AttributeError in feature_engineering_standard.

Use pd.to_datetime(col, utc=True) defensively to handle both int64 and
datetime inputs.

Ref: https://github.com/freqtrade/freqtrade/issues/13107

7 days agochore(deps): lock file maintenance (#67)
renovate[bot] [Wed, 29 Apr 2026 15:38:57 +0000 (17:38 +0200)] 
chore(deps): lock file maintenance (#67)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
11 days agoRevert "chore(deps): update poetry lock file"
Jérôme Benoit [Sat, 25 Apr 2026 14:46:27 +0000 (16:46 +0200)] 
Revert "chore(deps): update poetry lock file"

This reverts commit f96f0324f67438328a797346bce907efe70cf886.

11 days agochore: update openspec skills to v1.3.1
Jérôme Benoit [Sat, 25 Apr 2026 14:42:00 +0000 (16:42 +0200)] 
chore: update openspec skills to v1.3.1

11 days agochore(deps): update poetry lock file
Jérôme Benoit [Sat, 25 Apr 2026 14:41:54 +0000 (16:41 +0200)] 
chore(deps): update poetry lock file

13 days agodocs: neutralize Copilot-specific references in agent instructions
Jérôme Benoit [Thu, 23 Apr 2026 20:05:09 +0000 (22:05 +0200)] 
docs: neutralize Copilot-specific references in agent instructions

13 days agoperf(quickadapter): fine tune trade entry condition
Jérôme Benoit [Thu, 23 Apr 2026 14:21:49 +0000 (16:21 +0200)] 
perf(quickadapter): fine tune trade entry condition

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 weeks agochore: remove Cline references from devcontainer configurations
Jérôme Benoit [Wed, 22 Apr 2026 23:13:09 +0000 (01:13 +0200)] 
chore: remove Cline references from devcontainer configurations

2 weeks agochore: replace agent instruction indirections with symlinks to canonical source
Jérôme Benoit [Wed, 22 Apr 2026 23:09:35 +0000 (01:09 +0200)] 
chore: replace agent instruction indirections with symlinks to canonical source

2 weeks agochore(deps): lock file maintenance (#66)
renovate[bot] [Tue, 21 Apr 2026 11:50:34 +0000 (13:50 +0200)] 
chore(deps): lock file maintenance (#66)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agochore(deps): lock file maintenance (#63)
renovate[bot] [Tue, 14 Apr 2026 20:06:22 +0000 (22:06 +0200)] 
chore(deps): lock file maintenance (#63)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 weeks agobuild(deps): bump pytest in /ReforceXY/reward_space_analysis (#64)
dependabot[bot] [Tue, 14 Apr 2026 14:18:54 +0000 (16:18 +0200)] 
build(deps): bump pytest in /ReforceXY/reward_space_analysis (#64)

Bumps [pytest](https://github.com/pytest-dev/pytest) from 9.0.2 to 9.0.3.
- [Release notes](https://github.com/pytest-dev/pytest/releases)
- [Changelog](https://github.com/pytest-dev/pytest/blob/main/CHANGELOG.rst)
- [Commits](https://github.com/pytest-dev/pytest/compare/9.0.2...9.0.3)

---
updated-dependencies:
- dependency-name: pytest
  dependency-version: 9.0.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
4 weeks agochore(deps): lock file maintenance (#62)
renovate[bot] [Mon, 6 Apr 2026 16:14:05 +0000 (18:14 +0200)] 
chore(deps): lock file maintenance (#62)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
4 weeks agochore(qav3): refine reversal confirmation parameters
Jérôme Benoit [Mon, 6 Apr 2026 15:23:06 +0000 (17:23 +0200)] 
chore(qav3): refine reversal confirmation parameters

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
5 weeks agochore(quickadapter): refine template config parameters for better performance
Jérôme Benoit [Wed, 1 Apr 2026 16:19:33 +0000 (18:19 +0200)] 
chore(quickadapter): refine template config parameters for better performance

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
5 weeks agochore(deps): lock file maintenance (#60)
renovate[bot] [Tue, 31 Mar 2026 15:39:34 +0000 (17:39 +0200)] 
chore(deps): lock file maintenance (#60)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
5 weeks agobuild(deps): bump pygments in /ReforceXY/reward_space_analysis (#61)
dependabot[bot] [Tue, 31 Mar 2026 13:47:02 +0000 (15:47 +0200)] 
build(deps): bump pygments in /ReforceXY/reward_space_analysis (#61)

Bumps [pygments](https://github.com/pygments/pygments) from 2.19.2 to 2.20.0.
- [Release notes](https://github.com/pygments/pygments/releases)
- [Changelog](https://github.com/pygments/pygments/blob/master/CHANGES)
- [Commits](https://github.com/pygments/pygments/compare/2.19.2...2.20.0)

---
updated-dependencies:
- dependency-name: pygments
  dependency-version: 2.20.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
5 weeks agodocs: fix semantic accuracy of README configuration tunables
Jérôme Benoit [Tue, 31 Mar 2026 00:29:28 +0000 (02:29 +0200)] 
docs: fix semantic accuracy of README configuration tunables

- polyorder: correct range from int >= 1 to int >= 0 (savgol accepts degree-0)
- robust standardization: replace 'IQR' with '(Q₃-Q₁)' (quantiles are configurable)
- label_weights: broaden scope from 'distance calculations to ideal point' to 'trial selection methods'
- label_p_order: replace 'p-order parameter for distance metrics' with 'Lp exponent for parameterized metrics'
- label_density_aggregation_param: replace 'p-order' with 'Lp exponent' for consistency

6 weeks agochore(deps): update dependency ngboost to v0.5.10 (#59)
renovate[bot] [Wed, 25 Mar 2026 12:01:21 +0000 (13:01 +0100)] 
chore(deps): update dependency ngboost to v0.5.10 (#59)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
6 weeks agochore(deps): lock file maintenance (#58)
renovate[bot] [Mon, 23 Mar 2026 12:04:14 +0000 (13:04 +0100)] 
chore(deps): lock file maintenance (#58)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 weeks agochore(deps): lock file maintenance (#56)
renovate[bot] [Wed, 18 Mar 2026 18:12:30 +0000 (19:12 +0100)] 
chore(deps): lock file maintenance (#56)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 weeks agochore(deps): update dependency optuna to v4.8.0 (#57)
renovate[bot] [Tue, 17 Mar 2026 18:15:01 +0000 (19:15 +0100)] 
chore(deps): update dependency optuna to v4.8.0 (#57)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
7 weeks agochore: cleanup openspec opencode commands
Jérôme Benoit [Tue, 17 Mar 2026 13:02:09 +0000 (14:02 +0100)] 
chore: cleanup openspec opencode commands

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
7 weeks agochore: update serena project configuration with new settings
Jérôme Benoit [Sun, 15 Mar 2026 22:17:35 +0000 (23:17 +0100)] 
chore: update serena project configuration with new settings

7 weeks agochore(deps): lock file maintenance (#55)
renovate[bot] [Thu, 12 Mar 2026 11:46:19 +0000 (12:46 +0100)] 
chore(deps): lock file maintenance (#55)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agochore(deps): lock file maintenance (#54)
renovate[bot] [Wed, 4 Mar 2026 12:39:22 +0000 (13:39 +0100)] 
chore(deps): lock file maintenance (#54)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agochore(quickadapter): update config-template.json
Jérôme Benoit [Sun, 1 Mar 2026 20:14:59 +0000 (21:14 +0100)] 
chore(quickadapter): update config-template.json

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agofeat(reforcexy): log invalid actions with enum names for non-masking models
Jérôme Benoit [Sun, 1 Mar 2026 18:54:50 +0000 (19:54 +0100)] 
feat(reforcexy): log invalid actions with enum names for non-masking models

2 months agochore: update serena project configuration
Jérôme Benoit [Thu, 26 Feb 2026 21:55:31 +0000 (22:55 +0100)] 
chore: update serena project configuration

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agochore(deps): update dependency ngboost to v0.5.9 (#53)
renovate[bot] [Thu, 26 Feb 2026 13:20:15 +0000 (14:20 +0100)] 
chore(deps): update dependency ngboost to v0.5.9 (#53)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agochore: update OpenSpec artifacts
Jérôme Benoit [Tue, 24 Feb 2026 10:58:10 +0000 (11:58 +0100)] 
chore: update OpenSpec artifacts

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agorefactor(quickadapter): harmonize eps values across the codebase
Jérôme Benoit [Thu, 19 Feb 2026 09:07:21 +0000 (10:07 +0100)] 
refactor(quickadapter): harmonize eps values across the codebase

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agochore(deps): update dependency catboost to v1.2.10 (#52)
renovate[bot] [Thu, 19 Feb 2026 09:03:43 +0000 (10:03 +0100)] 
chore(deps): update dependency catboost to v1.2.10 (#52)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agofeat(zigzag): add normalize flag, disable in label_objective
Jérôme Benoit [Thu, 19 Feb 2026 00:51:39 +0000 (01:51 +0100)] 
feat(zigzag): add normalize flag, disable in label_objective

2 months agofix(zigzag): skip minmax normalization with single valid value
Jérôme Benoit [Thu, 19 Feb 2026 00:40:34 +0000 (01:40 +0100)] 
fix(zigzag): skip minmax normalization with single valid value

2 months agofix(normalization): use eps-based threshold for minmax numerical stability
Jérôme Benoit [Thu, 19 Feb 2026 00:15:08 +0000 (01:15 +0100)] 
fix(normalization): use eps-based threshold for minmax numerical stability

2 months agochore: bump version to 3.11.4
Jérôme Benoit [Wed, 18 Feb 2026 23:33:06 +0000 (00:33 +0100)] 
chore: bump version to 3.11.4

2 months agostyle(zigzag): harmonize minmax_scale with codebase conventions
Jérôme Benoit [Wed, 18 Feb 2026 23:21:54 +0000 (00:21 +0100)] 
style(zigzag): harmonize minmax_scale with codebase conventions

2 months agorefactor(zigzag): replace ad-hoc x/(x+y) normalization with pure ratios + MinMaxScaler
Jérôme Benoit [Wed, 18 Feb 2026 23:07:20 +0000 (00:07 +0100)] 
refactor(zigzag): replace ad-hoc x/(x+y) normalization with pure ratios + MinMaxScaler

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-opencode)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
2 months agochore(deps): update dependency catboost to v1.2.9 (#51)
renovate[bot] [Wed, 18 Feb 2026 15:51:33 +0000 (16:51 +0100)] 
chore(deps): update dependency catboost to v1.2.9 (#51)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agochore(deps): lock file maintenance (#50)
renovate[bot] [Mon, 16 Feb 2026 22:21:50 +0000 (23:21 +0100)] 
chore(deps): lock file maintenance (#50)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agodocs(quickadapter): clarify gpu_vram_gb is available VRAM, not total
Jérôme Benoit [Sun, 15 Feb 2026 15:09:31 +0000 (16:09 +0100)] 
docs(quickadapter): clarify gpu_vram_gb is available VRAM, not total

2 months agofeat(quickadapter): add VRAM-aware CatBoost GPU hyperparameter ranges
Jérôme Benoit [Sun, 15 Feb 2026 14:21:02 +0000 (15:21 +0100)] 
feat(quickadapter): add VRAM-aware CatBoost GPU hyperparameter ranges

2 months agofix(ReforceXY): exclude gpu_memory_fraction from model params
Jérôme Benoit [Sun, 15 Feb 2026 12:41:37 +0000 (13:41 +0100)] 
fix(ReforceXY): exclude gpu_memory_fraction from model params

2 months agofeat(ReforceXY): add gpu_memory_fraction tunable
Jérôme Benoit [Sun, 15 Feb 2026 12:31:58 +0000 (13:31 +0100)] 
feat(ReforceXY): add gpu_memory_fraction tunable

2 months agofix(devcontainer): disable gh config mount to avoid migration bug
Jérôme Benoit [Sat, 14 Feb 2026 23:57:39 +0000 (00:57 +0100)] 
fix(devcontainer): disable gh config mount to avoid migration bug

Prevents gh cli from failing due to multi-account migration when
keyring (dbus) is unavailable. GITHUB_TOKEN env var is used instead.

See: https://github.com/cli/cli/issues/8441

2 months agoconfig(ReforceXY): optimize RL training params
Jérôme Benoit [Fri, 13 Feb 2026 23:32:04 +0000 (00:32 +0100)] 
config(ReforceXY): optimize RL training params

- train_period_days: 120→90 (reduce training window)
- weight_factor: 0.9→0 (disable, unused by RL models)

2 months agodocs(quickadapter): sensible template defaults
Jérôme Benoit [Fri, 13 Feb 2026 15:54:41 +0000 (16:54 +0100)] 
docs(quickadapter): sensible template defaults

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agodocs(ReforceXY): document efficiency coefficient min_range guard
Jérôme Benoit [Thu, 12 Feb 2026 23:21:50 +0000 (00:21 +0100)] 
docs(ReforceXY): document efficiency coefficient min_range guard

2 months agoMerge branch 'main' of origin into main
Jérôme Benoit [Thu, 12 Feb 2026 23:16:32 +0000 (00:16 +0100)] 
Merge branch 'main' of origin into main

2 months agofix(ReforceXY): add context-aware guard for efficiency coefficient division
Jérôme Benoit [Thu, 12 Feb 2026 23:10:08 +0000 (00:10 +0100)] 
fix(ReforceXY): add context-aware guard for efficiency coefficient division

Prevent division explosion in _compute_efficiency_coefficient() when
max_unrealized_profit ≈ min_unrealized_profit by requiring a minimum
meaningful range based on pnl_target. Also adds validation warnings
for potential_gamma=0 and pnl_target<=0 edge cases.

2 months agofeat(ReforceXY): tune reward sensitivity and extend training period
Jérôme Benoit [Thu, 12 Feb 2026 14:17:10 +0000 (15:17 +0100)] 
feat(ReforceXY): tune reward sensitivity and extend training period

- Increase pnl_amplification_sensitivity from 0.5 to 2.0 for stronger
  reward signal differentiation
- Extend train_period_days from 60 to 120 for more training data

2 months agodocs: refine README formatting
Jérôme Benoit [Wed, 11 Feb 2026 23:19:49 +0000 (00:19 +0100)] 
docs: refine README formatting

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agofix(quickadapter): use Optuna params for TimeSeriesSplit gap calculation
Jérôme Benoit [Mon, 9 Feb 2026 21:04:23 +0000 (22:04 +0100)] 
fix(quickadapter): use Optuna params for TimeSeriesSplit gap calculation

Previously gap was calculated from ft_params with a hardcoded default, which could return incorrect values when Optuna optimized parameters. Also standardizes log message format to use [pair] prefix.

2 months agochore(deps): lock file maintenance (#49)
renovate[bot] [Mon, 9 Feb 2026 15:44:14 +0000 (16:44 +0100)] 
chore(deps): lock file maintenance (#49)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2 months agofeat(quickadapter): add TimeSeriesSplit as alternative data splitting method (#48)
Jérôme Benoit [Sun, 8 Feb 2026 23:55:14 +0000 (00:55 +0100)] 
feat(quickadapter): add TimeSeriesSplit as alternative data splitting method (#48)

* feat(model): add TimeSeriesSplit support via train() override

* docs(readme): document TimeSeriesSplit configuration options

* fix: address PR review comments

- Use test_size parameter in TimeSeriesSplit
- Remove unused dk parameter from _make_timeseries_split_datasets()
- Assign dk.data_dictionary = dd before logging
- Fix typo: train_test_test -> train_test_split in README

* docs: integrate data_split_parameters into tunables table

Remove standalone section and add parameters to existing table
with freqai. prefix for consistency.

* refactor: use FreqAI APIs for weight calculation and data dictionary

- Use dk.set_weights_higher_recent() instead of duplicating weight formula
- Use dk.build_data_dictionary() for consistent data structure
- Respects feature_parameters.weight_factor configuration
- Fix bug: was using data_kitchen_thread_count instead of weight_factor

* refactor: extract _apply_pipelines() to reduce code duplication

- Move pipeline definition and application logic to helper method
- Reduces train() override complexity while keeping same behavior
- Helper can be reused by future custom split implementations

* style: harmonize namespace and remove inline comments

- Rename DATA_SPLIT_METHODS to _DATA_SPLIT_METHODS (private tuple pattern)
- Reference DATA_SPLIT_METHOD_DEFAULT from _DATA_SPLIT_METHODS[0]
- Remove 22 inline comments to match self-documenting codebase style

* fix: align TimeSeriesSplit weight calculation with FreqAI semantics

Calculate weights on combined train+test set before splitting to maintain
temporal weight continuity, matching FreqAI's make_train_test_datasets behavior.

* feat: add gap=0 warning and improve TimeSeriesSplit validation

- Warn when gap=0 about look-ahead bias risk (reference label_period_candles)
- Add _compute_timeseries_min_samples() for accurate minimum sample calculation
- Account for gap and test_size in minimum sample validation
- Improve error message with all relevant parameters

* style: harmonize error messages with codebase conventions

- Use 'Invalid {param} value {value!r}: {constraint}' pattern
- Align with existing validation error format (lines 718, 1145)

* style: add cached set accessor for data split methods

- Add _data_split_methods_set() with @staticmethod @lru_cache
- Use QuickAdapterRegressorV3 prefix for class attribute access
- Use cached set for O(1) membership check in validation

* fix: address PR review comments for TimeSeriesSplit

- Use dd consistently in training logs instead of dk.data_dictionary
- Use self.data_split_parameters consistently in _apply_pipelines
- Add explicit type coercion for n_splits, gap, max_train_size
- Add validation for gap >= 0 and max_train_size >= 1
- Improve test_size validation: float in (0,1) as fraction, int >= 1 as count
- Fix _compute_timeseries_min_samples formula: (n_splits+1)*test_size + n_splits*gap
- Optimize tscv.split() iteration to avoid unnecessary list materialization

* fix: correct min_samples formula to match sklearn validation

sklearn validates: n_samples - gap - (test_size * n_splits) > 0
Correct formula: test_size * n_splits + gap + 1

* feat: auto-calculate TimeSeriesSplit gap from label_period_candles

When gap=0 is configured, automatically set gap to label_period_candles
to prevent look-ahead bias from overlapping label windows. This ensures
temporal separation between train and test sets without requiring manual
configuration.

* fix: remove redundant time import shadowing module

* fix: correct min_samples formula for dynamic test_size and document test_size param

* refactor: remove redundant TimeSeriesSplit min_samples validation

* docs: clarify test_size default per split method

* refactor: move DependencyException import to file header

* style: use class name for class constant access

* Apply suggestion from @Copilot

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* docs: use Python None instead of null in README

* docs: fix train_test_split description (sequential, not random)

* fix: use explicit None check for max_train_size validation

* docs: clarify timeseries_split as chronological split, not cross-validation

* refactor(quickadapter): shorten log prefixes and tailor empty test set error by split method

* refactor(quickadapter): use index pattern for timeseries_split method constant

Replace string literals with index access pattern following existing
codebase convention for _DATA_SPLIT_METHODS.

Also renames variables for semantic clarity:
- test_size_param -> test_size
- feat_dict -> feature_parameters

* refactor(quickadapter): use _TEST_SIZE constant instead of hardcoded 0.1

* chore(quickadapter): bump version to 3.11.2

* fix(quickadapter): restore test_size parameter in TimeSeriesSplit

The test_size variable from data_split_parameters was being
immediately overwritten by a type annotation line, making it
always None regardless of user configuration.

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2 months agorefactor: add opencode cache mounts to devcontainer.json
Jérôme Benoit [Sun, 8 Feb 2026 18:08:27 +0000 (19:08 +0100)] 
refactor: add opencode cache mounts to devcontainer.json

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
2 months agorefactor: .env initialization to devcontainer setup
Jérôme Benoit [Sun, 8 Feb 2026 18:01:40 +0000 (19:01 +0100)] 
refactor: .env initialization to devcontainer setup

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore(deps): lock file maintenance (#47)
renovate[bot] [Mon, 2 Feb 2026 19:10:54 +0000 (20:10 +0100)] 
chore(deps): lock file maintenance (#47)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 months agofix(ReforceXY): use .item() to extract scalar from action array
Jérôme Benoit [Sat, 31 Jan 2026 20:48:50 +0000 (21:48 +0100)] 
fix(ReforceXY): use .item() to extract scalar from action array

SB3 model.predict() returns 1D array when vectorized_env=True is detected, causing int() to fail on non-0D arrays.

3 months agofix: disable moby for docker-in-docker on Debian Trixie
Jérôme Benoit [Sat, 31 Jan 2026 19:58:48 +0000 (20:58 +0100)] 
fix: disable moby for docker-in-docker on Debian Trixie

3 months agochore: update openspec artifacts
Jérôme Benoit [Sat, 31 Jan 2026 18:34:59 +0000 (19:34 +0100)] 
chore: update openspec artifacts

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore: update .serena/project.yml
Jérôme Benoit [Fri, 30 Jan 2026 10:20:05 +0000 (11:20 +0100)] 
chore: update .serena/project.yml

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agodocs(openspec): add project context to config
Jérôme Benoit [Wed, 28 Jan 2026 15:20:54 +0000 (16:20 +0100)] 
docs(openspec): add project context to config

3 months agochore: update OpenSpec
Jérôme Benoit [Wed, 28 Jan 2026 12:00:12 +0000 (13:00 +0100)] 
chore: update OpenSpec

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore: mount host gh config directory instead of creating it manually
Jérôme Benoit [Wed, 28 Jan 2026 01:57:16 +0000 (02:57 +0100)] 
chore: mount host gh config directory instead of creating it manually

3 months agochore: update OpenSpec commands and documentation
Jérôme Benoit [Tue, 27 Jan 2026 12:46:29 +0000 (13:46 +0100)] 
chore: update OpenSpec commands and documentation

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore(quickadapter): use np.inf instead of float("inf")
Jérôme Benoit [Tue, 27 Jan 2026 11:42:53 +0000 (12:42 +0100)] 
chore(quickadapter): use np.inf instead of float("inf")

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agorefactor(quickadapter): use ndarray.size instead of len() for array length
Jérôme Benoit [Mon, 26 Jan 2026 20:50:42 +0000 (21:50 +0100)] 
refactor(quickadapter): use ndarray.size instead of len() for array length

3 months agorefactor(quickadapter): harmonize parameter naming in threshold computation
Jérôme Benoit [Mon, 26 Jan 2026 20:27:52 +0000 (21:27 +0100)] 
refactor(quickadapter): harmonize parameter naming in threshold computation

- Rename extrema_selection → selection_method to match tunable name
- Rename pred_extrema → pred_label for consistency across methods
- Rename n_extrema → n_values in _build_weights_array (generic function)
- Fix bug: use default_weight param instead of constant in early return

3 months agochore(deps): lock file maintenance (#46)
renovate[bot] [Mon, 26 Jan 2026 16:11:52 +0000 (17:11 +0100)] 
chore(deps): lock file maintenance (#46)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 months agorefactor(quickadapter): remove verbose optuna results logging
Jérôme Benoit [Mon, 26 Jan 2026 12:49:21 +0000 (13:49 +0100)] 
refactor(quickadapter): remove verbose optuna results logging

format_dict() now handles study_best_results in a single line, making
the per-key logging loop redundant.

3 months agorefactor(quickadapter): add format_dict helper and improve numeric formatting
Jérôme Benoit [Mon, 26 Jan 2026 12:23:51 +0000 (13:23 +0100)] 
refactor(quickadapter): add format_dict helper and improve numeric formatting

- Add format_dict() with singledispatch for type-safe dict/params formatting
- Refactor format_number() with unified significant digits formula
- Replace raw dict logging with format_dict() across strategy and model
- Remove redundant _format_label_method_config method
- Bump version to 3.11.1

3 months agochore: refine label logging messages to quote label column names
Jérôme Benoit [Sun, 25 Jan 2026 23:24:27 +0000 (00:24 +0100)] 
chore: refine label logging messages to quote label column names

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agorefactor(quickadapter): orthogonal multi-target label processing pipeline (#45)
Jérôme Benoit [Sun, 25 Jan 2026 22:55:46 +0000 (23:55 +0100)] 
refactor(quickadapter): orthogonal multi-target label processing pipeline (#45)

* refactor(quickadapter): orthogonal multi-target label processing pipeline

- Refactor label processing into 4 orthogonal phases:
  1. Weighting: apply weights to raw label values per column
  2. Smoothing: smooth weighted values per column
  3. Pipeline: LabelTransformer standardization per column
  4. Prediction: threshold calculation per column

- Loop over LABEL_COLUMNS for weighting and smoothing in set_freqai_targets()
- Loop over dk.label_list for thresholds in fit_live_predictions()
- All config helpers return {default, columns} structure with glob pattern support
- Rename ExtremaWeightingTransformer to LabelTransformer
- Harmonize namespace: label_weighting, label_smoothing, label_prediction
- Backward compatible with flat configs and legacy column names

* refactor: remove deprecated internal APIs

Remove unused deprecated functions that were replaced by the orthogonal
label processing architecture:
- get_label_transformer_config() from Utils.py
- get_label_transformer_config import from QuickAdapterV3.py
- extrema_smoothing property from QuickAdapterV3.py

* refactor: remove deprecated predictions_extrema property

* refactor: use DEFAULTS_LABEL_PREDICTION for outlier_quantile fallback

* refactor: make label weighting generic with metrics dict

- compute_label_weights() takes generic metrics dict instead of hardcoded params
- _compute_combined_weights() takes generic metrics dict
- apply_label_weighting() takes generic metrics dict
- Caller builds metrics dict, making weighting truly transverse to any label

* refactor: centralize deprecation handling with PARAM_DEPRECATIONS table

* refactor: call resolve_deprecated_params once at startup

- Change resolve_deprecated_params to modify dict in-place (returns None)
- Centralize all deprecation calls in bot_start() and __init__()
- Remove calls from properties and utility functions that run multiple times
- This ensures deprecation warnings are logged once, not repeatedly

* fix: resolve deprecations in __init__ before regressor loads

- Move deprecation resolution from bot_start() to Strategy.__init__()
  so it runs before FreqaiModel.__init__() (which reads same config)
- Remove label_transformer legacy support (never released)
- Simplify label_weighting/label_pipeline properties
- Keep regressor-specific deprecations in regressor __init__

* fix: address PR review comments

- Fix label_weighting['strategy'] KeyError by using ['default']['strategy']
- Respect label_prediction.method='none' in min_max_pred()
- Use float('inf') specificity for exact matches in get_column_config
- Reuse Utils.get_column_config in LabelTransformer
- Default label_smoothing method to 'gaussian'

* refactor: unify threshold column naming and soft_extremum_alpha

- Remove MINIMA_THRESHOLD_COLUMN/MAXIMA_THRESHOLD_COLUMN constants
- Use uniform {label}_minima_threshold/{label}_maxima_threshold for all labels
- Rename internal soft_alpha to soft_extremum_alpha for consistency with config
- Remove redundant docstrings from LabelTransformer (code is self-documenting)

* refactor: cleanup docstrings and rename internal functions

* refactor: make label_pipeline orthogonal from label_weighting

* refactor: rename get_column_config to get_label_column_config

* fix: add missing method field to label_prediction logging

* refactor: per-column logging and deprecate label_smoothing.window

- Update logging in QuickAdapterV3 and QuickAdapterRegressorV3 to show
  resolved per-column configs instead of just defaults with override keys
- Move get_label_column_config() to LabelTransformer.py (re-export from Utils)
- Add deprecation mapping for label_smoothing.window -> window_candles
- Fix extrema_direction undefined variable bug in populate_any_indicators

* fix: correct deprecation mappings for label_prediction params

* refactor: move label_pipeline property and logging to regressor

- Move label_pipeline property from QuickAdapterV3 strategy to QuickAdapterRegressorV3
- Move Pipeline configuration logging from _log_strategy_configuration() to
  _log_model_configuration()
- Simplify define_label_pipeline() to use self.label_pipeline property
- Remove unused get_label_pipeline_config import from strategy
- Rename local variable label_weighting to label_weighting_raw for consistency

* fix: import get_label_column_config from LabelTransformer

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* refactor(quickadapter): replace string literals with constant references in LabelTransformer

* refactor(quickadapter): use per-column prediction config in regressor and strategy

* fix: reference correct config paths for label processing

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* fix(quickadapter): warn when column doesn't match any config pattern

* feat(deprecation): support cross-section parameter moves

Extend PARAM_DEPRECATIONS to handle parameters that moved between
config sections, not just renames within the same section.

- Add tuple[str, str] value type for (old_section, old_key) moves
- Add root_config parameter to resolve_deprecated_params()
- Add deprecation entries for 7 params moved from label_weighting
  to label_pipeline: standardization, robust_quantiles,
  mmad_scaling_factor, normalization, minmax_range, sigmoid_scale,
  gamma
- Add call sites in QuickAdapterV3 and QuickAdapterRegressorV3

* refactor(quickadapter): replace imperative deprecation handling with declarative path-based migrations

- Replace PARAM_DEPRECATIONS dict and resolve_deprecated_params() with
  CONFIG_MIGRATIONS tuple and migrate_config()
- Single migrate_config() call in __init__ replaces 6+ resolve_deprecated_params() calls
- Fix bug in set_freqai_targets: move maxima/minima column creation after weighting
- Fix DI_value_param assignment to only occur when Weibull fit succeeds

* refactor(validation): replace imperative validation with declarative system

- Add dataclass-based validators (_EnumValidator, _NumericValidator, etc.)
- Replace ~240 lines of repetitive validation code with _validate_params()
- Consolidate type aliases in LabelTransformer.py (avoid duplicates)
- Fix pyright errors: float() casts, np.asarray() for pmean returns
- Use np.nan as default for optuna .get() (proper 'no value' sentinel)
- Add pyright to requirements-dev.txt

* chore(ReforceXY): add pyright to dev dependencies

* refactor(quickadapter): simplify fit_live_predictions thresholding flow

- Move DI_value stats computation before label loop
- Unify warmed_up conditional to single if/else block
- Always set threshold values (defaults when not warmed up)

* refactor(quickadapter): add OPTUNA_*_DEFAULT constants and fix static member access

- Add OPTUNA_*_DEFAULT class constants for n_jobs, n_trials, timeout,
  n_startup_trials, min_resource, label_candles_step, space_reduction,
  space_fraction, and seed
- Update _optuna_config property to use constants instead of hardcoded values
- Update all .get() calls to use constants as defaults for type safety
- Fix static method/property access: use QuickAdapterRegressorV3.method()
  instead of self.method() for static members
- Add assertions for narrowing Optional types (weights)
- Fix min_max_pred signature to accept Optional[int] for label_period_candles

Reduces pyright errors from 174 to 158 (-16)

* fix(quickadapter): default label_prediction method to 'thresholding' for backward compatibility

DEFAULTS_LABEL_PREDICTION['method'] was 'none' which broke backward
compatibility - legacy configs without explicit method would skip
threshold computation. Changed to 'thresholding' to preserve historical
behavior where thresholds were always computed by default.

* chore: refine log message

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* docs(quickadapter): update README for orthogonal label processing refactor

Rename config sections: extrema_weighting → label_weighting,
extrema_smoothing → label_smoothing, predictions_extrema → label_prediction.
Split label_weighting into label_weighting + label_pipeline.
Update parameter names and defaults. Remove deprecated alias mentions.

* chore(quickadapter): bump version to 3.11.0

---------

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore(deps): lock file maintenance (#42)
renovate[bot] [Thu, 22 Jan 2026 11:22:03 +0000 (12:22 +0100)] 
chore(deps): lock file maintenance (#42)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 months agochore(quickadapter): update labeling method and weights
Jérôme Benoit [Thu, 22 Jan 2026 10:47:58 +0000 (11:47 +0100)] 
chore(quickadapter): update labeling method and weights

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore(deps): update dependency optuna to v4.7.0 (#43)
renovate[bot] [Tue, 20 Jan 2026 11:07:05 +0000 (12:07 +0100)] 
chore(deps): update dependency optuna to v4.7.0 (#43)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 months agofeat(quickadapter): add model_path parameter for CatBoost train_dir
Jérôme Benoit [Tue, 13 Jan 2026 20:05:42 +0000 (21:05 +0100)] 
feat(quickadapter): add model_path parameter for CatBoost train_dir

Pass dk.data_path to fit_regressor to enable CatBoost train_dir configuration. For Optuna trials, creates isolated hp_trial_{N} subdirectories to avoid conflicts between parallel trial logs. Follows FreqTrade's mkdir pattern (parents=True, exist_ok=True).

3 months agoperf(quickadapter): tune catboost depth optuna search space
Jérôme Benoit [Tue, 13 Jan 2026 11:47:03 +0000 (12:47 +0100)] 
perf(quickadapter): tune catboost depth optuna search space

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agodocs: README.md formatting
Jérôme Benoit [Tue, 13 Jan 2026 11:40:06 +0000 (12:40 +0100)] 
docs: README.md formatting

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agochore(deps): lock file maintenance (#40)
renovate[bot] [Tue, 13 Jan 2026 11:02:52 +0000 (12:02 +0100)] 
chore(deps): lock file maintenance (#40)

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
3 months agochore/ refine update config-template.json
Jérôme Benoit [Tue, 13 Jan 2026 10:54:57 +0000 (11:54 +0100)] 
chore/ refine update config-template.json

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
3 months agoperf(quickadapter): eliminate ~15k np.log() recalculations via pure log space (#41)
Jérôme Benoit [Mon, 12 Jan 2026 15:58:52 +0000 (16:58 +0100)] 
perf(quickadapter): eliminate ~15k np.log() recalculations via pure log space (#41)

* perf(zigzag): eliminate ~15k np.log() recalculations via pure log space

Comprehensive optimization of zigzag() function to operate entirely in
logarithmic space, eliminating redundant np.log() recalculations.

**Performance Impact:**
- ~11,000-15,000 fewer np.log() calls per zigzag() execution
- Pre-computation: ~10,000 calls eliminated
- Pure log space conversion: ~1,050-5,100 calls eliminated

**Implementation Changes:**

Utils.py (zigzag function):
- Pre-compute log arrays once: closes_log, highs_log, lows_log (L1195-1199)
- Convert update_candidate_pivot() to accept log values (L1245)
- Convert add_pivot() to accept log values (L1401)
- Convert initial phase to log space (L1531-1569)
- Convert main loop comparisons to log space (L1583-1615)
- Rename top_change_percent() → top_log_return() (L813)
- Rename bottom_change_percent() → bottom_log_return() (L834)
- Convert efficiency ratio calculations to log space (L1343, L1368)

**API Changes:**
- zigzag() now returns pivots_values_log instead of pivots_values
- calculate_pivot_metrics() accepts log values directly

**Callers Updated:**
- QuickAdapterV3.py: Use renamed functions, add TODO comments (L674, L676, L702)
- QuickAdapterRegressorV3.py: Use len(pivots_indices) instead of len(pivots_values) (L3350, L3396)

**Mathematical Correctness:**
- Maintains semantic equivalence via log monotonicity: a > b ⟺ log(a) > log(b)
- Provides symmetric treatment of returns in log space
- All comparisons and calculations mathematically equivalent

**Breaking Changes (Future):**
- Added TODO comments for feature renaming (requires model retraining)
  - %-tcp-period → %-top_log_return-period
  - %-bcp-period → %-bottom_log_return-period
  - %-close_pct_change → %-close_log_return

* refactor(zigzag): harmonize log variable naming to _log suffix

Rename variables for consistency:
- log_candidate_pivot_close → candidate_pivot_close_log
- log_current_close → current_close_log
- log_slope_close → slope_close_log

All log-space variables now consistently use _log suffix.

* fix: revert incorrect global state usage in zigzag()

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* refactor: code formatting in zigzag()

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* refactor: remove redundant variable assignments

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
* chore: bump version to 3.10.11

---------

Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>