Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add Dukes/MacDonald #128

Merged
merged 2 commits into from
Jul 3, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/MortalityTables.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@ include("table_source_map.jl")
include("MetaData.jl")
include("death_distribution.jl")
include("MortalityTable.jl")
include("dukes_macdonald.jl")
include("XTbML.jl")
include("get_SOA_table.jl")
include("parameterized_models.jl")
include("life_expectancy.jl")

table_dirs = Dict(
"mort.soa.org" => artifact"mort.soa.org",
)
)

export MortalityTable,
survival,
Expand All @@ -36,7 +37,7 @@ export MortalityTable,
DeathDistribution,
get_SOA_table,
Makeham, Gompertz, MakehamGompertz,
hazard,cumhazard,
hazard, cumhazard,
mortality_vector

# lazy load part of the package
Expand Down
43 changes: 43 additions & 0 deletions src/dukes_macdonald.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using MortalityTables: SelectUltimateTable

function dukes_macdonald1(point_in_scale::Float64, select_rate::Float64, base_lapses::Float64, total_lapses::Float64, effectiveness::Float64)
excess_lapses = total_lapses - base_lapses
select_excess_lapses = effectiveness * excess_lapses
not_lapses = 1 - total_lapses
deteriorated_rate = (point_in_scale * (select_excess_lapses + not_lapses) - select_excess_lapses * select_rate) / not_lapses
return deteriorated_rate
end

function dukes_macdonald1(selectultimate::SelectUltimateTable, issue_age::Int, attained_age::Int, base_lapses::Float64, total_lapses::Float64, effectiveness::Float64)
point_in_scale = selectultimate.select[issue_age][attained_age]
select_rate = selectultimate.select[attained_age][attained_age]
return dukes_macdonald1(point_in_scale, select_rate, base_lapses, total_lapses, effectiveness)
end

function dukes_macdonald2(point_in_scale::Float64, select_rate::Float64, base_lapses::Float64, total_lapses::Float64, effectiveness::Float64)
excess_lapses = total_lapses - base_lapses
select_excess_lapses = effectiveness * excess_lapses
nonselect_excess_lapses = excess_lapses - select_excess_lapses
not_lapses = 1 - total_lapses
deteriorated_rate = (point_in_scale * (not_lapses + excess_lapses) - select_excess_lapses * select_rate) / (nonselect_excess_lapses + not_lapses)
return deteriorated_rate
end

function dukes_macdonald2(selectultimate::SelectUltimateTable, issue_age::Int, attained_age::Int, base_lapses::Float64, total_lapses::Float64, effectiveness::Float64)
point_in_scale = selectultimate.select[issue_age][attained_age]
select_rate = selectultimate.select[attained_age][attained_age]
return dukes_macdonald2(point_in_scale, select_rate, base_lapses, total_lapses, effectiveness)
end

function dukes_macdonald3(point_in_scale::Float64, select_rate::Float64, base_lapses::Float64, total_lapses::Float64, effectiveness::Float64)
excess_lapses = total_lapses - base_lapses
select_excess_lapses = effectiveness * excess_lapses
deteriorated_rate = (point_in_scale - select_excess_lapses * select_rate) / (1 - select_excess_lapses)
return deteriorated_rate
end

function dukes_macdonald3(selectultimate::SelectUltimateTable, issue_age::Int, attained_age::Int, base_lapses::Float64, total_lapses::Float64, effectiveness::Float64)
point_in_scale = selectultimate.select[issue_age][attained_age]
select_rate = selectultimate.select[attained_age][attained_age]
return dukes_macdonald3(point_in_scale, select_rate, base_lapses, total_lapses, effectiveness)
end
36 changes: 36 additions & 0 deletions test/dukes_macdonald.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
using MortalityTables: SelectUltimateTable, TableMetaData, table, dukes_macdonald1, dukes_macdonald2, dukes_macdonald3

@testset "Dukes/MacDonald" begin
base_lapses = 0.10
total_lapses = 0.85
effectiveness = 0.80
@testset "from newsletter Doll, 2003" begin
select = 0.01
point_in_scale = 0.03
issue_age = 1
attained_age = 2
testSelectUltimate = SelectUltimateTable(
[[0.005, point_in_scale], [nothing, select]], # nothing is like offset array
[0.02, 0.04, 0.05],
TableMetaData()
)
@test 3.67 == round(dukes_macdonald1(testSelectUltimate, issue_age, attained_age, base_lapses, total_lapses, effectiveness) / point_in_scale; digits=2)
@test 2.33 == round(dukes_macdonald2(testSelectUltimate, issue_age, attained_age, base_lapses, total_lapses, effectiveness) / point_in_scale; digits=2)
@test 2.00 == round(dukes_macdonald3(testSelectUltimate, issue_age, attained_age, base_lapses, total_lapses, effectiveness) / point_in_scale; digits=2)
end
@testset "using real data" begin
issue_age = 50
attained_age = 60
tbl = table(3299)
dukes_methods = [
dukes_macdonald1,
dukes_macdonald2,
dukes_macdonald3
]
results = [
dukes_method(tbl, issue_age, attained_age, base_lapses, total_lapses, effectiveness) / tbl.select[attained_age][attained_age]
for dukes_method in dukes_methods
]
@test 1 < results[3] < results[2] < results[1] < 8
end
end
3 changes: 2 additions & 1 deletion test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ include("XTbML.jl")
include("parameterized_models.jl")
include("distribution.jl")
include("life_expectancy.jl")
include("dukes_macdonald.jl")

# load tables to be used in subsequent tests
@test isa(MortalityTables.table(1),MortalityTables.MortalityTable)
@test isa(MortalityTables.table(1), MortalityTables.MortalityTable)

include("projection_scale.jl")
include("MortalityTables.jl")
Expand Down