[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [6388] Assert certain invariants
From: |
Greg Chicares |
Subject: |
[lmi-commits] [6388] Assert certain invariants |
Date: |
Fri, 06 Nov 2015 19:11:25 +0000 |
Revision: 6388
http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=6388
Author: chicares
Date: 2015-11-06 19:11:24 +0000 (Fri, 06 Nov 2015)
Log Message:
-----------
Assert certain invariants
Modified Paths:
--------------
lmi/trunk/input_harmonization.cpp
Modified: lmi/trunk/input_harmonization.cpp
===================================================================
--- lmi/trunk/input_harmonization.cpp 2015-11-04 10:16:23 UTC (rev 6387)
+++ lmi/trunk/input_harmonization.cpp 2015-11-06 19:11:24 UTC (rev 6388)
@@ -31,6 +31,7 @@
#include "actuarial_table.hpp" // e_reenter_upon_rate_reset
#include "alert.hpp"
#include "calendar_date.hpp"
+#include "contains.hpp"
#include "database.hpp"
#include "dbnames.hpp"
#include "global_settings.hpp"
@@ -1071,10 +1072,50 @@
SolveEndTime = issue_age() + SolveEndYear .value();
}
-/// Determine number of full years and months since issue.
+/// Set inforce durations (full years and months) from calendar dates.
///
-/// If the contract has been in force for a nonzero period less than
-/// one full month, then InforceYear and InforceMonth are both zero.
+/// For illustrations, time has a monthly pulse: a year consists only
+/// of the twelve discrete instants on which monthiversary processing
+/// occurs. The intervals between pulses affect interest crediting
+/// only. To match spreadsheets or other illustration systems, lmi
+/// treats the intervals as though they were of equal length; but its
+/// AccountValue::daily_interest_accounting option uses exact calendar
+/// lengths instead, which more closely models the typical behavior of
+/// admin systems.
+///
+/// At each pulse, the monthly deduction is taken, and interest to the
+/// next monthiversary is credited, as one combined atomic operation.
+/// Therefore, any inforce data must be given as of a monthiversary
+/// date, after interest has been credited for the month just ending,
+/// and immediately before a monthiversary deduction. (Admin systems
+/// might reckon this point to occur one second after midnight on a
+/// monthiversary date, or one second before midnight on the preceding
+/// day, but the InforceAsOfDate they provide to lmi must follow lmi's
+/// reckoning: it must be the monthiversary date.)
+///
+/// Preconditions: Neither EffectiveDate nor LastMaterialChangeDate
+/// can be later than InforceAsOfDate; years_and_months_since() checks
+/// these preconditions, and throws if either is violated.
+///
+/// [The following experimental precondition is asserted, but can be
+/// bypassed in case surprises appear in production.]
+/// Precondition: InforceAsOfDate is an exact monthiversary date.
+/// (LastMaterialChangeDate need not be: material changes may be made
+/// at any time.)
+///
+/// Postcondition: Inforce illustrations are not allowed before the
+/// first monthiversary date after the issue date. This follows from
+/// the explanation above. On the issue date, the policy is not yet in
+/// force; then InforceAsOfDate must equal EffectiveDate, and both the
+/// inforce year and the inforce month must equal zero. Otherwise, the
+/// policy is in force; then InforceAsOfDate can't equal EffectiveDate
+/// because of the quantization of illustration time, so inforce year
+/// and inforce month cannot both equal zero. An exception is thrown
+/// if this postcondition is violated because new business and inforce
+/// illustrations differ categorically: they regulated differently,
+/// and they're calculated differently (e.g., input inforce values
+/// must be taken into account for inforce, but disregarded (or
+/// asserted to be zero) for new business).
void Input::set_inforce_durations_from_dates()
{
@@ -1091,5 +1132,47 @@
);
InforceContractYear = ym1.first;
InforceContractMonth = ym1.second;
+
+ calendar_date expected = add_years_and_months
+ (EffectiveDate.value()
+ ,InforceYear .value()
+ ,InforceMonth .value()
+ ,true
+ );
+ // After testing in production, either remove the "pyx" bypass, or
+ // redesign this. Replacing fatal_error() with warning() would cause
+ // multiple messageboxes, which is unavoidable if the diagnostic is
+ // to be given when GUI input enters an invalid state, and also
+ // whenever an illustration is about to be produced.
+ if(expected != InforceAsOfDate.value() &&
!contains(global_settings::instance().pyx(), "off_monthiversary"))
+ {
+ fatal_error()
+ << "Input inforce-as-of date, "
+ << InforceAsOfDate.value().str()
+ << ", should be an exact monthiversary date."
+ << "\nIt would be interpreted as "
+ << expected.str()
+ << ", which is "
+ << InforceYear
+ << " full years and "
+ << InforceMonth
+ << " full months"
+ << "\nafter the "
+ << EffectiveDate.value().str()
+ << " effective date."
+ << LMI_FLUSH
+ ;
+ }
+
+ if
+ ( EffectiveDate.value() != InforceAsOfDate.value()
+ && (0 == InforceYear && 0 == InforceMonth)
+ )
+ {
+ fatal_error()
+ << "Inforce illustrations not permitted during month of issue."
+ << LMI_FLUSH
+ ;
+ }
}
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi-commits] [6388] Assert certain invariants,
Greg Chicares <=