diff --git a/src/ml4t/backtest/config.py b/src/ml4t/backtest/config.py index e7007b5..6d5f6c1 100644 --- a/src/ml4t/backtest/config.py +++ b/src/ml4t/backtest/config.py @@ -312,11 +312,9 @@ def _margin_schedule_to_dict( def _serialize_invalid_margin_schedule_value(value: Any) -> Any: - try: - values = list(value) - except TypeError: + if not isinstance(value, list | tuple): return _serialize_invalid_margin_scalar(value) - return [_serialize_invalid_margin_scalar(item) for item in values] + return [_serialize_invalid_margin_scalar(item) for item in value] def _serialize_invalid_margin_scalar(value: Any) -> Any: diff --git a/tests/test_config_wiring.py b/tests/test_config_wiring.py index 0e987d5..6289383 100644 --- a/tests/test_config_wiring.py +++ b/tests/test_config_wiring.py @@ -1020,6 +1020,26 @@ def test_invalid_margin_pct_schedule_export_does_not_raise(self): data = config.to_dict() assert data["account"]["margin_pct_schedule"] == {"ES": [0.05]} + def test_invalid_margin_pct_schedule_export_keeps_non_sequences_scalar(self): + def values(): + yield "initial" + yield "maintenance" + yield "extra" + + config = BacktestConfig( + margin_pct_schedule={ + "DICT": {"initial": 0.05, "maintenance": 0.035}, # type: ignore[dict-item] + "GEN": values(), # type: ignore[dict-item] + "STR": "im", # type: ignore[dict-item] + } + ) + + data = config.to_dict() + + assert isinstance(data["account"]["margin_pct_schedule"]["DICT"], str) + assert isinstance(data["account"]["margin_pct_schedule"]["GEN"], str) + assert data["account"]["margin_pct_schedule"]["STR"] == "im" + def test_margin_pct_schedule_float_overflow_is_reported(self, tmp_path): class OverflowFloat: def __float__(self):