calculate_n_extrema,
fit_regressor,
format_number,
+ get_min_max_label_period_candles,
get_optuna_callbacks,
get_optuna_study_model_parameters,
- largest_divisor,
- round_to_nearest_int,
soft_extremum,
zigzag,
)
https://github.com/sponsors/robcaulk
"""
- version = "3.7.111"
+ version = "3.7.112"
@cached_property
def _optuna_config(self) -> dict[str, Any]:
if np.any(np_weights < 0):
raise ValueError("label_weights values must be non-negative")
label_weights_sum = np.sum(np_weights)
- if np.isclose(label_weights_sum, 0):
+ if np.isclose(label_weights_sum, 0.0):
raise ValueError("label_weights sum cannot be zero")
np_weights = np_weights / label_weights_sum
knn_kwargs = {}
finite_max_val = np.max(finite_col)
finite_range_val = finite_max_val - finite_min_val
- if np.isclose(finite_range_val, 0):
+ if np.isclose(finite_range_val, 0.0):
if np.any(is_pos_inf_mask) and np.any(is_neg_inf_mask):
normalized_matrix[is_finite_mask, i] = 0.5
elif np.any(is_pos_inf_mask):
fit_live_predictions_candles: int,
candles_step: int,
) -> tuple[float, int]:
- fit_live_predictions_candles_largest_divisor = largest_divisor(
- fit_live_predictions_candles, candles_step
- )
- if fit_live_predictions_candles_largest_divisor is None:
- raise ValueError(
- f"Could not find a suitable largest divisor for {fit_live_predictions_candles} with step {candles_step}, please change your fit_live_predictions_candles or candles_step parameters"
- )
- min_label_period_candles: int = round_to_nearest_int(
- max(
- fit_live_predictions_candles
- // fit_live_predictions_candles_largest_divisor,
- candles_step,
- 12,
- ),
- candles_step,
- )
- max_label_period_candles: int = round_to_nearest_int(
- max(fit_live_predictions_candles // 24, min_label_period_candles, 22),
- candles_step,
+ min_label_period_candles, max_label_period_candles, candles_step = (
+ get_min_max_label_period_candles(candles_step)
)
+
label_period_candles = trial.suggest_int(
"label_period_candles",
min_label_period_candles,
max_label_period_candles,
step=candles_step,
)
- label_natr_ratio = trial.suggest_float("label_natr_ratio", 2.0, 44.0, step=0.01)
+ label_natr_ratio = trial.suggest_float("label_natr_ratio", 2.0, 48.0, step=0.01)
label_period_cycles = fit_live_predictions_candles / label_period_candles
df = df.iloc[-(max(2, int(label_period_cycles)) * label_period_candles) :]
np_array = series.to_numpy()
if np_array.size == 0:
return np.nan
- if np.isclose(alpha, 0):
+ if np.isclose(alpha, 0.0):
return np.mean(np_array)
scaled_np_array = alpha * np_array
max_scaled_np_array = np.max(scaled_np_array)
return numerator / denominator
+@lru_cache(maxsize=8)
+def get_min_max_label_period_candles(
+ candles_step: int,
+ min_label_period_candles: int = 8,
+ max_label_period_candles: int = 48,
+) -> tuple[int, int, int]:
+ if min_label_period_candles > max_label_period_candles:
+ min_label_period_candles, max_label_period_candles = (
+ max_label_period_candles,
+ min_label_period_candles,
+ )
+
+ if candles_step <= (max_label_period_candles - min_label_period_candles):
+ low = ceil_to_step(min_label_period_candles, candles_step)
+ high = floor_to_step(max_label_period_candles, candles_step)
+ if low > high:
+ low, high, candles_step = (
+ min_label_period_candles,
+ max_label_period_candles,
+ 1,
+ )
+ else:
+ low, high, candles_step = min_label_period_candles, max_label_period_candles, 1
+
+ return low, high, candles_step
+
+
@lru_cache(maxsize=128)
-def round_to_nearest_int(value: float, step: int) -> int:
+def round_to_step(value: float | int, step: int) -> int:
"""
Round a value to the nearest multiple of a given step.
:param value: The value to round.
- :param step: The step size to round to (must be non-zero).
+ :param step: The step size to round to (must be a positive integer).
:return: The rounded value.
- :raises ValueError: If step is zero.
+ :raises ValueError: If step is not a positive integer or value is not finite.
"""
+ if not np.isfinite(value):
+ raise ValueError("value must be finite")
+ if not isinstance(step, int) or step <= 0:
+ raise ValueError("step must be a positive integer")
+ return int(round(float(value) / step) * step)
+
+
+@lru_cache(maxsize=128)
+def ceil_to_step(value: float | int, step: int) -> int:
+ if not isinstance(step, int) or step <= 0:
+ raise ValueError("step must be a positive integer")
+ if isinstance(value, (int, np.integer)):
+ return int(-(-int(value) // step) * step)
+ if not np.isfinite(value):
+ raise ValueError("value must be finite")
+ return int(math.ceil(float(value) / step) * step)
+
+
+@lru_cache(maxsize=128)
+def floor_to_step(value: float | int, step: int) -> int:
if not isinstance(step, int) or step <= 0:
raise ValueError("step must be a positive integer")
- return int(round(value / step) * step)
+ if isinstance(value, (int, np.integer)):
+ return int((int(value) // step) * step)
+ if not np.isfinite(value):
+ raise ValueError("value must be finite")
+ return int(math.floor(float(value) / step) * step)