Found reviewing #846.
build_dca_plan (keel/commands/dca_plan.py:437) compares spend -- a 30.4375-day average month -- against rail 14's allowance. Rail 14 (guards._monthly_buy_spend_usd) sums the UTC calendar month, and Dca.detect fires every rule on the same epoch-day boundary (ts // 86400 % cadence_days == 0), so a weekly plan buys 5 times in some months.
Concrete: the worked example (budget 500, buffer 0.1, cap 500) is approvable with spend $450.00; per-buy sum is $103.47/week. October 2026 has 5 cadence days (Oct 1, 8, 15, 22, 29), so the month totals 5 x 103.47 = $517.35 > $500 and rail 14 vetoes the fifth week's last buy. The default 10% buffer does not absorb it (35/30.4375 = +15%).
Fix: check (or at least warn on) the worst calendar month, e.g. sum(per_buy) * ceil(31 / cadence_days) against the cap, with a test pinning the 5-buy case.
🤖 Generated with Claude Code
Found reviewing #846.
build_dca_plan(keel/commands/dca_plan.py:437) comparesspend-- a 30.4375-day average month -- against rail 14's allowance. Rail 14 (guards._monthly_buy_spend_usd) sums the UTC calendar month, andDca.detectfires every rule on the same epoch-day boundary (ts // 86400 % cadence_days == 0), so a weekly plan buys 5 times in some months.Concrete: the worked example (budget 500, buffer 0.1, cap 500) is approvable with spend $450.00; per-buy sum is $103.47/week. October 2026 has 5 cadence days (Oct 1, 8, 15, 22, 29), so the month totals 5 x 103.47 = $517.35 > $500 and rail 14 vetoes the fifth week's last buy. The default 10% buffer does not absorb it (35/30.4375 = +15%).
Fix: check (or at least warn on) the worst calendar month, e.g.
sum(per_buy) * ceil(31 / cadence_days)against the cap, with a test pinning the 5-buy case.🤖 Generated with Claude Code