[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)
{
- [lmi-commits] [lmi] master updated (ef8f7b4 -> 64c9105), Greg Chicares, 2021/01/31
- [lmi-commits] [lmi] master 72b54df 3/6: Expunge experience-rating calculations [322],
Greg Chicares <=
- [lmi-commits] [lmi] master 2384269 1/6: Allow currency/currency --> double, Greg Chicares, 2021/01/31
- [lmi-commits] [lmi] master 64c9105 6/6: Expunge experience rating from ledger, Greg Chicares, 2021/01/31
- [lmi-commits] [lmi] master 0e4c210 2/6: Mark experience-rating code for expunction, Greg Chicares, 2021/01/31
- [lmi-commits] [lmi] master 7d7b4b4 4/6: Expunge experience rating from database [321], Greg Chicares, 2021/01/31
- [lmi-commits] [lmi] master 526fdb4 5/6: Neither use nor allow experience rating, Greg Chicares, 2021/01/31