Directional Metrics

Directional metrics are used to evaluate the performance of forecasting models, especially in time-series and financial contexts where the trend direction is often more important than the exact magnitude of the change.

Directional Accuracy Score

ds_utils.metrics.time_series.directional_accuracy_score(y_true: ndarray, y_pred: ndarray, baseline: ndarray | None = None, sample_weight: ndarray | None = None, handle_equal: str = 'exclude') float[source]

Calculate the directional accuracy score.

Directional accuracy (DA) measures the proportion of time steps for which the predicted direction of change matches the true direction of change, relative to a baseline.

The formula is: DA = (1/n) * Σ I(sign(y_true - baseline) == sign(y_pred - baseline))

Parameters:
  • y_true – Ground truth (correct) target values.

  • y_pred – Estimated target values.

  • baseline – Baseline values to compare against. If None, uses the previous value of y_true (time-series mode). If provided, must have the same shape as y_true.

  • sample_weight – Sample weights.

  • handle_equal – How to treat samples where y_true == baseline. - ‘exclude’: Filter out these samples (default). - ‘correct’: Count as correct if y_pred == baseline, else incorrect. - ‘incorrect’: Always count as incorrect.

Returns:

Directional accuracy score as a float.

Raises:

ValueError – If handle_equal is invalid, if shapes mismatch, or if insufficient samples are provided for time-series mode.

Time series example: >>> import numpy as np >>> y_true = np.array([100, 102, 98, 101, 99]) >>> y_pred = np.array([100.5, 103, 97, 102, 98]) >>> directional_accuracy_score(y_true, y_pred) 1.0

Custom baseline example: >>> y_true = np.array([102, 98, 101, 99, 102]) >>> baseline = np.array([100, 100, 100, 100, 100]) >>> y_pred = np.array([101, 99, 99, 101, 99]) >>> directional_accuracy_score(y_true, y_pred, baseline=baseline) 0.4

Code Example

from ds_utils.metrics.time_series import directional_accuracy_score
import numpy as np

# Directional accuracy — time series mode (uses previous value as baseline)
# true changes from baseline: +2, -4, +3, -2
# pred changes from baseline: +3, -5, +4, -3  -> all directions match
y_true = np.array([100, 102, 98, 101, 99])
y_pred = np.array([101, 103, 97, 102, 98])
da = directional_accuracy_score(y_true, y_pred)
print(f"Directional Accuracy: {da:.2%}")
Output:
Directional Accuracy: 100.00%

Directional Bias Score

ds_utils.metrics.time_series.directional_bias_score(y_true: ndarray, y_pred: ndarray, sample_weight: ndarray | None = None, handle_equal: str = 'exclude') float[source]

Calculate the directional bias score.

Directional bias (DB) measures the systematic tendency of a model to over-predict or under-predict the target values.

The formula is: DB = (n_over - n_under) / n

Parameters:
  • y_true – Ground truth (correct) target values.

  • y_pred – Estimated target values.

  • sample_weight – Sample weights.

  • handle_equal – How to treat samples where y_pred == y_true. - ‘exclude’: Filter out these samples (default). - ‘neutral’: Keep samples; they contribute 0 to the bias.

Returns:

Directional bias score as a float in [-1, 1]. 1.0 = complete over-prediction, -1.0 = complete under-prediction, 0.0 = balanced predictions.

Raises:

ValueError – If handle_equal is invalid, if shapes mismatch, or if no samples remain after filtering.

Complete over-prediction example: >>> import numpy as np >>> y_true = np.array([1.0, 2.0, 3.0, 4.0, 5.0]) >>> y_pred = np.array([1.1, 2.1, 3.1, 4.1, 5.1]) >>> directional_bias_score(y_true, y_pred) 1.0

Complete under-prediction example: >>> y_pred = np.array([0.9, 1.9, 2.9, 3.9, 4.9]) >>> directional_bias_score(y_true, y_pred) -1.0

Balanced example: >>> y_pred = np.array([1.1, 1.9, 3.1, 3.9, 5.0]) >>> directional_bias_score(y_true, y_pred) 0.0

Code Example

from ds_utils.metrics.time_series import directional_bias_score
import numpy as np

# Directional bias — detect systematic over/under-prediction
# All predictions are 0.1 above the true value
y_true = np.array([1.0, 2.0, 3.0, 4.0, 5.0])
y_pred = np.array([1.1, 2.1, 3.1, 4.1, 5.1])
bias = directional_bias_score(y_true, y_pred)
print(f"Directional Bias: {bias:.2f}")
Output:
Directional Bias: 1.00