Loading [MathJax]/extensions/tex2jax.js
MRFFL: MR Fortran Finance Library 2024-12-28
Computational Tools For Finance
All Namespaces Files Functions Variables
mrffl_life_table.f90
Go to the documentation of this file.
1! -*- Mode:F90; Coding:us-ascii-unix; fill-column:129 -*-
2!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.H.S.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!.H.E.!!
3!>
4!! @file mrffl_life_table.f90
5!! @author Mitch Richling http://www.mitchr.me/
6!! @date 2025-01-09
7!! @brief This module provides life table computations, and some US life table data.@EOL
8!! @keywords finance fortran monte carlo inflation cashflow time value of money tvm percentages taxes stock market
9!! @std F2023
10!! @see https://github.com/richmit/FortranFinance
11!! @copyright
12!! @parblock
13!! Copyright (c) 2025, Mitchell Jay Richling <http://www.mitchr.me/> All rights reserved.
14!!
15!! Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following
16!! conditions are met:
17!!
18!! 1. Redistributions of source code must retain the above copyright notice, this list of conditions, and the following
19!! disclaimer.
20!!
21!! 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions, and the following
22!! disclaimer in the documentation and/or other materials provided with the distribution.
23!!
24!! 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products
25!! derived from this software without specific prior written permission.
26!!
27!! THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
28!! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
29!! DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
30!! EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
31!! USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32!! LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
33!! OF THE POSSIBILITY OF SUCH DAMAGE.
34!! @endparblock
35!!
36
37!----------------------------------------------------------------------------------------------------------------------------------
38!> Life table computations, and some US life table data.
39!!
40!! @par Life Table Data
41!! The following tables are provided as public arrays exported from this module:
42!! - @f$ l_x @f$ for males as recorded in the 2021 period life table for the US Social Security Administration.
43!! - @f$ l_x @f$ for females as recorded in the 2021 period life table for the US Social Security Administration.
44!! - @f$ q_x @f$ for males as recorded in the 2021 period life table for the US Social Security Administration.
45!! - @f$ q_x @f$ for females as recorded in the 2021 period life table for the US Social Security Administration.
46!! - @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021, White Females
47!! - @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021, White Males
48!! - @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021, White
49!! - @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021
50!!
51!! @par Computation
52!!
53!! @par `probability_of_death`
54!! @f$ q_x @f$ is the probability that someone aged exactly @f$ x @f$ will die before reaching age @f$ (x+1) @f$.
55!! @f[ q_x = 1 - \frac{l_{x+1}}{l_x} @f]
56!!
57!! @warning
58!! It is common for the value of @f$ q_x @f$ to be adjusted. It is also common for life tables with adjusted @f$ q_x @f$ values
59!! to still report the actual values for @f$ l_x @f$ -- thus making the two columns inconsistent with each other with respect to
60!! the above formula. The 2021 Social Security life table is an example. This module treats this single life table as two
61!! separate, and independent entities -- this allows us to use whichever column is most appropriate for our application.
62!!
63!! @par `probability_of_survival_1`
64!! @f$ p_x @f$ is the probability that someone aged exactly @f$ x @f$ will survive to age @f$ (x+1) @f$.
65!! @f[ p_x = 1 - q_x @f]
66!! @f[ p_x = \frac{l_{x+1}}{l_x} @f]
67!!
68!! @par `cohort_size`
69!! @f$ l_0 @f$ is the number of people in the cohort (sometimes called the "radix").
70!!
71!! @par `survivors` & `age_all_dead`
72!! @f$ l_x @f$ is the number of people who survive to age @f$ x @f$.
73!! @f[ l_x = (1 - q_x)l_{x-1} \text{ with } l_0 \text{ known}@f]
74!!
75!! @par `died`
76!! @f$ d_x @f$ is the number of people who die aged @f$ x @f$ -- i.e. last birthday was age @f$ x @f$.
77!! @f[ d_x = l_x q_x @f]
78!! @f[ d_x = l_x - l_{x+1} @f]
79!!
80!! @par `probability_of_survival_n`
81!! @f$ _tp_x @f$ the probability that someone aged exactly @f$ x @f$ will survive for @f$ t @f$ more years living up to
82!! at least age @f$ x+t @f$.
83!! @f[ _tp_x = \frac{l_{x+t}}{l_x} @f]
84!!
85!! @par `person_years`
86!! @f$ L_x @f$ the total number of person-years lived by the cohort from age @f$ x @f$ to @f$ x+1 @f$.
87!! @f[ L_x = l_{x+1} + \frac{d_x}{2} @f]
88!!
89!! @warning
90!! I like the simple approach of assuming people die uniformly on the time interval. That is to say the average number of years
91!! lived by people who died on the interval was 0.5 years. There are several other methodologies in common use today that do not
92!! make this assumption. The most common approaches are to use some kind of smoothing criteria. For a popular example, see
93!! "Keyfitz N. A life table that agrees with the data. Journal of the American Statistical Association. 1966 Jun 1".
94!!
95!! @par `total_person_years`
96!! @f$ T_x @f$ the total number of person-years lived by the cohort from age @f$ x @f$ until all have died.
97!! @f[ T_x = \sum_{k=x}^\infty L_k @f]
98!!
99!! @par `life_expectancy` & `life_expectancy_at_birth`
100!! @f$ e_x @f$ is the average number of years of life remaining at age @f$ x @f$.
101!! This value is provided directly in our data table, so we do *not* use the approximation below.
102!! @f[ e_x = \frac{T_x}{l_x} @f]
103!!
104!! @par `mortality_rate`
105!! @f$ m_x @f$ is the mortality rate at age @f$ x @f$.
106!! @f[ m_x = \frac{d_x}{L_x} @f]
107!!
108!! @par life_table & cohort parameters
109!! Every function in this library takes `life_table` and `cohort_size` as the last two arguments. These arguments are used in
110!! the same way in all functions, and are documented here:
111!! - `life_table` is a rank 1 array containing life table data enumerated at whole number ages starting at 0 and incrementing by
112!! one for each element. It may contain values for the survival function (number of people alive at the given age) or the
113!! probability_of_death function (the probability of someone at a given age expiring within one year). The upper and lower
114!! bounds are irrelevant; however, it is very important that the first element of the array express the value for the
115!! function at age 0. I normally use a lower bound of zero.
116!! - `cohort_size` is used to identify the type of functional data stored in `life_table`, and to specify the cohort size when
117!! that functional data is the probability_of_death. When `cohort_size <= 0` the `life_table` is assumed to contain the survival
118!! function (in this case the cohort size is the first element of the `life_table` array). When `cohort_size > 0`, the
119!! `life_table` is assumed to contain the probability of death function and the value of `cohort_size` is used to compute the
120!! survival function at age 0 - i.e. it is used as the cohort size.
121!!
123 use mrffl_config, only: rk=>mrfflrk, ik=>mrfflik, zero_epsilon
126 use mrffl_stats, only: rand_int
127 implicit none
128
129 private
130
131 !--------------------------------------------------------------------------------------------------------------------------------
132 !> @f$ l_x @f$ for males as recorded in the 2021 period life table for the US Social Security Administration.
133 !!
134 real(kind=rk), public, parameter :: usss_m_lx_dat(0:119) = [ &
135 100000, 99414, 99372, 99345, 99323, 99304, 99289, 99275, 99262, 99250, &
136 99238, 99225, 99211, 99195, 99173, 99143, 99098, 99035, 98949, 98840, &
137 98715, 98579, 98433, 98275, 98106, 97926, 97734, 97530, 97316, 97089, &
138 96850, 96601, 96342, 96073, 95797, 95512, 95218, 94916, 94603, 94277, &
139 93937, 93582, 93211, 92825, 92423, 92003, 91564, 91100, 90608, 90083, &
140 89523, 88926, 88289, 87606, 86874, 86089, 85248, 84347, 83386, 82361, &
141 81272, 80112, 78882, 77582, 76215, 74786, 73296, 71749, 70141, 68468, &
142 66732, 64927, 63046, 61080, 59018, 56849, 54543, 52126, 49598, 46958, &
143 44198, 41342, 38409, 35420, 32385, 29314, 26234, 23175, 20178, 17298, &
144 14571, 12029, 9707, 7640, 5863, 4386, 3198, 2271, 1572, 1060, &
145 698, 448, 279, 169, 99, 56, 30, 16, 8, 4, &
146 2, 1, 0, 0, 0, 0, 0, 0, 0, 0]
147
148 !--------------------------------------------------------------------------------------------------------------------------------
149 !> @f$ l_x @f$ for females as recorded in the 2021 period life table for the US Social Security Administration.
150 !!
151 real(kind=rk), public, parameter :: usss_f_lx_dat(0:119) = [ &
152 100000, 99494, 99455, 99432, 99415, 99400, 99388, 99378, 99367, 99358, &
153 99348, 99338, 99327, 99314, 99298, 99279, 99256, 99227, 99192, 99150, &
154 99105, 99055, 98999, 98939, 98873, 98802, 98725, 98643, 98555, 98462, &
155 98361, 98252, 98135, 98008, 97873, 97730, 97579, 97420, 97252, 97075, &
156 96887, 96687, 96474, 96247, 96008, 95756, 95489, 95203, 94897, 94568, &
157 94215, 93837, 93433, 93000, 92537, 92040, 91503, 90924, 90303, 89635, &
158 88915, 88142, 87313, 86427, 85490, 84502, 83470, 82389, 81248, 80041, &
159 78758, 77393, 75934, 74369, 72686, 70872, 68895, 66764, 64485, 62059, &
160 59469, 56714, 53803, 50741, 47530, 44170, 40672, 37065, 33386, 29698, &
161 26043, 22471, 19042, 15814, 12847, 10192, 7890, 5956, 4385, 3149, &
162 2208, 1509, 1003, 646, 402, 241, 139, 77, 40, 20, &
163 9, 4, 2, 1, 0, 0, 0, 0, 0, 0]
164
165 !--------------------------------------------------------------------------------------------------------------------------------
166 !> @f$ q_x @f$ for males as recorded in the 2021 period life table for the US Social Security Administration.
167 !! cohort_size=100000
168 !!
169 real(kind=rk), public, parameter :: usss_m_qx_dat(0:119) = [ &
170 0.0058600, 0.0004200, 0.0002720, 0.0002250, 0.0001840, 0.0001570, 0.0001400, 0.0001280, 0.0001220, 0.0001230, &
171 0.0001290, 0.0001380, 0.0001640, 0.0002200, 0.0003100, 0.0004460, 0.0006370, 0.0008680, 0.0011000, 0.0012700, &
172 0.0013730, 0.0014880, 0.0016050, 0.0017140, 0.0018350, 0.0019630, 0.0020820, 0.0022020, 0.0023300, 0.0024570, &
173 0.0025740, 0.0026830, 0.0027870, 0.0028810, 0.0029740, 0.0030740, 0.0031750, 0.0032950, 0.0034440, 0.0036080, &
174 0.0037800, 0.0039580, 0.0041440, 0.0043370, 0.0045400, 0.0047740, 0.0050640, 0.0053990, 0.0057960, 0.0062140, &
175 0.0066710, 0.0071670, 0.0077360, 0.0083510, 0.0090350, 0.0097700, 0.0105670, 0.0113980, 0.0122910, 0.0132240, &
176 0.0142670, 0.0153530, 0.0164840, 0.0176170, 0.0187590, 0.0199140, 0.0211040, 0.0224230, 0.0238470, 0.0253570, &
177 0.0270500, 0.0289700, 0.0311880, 0.0337540, 0.0367470, 0.0405630, 0.0443080, 0.0484980, 0.0532290, 0.0587780, &
178 0.0646170, 0.0709470, 0.0778340, 0.0856860, 0.0948090, 0.1050900, 0.1165920, 0.1293060, 0.1427320, 0.1576380, &
179 0.1744580, 0.1930270, 0.2129300, 0.2326570, 0.2518260, 0.2709430, 0.2897560, 0.3079980, 0.3253930, 0.3416620, &
180 0.3587460, 0.3766830, 0.3955170, 0.4152930, 0.4360580, 0.4578600, 0.4807530, 0.5047910, 0.5300310, 0.5565320, &
181 0.5843590, 0.6135770, 0.6442560, 0.6764680, 0.7102920, 0.7458060, 0.7830970, 0.8222510, 0.8633640, 0.9065320]
182
183 !--------------------------------------------------------------------------------------------------------------------------------
184 !> @f$ q_x @f$ for females as recorded in the 2021 period life table for the US Social Security Administration.
185 !! cohort_size=100000
186 !!
187 real(kind=rk), public, parameter :: usss_f_qx_dat(0:119) = [ &
188 0.0050630, 0.0003930, 0.0002230, 0.0001770, 0.0001440, 0.0001220, 0.0001090, 0.0001020, 0.0000980, 0.0000970, &
189 0.0001030, 0.0001130, 0.0001310, 0.0001570, 0.0001900, 0.0002330, 0.0002910, 0.0003550, 0.0004180, 0.0004610, &
190 0.0005070, 0.0005560, 0.0006100, 0.0006660, 0.0007220, 0.0007750, 0.0008310, 0.0008890, 0.0009520, 0.0010250, &
191 0.0011040, 0.0011920, 0.0012890, 0.0013830, 0.0014650, 0.0015440, 0.0016260, 0.0017190, 0.0018240, 0.0019400, &
192 0.0020660, 0.0022020, 0.0023510, 0.0024820, 0.0026220, 0.0027890, 0.0029940, 0.0032190, 0.0034670, 0.0037290, &
193 0.0040110, 0.0043060, 0.0046340, 0.0049810, 0.0053700, 0.0058310, 0.0063260, 0.0068370, 0.0073990, 0.0080330, &
194 0.0086870, 0.0094110, 0.0101390, 0.0108490, 0.0115500, 0.0122160, 0.0129520, 0.0138440, 0.0148630, 0.0160280, &
195 0.0173290, 0.0188590, 0.0206090, 0.0226200, 0.0249580, 0.0279060, 0.0309250, 0.0341400, 0.0376200, 0.0417250, &
196 0.0463240, 0.0513340, 0.0569110, 0.0632790, 0.0707040, 0.0791840, 0.0886970, 0.0992400, 0.1104800, 0.1230780, &
197 0.1371520, 0.1526050, 0.1694940, 0.1876230, 0.2066470, 0.2258900, 0.2450540, 0.2638150, 0.2818280, 0.2987380, &
198 0.3166620, 0.3356620, 0.3558020, 0.3771500, 0.3997790, 0.4237660, 0.4491920, 0.4761430, 0.5047120, 0.5349940, &
199 0.5670940, 0.6011200, 0.6371870, 0.6754180, 0.7102920, 0.7458060, 0.7830970, 0.8222510, 0.8633640, 0.9065320]
200
201 !--------------------------------------------------------------------------------------------------------------------------------
202 !> @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021, White Females
203 !!
204 real(kind=rk), public, parameter :: uscdc_w_f_lx_dat(0:100) = [ &
205 100000, 99594, 99565, 99547, 99536, 99526, 99517, 99509, 99501, 99494, &
206 99487, 99480, 99472, 99463, 99450, 99433, 99410, 99383, 99351, 99314, &
207 99273, 99227, 99176, 99120, 99059, 98992, 98920, 98843, 98759, 98667, &
208 98566, 98457, 98339, 98212, 98077, 97933, 97781, 97619, 97447, 97265, &
209 97074, 96871, 96655, 96426, 96185, 95929, 95658, 95368, 95057, 94725, &
210 94371, 93996, 93596, 93169, 92709, 92213, 91680, 91110, 90497, 89837, &
211 89127, 88364, 87548, 86684, 85779, 84833, 83844, 82800, 81693, 80509, &
212 79235, 77876, 76421, 74863, 73179, 71381, 69377, 67214, 64874, 62393, &
213 59748, 56950, 54018, 50925, 47681, 44270, 40716, 37095, 33384, 29635, &
214 25909, 22273, 18795, 15540, 12566, 9919, 7628, 5706, 4143, 2915, &
215 1985]
216
217 !--------------------------------------------------------------------------------------------------------------------------------
218 !> @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021, White Males
219 !!
220 real(kind=rk), public, parameter :: uscdc_w_m_lx_dat(0:100) = [ &
221 100000, 99532, 99493, 99466, 99443, 99426, 99411, 99397, 99384, 99373, &
222 99363, 99353, 99342, 99327, 99304, 99270, 99225, 99168, 99099, 99016, &
223 98921, 98812, 98689, 98552, 98402, 98239, 98066, 97880, 97682, 97470, &
224 97246, 97008, 96757, 96495, 96223, 95942, 95652, 95351, 95041, 94719, &
225 94385, 94038, 93675, 93296, 92902, 92492, 92062, 91608, 91124, 90609, &
226 90060, 89478, 88860, 88199, 87490, 86725, 85903, 85026, 84088, 83084, &
227 82013, 80874, 79670, 78407, 77091, 75722, 74301, 72810, 71249, 69611, &
228 67896, 66113, 64254, 62304, 60243, 58093, 55744, 53282, 50670, 47963, &
229 45115, 42200, 39199, 36136, 33021, 29850, 26717, 23576, 20479, 17483, &
230 14643, 12011, 9630, 7534, 5740, 4252, 3056, 2129, 1434, 934, &
231 587]
232
233 !--------------------------------------------------------------------------------------------------------------------------------
234 !> @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021, White
235 !!
236 real(kind=rk), public, parameter :: uscdc_w_lx_dat(0:100) = [ &
237 100000, 99562, 99527, 99505, 99488, 99475, 99463, 99451, 99441, 99432, &
238 99423, 99415, 99406, 99393, 99375, 99349, 99315, 99273, 99221, 99161, &
239 99092, 99014, 98926, 98828, 98721, 98606, 98482, 98349, 98206, 98053, &
240 97889, 97714, 97528, 97333, 97128, 96914, 96691, 96458, 96215, 95962, &
241 95697, 95420, 95128, 94822, 94502, 94167, 93814, 93439, 93039, 92613, &
242 92158, 91675, 91162, 90613, 90024, 89388, 88706, 87978, 87197, 86360, &
243 85464, 84506, 83490, 82419, 81301, 80137, 78925, 77650, 76310, 74893, &
244 73392, 71814, 70151, 68390, 66512, 64531, 62348, 60029, 57547, 54948, &
245 52197, 49338, 46371, 43294, 40117, 36832, 33508, 30123, 26725, 23367, &
246 20105, 16996, 14093, 11443, 9082, 7035, 5308, 3895, 2775, 1918, &
247 1283]
248
249 !--------------------------------------------------------------------------------------------------------------------------------
250 !> @f$ l_x @f$ from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables, 2021
251 !!
252 real(kind=rk), public, parameter :: uscdc_lx_dat(0:100) = [ &
253 100000, 99455, 99415, 99390, 99371, 99355, 99341, 99328, 99316, 99305, &
254 99296, 99287, 99277, 99264, 99243, 99214, 99173, 99123, 99061, 98988, &
255 98906, 98812, 98706, 98591, 98467, 98335, 98197, 98052, 97899, 97737, &
256 97566, 97386, 97196, 96998, 96792, 96577, 96354, 96122, 95880, 95627, &
257 95363, 95084, 94792, 94484, 94162, 93824, 93468, 93091, 92690, 92261, &
258 91803, 91316, 90797, 90241, 89644, 89000, 88309, 87570, 86778, 85928, &
259 85017, 84042, 83005, 81912, 80767, 79571, 78325, 77015, 75640, 74193, &
260 72671, 71078, 69405, 67644, 65776, 63810, 61658, 59380, 56945, 54396, &
261 51702, 48904, 45995, 42987, 39882, 36667, 33399, 30073, 26734, 23433, &
262 20222, 17157, 14288, 11660, 9310, 7260, 5520, 4086, 2940, 2053, &
263 1390]
264
265 public :: life_table_print
268 public :: life_expectancy, rand_age
270
271contains
272
273 !--------------------------------------------------------------------------------------------------------------------------------
274 !> Return @f$ l_x @f$ for the given age. See the module documentation for a guide to symbols.
275 !!
276 !! @param age Age of the person.
277 !! @param life_table Data for life table. See module documentation for description.
278 !! @param cohort_size Number of people in the cohort. See module documentation for description.
279 !!
280 real(kind=rk) pure function survivors(age, life_table, cohort_size)
281 implicit none
282 integer(kind=ik), intent(in) :: age, cohort_size
283 real(kind=rk), intent(in) :: life_table(:)
284 integer(kind=ik) :: i
285 if (age > size(life_table)-1) then
286 survivors = 0
287 else
288 if (cohort_size <= 0) then ! life_table contains lx
289 if (age <= 0) then
290 survivors = life_table(1)
291 else
292 survivors = life_table(age+1)
293 end if
294 else
295 if (age <= 0) then
296 survivors = cohort_size
297 else
298 survivors = cohort_size
299 do i=2,min(age+1_ik, size(life_table, kind=ik))
300 survivors = (1_ik - life_table(i-1)) * survivors
301 end do
302 end if
303 end if
304 end if
305 end function survivors
306
307 !--------------------------------------------------------------------------------------------------------------------------------
308 !> Return @f$ q_x @f$ for the given age. See the module documentation for a guide to symbols.
309 !!
310 !! @param age Age of the person.
311 !! @param life_table Data for life table. See module documentation for description.
312 !! @param cohort_size Number of people in the cohort. See module documentation for description.
313 !!
314 real(kind=rk) pure function probability_of_death(age, life_table, cohort_size)
315 implicit none
316 integer(kind=ik), intent(in) :: age, cohort_size
317 real(kind=rk), intent(in) :: life_table(:)
318 real(kind=rk) :: tmp1
319 if (age < 0) then
321 else if (age > size(life_table)-1) then
323 else
324 if (cohort_size <= 0) then ! life_table contains lx
325 if (age == size(life_table)-1) then
327 else
328 tmp1 = life_table(age+1)
329 if (abs(tmp1) < zero_epsilon) then
331 else
332 probability_of_death = 1 - life_table(age+2) / tmp1
333 end if
334 end if
335 else
336 probability_of_death = life_table(age+1)
337 end if
338 end if
339 end function probability_of_death
340
341 !--------------------------------------------------------------------------------------------------------------------------------
342 !> Return @f$ e_x @f$ for the given age. See the module documentation for a guide to symbols.
343 !!
344 !! @param age Age of the person.
345 !! @param life_table Data for life table. See module documentation for description.
346 !! @param cohort_size Number of people in the cohort. See module documentation for description.
347 !!
348 real(kind=rk) pure function life_expectancy(age, life_table, cohort_size)
349 implicit none
350 integer(kind=ik), intent(in) :: age, cohort_size
351 real(kind=rk), intent(in) :: life_table(:)
352 real(kind=rk) :: tmp1
353 tmp1 = survivors(age, life_table, cohort_size)
354 if (abs(tmp1) < zero_epsilon) then
356 else
357 life_expectancy = total_person_years(age, life_table, cohort_size) / tmp1
358 end if
359 end function life_expectancy
360
361 !--------------------------------------------------------------------------------------------------------------------------------
362 !> Return @f$ e_0 @f$. See the module documentation for a guide to symbols.
363 !!
364 !! @param life_table Data for life table. See module documentation for description.
365 !! @param cohort_size Number of people in the cohort. See module documentation for description.
366 !!
367 real(kind=rk) pure function life_expectancy_at_birth(life_table, cohort_size)
368 implicit none
369 integer(kind=ik), intent(in) :: cohort_size
370 real(kind=rk), intent(in) :: life_table(:)
371 life_expectancy_at_birth = life_expectancy(0_ik, life_table, cohort_size)
372 end function life_expectancy_at_birth
373
374 !--------------------------------------------------------------------------------------------------------------------------------
375 !> Return @f$ _tp_x @f$ for the given age. See the module documentation for a guide to symbols.
376 !!
377 !! @param age Age of the person.
378 !! @param n Number of years. Must be non-negative.
379 !! @param life_table Data for life table. See module documentation for description.
380 !! @param cohort_size Number of people in the cohort. See module documentation for description.
381 !!
382 real(kind=rk) pure function probability_of_survival_n(age, n, life_table, cohort_size)
383 implicit none
384 integer(kind=ik), intent(in) :: age, n, cohort_size
385 real(kind=rk), intent(in) :: life_table(:)
386 real(kind=rk) :: tmp1
387 tmp1 = survivors(age, life_table, cohort_size)
388 if (abs(tmp1) < zero_epsilon) then
390 else
391 probability_of_survival_n = survivors(age+n, life_table, cohort_size) / tmp1
392 end if
393 end function probability_of_survival_n
394
395 !--------------------------------------------------------------------------------------------------------------------------------
396 !> Return @f$ p_x @f$ for the given age. See the module documentation for a guide to symbols.
397 !!
398 !! @param age Age of the person.
399 !! @param life_table Data for life table. See module documentation for description.
400 !! @param cohort_size Number of people in the cohort. See module documentation for description.
401 !!
402 real(kind=rk) pure function probability_of_survival_1(age, life_table, cohort_size)
403 implicit none
404 integer(kind=ik), intent(in) :: age, cohort_size
405 real(kind=rk), intent(in) :: life_table(:)
406 probability_of_survival_1 = probability_of_survival_n(age, 1_ik, life_table, cohort_size)
407 end function probability_of_survival_1
408
409 !--------------------------------------------------------------------------------------------------------------------------------
410 !> Return @f$ d_x @f$ for the given age. See the module documentation for a guide to symbols.
411 !!
412 !! @param age Age of the person.
413 !! @param life_table Data for life table. See module documentation for description.
414 !! @param cohort_size Number of people in the cohort. See module documentation for description.
415 !!
416 real(kind=rk) pure function died(age, life_table, cohort_size)
417 implicit none
418 integer(kind=ik), intent(in) :: age, cohort_size
419 real(kind=rk), intent(in) :: life_table(:)
420 died = survivors(age, life_table, cohort_size) - survivors(age+1_ik, life_table, cohort_size)
421 end function died
422
423 !--------------------------------------------------------------------------------------------------------------------------------
424 !> Return @f$ L_x @f$ for the given age. See the module documentation for a guide to symbols.
425 !!
426 !! @param age Age of the person.
427 !! @param life_table Data for life table. See module documentation for description.
428 !! @param cohort_size Number of people in the cohort. See module documentation for description.
429 !!
430 real(kind=rk) pure function person_years(age, life_table, cohort_size)
431 implicit none
432 integer(kind=ik), intent(in) :: age, cohort_size
433 real(kind=rk), intent(in) :: life_table(:)
434 real(kind=rk), parameter :: ax = 0.5
435 real(kind=rk) :: tmp1
436 tmp1 = survivors(age+1_ik, life_table, cohort_size)
437 person_years = tmp1 + ax * (survivors(age, life_table, cohort_size) - tmp1)
438 end function person_years
439
440 !--------------------------------------------------------------------------------------------------------------------------------
441 !> Return @f$ T_x @f$ for the given age. See the module documentation for a guide to symbols.
442 !!
443 !! @param age Age of the person.
444 !! @param life_table Data for life table. See module documentation for description.
445 !! @param cohort_size Number of people in the cohort. See module documentation for description.
446 !!
447 real(kind=rk) pure function total_person_years(age, life_table, cohort_size)
448 implicit none
449 integer(kind=ik), intent(in) :: age, cohort_size
450 real(kind=rk), intent(in) :: life_table(:)
451 integer(kind=ik) :: i
453 do i=age,size(life_table, kind=ik)-1_ik
454 total_person_years = total_person_years + person_years(i, life_table, cohort_size)
455 end do
456 end function total_person_years
457
458 !--------------------------------------------------------------------------------------------------------------------------------
459 !> Return @f$ m_x @f$ for the given age. See the module documentation for a guide to symbols.
460 !!
461 !! @param age Age of the person.
462 !! @param life_table Data for life table. See module documentation for description.
463 !! @param cohort_size Number of people in the cohort. See module documentation for description.
464 !!
465 real(kind=rk) pure function mortality_rate(age, life_table, cohort_size)
466 implicit none
467 integer(kind=ik), intent(in) :: age, cohort_size
468 real(kind=rk), intent(in) :: life_table(:)
469 real(kind=rk) :: tmp1
470 tmp1 = person_years(age, life_table, cohort_size)
471 if (abs(tmp1) < zero_epsilon) then
473 else
474 mortality_rate = died(age, life_table, cohort_size) / tmp1
475 end if
476 end function mortality_rate
477
478 !--------------------------------------------------------------------------------------------------------------------------------
479 !> Return lowest age for which @f$ l_x=0 @f$. See the module documentation for a guide to symbols.
480 !!
481 !! This function is super slow.
482 !!
483 !! @param life_table Data for life table. See module documentation for description.
484 !! @param cohort_size Number of people in the cohort. See module documentation for description.
485 !!
486 real(kind=rk) pure function age_all_dead(life_table, cohort_size)
487 implicit none
488 integer(kind=ik), intent(in) :: cohort_size
489 real(kind=rk), intent(in) :: life_table(:)
490 integer(kind=ik) :: i
491 age_all_dead = 0
492 do i=0,size(life_table, kind=ik)-1_ik
493 if (abs(survivors(i, life_table, cohort_size)) <= zero_epsilon) then
494 age_all_dead = i
495 return
496 end if
497 end do
498 end function age_all_dead
499
500 !--------------------------------------------------------------------------------------------------------------------------------
501 !> Return random age for death given current age and life_table.
502 !!
503 !! This function is super slow.
504 !!
505 !! @param age Age of the person.
506 !! @param life_table Data for life table. See module documentation for description.
507 !! @param cohort_size Number of people in the cohort. See module documentation for description.
508 !!
509 integer(kind=ik) function rand_age(age, life_table, cohort_size)
510 implicit none
511 integer(kind=ik), intent(in) :: age, cohort_size
512 real(kind=rk), intent(in) :: life_table(:)
513 integer(kind=ik) :: i, r
514 r = rand_int(floor(survivors(age, life_table, cohort_size), kind=ik))
515 do i=age,size(life_table, kind=ik)-1_ik
516 if (floor(survivors(i, life_table, cohort_size)) <= r) then
517 rand_age = i
518 return
519 end if
520 end do
521 rand_age = size(life_table, kind=ik)-1_ik
522 end function rand_age
523
524 !--------------------------------------------------------------------------------------------------------------------------------
525 !> Print life table.
526 !!
527 !! An ERROR STOP occures if a WRITE causes an I/O error
528 !!
529 !! @param out_io_unit Unit to which to print table
530 !! @param print_out Bitset built from the following constants prt_title, prt_table, & prt_space
531 !! @param life_table Data for life table. See module documentation for description.
532 !! @param cohort_size Number of people in the cohort. See module documentation for description.
533 !!
534 subroutine life_table_print(out_io_unit, print_out, life_table, cohort_size)
535 implicit none
536 integer(kind=ik), intent(in) :: cohort_size, print_out
537 real(kind=rk), intent(in) :: life_table(:)
538 integer, intent(in) :: out_io_unit
539 integer(kind=ik) :: age
540 character(len=:), allocatable :: fmt_t, fmt_n
541 integer :: out_io_stat
542 fmt_t = '(a5,a11, a11, a10, a11, a12, a8, a11, a11 )'
543 fmt_n = '(i5,f11.7,f11.2,f10.2,f11.2,f12.2,f8.2,f11.7,f11.7)'
544 if (bitset_subsetp(prt_space, print_out)) then
545 write (unit=out_io_unit, iostat=out_io_stat, fmt='(a)') ""
546 if (out_io_stat /= 0) error stop "ERROR(life_table_print): I/O Error!"
547 end if
548 if (bitset_subsetp(prt_title, print_out)) then
549 write (unit=out_io_unit, iostat=out_io_stat, fmt=fmt_t) &
550 "age", "qx", "lx", "dx", "Lx", "Tx", "ex", "mx", "px"
551 if (out_io_stat /= 0) error stop "ERROR(life_table_print): I/O Error!"
552 end if
553 if (bitset_subsetp(prt_table, print_out)) then
554 do age=0,size(life_table, kind=ik)-1_ik
555 write (unit=out_io_unit, iostat=out_io_stat, fmt=fmt_n) &
556 age, &
557 probability_of_death(age, life_table, cohort_size), &
558 survivors(age, life_table, cohort_size), &
559 died(age, life_table, cohort_size), &
560 person_years(age, life_table, cohort_size), &
561 total_person_years(age, life_table, cohort_size), &
562 life_expectancy(age, life_table, cohort_size), &
563 mortality_rate(age, life_table, cohort_size), &
564 probability_of_survival_1(age, life_table, cohort_size)
565 if (out_io_stat /= 0) error stop "ERROR(life_table_print): I/O Error!"
566 end do
567 end if
568 if (bitset_subsetp(prt_space, print_out)) then
569 write (unit=out_io_unit, iostat=out_io_stat, fmt='(a)') ""
570 if (out_io_stat /= 0) error stop "ERROR(life_table_print): I/O Error!"
571 end if
572 end subroutine life_table_print
573
574end module mrffl_life_table
Simple sets (using the bits of an integer to indicate element existence).
logical pure function, public bitset_subsetp(bitset1, bitset2)
Configuration for MRFFL (MR Fortran Finance Library).
integer, parameter, public mrfflrk
Real kind used in interfaces.
real(kind=mrfflrk), parameter, public zero_epsilon
Used to test for zero.
integer, parameter, public mrfflik
Integer kinds used in interfaces.
Life table computations, and some US life table data.
real(kind=rk), dimension(0:100), parameter, public uscdc_w_lx_dat
from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables,...
real(kind=rk), dimension(0:119), parameter, public usss_f_qx_dat
for females as recorded in the 2021 period life table for the US Social Security Administration.
real(kind=rk), dimension(0:100), parameter, public uscdc_w_m_lx_dat
from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables,...
real(kind=rk), dimension(0:100), parameter, public uscdc_w_f_lx_dat
from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables,...
real(kind=rk) pure function, public life_expectancy(age, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public person_years(age, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public mortality_rate(age, life_table, cohort_size)
Return for the given age.
real(kind=rk), dimension(0:119), parameter, public usss_m_lx_dat
for males as recorded in the 2021 period life table for the US Social Security Administration.
real(kind=rk) pure function, public probability_of_death(age, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public total_person_years(age, life_table, cohort_size)
Return for the given age.
real(kind=rk), dimension(0:119), parameter, public usss_f_lx_dat
for females as recorded in the 2021 period life table for the US Social Security Administration.
integer(kind=ik) function, public rand_age(age, life_table, cohort_size)
Return random age for death given current age and life_table.
real(kind=rk) pure function, public survivors(age, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public life_expectancy_at_birth(life_table, cohort_size)
Return .
real(kind=rk), dimension(0:100), parameter, public uscdc_lx_dat
from National Vital Statistics Reports, Volume 72, Number 12, United States Life Tables,...
real(kind=rk) pure function, public probability_of_survival_n(age, n, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public died(age, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public probability_of_survival_1(age, life_table, cohort_size)
Return for the given age.
real(kind=rk) pure function, public age_all_dead(life_table, cohort_size)
Return lowest age for which .
subroutine, public life_table_print(out_io_unit, print_out, life_table, cohort_size)
Print life table.
real(kind=rk), dimension(0:119), parameter, public usss_m_qx_dat
for males as recorded in the 2021 period life table for the US Social Security Administration.
Constants to select what *_print subroutines will print.
integer(kind=ik), parameter, public prt_table
Print a table.
integer(kind=ik), parameter, public prt_title
Print titles on the tables.
integer(kind=ik), parameter, public prt_space
Print vertical whitespace between parameters & table/titles & totals.
Some statstical utilities supporting other MRFFL modules.
integer(kind=ik) function, public rand_int(upper_bound, optional_lower_bound)
Return random integer in U([optional_lower_bound,upper_bound)) – optional_lower_bound is 0 if missing...