diff --git a/src/fxhnt/domain/strategies/equity_factor.py b/src/fxhnt/domain/strategies/equity_factor.py index 02e76de..b6b8e0b 100644 --- a/src/fxhnt/domain/strategies/equity_factor.py +++ b/src/fxhnt/domain/strategies/equity_factor.py @@ -29,7 +29,7 @@ def momentum_12_1_from_closes(closes: list[float]) -> float | None: return None p_then = closes[-_LOOKBACK] p_recent = closes[-_SKIP] - if p_then is None or p_then <= 0: + if p_then is None or p_then <= 0 or p_recent is None or p_recent <= 0: return None return p_recent / p_then - 1.0 diff --git a/tests/unit/test_equity_factor_helpers.py b/tests/unit/test_equity_factor_helpers.py index 9bd5d7c..1b22665 100644 --- a/tests/unit/test_equity_factor_helpers.py +++ b/tests/unit/test_equity_factor_helpers.py @@ -19,6 +19,18 @@ def test_momentum_12_1_none_when_insufficient_history(): assert momentum_12_1_from_closes(_ramp(50)) is None +def test_momentum_12_1_none_when_recent_price_nonpositive(): + closes = _ramp(300) + closes[-21] = 0.0 # the "recent" (skip) price is non-positive + assert momentum_12_1_from_closes(closes) is None + + +def test_momentum_12_1_none_when_lookback_price_nonpositive(): + closes = _ramp(300) + closes[-252] = 0.0 # the lookback base price is non-positive + assert momentum_12_1_from_closes(closes) is None + + def test_realized_vol_zero_for_constant_series(): v = realized_vol_from_closes([100.0] * 120) assert v is not None and v == 0.0