]> Piment Noir Git Repositories - freqai-strategies.git/commitdiff
fix(qav3): format number properly in log messages
authorJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 7 Aug 2025 19:05:15 +0000 (21:05 +0200)
committerJérôme Benoit <jerome.benoit@piment-noir.org>
Thu, 7 Aug 2025 19:05:15 +0000 (21:05 +0200)
Signed-off-by: Jérôme Benoit <jerome.benoit@piment-noir.org>
quickadapter/user_data/freqaimodels/QuickAdapterRegressorV3.py
quickadapter/user_data/strategies/QuickAdapterV3.py
quickadapter/user_data/strategies/Utils.py

index 41610652e76fb1197269d581e839f162c08486f5..fba0e280dc40a7e14e8316a7749d4ed254a48ae4 100644 (file)
@@ -21,6 +21,7 @@ from Utils import (
     calculate_min_extrema,
     calculate_n_extrema,
     fit_regressor,
+    format_number,
     get_optuna_callbacks,
     get_optuna_study_model_parameters,
     largest_divisor,
@@ -1009,8 +1010,14 @@ class QuickAdapterRegressorV3(BaseRegressionModel):
             f"Optuna {pair} {namespace} {objective_type} objective done{metric_log_msg} ({time_spent:.2f} secs)"
         )
         for key, value in study_best_results.items():
+            if isinstance(value, list):
+                formatted_value = (
+                    f"[{', '.join([format_number(item) for item in value])}]"
+                )
+            elif isinstance(value, (int, float)):
+                formatted_value = format_number(value)
             logger.info(
-                f"Optuna {pair} {namespace} {objective_type} objective hyperopt | {key:>20s} : {value}"
+                f"Optuna {pair} {namespace} {objective_type} objective hyperopt | {key:>20s} : {formatted_value}"
             )
         if not self.optuna_params_valid(pair, namespace, study):
             logger.warning(
index 29b07aa276318741729a1fac8844205569cb326d..09d6b8c6a592aa0c1017581337e2fed22a07cd23 100644 (file)
@@ -23,6 +23,7 @@ from Utils import (
     calculate_n_extrema,
     calculate_quantile,
     ewo,
+    format_number,
     get_distance,
     get_zl_ma_fn,
     non_zero_diff,
@@ -63,7 +64,7 @@ class QuickAdapterV3(IStrategy):
     INTERFACE_VERSION = 3
 
     def version(self) -> str:
-        return "3.3.142"
+        return "3.3.143"
 
     timeframe = "5m"
 
@@ -932,7 +933,7 @@ class QuickAdapterV3(IStrategy):
                 current_time=current_time,
                 callback=lambda: logger.info(
                     f"Trade {trade.trade_direction} {trade.pair} stage {trade_exit_stage} | "
-                    f"Take Profit: {trade_take_profit_price:.4f}, Rate: {current_rate:.4f}"
+                    f"Take Profit: {format_number(trade_take_profit_price)}, Rate: {format_number(current_rate)}"
                 ),
             )
         if trade_partial_exit:
@@ -1177,7 +1178,7 @@ class QuickAdapterV3(IStrategy):
                 current_time=current_time,
                 callback=lambda: logger.info(
                     f"Trade {trade.trade_direction} {trade.pair} stage {trade_exit_stage} | "
-                    f"Take Profit: {trade_take_profit_price:.4f}, Rate: {current_rate:.4f} | "
+                    f"Take Profit: {format_number(trade_take_profit_price)}, Rate: {format_number(current_rate)} | "
                     f"Spiking: {trade_recent_pnl_spiking} "
                     f"(V:{trade_recent_pnl_velocity:.5f} S:{trade_recent_pnl_velocity_std:.5f}, "
                     f"A:{trade_recent_pnl_acceleration:.5f} S:{trade_recent_pnl_acceleration_std:.5f}) | "
@@ -1223,7 +1224,7 @@ class QuickAdapterV3(IStrategy):
         ):
             return True
         logger.info(
-            f"User denied {side} entry for {pair}: rate {rate} did not break threshold {current_threshold}"
+            f"User denied {side} entry for {pair}: rate {format_number(rate)} did not break threshold {format_number(current_threshold)}"
         )
         return False
 
index 88d000e59cdfad033f6f03d012345bc4115f8d7c..7b8fc6349db8b3e8dbb315c0dbc368cb1ff3f0d3 100644 (file)
@@ -112,6 +112,39 @@ def smooth_extrema(
     )
 
 
+def format_number(value: int | float, significant_digits: int = 4) -> str:
+    if not isinstance(value, (int, float)):
+        return str(value)
+
+    if np.isinf(value):
+        return "+∞" if value > 0 else "-∞"
+    if np.isnan(value):
+        return "NaN"
+
+    if value == int(value):
+        return str(int(value))
+
+    abs_value = abs(value)
+
+    if abs_value >= 1.0:
+        return f"{value:.{significant_digits}f}"
+
+    value_str = f"{abs_value:.18f}"
+    first_digit_pos = -1
+    for i, char in enumerate(value_str):
+        if char > "0" and char <= "9":
+            first_digit_pos = i
+            break
+
+    if first_digit_pos == -1:
+        return f"{value:.{significant_digits}f}"
+
+    leading_zeros = first_digit_pos - 2
+    required_precision = leading_zeros + significant_digits
+
+    return f"{value:.{required_precision}f}"
+
+
 @lru_cache(maxsize=128)
 def calculate_min_extrema(
     size: int, fit_live_predictions_candles: int, min_extrema: int = 4