Commit 995718e1 authored by Reinhold Kainhofer's avatar Reinhold Kainhofer
Browse files

Generalize premium rebate calculation and administration cost reserves

Introduce hooks Hooks$premiumRebateCalculation and Hooks$adjustPVForReserves to modify the premium rebate calculation (e.g. a rebate relative to admin cost, or admin cost reserves that exclude a premium rebate).

The premiumRebateCalculation hook is called after the premiumRebate rate is evaluated and can be used to adjust the rate to some other value that e.g. includes reserves / future present values, etc. This way, one can have a varying rate, but always the same logic to apply the rebate rate. So parameter and calculation are separated cleanly.

The adjustPVForReserves hook is called before all present values are combined to the corresponding reserves. This allows modifying all present values that will be used in the reserves. E.g. one can reduce the admin cost present values by a premium rebate and the admin cost reserve properly discounts the rebate from the reserve. The PV modifications have NO influence on the actual present values stored for the contract or used for other purposes. Only the local copy of the present values in the reserve calculation funciton is modified.
parent 2c987d64
...@@ -513,6 +513,8 @@ InsuranceContract.Values = list( ...@@ -513,6 +513,8 @@ InsuranceContract.Values = list(
#' \item{\code{$adjustCosts}}{Function with signature \code{function(costs, params, values, ...)} to adjust the tariff costs after their setup (e.g. contract-specific conditions/waivers, etc.).} #' \item{\code{$adjustCosts}}{Function with signature \code{function(costs, params, values, ...)} to adjust the tariff costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
#' \item{\code{$adjustMinCosts}}{Function with signature \code{function(minCosts, costs, params, values, ...)} to adjust the tariff minimum (unwaivable) costs after their setup (e.g. contract-specific conditions/waivers, etc.).} #' \item{\code{$adjustMinCosts}}{Function with signature \code{function(minCosts, costs, params, values, ...)} to adjust the tariff minimum (unwaivable) costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
#' \item{\code{$adjustPremiumCoefficients}}{Function with signature \code{function(coeff, type, premiums, params, values, premiumCalculationTime)} to adjust the coefficients for premium calculation after their default setup. Use cases are e.g. term-fix tariffs where the Zillmer premium term contains the administration cost over the whole contract, but not other gamma- or beta-costs.} #' \item{\code{$adjustPremiumCoefficients}}{Function with signature \code{function(coeff, type, premiums, params, values, premiumCalculationTime)} to adjust the coefficients for premium calculation after their default setup. Use cases are e.g. term-fix tariffs where the Zillmer premium term contains the administration cost over the whole contract, but not other gamma- or beta-costs.}
#' \item{\code{$adjustPVForReserves}}{Adjust the absolute present value vectors used to derive reserves (e.g. when a sum rebate is subtracted from the gamma-cost reserves without influencing the premium calculation). \code{function(absPV, params, values)}}
#' \item{\code{$premiumRebateCalculation}}{Calculate the actual premium rebate from the rebate rate (e.g. when the premium rate is given as a yearly cost reduction applied to a single-premium contract). \code{function(premiumRebateRate, params = params, values = values)}}
#' } #' }
#' #'
#' #'
...@@ -626,7 +628,9 @@ InsuranceContract.ParameterDefaults = list( ...@@ -626,7 +628,9 @@ InsuranceContract.ParameterDefaults = list(
adjustCashFlowsCosts = NULL, adjustCashFlowsCosts = NULL,
adjustCosts = NULL, adjustCosts = NULL,
adjustMinCosts = NULL, adjustMinCosts = NULL,
adjustPremiumCoefficients = NULL # function(coeff, type = type, premiums = premiums, params = params, values = values, premiumCalculationTime = premiumCalculationTime) adjustPremiumCoefficients = NULL, # function(coeff, type = type, premiums = premiums, params = params, values = values, premiumCalculationTime = premiumCalculationTime)
adjustPVForReserves = NULL, # function(absPresentValues, params, values)
premiumRebateCalculation = NULL # function(premiumRebateRate, params = params, values = values)
) )
); );
......
...@@ -991,7 +991,9 @@ InsuranceTarif = R6Class( ...@@ -991,7 +991,9 @@ InsuranceTarif = R6Class(
noMedicalExam.relative = valueOrFunction(loadings$noMedicalExamRelative,params = params, values = values); noMedicalExam.relative = valueOrFunction(loadings$noMedicalExamRelative,params = params, values = values);
extraRebate = valueOrFunction(loadings$extraRebate, params = params, values = values); extraRebate = valueOrFunction(loadings$extraRebate, params = params, values = values);
sumRebate = valueOrFunction(loadings$sumRebate, params = params, values = values); sumRebate = valueOrFunction(loadings$sumRebate, params = params, values = values);
premiumRebate = valueOrFunction(loadings$premiumRebate,params = params, values = values); premiumRebateRate = valueOrFunction(loadings$premiumRebate,params = params, values = values);
premiumRebate = applyHook(params$Hooks$premiumRebateCalculation, premiumRebateRate, params = params, values = values);
extraChargeGrossPremium = valueOrFunction(loadings$extraChargeGrossPremium, params = params, values = values); extraChargeGrossPremium = valueOrFunction(loadings$extraChargeGrossPremium, params = params, values = values);
advanceProfitParticipation = 0; advanceProfitParticipation = 0;
advanceProfitParticipationUnitCosts = 0; advanceProfitParticipationUnitCosts = 0;
...@@ -1016,7 +1018,7 @@ InsuranceTarif = R6Class( ...@@ -1016,7 +1018,7 @@ InsuranceTarif = R6Class(
values$premiums[["unitcost"]] = premium.unitcosts; values$premiums[["unitcost"]] = premium.unitcosts;
frequencyLoading = self$evaluateFrequencyLoading(loadings$premiumFrequencyLoading, params$ContractData$premiumFrequency, params = params, values = values) frequencyLoading = self$evaluateFrequencyLoading(loadings$premiumFrequencyLoading, params$ContractData$premiumFrequency, params = params, values = values)
premiumBeforeTax = (values$premiums[["unit.gross"]]*(1 + noMedicalExam.relative + extraChargeGrossPremium) + noMedicalExam - sumRebate - extraRebate) * sumInsured * (1 - advanceProfitParticipation); premiumBeforeTax = (values$premiums[["unit.gross"]]*(1 + noMedicalExam.relative + extraChargeGrossPremium) + noMedicalExam - sumRebate - extraRebate) * sumInsured * (1 - advanceProfitParticipation);
if (!params$Features$unitcostsInGross) { if (!params$Features$unitcostsInGross) {
premiumBeforeTax = premiumBeforeTax + premium.unitcosts; premiumBeforeTax = premiumBeforeTax + premium.unitcosts;
...@@ -1045,20 +1047,22 @@ InsuranceTarif = R6Class( ...@@ -1045,20 +1047,22 @@ InsuranceTarif = R6Class(
securityFactor = (1 + valueOrFunction(params$Loadings$security, params = params, values = values)); securityFactor = (1 + valueOrFunction(params$Loadings$security, params = params, values = values));
ppScheme = params$ProfitParticipation$profitParticipationScheme; ppScheme = params$ProfitParticipation$profitParticipationScheme;
absPV = applyHook(params$Hooks$adjustPVForReserves, values$absPresentValues, params = params, values = values);
# Net, Zillmer and Gross reserves # Net, Zillmer and Gross reserves
resNet = values$absPresentValues[,"benefitsAndRefund"] * securityFactor - values$premiums[["net"]] * values$absPresentValues[,"premiums.unit"]; resNet = absPV[,"benefitsAndRefund"] * securityFactor - values$premiums[["net"]] * absPV[,"premiums.unit"];
BWZcorr = ifelse(values$absPresentValues[t, "premiums"] == 0, 0, BWZcorr = ifelse(absPV[t, "premiums"] == 0, 0,
values$absPresentValues[t, "Zillmer"] / values$absPresentValues[t, "premiums"]) * values$absPresentValues[,"premiums"]; absPV[t, "Zillmer"] / absPV[t, "premiums"]) * absPV[,"premiums"];
resZ = resNet - BWZcorr; resZ = resNet - BWZcorr;
resAdeq = values$absPresentValues[,"benefitsAndRefund"] * securityFactor + resAdeq = absPV[,"benefitsAndRefund"] * securityFactor +
values$absPresentValues[,"alpha"] + values$absPresentValues[,"beta"] + values$absPresentValues[,"gamma"] - absPV[,"alpha"] + absPV[,"beta"] + absPV[,"gamma"] -
values$premiums[["gross"]] * values$absPresentValues[,"premiums.unit"]; values$premiums[["gross"]] * absPV[,"premiums.unit"];
#values$premiums[["Zillmer"]] * values$absPresentValues[,"premiums"]; #values$premiums[["Zillmer"]] * absPV[,"premiums"];
resGamma = values$absPresentValues[,"gamma"] - resGamma = absPV[,"gamma"] -
ifelse(values$absPresentValues[t, "premiums"] == 0, 0, ifelse(absPV[t, "premiums"] == 0, 0,
values$absPresentValues[t, "gamma"] / values$absPresentValues[t, "premiums"]) * values$absPresentValues[,"premiums"] absPV[t, "gamma"] / absPV[t, "premiums"]) * absPV[,"premiums"]
advanceProfitParticipation = 0; advanceProfitParticipation = 0;
if (!is.null(ppScheme)) { if (!is.null(ppScheme)) {
...@@ -1106,7 +1110,7 @@ InsuranceTarif = R6Class( ...@@ -1106,7 +1110,7 @@ InsuranceTarif = R6Class(
"reduction" = resReduction "reduction" = resReduction
#, "Reserve.premiumfree"=res.premiumfree, "Reserve.gamma.premiumfree"=res.gamma.premiumfree); #, "Reserve.premiumfree"=res.premiumfree, "Reserve.gamma.premiumfree"=res.gamma.premiumfree);
); );
rownames(res) <- rownames(values$absPresentValues); rownames(res) <- rownames(absPV);
values$reserves = res; values$reserves = res;
# The surrender value functions can have arbitrary form, so we store a function # The surrender value functions can have arbitrary form, so we store a function
...@@ -1136,9 +1140,9 @@ InsuranceTarif = R6Class( ...@@ -1136,9 +1140,9 @@ InsuranceTarif = R6Class(
premiumfreeValue = surrenderValue premiumfreeValue = surrenderValue
} }
Storno = 0; # TODO: Implement storno costs Storno = 0; # TODO: Implement storno costs
premiumfreePV = (values$absPresentValues[, "benefits"] * securityFactor + values$absPresentValues[, "gamma_nopremiums"]); # PV of future premium free claims + costs premiumfreePV = (absPV[, "benefits"] * securityFactor + absPV[, "gamma_nopremiums"]); # PV of future premium free claims + costs
newSI = ifelse(premiumfreePV == 0, 0, newSI = ifelse(premiumfreePV == 0, 0,
(premiumfreeValue - values$absPresentValues[,"death_Refund_past"] * securityFactor - c(Storno)) / (premiumfreeValue - absPV[,"death_Refund_past"] * securityFactor - c(Storno)) /
premiumfreePV * params$ContractData$sumInsured); premiumfreePV * params$ContractData$sumInsured);
cbind(res, cbind(res,
...@@ -1348,7 +1352,9 @@ InsuranceTarif = R6Class( ...@@ -1348,7 +1352,9 @@ InsuranceTarif = R6Class(
profits.advance = profits.advance + afterProfit - afterUnitCosts; profits.advance = profits.advance + afterProfit - afterUnitCosts;
# premium rebate # premium rebate
premiumRebate = valueOrFunction(loadings$premiumRebate,params = params, values = values); premiumRebateRate = valueOrFunction(loadings$premiumRebate,params = params, values = values);
premiumRebate = applyHook(params$Hooks$premiumRebateCalculation, premiumRebateRate, params = params, values = values);
afterPremiumRebate = afterUnitCosts * (1 - premiumRebate); afterPremiumRebate = afterUnitCosts * (1 - premiumRebate);
rebate.premium = afterPremiumRebate - afterUnitCosts; rebate.premium = afterPremiumRebate - afterUnitCosts;
......
...@@ -110,6 +110,9 @@ those cost components that are defined to be waivable, i.e. by ...@@ -110,6 +110,9 @@ those cost components that are defined to be waivable, i.e. by
defining a corresponding \code{$minCosts}). Linearly interpolates defining a corresponding \code{$minCosts}). Linearly interpolates
between \code{$Costs} and \code{$minCosts}, if the latter is set. between \code{$Costs} and \code{$minCosts}, if the latter is set.
Otherwise is has no effect.} Otherwise is has no effect.}
\item{\code{$attributes}}{Additional custom attributes (as a named list),
which can be used for particular behaviour of different contracts
or contract slices.}
} }
} }
...@@ -291,6 +294,8 @@ participation rates are defined at the level of profit classes.} ...@@ -291,6 +294,8 @@ participation rates are defined at the level of profit classes.}
\item{\code{$adjustCosts}}{Function with signature \code{function(costs, params, values, ...)} to adjust the tariff costs after their setup (e.g. contract-specific conditions/waivers, etc.).} \item{\code{$adjustCosts}}{Function with signature \code{function(costs, params, values, ...)} to adjust the tariff costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
\item{\code{$adjustMinCosts}}{Function with signature \code{function(minCosts, costs, params, values, ...)} to adjust the tariff minimum (unwaivable) costs after their setup (e.g. contract-specific conditions/waivers, etc.).} \item{\code{$adjustMinCosts}}{Function with signature \code{function(minCosts, costs, params, values, ...)} to adjust the tariff minimum (unwaivable) costs after their setup (e.g. contract-specific conditions/waivers, etc.).}
\item{\code{$adjustPremiumCoefficients}}{Function with signature \code{function(coeff, type, premiums, params, values, premiumCalculationTime)} to adjust the coefficients for premium calculation after their default setup. Use cases are e.g. term-fix tariffs where the Zillmer premium term contains the administration cost over the whole contract, but not other gamma- or beta-costs.} \item{\code{$adjustPremiumCoefficients}}{Function with signature \code{function(coeff, type, premiums, params, values, premiumCalculationTime)} to adjust the coefficients for premium calculation after their default setup. Use cases are e.g. term-fix tariffs where the Zillmer premium term contains the administration cost over the whole contract, but not other gamma- or beta-costs.}
\item{\code{$adjustPVForReserves}}{Adjust the absolute present value vectors used to derive reserves (e.g. when a sum rebate is subtracted from the gamma-cost reserves without influencing the premium calculation). \code{function(absPV, params, values)}}
\item{\code{$premiumRebateCalculation}}{Calculate the actual premium rebate from the rebate rate (e.g. when the premium rate is given as a yearly cost reduction applied to a single-premium contract). \code{function(premiumRebateRate, params = params, values = values)}}
} }
} }
} }
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment