lmi-commits
[Top][All Lists]
Advanced

[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;




reply via email to

[Prev in Thread] Current Thread [Next in Thread]