"""Synthetic demonstration; no live market data or performance claim.
Validated with scikit-learn 1.7.2. Install: pip install scikit-learn==1.7.2
"""
import numpy as np
import sklearn
from sklearn.calibration import CalibratedClassifierCV, calibration_curve
from sklearn.datasets import make_classification
from sklearn.frozen import FrozenEstimator
from sklearn.metrics import brier_score_loss, log_loss
from sklearn.naive_bayes import GaussianNB

# Independent synthetic records, not a validation of chronological market data.
X, y = make_classification(n_samples=6000, n_features=8, n_informative=4,
                           n_redundant=2, random_state=31)
train, calibration, evaluation = np.split(np.arange(len(y)), 3)
assert not (set(train) & set(calibration) or set(train) & set(evaluation)
            or set(calibration) & set(evaluation))
base = GaussianNB().fit(X[train], y[train])
assert list(base.classes_) == [0, 1]
models = {"raw": base}
for method in ("sigmoid", "isotonic"):
    models[method] = CalibratedClassifierCV(
        FrozenEstimator(base), method=method, ensemble=False
    ).fit(X[calibration], y[calibration])

print("scikit-learn", sklearn.__version__)
print("method       Brier   log loss   evaluation records")
for name, model in models.items():
    p = model.predict_proba(X[evaluation])[:, 1]
    assert np.isfinite(p).all() and ((p >= 0) & (p <= 1)).all()
    print(f"{name:10s} {brier_score_loss(y[evaluation], p):.4f} "
          f"{log_loss(y[evaluation], p, labels=[0, 1]):.4f}   {len(p)}")
    observed, mean_probability = calibration_curve(
        y[evaluation], p, n_bins=10, strategy="uniform"
    )
    print("  occupied-bin means / positive frequencies:",
          list(zip(mean_probability.round(3), observed.round(3))))
# Inspect both scores and curves. No assertion that calibration always improves.
