feat: train forecasts on trade outcomes

This commit is contained in:
Курнат Андрей
2026-07-14 07:49:32 +03:00
parent 668e606ee2
commit 7186acb9a1
18 changed files with 867 additions and 94 deletions
+46 -1
View File
@@ -7,12 +7,20 @@ from tools.calibrate_torch_thresholds import (
ForecastRecord,
_average_selected_predictions,
_apply_platt_calibration,
_build_torch_model,
_choose_recommendation,
_full_backtest,
_fit_platt_calibration,
_record_event_target,
_entry_validation_skill,
)
from tools.train_torch_recurrent_forecaster import _ensemble_candidate
from tools.train_torch_recurrent_forecaster import (
OUTPUT_LAYOUT,
RecurrentReturnModel,
_ensemble_candidate,
_export_head_state,
_export_recurrent_state,
)
def _result(*, trades: int, average: float, total: float, profit_factor: float) -> CalibrationResult:
@@ -85,6 +93,13 @@ def test_platt_calibration_learns_probability_direction_from_train_records() ->
assert calibrated[0].probability_up < calibrated[1].probability_up
def test_barrier_event_target_takes_precedence_over_terminal_profit() -> None:
record = _record(1, 0.8, 3.0)
record.take_profit_first = False
assert _record_event_target(record) == 0.0
def test_entry_quality_never_falls_back_to_holdout_skill() -> None:
entry = {"validation_skill": 0.12, "skill": 0.99, "holdout_skill": 0.99}
@@ -107,6 +122,36 @@ def test_batched_ensemble_averages_decoded_predictions() -> None:
}
def test_calibrator_loads_multitask_head() -> None:
model = RecurrentReturnModel(
architecture="gru",
input_size=2,
hidden_size=4,
num_layers=1,
dropout=0.0,
output_size=len(OUTPUT_LAYOUT),
attention_pooling=False,
context_norm=False,
multitask_head=True,
head_hidden_size=6,
)
entry = {
"input_size": 2,
"hidden_size": 4,
"num_layers": 1,
"output_size": len(OUTPUT_LAYOUT),
"multitask_head": True,
"head_hidden_size": 6,
"state_dict": _export_recurrent_state(model),
**_export_head_state(model),
}
loaded = _build_torch_model(entry, "torch_gru")
assert loaded is not None
assert loaded.multitask_head is True
def test_multi_seed_export_does_not_duplicate_first_member_weights() -> None:
members = [
{