lmi-commits
[Top][All Lists]
Advanced

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

[lmi-commits] [lmi] valyuta/004 50ed405 3/9: Prefer explicit to implicit


From: Greg Chicares
Subject: [lmi-commits] [lmi] valyuta/004 50ed405 3/9: Prefer explicit to implicit currency rounding
Date: Tue, 29 Dec 2020 14:46:01 -0500 (EST)

branch: valyuta/004
commit 50ed4050acf3ded17fb862f559591d81d22b7de0
Author: Gregory W. Chicares <gchicares@sbcglobal.net>
Commit: Gregory W. Chicares <gchicares@sbcglobal.net>

    Prefer explicit to implicit currency rounding
    
    Incidentally, the commentary added to 'loads_impl.hpp' explains why
    'TgtPremMonthlyPolFee' is rounded with a gross-premium rule (as seems
    natural), but class Loads uses a different rule for other policy fees.
---
 accountvalue.cpp | 13 +++++++------
 basicvalues.cpp  |  6 +++---
 ihs_acctval.cpp  | 11 ++++++-----
 ihs_basicval.cpp | 16 ++++++++--------
 loads_impl.hpp   |  6 +++++-
 5 files changed, 29 insertions(+), 23 deletions(-)

diff --git a/accountvalue.cpp b/accountvalue.cpp
index 69dd868..e848495 100644
--- a/accountvalue.cpp
+++ b/accountvalue.cpp
@@ -128,7 +128,8 @@ AccountValue::AccountValue(Input const& input)
 
 currency AccountValue::base_specamt(int year) const
 {
-    return currency(InvariantValues().SpecAmt[year]);
+    // CURRENCY !! Cents in ledger will make rounding unnecessary.
+    return round_specamt().c(InvariantValues().SpecAmt[year]);
 }
 
 //============================================================================
@@ -222,7 +223,7 @@ void AccountValue::RunOneCell(mcenum_run_basis TheBasis)
 
     InforceYear      = yare_input_.InforceYear;
     InforceMonth     = yare_input_.InforceMonth;
-    InforceAVGenAcct = currency(yare_input_.InforceGeneralAccountValue);
+    InforceAVGenAcct = 
round_minutiae().c(yare_input_.InforceGeneralAccountValue);
 
     ItLapsed         = false;
     LapseMonth       = 0;
@@ -282,7 +283,7 @@ void AccountValue::DoYear
 
     pmt                   = stored_pmts[Year];
     YearsPremLoadTgt      = Loads_->target_premium_load(GenBasis_)[Year];
-    YearsMonthlyPolicyFee = 
currency(Loads_->monthly_policy_fee(GenBasis_)[Year]);
+    YearsMonthlyPolicyFee = Loads_->monthly_policy_fee (GenBasis_)[Year];
     ActualSpecAmt         = base_specamt(Year);
 
     // These variables are set for each pass independently.
@@ -795,7 +796,7 @@ void AccountValue::TxSetRiderDed()
     WpCharge = C0;
     if(haswp)
         {
-        WpCharge = currency
+        WpCharge = round_rider_charges().c
             (
                 YearsWpRate
             *   (CoiCharge + YearsMonthlyPolicyFee + AdbCharge)
@@ -805,7 +806,7 @@ void AccountValue::TxSetRiderDed()
     AdbCharge = C0;
     if(hasadb)
         {
-        AdbCharge = currency(YearsAdbRate * std::min(500000.0, 
ActualSpecAmt.d()));
+        AdbCharge = round_rider_charges().c(YearsAdbRate * std::min(500000.0, 
ActualSpecAmt.d()));
         }
 }
 
@@ -944,7 +945,7 @@ void AccountValue::TxTakeWD()
         }
 
     // Deduct withdrawal fee.
-    wd -= std::min(WDFee, currency(wd * WDFeeRate));
+    wd -= std::min(WDFee, round_withdrawal().c(wd * WDFeeRate));
     // IHS !! This treats input WD as gross; it probably should be net. But 
compare lmi.
 
     InvariantValues().NetWD[Year] = wd.d();
diff --git a/basicvalues.cpp b/basicvalues.cpp
index e83093b..da619ae 100644
--- a/basicvalues.cpp
+++ b/basicvalues.cpp
@@ -123,9 +123,9 @@ void BasicValues::Init()
 //  database().query_into(DB_MinWd     , MinWD     );
 //  database().query_into(DB_WdFee     , WDFee     );
 //  database().query_into(DB_WdFeeRate , WDFeeRate );
-    MinSpecAmt = currency(database().query<int>(DB_MinSpecAmt));
-    MinWD      = currency(database().query<int>(DB_MinWd     ));
-    WDFee      = currency(database().query<int>(DB_WdFee     ));
+    MinSpecAmt = round_specamt   ().c(database().query<int>(DB_MinSpecAmt));
+    MinWD      = round_withdrawal().c(database().query<int>(DB_MinWd     ));
+    WDFee      = round_withdrawal().c(database().query<int>(DB_WdFee     ));
 //  WDFeeRate  = database().query<int>(DB_WdFeeRate ); // no, this line looks 
wrong
     database().query_into(DB_WdFeeRate , WDFeeRate );
 
diff --git a/ihs_acctval.cpp b/ihs_acctval.cpp
index b0d64f0..fdbf5aa 100644
--- a/ihs_acctval.cpp
+++ b/ihs_acctval.cpp
@@ -143,14 +143,16 @@ AccountValue::AccountValue(Input const& input)
 
 currency AccountValue::base_specamt(int year) const
 {
-    return currency(InvariantValues().SpecAmt[year]);
+    // CURRENCY !! Cents in ledger will make rounding unnecessary.
+    return round_specamt().c(InvariantValues().SpecAmt[year]);
 }
 
 /// Specified amount of term rider.
 
 currency AccountValue::term_specamt(int year) const
 {
-    return currency(InvariantValues().TermSpecAmt[year]);
+    // CURRENCY !! Cents in ledger will make rounding unnecessary.
+    return round_specamt().c(InvariantValues().TermSpecAmt[year]);
 }
 
 /// Specified amount for 7702 (not 7702A).
@@ -1372,9 +1374,8 @@ void AccountValue::SetAnnualInvariants()
 {
     YearsCorridorFactor     = GetCorridorFactor()[Year];
     YearsDBOpt              = DeathBfts_->dbopt()[Year];
-    // policy fee should be rounded in loads class
-    YearsMonthlyPolicyFee   = 
currency(Loads_->monthly_policy_fee(GenBasis_)[Year]);
-    YearsAnnualPolicyFee    = currency(Loads_->annual_policy_fee 
(GenBasis_)[Year]);
+    YearsMonthlyPolicyFee   = Loads_->monthly_policy_fee(GenBasis_)[Year];
+    YearsAnnualPolicyFee    = Loads_->annual_policy_fee (GenBasis_)[Year];
 
     YearsGenAcctIntRate     = InterestRates_->GenAcctNetRate
         (GenBasis_
diff --git a/ihs_basicval.cpp b/ihs_basicval.cpp
index 0830e7f..5bc92ed 100644
--- a/ihs_basicval.cpp
+++ b/ihs_basicval.cpp
@@ -564,10 +564,10 @@ currency BasicValues::GetAnnualTgtPrem(int a_year, 
currency a_specamt) const
 void BasicValues::SetPermanentInvariants()
 {
     // maybe implement query_into<currency>
-    MinIssSpecAmt      = currency(database().query<int>(DB_MinIssSpecAmt     
));
-    MinIssBaseSpecAmt  = currency(database().query<int>(DB_MinIssBaseSpecAmt 
));
-    MinRenlSpecAmt     = currency(database().query<int>(DB_MinRenlSpecAmt    
));
-    MinRenlBaseSpecAmt = 
currency(database().query<int>(DB_MinRenlBaseSpecAmt));
+    MinIssSpecAmt      = 
round_specamt().c(database().query<int>(DB_MinIssSpecAmt     ));
+    MinIssBaseSpecAmt  = 
round_specamt().c(database().query<int>(DB_MinIssBaseSpecAmt ));
+    MinRenlSpecAmt     = 
round_specamt().c(database().query<int>(DB_MinRenlSpecAmt    ));
+    MinRenlBaseSpecAmt = 
round_specamt().c(database().query<int>(DB_MinRenlBaseSpecAmt));
     database().query_into(DB_NoLapseDboLvlOnly    , NoLapseDboLvlOnly);
     database().query_into(DB_NoLapseUnratedOnly   , NoLapseUnratedOnly);
     database().query_into(DB_DboChgCanIncrSpecAmt , OptChgCanIncrSA);
@@ -585,7 +585,7 @@ void BasicValues::SetPermanentInvariants()
     database().query_into(DB_MinPremType          , MinPremType);
     database().query_into(DB_TgtPremType          , TgtPremType);
     database().query_into(DB_TgtPremFixedAtIssue  , TgtPremFixedAtIssue);
-    TgtPremMonthlyPolFee = 
currency(database().query<int>(DB_TgtPremMonthlyPolFee));
+    TgtPremMonthlyPolFee = 
round_gross_premium().c(database().query<int>(DB_TgtPremMonthlyPolFee));
     // Assertion: see comments on GetModalPremTgtFromTable().
     LMI_ASSERT(C0 == TgtPremMonthlyPolFee || oe_modal_table == TgtPremType);
     database().query_into(DB_CurrCoiTable0Limit   , CurrCoiTable0Limit);
@@ -611,8 +611,8 @@ void BasicValues::SetPermanentInvariants()
 //  AdbLimit         = database().query<int>(DB_AdbLimit        );
 //  WpLimit          = database().query<int>(DB_WpLimit         );
 //  SpecAmtLoadLimit = database().query<int>(DB_SpecAmtLoadLimit);
-    MinWD            = currency(database().query<int>(DB_MinWd           ));
-    WDFee            = currency(database().query<int>(DB_WdFee           ));
+    MinWD            = round_withdrawal().c(database().query<int>(DB_MinWd));
+    WDFee            = round_withdrawal().c(database().query<int>(DB_WdFee));
     database().query_into(DB_WdFeeRate            , WDFeeRate);
     database().query_into(DB_AllowChangeToDbo2    , AllowChangeToDBO2);
     database().query_into(DB_AllowSpecAmtIncr     , AllowSAIncr);
@@ -720,7 +720,7 @@ void BasicValues::SetPermanentInvariants()
     database().query_into(DB_Effective7702DboRop, Effective7702DboRop);
     TermIsDbFor7702     = oe_7702_term_is_db == 
database().query<oenum_7702_term>(DB_TermIsQABOrDb7702 );
     TermIsDbFor7702A    = oe_7702_term_is_db == 
database().query<oenum_7702_term>(DB_TermIsQABOrDb7702A);
-    MaxNAAR             = currency(yare_input_.MaximumNaar);
+    MaxNAAR             = round_naar().c(yare_input_.MaximumNaar);
 
     database().query_into(DB_MinPremIntSpread, MinPremIntSpread_);
 }
diff --git a/loads_impl.hpp b/loads_impl.hpp
index 5cb3154..47a7e1c 100644
--- a/loads_impl.hpp
+++ b/loads_impl.hpp
@@ -68,7 +68,11 @@ class product_database;
 /// However, if the monthly policy fee is $3.25 (current) and $5.00
 /// (guaranteed), the midpoint mustn't be $4.125, because subtracting
 /// that from the account value would make it a non-integral number
-/// of cents.
+/// of cents. An argument could be made for using a gross-premium
+/// rounding rule instead, reasoning that a policy fee ought to be
+/// independently payable, but the minutiae rule is likely to specify
+/// finer (or no different) rounding, which seems better for the
+/// midpoint case.
 ///
 /// VectorExtraCompLoad_: Input extra load per dollar of premium.
 ///



reply via email to

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