diff --git a/R/InsuranceContract.R b/R/InsuranceContract.R
index a7c999fb20980e59ae4813cd86f11d41c4dd53d9..6b3121f83a80607873848c017cf8660a9b5e8794 100644
--- a/R/InsuranceContract.R
+++ b/R/InsuranceContract.R
@@ -10,6 +10,7 @@ InsuranceContract = R6Class(
     #### Contract settings
     params = list(
       sumInsured = 1,
+      premiumWaiver= 0,
       YOB = NA,
       age = NA,
       policyPeriod = Inf,
@@ -101,6 +102,7 @@ InsuranceContract = R6Class(
       self$calculateAbsPresentValues();
       self$calculateReserves();
       self$premiumAnalysis();
+      self$addHistorySnapshot(0, "Initial contract values", type="Contract", params=self$params, values = self$values);
     },
 
 
@@ -111,87 +113,71 @@ InsuranceContract = R6Class(
 
     determineCashFlows = function() {
       self$values$cashFlowsBasic = do.call(self$tarif$getBasicCashFlows, self$params);
-      self$values$cashFlows = do.call(self$tarif$getCashFlows, c(self$params, "basicCashFlows" = self$values$cashFlowsBasic));
+      self$values$cashFlows = do.call(self$tarif$getCashFlows, c(self$params, self$values));
       self$values$premiumSum = sum(self$values$cashFlows$premiums_advance + self$values$cashFlows$premiums_arrears);
-      self$values$cashFlowsCosts = do.call(self$tarif$getCashFlowsCosts, self$params);
+      self$values$cashFlowsCosts = do.call(self$tarif$getCashFlowsCosts, c(self$params, self$values));
       list("benefits"= self$values$cashFlows, "costs"=self$values$cashFlowCosts, "premiumSum" = self$values$premiumSum)
     },
 
     calculatePresentValues = function() {
+str(self$values);
       self$values$presentValues = do.call(self$tarif$presentValueCashFlows,
-                                   c(list("cashflows"=self$values$cashFlows), self$params));
+                                   c(self$params, self$values));
       self$values$presentValuesCosts = do.call(self$tarif$presentValueCashFlowsCosts,
-                                        c(list("cashflows"=self$values$cashFlowsCosts), self$params));
+                                        c(self$params, self$values));
       list("benefits" = self$values$presentValues, "costs" = self$values$presentValuesCosts)
     },
 
     calculatePremiums = function() {
       # the premiumCalculation function returns the premiums AND the cofficients,
       # so we have to extract the coefficients and store them in a separate variable
-      res = do.call(self$tarif$premiumCalculation,
-                    c(list(pvBenefits=self$values$presentValues,
-                      pvCosts=self$values$presentValuesCosts,
-                      premiumSum = self$values$premiumSum),
-                      self$params));
+      res = do.call(self$tarif$premiumCalculation, c(self$params, self$values));
       self$values$premiumCoefficients = res[["coefficients"]];
       self$values$premiums = res[["premiums"]]
       self$values$premiums
     },
 
     updatePresentValues = function() {
-      pvAllBenefits = do.call(self$tarif$presentValueBenefits,
-                              c(list(presentValues = self$values$presentValues,
-                                     presentValuesCosts = self$values$presentValuesCosts,
-                                     premiums = self$values$premiums,
-                                     premiumSum = self$values$premiumSum),
-                                self$params));
+      pvAllBenefits = do.call(self$tarif$presentValueBenefits, c(self$params, self$values));
       self$values$presentValues = cbind(self$values$presentValues, pvAllBenefits)
       self$values$presentValue
     },
 
     calculateAbsCashFlows = function() {
-      absCashFlows = do.call(self$tarif$getAbsCashFlows,
-                             c(list(premiums = self$values$premiums,
-                                    premiumSum = self$values$premiumSum,
-                                    cashflows = self$values$cashFlows,
-                                    cashflowsCosts = self$values$cashFlowsCosts),
-                               self$params));
-      self$values$absCashFlows = absCashFlows
+      self$values$absCashFlows = do.call(self$tarif$getAbsCashFlows, c(self$params, self$values));
       self$values$absCashFlows
     },
 
     calculateAbsPresentValues = function() {
-      absPresentValues = do.call(self$tarif$getAbsPresentValues,
-                                 c(list(premiums = self$values$premiums,
-                                        premiumSum = self$values$premiumSum,
-                                        presentValues = self$values$presentValues,
-                                        presentValuesCosts = self$values$presentValuesCosts),
-                                   self$params));
-      self$values$absPresentValues = absPresentValues
+      self$values$absPresentValues = do.call(self$tarif$getAbsPresentValues, c(self$params, self$values));
       self$values$absPresentValues
     },
 
     calculateReserves = function() {
-      self$values$reserves = do.call(self$tarif$reserveCalculation,
-                              c(list(premiums=self$values$premiums,
-                                presentValues=self$values$absPresentValues,
-                                cashflows = self$values$absCashFlows,
-                                premiumSum = self$values$premiumSum),
-                                self$params));
+      self$values$reserves = do.call(self$tarif$reserveCalculation, c(self$params, self$values));
       self$values$reserves
     },
 
     premiumAnalysis = function() {
-      self$values$premiumComposition = do.call(self$tarif$premiumDecomposition,
-                                        c(list(premiums=self$values$premiums,
-                                               reserves=self$values$reserves,
-                                               cashflows=self$values$absCashFlows,
-                                               presentValues=self$values$absPresentValues,
-                                               q=self$values$transitionProbabilities),
-                                          self$params));
+      self$values$premiumComposition = do.call(self$tarif$premiumDecomposition, c(self$params, self$values));
       self$values$premiumComposition
     },
 
+    # Premium Waiver: Stop all premium payments at time t
+    # the SumInsured is determined from the available
+    premiumWaiver = function (t) {
+      newSumInsured = self$values$reserves[[toString(t), "PremiumFreeSumInsured"]];
+      self$premiumWaiver = TRUE;
+      self$recalculatePremiumFreeSumInsured(t=t, SumInsured=newSumInsured)
+
+      # TODO: Update cashflows from t onwards
+      # TODO: Update present values from t onwards
+      # TODO: Update reserves from t onwards
+
+
+      self$addHistorySnapshot(t=t, comment=sprintf("Premium waiver at time %d", t), type="PremiumWaiver", params=self$params, values=self$values);
+    },
+
     dummy=NULL
   )
 );
diff --git a/R/InsuranceTarif.R b/R/InsuranceTarif.R
index 08da0cd2a902a1b07ca27992bb10a33b14623495..f0a463c60088ddd822f2392531508b0ac68574fe 100644
--- a/R/InsuranceTarif.R
+++ b/R/InsuranceTarif.R
@@ -153,12 +153,12 @@ InsuranceTarif = R6Class(
       cf
     },
 
-    getCashFlows = function(age, ..., premiumPayments = "in advance", benefitPayments = "in advance", guaranteed = 0, policyPeriod=Inf, premiumPeriod = policyPeriod, deferral=0, maxAge = getOmega(self$mortalityTable), basicCashFlows = NULL) {
-      if (missing(basicCashFlows)) {
-        basicCashFlows = self$getBasicCashFlows(age = age, ..., guaranteed = guaranteed,
+    getCashFlows = function(age, ..., premiumPayments = "in advance", benefitPayments = "in advance", guaranteed = 0, policyPeriod=Inf, premiumPeriod = policyPeriod, deferral=0, maxAge = getOmega(self$mortalityTable), cashFlowsBasic = NULL) {
+      if (missing(cashFlowsBasic)) {
+        cashFlowsBasic = self$getBasicCashFlows(age = age, ..., guaranteed = guaranteed,
               policyPeriod = policyPeriod, deferral = deferral, maxAge = maxAge);
       }
-      cflen = length(basicCashFlows$survival);
+      cflen = length(cashFlowsBasic$survival);
       zeroes = pad0(0, cflen);
       ages = pad0(self$getAges(age, YOB = YOB), cflen);
       cf = data.frame(
@@ -186,16 +186,16 @@ InsuranceTarif = R6Class(
 
       # Survival Benefits
       if (benefitPayments == "in advance") {
-        cf$guaranteed_advance = pad0(basicCashFlows$guaranteed, cflen);
-        cf$survival_advance = pad0(basicCashFlows$survival, cflen);
+        cf$guaranteed_advance = pad0(cashFlowsBasic$guaranteed, cflen);
+        cf$survival_advance = pad0(cashFlowsBasic$survival, cflen);
       } else {
-        cf$guaranteed_arrears = pad0(basicCashFlows$guaranteed, cflen);
-        cf$survival_arrears = pad0(basicCashFlows$survival, cflen);
+        cf$guaranteed_arrears = pad0(cashFlowsBasic$guaranteed, cflen);
+        cf$survival_arrears = pad0(cashFlowsBasic$survival, cflen);
       }
 
       # Death Benefits
-      cf$death_SumInsured = pad0(basicCashFlows$death, cflen);
-      cf$disease_SumInsured = pad0(basicCashFlows$disease, cflen);
+      cf$death_SumInsured = pad0(cashFlowsBasic$death, cflen);
+      cf$disease_SumInsured = pad0(cashFlowsBasic$disease, cflen);
       cf$death_PremiumFree = cf$death_SumInsured;
       # premium refund
       if (self$premiumRefund != 0) {
@@ -233,8 +233,8 @@ InsuranceTarif = R6Class(
       cf
     },
 
-    presentValueCashFlows = function(cashflows, age, ..., premiumFrequency = 1, benefitFrequency = 1, maxAge = getOmega(self$mortalityTable)) {
-      len = length(cashflows$premiums_advance);
+    presentValueCashFlows = function(cashFlows, age, ..., premiumFrequency = 1, benefitFrequency = 1, maxAge = getOmega(self$mortalityTable)) {
+      len = length(cashFlows$premiums_advance);
       qq = self$getTransitionProbabilities (age, ...);
       qx = pad0(qq$q, len);
       ix = pad0(qq$i, len);
@@ -242,32 +242,35 @@ InsuranceTarif = R6Class(
       benefitFrequencyCorrection = correctionPaymentFrequency(m = benefitFrequency, i = self$i, order = self$benefitFrequencyOrder);
       premiumFrequencyCorrection = correctionPaymentFrequency(m = premiumFrequency, i = self$i, order = self$premiumFrequencyOrder);
 
-      pvRefund = calculatePVDeath (px, qx, cashflows$death_GrossPremium, v=self$v);
-      pvRefundPast = calculatePVDeath (px, qx, cashflows$death_Refund_past, v=self$v) * (cashflows[,"death_GrossPremium"]-cashflows[,"premiums_advance"]);
+      pvRefund = calculatePVDeath (px, qx, cashFlows$death_GrossPremium, v=self$v);
+      pvRefundPast = calculatePVDeath (px, qx, cashFlows$death_Refund_past, v=self$v) * (cashFlows[,"death_GrossPremium"]-cashFlows[,"premiums_advance"]);
 
+str(px/px);
+str(qx*0);
       pv = cbind(
-        premiums = calculatePVSurvival (px, qx, cashflows$premiums_advance, cashflows$premiums_arrears, m=premiumFrequency, mCorrection=premiumFrequencyCorrection, v=self$v),
-        guaranteed = calculatePVSurvival (px/px, qx*0, cashflows$guaranteed_advance, cashflows$guaranteed_arrears, m=benefitFrequency, mCorrection=benefitFrequencyCorrection, v=self$v),
-        survival = calculatePVSurvival (px, qx, cashflows$survival_advance, cashflows$survival_arrears, m=benefitFrequency, mCorrection=benefitFrequencyCorrection, v=self$v),
-        death_SumInsured = calculatePVDeath (px, qx, cashflows$death_SumInsured, v=self$v),
-        disease_SumInsured = calculatePVDisease(px, qx, ix, cashflows$disease_SumInsured, v=self$v),
+        premiums = calculatePVSurvival (px, qx, cashFlows$premiums_advance, cashFlows$premiums_arrears, m=premiumFrequency, mCorrection=premiumFrequencyCorrection, v=self$v),
+        guaranteed = calculatePVGuaranteed (cashFlows$guaranteed_advance, cashFlows$guaranteed_arrears, m=benefitFrequency, mCorrection=benefitFrequencyCorrection, v=self$v),
+        survival = calculatePVSurvival (px, qx, cashFlows$survival_advance, cashFlows$survival_arrears, m=benefitFrequency, mCorrection=benefitFrequencyCorrection, v=self$v),
+        death_SumInsured = calculatePVDeath (px, qx, cashFlows$death_SumInsured, v=self$v),
+        disease_SumInsured = calculatePVDisease(px, qx, ix, cashFlows$disease_SumInsured, v=self$v),
         death_GrossPremium = pvRefund,
         death_Refund_past = pvRefundPast,
         death_Refund_future = pvRefund - pvRefundPast,
-        death_PremiumFree = calculatePVDeath (px, qx, cashflows$death_PremiumFree, v=self$v)
+        death_PremiumFree = calculatePVDeath (px, qx, cashFlows$death_PremiumFree, v=self$v)
       );
 
       rownames(pv) <- pad0(rownames(qq), len);
       pv
     },
 
-    presentValueCashFlowsCosts = function(cashflows, age, ..., maxAge = getOmega(self$mortalityTable)) {
-      len = dim(cashflows)[1];
+    presentValueCashFlowsCosts = function(cashFlowsCosts, age, ..., maxAge = getOmega(self$mortalityTable)) {
+      len = dim(cashFlowsCosts)[1];
       q = self$getTransitionProbabilities (age, ...);
       qx = pad0(q$q, len);
       px = pad0(q$p, len);
 
-      pvc = calculatePVCosts(px, qx, cashflows, v=self$v);
+# str(cashFlowsCosts);
+      pvc = calculatePVCosts(px, qx, cashFlowsCosts, v=self$v);
       pvc
     },
 
@@ -283,26 +286,26 @@ InsuranceTarif = R6Class(
       res
     },
 
-    getAbsCashFlows = function(cashflows, cashflowsCosts, premiums, sumInsured=1, premiumSum=0, ...) {
+    getAbsCashFlows = function(cashFlows, cashFlowsCosts, premiums, sumInsured=1, premiumSum=0, ...) {
       refundAddon = self$premiumRefundLoading;
 
       # TODO: Set up a nice list with coefficients for each type of cashflow, rather than multiplying each item manually (this also mitigates the risk of forgetting a dimension, because then the dimensions would not match, while here it's easy to overlook a multiplication)
       # Multiply each CF column by the corresponding basis
-      cashflows[,c("premiums_advance", "premiums_arrears")] = cashflows[,c("premiums_advance", "premiums_arrears")] * premiums[["gross"]];
-      cashflows[,c("guaranteed_advance", "guaranteed_arrears", "survival_advance", "survival_arrears", "death_SumInsured", "death_PremiumFree", "disease_SumInsured")] =
-        cashflows[,c("guaranteed_advance", "guaranteed_arrears", "survival_advance", "survival_arrears", "death_SumInsured", "death_PremiumFree", "disease_SumInsured")] * sumInsured;
-      cashflows[,c("death_GrossPremium", "death_Refund_past")] = cashflows[,c("death_GrossPremium","death_Refund_past")] * premiums[["gross"]] * (1+refundAddon);
+      cashFlows[,c("premiums_advance", "premiums_arrears")] = cashFlows[,c("premiums_advance", "premiums_arrears")] * premiums[["gross"]];
+      cashFlows[,c("guaranteed_advance", "guaranteed_arrears", "survival_advance", "survival_arrears", "death_SumInsured", "death_PremiumFree", "disease_SumInsured")] =
+        cashFlows[,c("guaranteed_advance", "guaranteed_arrears", "survival_advance", "survival_arrears", "death_SumInsured", "death_PremiumFree", "disease_SumInsured")] * sumInsured;
+      cashFlows[,c("death_GrossPremium", "death_Refund_past")] = cashFlows[,c("death_GrossPremium","death_Refund_past")] * premiums[["gross"]] * (1+refundAddon);
 
       # Sum all death-related payments to "death"  and remove the death_GrossPremium column
-      cashflows[,"death_SumInsured"] = cashflows[,"death_SumInsured"] + cashflows[,"death_GrossPremium"]
-      colnames(cashflows)[colnames(cashflows)=="death_SumInsured"] = "death";
-      # cashflows[,"death_GrossPremium"] = NULL;
+      cashFlows[,"death_SumInsured"] = cashFlows[,"death_SumInsured"] + cashFlows[,"death_GrossPremium"]
+      colnames(cashFlows)[colnames(cashFlows)=="death_SumInsured"] = "death";
+      # cashFlows[,"death_GrossPremium"] = NULL;
 
-      cashflowsCosts = cashflowsCosts[,,"SumInsured"] * sumInsured +
-        cashflowsCosts[,,"SumPremiums"] * premiumSum * premiums[["gross"]] +
-        cashflowsCosts[,,"GrossPremium"] * premiums[["gross"]];
+      cashFlowsCosts = cashFlowsCosts[,,"SumInsured"] * sumInsured +
+        cashFlowsCosts[,,"SumPremiums"] * premiumSum * premiums[["gross"]] +
+        cashFlowsCosts[,,"GrossPremium"] * premiums[["gross"]];
 
-      cbind(cashflows, cashflowsCosts)
+      cbind(cashFlows, cashFlowsCosts)
     },
 
     getAbsPresentValues = function(presentValues, premiums, sumInsured=1, premiumSum=0, ...) {
@@ -403,31 +406,31 @@ InsuranceTarif = R6Class(
       coeff
     },
 
-    premiumCalculation = function(pvBenefits, pvCosts, costs=self$costs, premiumSum=0, sumInsured=1, premiumFrequency = 1, loadings=list(), ...) {
+    premiumCalculation = function(presentValues, presentValuesCosts, costs=self$costs, premiumSum=0, sumInsured=1, premiumFrequency = 1, loadings=list(), ...) {
       # Merge a possibly passed loadings override with the defaults of this class:
       loadings = self$getLoadings(loadings=loadings);
       premiums = c("unit.net" = 0, "unit.Zillmer" = 0, "unit.gross"= 0, "net" = 0, "Zillmer" = 0, "gross" = 0, "written" = 0);
       coefficients = list("gross"=c(), "Zillmer"=c(), "net"=c());
 
       # net, gross and Zillmer premiums are calculated from the present values using the coefficients on each present value as described in the formulas document
-      coeff=self$getPremiumCoefficients("gross", pvBenefits["0",]*0, pvCosts["0",,]*0, premiums=premiums, premiumSum=premiumSum, loadings=loadings)
-      enumerator  = sum(coeff[["SumInsured"]][["benefits"]] * pvBenefits["0",]) + sum(coeff[["SumInsured"]][["costs"]] * pvCosts["0",,]);
-      denominator = sum(coeff[["Premium"   ]][["benefits"]] * pvBenefits["0",]) + sum(coeff[["Premium"   ]][["costs"]] * pvCosts["0",,]);
+      coeff=self$getPremiumCoefficients("gross", presentValues["0",]*0, presentValuesCosts["0",,]*0, premiums=premiums, premiumSum=premiumSum, loadings=loadings)
+      enumerator  = sum(coeff[["SumInsured"]][["benefits"]] * presentValues["0",]) + sum(coeff[["SumInsured"]][["costs"]] * presentValuesCosts["0",,]);
+      denominator = sum(coeff[["Premium"   ]][["benefits"]] * presentValues["0",]) + sum(coeff[["Premium"   ]][["costs"]] * presentValuesCosts["0",,]);
       ongoingAlphaGrossPremium = loadings$ongoingAlphaGrossPremium;
       premiums[["unit.gross"]] = enumerator/denominator * (1 + ongoingAlphaGrossPremium);
       premiums[["gross"]] = premiums[["unit.gross"]] * sumInsured;
       coefficients[["gross"]] = coeff;
 
-      coeff=self$getPremiumCoefficients("net", pvBenefits["0",]*0, pvCosts["0",,]*0, premiums=premiums, premiumSum=premiumSum)
-      enumerator  = sum(coeff[["SumInsured"]][["benefits"]] * pvBenefits["0",]) + sum(coeff[["SumInsured"]][["costs"]] * pvCosts["0",,]);
-      denominator = sum(coeff[["Premium"   ]][["benefits"]] * pvBenefits["0",]) + sum(coeff[["Premium"   ]][["costs"]] * pvCosts["0",,]);
+      coeff=self$getPremiumCoefficients("net", presentValues["0",]*0, presentValuesCosts["0",,]*0, premiums=premiums, premiumSum=premiumSum)
+      enumerator  = sum(coeff[["SumInsured"]][["benefits"]] * presentValues["0",]) + sum(coeff[["SumInsured"]][["costs"]] * presentValuesCosts["0",,]);
+      denominator = sum(coeff[["Premium"   ]][["benefits"]] * presentValues["0",]) + sum(coeff[["Premium"   ]][["costs"]] * presentValuesCosts["0",,]);
       premiums[["unit.net"]] = enumerator/denominator; premiums
       premiums[["net"]] = premiums[["unit.net"]] * sumInsured;
       coefficients[["net"]] = coeff;
 
-      coeff=self$getPremiumCoefficients("Zillmer", pvBenefits["0",]*0, pvCosts["0",,]*0, premiums=premiums, premiumSum=premiumSum)
-      enumerator  = sum(coeff[["SumInsured"]][["benefits"]] * pvBenefits["0",]) + sum(coeff[["SumInsured"]][["costs"]] * pvCosts["0",,]);
-      denominator = sum(coeff[["Premium"   ]][["benefits"]] * pvBenefits["0",]) + sum(coeff[["Premium"   ]][["costs"]] * pvCosts["0",,]);
+      coeff=self$getPremiumCoefficients("Zillmer", presentValues["0",]*0, presentValuesCosts["0",,]*0, premiums=premiums, premiumSum=premiumSum)
+      enumerator  = sum(coeff[["SumInsured"]][["benefits"]] * presentValues["0",]) + sum(coeff[["SumInsured"]][["costs"]] * presentValuesCosts["0",,]);
+      denominator = sum(coeff[["Premium"   ]][["benefits"]] * presentValues["0",]) + sum(coeff[["Premium"   ]][["costs"]] * presentValuesCosts["0",,]);
       premiums[["unit.Zillmer"]] = enumerator/denominator;
       premiums[["Zillmer"]] = premiums[["unit.Zillmer"]] * sumInsured;
       coefficients[["Zillmer"]] = coeff;
@@ -456,28 +459,28 @@ InsuranceTarif = R6Class(
       list("premiums"=premiums, "coefficients"=coefficients)
     },
 
-    reserveCalculation = function (premiums, presentValues, cashflows, sumInsured=1, premiumSum=0, policyPeriod = 1, age = 0, ..., loadings=list()) {
+    reserveCalculation = function (premiums, absPresentValues, absCashFlows, sumInsured=1, premiumSum=0, policyPeriod = 1, age = 0, ..., loadings=list()) {
       # Merge a possibly passed loadings override with the defaults of this class:
       loadings = self$getLoadings(loadings=loadings);
       # Net, Zillmer and Gross reserves
-      resNet = presentValues[,"benefitsAndRefund"] * (1+loadings$security) - premiums[["net"]] * presentValues[,"premiums.unit"];
-      BWZcorr = presentValues["0", "Zillmer"] / presentValues["0", "premiums"] * presentValues[,"premiums"];
+      resNet = absPresentValues[,"benefitsAndRefund"] * (1+loadings$security) - premiums[["net"]] * absPresentValues[,"premiums.unit"];
+      BWZcorr = absPresentValues["0", "Zillmer"] / absPresentValues["0", "premiums"] * absPresentValues[,"premiums"];
       resZ = resNet - BWZcorr;
 
-      resAdeq = presentValues[,"benefitsAndRefund"] * (1+loadings$security) +
-        presentValues[,"alpha"] + presentValues[,"beta"] + presentValues["gamma"] -
-        premiums[["gross"]] * presentValues[,"premiums.unit"];
+      resAdeq = absPresentValues[,"benefitsAndRefund"] * (1+loadings$security) +
+        absPresentValues[,"alpha"] + absPresentValues[,"beta"] + absPresentValues["gamma"] -
+        premiums[["gross"]] * absPresentValues[,"premiums.unit"];
 
-      #premiums[["Zillmer"]] * presentValues[,"premiums"];
-      resGamma = presentValues[,"gamma"] - presentValues["0", "gamma"] / presentValues["0", "premiums"] * presentValues[,"premiums"]
+      #premiums[["Zillmer"]] * absPresentValues[,"premiums"];
+      resGamma = absPresentValues[,"gamma"] - absPresentValues["0", "gamma"] / absPresentValues["0", "premiums"] * absPresentValues[,"premiums"]
 
 
       resConversion = (resZ + resGamma) * (1-loadings$advanceProfitParticipation);
 
       # Alpha refund: Distribute alpha-costs to 5 year (or if shorter, the policy period):
       r = min(policyPeriod, 5);
-      ZillmerSoFar = Reduce("+", cashflows$Zillmer, accumulate = TRUE);
-      ZillmerTotal = sum(cashflows$Zillmer);
+      ZillmerSoFar = Reduce("+", absCashFlows$Zillmer, accumulate = TRUE);
+      ZillmerTotal = sum(absCashFlows$Zillmer);
       len = length(ZillmerSoFar);
       if (self$features$alphaRefundLinear) {
         ZillmerVerteilungCoeff = pad0((0:r)/r, len, 1);
@@ -497,43 +500,57 @@ InsuranceTarif = R6Class(
                   "contractual"=resZ+resGamma, "conversion"=resConversion, "alphaRefund"=alphaRefund, "reduction"=resReduction
                   #, "Reserve.premiumfree"=res.premiumfree, "Reserve.gamma.premiumfree"=res.gamma.premiumfree);
       );
-      rownames(res) <- rownames(presentValues);
+      rownames(res) <- rownames(absPresentValues);
 
       # The surrender value functions can have arbitrary form, so we store a function
       # here in the tarif and call that, passing the reduction reserve as
       # starting point, but also all reserves, cash flows, premiums and present values
       if (!is.null(self$surrenderValueCalculation)) {
         surrenderValue = self$surrenderValueCalculation(
-          resReduction, reserves=res, premiums=premiums, presentValues=presentValues,
-          cashflows=cashflows, sumInsured=sumInsured, premiumSum=premiumSum,
+          resReduction, reserves=res, premiums=premiums, absPresentValues=absPresentValues,
+          absCashFlows=absCashFlows, sumInsured=sumInsured, premiumSum=premiumSum,
           policyPeriod = policyPeriod, age = age, loadings=loadings, ...);
       } else {
-        surrenderValue = resReduction;
+        # by default, refund the full reduction reserve, except the advance profit participation, which is also included in the reserve, but not charged on the premium!
+        surrenderValue = resReduction * (1-loadings$advanceProfitParticipationInclUnitCost);
       }
 
 
       # Calculate new sum insured after premium waiver
       Storno = 0; # TODO: Implement storno costs
-      newSI = (surrenderValue - presentValues[,"death_Refund_past"] * (1+loadings$security) - c(Storno)) /
-        (presentValues[, "benefits"] * (1+loadings$security) + presentValues[, "gamma_nopremiums"]) * sumInsured;
+      newSI = (surrenderValue - absPresentValues[,"death_Refund_past"] * (1+loadings$security) - c(Storno)) /
+        (absPresentValues[, "benefits"] * (1+loadings$security) + absPresentValues[, "gamma_nopremiums"]) * sumInsured;
 
       cbind(res,
-            "PremiumsPaid"=Reduce("+", cashflows$premiums_advance, accumulate = TRUE),
+            "PremiumsPaid"=Reduce("+", absCashFlows$premiums_advance, accumulate = TRUE),
             "Surrender"=surrenderValue,
             "PremiumFreeSumInsured" = newSI
       )
     },
 
-    premiumDecomposition = function(premiums, reserves, cashflows, presentValues, q, sumInsured=1, ...) {
+    getBasicDataTimeseries = function(premiums, reserves, absCashFlows, absPresentValues, sumInsured=1, policyPeriod, premiumPeriod, ...) {
+      res=cbind(
+        "PremiumPayment" = c(rep(1, premiumPeriod), rep(0, policyPeriod-premiumPeriod)),
+        "SumInsured" = rep(sumInsured, policyPeriod),
+        "Premiums" = absCashFlows$premiums_advance + absCashFlows$premiums_arrears,
+        "InterestRate" = rep(self$i, policyPeriod),
+        "PolicyDuration" = rep(policyPeriod, policyPeriod),
+        "PremiumPeriod" = rep(premiumPeriod, policyPeriod)
+      );
+      rownames(res) = 0:(policyPeriod-1);
+      res
+    },
+
+    premiumDecomposition = function(premiums, reserves, absCashFlows, absPresentValues, transitionProbabilities, sumInsured=1, ...) {
       l = dim(reserves)[[1]];
       premium.savings = getSavingsPremium(reserves[,"Zillmer"], self$v) + getSavingsPremium(reserves[,"gamma"], self$v);
       # TODO: Switch to use the Ziller or net or adequate reserve!
-      premium.risk    = self$v * (cashflows[,"death"] - c(reserves[,"Zillmer"][-1], 0)) * pad0(q$q, l) +
-        self$v * (cashflows[,"disease_SumInsured"] - c(reserves[,"Zillmer"][-1], 0)) * pad0(q$i, l);
-      # premium.risk    = self$v * (cashflows[,"death"] - c(reserves[,"Zillmer"][-1], 0)) * q$q;
+      premium.risk    = self$v * (absCashFlows[,"death"] - c(reserves[,"Zillmer"][-1], 0)) * pad0(transitionProbabilities$q, l) +
+        self$v * (absCashFlows[,"disease_SumInsured"] - c(reserves[,"Zillmer"][-1], 0)) * pad0(transitionProbabilities$i, l);
+      # premium.risk    = self$v * (absCashFlows[,"death"] - c(reserves[,"Zillmer"][-1], 0)) * transitionProbabilities$q;
 
 
-      res = cbind("savings"=premium.savings, "risk"=premium.risk, "savings+risk"= premium.savings+premium.risk, "gamma"=cashflows[,"gamma"]);
+      res = cbind("savings"=premium.savings, "risk"=premium.risk, "savings+risk"= premium.savings+premium.risk, "gamma"=absCashFlows[,"gamma"]);
       rownames(res) <- rownames(premiums);
       res
     },
@@ -541,61 +558,9 @@ InsuranceTarif = R6Class(
 
 
 
+
+
     # Dummy to allow commas
     dummy = 0
   )
 );
-#
-#
-# costs = initializeCosts();
-# # costs["alpha", "SumInsured",] = c(1,2,5);
-# # costs["beta", "SumPremiums",] = c(3,2,1);
-# costs["alpha", "SumPremiums", "once"] = 0.05;
-# costs["Zillmer", "SumPremiums", "once"] = 0.04;
-# costs["gamma", "SumInsured", "PremiumPeriod"] = 0.005;
-# costs["gamma", "SumInsured", "PremiumFree"] = 0.01;
-# costs["gamma_nopremiums", "SumInsured", "PolicyPeriod"] = 0.01;
-#
-# costs
-#
-# TestTarif = InsuranceTarif$new(name = "Testtarif", mortalityTable = AVOe2005R.male, type = "annuity", costs=costs)
-# q = TestTarif$getTransitionProbabilities(YOB = 1980, age = 30)
-# TestTarif = InsuranceTarif$new(name = "Testtarif", mortalityTable = AVOe2005R.male, type = "wholelife", costs=costs)
-# TestTarif$getBasicCashFlows(YOB = 1980, age = 30, policyPeriod = 5, deferral = 3, guaranteed=10)
-#
-# # Gemischte Versicherung, i=1%, AVÖ2005R Unisex, YOB=1980, age=30, Laufzeit=10, Prämienzahlungsdauer=5,
-# TestTarif = InsuranceTarif$new(name = "Testtarif", mortalityTable = AVOe2005R.unisex, type = "endowment", costs=costs, i=0.01)
-# TestTarif$getBasicCashFlows(YOB = 1980, age = 30, premiumPaymentPeriod = 5, policyPeriod = 10, deferral = 0, guaranteed=0)
-#
-# TestTarif$costs=costs;
-# TestTarif$premiumRefund = 0;
-#
-# cf = TestTarif$getCashFlows(YOB = 1980, age = 30, premiumPaymentPeriod = 5, policyPeriod = 10, deferral = 0, guaranteed=0); cf
-# cfc = TestTarif$getCashFlowsCosts(YOB = 1980, age = 30, premiumPaymentPeriod = 5, policyPeriod = 10, deferral = 0, guaranteed=0); cfc
-#
-# pv = TestTarif$presentValueCashFlows(cf, age = 30, YOB=1980); pv
-# pvc = TestTarif$presentValueCashFlowsCosts(cfc, age=30, YOB=1980); pvc
-#
-# premiums=TestTarif$premiumCalculation(pv, pvc, premiumSum=15); premiums
-#
-#
-#
-# premiums*1000
-# as.array(premiums)*1000
-#
-# c("net"=1, "gross"=23, "Zillmer"=44)
-# str(as.matrix( premiums))
-# as.matrix(premiums)*1000
-# scf
-# cfc
-# dim(cfc)[1]
-#
-# str(cf$premiums_advance)
-# calculatePVSurvival(q$q, cf$premiums_advance, cf$premiums_arrears, v=1/1.01)
-# calculatePVSurvival(q$q, cf$survival_advance, cf$survival_arrears, v=1/1.01)
-#
-# calculatePVDeath(q$q, cf$death_SumInsured, v=1/1.01)
-# calculatePVDeath(q$q, cf$death_GrossPremium, v=1/1.01)
-# calculatePVDeath(q$q, cf$death_PremiumFree, v=1/1.01)
-#
-#