Repository navigation
Constant-rate escalation takes the end-of-month rule - #46
Merged
Merged
Conversation
Co-Authored-By: Claude <noreply@anthropic.com>
…f_month Co-Authored-By: Claude <noreply@anthropic.com>
j-bryan
force-pushed
the
anchored-escalation
branch
from
October 13, 2026 22:04
65a5d90 to
36facc1
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Related to #38 (does not close it). Stacked on #45, in stack #51.
Constant-rate escalation can now choose the end-of-month rule. Before this, it always used the default from #45.
ConstantRateEscalation(..., end_of_month=True): new last dataclass field, so positional calls are unaffected.factor()passes it toelapsed_periods, so monthly and quarterly escalation compounds one full step at each boundary of the schedule anchored atreference_date. Yearly and daily escalation ignore it.EscalationBuilder.constant_rate(..., end_of_month=True): keyword-only, passed through to the segment's policy.IndexSeriesEscalationandCompositeEscalationdon't take the flag. Index series step on their observed dates, and a composite takes the setting from each of its segments.tests/unit/test_escalation.py):factor(add_periods(ref, k))equals(1+r)**kfor months and quarters under both settings. Apr 30 → May 31 is exactly(1+r)with the flag on and(1+r)**(1 + 1/31)with it off. Also tested: the default isTrue, year and day factors don't depend on the flag, and the builder passes it through.Behavior changes
None beyond #45.
Truewas already the effective default there; this PR only exposes the setting.Not in this PR
Callers that build a
ConstantRateEscalationinternally (stream factories, the OPEX and revenue compilers, construction) still don't expose the flag. Construction is handled in #49, and the stream factories and builder in later PRs (see the plan in #38).Testing
uv run ruff check,uv run ruff format --check,uv run mypy dcaf/, anduv run pytestpass (936 tests), and the Hypothesis properties also pass at 3,000 examples each.🤖 Generated with Claude Code