[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[lmi-commits] [6421] Support a one-of-a-kind minimum initial premium
From: |
Greg Chicares |
Subject: |
[lmi-commits] [6421] Support a one-of-a-kind minimum initial premium |
Date: |
Sun, 22 Nov 2015 03:21:49 +0000 |
Revision: 6421
http://svn.sv.gnu.org/viewvc/?view=rev&root=lmi&revision=6421
Author: chicares
Date: 2015-11-22 03:21:48 +0000 (Sun, 22 Nov 2015)
Log Message:
-----------
Support a one-of-a-kind minimum initial premium
Modified Paths:
--------------
lmi/trunk/ChangeLog
lmi/trunk/account_value.hpp
lmi/trunk/ihs_acctval.cpp
lmi/trunk/ihs_avmly.cpp
Modified: lmi/trunk/ChangeLog
===================================================================
--- lmi/trunk/ChangeLog 2015-11-22 03:20:46 UTC (rev 6420)
+++ lmi/trunk/ChangeLog 2015-11-22 03:21:48 UTC (rev 6421)
@@ -37574,3 +37574,37 @@
dbnames.xpp
Add a database entity for minimum initial premium.
+20151120T1843Z <address@hidden> [461]
+
+ ihs_avmly.cpp
+ ihs_irc7702.cpp
+ ihs_irc7702.hpp
+Eliminate an unused function argument.
+
+20151120T1855Z <address@hidden> [460]
+
+ ihs_avmly.cpp
+Improve documentation.
+
+20151120T2110Z <address@hidden> [459]
+
+ ihs_avmly.cpp
+Refactor for simplicity and extensibility.
+
+20151120T2111Z <address@hidden> [459]
+
+ ihs_acctval.cpp
+Add more assertions.
+
+20151122T0320Z <address@hidden> [459]
+
+ dbnames.xpp
+Let 1 signify 1.
+
+20151122T0321Z <address@hidden> [459]
+
+ account_value.hpp
+ ihs_acctval.cpp
+ ihs_avmly.cpp
+Support a one-of-a-kind minimum initial premium.
+
Modified: lmi/trunk/account_value.hpp
===================================================================
--- lmi/trunk/account_value.hpp 2015-11-22 03:20:46 UTC (rev 6420)
+++ lmi/trunk/account_value.hpp 2015-11-22 03:21:48 UTC (rev 6421)
@@ -288,6 +288,8 @@
void ReduceSurrChg (int year, double partial_surrchg);
double SurrChg ();
+ double MinInitDumpin() const;
+ double ModalMinInitPremShortfall() const;
double SuppositiveModalPremium
(bool with_adb
,bool with_wp
@@ -369,6 +371,8 @@
double Internal1035Amount;
double Dumpin;
+ double InitAnnPlannedPrem_;
+
double MlyNoLapsePrem;
double CumNoLapsePrem;
bool NoLapseActive;
Modified: lmi/trunk/ihs_acctval.cpp
===================================================================
--- lmi/trunk/ihs_acctval.cpp 2015-11-22 03:20:46 UTC (rev 6420)
+++ lmi/trunk/ihs_acctval.cpp 2015-11-22 03:21:48 UTC (rev 6421)
@@ -662,6 +662,7 @@
YearlyTaxBasis.assign(BasicValues::GetLength(), 0.0);
MlyNoLapsePrem = 0.0;
CumNoLapsePrem = InforceCumNoLapsePrem;
+ InitAnnPlannedPrem_ = 0.0;
// Initialize all elements of this vector to 'false'. Then, when
// the no-lapse criteria fail to be met, future values are right.
@@ -1042,6 +1043,8 @@
// Four premiums are calculated, for base and "supplemental"
// coverage combined:
// without riders; with ADB only; with WP only; with ADB and WP
+ // All reflect MinInitDumpin() (which may be zero).
+ //
// This is intended for presale use only; for inforce cells, these
// premiums retain their default initial values of zero. There
// seems to be no compelling argument for further restrictions
@@ -1061,6 +1064,86 @@
// TODO ?? Perform specamt strategy here?
}
+/// Minimum initial extra premium--zero for most products.
+///
+/// Motivation: to help ensure VUL suitability for products whose
+/// minimum premium alone would generate little if any account value.
+///
+/// Custom MinInitPremType #1: first-year payments must be at least
+/// the pay-as-you-go minimum premium (calculated elsewhere) plus half
+/// the target premium (calculated here, and rounded according to its
+/// own rule). This extra amount is defined only for new business; for
+/// inforce, it is impracticable to calculate because the target may
+/// have changed, and suitability is determined at issue anyway.
+///
+/// Because the result is twelve times a rounded value, it can be
+/// modalized without further rounding.
+
+double AccountValue::MinInitDumpin() const
+{
+ if
+ ( 0 == Year
+ && 1 == Database_->Query(DB_MinInitPremType)
+ && yare_input_.EffectiveDate == yare_input_.InforceAsOfDate
+ )
+ {
+ double const target = InvariantValues().InitTgtPrem;
+ return 12.0 * round_min_init_premium()(target / 24.0);
+ }
+ else
+ {
+ return 0.0;
+ }
+}
+
+/// Required modal increment to initial planned premium.
+///
+/// If the minimum is not otherwise satisfied, then employee payments
+/// must be increased to fulfill it.
+///
+/// First-year payments from all sources count toward satisfying the
+/// minimum, including dumpins and 1035 proceeds--which are amodal by
+/// their nature. This function is designed to support a product whose
+/// minimum premium reflects only the er mode; yet lmi permits ee and
+/// er modes to differ, so it is necessary to compare the first-year
+/// minimum to the first year's total planned premium, including any
+/// dumpin and 1035 exchange, and modalize any shortfall. Because 1035
+/// and dumpin amounts are arbitrary, modalization could yield a value
+/// in fractional cents; therefore, the result must be rounded up.
+///
+/// Alternative not pursued: The shortfall could be calculated on each
+/// payment date, taking into account the annual incidence of dumpins
+/// and 1035 exchanges. Thus, if the shortfall before a $40 dumpin is
+/// $100, and the ee pays quarterly, an increase of {0, 10, 25, 25}
+/// rather than a level $15 could be calculated. No strong rationale
+/// was found for this exquisite refinement.
+///
+/// Planned payments might be reduced to the guideline or non-MEC
+/// limit, in which case the minimum is deemed to be satisfied. This
+/// case should not arise with the contemplated product, whose minimum
+/// is designed to be lower than those limits.
+
+double AccountValue::ModalMinInitPremShortfall() const
+{
+ if
+ ( 0 == Year
+ && 1 == Database_->Query(DB_MinInitPremType)
+ && yare_input_.EffectiveDate == yare_input_.InforceAsOfDate
+ )
+ {
+ mcenum_mode const ee_mode = InvariantValues().EeMode[0].value();
+ mcenum_mode const er_mode = InvariantValues().ErMode[0].value();
+ double const modal_min_prem = InvariantValues().ModalMinimumPremium[0];
+ double const required = MinInitDumpin() + modal_min_prem * er_mode;
+ double const shortfall = std::max(0.0, required - InitAnnPlannedPrem_);
+ return round_min_premium()(shortfall / ee_mode);
+ }
+ else
+ {
+ return 0.0;
+ }
+}
+
double AccountValue::SuppositiveModalPremium
(bool with_adb
,bool with_wp
@@ -1090,6 +1173,14 @@
/// user might reasonably wish to show the effect of other riders; if
/// assertions as to input are to be made at all, then they should be
/// made in the function that creates the group premium quote report.
+///
+/// Consistent with that purpose, deem the modal minimum premium to be
+/// the planned premium, and add modalized MinInitDumpin() for custom
+/// MinInitPremType #1. As a consequence, illustrations may differ
+/// from group premium quotes: for example, an illustration with a
+/// sufficiently large 1035 rollover requires no additional payment,
+/// but a group premium quote generated from the same input file
+/// ignores the 1035 exchange and always reflects MinInitDumpin().
double AccountValue::SuppositiveModalPremium
(int year
@@ -1132,7 +1223,9 @@
LMI_ASSERT(z == InvariantValues().ModalMinimumPremium[0]);
}
- return z;
+ // The quotient needn't be rounded because MinInitDumpin() is a
+ // multiple of twelve.
+ return z + MinInitDumpin() / mode;
}
//============================================================================
Modified: lmi/trunk/ihs_avmly.cpp
===================================================================
--- lmi/trunk/ihs_avmly.cpp 2015-11-22 03:20:46 UTC (rev 6420)
+++ lmi/trunk/ihs_avmly.cpp 2015-11-22 03:21:48 UTC (rev 6421)
@@ -1272,11 +1272,41 @@
HOPEFULLY(materially_equal(GrossPmts[Month], EeGrossPmts[Month] +
ErGrossPmts[Month]));
HOPEFULLY(GrossPmts[Month] < 1.0e100);
+ // On the issue date (which is always a modal payment date), store
+ // annualized planned premium, including dumpin and 1035 proceeds,
+ // and reflecting the payment strategies just applied (and premium
+ // solves, on the final iteration). Of course, any planned premium
+ // might be reduced to the guideline or non-MEC limit.
if(0 == Year && 0 == Month)
{
+ InitAnnPlannedPrem_ =
+ Dumpin
+ + External1035Amount
+ + Internal1035Amount
+ + ee_mode * eepmt
+ + er_mode * erpmt
+ ;
+ }
+
+ if(0 == Year && ee_pay_this_month && 1 ==
Database_->Query(DB_MinInitPremType))
+ {
+ double z = ModalMinInitPremShortfall();
// Illustration-reg guaranteed premium ignores GPT limit.
if(!SolvingForGuarPremium)
{
+ Irc7702_->ProcessGptPmt(Year, z);
+ }
+ EeGrossPmts[Month] += z;
+ GrossPmts [Month] += z;
+ }
+
+ HOPEFULLY(materially_equal(GrossPmts[Month], EeGrossPmts[Month] +
ErGrossPmts[Month]));
+
+ if(0 == Year && 0 == Month)
+ {
+ // Illustration-reg guaranteed premium ignores GPT limit.
+ if(!SolvingForGuarPremium)
+ {
Irc7702_->ProcessGptPmt(Year, Dumpin);
}
EeGrossPmts[Month] += Dumpin;
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [lmi-commits] [6421] Support a one-of-a-kind minimum initial premium,
Greg Chicares <=