| freqai.feature_parameters.min_label_natr_multiplier | 9.0 | float > 0 | Minimum labeling NATR multiplier used for reversals labeling HPO. (Deprecated alias: `freqai.feature_parameters.min_label_natr_ratio`) |
| freqai.feature_parameters.max_label_natr_multiplier | 12.0 | float > 0 | Maximum labeling NATR multiplier used for reversals labeling HPO. (Deprecated alias: `freqai.feature_parameters.max_label_natr_ratio`) |
| freqai.feature_parameters.label_frequency_candles | `auto` | int >= 2 \| `auto` | Reversals labeling frequency. `auto` = max(2, 2 \* number of whitelisted pairs). |
-| freqai.feature_parameters.label_metric | `euclidean` | string (supported: `euclidean`,`minkowski`,`cityblock`,`chebyshev`,`mahalanobis`,`seuclidean`,`jensenshannon`,`sqeuclidean`,...) | Metric used in distance calculations to ideal point. |
+| freqai.feature_parameters.label_metric | `euclidean` | string | Metric for Pareto front trial selection (SciPy distance metrics or selection metrics like `topsis`, `medoid`, `kmeans`, `kmedoids`, ...). |
| freqai.feature_parameters.label_weights | [1/7,1/7,1/7,1/7,1/7,1/7,1/7] | list[float] | Per-objective weights used in distance calculations to ideal point. Objectives: (1) number of detected reversals, (2) median swing amplitude, (3) median (swing amplitude / median volatility-threshold ratio), (4) median swing volume per candle, (5) median swing speed, (6) median swing efficiency ratio, (7) median swing volume-weighted efficiency ratio. |
-| freqai.feature_parameters.label_p_order | `None` | float \| None | p-order used by `minkowski` / `power_mean` (optional). |
-| freqai.feature_parameters.label_medoid_metric | `euclidean` | string | Metric used with `medoid`. |
-| freqai.feature_parameters.label_kmeans_metric | `euclidean` | string | Metric used for k-means clustering. |
+| freqai.feature_parameters.label_p_order | `None` | float \| None | p-order for Minkowski distance. Used by `minkowski`, `power_mean`, `medoid`, `kmeans`, `kmedoids`, `knn`, `topsis` when their sub-metric is `minkowski`. |
+| freqai.feature_parameters.label_medoid_metric | `euclidean` | string | Distance metric used with `medoid`. |
+| freqai.feature_parameters.label_kmeans_metric | `euclidean` | string | Distance metric used for k-means clustering. |
| freqai.feature_parameters.label_kmeans_selection | `min` | enum {`min`,`medoid`} | Strategy to select trial in the best k-means cluster. |
-| freqai.feature_parameters.label_kmedoids_metric | `euclidean` | string | Metric used for k-medoids clustering. |
+| freqai.feature_parameters.label_kmedoids_metric | `euclidean` | string | Distance metric used for k-medoids clustering. |
| freqai.feature_parameters.label_kmedoids_selection | `min` | enum {`min`,`medoid`} | Strategy to select trial in the best k-medoids cluster. |
+| freqai.feature_parameters.label_topsis_metric | `euclidean` | string | Distance metric for TOPSIS ideal/anti-ideal point calculations. |
| freqai.feature_parameters.label_knn_metric | `minkowski` | string | Distance metric for KNN. |
-| freqai.feature_parameters.label_knn_p_order | `None` | float \| None | Tunable for KNN neighbor distances aggregation methods: p-order (`knn_power_mean`, default: 1.0) or quantile (`knn_quantile`, default: 0.5). (optional) |
+| freqai.feature_parameters.label_knn_p_order | `None` | float \| None | Tunable for KNN neighbor distances aggregation methods: p-order (`knn_power_mean`, default: 1.0) or quantile (`knn_quantile`, default: 0.5). |
| freqai.feature_parameters.label_knn_n_neighbors | 5 | int >= 1 | Number of neighbors for KNN. |
| _Predictions extrema_ | | | |
| freqai.predictions_extrema.selection_method | `rank_extrema` | enum {`rank_extrema`,`rank_peaks`,`partition`} | Extrema selection method. `rank_extrema` ranks extrema values, `rank_peaks` ranks detected peak values, `partition` uses sign-based partitioning. |
----------------------
R'(s,a,s') = R(s,a,s') + Δ(s,a,s')
- Non Canonical PBRS Formula
+ Non-Canonical PBRS Formula
--------------------------
R'(s,a,s') = R(s,a,s') + Δ(s,a,s') + entry_additive + exit_additive
https://github.com/sponsors/robcaulk
"""
- version = "3.8.4"
+ version = "3.8.5"
_TEST_SIZE: Final[float] = 0.1
"knn_min",
"knn_max",
"medoid",
+ "topsis",
)
_METRICS: Final[tuple[str, ...]] = (
label_p_order_reason = (
f"{label_metric} (via label_knn_metric={label_knn_metric})"
)
+ elif (
+ label_metric == QuickAdapterRegressorV3._CUSTOM_METRICS[17]
+ ): # "topsis"
+ label_topsis_metric = self.ft_params.get(
+ "label_topsis_metric",
+ QuickAdapterRegressorV3._SCIPY_METRICS[2], # "euclidean" default
+ )
+ if (
+ label_topsis_metric == QuickAdapterRegressorV3._SCIPY_METRICS[5]
+ ): # "minkowski"
+ label_p_order_is_used = True
+ label_p_order_reason = f"{label_metric} (via label_topsis_metric={label_topsis_metric})"
if label_p_order_config is not None:
logger.info(
f" label_knn_p_order: {format_number(label_knn_p_order_default)} (default for {label_metric})"
)
+ label_topsis_metric_config = self.ft_params.get("label_topsis_metric")
+ if label_topsis_metric_config is not None:
+ logger.info(f" label_topsis_metric: {label_topsis_metric_config}")
+ elif (
+ label_metric == QuickAdapterRegressorV3._CUSTOM_METRICS[17]
+ ): # "topsis"
+ logger.info(
+ f" label_topsis_metric: {QuickAdapterRegressorV3._SCIPY_METRICS[2]} (default for {label_metric})"
+ )
+
logger.info("Predictions Extrema Configuration:")
predictions_extrema = self.predictions_extrema
logger.info(
return np.nanmin(neighbor_distances, axis=1)
elif metric == QuickAdapterRegressorV3._CUSTOM_METRICS[15]: # "knn_max"
return np.nanmax(neighbor_distances, axis=1)
+ elif metric == QuickAdapterRegressorV3._CUSTOM_METRICS[17]: # "topsis"
+ # TOPSIS (Hwang & Yoon, 1981): returns D+ / (D+ + D-) for argmin selection
+ # where D+ = distance to ideal [1,1,...], D- = distance to anti-ideal [0,0,...]
+ label_topsis_metric = self.ft_params.get(
+ "label_topsis_metric",
+ QuickAdapterRegressorV3._SCIPY_METRICS[2], # "euclidean"
+ )
+ cdist_kwargs: dict[str, Any] = {
+ "metric": label_topsis_metric,
+ "w": np_weights,
+ }
+ if (
+ label_topsis_metric
+ == QuickAdapterRegressorV3._SCIPY_METRICS[5] # "minkowski"
+ ):
+ cdist_kwargs["p"] = (
+ label_p_order
+ if label_p_order is not None and np.isfinite(label_p_order)
+ else self._get_label_p_order_default(label_topsis_metric)
+ )
+ dist_to_ideal = sp.spatial.distance.cdist(
+ normalized_matrix, ideal_point_2d, **cdist_kwargs
+ ).flatten()
+ dist_to_anti_ideal = sp.spatial.distance.cdist(
+ normalized_matrix, np.zeros((1, n_objectives)), **cdist_kwargs
+ ).flatten()
+
+ denominator = dist_to_ideal + dist_to_anti_ideal
+ zero_mask = np.isclose(denominator, 0.0)
+ denominator[zero_mask] = 1.0
+ topsis_score = dist_to_ideal / denominator
+ topsis_score[zero_mask] = 0.5
+ return topsis_score
else:
raise ValueError(
f"Invalid label metric {metric!r}. Supported: {', '.join(metrics)}"
_TRADING_MODES: Final[tuple[TradingMode, ...]] = ("spot", "margin", "futures")
def version(self) -> str:
- return "3.8.4"
+ return "3.8.5"
timeframe = "5m"