diff --git a/DESCRIPTION b/DESCRIPTION
index 9fda3583e535741623415bbea1dcfdc8dc714443..07c56c8e86de013c462452d8810ae7f502175777 100644
--- a/DESCRIPTION
+++ b/DESCRIPTION
@@ -1,6 +1,6 @@
 Package: LifeInsuranceContracts
 Type: Package
-Version: 0.0.1
+Version: 0.0.2
 Date: 2020-09-04
 Title: A Framework for General, Traditional Life Insurance Contracts, Including Profit
     Participation and Contract Changes
diff --git a/NAMESPACE b/NAMESPACE
index 45d60ab6b1e711a7a290baf2e25603d97e53bf6b..91ad374b6432fc7d0a5708e04c898441c4cb976e 100644
--- a/NAMESPACE
+++ b/NAMESPACE
@@ -69,9 +69,11 @@ export(pad0)
 export(padLast)
 export(rollingmean)
 export(showVmGlgExamples)
+export(sumProfits)
 export(valueOrFunction)
 exportClasses(CalculationSingleEnum)
 exportClasses(PaymentTimeSingleEnum)
+exportClasses(ProfitComponentsMultipleEnum)
 exportClasses(SexSingleEnum)
 exportClasses(TariffTypeSingleEnum)
 import(MortalityTables)
diff --git a/R/HelperFunctions.R b/R/HelperFunctions.R
index 7dc0be10e91c1d7c8da2e8455488255706101ee9..98bf94f86c32744698d14dbe6c75bd0ccd53b14f 100644
--- a/R/HelperFunctions.R
+++ b/R/HelperFunctions.R
@@ -18,7 +18,7 @@ PaymentTimeEnum = objectProperties::setSingleEnum("PaymentTime", levels = c("in
 
 #' Enum to describe possible sexes in an insurance contract or tariff.
 #' @details
-#' Currently, only possible values are allowed;
+#' Currently, the only possible values are:
 #' * "unisex"
 #' * "male"
 #' * "female"
@@ -33,6 +33,18 @@ SexEnum = objectProperties::setSingleEnum("Sex", levels = c("unisex", "male", "f
 #' would be a waste of resources to calculate e.g. all future reserves and
 #' profit participation, if only premiums are of interest.
 #'
+#' Possible values are:
+#' * "all"
+#' * "probabilities"
+#' * "cashflows"
+#' * "presentvalues"
+#' * "premiums"
+#' * "absvalues"
+#' * "reserves"
+#' * "premiumcomposition"
+#' * "profitparticipation"
+#' * "history"
+#'
 #' @export
 CalculationEnum = objectProperties::setSingleEnum("Calculation",
     levels = c(
@@ -49,6 +61,46 @@ CalculationEnum = objectProperties::setSingleEnum("Calculation",
     )
 )
 
+
+#' Enum to define the different components of profit participation.
+#' @details
+#' Profit participation schemes typically consist of different components,
+#' which are calculated independently. Typical components are interest profit
+#' to distribute investment gains to the customer, risk profit and expense profit
+#' to return security margins in the biometric risk and the expenses to the customer
+#' and sum profit, which aplies to contracts with higher sums insured, where
+#' charged expenses are calculated from the sum insured, while the actual
+#' expenses are more or less constant. Thus, high contracts are charged more,
+#' which causes profits that are returned as sum profit.
+#'
+#' As a special case, part of the profits can be stored in a terminal bonus
+#' reserve and only distributed on maturity (or potentially on death), but
+#' not on surrender. Some (older) profit participation schemes add an independently
+#' calculated bonus on maturity (e.g. twice the total profit assignment of the
+#' last year) at maturity to give customers an additional incentive not to
+#' surrender a contract.
+#'
+#' Possible values are (multiple can be given):
+#' * "interest"
+#' * "risk"
+#' * "expense"
+#' * "sum"
+#' * "terminal"
+#' * "TBF"
+#'
+#' @export
+ProfitComponentsEnum = objectProperties::setMultipleEnum("ProfitComponents",
+    levels = c(
+      "advance",
+      "interest",
+      "risk",
+      "expense",
+      "sum",
+      "terminal",
+      "TBF"
+    )
+)
+
 #' Describes the death benefit of a linearly decreasing whole life insurance (after a possible deferall period)
 #'
 #' The death benefit will be the full sumInsured for the first year after the
@@ -464,6 +516,26 @@ fallbackFields = function(fields, valuelist) {
 rollingmean = function(x) (tail(x, -1) + head(x, -1))/2
 
 
+# Sum two or more vectors and correctly handle (i.e. ignore) NULL values given
+plusNULL = function(v1, v2, ...) {
+  if (missing(v2) && length(list(...)) == 0) {
+    if (missing(v1) || is.null(v1)) {
+      return(0)
+    } else {
+      return(v1)
+    }
+  }
+  if (missing(v1) || is.null(v1)) {
+    return(plusNULL(v2, ...));
+  }
+  if (missing(v2) || is.null(v2)) {
+    return(plusNULL(v1, ...));
+  } else {
+    return(plusNULL(v1 + v2, ...))
+  }
+}
+
+
 ######################################################################=#
 # Functions for handling sub-contract blocks                        ####
 
@@ -493,3 +565,5 @@ sumPaddedArrays = function(arr1 = NULL, arr2 = NULL, pad1 = 0, pad2 = 0) {
     arr1 + arr2
   }
 }
+
+
diff --git a/R/InsuranceParameters.R b/R/InsuranceParameters.R
index 4403f768481efe4982c521da57e937bd8acb6e8a..388ef50b5fc9df7cf8f89b1fbf20b6872a7b1987 100644
--- a/R/InsuranceParameters.R
+++ b/R/InsuranceParameters.R
@@ -293,7 +293,7 @@ InsuranceContract.Values = list(
 #'     \item{\code{$premiumFrequencyLoading}}{Loading on the premium for premium
 #'               payment frequencies of more than once a year. Format is
 #'               \code{list("1" = 0.0, "2" = 0.0, "4" = 0.0, "12" = 0.0)}}
-#'     \item{\code{$alphaRefundPeriod}}{How long the acquisition costs should be 
+#'     \item{\code{$alphaRefundPeriod}}{How long the acquisition costs should be
 #'               (partially) refunded in case of surrender or premium waiver.}
 #' }
 #'
@@ -438,7 +438,7 @@ InsuranceContract.ParameterDefaults = list(
         terminalBonusFundRate = NULL,
 
         profitParticipationScheme = NULL,      # Gewinnbeteiligungssystem (object of class Profit Participation)
-        profitComponents = c("interest", "risk", "expense", "sum", "terminal"),
+        profitComponents = c(),                 # Potential values: "interest", "risk", "expense", "sum", "terminal", "TBF"
         profitClass = NULL,
         profitRates = NULL,                     # General, company-wide profit rates, key columns are year and profitClass
 
diff --git a/R/ProfitParticipation.R b/R/ProfitParticipation.R
index a289a893797616b20691283f920e8166dcbf08fc..88ce7efc2602ab6e5a0b0ac280f496e08ed8b12c 100644
--- a/R/ProfitParticipation.R
+++ b/R/ProfitParticipation.R
@@ -377,24 +377,34 @@ ProfitParticipation = R6Class(
         }
         rates        = self$setupRates(params = params, values = values, ...)
 
-        intBase      = self$Functions$getInterestProfitBase(rates = rates, params = params, values = values);
-        riskBase     = self$Functions$getRiskProfitBase(rates = rates, params = params, values = values);
-        expenseBase  = self$Functions$getExpenseProfitBase(rates = rates, params = params, values = values);
-        sumBase      = self$Functions$getSumProfitBase(rates = rates, params = params, values = values);
-
-        intRate      = self$Functions$getInterestProfitRate(rates = rates, params = params, values = values);
-        riskRate     = self$Functions$getRiskProfitRate(rates = rates, params = params, values = values);
-        expenseRate  = self$Functions$getExpenseProfitRate(rates = rates, params = params, values = values);
-        sumRate      = self$Functions$getSumProfitRate(rates = rates, params = params, values = values);
-
-        intProfit     = self$Functions$calculateInterestProfit(base = intBase, rate = intRate, waiting = waitingFactor, rates = rates, params = params, values = values);
-        riskProfit    = self$Functions$calculateRiskProfit(base = riskBase, rate = riskRate, waiting = waitingFactor, rates = rates, params = params, values = values);
-        expenseProfit = self$Functions$calculateExpenseProfit(base = expenseBase, rate = expenseRate, waiting = waitingFactor, rates = rates, params = params, values = values);
-        sumProfit     = self$Functions$calculateSumProfit(base = sumBase, rate = sumRate, waiting = waitingFactor, rates = rates, params = params, values = values);
+        # Initialize all rates, bases and calc functions to NULL and then set
+        # only those that are actually used in this profit scheme (all values
+        # with NULL will silently be ignored in the cbind call)
+        intBase      = riskBase     = expenseBase   = sumBase      = NULL;
+        intRate      = riskRate     = expenseRate   = sumRate      = NULL;
+        intProfit    = riskProfit   = expenseProfit = sumProfit   = NULL
 
         interestOnProfitRate = self$Functions$getInterestOnProfits(rates = rates, params = params, values = values);
-
-
+        if ("interest" %in% params$ProfitParticipation$profitComponents) {
+          intBase      = self$Functions$getInterestProfitBase(rates = rates, params = params, values = values);
+          intRate      = self$Functions$getInterestProfitRate(rates = rates, params = params, values = values);
+          intProfit     = self$Functions$calculateInterestProfit(base = intBase, rate = intRate, waiting = waitingFactor, rates = rates, params = params, values = values);
+        }
+        if ("risk" %in% params$ProfitParticipation$profitComponents) {
+          riskBase     = self$Functions$getRiskProfitBase(rates = rates, params = params, values = values);
+          riskRate     = self$Functions$getRiskProfitRate(rates = rates, params = params, values = values);
+          riskProfit    = self$Functions$calculateRiskProfit(base = riskBase, rate = riskRate, waiting = waitingFactor, rates = rates, params = params, values = values);
+        }
+        if ("expense" %in% params$ProfitParticipation$profitComponents) {
+          expenseBase  = self$Functions$getExpenseProfitBase(rates = rates, params = params, values = values);
+          expenseRate  = self$Functions$getExpenseProfitRate(rates = rates, params = params, values = values);
+          expenseProfit = self$Functions$calculateExpenseProfit(base = expenseBase, rate = expenseRate, waiting = waitingFactor, rates = rates, params = params, values = values);
+        }
+        if ("sum" %in% params$ProfitParticipation$profitComponents) {
+          sumBase      = self$Functions$getSumProfitBase(rates = rates, params = params, values = values);
+          sumRate      = self$Functions$getSumProfitRate(rates = rates, params = params, values = values);
+          sumProfit     = self$Functions$calculateSumProfit(base = sumBase, rate = sumRate, waiting = waitingFactor, rates = rates, params = params, values = values);
+        }
 
         res = cbind(
             # Profit Calculation Bases
@@ -417,93 +427,116 @@ ProfitParticipation = R6Class(
             riskProfit = c(riskProfit),
             expenseProfit = c(expenseProfit),
             sumProfit = c(sumProfit),
-            componentsProfit = c(intProfit + riskProfit + expenseProfit + sumProfit),
+            componentsProfit = plusNULL(intProfit, riskProfit, expenseProfit, sumProfit),
             interestOnProfit = c(0),
             totalProfitAssignment = c(0),
 
             totalProfit = c(0)
         );
-        # Use only newly calculated values starting at 'calculateFrom', but use old values up to that moment (might be a contract change with a completely different profit participation system before!)
+
+        # Use only newly calculated values starting at 'calculateFrom', but use
+        # old values up to that moment (might be a contract change with a
+        # completely different profit participation system before!)
         res = mergeValues(starting = profitScenario[,colnames(res)], ending = res, t = calculateFrom);
 
-        # res = self$Functions$calculateInterestOnProfit(base = sumBase, rate = sumRate, waiting = waitingFactor, rates = rates, params = params, values = values);
         if (calculateFrom > 0 && !is.null(profitScenario)) {
           prev = profitScenario[calculateFrom - 1, "totalProfit"]
         } else {
           prev = 0;
         }
+        # TODO: turn the interest on profit into a calculator function!
+        # res = self$Functions$calculateInterestOnProfit(base = sumBase, rate = sumRate, waiting = waitingFactor, rates = rates, params = params, values = values);
         for (i in (calculateFrom + 1):nrow(res)) {
             res[i,"interestOnProfit"] = res[i,"interestOnProfitRate"] * prev;
             res[i,"totalProfitAssignment"] = res[i, "componentsProfit"] + res[i,"interestOnProfit"];
             res[i,"totalProfit"] = prev + res[i,"totalProfitAssignment"];
             prev = res[i,"totalProfit"];
         }
+        regularBonusAssignment = res[,"totalProfitAssignment"]
 
+        ###########################################################################################################%#
         #### OLD Terminal bonus (not through terminal bonus fund, i.e. part of ongoing profits, but in addition) ####
         #### Terminal Bonus calculations (might depend on the individual profit assignments calculated above!
+        ###########################################################################################################%#
         #### => TODO: Pass the current profit calculation inside the values!)
-        terminalBase = self$Functions$getTerminalBonusBase(res, rates = rates, params = params, values = values);
-        terminalRate = self$Functions$getTerminalBonusRate(res, rates = rates, params = params, values = values);
-        terminalBonus = self$Functions$calculateTerminalBonus(res, base = terminalBase, rate = terminalRate, calculateFrom = calculateFrom, waiting = waitingFactor, rates = rates, params = params, values = values); # TODO: Add the AF(v) factor!
-        res1 = cbind(
-          terminalBase,
-          terminalRate,
-          terminalBonus
-        )
-        res1 = mergeValues(starting = profitScenario[,colnames(res1)], ending = res1, t = calculateFrom)
-        if (calculateFrom == 0) {
-          terminalBonusAccount = cumsum(terminalBonus); # TODO: Generalize! Not every scheme uses a cumulative account!
-        } else {
-          past = profitScenario[1:calculateFrom, "terminalBonusAccount"]
-          # Preserve values up to calculateFrom, start from the last known value at calculateFrom-1 and sum all further contributions:
-          terminalBonusAccount = c(head(past, -1), cumsum(c(tail(past,1), tail(terminalBonus, -calculateFrom))))
+        if ("terminal" %in% params$ProfitParticipation$profitComponents) {
+          terminalBase = self$Functions$getTerminalBonusBase(res, rates = rates, params = params, values = values);
+          terminalRate = self$Functions$getTerminalBonusRate(res, rates = rates, params = params, values = values);
+          terminalBonus = self$Functions$calculateTerminalBonus(res,
+                  base = terminalBase, rate = terminalRate, calculateFrom = calculateFrom,
+                  waiting = waitingFactor, rates = rates, params = params, values = values); # TODO: Add the AF(v) factor!
+
+          if (calculateFrom == 0) {
+            terminalBonusAccount = cumsum(terminalBonus); # TODO: Generalize! Not every scheme uses a cumulative account!
+          } else {
+            past = profitScenario[1:calculateFrom, "terminalBonusAccount"]
+            # Preserve values up to calculateFrom, start from the last known value at calculateFrom-1 and sum all further contributions:
+            terminalBonusAccount = c(head(past, -1), cumsum(c(tail(past,1), tail(terminalBonus, -calculateFrom))))
+          }
+          terminalBonusReserve = self$Functions$getTerminalBonusReserve(res, rates = rates, terminalBonus, terminalBonusAccount, params = params, values = values)
+
+          resTerminal = cbind(
+            terminalBase,
+            terminalRate,
+            terminalBonus,
+            terminalBonusAccount,
+            terminalBonusReserve
+          )
+          resTerminal = mergeValues(starting = profitScenario[,colnames(resTerminal)], ending = resTerminal, t = calculateFrom)
+          # Add the terminal bonus values to the array:
+          res = cbind(res, resTerminal)
         }
-        terminalBonusReserve = self$Functions$getTerminalBonusReserve(res, rates = rates, terminalBonus, terminalBonusAccount, params = params, values = values)
-        res2 = cbind(terminalBonusAccount, terminalBonusReserve)
-        res = cbind(
-            res,
-            # Terminal Bonus values
-            res1,
-            mergeValues(starting = profitScenario[,colnames(res2)], ending = res2, t = calculateFrom)
-        )
 
+        ###########################################################################################################%#
         #### NEW Terminal bonus fund (part of regular profits, but not paid out on surrender, reserved as part of the free RfB) ####
-        TBFBase = self$Functions$getTerminalBonusFundBase(res, rates = rates, params = params, values = values);
-        TBFRate = self$Functions$getTerminalBonusFundRate(res, rates = rates, params = params, values = values);
-        TBFBonusAssignment = self$Functions$calculateTerminalBonusFund(res, base = TBFBase, rate = TBFRate, calculateFrom = calculateFrom, waiting = waitingFactor, rates = rates, params = params, values = values);
-        regularBonusAssignment = res[,"totalProfitAssignment"] - TBFBonusAssignment
-        res1 = cbind(
-          TBFBase,
-          TBFRate,
-          TBFBonusAssignment,
-          regularBonusAssignment
-        )
-        res1 = mergeValues(starting = profitScenario[,colnames(res1)], ending = res1, t = calculateFrom)
+        ###########################################################################################################%#
+        if ("TBF" %in% params$ProfitParticipation$profitComponents) {
+          TBFBase = self$Functions$getTerminalBonusFundBase(res, rates = rates, params = params, values = values);
+          TBFRate = self$Functions$getTerminalBonusFundRate(res, rates = rates, params = params, values = values);
+          TBFBonusAssignment = self$Functions$calculateTerminalBonusFund(res,
+                base = TBFBase, rate = TBFRate, calculateFrom = calculateFrom,
+                waiting = waitingFactor, rates = rates, params = params, values = values);
+          regularBonusAssignment = res[,"totalProfitAssignment"] - TBFBonusAssignment
+
+          # Calculate TBF and regular bonus as cumulative sum  of the assignments starting at t = calculateFrom plus the previous value!
+          if (calculateFrom == 0) {
+            TBF = cumsum(TBFBonusAssignment)
+          } else {
+            past = profitScenario[1:calculateFrom, "TBF"]
+            # Preserve values up to calculateFrom, start from the last known value at calculateFrom-1 and sum all further contributions:
+            TBF = c(head(past, -1), cumsum(c(tail(past,1), tail(TBFBonusAssignment, -calculateFrom))))
+          }
+
+
+          resTBF = cbind(
+            TBFBase,
+            TBFRate,
+            TBFBonusAssignment,
+            TBF
+          )
+          resTBF = mergeValues(starting = profitScenario[,colnames(resTBF)], ending = resTBF, t = calculateFrom)
+          # Add the terminal bonus fund values to the array:
+          res = cbind(res, resTBF)
+        }
 
-        # Calcula TBF and regular bonus as cumulative usm of the assignments starting at t=calculateFrom plus the previous value!
+        ###########################################################################################################%#
+        #### Regular bonus assignment / accrued regular bonus AFTER TBF                                          ####
+        ###########################################################################################################%#
+        # Calculate regular bonus (after potential TBF subtraction) as cumulative sum  of the assignments starting at t = calculateFrom plus the previous value!
         if (calculateFrom == 0) {
-          TBF = cumsum(TBFBonusAssignment)
           regularBonus = cumsum(regularBonusAssignment)
         } else {
-          past = profitScenario[1:calculateFrom, "TBF"]
-          # Preserve values up to calculateFrom, start from the last known value at calculateFrom-1 and sum all further contributions:
-          TBF = c(head(past, -1), cumsum(c(tail(past,1), tail(TBFBonusAssignment, -calculateFrom))))
           past = profitScenario[1:calculateFrom, "regularBonus"]
           regularBonus = c(head(past, -1), cumsum(c(tail(past,1), tail(regularBonusAssignment, -calculateFrom))))
         }
-        res2 = cbind(
-          TBF,
-          regularBonus
-        )
-        res2 = mergeValues(starting = profitScenario[,colnames(res2)], ending = res2, t = calculateFrom)
-
+        resRegular = cbind(regularBonusAssignment, regularBonus)
+        resRegular = mergeValues(starting = profitScenario[,colnames(resRegular)], ending = resRegular, t = calculateFrom)
+        res = cbind(res, resRegular)
 
-        res = cbind(
-          res,
-          res1,
-          res2
-        )
 
+        ###########################################################################################################%#
+        #### BENEFITS                                                                                            ####
+        ###########################################################################################################%#
 
         survival       = self$Functions$calculateSurvivalBenefit(res, rates = rates, params = params, values = values);
 
@@ -516,7 +549,7 @@ ProfitParticipation = R6Class(
         premiumWaiverAccrued  = self$Functions$calculatePremiumWaiverBenefitAccrued(res, rates = rates, params = params, values = values);
         premiumWaiverTerminalBonus = self$Functions$calculatePremiumWaiverBenefitTerminal(res, rates = rates, params = params, values = values);
 
-        res1 = cbind(
+        resBenefit = cbind(
           survival = survival,
 
           deathAccrued = deathAccrued,
@@ -532,45 +565,9 @@ ProfitParticipation = R6Class(
           premiumWaiver  = premiumWaiverAccrued + premiumWaiverTerminalBonus
         )
         # Preserve values up to time t=calculateFrom of the old scenario values
-        res1 = mergeValues(starting = profitScenario[,colnames(res1)], ending = res1, t = calculateFrom)
-
-
-        res = cbind(
-            res,
-            res1
-        );
-
-        # Clean the huge dataframe by removing columns that refer to profit
-        # sources that the current profit plan does not provide
-        toremove = c();
-        cnames = colnames(res)
-        if (!"interest" %in% params$ProfitParticipation$profitComponents) {
-            toremove = c(toremove, grep("^interest[BP]", cnames));
-        }
-        if (!"risk" %in% params$ProfitParticipation$profitComponents) {
-            toremove = c(toremove, grep("^risk", cnames));
-        }
-        if (!"expense" %in% params$ProfitParticipation$profitComponents) {
-            toremove = c(toremove, grep("^expense", cnames));
-        }
-        if (!"sum" %in% params$ProfitParticipation$profitComponents) {
-            toremove = c(toremove, grep("^sum", cnames));
-        }
-        if (!"terminal" %in% params$ProfitParticipation$profitComponents) {
-          toremove = c(toremove,
-                       grep("^terminal", cnames),
-                       grep("^.*TerminalBonus$", cnames)
-          );
-        }
-        if (!"TBF" %in% params$ProfitParticipation$profitComponents) {
-          toremove = c(toremove,
-                       grep("^TBF", cnames)
-          );
-        }
-        if (length(toremove) > 0) {
-            res = res[,-toremove]
-        }
+        resBenefit = mergeValues(starting = profitScenario[,colnames(resBenefit)], ending = resBenefit, t = calculateFrom)
 
+        res = cbind(res, resBenefit);
         res
     },
 
diff --git a/R/ProfitParticipation_Functions.R b/R/ProfitParticipation_Functions.R
index 5a472429181131c3820db3661d062c6e3fdf2cbe..492514efe08bc6253948f431363abb7ebc9a1d3f 100644
--- a/R/ProfitParticipation_Functions.R
+++ b/R/ProfitParticipation_Functions.R
@@ -241,11 +241,32 @@ PP.calculate.RateOnBaseSGFFactor = function(base, rate, waiting, rates, params,
 # rates defined with the functions above.
 #++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
+#' @describeIn ProfitParticipationFunctions
+#' Extract the given columns of the profit participation array of values and sum
+#' them up. Columns that do not exist, because the profit scheme does not
+#' provide the corresponding profit component will be silently ignored.
+#' This allows generic benefit calculation functions to be written that do
+#' not need to distinguish e.g. whether an old-style terminal bonus or a terminal
+#' bonus fund is provided.
+#'
+#' This function is not meant to be called directly, but within a profit benefit
+#' calculation function.
+#'
+#' @param profits The array of profit participation component values
+#' @param cols The columns of the profit values array to be summed (columns given that do not exist in the profits array are ignired)
+#' @export
+sumProfits = function(profits, cols) {
+  # extract the columns -- if they exist -- and sum them up:
+  rowSums(
+    profits[, intersect(c(), colnames(profits))]
+  )
+}
+
 #' @describeIn ProfitParticipationFunctions
 #' Calculate survival benefit as total profit amount plus the terminal bonus reserve
 #' @export
 PP.benefit.ProfitPlusTerminalBonusReserve = function(profits, ...) {
-  profits[,"regularBonus"] + profits[,"TBF"] + profits[,"terminalBonusReserve"]
+  sumProfits(profits, c("regularBonus", "TBF", "terminalBonusReserve"))
 };
 
 #' @describeIn ProfitParticipationFunctions
@@ -309,7 +330,7 @@ PP.benefit.ProfitGuaranteeSupporting = function(profits, rates, params, values,
 #' @export
 PP.benefit.TerminalBonus5YearsProRata = function(profits, params, ...) {
   n = params$ContractData$policyPeriod;
-  (profits[, "terminalBonusReserve"] + profits[, "TBF"]) * (0:n)/n * ((0:n) >= max(10, n - 5))
+  sumProfits(profits, c("TBF", "terminalBonusReserve")) * (0:n)/n * ((0:n) >= max(10, n - 5))
 };
 
 #' @describeIn ProfitParticipationFunctions
@@ -317,14 +338,14 @@ PP.benefit.TerminalBonus5YearsProRata = function(profits, params, ...) {
 #' @export
 PP.benefit.TerminalBonus5Years = function(profits, params, ...) {
   n = params$ContractData$policyPeriod;
-  (profits[, "terminalBonusReserve"] + profits[, "TBF"]) * ((0:n) >= max(10, n - 5))
+  sumProfits(profits, c("TBF", "terminalBonusReserve")) * ((0:n) >= max(10, n - 5))
 }
 
 #' @describeIn ProfitParticipationFunctions
 #' Calculate benefit from terminal bonus (full bonus), either old-style terminal bonus reserve or Terminal Bonus Fund (TBF)
 #' @export
 PP.benefit.TerminalBonus = function(profits, params, ...) {
-  profits[, "terminalBonusReserve"] + profits[, "TBF"]
+  sumProfits(profits, c("TBF", "terminalBonusReserve"))
 };
 
 "dummy"
diff --git a/man/CalculationSingleEnum-class.Rd b/man/CalculationSingleEnum-class.Rd
index b84793a3914d3099240ace848f33299fdf9d49f8..ed8e8db53fd75487c8da0b8bf1d3d488968e8106 100644
--- a/man/CalculationSingleEnum-class.Rd
+++ b/man/CalculationSingleEnum-class.Rd
@@ -13,4 +13,18 @@ When an \link{InsuranceContract} object is created, all time series are immediat
 calculated. However, sometimes, one only needs part of the values, so it
 would be a waste of resources to calculate e.g. all future reserves and
 profit participation, if only premiums are of interest.
+
+Possible values are:
+\itemize{
+\item "all"
+\item "probabilities"
+\item "cashflows"
+\item "presentvalues"
+\item "premiums"
+\item "absvalues"
+\item "reserves"
+\item "premiumcomposition"
+\item "profitparticipation"
+\item "history"
+}
 }
diff --git a/man/InsuranceContract.ParameterDefaults.Rd b/man/InsuranceContract.ParameterDefaults.Rd
index 68ddbb386999887a4733f3e520ca5a565ff35f1c..cc60d3bf09c11c97885fff5967928a30bbe885c1 100644
--- a/man/InsuranceContract.ParameterDefaults.Rd
+++ b/man/InsuranceContract.ParameterDefaults.Rd
@@ -184,6 +184,8 @@ payment frequencies of more than once a year. Format is
 \item{\code{$premiumFrequencyLoading}}{Loading on the premium for premium
 payment frequencies of more than once a year. Format is
 \code{list("1" = 0.0, "2" = 0.0, "4" = 0.0, "12" = 0.0)}}
+\item{\code{$alphaRefundPeriod}}{How long the acquisition costs should be
+(partially) refunded in case of surrender or premium waiver.}
 }
 }
 
diff --git a/man/ProfitComponentsMultipleEnum-class.Rd b/man/ProfitComponentsMultipleEnum-class.Rd
new file mode 100644
index 0000000000000000000000000000000000000000..e0d0f521929d078326f12942d9f72d344c2a1e5f
--- /dev/null
+++ b/man/ProfitComponentsMultipleEnum-class.Rd
@@ -0,0 +1,37 @@
+% Generated by roxygen2: do not edit by hand
+% Please edit documentation in R/HelperFunctions.R
+\docType{class}
+\name{ProfitComponentsMultipleEnum-class}
+\alias{ProfitComponentsMultipleEnum-class}
+\alias{ProfitComponentsEnum}
+\title{Enum to define the different components of profit participation.}
+\description{
+Enum to define the different components of profit participation.
+}
+\details{
+Profit participation schemes typically consist of different components,
+which are calculated independently. Typical components are interest profit
+to distribute investment gains to the customer, risk profit and expense profit
+to return security margins in the biometric risk and the expenses to the customer
+and sum profit, which aplies to contracts with higher sums insured, where
+charged expenses are calculated from the sum insured, while the actual
+expenses are more or less constant. Thus, high contracts are charged more,
+which causes profits that are returned as sum profit.
+
+As a special case, part of the profits can be stored in a terminal bonus
+reserve and only distributed on maturity (or potentially on death), but
+not on surrender. Some (older) profit participation schemes add an independently
+calculated bonus on maturity (e.g. twice the total profit assignment of the
+last year) at maturity to give customers an additional incentive not to
+surrender a contract.
+
+Possible values are (multiple can be given):
+\itemize{
+\item "interest"
+\item "risk"
+\item "expense"
+\item "sum"
+\item "terminal"
+\item "TBF"
+}
+}
diff --git a/man/ProfitParticipationFunctions.Rd b/man/ProfitParticipationFunctions.Rd
index 2b2910dae91ccf0ee57c57270c0fc364be8781da..463246dbee555f2ab1e9695478ba6d6a20fe1735 100644
--- a/man/ProfitParticipationFunctions.Rd
+++ b/man/ProfitParticipationFunctions.Rd
@@ -27,6 +27,7 @@
 \alias{PP.calculate.RateOnBaseMin0}
 \alias{PP.calculate.RatePlusGuaranteeOnBase}
 \alias{PP.calculate.RateOnBaseSGFFactor}
+\alias{sumProfits}
 \alias{PP.benefit.ProfitPlusTerminalBonusReserve}
 \alias{PP.benefit.Profit}
 \alias{PP.benefit.ProfitPlusGuaranteedInterest}
@@ -115,6 +116,8 @@ PP.calculate.RateOnBaseSGFFactor(
   ...
 )
 
+sumProfits(profits, cols)
+
 PP.benefit.ProfitPlusTerminalBonusReserve(profits, ...)
 
 PP.benefit.Profit(profits, ...)
@@ -153,7 +156,7 @@ insurance contract, including cash flows, premiums, reserves etc.).}
 
 \item{res}{the data.frame of reserves.}
 
-\item{profits}{The data.frame of profits assigned}
+\item{profits}{The array of profit participation component values}
 
 \item{terminalBonus}{The terminal bonus calculated}
 
@@ -165,6 +168,8 @@ where terminal bonuses are accrued, potentiall discounted from the maturity)}
 \item{rate}{The profit participation rate}
 
 \item{waiting}{A possible waiting period}
+
+\item{cols}{The columns of the profit values array to be summed (columns given that do not exist in the profits array are ignired)}
 }
 \description{
 Various helper functions for the \code{ProfitParticipation} class that
@@ -223,6 +228,16 @@ the rates and how the assigned profit is calculated.
 
 \item \code{PP.calculate.RateOnBaseSGFFactor}: Calculate profit by a simple rate applied on the basis (with only (1-SGFFactor) put into profit participation, and an optional waiting vector of values 0 or 1)
 
+\item \code{sumProfits}: Extract the given columns of the profit participation array of values and sum
+them up. Columns that do not exist, because the profit scheme does not
+provide the corresponding profit component will be silently ignored.
+This allows generic benefit calculation functions to be written that do
+not need to distinguish e.g. whether an old-style terminal bonus or a terminal
+bonus fund is provided.
+
+This function is not meant to be called directly, but within a profit benefit
+calculation function.
+
 \item \code{PP.benefit.ProfitPlusTerminalBonusReserve}: Calculate survival benefit as total profit amount plus the terminal bonus reserve
 
 \item \code{PP.benefit.Profit}: Calculate benefit as total profit accrued so far
diff --git a/man/SexSingleEnum-class.Rd b/man/SexSingleEnum-class.Rd
index 370804b793ebf930193b6dc2473833dd6edcb5e6..8d28e94c8d841d3c0058ae95ab6617dc30c18bfa 100644
--- a/man/SexSingleEnum-class.Rd
+++ b/man/SexSingleEnum-class.Rd
@@ -9,7 +9,7 @@
 Enum to describe possible sexes in an insurance contract or tariff.
 }
 \details{
-Currently, only possible values are allowed;
+Currently, the only possible values are:
 \itemize{
 \item "unisex"
 \item "male"