lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 72b54df 3/6: Expunge experience-rating calcul


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 72b54df 3/6: Expunge experience-rating calculations [322]
Date: Sun, 31 Jan 2021 17:27:28 -0500 (EST)

branch: master
commit 72b54dfc1b338a33b3ea08d15d8fe8bb63a078d8
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Expunge experience-rating calculations [322]
---
 account_value.hpp |  29 -------
 accountvalue.cpp  |  12 +--
 group_values.cpp  | 242 +-----------------------------------------------------
 ihs_acctval.cpp   | 192 +------------------------------------------
 ihs_avmly.cpp     |  48 +----------
 5 files changed, 4 insertions(+), 519 deletions(-)

diff --git a/account_value.hpp b/account_value.hpp
index ec54b96..3dda4b3 100644
--- a/account_value.hpp
+++ b/account_value.hpp
@@ -164,13 +164,6 @@ class LMI_SO AccountValue final
     void   DebugPrint           ();
 
     void   SetClaims();
-    double GetCurtateNetClaimsInforce    () const; // EXPUNGE
-    double GetCurtateNetCoiChargeInforce () const; // EXPUNGE
-    void   SetProjectedCoiCharge         (); // EXPUNGE
-    double GetProjectedCoiChargeInforce  () const; // EXPUNGE
-    double ApportionNetMortalityReserve(double reserve_per_life_inforce); // 
EXPUNGE
-    double experience_rating_amortization_years() const; // EXPUNGE
-    double ibnr_as_months_of_mortality_charges() const; // EXPUNGE
 
     // To support the notion of an M&E charge that depends on total case
     // assets, we provide these functions, which are designed to be
@@ -183,7 +176,6 @@ class LMI_SO AccountValue final
     currency IncrementBOM
         (int    year
         ,int    month
-        ,double a_case_k_factor // EXPUNGE
         );
     // Credit interest and process all subsequent monthly transactions
     void IncrementEOM
@@ -423,7 +415,6 @@ class LMI_SO AccountValue final
     currency NAAR;
     currency CoiCharge;
     currency RiderCharges;
-    currency NetCoiCharge; // EXPUNGE
     currency SpecAmtLoadBase;
     double   DacTaxRsv; // CURRENCY !! obsolete--always zero
 
@@ -539,7 +530,6 @@ class LMI_SO AccountValue final
     currency CumPmtsPostBom;
     currency SepAcctLoad;
 
-    double   case_k_factor;
     double   ActualCoiRate;
 
     bool     SplitMinPrem;
@@ -589,13 +579,6 @@ class LMI_SO AccountValue final
     currency YearsTotalSpecAmtLoad;
     currency YearsTotalSepAcctLoad;
 
-    // For experience rating.
-    double   CoiRetentionRate; // EXPUNGE
-    double   ExperienceRatingAmortizationYears; // EXPUNGE
-    double   IbnrAsMonthsOfMortalityCharges; // EXPUNGE
-    double   NextYearsProjectedCoiCharge; // EXPUNGE
-    double   YearsTotalNetCoiCharge; // EXPUNGE
-
     currency CumulativeSalesLoad;
 
     // Illustrated outlay must be the same for current, guaranteed,
@@ -656,16 +639,4 @@ inline int AccountValue::GetLength() const
     return BasicValues::GetLength();
 }
 
-//============================================================================
-inline double AccountValue::experience_rating_amortization_years() const
-{
-    return ExperienceRatingAmortizationYears;
-}
-
-//============================================================================
-inline double AccountValue::ibnr_as_months_of_mortality_charges() const
-{
-    return IbnrAsMonthsOfMortalityCharges;
-}
-
 #endif // account_value_hpp
diff --git a/accountvalue.cpp b/accountvalue.cpp
index 0e737b0..e95e79c 100644
--- a/accountvalue.cpp
+++ b/accountvalue.cpp
@@ -1038,8 +1038,6 @@ void AccountValue::SetDebugFilename(std::string const& s)
 
 // Stubs for member functions not implemented on this branch.
 
-double AccountValue::ApportionNetMortalityReserve(double)
-    {return 0.0;}
 void   AccountValue::CoordinateCounters()
     {return;}
 void   AccountValue::DebugPrint()
@@ -1050,15 +1048,9 @@ void   AccountValue::FinalizeLife(mcenum_run_basis)
     {return;}
 void   AccountValue::FinalizeLifeAllBases()
     {return;}
-double AccountValue::GetCurtateNetClaimsInforce() const
-    {return 0.0;}
-double AccountValue::GetCurtateNetCoiChargeInforce() const
-    {return 0.0;}
-double AccountValue::GetProjectedCoiChargeInforce() const
-    {return 0.0;}
 currency AccountValue::GetSepAcctAssetsInforce() const
     {return C0;}
-currency AccountValue::IncrementBOM(int, int, double)
+currency AccountValue::IncrementBOM(int, int)
     {return C0;}
 void   AccountValue::IncrementEOM(int, int, currency, currency)
     {return;}
@@ -1076,5 +1068,3 @@ bool   AccountValue::PrecedesInforceDuration(int, int)
     {return false;}
 void   AccountValue::SetClaims()
     {return;}
-void   AccountValue::SetProjectedCoiCharge()
-    {return;}
diff --git a/group_values.cpp b/group_values.cpp
index 57f2dd5..f779fa5 100644
--- a/group_values.cpp
+++ b/group_values.cpp
@@ -165,74 +165,6 @@ census_run_result run_census_in_series::operator()
     return result;
 }
 
-/// Illustrations with group experience rating // EXPUNGE
-///
-/// Mortality profit,
-///   accumulated (net mortality charges - net claims) - IBNR,
-/// is amortized into future mortality charges by applying a k factor
-/// to COI rates. This profit accumulates in the general account at
-/// a special input gross rate that's notionally similar to a LIBOR
-/// rate; optionally, the separate-account rate may be used, but the
-/// reserve is nonetheless still held in the general account. This is
-/// a life-insurance reserve; it does not affect a certificate's CSV
-/// or 7702 corridor.
-///
-/// Yearly totals (without monthly interest) of monthly values of the
-/// accumulands are accumulated at annual interest. Treating mortality
-/// charges as though they were deducted at the end of the year is
-/// consistent with curtate partial mortality, though not with normal
-/// monthiversary processing. Both accumulands are zero in a lapse
-/// year. These simplifying assumptions are okay because this process
-/// is self correcting and therefore needs no exquisite refinements.
-///
-/// The current COI rate is the tabular current COI rate times the
-/// input current COI multiplier, with all other customary adjustments
-/// for substandard, foreign country, etc., but with no adjustment for
-/// retention or k factor--yet never to exceed the guaranteed COI rate.
-///
-/// The actual mortality charge deducted from the account value is
-/// loaded for retention, and reflects experience through the k factor.
-/// The net mortality charge is whatever remains after subtracting the
-/// retention charge from the actual mortality charge.
-///
-///   actual mortality charge = NAAR * min(G, C * (R + K))
-///   retention charge        = NAAR *        C *  R
-///   net mortality charge = actual mortality charge - retention charge
-///
-/// where C is the current COI rate defined above, G is its guaranteed
-/// analogue, R is the retention rate, K is the k factor, and NAAR is
-/// by convention nonnegative.
-///
-/// Database entity 'UseRawTableForRetention' optionally causes R to be
-/// divided by the input current COI multiplier, removing the latter
-/// from the retention calculation; in that case, retention becomes
-/// zero whenever the input current COI multiplier is zero.
-///
-/// Net claims = partial mortality rate times (DB - AV).
-///
-/// IBNR (incurred but not reported reserve) is zero on the issue date;
-/// on each anniversary, it becomes
-///   the past twelve months' total net mortality charges, times
-///   one-twelfth (to get a monthly average), times
-///   the number of months given in database entity ExpRatIBNRMult.
-///
-/// On the date the projection begins--the issue date for new business,
-/// else the inforce date--the k factor is an input scalar. On each
-/// anniversary, it becomes
-///   1 - (mortality profit / denominator),
-/// denominator being the number of years specified in database entity
-/// ExpRatAmortPeriod times a proxy for the coming year's mortality
-/// charge:
-///   the just-completed year's EOY (DB - AV), times
-///   the about-to-begin year's COI rate times twelve, times
-///   the proportion surviving into the about-to-begin year;
-/// except that the k factor is set to
-///   0.0 if it would otherwise be less than 0.0, or
-///   1.0 if the denominator is zero.
-/// Here, EOY AV reflects interest to the last day of the year, and
-/// EOY DB reflects EOY AV: thus, they're the values normally printed
-/// on an illustration.
-
 census_run_result run_census_in_parallel::operator()
     (fs::path           const& file
     ,mcenum_emission    const  emission
@@ -357,51 +289,8 @@ census_run_result run_census_in_parallel::operator()
             ,progress_meter_mode(emission)
             );
 
-#if 0 // EXPUNGE
-        // Variables to support tiering and experience rating. // EXPUNGE 
[nothing here for tiering]
-
-        double const case_ibnr_months = // EXPUNGE
-            cell_values.front().ibnr_as_months_of_mortality_charges()
-            ;
-        double const case_experience_rating_amortization_years = // EXPUNGE
-            cell_values.front().experience_rating_amortization_years()
-            ;
-
-        double case_accum_net_mortchgs = 0.0; // EXPUNGE
-        double case_accum_net_claims   = 0.0; // EXPUNGE
-        double case_k_factor = 
cell_values.front().yare_input_.ExperienceRatingInitialKFactor; // EXPUNGE
-
-        // Experience rating as implemented here uses either a special // 
EXPUNGE
-        // scalar input rate, or the separate-account rate. Those
-        // rates as entered might vary across cells, but there must be
-        // only one rate: therefore, use the first cell's rate, and
-        // extend its last element if it doesn't have enough values.
-
-        std::vector<double> experience_reserve_rate; // EXPUNGE
-        std::copy
-            (cell_values.front().yare_input_.SeparateAccountRate.begin()
-            ,cell_values.front().yare_input_.SeparateAccountRate.end()
-            ,std::back_inserter(experience_reserve_rate)
-            );
-        experience_reserve_rate.resize(MaxYr, experience_reserve_rate.back());
-        if(cell_values.front().yare_input_.OverrideExperienceReserveRate) // 
EXPUNGE
-            {
-            experience_reserve_rate.assign
-                (experience_reserve_rate.size()
-                ,cell_values.front().yare_input_.ExperienceReserveRate // 
EXPUNGE
-                );
-            }
-#endif // EXPUNGE
-
         for(int year = first_cell_inforce_year; year < MaxYr; ++year)
             {
-#if 0 // EXPUNGE
-            double experience_reserve_annual_u = // EXPUNGE
-                    1.0
-                +   experience_reserve_rate[year]
-                ;
-#endif // EXPUNGE
-
             for(auto& i : cell_values)
                 {
                 // A cell must be initialized at the beginning of any
@@ -437,7 +326,7 @@ census_run_result run_census_in_parallel::operator()
                         }
                     i.Month = month;
                     i.CoordinateCounters();
-                    i.IncrementBOM(year, month, 0.0); // EXPUNGE 
case_k_factor);
+                    i.IncrementBOM(year, month);
                     assets += i.GetSepAcctAssetsInforce();
                     }
 
@@ -464,11 +353,6 @@ census_run_result run_census_in_parallel::operator()
             // mortality.
 
             double eoy_inforce_lives      = 0.0;
-#if 0 // EXPUNGE
-            double years_net_claims       = 0.0; // EXPUNGE
-            double years_net_mortchgs     = 0.0; // EXPUNGE
-            double projected_net_mortchgs = 0.0; // EXPUNGE
-#endif // EXPUNGE
             for(auto& i : cell_values)
                 {
                 if(i.PrecedesInforceDuration(year, 11))
@@ -476,133 +360,9 @@ census_run_result run_census_in_parallel::operator()
                     continue;
                     }
                 i.SetClaims();
-#if 0 // EXPUNGE
-                i.SetProjectedCoiCharge(); // EXPUNGE
-#endif // EXPUNGE
                 eoy_inforce_lives      += i.InforceLivesEoy();
                 i.IncrementEOY(year);
-#if 0 // EXPUNGE
-                years_net_claims       += i.GetCurtateNetClaimsInforce(); // 
EXPUNGE
-                years_net_mortchgs     += i.GetCurtateNetCoiChargeInforce(); 
// EXPUNGE
-                projected_net_mortchgs += i.GetProjectedCoiChargeInforce(); // 
EXPUNGE
-#endif // EXPUNGE
-                }
-
-#if 0 // EXPUNGE
-            // Calculate next year's k factor. Do this only for // EXPUNGE
-            // current-expense bases, not as a speed optimization,
-            // but rather because experience rating on other bases
-            // is undefined.
-
-            case_accum_net_claims   *= experience_reserve_annual_u;
-            case_accum_net_claims   += years_net_claims;
-
-            case_accum_net_mortchgs *= experience_reserve_annual_u;
-            case_accum_net_mortchgs += years_net_mortchgs;
-
-            // Presumably an admin system would maintain a scalar
-            // reserve instead of tracking claims and mortality
-            // charges separately, and accumulate it at interest more
-            // frequently than once a year.
-            //
-            // Therefore, add inforce reserve here, to avoid crediting
-            // a year's interest to it. Because only a scalar reserve
-            // is captured, it must all be added to one side of the
-            // reserve equation: the distinction between claims and
-            // mortality charges is lost, but their difference is
-            // preserved, so the resulting reserve is correct.
-            //
-            // The inforce reserve would reflect net claims already
-            // paid as well as mortality charges already deducted for
-            // any partial year. Therefore, although inforce YTD COI
-            // charge is captured separately for adjusting IBNR, it
-            // would be incorrect to add it here.
-
-            if(first_cell_inforce_year == year) // EXPUNGE
-                {
-                case_accum_net_mortchgs += 
cell_values.front().yare_input_.InforceNetExperienceReserve;
-                }
-
-            // Apportion experience-rating reserve uniformly across
-            // inforce lives. Previously, it had been apportioned by
-            // projected mortality charges; that proved unworkable
-            // when a cell lapsed, matured, or failed to have a
-            // nonzero NAAR due to a corridor factor of unity. To
-            // guard against such problems, the apportioned reserve
-            // is summed across cells and asserted materially to
-            // equal the original total reserve.
-
-            if // EXPUNGE
-                (   cell_values.front().yare_input_.UseExperienceRating
-                &&  mce_gen_curr == expense_and_general_account_basis
-                &&  0.0 != eoy_inforce_lives
-                )
-                {
-                if(first_cell_inforce_year == year)
-                    {
-                    years_net_mortchgs += 
cell_values.front().yare_input_.InforceYtdNetCoiCharge;
-                    }
-                double case_ibnr = // EXPUNGE
-                        years_net_mortchgs
-                    *   case_ibnr_months
-                    /   12.0
-                    ;
-                double case_net_mortality_reserve = // EXPUNGE
-                        case_accum_net_mortchgs
-                    -   case_accum_net_claims
-                    -   case_ibnr
-                    ;
-
-                // Current net mortality charge can actually be zero,
-                // e.g., when the corridor factor is unity.
-                double denominator =
-                        case_experience_rating_amortization_years
-                    *   projected_net_mortchgs
-                    ;
-                if(0.0 == denominator)
-                    {
-                    case_k_factor = 1.0;
-                    }
-                else
-                    {
-                    case_k_factor = std::max
-                        (0.0
-                        ,1.0 - case_net_mortality_reserve / denominator
-                        );
-                    }
-
-                double case_net_mortality_reserve_checksum = 0.0; // EXPUNGE
-                for(auto& i : cell_values)
-                    {
-                    if(i.PrecedesInforceDuration(year, 11))
-                        {
-                        continue;
-                        }
-                    case_net_mortality_reserve_checksum += // EXPUNGE
-                        i.ApportionNetMortalityReserve // EXPUNGE
-                            (   case_net_mortality_reserve
-                            /   eoy_inforce_lives
-                            );
-                    }
-                if // EXPUNGE
-                    (!materially_equal
-                        (case_net_mortality_reserve
-                        ,case_net_mortality_reserve_checksum
-                        )
-                    )
-                    {
-                    alarum()
-                        << "\nExperience-rating reserve discrepancy in year "
-                        << year
-                        << ": "
-                        << case_net_mortality_reserve
-                        << " != "
-                        << case_net_mortality_reserve_checksum
-                        << LMI_FLUSH
-                        ;
-                    }
                 }
-#endif // EXPUNGE
 
             if(!meter->reflect_progress())
                 {
diff --git a/ihs_acctval.cpp b/ihs_acctval.cpp
index 7c4ddcd..7dfa2d8 100644
--- a/ihs_acctval.cpp
+++ b/ihs_acctval.cpp
@@ -364,11 +364,7 @@ void AccountValue::RunOneCell(mcenum_run_basis a_Basis)
             {
             Month = month;
             CoordinateCounters();
-            // Absent a group context, case-level k factor is unity:
-            // because partial mortality has no effect, experience
-            // rating is impossible. USER !! Explain this in user
-            // documentation.
-            IncrementBOM(year, month, 1.0);
+            IncrementBOM(year, month);
             IncrementEOM
                 (year
                 ,month
@@ -378,7 +374,6 @@ void AccountValue::RunOneCell(mcenum_run_basis a_Basis)
             }
 
         SetClaims();
-//      SetProjectedCoiCharge(); // EXPUNGE
         IncrementEOY(year);
         }
 
@@ -670,14 +665,9 @@ void AccountValue::SetInitialValues()
 
     CoiCharge                   = C0;
     RiderCharges                = C0;
-    NetCoiCharge                = C0; // EXPUNGE
     MlyDed                      = C0;
     CumulativeSalesLoad         = 
round_minutiae().c(yare_input_.InforceCumulativeSalesLoad);
 
-    database().query_into(DB_ExpRatCoiRetention, CoiRetentionRate);
-    database().query_into(DB_ExpRatAmortPeriod , 
ExperienceRatingAmortizationYears);
-    database().query_into(DB_ExpRatIbnrMult    , 
IbnrAsMonthsOfMortalityCharges);
-
     Dumpin             = Outlay_->dumpin();
     External1035Amount = Outlay_->external_1035_amount();
     Internal1035Amount = Outlay_->internal_1035_amount();
@@ -720,7 +710,6 @@ void AccountValue::SetInitialValues()
 currency AccountValue::IncrementBOM
     (int    year
     ,int    month
-    ,double a_case_k_factor
     )
 {
     if(ItLapsed || BasicValues::GetLength() <= year)
@@ -760,15 +749,6 @@ currency AccountValue::IncrementBOM
             ;
         }
 
-    if
-        (   yare_input_.UsePartialMortality
-        &&  yare_input_.UseExperienceRating
-        &&  mce_gen_curr == GenBasis_
-        )
-        {
-        case_k_factor = a_case_k_factor;
-        }
-
     DoMonthDR();
     return TotalAccountValue();
 }
@@ -864,15 +844,12 @@ void AccountValue::InitializeYear()
     YearsTotalNetIntCredited    = C0;
     YearsTotalGrossIntCredited  = C0;
     YearsTotalLoanIntAccrued    = C0;
-    YearsTotalNetCoiCharge      = 0.0; // EXPUNGE
     YearsTotalPolicyFee         = C0;
     YearsTotalDacTaxLoad        = 0.0;
     YearsTotalSpecAmtLoad       = C0;
     YearsTotalSepAcctLoad       = C0;
     YearsTotalGptForceout       = C0;
 
-    NextYearsProjectedCoiCharge = 0.0;
-
     DacTaxRsv                   = 0.0;
 
     RequestedLoan               = Outlay_->new_cash_loans()[Year];
@@ -1110,50 +1087,6 @@ void AccountValue::SetClaims()
         );
 }
 
-#if 0 // EXPUNGE
-//============================================================================
-// Proxy for next year's COI charge, used only for experience rating.
-void AccountValue::SetProjectedCoiCharge() // EXPUNGE
-{
-    if
-        (   ItLapsed
-        ||  BasicValues::GetLength() <= Year
-        ||  !yare_input_.UsePartialMortality
-        ||  !yare_input_.UseExperienceRating
-        ||  mce_gen_curr != GenBasis_
-        )
-        {
-        return;
-        }
-
-    // Project a charge of zero for the year after maturity.
-    //
-    // This is written separately to emphasize its meaning, though it
-    // obviously could be combined with the above '<=' comparison.
-    //
-    if(BasicValues::GetLength() == 1 + Year)
-        {
-        return;
-        }
-
-    TxSetDeathBft();
-    TxSetTermAmt();
-    // CURRENCY !! presumably material_difference() isn't needed at all? 
um...yes, it is
-    double this_years_terminal_naar = material_difference
-        (dblize(DBReflectingCorr + TermDB)
-        ,dblize(TotalAccountValue())
-        );
-    this_years_terminal_naar = std::max(0.0, this_years_terminal_naar);
-    double next_years_coi_rate = GetBandedCoiRates(GenBasis_, ActualSpecAmt)[1 
+ Year];
-
-    NextYearsProjectedCoiCharge =
-            12.0
-        *   this_years_terminal_naar
-        *   next_years_coi_rate
-        ;
-}
-#endif // EXPUNGE
-
 /// Post year-end results to ledger.
 ///
 /// This function is called only if the contract is in force at the
@@ -1183,7 +1116,6 @@ void AccountValue::FinalizeYear()
     currency csv_net =
           total_av
         - (RegLnBal + PrfLnBal)
-//        + ExpRatReserve // This would be added if it existed.
         ;
 
     // While performing a solve, ignore any sales-load refund, because
@@ -1220,7 +1152,6 @@ void AccountValue::FinalizeYear()
     currency cv_7702 =
           total_av
         + GetRefundableSalesLoad()
-//        + std::max(0.0, ExpRatReserve) // This would be added if it existed.
         ;
     // Increase by negative surrender charge. If some components of
     // the surrender charge are negative while others are positive,
@@ -1253,27 +1184,6 @@ void AccountValue::FinalizeYear()
     VariantValues().BaseDeathBft    [Year] = dblize(DBReflectingCorr);
     VariantValues().EOYDeathBft     [Year] = dblize(DBReflectingCorr + TermDB);
 
-/*
-    // AV already includes any experience refund credited, but it's
-    // forborne among the survivors. That was the right thing to use
-    // for calculating the corridor death benefit for each individual.
-    // But it's not the right thing to multiply by EOY inforce and add
-    // into a composite. The right thing is for the composite to sum
-    // the AV plus *cash* refund instead of forborne, multiplied by EOY
-    // inforce. Otherwise an account-value rollforward cross-check
-    // wouldn't work.
-    //
-    // TODO ?? Maybe the AV before this adjustment is what we really want
-    // to display for an individual illustration. That's what we did
-    // originally, and I'm not at all sure it's right to change it
-    // now.
-    VariantValues().AcctVal         [Year] =
-          TotalAccountValue()
-        + VariantValues().ExpRatRfdCash     [Year]
-        - VariantValues().ExpRatRfdForborne [Year]
-        ;
-*/
-
     // Monthly deduction detail
 
     VariantValues().COICharge         [Year] = dblize(YearsTotalCoiCharge)    ;
@@ -1285,7 +1195,6 @@ void AccountValue::FinalizeYear()
     VariantValues().NetIntCredited    [Year] = 
dblize(YearsTotalNetIntCredited);
     VariantValues().GrossIntCredited  [Year] = 
dblize(YearsTotalGrossIntCredited);
     VariantValues().LoanIntAccrued    [Year] = 
dblize(YearsTotalLoanIntAccrued);
-    VariantValues().NetCOICharge      [Year] = YearsTotalNetCoiCharge         
; // EXPUNGE
     VariantValues().PolicyFee         [Year] = dblize(YearsTotalPolicyFee)    ;
     VariantValues().DacTaxLoad        [Year] = YearsTotalDacTaxLoad           ;
     VariantValues().SpecAmtLoad       [Year] = dblize(YearsTotalSpecAmtLoad)  ;
@@ -1493,105 +1402,6 @@ currency AccountValue::GetSepAcctAssetsInforce() const
     return round_minutiae().c(SepAcctValueAfterDeduction * 
partial_mortality_lx()[Year]);
 }
 
-#if 0 // EXPUNGE
-//============================================================================
-double AccountValue::GetCurtateNetCoiChargeInforce() const // EXPUNGE
-{
-    if
-        (   ItLapsed
-        ||  BasicValues::GetLength() <= Year
-        ||  !yare_input_.UsePartialMortality
-        ||  !yare_input_.UseExperienceRating
-        ||  mce_gen_curr != GenBasis_
-        )
-        {
-        return 0.0;
-        }
-
-    LMI_ASSERT(11 == Month);
-    return YearsTotalNetCoiCharge * InforceLivesBoy();
-}
-
-//============================================================================
-double AccountValue::GetCurtateNetClaimsInforce() const // EXPUNGE
-{
-    if
-        (   ItLapsed
-        ||  BasicValues::GetLength() <= Year
-        ||  !yare_input_.UsePartialMortality
-        ||  !yare_input_.UseExperienceRating
-        ||  mce_gen_curr != GenBasis_
-        )
-        {
-        return 0.0;
-        }
-
-    LMI_ASSERT(11 == Month);
-    return YearsNetClaims * partial_mortality_lx()[Year];
-}
-
-//============================================================================
-double AccountValue::GetProjectedCoiChargeInforce() const // EXPUNGE
-{
-    if
-        (   ItLapsed
-        ||  BasicValues::GetLength() <= Year
-        ||  !yare_input_.UsePartialMortality
-        ||  !yare_input_.UseExperienceRating
-        ||  mce_gen_curr != GenBasis_
-        )
-        {
-        return 0.0;
-        }
-
-    LMI_ASSERT(11 == Month);
-    return NextYearsProjectedCoiCharge * InforceLivesEoy();
-}
-
-//============================================================================
-// The experience-rating mortality reserve isn't actually held in
-// individual certificates: it really exists only at the case level.
-// Yet it is apportioned among certificates in order to conform to the
-// design invariant that a composite is a weighted sum of cells.
-//
-// The return value, added across cells, should reproduce the total
-// total reserve at the case level, as the caller may assert.
-//
-double AccountValue::ApportionNetMortalityReserve // EXPUNGE
-    (double reserve_per_life_inforce
-    )
-{
-    if
-        (   ItLapsed
-        ||  BasicValues::GetLength() <= Year
-        ||  !yare_input_.UsePartialMortality
-        ||  !yare_input_.UseExperienceRating
-        ||  mce_gen_curr != GenBasis_
-        )
-        {
-        return 0.0;
-        }
-
-    double inforce_factor =
-        (0.0 != yare_input_.NumberOfIdenticalLives)
-        ? InforceLivesEoy() / yare_input_.NumberOfIdenticalLives
-        : 0.0
-        ;
-
-    double apportioned_reserve = reserve_per_life_inforce * inforce_factor;
-
-    // The experience-rating reserve can't be posted to the ledger in
-    // FinalizeYear(), which is run before the reserve is calculated.
-    // The projected COI charge and K factor are posted to the ledger
-    // here as well, simply for uniformity.
-    VariantValues().ExperienceReserve [Year] = apportioned_reserve;
-    VariantValues().ProjectedCoiCharge[Year] = NextYearsProjectedCoiCharge;
-    VariantValues().KFactor           [Year] = case_k_factor;
-
-    return apportioned_reserve * yare_input_.NumberOfIdenticalLives;
-}
-#endif // EXPUNGE
-
 /// Beginning of year inforce lives, reflecting lapses and survivorship.
 
 double AccountValue::InforceLivesBoy() const
diff --git a/ihs_avmly.cpp b/ihs_avmly.cpp
index 9be6163..0052a2d 100644
--- a/ihs_avmly.cpp
+++ b/ihs_avmly.cpp
@@ -75,7 +75,6 @@
 // - loan balance             yes  no    no   yes  n/a  n/a   ?     no
 // + refundable sales load    yes  yes   yes  no   no   no?   no    yes?
 // - surrender charge         yes  if<0  if<0 if>0 if>0 if>0  if>0? yes
-// + experience reserve       yes  if>0  if>0 no   no   no    yes   if>0
 // - anticipated deductions   no   no    no   yes  yes  no    no    no
 // honeymoon value if greater yes  ?     yes  no   no   no?   yes   n/a
 //
@@ -148,7 +147,6 @@ void AccountValue::DoMonthDR()
         (HoneymoonValue
         ,   kludge_account_value
           + GetRefundableSalesLoad()
-//          + std::max(0.0, ExpRatReserve) // This would be added if it 
existed.
         );
 // TODO ?? TAXATION !! Use CashValueFor7702() instead?
     double max_necessary_premium = Irc7702A_->MaxNecessaryPremium
@@ -649,7 +647,6 @@ currency AccountValue::CashValueFor7702() const
         (HoneymoonValue
         ,   TotalAccountValue()
           + GetRefundableSalesLoad()
-//          + std::max(0.0, ExpRatReserve) // This would be added if it 
existed.
         );
 }
 
@@ -1360,7 +1357,6 @@ void AccountValue::TxRecognizePaymentFor7702A
         (HoneymoonValue
         ,   kludge_account_value
           + GetRefundableSalesLoad()
-//          + std::max(0.0, ExpRatReserve) // This would be added if it 
existed.
         );
     LMI_ASSERT(0.0 <= Dcv);
 
@@ -1676,7 +1672,6 @@ void AccountValue::TxSetDeathBft()
           TotalAccountValue()
         - std::min(C0, SurrChg())
         + GetRefundableSalesLoad()
-//        + std::max(0.0, ExpRatReserve) // This would be added if it existed.
         ;
 
     cash_value_for_corridor = std::max
@@ -1701,7 +1696,6 @@ void AccountValue::TxSetDeathBft()
             *   (   Dcv
                 -   dblize(std::min(C0, SurrChg()))
                 +   dblize(GetRefundableSalesLoad())
-//                +   std::max(0.0, ExpRatReserve) // This would be added if 
it existed.
                 )
             )
         );
@@ -1813,40 +1807,14 @@ void AccountValue::TxSetCoiCharge()
     // DCV need not be rounded.
     DcvNaar = std::max(0.0, DcvNaar);
 
-    double retention_charge = 0.0; // EXPUNGE
-stifle_warning_for_unused_value(retention_charge); // EXPUNGE
     double coi_rate = GetBandedCoiRates(GenBasis_, ActualSpecAmt)[Year];
     ActualCoiRate = coi_rate;
 
-    // COI retention is a percentage of tabular rather than current
-    // COI charge. It's a risk charge, so it follows mortality
-    // expectations rather than fluctuations.
-    //
-    // TODO ?? For now, however, the COI retention calculated here
-    // improvidently reflects the current COI multiplier, so end users
-    // need to divide input CoiRetentionRate by that multiplier.
-
-    if
-        (   yare_input_.UseExperienceRating
-        &&  mce_gen_curr == GenBasis_
-        )
-        {
-        ActualCoiRate = round_coi_rate()
-            (std::min
-                (GetBandedCoiRates(mce_gen_guar, ActualSpecAmt)[Year]
-                ,coi_rate * (case_k_factor + CoiRetentionRate)
-                )
-            );
-        double retention_rate = round_coi_rate()(coi_rate * CoiRetentionRate);
-        retention_charge = 0.0 * NAAR * retention_rate; // EXPUNGE
-        }
-
     CoiCharge    = round_coi_charge().c(NAAR * ActualCoiRate);
-//  NetCoiCharge = CoiCharge - round_coi_charge().c(retention_charge); // 
EXPUNGE
     YearsTotalCoiCharge += CoiCharge;
 
     // DCV need not be rounded.
-    DcvCoiCharge = DcvNaar * (YearsDcvCoiRate + CoiRetentionRate);
+    DcvCoiCharge = DcvNaar * YearsDcvCoiRate;
 }
 
 /// Calculate rider charges.
@@ -1981,8 +1949,6 @@ void AccountValue::TxDoMlyDed()
     // determined.
     MlyDed += MonthsPolicyFees + SpecAmtLoad;
 
-//  YearsTotalNetCoiCharge += dblize(NetCoiCharge); // EXPUNGE
-
     SepAcctValueAfterDeduction = AVSepAcct;
 }
 
@@ -1999,17 +1965,10 @@ void AccountValue::TxTestHoneymoonForExpiration()
     // Loan balance should not be subtracted from this value: if it
     // were, then the owner could retain the honeymoon forever by
     // maintaining a maximum loan.
-    //
-    // Honeymoon provisions are probably inconsistent with experience
-    // rating. If those features occur together, then presumably the
-    // experience rating reserve would affect the cash surrender value
-    // but not the honeymoon value.
-    //
     currency csv_ignoring_loan =
           TotalAccountValue()
         - SurrChg()
         + GetRefundableSalesLoad()
-//        + std::max(0.0, ExpRatReserve) // This would be added if it existed.
         ;
 
     // It may seem 'obvious' that 'HoneymoonValue' can never be
@@ -2825,15 +2784,10 @@ void AccountValue::TxTestLapse()
     // The refundable load cannot prevent a lapse that would otherwise
     // occur, because it is refunded only after termination. The same
     // principle applies to a negative surrender charge.
-    //
-    // The experience rating reserve can prevent a lapse, because it
-    // is an actual balance-sheet item that is actually held in the
-    // certificate.
 
     currency lapse_test_csv =
           TotalAccountValue()
         - (RegLnBal + PrfLnBal)
-//        + std::max(0.0, ExpRatReserve) // This would be added if it existed.
         ;
     if(!LapseIgnoresSurrChg)
         {



reply via email to

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