Switch to overnight_recovery_top10, rebalanced every 10 sessions
Under quant-trading's PIT research engine (S&P 500 members 2006-2026, 10 bp), overnight_recovery_top10 filled at the next close beat the daily UpCap+MomGap by 10.5%/yr (paired Newey-West t 2.44) at 3x instead of 29x yearly turnover. UpCap+MomGap was a CN champion there, and its daily variant was never picked for the US book. - strategy: overnight-return momentum (12m skip 1m) + distance from the 126-day low, ported from strategies/robust_momentum.py; top 10 equal weight, a held name stays while ranked within 30. Scores and picks match RobustMomentumStrategy on the IB bars (25 rebalances, 0 diffs). - rebalance: every 10 sessions from strategy.anchor (2026-09-29), on completed sessions through yesterday's close, MOC at today's close; other sessions do nothing and weights drift. - backtest trades only on rebalance sessions, like the live loop. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
28
tests/test_strategy.py
Normal file
28
tests/test_strategy.py
Normal file
@@ -0,0 +1,28 @@
|
||||
import datetime as dt
|
||||
|
||||
import pandas as pd
|
||||
import pytest
|
||||
|
||||
from ibkr_quant.strategy import select_with_buffer, sessions_until_rebalance
|
||||
|
||||
SCORE = pd.Series({"A": 0.9, "B": 0.8, "C": 0.7, "D": 0.6, "E": 0.5, "F": None})
|
||||
|
||||
|
||||
def test_picks_top_n_equal_weight_without_holdings():
|
||||
assert select_with_buffer(SCORE, set(), top_n=2, buffer=0.0) == {"A": 0.5, "B": 0.5}
|
||||
|
||||
|
||||
def test_keeps_held_names_within_the_buffer_and_fills_from_the_top():
|
||||
# top_n * (1 + buffer) = 4: D (rank 3) stays, E (rank 4) and unscored F go.
|
||||
assert select_with_buffer(SCORE, {"D", "E", "F"}, top_n=2, buffer=1.0) == {"D": 0.5, "A": 0.5}
|
||||
|
||||
|
||||
def test_refuses_too_few_scored_names():
|
||||
with pytest.raises(ValueError, match="only 5 names"):
|
||||
select_with_buffer(SCORE, set(), top_n=6, buffer=0.0)
|
||||
|
||||
|
||||
def test_rebalances_on_the_anchor_session_and_every_n_after():
|
||||
sessions = pd.bdate_range("2026-09-24", periods=12) # anchor 09-29 is the 4th
|
||||
wait = [sessions_until_rebalance(sessions[: i + 1], dt.date(2026, 9, 29), 5) for i in range(len(sessions))]
|
||||
assert wait == [None, None, None, 0, 4, 3, 2, 1, 0, 4, 3, 2]
|
||||
Reference in New Issue
Block a user