lmi-commits
[Top][All Lists]

## [lmi-commits] [lmi] master a2c3a37c 3/3: Store all "scalable" vectors in

 From: Greg Chicares Subject: [lmi-commits] [lmi] master a2c3a37c 3/3: Store all "scalable" vectors in ledger as cents Date: Wed, 27 Apr 2022 16:19:13 -0400 (EDT)

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

Store all "scalable" vectors in ledger as cents

"Scalable" columns are scaled so that the most extreme positive or
negative value fits without overflowing a format like "999,999,999".
The scaling factor naturally must apply to all columns, so that a
caption like "values in thousands" describes them all. Therefore,
the extrema must embrace all values in all these vectors, which is
easiest to accomplish when all use the same unit. Now they all use
the same unit, cents.

As an alternative, a multiplier (say, 1.00 for dollars and 100.0
for cents) could be stored somewhere and applied to the values for
determination of the extrema. That just seemed less simple.

As an alternative, the scaling factor could be based on some
presumptively maximal column like EOY death benefit. That would be
less robust, though: for example, some other column might exceed
-0.1 times the maximal death benefit, and the negative sign occupies
an extra character in the output; for another example, the salary
column is unbounded, so that a group death benefit of three times
salary to a maximum of \$1M would produce a \$1M death benefit for
an oligarch with a salary orders of magnitude higher.

The scaling logic pays little attention to formats that contain
decimals. Generally, that doesn't matter because such amounts are
tiny. The only one that seems relevant here is "AddonMonthlyFee":

,{"AnnGAIntRate_Current"            ,      "99.99%"}

which is surpassingly unlikely to be large: it looks weird because
the leftmost character is blank, but ",999,999.99" would clearly
be wrong.
---
ihs_acctval.cpp           | 14 +++++++-------
ledger_evaluator.cpp      | 24 +++++++++++++-----------
ledger_invariant.cpp      |  4 ++--
ledger_invariant_init.cpp |  7 +++++--
ledger_text_formats.cpp   | 10 +++++-----
ledger_variant.cpp        | 16 ++++++++--------
6 files changed, 40 insertions(+), 35 deletions(-)

diff --git a/ihs_acctval.cpp b/ihs_acctval.cpp
index 02b84a5b..b9345aba 100644
--- a/ihs_acctval.cpp
+++ b/ihs_acctval.cpp
@@ -1228,7 +1228,7 @@ void AccountValue::FinalizeYear()
VariantValues().AcctVal     [Year] = centize(total_av);
VariantValues().AVGenAcct   [Year] = centize(AVGenAcct + AVRegLn +
AVPrfLn);
VariantValues().AVSepAcct   [Year] = centize(AVSepAcct);
-    VariantValues().DacTaxRsv   [Year] = DacTaxRsv;
+    VariantValues().DacTaxRsv   [Year] = 100.0 * DacTaxRsv;
VariantValues().CSVNet      [Year] = centize(csv_net);
VariantValues().CV7702      [Year] = centize(cv_7702);

@@ -1252,17 +1252,17 @@ void AccountValue::FinalizeYear()

VariantValues().COICharge         [Year] = centize(YearsTotalCoiCharge)   ;
VariantValues().RiderCharges      [Year] = centize(YearsTotalRiderCharges);
-    VariantValues().AVRelOnDeath      [Year] = YearsAVRelOnDeath              ;
-    VariantValues().ClaimsPaid        [Year] = YearsGrossClaims               ;
-    VariantValues().DeathProceedsPaid [Year] = YearsDeathProceeds             ;
-    VariantValues().NetClaims         [Year] = YearsNetClaims                 ;
+    VariantValues().AVRelOnDeath      [Year] = 100.0 * YearsAVRelOnDeath      ;
+    VariantValues().ClaimsPaid        [Year] = 100.0 * YearsGrossClaims       ;
+    VariantValues().DeathProceedsPaid [Year] = 100.0 * YearsDeathProceeds     ;
+    VariantValues().NetClaims         [Year] = 100.0 * YearsNetClaims         ;
VariantValues().NetIntCredited    [Year] =
centize(YearsTotalNetIntCredited);
VariantValues().GrossIntCredited  [Year] =
centize(YearsTotalGrossIntCredited);
VariantValues().LoanIntAccrued    [Year] =
centize(YearsTotalLoanIntAccrued);
VariantValues().PolicyFee         [Year] = centize(YearsTotalPolicyFee)   ;

currency notional_sep_acct_charge =
diff --git a/ledger_evaluator.cpp b/ledger_evaluator.cpp
index 5b7dec50..69aec38a 100644
--- a/ledger_evaluator.cpp
+++ b/ledger_evaluator.cpp
,{"AcctVal_GuaranteedZero"          , "999,999,999"}
,{"AnnGAIntRate_Current"            ,      "99.99%"}
,{"AnnGAIntRate_Guaranteed"         ,      "99.99%"}
,{"AnnHoneymoonValueRate_Current"   ,      "99.99%"}
@@ -554,24 +554,14 @@ format_map_t static_formats()
,{"PolicyYear"                      , f1}
// F1: zero decimals, commas
// > Format as a number with thousand separators and no decimal places
(#,###,##0)
-    ,{"AVRelOnDeath"                    , f1}
-    ,{"AvgDeathBft"                     , f1}
-    ,{"ClaimsPaid"                      , f1}
-    ,{"DacTaxRsv"                       , f1}
-    ,{"DeathProceedsPaid"               , f1}
//  ,{"EeMode"                          , f1} // Not numeric.
//  ,{"ErMode"                          , f1} // Not numeric.
-    ,{"NetClaims"                       , f1}
-    ,{"Salary"                          , f1}
,{"SpouseRiderAmount"               , f1}
// F2: two decimals, commas
// > Format as a number with thousand separators and two decimal places
(#,###,###.00)
,{"AnnualFlatExtra"                 , f2}
// TODO ?? The precision of 'InforceLives' is inadequate. Is every other
format OK?
,{"InforceLives"                    , f2}
@@ -616,13 +606,19 @@ format_map_t static_formats()
// F5: zero decimals, commas, cents to dollars
// > Format as a number with thousand separators and no decimal places
(#,###,##0)
,{"AVGenAcct"                       , f5}
+    ,{"AVRelOnDeath"                    , f5}
,{"AVSepAcct"                       , f5}
,{"AcctVal"                         , f5}
+    ,{"AvgDeathBft"                     , f5}
,{"BaseDeathBft"                    , f5}
,{"COICharge"                       , f5}
,{"CSVNet"                          , f5}
,{"CV7702"                          , f5}
+    ,{"ClaimsPaid"                      , f5}
+    ,{"DacTaxRsv"                       , f5}
,{"Dcv"                             , f5}
+    ,{"DeathProceedsPaid"               , f5}
,{"EOYDeathBft"                     , f5}
,{"EeGrossPmt"                      , f5}
@@ -635,6 +631,7 @@ format_map_t static_formats()
,{"LoanIntAccrued"                  , f5}
,{"NaarForceout"                    , f5}
+    ,{"NetClaims"                       , f5}
,{"NetIntCredited"                  , f5}
,{"NetPmt"                          , f5}
,{"NetWD"                           , f5}
@@ -642,7 +639,9 @@ format_map_t static_formats()
,{"Outlay"                          , f5}
,{"PolicyFee"                       , f5}
,{"PrefLoanBalance"                 , f5} // Not used yet.
,{"RiderCharges"                    , f5}
+    ,{"Salary"                          , f5}
,{"SepAcctCharges"                  , f5}
,{"SpecAmt"                         , f5}
@@ -650,6 +649,9 @@ format_map_t static_formats()
,{"TermPurchased"                   , f5}
,{"TermSpecAmt"                     , f5}
,{"TotalLoanBalance"                , f5}
+// F6: two decimals, commas, cents to dollars
+// > Format as a number with thousand separators and two decimal places
(#,###,###.00)
};

return format_map;
diff --git a/ledger_invariant.cpp b/ledger_invariant.cpp
index ceecc0c5..cb61fa1b 100644
--- a/ledger_invariant.cpp
+++ b/ledger_invariant.cpp
@@ -92,7 +92,7 @@ void LedgerInvariant::Alloc(int len)
; // f5
; // f5
; // f5
; // f2
; // f6

// EOY vectors.
EndYearVectors  ["TermSpecAmt"                ] = &TermSpecAmt
; // f5
@@ -100,7 +100,7 @@ void LedgerInvariant::Alloc(int len)
EndYearVectors  ["Dcv"                        ] = &Dcv
; // f5

// Forborne vectors.
-    ForborneVectors ["Salary"                     ] = &Salary
; // f1
+    ForborneVectors ["Salary"                     ] = &Salary
; // f5

// Nonscalable vectors.
OtherVectors    ["IndvTaxBracket"             ] = &IndvTaxBracket
;
diff --git a/ledger_invariant_init.cpp b/ledger_invariant_init.cpp
index da360bfc..50131860 100644
--- a/ledger_invariant_init.cpp
+++ b/ledger_invariant_init.cpp
@@ -31,6 +31,7 @@
#include "database.hpp"
#include "dbnames.hpp"
#include "death_benefits.hpp"
+#include "et_vector.hpp"
#include "fund_data.hpp"
#include "i7702.hpp"
#include "interest_rates.hpp"
@@ -98,7 +99,8 @@ void LedgerInvariant::Init(BasicValues const* b)

+    // convert to decimal cents:
b->yare_input_.ExtraMonthlyCustodialFee  ;

// EOY vectors.

@@ -124,7 +126,8 @@ void LedgerInvariant::Init(BasicValues const* b)

// Forborne vectors.

-    Salary                     = b->yare_input_.ProjectedSalary           ;
+    // convert to decimal cents:
+    Salary                   <<= 100.0 * b->yare_input_.ProjectedSalary   ;

// Nonscalable vectors.

diff --git a/ledger_text_formats.cpp b/ledger_text_formats.cpp
index cddd83d9..e761e84d 100644
--- a/ledger_text_formats.cpp
+++ b/ledger_text_formats.cpp
@@ -576,8 +576,8 @@ void PrintCellTabDelimited

os << Curr_.value_str("NetPmt"                ,j, 100.0) << '\t';

-        os << Curr_.value_str("PremTaxLoad"           ,j) << '\t';
-        os << Curr_.value_str("DacTaxLoad"            ,j) << '\t';
+        os << Curr_.value_str("PremTaxLoad"           ,j, 100.0) << '\t';
+        os << Curr_.value_str("DacTaxLoad"            ,j, 100.0) << '\t';
os << Curr_.value_str("PolicyFee"             ,j, 100.0) << '\t';
os << Curr_.value_str("SpecAmtLoad"           ,j, 100.0) << '\t';
os << Invar.value_str("AnnualFlatExtra"       ,j) << '\t';
@@ -612,8 +612,8 @@ void PrintCellTabDelimited
// First element of InforceLives is BOY--show only EOY.
os << value_cast<std::string>(Invar.InforceLives[1 + j]) << '\t';

-        os << Curr_.value_str("ClaimsPaid"            ,j) << '\t';
-        os << Curr_.value_str("NetClaims"             ,j) << '\t';
+        os << Curr_.value_str("ClaimsPaid"            ,j, 100.0) << '\t';
+        os << Curr_.value_str("NetClaims"             ,j, 100.0) << '\t';
os << "0\t"; // obsolete
os << "0\t"; // obsolete
os << "0\t"; // obsolete
@@ -747,7 +747,7 @@ void PrintRosterTabDelimited
<< Invar.Age + Invar.InforceYear              << '\t'
<< Invar.value_str("UWClass"                ) << '\t'
<< Invar.value_str("Smoker"                 ) << '\t'
-        << Invar.value_str("Salary"               ,d) << '\t'
+        << Invar.value_str("Salary"               ,d, 100.0) << '\t'
<< Invar.value_str("SpecAmt"              ,d, 100.0) << '\t'
<< Invar.value_str("TermSpecAmt"          ,d, 100.0) << '\t'
<< Invar.value_str("InitTgtPrem"            , 100.0) << '\t'
diff --git a/ledger_variant.cpp b/ledger_variant.cpp
index 10189b60..e4a0734e 100644
--- a/ledger_variant.cpp
+++ b/ledger_variant.cpp
@@ -88,34 +88,34 @@ void LedgerVariant::Alloc(int len)
// rather than at either of the year's endpoints. The same is
// true of various other items such as policy fee and interest
// credited as used here.
-    BegYearVectors  ["AVRelOnDeath"           ] = &AVRelOnDeath           ; //
f1
+    BegYearVectors  ["AVRelOnDeath"           ] = &AVRelOnDeath           ; //
f5
BegYearVectors  ["NetIntCredited"         ] = &NetIntCredited         ; //
f5
BegYearVectors  ["GrossIntCredited"       ] = &GrossIntCredited       ; //
f5
BegYearVectors  ["LoanIntAccrued"         ] = &LoanIntAccrued         ; //
f5

BegYearVectors  ["PolicyFee"              ] = &PolicyFee              ; //
f5
f1
f1
f5
f5
f5
BegYearVectors  ["SepAcctCharges"         ] = &SepAcctCharges         ; //
f5

// Deaths are assumed to come at the end of the year only; but
// they're discounted by the proportion in force at the beginning.
-    BegYearVectors  ["ClaimsPaid"             ] = &ClaimsPaid             ; //
f1
-    BegYearVectors  ["DeathProceedsPaid"      ] = &DeathProceedsPaid      ; //
f1
-    BegYearVectors  ["NetClaims"              ] = &NetClaims              ; //
f1
+    BegYearVectors  ["ClaimsPaid"             ] = &ClaimsPaid             ; //
f5
+    BegYearVectors  ["DeathProceedsPaid"      ] = &DeathProceedsPaid      ; //
f5
+    BegYearVectors  ["NetClaims"              ] = &NetClaims              ; //
f5
BegYearVectors  ["NetPmt"                 ] = &NetPmt                 ; //
f5

EndYearVectors  ["AcctVal"                ] = &AcctVal                ; //
f5
EndYearVectors  ["AVGenAcct"              ] = &AVGenAcct              ; //
f5
EndYearVectors  ["AVSepAcct"              ] = &AVSepAcct              ; //
f5
-    EndYearVectors  ["DacTaxRsv"              ] = &DacTaxRsv              ; //
f1
+    EndYearVectors  ["DacTaxRsv"              ] = &DacTaxRsv              ; //
f5
EndYearVectors  ["CSVNet"                 ] = &CSVNet                 ; //
f5
EndYearVectors  ["CV7702"                 ] = &CV7702                 ; //
f5
EndYearVectors  ["EOYDeathBft"            ] = &EOYDeathBft            ; //
f5
EndYearVectors  ["PrefLoanBalance"        ] = &PrefLoanBalance        ; //
f5
EndYearVectors  ["TotalLoanBalance"       ] = &TotalLoanBalance       ; //
f5
-    EndYearVectors  ["AvgDeathBft"            ] = &AvgDeathBft            ; //
f1
+    EndYearVectors  ["AvgDeathBft"            ] = &AvgDeathBft            ; //
f5
EndYearVectors  ["SurrChg"                ] = &SurrChg                ; //
f5
EndYearVectors  ["TermPurchased"          ] = &TermPurchased          ; //
f5
EndYearVectors  ["BaseDeathBft"           ] = &BaseDeathBft           ; //
f5

```