Skip to content

Commit 956bef3

Browse files
Fix CI: ns-Timestamp overflow in synthetic generators (285/286/287/290)
The daily/monthly synthetic tapes generated DatetimeIndexes past pandas' ns bound (2262-04-11) when tests asked for very long samples — fine under local pandas 3, but OverflowError under CI's pandas/Py3.10 build: - 285 st-patricks: end-anchor bdate_range so n_years*252 days can't overflow. - 286 valentines / 287 easter: tests used end_year=2299 -> 2260 (still ~360y). - 290 september: large-sample null tests anchored at start_year=1700 (n_years=500 -> 1700-2200) instead of overflowing from the 1950 default. Verified: an AST-driven detector confirms every synthetic index now stays in ns bounds, and all 49 new suites pass with caches masked (CI-equivalent).
1 parent a480b85 commit 956bef3

7 files changed

Lines changed: 16 additions & 11 deletions

File tree

studies/285-st-patricks-day/st_patricks_day/data.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,12 @@ def synthetic_daily(
141141
is_march`` indexed by date.
142142
"""
143143
rng = np.random.default_rng(seed)
144-
idx = pd.bdate_range(start=start, periods=n_years * 252)
144+
# End-anchor the synthetic span so a large n_years can't push the final date
145+
# past pandas' ns Timestamp bound (2262-04-11) and OverflowError under CI's
146+
# pandas build. The calendar structure (one St Patrick's session per year) is
147+
# unaffected by which century the window sits in; `start` is kept for API compat.
148+
_ = start
149+
idx = pd.bdate_range(end="2260-12-31", periods=n_years * 252)
145150
n = len(idx)
146151
daily_mu = annual_drift / 252.0
147152
daily_sig = annual_vol / np.sqrt(252.0)

studies/286-valentines-day/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ def synthetic_null():
3434
@pytest.fixture
3535
def synthetic_signal():
3636
"""A long synthetic daily frame with a strong planted Valentine premium."""
37-
df, truth = data.synthetic_daily(start_year=1900, end_year=2299, premium_bps=50.0, seed=286)
37+
df, truth = data.synthetic_daily(start_year=1900, end_year=2260, premium_bps=50.0, seed=286)
3838
return df, truth

studies/286-valentines-day/tests/test_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,15 @@ def test_synthetic_different_seeds_differ():
9191

9292
def test_synthetic_null_has_no_premium():
9393
"""On the null tape, Valentine vs non-Valentine means should be close."""
94-
df, _ = data.synthetic_daily(start_year=1900, end_year=2299, premium_bps=0.0, seed=286)
94+
df, _ = data.synthetic_daily(start_year=1900, end_year=2260, premium_bps=0.0, seed=286)
9595
val = df.loc[df["is_valentine"], "ret"].mean()
9696
non = df.loc[~df["is_valentine"], "ret"].mean()
9797
assert abs(val - non) < 0.001 # < 10 bps
9898

9999

100100
def test_synthetic_signal_creates_premium():
101101
"""A planted premium should lift the Valentine mean above the rest."""
102-
df, _ = data.synthetic_daily(start_year=1900, end_year=2299, premium_bps=100.0, seed=286)
102+
df, _ = data.synthetic_daily(start_year=1900, end_year=2260, premium_bps=100.0, seed=286)
103103
val = df.loc[df["is_valentine"], "ret"].mean()
104104
non = df.loc[~df["is_valentine"], "ret"].mean()
105105
assert val > non + 0.005 # premium clearly visible

studies/287-easter-effect/tests/conftest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,5 @@ def synthetic_null():
3434
@pytest.fixture
3535
def synthetic_signal():
3636
"""A long synthetic daily frame with a strong planted pre-holiday premium."""
37-
df, truth = data.synthetic_daily(start_year=1900, end_year=2299, premium_bps=50.0, seed=287)
37+
df, truth = data.synthetic_daily(start_year=1900, end_year=2260, premium_bps=50.0, seed=287)
3838
return df, truth

studies/287-easter-effect/tests/test_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,15 +122,15 @@ def test_synthetic_different_seeds_differ():
122122

123123
def test_synthetic_null_has_no_premium():
124124
"""On the null tape, pre vs non-pre means should be close."""
125-
df, _ = data.synthetic_daily(start_year=1900, end_year=2299, premium_bps=0.0, seed=287)
125+
df, _ = data.synthetic_daily(start_year=1900, end_year=2260, premium_bps=0.0, seed=287)
126126
pre = df.loc[df["is_pre"], "ret"].mean()
127127
non = df.loc[~df["is_pre"], "ret"].mean()
128128
assert abs(pre - non) < 0.001 # < 10 bps
129129

130130

131131
def test_synthetic_signal_creates_premium():
132132
"""A planted premium should lift the pre-holiday mean above the rest."""
133-
df, _ = data.synthetic_daily(start_year=1900, end_year=2299, premium_bps=100.0, seed=287)
133+
df, _ = data.synthetic_daily(start_year=1900, end_year=2260, premium_bps=100.0, seed=287)
134134
pre = df.loc[df["is_pre"], "ret"].mean()
135135
non = df.loc[~df["is_pre"], "ret"].mean()
136136
assert pre > non + 0.005 # premium clearly visible

studies/290-september-effect/tests/test_data.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,15 +51,15 @@ def test_synthetic_different_seeds_differ():
5151
# ---------------------------------------------------------------------------
5252
def test_null_has_no_september_drag():
5353
"""On the null tape with large n, September mean ~ other-month mean."""
54-
df, _ = data.synthetic_monthly(n_years=2000, sep_bps=0.0, seed=290)
54+
df, _ = data.synthetic_monthly(n_years=500, start_year=1700, sep_bps=0.0, seed=290)
5555
sep = df.loc[df["month"] == 9, "ret"].mean()
5656
oth = df.loc[df["month"] != 9, "ret"].mean()
5757
assert abs(sep - oth) < 0.003 # < 30 bps with n=2000 Septembers
5858

5959

6060
def test_planted_drag_creates_gap():
6161
"""A negative planted drag makes September meaningfully lower."""
62-
df, _ = data.synthetic_monthly(n_years=500, sep_bps=-1000.0, seed=290)
62+
df, _ = data.synthetic_monthly(n_years=500, start_year=1700, sep_bps=-1000.0, seed=290)
6363
sep = df.loc[df["month"] == 9, "ret"].mean()
6464
oth = df.loc[df["month"] != 9, "ret"].mean()
6565
assert sep < oth - 0.05 # planted -1000 bps/mo dominates the noise

studies/290-september-effect/tests/test_strategy.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ def test_permutation_deterministic(synthetic_null):
7878

7979
def test_null_has_no_signal():
8080
"""On the null tape (large n) HAC t and gap should be near zero."""
81-
df, _ = data.synthetic_monthly(n_years=1500, sep_bps=0.0, seed=290)
81+
df, _ = data.synthetic_monthly(n_years=500, start_year=1700, sep_bps=0.0, seed=290)
8282
s = st.september_stats(df, n_permutations=300, seed=290)
8383
assert abs(s["hac_t_gap"]) < 2.0
8484
assert abs(s["gap_pct"]) < 0.3
@@ -120,7 +120,7 @@ def test_backtest_keys_and_cost_ordering(synthetic_null):
120120

121121
def test_backtest_drag_helps_avoidance():
122122
"""If September really drags, avoiding it should beat buy-and-hold gross."""
123-
df, _ = data.synthetic_monthly(n_years=300, sep_bps=-1000.0, seed=290)
123+
df, _ = data.synthetic_monthly(n_years=500, start_year=1700, sep_bps=-1000.0, seed=290)
124124
bt = st.avoid_september_backtest(df, one_way_bps=0.0)
125125
assert bt["strat_gross_ann_pct"] > bt["buyhold_ann_pct"]
126126

0 commit comments

Comments
 (0)