モデル3 - ベース計算クラス¶
複数商品を管理し、またEV(エンベデッドヴァリュー)の計算ができる本格的なモデルです。
チュートリアル3 で説明しています。
このファイルでは、各商品の共通のロジックを記述しています。
ベース計算クラス¶
// ベース計算クラス
abstract calculation Base {
// ユーティリティ関数
module Util{
int max_x = 130
int max_t = 100
}
// P基礎基数
module CT_P{
@range = x
@range_last = Util.max_x
string sex = Inf.get_string("sex")
double CIR = NotImplemented
double[] qx = NotImplemented
double[] lx = if (x == 0) { 1.0 }
else { Utl.max(lx(x-1) - d_x(x-1), 0.0) }
double[] d_x = lx(x) * qx(x)
double v = 1.0 / (1.0 + CIR)
double[] vx = if(x == 0) { 1.0 }
else { vx(x-1) * v }
double[] Dx = lx(x) * vx(x)
double[] Cx = d_x(x) * vx(x) * v ^ 0.5
double[] Nx =
if (x >= Util.max_x) { Dx(x) }
else { Dx(x) + Nx(x+1) }
double[] Mx =
if (x >= Util.max_x) { Cx(x) }
else { Cx(x) + Mx(x + 1) }
// 終身年金現価
function double annuity_x(int x) =
if (Dx(x) <= 0) { 0.0 }
else { Nx(x) / Dx(x) }
// 終身年金現価(月単位支払)
function double annuity_x_12(int x) =
if (Dx(x) <= 0) { 0.0 }
else { annuity_x(x) - (12.0 - 1.0)/(2.0 * 12.0) }
// n年支払年金現価
function double annuity_xn(int x, int n) =
if (Dx(x) <= 0 || n < 0) { 0.0 }
else { (Nx(x) - Nx(x + n)) / Dx(x) }
// n年支払年金現価(月単位支払)
function double annuity_xn_12(int x, int n) =
if (Dx(x) <= 0 || n < 0) { 0.0 }
else { annuity_xn(x, n) - (12.0 - 1.0)/(2.0 * 12.0) * (1.0 - Dx(x+n) / Dx(x)) }
}
// V基礎基数
module CT_V{
@range = x
@range_last = Util.max_x
string sex = Inf.get_string("sex")
double CIR = NotImplemented
double[] qx = NotImplemented
double[] lx = if (x == 0) { 1.0 }
else { Utl.max(lx(x-1) - d_x(x-1), 0.0) }
double[] d_x = lx(x) * qx(x)
double v = 1.0 / (1.0 + CIR)
double[] vx = if(x == 0) { 1.0 }
else { vx(x-1) * v }
double[] Dx = lx(x) * vx(x)
double[] Cx = d_x(x) * vx(x) * v ^ 0.5
double[] Nx =
if (x >= Util.max_x) { Dx(x) }
else { Dx(x) + Nx(x+1) }
double[] Mx =
if (x >= Util.max_x) { Cx(x) }
else { Cx(x) + Mx(x + 1) }
// 終身年金現価
function double annuity_x(int x) =
if (Dx(x) <= 0) { 0.0 }
else { Nx(x) / Dx(x) }
// 終身年金現価(月単位支払)
function double annuity_x_12(int x) =
if (Dx(x) <= 0) { 0.0 }
else { annuity_x(x) - (12.0 - 1.0)/(2.0 * 12.0) }
// n年支払年金現価
function double annuity_xn(int x, int n) =
if (Dx(x) <= 0 || n < 0) { 0.0 }
else { (Nx(x) - Nx(x + n)) / Dx(x) }
// n年支払年金現価(月単位支払)
function double annuity_xn_12(int x, int n) =
if (Dx(x) <= 0 || n < 0) { 0.0 }
else { annuity_xn(x, n) - (12.0 - 1.0)/(2.0 * 12.0) * (1.0 - Dx(x+n) / Dx(x)) }
}
// レート計算
module Rate{
@range = t
@range_last = Util.max_t
int x = Inf.get_int("x")
int n = Inf.get_int("n")
int m = Inf.get_int("m")
string sex = Inf.get_string("sex")
double grossP = NotImplemented
double baseP = NotImplemented
double netP_P = NotImplemented
double netP_V = NotImplemented
double[] CV = NotImplemented
double[] netV_P = NotImplemented
double[] netV_V = NotImplemented
double[] azilV_V = NotImplemented
}
// キャッシュフロー
module CashFlow{
@range = t
@range_last = Util.max_t
// インフォース項目
string plan = Inf.get_string("plan")
int x = Inf.get_int("x")
int n = Inf.get_int("n")
int m = Inf.get_int("m")
string sex = Inf.get_string("sex")
double S = Inf.get_double("S")
// 前提 ----------
// 死亡率・解約率・選択効果
double[] qx_crude = NotImplemented
double[] qwx_crude = NotImplemented
double[] selection_factor = NotImplemented
// コミッション
double comm_ratio_first = NotImplemented
double comm_ratio_recur = NotImplemented
double comm_ratio_year = NotImplemented
// 給付の定義
double[] death_benefit_perS = NotImplemented
double[] surrender_benefit_perS = NotImplemented
double[] endow_benefit_perS = NotImplemented
// ユニットコスト
double expense_acq_perN = NotImplemented
double expense_acq_perS = NotImplemented
double expense_acq_perP = NotImplemented
double expense_maint_paying_perS = NotImplemented
double expense_maint_paying_perN = NotImplemented
double expense_maint_paid_perS = NotImplemented
double expense_maint_paid_perN = NotImplemented
double expense_maint_perP = NotImplemented
// ショック(リスク量)
double mort_shock = if ($shock == 1) { 0.15 }
elseif($shock == 2) { -0.20 }
else { 0.0 }
double lapse_shock = if ($shock == 3) { 0.50 }
elseif($shock == 4) { -0.50 }
else { 0.0 }
double morb_shock = if ($shock == 5) { 0.25 }
else { 0.0 }
double expense_shock = if ($shock == 6) { 0.10 }
else { 0.0 }
// ショック(追加でショックを与えたい場合)
double mort_shock_ex = Asm.get_double("mort_shock_ex")
double lapse_shock_ex = Asm.get_double("lapse_shock_ex")
double morb_shock_ex = Asm.get_double("morb_shock_ex")
double expense_shock_ex = Asm.get_double("expense_shock_ex")
// 金利・税率
double[] investment_yield = Asm2d.get_double("int_rate", $scenario, t)
double[] discount_yield = investment_yield(t)
double tax_rate = Asm.get_double("tax_rate")
// 生命表 ----------
double[] qx_base = if (t == 0 || t > n) { 0.0 }
elseif (qx_crude(t) >= 1.0 ) { 1.0 }
else { Utl.clip(qx_crude(t) * selection_factor(t) * (1.0 + mort_shock_ex), 0.0, 1.0) }
double[] qwx_base = if (t == 0 || t > n) { 0.0 }
else { Utl.clip(qwx_crude(t) * (1.0 + lapse_shock_ex), 0.0, 1.0) }
double[] qx = if (qx_base(t) >= 1.0) { 1.0 }
else { Utl.clip(qx_base(t) * (1.0 + mort_shock), 0.0, 1.0) }
double[] qwx = Utl.clip(qwx_base(t) * (1.0 + lapse_shock), 0.0, 1.0)
double[] lx_beg = if (t == 0) { 0.0 }
else { lx_end_after_mat(t - 1) }
double[] lx_mid = if (t == 0) { 0.0 }
else { (lx_beg(t) + lx_end(t)) / 2.0 }
double[] lx_pay = if (t <= m) { lx_beg(t) }
else { 0.0 }
double[] lx_end = if (t == 0) { 1.0 }
else { Utl.max(lx_beg(t) - d_x(t) - dwx(t), 0.0) }
double[] lx_end_after_mat = if (t >= n) { 0.0 }
else { lx_end(t) }
double[] d_x = if (t == 0) { 0.0 }
else { lx_beg(t) * qx(t) * (1.0 - qwx(t) / 2.0) }
double[] dwx = if (t == 0) { 0.0 }
else { lx_beg(t) * qwx(t) * (1.0 - qx(t) / 2.0) }
// キャッシュフロー項目 ----------
double[] premium_income = lx_pay(t) * Rate.grossP * S
double[] commission = if (t == 0) { 0.0 }
elseif (t == 1) { premium_income(t) * comm_ratio_first }
elseif (t <= comm_ratio_year) { premium_income(t) * comm_ratio_recur }
else { 0.0 }
double[] death_benefit = d_x(t) * S * death_benefit_perS(t)
double[] surrender_benefit = dwx(t) * S * surrender_benefit_perS(t)
double[] endow_benefit = lx_end(t) * S * endow_benefit_perS(t)
double[] medical_benefit = 0.0
double[] annuity_benefit = 0.0
double[] unpaid_cashout = 0.0
// (事業費支出の内訳項目)---
double[] init_expense_S = if (t == 1) { lx_beg(t) * S * expense_acq_perS }
else { 0.0 }
double[] init_expense_P = if (t == 1) { premium_income(t) * expense_acq_perP }
else { 0.0 }
double[] maint_expense_S = if (t == 0 || t > n) { 0.0 }
elseif (t <= m) { lx_mid(t) * S * expense_maint_paying_perS }
else { lx_mid(t) * S * expense_maint_paid_perS }
double[] maint_expense_N = if (t == 0 || t > n) { 0.0 }
elseif (t <= m) { lx_mid(t) * expense_maint_paying_perN }
else { lx_mid(t) * expense_maint_paid_perN }
double[] maint_expense_P = if (t == 0 || t > n) { 0.0 }
else { premium_income(t) * expense_maint_perP }
// ------------------------
double[] init_expense = (init_expense_S(t) + init_expense_P(t))
* (1.0 + expense_shock) * (1.0 + expense_shock_ex)
double[] maint_expense = (maint_expense_S(t) + maint_expense_N(t) + maint_expense_P(t))
* (1.0 + expense_shock) * (1.0 + expense_shock_ex)
double[] investment_income = investment_asset(t) * investment_yield(t)
double[] reserve_increase = if (t == 0) { 0.0 }
else { reserve(t) - reserve(t-1) }
double[] profit_before_tax = CF_beg(t) + CF_mid(t) + CF_end(t) + investment_income(t) - reserve_increase(t)
double[] corporate_tax = profit_before_tax(t) * tax_rate
double[] profit_after_tax = profit_before_tax(t) - corporate_tax(t)
double[] CF_beg = premium_income(t) - (commission(t) + init_expense(t))
double[] CF_mid = - (death_benefit(t) + surrender_benefit(t) + medical_benefit(t) + annuity_benefit(t)
+ unpaid_cashout(t) + maint_expense(t) )
double[] CF_end = - (endow_benefit(t))
// ストック項目
double[] premium_reserve = lx_end_after_mat(t) * Rate.netV_V(t) * S
double[] unpaid_prem_reserve = 0.0
double[] reserve = premium_reserve(t) + unpaid_prem_reserve(t)
double[] CV_end = lx_end_after_mat(t) * Rate.CV(t) * S
double[] azilV_end = lx_end_after_mat(t) * Rate.azilV_V(t) * S
double[] investment_asset =
if (t == 0) { 0.0 }
else { reserve(t - 1) + CF_beg(t) + CF_mid(t) * 0.5 }
// ディスカウントファクター・現価
double[] discount_factor_beg = if (t == 0) { 1.0 }
else { discount_factor_end(t-1) }
double[] discount_factor_mid = if (t == 0) { 1.0 }
else { discount_factor_end(t-1) / ((1 + discount_yield(t)) ^ 0.5) }
double[] discount_factor_end = if (t == 0) { 1.0 }
else { discount_factor_end(t-1) / (1 + discount_yield(t)) }
double[] PV_profit_after_tax = Utl.pv(profit_after_tax , discount_factor_end, discount_factor_end)
double[] PV_profit_before_tax = Utl.pv(profit_before_tax , discount_factor_end, discount_factor_end)
double[] PV_premium_income = Utl.pv(premium_income , discount_factor_end, discount_factor_beg)
double[] PV_commission = Utl.pv(commission , discount_factor_end, discount_factor_beg)
double[] PV_death_benefit = Utl.pv(death_benefit , discount_factor_end, discount_factor_mid)
double[] PV_medical_benefit = Utl.pv(medical_benefit , discount_factor_end, discount_factor_mid)
double[] PV_endow_benefit = Utl.pv(endow_benefit , discount_factor_end, discount_factor_end)
double[] PV_annuity_benefit = Utl.pv(annuity_benefit , discount_factor_end, discount_factor_mid)
double[] PV_surrender_benefit = Utl.pv(surrender_benefit , discount_factor_end, discount_factor_mid)
double[] PV_unpaid_cashout = Utl.pv(unpaid_cashout , discount_factor_end, discount_factor_mid)
double[] PV_init_expense = Utl.pv(init_expense , discount_factor_end, discount_factor_beg)
double[] PV_maint_expense = Utl.pv(maint_expense , discount_factor_end, discount_factor_mid)
double[] PV_CF_beg = Utl.pv(CF_beg , discount_factor_end, discount_factor_beg)
double[] PV_CF_mid = Utl.pv(CF_mid , discount_factor_end, discount_factor_mid)
double[] PV_CF_end = Utl.pv(CF_end , discount_factor_end, discount_factor_end)
double[] PVLiab = -(PV_CF_beg(t) + PV_CF_mid(t) + PV_CF_end(t))
double profit_margin_before_tax = PV_profit_before_tax(0) / PV_premium_income(0)
double profit_margin_after_tax = PV_profit_after_tax(0) / PV_premium_income(0)
// 生命表(ショック計算が無いとした場合)
// EV計算における将来時点の負債現在価値差額の計算に必要
double[] lx_beg_base = if (t == 0) { 0.0 }
else { lx_end_after_mat_base(t - 1) }
double[] lx_mid_base = if (t == 0) { 0.0 }
else { (lx_beg_base(t) + lx_end_base(t)) / 2.0 }
double[] lx_pay_base = if (t <= m) { lx_beg_base(t) }
else { 0.0 }
double[] lx_end_base = if (t == 0) { 1.0 }
else { Utl.max(lx_beg_base(t) - d_x_base(t) - dwx_base(t), 0.0) }
double[] lx_end_after_mat_base = if (t >= n) { 0.0 }
else { lx_end_base(t) }
double[] d_x_base = if (t == 0) { 0.0 }
else { lx_beg_base(t) * qx_base(t) * (1.0 - qwx_base(t) / 2.0) }
double[] dwx_base = if (t == 0) { 0.0 }
else { lx_beg_base(t) * qwx_base(t) * (1.0 - qx_base(t) / 2.0) }
double[] PVLiab_adj = if (lx_end(t) <= 0.0) { 0.0 }
else { PVLiab(t) * lx_end_base(t) / lx_end(t)}
}
// 現価およびプロフィットマージンの出力
module OutputProfitability{
double profit_margin_before_tax = CashFlow.profit_margin_before_tax
double profit_margin_after_tax = CashFlow.profit_margin_after_tax
double PV_profit_before_tax = CashFlow.PV_profit_before_tax(0)
double PV_profit_after_tax = CashFlow.PV_profit_after_tax(0)
double PV_premium_income = CashFlow.PV_premium_income(0)
double PV_commission = CashFlow.PV_commission(0)
double PV_death_benefit = CashFlow.PV_death_benefit(0)
double PV_medical_benefit = CashFlow.PV_medical_benefit(0)
double PV_endow_benefit = CashFlow.PV_endow_benefit(0)
double PV_annuity_benefit = CashFlow.PV_annuity_benefit(0)
double PV_surrender_benefit = CashFlow.PV_surrender_benefit(0)
double PV_unpaid_cashout = CashFlow.PV_unpaid_cashout(0)
double PV_init_expense = CashFlow.PV_init_expense(0)
double PV_maint_expense = CashFlow.PV_maint_expense(0)
}
// 基本的なBSPL項目の出力
module OutputBSPL{
@range = t
@range_last = Util.max_t
// PL項目
double[] premium_income = CashFlow.premium_income(t)
double[] commission = CashFlow.commission(t)
double[] death_benefit = CashFlow.death_benefit(t)
double[] medical_benefit = CashFlow.medical_benefit(t)
double[] endow_benefit = CashFlow.endow_benefit(t)
double[] annuity_benefit = CashFlow.annuity_benefit(t)
double[] surrender_benefit = CashFlow.surrender_benefit(t)
double[] unpaid_cashout = CashFlow.unpaid_cashout(t)
double[] init_expense = CashFlow.init_expense(t)
double[] maint_expense = CashFlow.maint_expense(t)
double[] investment_income = CashFlow.investment_income(t)
double[] reserve_increase = CashFlow.reserve_increase(t)
double[] profit_before_tax = CashFlow.profit_before_tax(t)
double[] corporate_tax = CashFlow.corporate_tax(t)
double[] profit_after_tax = CashFlow.profit_after_tax(t)
// BS項目
double[] premium_reserve = CashFlow.premium_reserve(t)
double[] unpaid_prem_reserve = CashFlow.unpaid_prem_reserve(t)
double[] reserve = CashFlow.reserve(t)
double[] CV_end = CashFlow.CV_end(t)
double[] azilV_end = CashFlow.azilV_end(t)
double[] investment_asset = CashFlow.investment_asset(t)
double[] lx_end = CashFlow.lx_end(t)
}
// EV計算用項目の出力
module OutputEV{
@range = t
@range_last = Util.max_t
double[] PV_profit_after_tax = CashFlow.PV_profit_after_tax(t)
double[] PV_premium_income = CashFlow.PV_premium_income(t)
double[] PVLiab_adj = CashFlow.PVLiab_adj(t)
double[] CV_end = CashFlow.CV_end(t)
double[] discount_factor_end = CashFlow.discount_factor_end(t)
}
}