]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
fix(quickadapter): enforce reviewed training and trading contracts
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 17 Sep 2026 18:06:55 +0000 (20:06 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 17 Sep 2026 18:06:55 +0000 (20:06 +0200)
README.md
quickadapter/.basedpyright/diagnostics.json
quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py
quickadapter/user_data/strategies/QuickAdapterV3.py
quickadapter/user_data/strategies/Utils.py

index d3b52cd0aa5300a0d6f46944653d591584a5fbad..a0398a5a4e22ca27cedc3df5b06c91e398c557f2 100644 (file)
--- a/README.md
+++ b/README.md
@@ -169,6 +169,41 @@ ignored with a warning. Matching column patterns are applied from least to most
 specific; equally specific patterns follow declaration order, so the later one
 wins.
 
+Operational constraints:
+
+- Entries require every requested prior confirmation candle. Exits may use the
+  available history, but still reject a failed measurable comparison. Partial
+  take-profit exits check both the outgoing quantity and the remainder against
+  exchange minimums after contract precision rounding, including leverage.
+  An infeasible partial exit requests a full exit; this cannot guarantee that an
+  exchange accepts an already-dust position.
+- `freqai.fit_live_predictions_candles` defaults to 100. Missing or invalid
+  values normalize to 100 in the shared strategy/FreqAI configuration; valid
+  positive integers are preserved.
+- Label HPO scheduling permits pairs to share slots when there are fewer slots
+  than pairs. Scheduling is inactive when HPO is disabled.
+- Causal training removes unavailable terminal labels even with `test_size=0`.
+  Savitzky–Golay `interp` edge availability includes the whole edge-fit window
+  for labels and weights. A window longer than the series leaves both unchanged.
+- Cluster ranking and member selection honor supported objective weights. KNN
+  uses weighted SciPy distances, excludes only each row's own index, and retains
+  distinct candidates at zero distance. Its distance matrix requires quadratic
+  memory in the number of Pareto candidates.
+- Standardized Euclidean variance and Mahalanobis covariance are estimated once
+  from the full normalized Pareto front, after constant objectives are removed.
+  Singular covariance eigenvalues are floored at the largest eigenvalue times
+  the square root of machine epsilon. These two metrics do not support custom
+  objective weights; configured weights warn and fall back to uniform weights.
+- With `space_reduction=true`, `space_fraction=0` fixes numerical search ranges
+  at valid previous best values; it does not freeze every categorical choice.
+  Saved HPO suggestions reconstruct derived estimator parameters for final fits:
+  XGBoost `lossguide` uses unlimited depth and histogram gradient boosting
+  restores the selected zero-regularization branch.
+- NGBoost defaults to `model_training_parameters.dist="normal"`, which supports
+  signed labels. Explicit `"lognormal"` requires finite, strictly positive
+  transformed training and validation labels; incompatible HPO trials are pruned,
+  while direct fits raise an error.
+
 ### Backtest evaluation protocol
 
 Use this protocol before adopting a change to a QuickAdapter default. It is an
index a4031fd496fce608555c5f66cabf10fef32d8aa8..7545d9586ad635e2ae4e08af7908ceddd513f243 100644 (file)
   "diagnostics": [
     {
       "endCharacter": 46,
-      "endLine": 1333,
+      "endLine": 1335,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"str | None\" cannot be assigned to parameter \"default\" of type \"str\" in function \"_validate_label_selection_metric\"\n  Type \"str | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 24,
-      "startLine": 1333
+      "startLine": 1335
     },
     {
       "endCharacter": 79,
-      "endLine": 2105,
+      "endLine": 2117,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 74,
-      "startLine": 2105
+      "startLine": 2117
     },
     {
       "endCharacter": 72,
-      "endLine": 2107,
+      "endLine": 2119,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 67,
-      "startLine": 2107
+      "startLine": 2119
     },
     {
       "endCharacter": 90,
-      "endLine": 2116,
+      "endLine": 2128,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 85,
-      "startLine": 2116
+      "startLine": 2128
     },
     {
       "endCharacter": 34,
-      "endLine": 2129,
+      "endLine": 2141,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"train_features\" of type \"DataFrame\" in function \"_filter_train_by_mask\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2129
+      "startLine": 2141
     },
     {
       "endCharacter": 32,
-      "endLine": 2130,
+      "endLine": 2142,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"train_labels\" of type \"DataFrame\" in function \"_filter_train_by_mask\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2130
+      "startLine": 2142
     },
     {
       "endCharacter": 38,
-      "endLine": 2131,
+      "endLine": 2143,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"train_weights\" of type \"NDArray[floating[Any]]\" in function \"_filter_train_by_mask\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2131
+      "startLine": 2143
     },
     {
       "endCharacter": 59,
-      "endLine": 2134,
+      "endLine": 2146,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" cannot be assigned to parameter \"train_label_weights\" of type \"NDArray[floating[Any]] | None\" in function \"_filter_train_by_mask\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" is not assignable to type \"NDArray[floating[Any]] | None\"\n    Type \"list[Unknown]\" is not assignable to type \"NDArray[floating[Any]] | None\"\n      \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"\n      \"list[Unknown]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 40,
-      "startLine": 2134
+      "startLine": 2146
     },
     {
       "endCharacter": 34,
-      "endLine": 2151,
+      "endLine": 2180,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"features\" of type \"DataFrame\" in function \"_shuffle_split_rows\"\n  Type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2151
+      "startLine": 2180
     },
     {
       "endCharacter": 32,
-      "endLine": 2152,
+      "endLine": 2181,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"labels\" of type \"DataFrame\" in function \"_shuffle_split_rows\"\n  Type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2152
+      "startLine": 2181
     },
     {
       "endCharacter": 38,
-      "endLine": 2153,
+      "endLine": 2182,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"base_weights\" of type \"NDArray[floating[Any]]\" in function \"_shuffle_split_rows\"\n  Type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2153
+      "startLine": 2182
     },
     {
       "endCharacter": 39,
-      "endLine": 2154,
+      "endLine": 2183,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" cannot be assigned to parameter \"label_weights\" of type \"NDArray[floating[Any]] | None\" in function \"_shuffle_split_rows\"\n  Type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" is not assignable to type \"NDArray[floating[Any]] | None\"\n    Type \"list[Unknown]\" is not assignable to type \"NDArray[floating[Any]] | None\"\n      \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"\n      \"list[Unknown]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2154
+      "startLine": 2183
     },
     {
       "endCharacter": 37,
-      "endLine": 2161,
+      "endLine": 2190,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | DataFrame\" cannot be assigned to parameter \"features\" of type \"DataFrame\" in function \"_shuffle_split_rows\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | DataFrame\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 24,
-      "startLine": 2161
+      "startLine": 2190
     },
     {
       "endCharacter": 35,
-      "endLine": 2162,
+      "endLine": 2191,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | DataFrame\" cannot be assigned to parameter \"labels\" of type \"DataFrame\" in function \"_shuffle_split_rows\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | DataFrame\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 24,
-      "startLine": 2162
+      "startLine": 2191
     },
     {
       "endCharacter": 41,
-      "endLine": 2163,
+      "endLine": 2192,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | ndarray[_AnyShape, dtype[floating[Any]]]\" cannot be assigned to parameter \"base_weights\" of type \"NDArray[floating[Any]]\" in function \"_shuffle_split_rows\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | ndarray[_AnyShape, dtype[floating[Any]]]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 24,
-      "startLine": 2163
+      "startLine": 2192
     },
     {
       "endCharacter": 42,
-      "endLine": 2164,
+      "endLine": 2193,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | ndarray[_AnyShape, dtype[floating[Any]]] | None\" cannot be assigned to parameter \"label_weights\" of type \"NDArray[floating[Any]] | None\" in function \"_shuffle_split_rows\"\n  Type \"Unknown | NDArray[Unknown] | Any | list[Unknown] | ndarray[_AnyShape, dtype[floating[Any]]] | None\" is not assignable to type \"NDArray[floating[Any]] | None\"\n    Type \"list[Unknown]\" is not assignable to type \"NDArray[floating[Any]] | None\"\n      \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"\n      \"list[Unknown]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 24,
-      "startLine": 2164
+      "startLine": 2193
     },
     {
       "endCharacter": 30,
-      "endLine": 2182,
+      "endLine": 2211,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"base_weights\" of type \"NDArray[floating[Any]]\" in function \"_compose_train_weights_with_support\"\n  Type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2182
+      "startLine": 2211
     },
     {
       "endCharacter": 31,
-      "endLine": 2183,
+      "endLine": 2212,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" cannot be assigned to parameter \"label_weights\" of type \"NDArray[floating[Any]] | None\" in function \"_compose_train_weights_with_support\"\n  Type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" is not assignable to type \"NDArray[floating[Any]] | None\"\n    Type \"list[Unknown]\" is not assignable to type \"NDArray[floating[Any]] | None\"\n      \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"\n      \"list[Unknown]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2183
+      "startLine": 2212
     },
     {
       "endCharacter": 33,
-      "endLine": 2189,
+      "endLine": 2218,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"base_weights\" of type \"NDArray[floating[Any]]\" in function \"_compose_eval_weights\"\n  Type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2189
+      "startLine": 2218
     },
     {
       "endCharacter": 34,
-      "endLine": 2190,
+      "endLine": 2219,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" cannot be assigned to parameter \"label_weights\" of type \"NDArray[floating[Any]] | None\" in function \"_compose_eval_weights\"\n  Type \"NDArray[floating[Any]] | Unknown | NDArray[Unknown] | Any | list[Unknown] | None\" is not assignable to type \"NDArray[floating[Any]] | None\"\n    Type \"list[Unknown]\" is not assignable to type \"NDArray[floating[Any]] | None\"\n      \"list[Unknown]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"\n      \"list[Unknown]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2190
+      "startLine": 2219
     },
     {
       "endCharacter": 26,
-      "endLine": 2197,
+      "endLine": 2226,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"train_df\" of type \"DataFrame\" in function \"build_data_dictionary\"\n  Type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2197
+      "startLine": 2226
     },
     {
       "endCharacter": 25,
-      "endLine": 2198,
+      "endLine": 2227,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"test_df\" of type \"DataFrame\" in function \"build_data_dictionary\"\n  Type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2198
+      "startLine": 2227
     },
     {
       "endCharacter": 24,
-      "endLine": 2199,
+      "endLine": 2228,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"train_labels\" of type \"DataFrame\" in function \"build_data_dictionary\"\n  Type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2199
+      "startLine": 2228
     },
     {
       "endCharacter": 23,
-      "endLine": 2200,
+      "endLine": 2229,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" cannot be assigned to parameter \"test_labels\" of type \"DataFrame\" in function \"build_data_dictionary\"\n  Type \"DataFrame | Unknown | NDArray[Unknown] | Any | list[Unknown]\" is not assignable to type \"DataFrame\"\n    \"list[Unknown]\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2200
+      "startLine": 2229
     },
     {
       "endCharacter": 87,
-      "endLine": 2414,
+      "endLine": 2443,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 82,
-      "startLine": 2414
+      "startLine": 2443
     },
     {
       "endCharacter": 68,
-      "endLine": 2415,
+      "endLine": 2444,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 63,
-      "startLine": 2415
+      "startLine": 2444
     },
     {
       "endCharacter": 63,
-      "endLine": 2426,
+      "endLine": 2455,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2426
+      "startLine": 2455
     },
     {
       "endCharacter": 47,
-      "endLine": 2428,
+      "endLine": 2457,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"loc\" for class \"NDArray[Unknown]\"\n  Attribute \"loc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 44,
-      "startLine": 2428
+      "startLine": 2457
     },
     {
       "endCharacter": 47,
-      "endLine": 2428,
+      "endLine": 2457,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"loc\" for class \"list[Unknown]\"\n  Attribute \"loc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 44,
-      "startLine": 2428
+      "startLine": 2457
     },
     {
       "endCharacter": 43,
-      "endLine": 2429,
+      "endLine": 2458,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"loc\" for class \"NDArray[Unknown]\"\n  Attribute \"loc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 40,
-      "startLine": 2429
+      "startLine": 2458
     },
     {
       "endCharacter": 43,
-      "endLine": 2429,
+      "endLine": 2458,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"loc\" for class \"list[Unknown]\"\n  Attribute \"loc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 40,
-      "startLine": 2429
+      "startLine": 2458
     },
     {
       "endCharacter": 31,
-      "endLine": 2450,
+      "endLine": 2479,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"NDArray[Unknown]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 26,
-      "startLine": 2450
+      "startLine": 2479
     },
     {
       "endCharacter": 31,
-      "endLine": 2450,
+      "endLine": 2479,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"list[Unknown]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 26,
-      "startLine": 2450
+      "startLine": 2479
     },
     {
       "endCharacter": 60,
-      "endLine": 2450,
+      "endLine": 2479,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"NDArray[Unknown]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 2450
+      "startLine": 2479
     },
     {
       "endCharacter": 60,
-      "endLine": 2450,
+      "endLine": 2479,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"list[Unknown]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 2450
+      "startLine": 2479
     },
     {
       "endCharacter": 73,
-      "endLine": 2462,
+      "endLine": 2491,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" cannot be assigned to parameter \"target\" of type \"Index[Any]\" in function \"get_indexer\"\n  Type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" is not assignable to type \"Index[Any]\"\n    \"MethodType\" is not assignable to \"Index[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 53,
-      "startLine": 2462
+      "startLine": 2491
     },
     {
       "endCharacter": 73,
-      "endLine": 2462,
+      "endLine": 2491,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 2462
+      "startLine": 2491
     },
     {
       "endCharacter": 83,
-      "endLine": 2463,
+      "endLine": 2492,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" cannot be assigned to parameter \"target\" of type \"Index[Any]\" in function \"get_indexer\"\n  Type \"Unknown | Any | ((value: Unknown, start: SupportsIndex = 0, stop: SupportsIndex = sys.maxsize, /) -> int)\" is not assignable to type \"Index[Any]\"\n    \"MethodType\" is not assignable to \"Index[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2463
+      "startLine": 2492
     },
     {
       "endCharacter": 83,
-      "endLine": 2463,
+      "endLine": 2492,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"index\" for class \"NDArray[Unknown]\"\n  Attribute \"index\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 78,
-      "startLine": 2463
+      "startLine": 2492
     },
     {
       "endCharacter": 9,
-      "endLine": 2611,
+      "endLine": 2640,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Type \"ArrayLike\" is not assignable to declared type \"DataFrame\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 45,
-      "startLine": 2609
+      "startLine": 2638
     },
     {
       "endCharacter": 9,
-      "endLine": 2611,
+      "endLine": 2640,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Type \"ArrayLike\" is not assignable to declared type \"NDArray[floating[Any]]\"\n  Type \"ArrayLike\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"Buffer\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 45,
-      "startLine": 2609
+      "startLine": 2638
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"Buffer\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"_NestedSequence[complex | bytes | str]\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"_SupportsArray[dtype[Any]]\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"bytes\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"complex\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 60,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"str\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 79,
-      "endLine": 2621,
+      "endLine": 2650,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "\"base_weight_column\" is possibly unbound",
       "rule": "reportPossiblyUnboundVariable",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2621
+      "startLine": 2650
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"Buffer\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"_NestedSequence[complex | bytes | str]\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"_SupportsArray[dtype[Any]]\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"bytes\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"complex\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 61,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"pop\" for class \"str\"\n  Attribute \"pop\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 81,
-      "endLine": 2624,
+      "endLine": 2653,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "\"label_weight_column\" is possibly unbound",
       "rule": "reportPossiblyUnboundVariable",
       "severity": "error",
       "startCharacter": 62,
-      "startLine": 2624
+      "startLine": 2653
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"Buffer\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"_NestedSequence[complex | bytes | str]\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"_SupportsArray[dtype[Any]]\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"bytes\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"complex\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 68,
-      "endLine": 2630,
+      "endLine": 2659,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"columns\" for class \"str\"\n  Attribute \"columns\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 2630
+      "startLine": 2659
     },
     {
       "endCharacter": 32,
-      "endLine": 2638,
+      "endLine": 2667,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Type \"ArrayLike\" is not assignable to declared type \"DataFrame\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 17,
-      "startLine": 2638
+      "startLine": 2667
     },
     {
       "endCharacter": 62,
-      "endLine": 2639,
+      "endLine": 2668,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Type \"ArrayLike\" is not assignable to declared type \"DataFrame\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 23,
-      "startLine": 2639
+      "startLine": 2668
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"Buffer\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"_NestedSequence[complex | bytes | str]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"_SupportsArray[dtype[Any]]\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"bytes\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"complex\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 46,
-      "endLine": 2672,
+      "endLine": 2701,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Cannot access attribute \"empty\" for class \"str\"\n  Attribute \"empty\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 41,
-      "startLine": 2672
+      "startLine": 2701
     },
     {
       "endCharacter": 41,
-      "endLine": 2679,
+      "endLine": 2708,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"ArrayLike\" cannot be assigned to parameter \"features\" of type \"DataFrame\" in function \"_sanitize_pipeline_weights\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2679
+      "startLine": 2708
     },
     {
       "endCharacter": 39,
-      "endLine": 2728,
+      "endLine": 2757,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"ArrayLike\" cannot be assigned to parameter \"features\" of type \"DataFrame\" in function \"_sanitize_pipeline_weights\"\n  Type \"ArrayLike\" is not assignable to type \"DataFrame\"\n    \"Buffer\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2728
+      "startLine": 2757
     },
     {
       "endCharacter": 19,
-      "endLine": 2838,
+      "endLine": 2867,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"int | Any | None\" cannot be assigned to parameter \"gap\" of type \"int\" in function \"__init__\"\n  Type \"int | Any | None\" is not assignable to type \"int\"\n    \"None\" is not assignable to \"int\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2838
+      "startLine": 2867
     },
     {
       "endCharacter": 21,
-      "endLine": 2949,
+      "endLine": 2978,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2949
+      "startLine": 2978
     },
     {
       "endCharacter": 21,
-      "endLine": 2950,
+      "endLine": 2979,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2950
+      "startLine": 2979
     },
     {
       "endCharacter": 33,
-      "endLine": 2951,
+      "endLine": 2980,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"train_weights\" of type \"NDArray[floating[Any]]\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2951
+      "startLine": 2980
     },
     {
       "endCharacter": 32,
-      "endLine": 2952,
+      "endLine": 2981,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X_validation\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2952
+      "startLine": 2981
     },
     {
       "endCharacter": 32,
-      "endLine": 2953,
+      "endLine": 2982,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y_validation\" of type \"DataFrame\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2953
+      "startLine": 2982
     },
     {
       "endCharacter": 38,
-      "endLine": 2954,
+      "endLine": 2983,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"validation_weights\" of type \"NDArray[floating[Any]]\" in function \"hp_objective\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 2954
+      "startLine": 2983
     },
     {
       "endCharacter": 24,
-      "endLine": 2975,
+      "endLine": 3004,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X_test\" of type \"DataFrame\" in function \"make_test_set_and_weights\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2975
+      "startLine": 3004
     },
     {
       "endCharacter": 24,
-      "endLine": 2976,
+      "endLine": 3005,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y_test\" of type \"DataFrame\" in function \"make_test_set_and_weights\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2976
+      "startLine": 3005
     },
     {
       "endCharacter": 30,
-      "endLine": 2977,
+      "endLine": 3006,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"test_weights\" of type \"NDArray[floating[Any]]\" in function \"make_test_set_and_weights\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 2977
+      "startLine": 3006
     },
     {
       "endCharacter": 15,
-      "endLine": 2983,
+      "endLine": 3012,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"X\" of type \"DataFrame\" in function \"fit_regressor\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 14,
-      "startLine": 2983
+      "startLine": 3012
     },
     {
       "endCharacter": 15,
-      "endLine": 2984,
+      "endLine": 3013,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"y\" of type \"DataFrame\" in function \"fit_regressor\"\n  Type \"Any | None\" is not assignable to type \"DataFrame\"\n    \"None\" is not assignable to \"DataFrame\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 14,
-      "startLine": 2984
+      "startLine": 3013
     },
     {
       "endCharacter": 39,
-      "endLine": 2985,
+      "endLine": 3014,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"train_weights\" of type \"NDArray[floating[Any]]\" in function \"fit_regressor\"\n  Type \"Any | None\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"None\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 26,
-      "startLine": 2985
+      "startLine": 3014
     },
     {
       "endCharacter": 38,
-      "endLine": 2995,
+      "endLine": 3024,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "\"columns\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 31,
-      "startLine": 2995
+      "startLine": 3024
     },
     {
       "endCharacter": 34,
-      "endLine": 2996,
+      "endLine": 3025,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "\"index\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 29,
-      "startLine": 2996
+      "startLine": 3025
     },
     {
       "endCharacter": 82,
-      "endLine": 2998,
+      "endLine": 3027,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "\"copy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 78,
-      "startLine": 2998
+      "startLine": 3027
     },
     {
       "endCharacter": 62,
-      "endLine": 3281,
+      "endLine": 3310,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "\"get_pair_dataframe\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 44,
-      "startLine": 3281
+      "startLine": 3310
     },
     {
       "endCharacter": 68,
-      "endLine": 3656,
+      "endLine": 3685,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Type \"floating[Any] | NDArray[float64]\" is not assignable to return type \"NDArray[floating[Any]]\"\n  Type \"floating[Any] | NDArray[float64]\" is not assignable to type \"NDArray[floating[Any]]\"\n    \"floating[Any]\" is not assignable to \"ndarray[_AnyShape, dtype[floating[Any]]]\"",
       "rule": "reportReturnType",
       "severity": "error",
       "startCharacter": 15,
-      "startLine": 3652
+      "startLine": 3681
     },
     {
       "endCharacter": 13,
-      "endLine": 3694,
+      "endLine": 3714,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "No overloads for \"cdist\" match the provided arguments",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 19,
-      "startLine": 3689
+      "startLine": 3709
     },
     {
       "endCharacter": 38,
-      "endLine": 3692,
+      "endLine": 3712,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"cdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 23,
-      "startLine": 3692
+      "startLine": 3712
     },
     {
       "endCharacter": 9,
-      "endLine": 3803,
+      "endLine": 3817,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "No overloads for \"pdist\" match the provided arguments",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 3801
+      "startLine": 3815
     },
     {
       "endCharacter": 42,
-      "endLine": 3802,
+      "endLine": 3816,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"pdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 3802
+      "startLine": 3816
     },
     {
       "endCharacter": 9,
-      "endLine": 3900,
+      "endLine": 3894,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "No overloads for \"cdist\" match the provided arguments",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 15,
-      "startLine": 3895
+      "startLine": 3889
     },
     {
       "endCharacter": 34,
-      "endLine": 3898,
+      "endLine": 3892,
       "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"cdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 19,
-      "startLine": 3898
+      "startLine": 3892
+    },
+    {
+      "endCharacter": 99,
+      "endLine": 4083,
+      "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
+      "message": "No overloads for \"pdist\" match the provided arguments",
+      "rule": "reportCallIssue",
+      "severity": "error",
+      "startCharacter": 12,
+      "startLine": 4083
+    },
+    {
+      "endCharacter": 79,
+      "endLine": 4083,
+      "file": "quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py",
+      "message": "Argument of type \"str\" cannot be assigned to parameter \"metric\" of type \"_MetricFunc\" in function \"pdist\"\n  Type \"str\" is not assignable to type \"_MetricFunc\"",
+      "rule": "reportArgumentType",
+      "severity": "error",
+      "startCharacter": 64,
+      "startLine": 4083
     },
     {
       "endCharacter": 55,
-      "endLine": 217,
+      "endLine": 219,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Type \"int\" is not assignable to declared type \"cached_property[int]\"\n  \"int\" is not assignable to \"cached_property[int]\"",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 24,
-      "startLine": 217
+      "startLine": 219
     },
     {
       "endCharacter": 15,
-      "endLine": 253,
+      "endLine": 255,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Class variable \"minimal_roi\" overrides instance variable of same name in class \"IStrategy\"",
       "rule": "reportIncompatibleVariableOverride",
       "severity": "error",
       "startCharacter": 4,
-      "startLine": 253
+      "startLine": 255
     },
     {
       "endCharacter": 72,
-      "endLine": 253,
+      "endLine": 255,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"*\" not supported for types \"cached_property[int]\" and \"Literal[864]\"",
       "rule": "reportOperatorIssue",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 253
+      "startLine": 255
     },
     {
       "endCharacter": 64,
-      "endLine": 265,
+      "endLine": 268,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"timeframe_to_minutes\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 265
+      "startLine": 268
     },
     {
       "endCharacter": 17,
-      "endLine": 274,
+      "endLine": 277,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"can_short\" overrides symbol of same name in class \"IStrategy\"\n  \"property\" is not assignable to \"bool\"",
       "rule": "reportIncompatibleVariableOverride",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 274
+      "startLine": 277
     },
     {
       "endCharacter": 19,
-      "endLine": 278,
+      "endLine": 281,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"plot_config\" overrides symbol of same name in class \"IStrategy\"\n  \"cached_property[dict[str, Any]]\" is not assignable to \"dict[Unknown, Unknown]\"",
       "rule": "reportIncompatibleVariableOverride",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 278
+      "startLine": 281
     },
     {
       "endCharacter": 19,
-      "endLine": 322,
+      "endLine": 325,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"protections\" overrides symbol of same name in class \"IStrategy\"\n  \"cached_property[list[dict[str, Any]]]\" is not assignable to \"list[Unknown]\"",
       "rule": "reportIncompatibleVariableOverride",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 322
+      "startLine": 325
     },
     {
       "endCharacter": 28,
-      "endLine": 395,
+      "endLine": 398,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"startup_candle_count\" overrides symbol of same name in class \"IStrategy\"\n  \"property\" is not assignable to \"int\"",
       "rule": "reportIncompatibleVariableOverride",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 395
+      "startLine": 398
     },
     {
       "endCharacter": 44,
-      "endLine": 454,
+      "endLine": 457,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"/\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 454
+      "startLine": 457
     },
     {
       "endCharacter": 38,
-      "endLine": 707,
+      "endLine": 710,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 30,
-      "startLine": 707
+      "startLine": 710
     },
     {
       "endCharacter": 44,
-      "endLine": 740,
+      "endLine": 743,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"-\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 38,
-      "startLine": 740
+      "startLine": 743
     },
     {
       "endCharacter": 38,
-      "endLine": 748,
+      "endLine": 751,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Object of type \"None\" is not subscriptable",
       "rule": "reportOptionalSubscript",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 748
+      "startLine": 751
     },
     {
       "endCharacter": 39,
-      "endLine": 749,
+      "endLine": 752,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Object of type \"None\" is not subscriptable",
       "rule": "reportOptionalSubscript",
       "severity": "error",
       "startCharacter": 37,
-      "startLine": 749
+      "startLine": 752
     },
     {
       "endCharacter": 38,
-      "endLine": 750,
+      "endLine": 753,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Object of type \"None\" is not subscriptable",
       "rule": "reportOptionalSubscript",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 750
+      "startLine": 753
     },
     {
       "endCharacter": 44,
-      "endLine": 773,
+      "endLine": 776,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"-\" not supported for types \"Series[Any] | None\" and \"Series[Any] | None\"\n  Operator \"-\" not supported for types \"Series[Any]\" and \"None\"\n  Operator \"-\" not supported for types \"None\" and \"Series[Any]\"\n  Operator \"-\" not supported for types \"None\" and \"None\"",
       "rule": "reportOperatorIssue",
       "severity": "error",
       "startCharacter": 29,
-      "startLine": 773
+      "startLine": 776
     },
     {
       "endCharacter": 66,
-      "endLine": 773,
+      "endLine": 776,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"s1\" of type \"Series[Any]\" in function \"non_zero_diff\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 773
+      "startLine": 776
     },
     {
       "endCharacter": 72,
-      "endLine": 773,
+      "endLine": 776,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"s2\" of type \"Series[Any]\" in function \"non_zero_diff\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 773
+      "startLine": 776
     },
     {
       "endCharacter": 56,
-      "endLine": 777,
+      "endLine": 780,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 50,
-      "startLine": 777
+      "startLine": 780
     },
     {
       "endCharacter": 58,
-      "endLine": 778,
+      "endLine": 781,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 52,
-      "startLine": 778
+      "startLine": 781
     },
     {
       "endCharacter": 57,
-      "endLine": 779,
+      "endLine": 782,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 51,
-      "startLine": 779
+      "startLine": 782
     },
     {
       "endCharacter": 44,
-      "endLine": 782,
+      "endLine": 785,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"zlema\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 38,
-      "startLine": 782
+      "startLine": 785
     },
     {
       "endCharacter": 44,
-      "endLine": 783,
+      "endLine": 786,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"zlema\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 38,
-      "startLine": 783
+      "startLine": 786
     },
     {
       "endCharacter": 44,
-      "endLine": 784,
+      "endLine": 787,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"zlema\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 38,
-      "startLine": 784
+      "startLine": 787
     },
     {
       "endCharacter": 61,
-      "endLine": 785,
+      "endLine": 788,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 785
+      "startLine": 788
     },
     {
       "endCharacter": 61,
-      "endLine": 786,
+      "endLine": 789,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 786
+      "startLine": 789
     },
     {
       "endCharacter": 61,
-      "endLine": 787,
+      "endLine": 790,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 787
+      "startLine": 790
     },
     {
       "endCharacter": 81,
-      "endLine": 795,
+      "endLine": 798,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any]\" cannot be assigned to parameter \"p2\" of type \"T@get_distance\" in function \"get_distance\"\n  \"Series[Any]\" is not assignable to \"float\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 795
+      "startLine": 798
     },
     {
       "endCharacter": 67,
-      "endLine": 808,
+      "endLine": 811,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 808
+      "startLine": 811
     },
     {
       "endCharacter": 68,
-      "endLine": 809,
+      "endLine": 812,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 62,
-      "startLine": 809
+      "startLine": 812
     },
     {
       "endCharacter": 67,
-      "endLine": 810,
+      "endLine": 813,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 61,
-      "startLine": 810
+      "startLine": 813
     },
     {
       "endCharacter": 44,
-      "endLine": 811,
+      "endLine": 814,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"-\" not supported for types \"Series[Any] | None\" and \"Series[Any] | None\"\n  Operator \"-\" not supported for types \"Series[Any]\" and \"None\" when expected type is \"_SetItemValueNotDataFrame\"\n  Operator \"-\" not supported for types \"None\" and \"Series[Any]\" when expected type is \"_SetItemValueNotDataFrame\"\n  Operator \"-\" not supported for types \"None\" and \"None\" when expected type is \"_SetItemValueNotDataFrame\"",
       "rule": "reportOperatorIssue",
       "severity": "error",
       "startCharacter": 30,
-      "startLine": 811
+      "startLine": 814
     },
     {
       "endCharacter": 56,
-      "endLine": 812,
+      "endLine": 815,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "No overloads for \"__call__\" match the provided arguments",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 31,
-      "startLine": 812
+      "startLine": 815
     },
     {
       "endCharacter": 47,
-      "endLine": 812,
+      "endLine": 815,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x1\" of type \"ArrayLike\" in function \"__call__\"\n  Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n    Type \"None\" is not assignable to type \"ArrayLike\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n        \"__array__\" is not present\n      \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n        \"__len__\" is not present\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 42,
-      "startLine": 812
+      "startLine": 815
     },
     {
       "endCharacter": 55,
-      "endLine": 812,
+      "endLine": 815,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x2\" of type \"ArrayLike\" in function \"__call__\"\n  Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n    Type \"None\" is not assignable to type \"ArrayLike\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n        \"__array__\" is not present\n      \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n        \"__len__\" is not present\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 812
+      "startLine": 815
     },
     {
       "endCharacter": 64,
-      "endLine": 813,
+      "endLine": 816,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "No overloads for \"__call__\" match the provided arguments",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 39,
-      "startLine": 813
+      "startLine": 816
     },
     {
       "endCharacter": 55,
-      "endLine": 813,
+      "endLine": 816,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x1\" of type \"ArrayLike\" in function \"__call__\"\n  Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n    Type \"None\" is not assignable to type \"ArrayLike\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n        \"__array__\" is not present\n      \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n        \"__len__\" is not present\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 50,
-      "startLine": 813
+      "startLine": 816
     },
     {
       "endCharacter": 63,
-      "endLine": 813,
+      "endLine": 816,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"x2\" of type \"ArrayLike\" in function \"__call__\"\n  Type \"Series[Any] | None\" is not assignable to type \"ArrayLike\"\n    Type \"None\" is not assignable to type \"ArrayLike\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"_SupportsArray[dtype[Any]]\"\n        \"__array__\" is not present\n      \"None\" is incompatible with protocol \"_NestedSequence[_SupportsArray[dtype[Any]]]\"\n        \"__len__\" is not present\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 813
+      "startLine": 816
     },
     {
       "endCharacter": 55,
-      "endLine": 821,
+      "endLine": 824,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 821
+      "startLine": 824
     },
     {
       "endCharacter": 55,
-      "endLine": 822,
+      "endLine": 825,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 822
+      "startLine": 825
     },
     {
       "endCharacter": 55,
-      "endLine": 823,
+      "endLine": 826,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 823
+      "startLine": 826
     },
     {
       "endCharacter": 55,
-      "endLine": 824,
+      "endLine": 827,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 824
+      "startLine": 827
     },
     {
       "endCharacter": 55,
-      "endLine": 825,
+      "endLine": 828,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 825
+      "startLine": 828
     },
     {
       "endCharacter": 55,
-      "endLine": 826,
+      "endLine": 829,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"p1\" of type \"T@get_distance\" in function \"get_distance\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 826
+      "startLine": 829
     },
     {
       "endCharacter": 50,
-      "endLine": 855,
+      "endLine": 858,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 44,
-      "startLine": 855
+      "startLine": 858
     },
     {
       "endCharacter": 50,
-      "endLine": 855,
+      "endLine": 858,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 44,
-      "startLine": 855
+      "startLine": 858
     },
     {
       "endCharacter": 29,
-      "endLine": 856,
+      "endLine": 859,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 23,
-      "startLine": 856
+      "startLine": 859
     },
     {
       "endCharacter": 29,
-      "endLine": 856,
+      "endLine": 859,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToInt\"\n    Type \"None\" is not assignable to type \"ConvertibleToInt\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 23,
-      "startLine": 856
+      "startLine": 859
     },
     {
       "endCharacter": 60,
-      "endLine": 893,
+      "endLine": 896,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 50,
-      "startLine": 893
+      "startLine": 896
     },
     {
       "endCharacter": 60,
-      "endLine": 893,
+      "endLine": 896,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 50,
-      "startLine": 893
+      "startLine": 896
     },
     {
       "endCharacter": 35,
-      "endLine": 894,
+      "endLine": 897,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 25,
-      "startLine": 894
+      "startLine": 897
     },
     {
       "endCharacter": 35,
-      "endLine": 894,
+      "endLine": 897,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"Any | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 25,
-      "startLine": 894
+      "startLine": 897
     },
     {
       "endCharacter": 41,
-      "endLine": 1116,
+      "endLine": 1122,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"<\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 1116
+      "startLine": 1122
     },
     {
       "endCharacter": 41,
-      "endLine": 1126,
+      "endLine": 1132,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \">\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 1126
+      "startLine": 1132
     },
     {
       "endCharacter": 66,
-      "endLine": 1139,
+      "endLine": 1145,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"timeframe_to_prev_date\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 38,
-      "startLine": 1139
+      "startLine": 1145
     },
     {
       "endCharacter": 73,
-      "endLine": 1270,
+      "endLine": 1276,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Expected 1 more positional argument",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 51,
-      "startLine": 1270
+      "startLine": 1276
     },
     {
       "endCharacter": 74,
-      "endLine": 1334,
+      "endLine": 1340,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"int | None\" cannot be assigned to parameter \"trade_duration_candles\" of type \"int\" in function \"get_trade_natr\"\n  Type \"int | None\" is not assignable to type \"int\"\n    \"None\" is not assignable to \"int\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 52,
-      "startLine": 1334
+      "startLine": 1340
     },
     {
       "endCharacter": 74,
-      "endLine": 1361,
+      "endLine": 1367,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"int | None\" cannot be assigned to parameter \"trade_duration_candles\" of type \"int\" in function \"get_trade_natr\"\n  Type \"int | None\" is not assignable to type \"int\"\n    \"None\" is not assignable to \"int\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 52,
-      "startLine": 1361
+      "startLine": 1367
     },
     {
       "endCharacter": 96,
-      "endLine": 1409,
+      "endLine": 1415,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 1409
+      "startLine": 1415
     },
     {
       "endCharacter": 77,
-      "endLine": 1443,
+      "endLine": 1449,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"<=\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 57,
-      "startLine": 1443
+      "startLine": 1449
     },
     {
       "endCharacter": 9,
-      "endLine": 1448,
+      "endLine": 1454,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"+\" not supported for types \"float\" and \"float | None\"\n  Operator \"+\" not supported for types \"float\" and \"None\"",
       "rule": "reportOperatorIssue",
       "severity": "error",
       "startCharacter": 28,
-      "startLine": 1446
+      "startLine": 1452
     },
     {
       "endCharacter": 33,
-      "endLine": 1447,
+      "endLine": 1453,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"-\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 13,
-      "startLine": 1447
+      "startLine": 1453
     },
     {
       "endCharacter": 67,
-      "endLine": 1453,
+      "endLine": 1459,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 47,
-      "startLine": 1453
+      "startLine": 1459
     },
     {
       "endCharacter": 67,
-      "endLine": 1453,
+      "endLine": 1459,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"float | None\" cannot be assigned to parameter \"x\" of type \"ConvertibleToFloat\" in function \"__new__\"\n  Type \"float | None\" is not assignable to type \"ConvertibleToFloat\"\n    Type \"None\" is not assignable to type \"ConvertibleToFloat\"\n      \"None\" is not assignable to \"str\"\n      \"None\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"None\" is incompatible with protocol \"SupportsFloat\"\n        \"__float__\" is not present\n      \"None\" is incompatible with protocol \"SupportsIndex\"\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 47,
-      "startLine": 1453
+      "startLine": 1459
     },
     {
       "endCharacter": 64,
-      "endLine": 1607,
+      "endLine": 1613,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"isoformat\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 1607
+      "startLine": 1613
     },
     {
       "endCharacter": 37,
-      "endLine": 1658,
+      "endLine": 1664,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"<=\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 15,
-      "startLine": 1658
+      "startLine": 1664
     },
     {
       "endCharacter": 48,
-      "endLine": 1660,
+      "endLine": 1666,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"<=\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 15,
-      "startLine": 1660
+      "startLine": 1666
     },
     {
       "endCharacter": 96,
-      "endLine": 1840,
+      "endLine": 1846,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 1840
+      "startLine": 1846
     },
     {
       "endCharacter": 39,
-      "endLine": 1906,
+      "endLine": 1923,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"+\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 21,
-      "startLine": 1906
+      "startLine": 1923
     },
     {
       "endCharacter": 90,
-      "endLine": 1906,
+      "endLine": 1923,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"*\" not supported for types \"float\" and \"Any | None\"\n  Operator \"*\" not supported for types \"float\" and \"None\"",
       "rule": "reportOperatorIssue",
       "severity": "error",
       "startCharacter": 62,
-      "startLine": 1906
+      "startLine": 1923
     },
     {
       "endCharacter": 96,
-      "endLine": 2205,
+      "endLine": 2227,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 2205
+      "startLine": 2227
     },
     {
       "endCharacter": 85,
-      "endLine": 2230,
+      "endLine": 2252,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "\"isoformat\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 76,
-      "startLine": 2230
+      "startLine": 2252
     },
     {
       "endCharacter": 47,
-      "endLine": 2236,
+      "endLine": 2258,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \"<\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2236
+      "startLine": 2258
     },
     {
       "endCharacter": 42,
-      "endLine": 2240,
+      "endLine": 2262,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"side\" of type \"TradeDirection\" in function \"reversal_confirmed\"\n  Type \"str\" is not assignable to type \"TradeDirection\"\n    \"str\" is not assignable to type \"Literal['long']\"\n    \"str\" is not assignable to type \"Literal['short']\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2240
+      "startLine": 2262
     },
     {
       "endCharacter": 42,
-      "endLine": 2241,
+      "endLine": 2263,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"order\" of type \"OrderType\" in function \"reversal_confirmed\"\n  Type \"str\" is not assignable to type \"OrderType\"\n    \"str\" is not assignable to type \"Literal['entry']\"\n    \"str\" is not assignable to type \"Literal['exit']\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2241
+      "startLine": 2263
     },
     {
       "endCharacter": 69,
-      "endLine": 2243,
+      "endLine": 2265,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"int | float\" cannot be assigned to parameter \"lookback_period_candles\" of type \"int\" in function \"reversal_confirmed\"\n  Type \"int | float\" is not assignable to type \"int\"\n    \"float\" is not assignable to \"int\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2243
+      "startLine": 2265
     },
     {
       "endCharacter": 47,
-      "endLine": 2254,
+      "endLine": 2276,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Operator \">\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2254
+      "startLine": 2276
     },
     {
       "endCharacter": 43,
-      "endLine": 2258,
+      "endLine": 2280,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"side\" of type \"TradeDirection\" in function \"reversal_confirmed\"\n  Type \"str\" is not assignable to type \"TradeDirection\"\n    \"str\" is not assignable to type \"Literal['long']\"\n    \"str\" is not assignable to type \"Literal['short']\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2258
+      "startLine": 2280
     },
     {
       "endCharacter": 42,
-      "endLine": 2259,
+      "endLine": 2281,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"order\" of type \"OrderType\" in function \"reversal_confirmed\"\n  Type \"str\" is not assignable to type \"OrderType\"\n    \"str\" is not assignable to type \"Literal['entry']\"\n    \"str\" is not assignable to type \"Literal['exit']\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2259
+      "startLine": 2281
     },
     {
       "endCharacter": 69,
-      "endLine": 2261,
+      "endLine": 2283,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"int | float\" cannot be assigned to parameter \"lookback_period_candles\" of type \"int\" in function \"reversal_confirmed\"\n  Type \"int | float\" is not assignable to type \"int\"\n    \"float\" is not assignable to \"int\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2261
+      "startLine": 2283
     },
     {
       "endCharacter": 52,
-      "endLine": 2290,
+      "endLine": 2312,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"datetime | None\" cannot be assigned to parameter \"current_candle_date\" of type \"datetime\" in function \"_normalize_final_take_profit_state\"\n  Type \"datetime | None\" is not assignable to type \"datetime\"\n    \"None\" is not assignable to \"datetime\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 2290
+      "startLine": 2312
     },
     {
       "endCharacter": 96,
-      "endLine": 2410,
+      "endLine": 2432,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"Any | None\" cannot be assigned to parameter \"timeframe\" of type \"str\" in function \"get_analyzed_dataframe\"\n  Type \"Any | None\" is not assignable to type \"str\"\n    \"None\" is not assignable to \"str\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 2410
+      "startLine": 2432
     },
     {
       "endCharacter": 43,
-      "endLine": 2419,
+      "endLine": 2441,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"order\" of type \"OrderType\" in function \"reversal_confirmed\"\n  Type \"str\" is not assignable to type \"OrderType\"\n    \"str\" is not assignable to type \"Literal['entry']\"\n    \"str\" is not assignable to type \"Literal['exit']\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2419
+      "startLine": 2441
     },
     {
       "endCharacter": 69,
-      "endLine": 2421,
+      "endLine": 2443,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"int | float\" cannot be assigned to parameter \"lookback_period_candles\" of type \"int\" in function \"reversal_confirmed\"\n  Type \"int | float\" is not assignable to type \"int\"\n    \"float\" is not assignable to \"int\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 2421
+      "startLine": 2443
     },
     {
       "endCharacter": 32,
-      "endLine": 2497,
+      "endLine": 2519,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_trade_annotation_line_start_date\"\n  \"LocalTrade\" is not assignable to \"Trade\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 2497
+      "startLine": 2519
     },
     {
       "endCharacter": 72,
-      "endLine": 2500,
+      "endLine": 2522,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_trade_exit_stage\"\n  \"LocalTrade\" is not assignable to \"Trade\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 67,
-      "startLine": 2500
+      "startLine": 2522
     },
     {
       "endCharacter": 36,
-      "endLine": 2507,
+      "endLine": 2529,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_take_profit_target\"\n  \"LocalTrade\" is not assignable to \"Trade\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 31,
-      "startLine": 2507
+      "startLine": 2529
     },
     {
       "endCharacter": 71,
-      "endLine": 2538,
+      "endLine": 2560,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_trade_entry_date\"\n  \"LocalTrade\" is not assignable to \"Trade\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 66,
-      "startLine": 2538
+      "startLine": 2560
     },
     {
       "endCharacter": 32,
-      "endLine": 2569,
+      "endLine": 2591,
       "file": "quickadapter/user_data/strategies/QuickAdapterV3.py",
       "message": "Argument of type \"LocalTrade\" cannot be assigned to parameter \"trade\" of type \"Trade\" in function \"get_take_profit_target\"\n  \"LocalTrade\" is not assignable to \"Trade\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 2569
+      "startLine": 2591
     },
     {
       "endCharacter": 34,
     },
     {
       "endCharacter": 98,
-      "endLine": 1613,
+      "endLine": 1627,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Type \"bool | bool_\" is not assignable to return type \"bool\"\n  Type \"bool | bool_\" is not assignable to type \"bool\"\n    \"numpy.bool[builtins.bool]\" is not assignable to \"bool\"",
       "rule": "reportReturnType",
       "severity": "error",
       "startCharacter": 15,
-      "startLine": 1613
+      "startLine": 1627
     },
     {
       "endCharacter": 33,
-      "endLine": 1643,
+      "endLine": 1657,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"Scalar\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Scalar\" is not assignable to type \"ConvertibleToInt\"\n    Type \"complex\" is not assignable to type \"ConvertibleToInt\"\n      \"complex\" is not assignable to \"str\"\n      \"complex\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"complex\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"complex\" is incompatible with protocol \"SupportsIndex\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 1643
+      "startLine": 1657
     },
     {
       "endCharacter": 33,
-      "endLine": 1643,
+      "endLine": 1657,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"Scalar\" cannot be assigned to parameter \"x\" of type \"ConvertibleToInt\" in function \"__new__\"\n  Type \"Scalar\" is not assignable to type \"ConvertibleToInt\"\n    Type \"complex\" is not assignable to type \"ConvertibleToInt\"\n      \"complex\" is not assignable to \"str\"\n      \"complex\" is incompatible with protocol \"Buffer\"\n        \"__buffer__\" is not present\n      \"complex\" is incompatible with protocol \"SupportsInt\"\n        \"__int__\" is not present\n      \"complex\" is incompatible with protocol \"SupportsIndex\"\n  ...",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 1643
+      "startLine": 1657
     },
     {
       "endCharacter": 23,
-      "endLine": 1655,
+      "endLine": 1669,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Type \"float\" is not assignable to return type \"T@get_distance\"\n  Type \"float\" is not assignable to type \"T@get_distance\"",
       "rule": "reportReturnType",
       "severity": "error",
       "startCharacter": 11,
-      "startLine": 1655
+      "startLine": 1669
     },
     {
       "endCharacter": 83,
-      "endLine": 2508,
+      "endLine": 2522,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"str\" cannot be assigned to parameter \"key\" of type \"CombinedMetric\" in function \"__getitem__\"\n  Type \"str\" is not assignable to type \"CombinedMetric\"\n    \"str\" is not assignable to type \"Literal['amplitude']\"\n    \"str\" is not assignable to type \"Literal['amplitude_threshold_ratio']\"\n    \"str\" is not assignable to type \"Literal['volume_rate']\"\n    \"str\" is not assignable to type \"Literal['speed']\"\n    \"str\" is not assignable to type \"Literal['efficiency_ratio']\"\n    \"str\" is not assignable to type \"Literal['volume_weighted_efficiency_ratio']\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 58,
-      "startLine": 2508
+      "startLine": 2522
     },
     {
       "endCharacter": 38,
-      "endLine": 3391,
+      "endLine": 3405,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Cannot access attribute \"__func__\" for class \"FunctionType\"\n  Attribute \"__func__\" is unknown",
       "rule": "reportFunctionMemberAccess",
       "severity": "error",
       "startCharacter": 30,
-      "startLine": 3391
+      "startLine": 3405
     },
     {
       "endCharacter": 34,
-      "endLine": 3393,
+      "endLine": 3407,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Cannot access attribute \"__func__\" for class \"FunctionType\"\n  Attribute \"__func__\" is unknown",
       "rule": "reportFunctionMemberAccess",
       "severity": "error",
       "startCharacter": 26,
-      "startLine": 3393
+      "startLine": 3407
     },
     {
       "endCharacter": 55,
-      "endLine": 3618,
+      "endLine": 3632,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"rolling\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 48,
-      "startLine": 3618
+      "startLine": 3632
     },
     {
       "endCharacter": 38,
-      "endLine": 3643,
+      "endLine": 3657,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"rolling\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 31,
-      "startLine": 3643
+      "startLine": 3657
     },
     {
       "endCharacter": 55,
-      "endLine": 3669,
+      "endLine": 3683,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"rolling\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 48,
-      "startLine": 3669
+      "startLine": 3683
     },
     {
       "endCharacter": 56,
-      "endLine": 3670,
+      "endLine": 3684,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"rolling\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 49,
-      "startLine": 3670
+      "startLine": 3684
     },
     {
       "endCharacter": 33,
-      "endLine": 3738,
+      "endLine": 3752,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"Series[Any] | NDArray[floating[Any]]\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n  Type \"Series[Any] | NDArray[floating[Any]]\" is not assignable to type \"Series[Any]\"\n    \"ndarray[_AnyShape, dtype[floating[Any]]]\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 3738
+      "startLine": 3752
     },
     {
       "endCharacter": 69,
-      "endLine": 3738,
+      "endLine": 3752,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Expected 1 more positional argument",
       "rule": "reportCallIssue",
       "severity": "error",
       "startCharacter": 59,
-      "startLine": 3738
+      "startLine": 3752
     },
     {
       "endCharacter": 40,
-      "endLine": 3793,
+      "endLine": 3807,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 35,
-      "startLine": 3793
+      "startLine": 3807
     },
     {
       "endCharacter": 38,
-      "endLine": 3794,
+      "endLine": 3808,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 34,
-      "startLine": 3794
+      "startLine": 3808
     },
     {
       "endCharacter": 42,
-      "endLine": 3795,
+      "endLine": 3809,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"Series[Any] | None\" cannot be assigned to parameter \"series\" of type \"Series[Any]\" in function \"calculate_zero_lag\"\n  Type \"Series[Any] | None\" is not assignable to type \"Series[Any]\"\n    \"None\" is not assignable to \"Series[Any]\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 3795
+      "startLine": 3809
     },
     {
       "endCharacter": 45,
-      "endLine": 3797,
+      "endLine": 3811,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"index\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 40,
-      "startLine": 3797
+      "startLine": 3811
     },
     {
       "endCharacter": 33,
-      "endLine": 3799,
+      "endLine": 3813,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"iloc\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 29,
-      "startLine": 3799
+      "startLine": 3813
     },
     {
       "endCharacter": 31,
-      "endLine": 3800,
+      "endLine": 3814,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"iloc\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 3800
+      "startLine": 3814
     },
     {
       "endCharacter": 48,
-      "endLine": 3805,
+      "endLine": 3819,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"index\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 43,
-      "startLine": 3805
+      "startLine": 3819
     },
     {
       "endCharacter": 40,
-      "endLine": 3806,
+      "endLine": 3820,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"iloc\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 36,
-      "startLine": 3806
+      "startLine": 3820
     },
     {
       "endCharacter": 59,
-      "endLine": 3808,
+      "endLine": 3822,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Cannot access attribute \"iloc\" for class \"NDArray[Any]\"\n  Attribute \"iloc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 55,
-      "startLine": 3808
+      "startLine": 3822
     },
     {
       "endCharacter": 34,
-      "endLine": 3810,
+      "endLine": 3824,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Cannot access attribute \"iloc\" for class \"NDArray[Any]\"\n  Attribute \"iloc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 30,
-      "startLine": 3810
+      "startLine": 3824
     },
     {
       "endCharacter": 51,
-      "endLine": 3810,
+      "endLine": 3824,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"iloc\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 47,
-      "startLine": 3810
+      "startLine": 3824
     },
     {
       "endCharacter": 72,
-      "endLine": 3810,
+      "endLine": 3824,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Cannot access attribute \"iloc\" for class \"NDArray[Any]\"\n  Attribute \"iloc\" is unknown",
       "rule": "reportAttributeAccessIssue",
       "severity": "error",
       "startCharacter": 68,
-      "startLine": 3810
+      "startLine": 3824
     },
     {
       "endCharacter": 40,
-      "endLine": 3877,
+      "endLine": 3891,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to declared type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n  Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n    Missing keyword parameter \"series\"\n    Missing keyword parameter \"timeperiod\"\n      Position-only parameter mismatch; parameter \"series\" is not position-only\n      Position-only parameter mismatch; parameter \"timeperiod\" is not position-only\n      Position-only parameter mismatch; expected 2 but received 0\n      Function return type \"Series[Any] | NDArray[floating[Any]]\" is incompatible with type \"Series[Any]\"\n        Type \"Series[Any] | NDArray[floating[Any]]\" is not assignable to type \"Series[Any]\"\n  ...",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 20,
-      "startLine": 3877
+      "startLine": 3891
     },
     {
       "endCharacter": 33,
-      "endLine": 3879,
+      "endLine": 3893,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to declared type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n  Type \"(Series[Any] | NDArray[floating[Any]], int) -> (Series[Any] | NDArray[floating[Any]])\" is not assignable to type \"(series: Unknown, timeperiod: Unknown) -> Series[Any]\"\n    Missing keyword parameter \"series\"\n    Missing keyword parameter \"timeperiod\"\n      Position-only parameter mismatch; parameter \"series\" is not position-only\n      Position-only parameter mismatch; parameter \"timeperiod\" is not position-only\n      Position-only parameter mismatch; expected 2 but received 0\n      Function return type \"Series[Any] | NDArray[floating[Any]]\" is incompatible with type \"Series[Any]\"\n        Type \"Series[Any] | NDArray[floating[Any]]\" is not assignable to type \"Series[Any]\"\n  ...",
       "rule": "reportAssignmentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 3879
+      "startLine": 3893
     },
     {
       "endCharacter": 35,
-      "endLine": 3925,
+      "endLine": 3939,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 3925
+      "startLine": 3939
     },
     {
       "endCharacter": 33,
-      "endLine": 3926,
+      "endLine": 3940,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 25,
-      "startLine": 3926
+      "startLine": 3940
     },
     {
       "endCharacter": 37,
-      "endLine": 4038,
+      "endLine": 4052,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 29,
-      "startLine": 4038
+      "startLine": 4052
     },
     {
       "endCharacter": 35,
-      "endLine": 4039,
+      "endLine": 4053,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 4039
+      "startLine": 4053
     },
     {
       "endCharacter": 33,
-      "endLine": 4040,
+      "endLine": 4054,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 25,
-      "startLine": 4040
+      "startLine": 4054
     },
     {
       "endCharacter": 39,
-      "endLine": 4060,
+      "endLine": 4074,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"to_numpy\" is not a known attribute of \"None\"",
       "rule": "reportOptionalMemberAccess",
       "severity": "error",
       "startCharacter": 31,
-      "startLine": 4060
+      "startLine": 4074
     },
     {
       "endCharacter": 92,
-      "endLine": 4419,
+      "endLine": 4433,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Type \"bool_ | bool\" is not assignable to return type \"bool\"\n  Type \"bool_ | bool\" is not assignable to type \"bool\"\n    \"numpy.bool[builtins.bool]\" is not assignable to \"bool\"",
       "rule": "reportReturnType",
       "severity": "error",
       "startCharacter": 15,
-      "startLine": 4419
+      "startLine": 4433
     },
     {
       "endCharacter": 85,
-      "endLine": 4803,
+      "endLine": 4817,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"XGBoostPruningCallback\" cannot be assigned to parameter \"object\" of type \"RegressorCallback\" in function \"append\"\n  Type \"XGBoostPruningCallback\" is not assignable to type \"RegressorCallback\"\n    Type \"XGBoostPruningCallback\" is not assignable to type \"(...) -> Any\"\n    \"XGBoostPruningCallback\" is not assignable to \"TrainingCallback\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 16,
-      "startLine": 4803
+      "startLine": 4817
     },
     {
       "endCharacter": 29,
-      "endLine": 4844,
+      "endLine": 4858,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"list[tuple[DataFrame, DataFrame]] | None\" cannot be assigned to parameter \"eval_set\" of type \"List[_LGBM_ScikitValidSet] | None\" in function \"fit\"\n  Type \"list[tuple[DataFrame, DataFrame]] | None\" is not assignable to type \"List[_LGBM_ScikitValidSet] | None\"\n    Type \"list[tuple[DataFrame, DataFrame]]\" is not assignable to type \"List[_LGBM_ScikitValidSet] | None\"\n      \"list[tuple[DataFrame, DataFrame]]\" is not assignable to \"List[_LGBM_ScikitValidSet]\"\n        Type parameter \"_T@list\" is invariant, but \"tuple[DataFrame, DataFrame]\" is not the same as \"_LGBM_ScikitValidSet\"\n        Consider switching from \"list\" to \"Sequence\" which is covariant\n      \"list[tuple[DataFrame, DataFrame]]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 21,
-      "startLine": 4844
+      "startLine": 4858
     },
     {
       "endCharacter": 43,
-      "endLine": 4845,
+      "endLine": 4859,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"list[NDArray[floating[Any]]] | None\" cannot be assigned to parameter \"eval_sample_weight\" of type \"List[_LGBM_WeightType] | None\" in function \"fit\"\n  Type \"list[NDArray[floating[Any]]] | None\" is not assignable to type \"List[_LGBM_WeightType] | None\"\n    Type \"list[NDArray[floating[Any]]]\" is not assignable to type \"List[_LGBM_WeightType] | None\"\n      \"list[NDArray[floating[Any]]]\" is not assignable to \"List[_LGBM_WeightType]\"\n        Type parameter \"_T@list\" is invariant, but \"NDArray[floating[Any]]\" is not the same as \"_LGBM_WeightType\"\n        Consider switching from \"list\" to \"Sequence\" which is covariant\n      \"list[NDArray[floating[Any]]]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 31,
-      "startLine": 4845
+      "startLine": 4859
     },
     {
       "endCharacter": 62,
-      "endLine": 4848,
+      "endLine": 4862,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"list[RegressorCallback] | None\" cannot be assigned to parameter \"callbacks\" of type \"List[(...) -> Unknown] | None\" in function \"fit\"\n  Type \"list[RegressorCallback] | None\" is not assignable to type \"List[(...) -> Unknown] | None\"\n    Type \"list[RegressorCallback]\" is not assignable to type \"List[(...) -> Unknown] | None\"\n      \"list[RegressorCallback]\" is not assignable to \"List[(...) -> Unknown]\"\n        Type parameter \"_T@list\" is invariant, but \"RegressorCallback\" is not the same as \"(...) -> Unknown\"\n        Consider switching from \"list\" to \"Sequence\" which is covariant\n      \"list[RegressorCallback]\" is not assignable to \"None\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 22,
-      "startLine": 4848
+      "startLine": 4862
     },
     {
       "endCharacter": 35,
-      "endLine": 4870,
+      "endLine": 4884,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Object of type \"None\" is not subscriptable",
       "rule": "reportOptionalSubscript",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 4870
+      "startLine": 4884
     },
     {
       "endCharacter": 35,
-      "endLine": 4906,
+      "endLine": 4930,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Object of type \"None\" is not subscriptable",
       "rule": "reportOptionalSubscript",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 4906
+      "startLine": 4930
     },
     {
       "endCharacter": 49,
-      "endLine": 4969,
+      "endLine": 4993,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Argument of type \"CatBoostPruningCallback\" cannot be assigned to parameter \"object\" of type \"RegressorCallback\" in function \"append\"\n  Type \"CatBoostPruningCallback\" is not assignable to type \"RegressorCallback\"\n    Type \"CatBoostPruningCallback\" is not assignable to type \"(...) -> Any\"\n    \"CatBoostPruningCallback\" is not assignable to \"TrainingCallback\"",
       "rule": "reportArgumentType",
       "severity": "error",
       "startCharacter": 33,
-      "startLine": 4969
+      "startLine": 4993
     },
     {
       "endCharacter": 75,
-      "endLine": 5211,
+      "endLine": 5235,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Operator \"<=\" not supported for \"None\"",
       "rule": "reportOptionalOperand",
       "severity": "error",
       "startCharacter": 54,
-      "startLine": 5211
+      "startLine": 5235
     },
     {
       "endCharacter": 23,
-      "endLine": 5374,
+      "endLine": 5398,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"best_params\" is possibly unbound",
       "rule": "reportPossiblyUnboundVariable",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 5374
+      "startLine": 5398
     },
     {
       "endCharacter": 38,
-      "endLine": 5381,
+      "endLine": 5405,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"best_params\" is possibly unbound",
       "rule": "reportPossiblyUnboundVariable",
       "severity": "error",
       "startCharacter": 27,
-      "startLine": 5381
+      "startLine": 5405
     },
     {
       "endCharacter": 22,
-      "endLine": 5393,
+      "endLine": 5417,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "\"best_params\" is possibly unbound",
       "rule": "reportPossiblyUnboundVariable",
       "severity": "error",
       "startCharacter": 11,
-      "startLine": 5393
+      "startLine": 5417
     },
     {
       "endCharacter": 22,
-      "endLine": 5536,
+      "endLine": 5572,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 5536
+      "startLine": 5572
     },
     {
       "endCharacter": 14,
-      "endLine": 5572,
+      "endLine": 5608,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"params\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 5572
+      "startLine": 5608
     },
     {
       "endCharacter": 22,
-      "endLine": 5656,
+      "endLine": 5692,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 5656
+      "startLine": 5692
     },
     {
       "endCharacter": 14,
-      "endLine": 5690,
+      "endLine": 5726,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"params\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 5690
+      "startLine": 5726
     },
     {
       "endCharacter": 22,
-      "endLine": 5761,
+      "endLine": 5797,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 5761
+      "startLine": 5797
     },
     {
       "endCharacter": 22,
-      "endLine": 5860,
+      "endLine": 5898,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 8,
-      "startLine": 5860
+      "startLine": 5898
     },
     {
       "endCharacter": 26,
-      "endLine": 5943,
+      "endLine": 5981,
       "file": "quickadapter/user_data/strategies/Utils.py",
       "message": "Declaration \"default_ranges\" is obscured by a declaration of the same name",
       "rule": "reportRedeclaration",
       "severity": "error",
       "startCharacter": 12,
-      "startLine": 5943
+      "startLine": 5981
     }
   ],
   "filesAnalyzed": 5,
index 43e4b07edf569e761e20e1df7c221aaa2024da1d..7b5ada0cadd61cfb9efaf93fb76ba4bb63c48898 100644 (file)
@@ -102,10 +102,12 @@ from Utils import (
     label_weight_known_at_lookahead_column_name,
     make_test_set_and_weights,
     migrate_config,
+    normalize_fit_live_predictions_config,
     optuna_load_best_params,
     optuna_save_best_params,
     require_bool,
     require_numeric,
+    resolve_optuna_model_parameters,
     safe_distribution_fit,
     sanitize_and_renormalize,
     soft_extremum,
@@ -1037,6 +1039,8 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         mode: ValidationMode = "none",
         metric_ctx: str = "distance_metric",
         p_ctx: str = "p",
+        *,
+        reference_matrix: NDArray[np.floating],
     ) -> dict[str, Any]:
         kwargs: dict[str, Any] = {}
 
@@ -1052,6 +1056,24 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             if validated_p is not None:
                 kwargs["p"] = validated_p
 
+        if distance_metric in {"seuclidean", "mahalanobis"}:
+            if reference_matrix.shape[0] < 2 or not np.all(np.isfinite(reference_matrix)):
+                raise ValueError(
+                    "Standardized distances require a finite full front with at least two rows"
+                )
+            variances = np.var(reference_matrix, axis=0, ddof=1)
+            if not np.all(np.isfinite(variances) & (variances > 0)):
+                raise ValueError(
+                    "Standardized distances require positive active-objective variances"
+                )
+            if distance_metric == "seuclidean":
+                kwargs["V"] = variances
+            else:
+                covariance = np.atleast_2d(np.cov(reference_matrix, rowvar=False, ddof=1))
+                eigenvalues, eigenvectors = np.linalg.eigh(covariance)
+                floor = eigenvalues[-1] * np.sqrt(np.finfo(float).eps)
+                kwargs["VI"] = (eigenvectors / np.maximum(eigenvalues, floor)) @ eigenvectors.T
+
         return kwargs
 
     @staticmethod
@@ -1216,26 +1238,6 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         )
         return cast("str", resolved_metric)
 
-    @staticmethod
-    def _prepare_knn_kwargs(
-        distance_metric: str,
-        *,
-        weights: NDArray[np.floating] | None = None,
-        p: float | None = None,
-        mode: ValidationMode = "warn",
-        p_ctx: str = "label_density_p",
-    ) -> dict[str, Any]:
-        knn_kwargs: dict[str, Any] = {}
-
-        if distance_metric == QuickAdapterRegressorV3._METRIC_MINKOWSKI:
-            validated_p = QuickAdapterRegressorV3._validate_minkowski_p(p, ctx=p_ctx, mode=mode)
-            if validated_p is not None:
-                knn_kwargs["p"] = validated_p
-            if weights is not None:
-                knn_kwargs["metric_params"] = {"w": weights}
-
-        return knn_kwargs
-
     @staticmethod
     def _resolve_p_order(
         distance_metric: str,
@@ -1581,9 +1583,10 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             ]
         return copy.deepcopy(self._optuna_label_candle_pool_full_cache[cache_key])
 
-    def __init__(self, *args, **kwargs):
-        super().__init__(*args, **kwargs)
-        migrate_config(self.config, logger)
+    def __init__(self, config: dict[str, Any], *args, **kwargs):
+        migrate_config(config, logger)
+        normalize_fit_live_predictions_config(config, logger)
+        super().__init__(config, *args, **kwargs)
         self._fit_live_predictions_candles: int = get_fit_live_predictions_candles(
             self.freqai_info, logger
         )
@@ -1612,7 +1615,9 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         self._optuna_label_params: dict[str, dict[str, Any]] = {}
         self._optuna_label_candle_pool_full_cache: dict[int, list[int]] = {}
         self._optuna_label_shuffle_rng = random.Random(self._optuna_config["seed"])
-        self.init_optuna_label_candle_pool()
+        self._optuna_label_candle_pool: list[int] = []
+        if self._optuna_hyperopt:
+            self.init_optuna_label_candle_pool()
         self._optuna_label_candle: dict[str, int] = {}
         self._optuna_label_candles: dict[str, int] = {}
         self._optuna_label_incremented_pairs: list[str] = []
@@ -1644,7 +1649,8 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             self._optuna_label_params[pair] = (
                 self.optuna_load_best_params(pair, _OPTUNA_NAMESPACES.label) if trade_mode else None
             ) or configured_label_params
-            self.set_optuna_label_candle(pair)
+            if self._optuna_hyperopt:
+                self.set_optuna_label_candle(pair)
             self._optuna_label_candles[pair] = 0
 
         self.regressor: Regressor = self.freqai_info.get("regressor", DEFAULT_REGRESSOR)
@@ -1907,7 +1913,11 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 remaining_candles = optuna_label_candle - optuna_label_candles
                 if remaining_candles in optuna_label_candle_pool:
                     optuna_label_candle_pool.remove(remaining_candles)
-        optuna_label_candle = optuna_label_candle_pool.pop()
+        optuna_label_candle = (
+            optuna_label_candle_pool[-1]
+            if optuna_label_candle_pool
+            else self._optuna_label_candle_pool[-1]
+        )
         self._optuna_label_candle[pair] = optuna_label_candle
         self._optuna_label_candle_pool.remove(optuna_label_candle)
         optuna_label_available_candles = (
@@ -1960,7 +1970,9 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             scaler_obj = SKLearnWrapper(MinMaxScaler(feature_range=feature_range))
 
         steps = [
-            (name, copy.deepcopy(scaler_obj)) if name in ("scaler", "post-pca-scaler") else (name, transformer)
+            (name, copy.deepcopy(scaler_obj))
+            if name in ("scaler", "post-pca-scaler")
+            else (name, transformer)
             for name, transformer in pipeline.steps
         ]
 
@@ -2139,6 +2151,23 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             train_labels = labels
             train_base_weights = weights.base
             train_label_weights = weights.label
+            if causal_mode:
+                keep_mask = self._known_before_position_mask(
+                    features, unfiltered_df, dk.pair, len(unfiltered_df)
+                )
+                (
+                    train_features,
+                    train_labels,
+                    train_base_weights,
+                    train_label_weights,
+                ) = QuickAdapterRegressorV3._filter_train_by_mask(
+                    train_features,
+                    train_labels,
+                    train_base_weights,
+                    keep_mask,
+                    f"[{dk.pair}] full-training causal guard",
+                    train_label_weights=train_label_weights,
+                )
             test_features = features.iloc[:0]
             test_labels = labels.iloc[:0]
             test_base_weights = weights.base[:0]
@@ -2969,7 +2998,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             if optuna_hp_params:
                 model_training_parameters = {
                     **model_training_parameters,
-                    **optuna_hp_params,
+                    **resolve_optuna_model_parameters(self.regressor, optuna_hp_params),
                 }
 
         eval_set, eval_weights = make_test_set_and_weights(
@@ -3642,12 +3671,11 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         mode: ValidationMode = "none",
         p_ctx: str = "p",
     ) -> NDArray[np.floating]:
-        validated_p = QuickAdapterRegressorV3._validate_power_mean_p(p, ctx=p_ctx, mode=mode)
-        power = (
-            QuickAdapterRegressorV3._POWER_MEAN_MAP[distance_metric]
-            if distance_metric in QuickAdapterRegressorV3._POWER_MEAN_METRICS_SET
-            else (1.0 if validated_p is None else validated_p)
-        )
+        if distance_metric in QuickAdapterRegressorV3._POWER_MEAN_METRICS_SET:
+            power = QuickAdapterRegressorV3._POWER_MEAN_MAP[distance_metric]
+        else:
+            validated_p = QuickAdapterRegressorV3._validate_power_mean_p(p, ctx=p_ctx, mode=mode)
+            power = 1.0 if validated_p is None else validated_p
         if weights is None:
             weights = np.ones(matrix.shape[1])
 
@@ -3676,18 +3704,9 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         p: float | None,
         method: str,
         apply_abs: bool,
-        cdist_kwargs: dict[str, Any] | None = None,
+        cdist_kwargs: dict[str, Any],
     ) -> NDArray[np.floating]:
         if distance_metric in QuickAdapterRegressorV3._SCIPY_METRICS_SET:
-            if cdist_kwargs is None:
-                cdist_kwargs = QuickAdapterRegressorV3._prepare_distance_kwargs(
-                    distance_metric,
-                    weights=weights,
-                    p=p,
-                    mode="warn",
-                    metric_ctx="label_distance_metric",
-                    p_ctx="label_distance_p",
-                )
             return sp.spatial.distance.cdist(
                 normalized_matrix,
                 reference_point.reshape(1, -1),
@@ -3740,6 +3759,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         normalized_matrix: NDArray[np.floating],
         distance_metric: str,
         *,
+        distance_kwargs: dict[str, Any],
         weights: NDArray[np.floating] | None = None,
         p: float | None = None,
     ) -> NDArray[np.floating]:
@@ -3763,6 +3783,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             p=p,
             method=QuickAdapterRegressorV3._METHOD_COMPROMISE_PROGRAMMING,
             apply_abs=False,
+            cdist_kwargs=distance_kwargs,
         )
 
     @staticmethod
@@ -3770,6 +3791,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         matrix: NDArray[np.floating],
         distance_metric: str,
         *,
+        distance_kwargs: dict[str, Any],
         weights: NDArray[np.floating] | None = None,
         p: float | None = None,
     ) -> NDArray[np.floating]:
@@ -3791,17 +3813,8 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         if n == 1:
             return np.array([0.0])
 
-        pdist_kwargs = QuickAdapterRegressorV3._prepare_distance_kwargs(
-            distance_metric,
-            weights=weights,
-            p=p,
-            mode="warn",
-            metric_ctx="label_density_metric",
-            p_ctx="label_density_p",
-        )
-
         pairwise_distances_vector = sp.spatial.distance.pdist(
-            matrix, metric=distance_metric, **pdist_kwargs
+            matrix, metric=distance_metric, **distance_kwargs
         )
 
         sums = np.zeros(n, dtype=float)
@@ -3817,6 +3830,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         normalized_matrix: NDArray[np.floating],
         distance_metric: str,
         *,
+        distance_kwargs: dict[str, Any],
         weights: NDArray[np.floating] | None = None,
         p: float | None = None,
     ) -> NDArray[np.floating]:
@@ -3833,19 +3847,6 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         ideal_point = np.ones(n_objectives)
         anti_ideal_point = np.zeros(n_objectives)
 
-        cdist_kwargs = (
-            QuickAdapterRegressorV3._prepare_distance_kwargs(
-                distance_metric,
-                weights=weights,
-                p=p,
-                mode="warn",
-                metric_ctx="label_distance_metric",
-                p_ctx="label_distance_p",
-            )
-            if distance_metric in QuickAdapterRegressorV3._SCIPY_METRICS_SET
-            else None
-        )
-
         dist_to_ideal = QuickAdapterRegressorV3._distance_to_reference(
             normalized_matrix,
             ideal_point,
@@ -3854,7 +3855,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             p=p,
             method=QuickAdapterRegressorV3._METHOD_TOPSIS,
             apply_abs=True,
-            cdist_kwargs=cdist_kwargs,
+            cdist_kwargs=distance_kwargs,
         )
         dist_to_anti_ideal = QuickAdapterRegressorV3._distance_to_reference(
             normalized_matrix,
@@ -3864,7 +3865,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             p=p,
             method=QuickAdapterRegressorV3._METHOD_TOPSIS,
             apply_abs=True,
-            cdist_kwargs=cdist_kwargs,
+            cdist_kwargs=distance_kwargs,
         )
 
         denominator = dist_to_ideal + dist_to_anti_ideal
@@ -3882,23 +3883,15 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         ideal_point_2d: NDArray[np.floating],
         distance_metric: str,
         *,
+        distance_kwargs: dict[str, Any],
         weights: NDArray[np.floating] | None = None,
         p: float | None = None,
     ) -> float:
-        cdist_kwargs = QuickAdapterRegressorV3._prepare_distance_kwargs(
-            distance_metric=distance_metric,
-            weights=weights,
-            p=p,
-            mode="warn",
-            metric_ctx="label_cluster_metric",
-            p_ctx="label_cluster_p",
-        )
-
         return sp.spatial.distance.cdist(
             normalized_matrix[[trial_index]],
             ideal_point_2d,
             metric=distance_metric,
-            **cdist_kwargs,
+            **distance_kwargs,
         ).item()
 
     def _select_best_trial_from_cluster(
@@ -3909,6 +3902,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         ideal_point_2d: NDArray[np.floating],
         distance_metric: str,
         *,
+        distance_kwargs: dict[str, Any],
         weights: NDArray[np.floating] | None = None,
         p: float | None = None,
     ) -> tuple[int, float]:
@@ -3921,6 +3915,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 distance_metric,
                 weights=weights,
                 p=p,
+                distance_kwargs=distance_kwargs,
             )
             return best_trial_index, best_trial_distance
 
@@ -3930,6 +3925,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 distance_metric,
                 weights=weights,
                 p=p,
+                distance_kwargs=distance_kwargs,
             )
         elif trial_selection_method == QuickAdapterRegressorV3._METHOD_TOPSIS:
             scores = QuickAdapterRegressorV3._topsis_scores(
@@ -3937,6 +3933,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 distance_metric,
                 weights=weights,
                 p=p,
+                distance_kwargs=distance_kwargs,
             )
         else:
             raise ValueError(
@@ -3956,6 +3953,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             distance_metric,
             weights=weights,
             p=p,
+            distance_kwargs=distance_kwargs,
         )
         return best_trial_index, best_trial_distance
 
@@ -3964,6 +3962,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         normalized_matrix: NDArray[np.floating],
         cluster_method: ClusterMethod,
         *,
+        distance_kwargs: dict[str, Any],
         distance_metric: str,
         selection_method: DistanceMethod,
         trial_selection_method: DistanceMethod,
@@ -3998,12 +3997,16 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 cluster_center_scores = QuickAdapterRegressorV3._compromise_programming_scores(
                     cluster_centers,
                     distance_metric,
+                    weights=weights,
+                    distance_kwargs=distance_kwargs,
                     p=p,
                 )
             elif selection_method == QuickAdapterRegressorV3._METHOD_TOPSIS:
                 cluster_center_scores = QuickAdapterRegressorV3._topsis_scores(
                     cluster_centers,
                     distance_metric,
+                    weights=weights,
+                    distance_kwargs=distance_kwargs,
                     p=p,
                 )
             else:
@@ -4033,6 +4036,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                     distance_metric,
                     weights=weights,
                     p=p,
+                    distance_kwargs=distance_kwargs,
                 )
                 trial_distances[best_trial_index] = best_trial_distance
             return trial_distances
@@ -4059,6 +4063,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         normalized_matrix: NDArray[np.floating],
         aggregation: DensityAggregation,
         *,
+        distance_kwargs: dict[str, Any],
         distance_metric: str,
         n_neighbors: int,
         weights: NDArray[np.floating] | None = None,
@@ -4072,20 +4077,15 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         if n_samples == 1:
             return np.array([0.0])
 
-        knn_kwargs = QuickAdapterRegressorV3._prepare_knn_kwargs(
-            distance_metric,
-            weights=weights,
-            p=p,
-            mode="raise",
+        k = min(n_neighbors, n_samples - 1)
+        if k < 1:
+            return np.full(n_samples, np.inf)
+        distances = sp.spatial.distance.squareform(
+            sp.spatial.distance.pdist(normalized_matrix, metric=distance_metric, **distance_kwargs)
         )
-
-        nbrs = sklearn.neighbors.NearestNeighbors(
-            n_neighbors=min(n_neighbors, n_samples - 1) + 1,
-            metric=distance_metric,
-            **knn_kwargs,
-        ).fit(normalized_matrix)
-        distances, _ = nbrs.kneighbors(normalized_matrix)
-        neighbor_distances = distances[:, 1:]
+        np.fill_diagonal(distances, np.inf)
+        distances.partition(k - 1, axis=1)
+        neighbor_distances = distances[:, :k]
 
         if neighbor_distances.shape[1] < 1:
             return np.full(n_samples, np.inf)
@@ -4382,21 +4382,31 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
         }:
             return np.array([0.0])
 
-        if category == "distance":
-            distance_metric = label_config["distance_metric"]
-            p = QuickAdapterRegressorV3._resolve_p_order(
+        distance_metric = label_config["distance_metric"]
+        p = QuickAdapterRegressorV3._resolve_p_order(
+            distance_metric, label_p_order, ctx=f"label_p_order for {method}", mode="none"
+        )
+        distance_kwargs = (
+            QuickAdapterRegressorV3._prepare_distance_kwargs(
                 distance_metric,
-                label_p_order,
-                ctx=f"label_p_order for {method}",
-                mode="none",
+                weights=weights,
+                p=p,
+                mode="warn",
+                metric_ctx=f"label_{category}_metric",
+                reference_matrix=normalized_matrix,
             )
+            if distance_metric in QuickAdapterRegressorV3._SCIPY_METRICS_SET and n_samples > 1
+            else {}
+        )
 
+        if category == "distance":
             if method == QuickAdapterRegressorV3._METHOD_COMPROMISE_PROGRAMMING:
                 return QuickAdapterRegressorV3._compromise_programming_scores(
                     normalized_matrix,
                     distance_metric,
                     weights=weights,
                     p=p,
+                    distance_kwargs=distance_kwargs,
                 )
             if method == QuickAdapterRegressorV3._METHOD_TOPSIS:
                 return QuickAdapterRegressorV3._topsis_scores(
@@ -4404,6 +4414,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                     distance_metric,
                     weights=weights,
                     p=p,
+                    distance_kwargs=distance_kwargs,
                 )
 
         if category == "cluster":
@@ -4411,12 +4422,6 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             cluster_selection_method = label_config["selection_method"]
             trial_selection_method = label_config["trial_selection_method"]
 
-            p = QuickAdapterRegressorV3._resolve_p_order(
-                cluster_metric,
-                label_p_order,
-                ctx=f"label_p_order for {method}",
-                mode="none",
-            )
             return self._cluster_based_selection(
                 normalized_matrix,
                 method,
@@ -4425,17 +4430,12 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                 trial_selection_method=trial_selection_method,
                 weights=weights,
                 p=p,
+                distance_kwargs=distance_kwargs,
             )
 
         if category == "density":
             density_method = cast("DensityMethod", method)
             density_metric = label_config["distance_metric"]
-            p = QuickAdapterRegressorV3._resolve_p_order(
-                density_metric,
-                label_p_order,
-                ctx=f"label_p_order for {density_method}",
-                mode="none",
-            )
 
             if density_method == QuickAdapterRegressorV3._DENSITY_KNN:
                 knn_n_neighbors = int(label_config["n_neighbors"])
@@ -4454,6 +4454,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                     weights=weights,
                     p=p,
                     aggregation_param=knn_aggregation_param,
+                    distance_kwargs=distance_kwargs,
                 )
 
             if density_method == QuickAdapterRegressorV3._DENSITY_MEDOID:
@@ -4462,6 +4463,7 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
                     density_metric,
                     weights=weights,
                     p=p,
+                    distance_kwargs=distance_kwargs,
                 )
 
         raise ValueError(
index 8f9e86f8937a48b4902544bc5b4b382b2acad926..83e8bdf628b762d72651a1df2aaffb695a5edaa6 100644 (file)
@@ -24,6 +24,7 @@ from freqtrade.exchange import (
 from freqtrade.persistence import Trade
 from freqtrade.strategy import AnnotationType, stoploss_from_absolute
 from freqtrade.strategy.interface import IStrategy
+from freqtrade.util import FtPrecise
 from LabelTransformer import (
     COMBINED_AGGREGATIONS,
     FILL_METHODS,
@@ -79,6 +80,7 @@ from Utils import (
     migrate_config,
     nan_average,
     non_zero_diff,
+    normalize_fit_live_predictions_config,
     optuna_load_best_params,
     price_retracement_percent,
     safe_divide,
@@ -256,8 +258,9 @@ class QuickAdapterV3(IStrategy):
     process_only_new_candles = True
 
     def __init__(self, config: dict[str, Any], *args, **kwargs) -> None:
+        migrate_config(config, logger)
+        normalize_fit_live_predictions_config(config, logger)
         super().__init__(config, *args, **kwargs)
-        migrate_config(self.config, logger)
         if self.is_trade_runmode and self.config.get("api_server", {}).get("enabled", False):
             _install_rpc_custom_data_cleanup_patch()
 
@@ -1055,7 +1058,10 @@ class QuickAdapterV3(IStrategy):
             ):
                 if lookahead_column in dataframe.columns:
                     dataframe[lookahead_column] = compose_label_lookahead(
-                        dataframe[lookahead_column], kernel_half_width
+                        dataframe[lookahead_column],
+                        kernel_half_width,
+                        method=col_smoothing_config["method"],
+                        mode=col_smoothing_config["mode"],
                     )
 
             if label_col == EXTREMA_COLUMN:
@@ -1864,40 +1870,51 @@ class QuickAdapterV3(IStrategy):
         if trade_partial_exit:
             trade_stake_percent = QuickAdapterV3.partial_exit_stages[trade_exit_stage][1]
             trade_partial_stake_amount = trade_stake_percent * trade.stake_amount
-            if min_stake is not None and min_stake > 0:
-                current_position_value = trade.amount * current_exit_rate
-                # Live/dry-run passes ``min_entry_stake``, while freqtrade's
-                # backtesting path already passes the adjusted minimum it guards.
-                min_remaining_position_value = min_stake
-                if self.is_trade_runmode:
-                    # For both the cost- and amount-driven minimum, ``min_exit_stake``
-                    # <= ``min_stake`` * max(exit/entry, 1/(1-|sl|)).
-                    min_remaining_position_value *= max(
-                        current_exit_rate / current_entry_rate,
-                        1.0 / (1.0 - abs(self.stoploss)),
-                    )
-                min_remaining_position_value *= 1.0 + QuickAdapterV3._PARTIAL_EXIT_MIN_STAKE_MARGIN
-                if current_position_value <= min_remaining_position_value:
-                    return None
-                remaining_position_value = current_position_value * (1 - trade_stake_percent)
-                if remaining_position_value < min_remaining_position_value:
-                    initial_trade_partial_stake_amount = trade_partial_stake_amount
-                    trade_partial_stake_amount = trade.stake_amount * (
-                        1 - min_remaining_position_value / current_position_value
-                    )
-                    logger.info(
-                        f"[{pair}] {trade.trade_direction} partial exit stage "
-                        f"{trade_exit_stage} | stake "
-                        f"{format_number(initial_trade_partial_stake_amount)} -> "
-                        f"{format_number(trade_partial_stake_amount)} to preserve "
-                        f"min_remaining_position_value {format_number(min_remaining_position_value)}"
+            tag = (
+                f"{QuickAdapterV3._TAKE_PROFIT_ORDER_TAG_PREFIX}"
+                f"{trade.trade_direction}_{trade_exit_stage}"
+            )
+            exchange = self.dp._exchange
+            if exchange is None:
+                return -trade.stake_amount, tag
+            exit_minimum = exchange.get_min_pair_stake_amount(
+                pair, current_exit_rate, 0.0, trade.leverage
+            )
+            remaining_minimum = exchange.get_min_pair_stake_amount(
+                pair, current_exit_rate, self.stoploss, trade.leverage
+            )
+            exit_minimum_value = (exit_minimum or 0.0) * trade.leverage
+            remaining_minimum_value = (remaining_minimum or 0.0) * trade.leverage
+            if not self.is_trade_runmode:
+                # Backtesting guards quote notional against its unleveraged callback minimum.
+                remaining_minimum_value = max(remaining_minimum_value, min_stake or 0.0)
+            remaining_minimum_value *= 1.0 + QuickAdapterV3._PARTIAL_EXIT_MIN_STAKE_MARGIN
+            current_position_value = trade.amount * current_exit_rate
+            if current_position_value <= remaining_minimum_value:
+                return -trade.stake_amount, tag
+            trade_partial_stake_amount = min(
+                trade_partial_stake_amount,
+                trade.stake_amount * (1 - remaining_minimum_value / current_position_value),
+            )
+            exit_amount = exchange.amount_to_contract_precision(
+                pair,
+                abs(
+                    float(
+                        FtPrecise(trade_partial_stake_amount)
+                        * FtPrecise(trade.amount)
+                        / FtPrecise(trade.stake_amount)
                     )
+                ),
+            )
+            if (
+                exit_amount <= 0
+                or exit_amount * current_exit_rate < exit_minimum_value
+                or (trade.amount - exit_amount) * current_exit_rate < remaining_minimum_value
+            ):
+                return -trade.stake_amount, tag
             return (
                 -trade_partial_stake_amount,
-                (
-                    f"{QuickAdapterV3._TAKE_PROFIT_ORDER_TAG_PREFIX}"
-                    f"{trade.trade_direction}_{trade_exit_stage}"
-                ),
+                tag,
             )
 
         return None
@@ -2108,6 +2125,11 @@ class QuickAdapterV3(IStrategy):
         trade_direction = side
 
         max_lookback_period_candles = max(0, len(df) - 1)
+        if (
+            order == QuickAdapterV3._ORDER_ENTRY
+            and lookback_period_candles > max_lookback_period_candles
+        ):
+            return False
         lookback_period_candles = min(lookback_period_candles, max_lookback_period_candles)
         if not isinstance(decay_fraction, (int, float)):
             logger.debug(f"[{pair}] Denied {trade_direction} {order}: invalid decay_fraction type")
index d0e55781a19a2831af4120bbdcf17c2c8c1ceace..72b41f7161e21320ca6f408a440f1099bfb94644 100644 (file)
@@ -982,6 +982,9 @@ def _sanitize_known_at_lookahead(
 def compose_label_lookahead(
     known_at_lookahead: pd.Series,
     kernel_half_width: int,
+    *,
+    method: SmoothingMethod,
+    mode: SmoothingMode,
 ) -> pd.Series:
     """Compose row-wise label availability with a centered smoothing kernel.
 
@@ -1007,6 +1010,10 @@ def compose_label_lookahead(
         center=True,
         min_periods=1,
     ).max()
+    if method == "savgol" and mode == "interp":
+        smoothed_known_at_positions.iloc[:kernel_half_width] = known_at_positions.iloc[
+            : 2 * kernel_half_width + 1
+        ].max()
     right_edge_start = max(0, n - kernel_half_width)
     smoothed_known_at_positions.iloc[right_edge_start:] = n
     return pd.Series(
@@ -1543,6 +1550,13 @@ def get_fit_live_predictions_candles(config: Any, logger: Logger) -> int:
     )["fit_live_predictions_candles"]
 
 
+def normalize_fit_live_predictions_config(config: dict[str, Any], logger: Logger) -> None:
+    """Publish the canonical window without hiding an absent/invalid FreqAI section."""
+    freqai = config.get("freqai")
+    if isinstance(freqai, dict) and freqai:
+        freqai["fit_live_predictions_candles"] = get_fit_live_predictions_candles(freqai, logger)
+
+
 DEFAULTS_REVERSAL_CONFIRMATION: Final[dict[str, Any]] = {
     "lookback_period_candles": 0,
     "decay_fraction": 0.5,
@@ -4898,7 +4912,17 @@ def fit_regressor(
 
         early_stopping_rounds = _pop_early_stopping_rounds(model_training_parameters, has_eval_set)
 
-        dist = model_training_parameters.pop("dist", "lognormal")
+        dist = model_training_parameters.pop("dist", "normal")
+        if dist == "lognormal":
+            label_sets = [y] + ([labels for _, labels in eval_set] if eval_set else [])
+            if any(
+                not np.all(np.isfinite(values) & (values > 0))
+                for values in (labels.to_numpy() for labels in label_sets)
+            ):
+                message = "NGBoost lognormal requires strictly positive finite training and evaluation labels"
+                if trial is not None:
+                    raise optuna.TrialPruned(message)
+                raise ValueError(message)
 
         X_val = None
         Y_val = None
@@ -5485,6 +5509,18 @@ def optuna_save_best_params(
         raise
 
 
+def resolve_optuna_model_parameters(regressor: Regressor, params: dict[str, Any]) -> dict[str, Any]:
+    """Reconstruct estimator parameters from replayable raw Optuna suggestions."""
+    resolved = params.copy()
+    if regressor == _REGRESSOR_SPECS.xgboost.name and resolved.get("grow_policy") == "lossguide":
+        resolved["max_depth"] = 0
+    elif regressor == _REGRESSOR_SPECS.histgradientboostingregressor.name and resolved.pop(
+        "l2_regularization_zero", False
+    ):
+        resolved["l2_regularization"] = 0.0
+    return resolved
+
+
 def get_optuna_study_model_parameters(
     trial: optuna.trial.Trial,
     regressor: Regressor,
@@ -5527,7 +5563,7 @@ def get_optuna_study_model_parameters(
                     new_max = center_value + margin
                 param_min = max(default_min, new_min)
                 param_max = min(default_max, new_max)
-                if param_min < param_max:
+                if param_min <= param_max:
                     ranges[param] = (param_min, param_max)
         return ranges
 
@@ -5586,7 +5622,7 @@ def get_optuna_study_model_parameters(
             "grow_policy": grow_policy,
             **(
                 {
-                    "max_depth": 0,
+                    # Unlimited depth is reconstructed at the estimator boundary.
                     "max_leaves": _optuna_suggest_int_from_range(
                         trial, "max_leaves", ranges["max_leaves"], min_val=2, log=True
                     ),
@@ -5649,7 +5685,7 @@ def get_optuna_study_model_parameters(
             params["skip_drop"] = trial.suggest_float("skip_drop", 0.0, 0.7)
             params["one_drop"] = trial.suggest_categorical("one_drop", [False, True])
 
-        return params
+        return resolve_optuna_model_parameters(regressor, params)
 
     elif regressor == _REGRESSOR_SPECS.lightgbm.name:
         # Parameter order: boosting -> tree structure -> leaf constraints ->
@@ -5808,7 +5844,7 @@ def get_optuna_study_model_parameters(
                 min(max_leaf_nodes_range[1], float(2**max_depth)),
             )
 
-        return {
+        params = {
             # Boosting/Training
             "max_iter": _optuna_suggest_int_from_range(
                 trial, "max_iter", ranges["max_iter"], min_val=1, log=True
@@ -5840,6 +5876,7 @@ def get_optuna_study_model_parameters(
             ),
             # Regularization
             "l2_regularization": l2_regularization,
+            "l2_regularization_zero": l2_regularization_zero,
             # Binning
             "max_bins": _optuna_suggest_int_from_range(
                 trial, "max_bins", ranges["max_bins"], min_val=2
@@ -5855,6 +5892,7 @@ def get_optuna_study_model_parameters(
                 log=True,
             ),
         }
+        return resolve_optuna_model_parameters(regressor, params)
 
     elif regressor == _REGRESSOR_SPECS.ngboost.name:
         # Parameter order: boosting -> tree structure -> sampling -> early stopping -> distribution