diff --git a/ifrs17-template/Test/Data/DataNodeParameter_InvalidDataNode.csv b/ifrs17-template/Test/Data/DataNodeParameter_InvalidDataNode.csv index 681a63c5..f20a6621 100644 --- a/ifrs17-template/Test/Data/DataNodeParameter_InvalidDataNode.csv +++ b/ifrs17-template/Test/Data/DataNodeParameter_InvalidDataNode.csv @@ -3,9 +3,9 @@ ReportingNode,Year,Month CH,2020,12 @@SingleDataNodeParameter -DataNode,PremiumAllocation -DT1.1,0.9 -DataNodeInvalid0,0.85 +DataNode,PremiumAllocation,CashFlowPeriodicity,InterpolationMethod +DT1.1,0.9,Monthly,Uniform +DataNodeInvalid0,0.85,Monthly,Uniform @@InterDataNodeParameter DataNode,LinkedDataNode,ReinsuranceCoverage diff --git a/ifrs17-template/Test/Data/DataNodeParameter_InvalidParameters.csv b/ifrs17-template/Test/Data/DataNodeParameter_InvalidParameters.csv new file mode 100644 index 00000000..00108a5f --- /dev/null +++ b/ifrs17-template/Test/Data/DataNodeParameter_InvalidParameters.csv @@ -0,0 +1,17 @@ +@@Main +ReportingNode,Year,Month +CH,2020,12 + +@@SingleDataNodeParameter +DataNode,PremiumAllocation,CashFlowPeriodicity,InterpolationMethod +DT1.1,0.9,Monthly,InvalidEntry +DT1.2,0.85,InvalidEntry,Uniform +DT1.3,0.9,,Uniform +DT1.4,0.85,Monthly, +DT1.5,0.9,Yearly, + +@@InterDataNodeParameter +DataNode,LinkedDataNode,ReinsuranceCoverage +DTR1.1,DT1.1,1 +DTR1.2,DT1.2,1 +DTR1.3,DT1.3,1 diff --git a/ifrs17-template/Test/Data/DataNodeParameter_MissingNonRequiredColumns.csv b/ifrs17-template/Test/Data/DataNodeParameter_MissingNonRequiredColumns.csv new file mode 100644 index 00000000..068b8fa4 --- /dev/null +++ b/ifrs17-template/Test/Data/DataNodeParameter_MissingNonRequiredColumns.csv @@ -0,0 +1,16 @@ +@@Main +ReportingNode,Year,Month +CH,2020,12 + +@@SingleDataNodeParameter +DataNode,PremiumAllocation +DT1.1,0.9 +DT1.2,0.85 +DT1.3,0.9 +DT1.4,0.85 + +@@InterDataNodeParameter +DataNode,LinkedDataNode,ReinsuranceCoverage +DTR1.1,DT1.1,1 +DTR1.2,DT1.2,1 +DTR1.3,DT1.3,1 diff --git a/ifrs17-template/Test/MapTemplateAndImportTest.ipynb b/ifrs17-template/Test/MapTemplateAndImportTest.ipynb index 60ac6284..4702c3dd 100644 --- a/ifrs17-template/Test/MapTemplateAndImportTest.ipynb +++ b/ifrs17-template/Test/MapTemplateAndImportTest.ipynb @@ -124,6 +124,42 @@ "execution_count": 0, "outputs": [] }, + { + "cell_type": "markdown", + "source": [ + "# Test Data Node Parameter" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var singleParam = (await DataSource.Query().Where(x => x.DataNode == \"DT1.1\").ToArrayAsync()).Single();" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "singleParam.CashFlowPeriodicity.Should().Be((CashFlowPeriodicity)default);" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "singleParam.InterpolationMethod.Should().Be((InterpolationMethod)default);" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "markdown", "source": [ @@ -397,7 +433,10 @@ "\n nameof(PartitionByReportingNodeAndPeriod.Month),", "\n nameof(PartitionByReportingNodeAndPeriod.Scenario)};", "\nvar singleDataNodeParamCols = new[]{nameof(DataNode),", - "\n nameof(SingleDataNodeParameter.PremiumAllocation)};", + "\n nameof(SingleDataNodeParameter.PremiumAllocation),", + "\n nameof(SingleDataNodeParameter.CashFlowPeriodicity),", + "\n nameof(SingleDataNodeParameter.InterpolationMethod),", + "\n };", "\nvar interDataNodeParamCols = new[]{nameof(DataNodeParameter.DataNode),", "\n nameof(InterDataNodeParameter.LinkedDataNode),", "\n nameof(InterDataNodeParameter.ReinsuranceCoverage)};", @@ -546,6 +585,7 @@ "\n{", "\n Activity.Start();", "\n var log = await Import.FromFile(inputFileName).WithFormat(ImportFormats.DataNodeParameter).WithTarget(workspace).ExecuteAsync();", + "\n log.Errors.Count().Should().Be(errorBms.Count());", "\n errorBms.Intersect(log.Errors.Select(x => x.ToString().Substring(0,x.ToString().Length-2).Substring(40)).ToArray()).Count().Should().Be(errorBms.Count());", "\n return Activity.Finish();", "\n}" @@ -616,7 +656,53 @@ "source": [ "var inputFileName = \"Data/DataNodeParameter_InvalidReinsCov.csv\";", "\nvar errorsBm = new List(){Get(Error.ReinsuranceCoverageDataNode, \"DT1.1\",\"DT1.1\")};", - "\nvar activity = await CheckErrors(inputFileName, errorsBm, ws3);", + "\nvar activity = await CheckErrors(inputFileName, errorsBm, ws3);" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var ws4 = Workspace.CreateNew();", + "\nws4.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_MissingNonRequiredColumns.csv\";", + "\nvar errorsBm = new List(){};", + "\nvar activity = await CheckErrors(inputFileName, errorsBm, ws4);", + "\nactivity" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var ws5 = Workspace.CreateNew();", + "\nws5.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_InvalidParameters.csv\";", + "\nvar errorsBm = new List(){Get(Error.InvalidInterpolationMethod, \"DT1.1\"), ", + "\n Get(Error.InvalidCashFlowPeriodicity, \"DT1.2\"),", + "\n Get(Error.InvalidCashFlowPeriodicity, \"DT1.3\"),", + "\n Get(Error.InvalidInterpolationMethod, \"DT1.5\")};", + "\nvar activity = await CheckErrors(inputFileName, errorsBm, ws5);", "\nactivity" ], "metadata": {}, diff --git a/ifrs17/Constants/Enums.ipynb b/ifrs17/Constants/Enums.ipynb index aa5231be..9094ea09 100644 --- a/ifrs17/Constants/Enums.ipynb +++ b/ifrs17/Constants/Enums.ipynb @@ -206,6 +206,42 @@ "execution_count": 0, "outputs": [] }, + { + "cell_type": "markdown", + "source": [ + "## CashFlowPeriodicity" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "public enum CashFlowPeriodicity { Monthly, Quarterly, Yearly }" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "## Interpolation Method" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "public enum InterpolationMethod { NotApplicable, Uniform /*, Linear, Start, End, Custom*/ }" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "markdown", "source": [ diff --git a/ifrs17/Constants/Validations.ipynb b/ifrs17/Constants/Validations.ipynb index e214b58a..b2684e17 100644 --- a/ifrs17/Constants/Validations.ipynb +++ b/ifrs17/Constants/Validations.ipynb @@ -76,7 +76,7 @@ "\n // Data Note State", "\n ChangeDataNodeState, InactiveDataNodeState,", "\n // Parameters", - "\n ReinsuranceCoverageDataNode, DuplicateInterDataNode, DuplicateSingleDataNode, InvalidDataNode, InvalidDataNodeForOpening,", + "\n ReinsuranceCoverageDataNode, DuplicateInterDataNode, DuplicateSingleDataNode, InvalidDataNode, InvalidDataNodeForOpening, InvalidCashFlowPeriodicity, InvalidInterpolationMethod,", "\n // Storage", "\n DataNodeNotFound, PartnerNotFound, RatingNotFound, CreditDefaultRateNotFound, MissingPremiumAllocation, ReinsuranceCoverage, ", "\n YieldCurveNotFound, YieldCurvePeriodNotApplicable, EconomicBasisNotFound, AccountingVariableTypeNotFound,", @@ -151,6 +151,8 @@ "\n (Error.DuplicateSingleDataNode , 1) => $\"Duplicated Single-DataNode parameter for {s[0]} is found.\",", "\n (Error.InvalidDataNode , 1) => $\"Data imported for invalid Data Node {s[0]}.\",", "\n (Error.InvalidDataNodeForOpening , 1) => $\"Data imported for invalid Data Node or for a Data Node after its inception year {s[0]}.\",", + "\n (Error.InvalidCashFlowPeriodicity, 1) => $\"Single Data Node Parameter CashFlowPeriodicity for Data Node {s[0]} is invalid.\",", + "\n (Error.InvalidInterpolationMethod, 1) => $\"Single Data Node Parameter InterpolationMethod for Data Node {s[0]} is invalid.\",", "\n // Storage", "\n (Error.DataNodeNotFound , 1) => $\"DataNode {s[0]} not found.\",", "\n (Error.PartnerNotFound , 1) => $\"Partner not found for DataNode {s[0]}.\",", diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index 78f4144a..8800c837 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -1541,6 +1541,8 @@ "\n", "\nData Node Parameters are used to keep track of other parameters pertaining to each Data Node, and their movements in time (year and month).", "\n
PremiumAllocation : defines the weight of Premium to be included in the Experience Adjustement AoC Type of the Technical Margin and is valid only for Group of Insurance Contract with LiabilityType : Liability for Remaining Coverage.", + "\n
CashFlowPeriodicity : defines the periodicity of the provided cash flows, it is not a mandatory input. Supported values can be found [here](../Constants/Enums#cashflowperiodicity). When the column *CashFlowPeriodicity* is missing from the input file it is assumed a monthly periodicity (default value). When the *CashFlowPeriodicity* column is present, a valid value must be entered. ", + "\n
InterpolationMethod : defines the interpolation method to be applied to interpolate the cash flow to the monthly granularity, it is not a mandatory input. Supported values can be found [here](../Constants/Enums#interpolation-method). When the *InterpolationMethod* is not present in the input file or the *CashFlowPeriodicity* has the default value, then the default value for the *InterpolationMethod* is applied. The default value is Not Applicable. ", "\n
ReinsuranceCoverage : defines the weight of the underlying gross business to be considered in the computation of the allocation of the Technical Margin in a Reinsurance case. In other words, it represents the percentage to which claims in the underlying GICs are expected to be reinboursed by the Reinsurance Contracts belonging to the GRIC. For proportional contracts, this factor is given by the cession while for other contracts it should be estimated. ", "\n", "\nThe latest Data Node Parameters available in the system with Year and Month earlier or equal to Year and Month of the closing period will be used as the current value during calculation." @@ -1576,6 +1578,7 @@ "\n [Required]", "\n [IdentityProperty]", "\n [Dimension(typeof(GroupOfContract))]", + "\n [Display(Order = 1)]", "\n public string DataNode { get; init; }", "\n", "\n [IdentityProperty]", @@ -1593,16 +1596,30 @@ "public record SingleDataNodeParameter : DataNodeParameter {", "\n [DefaultValue(DefaultPremiumExperienceAdjustmentFactor)]", "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", "\n public double PremiumAllocation { get; init; } = DefaultPremiumExperienceAdjustmentFactor;", + "\n", + "\n [IdentityProperty]", + "\n [Dimension(typeof(CashFlowPeriodicity))]", + "\n [Display(Order = 30)]", + "\n public CashFlowPeriodicity CashFlowPeriodicity { get; init; }", + "\n ", + "\n [IdentityProperty]", + "\n [Dimension(typeof(InterpolationMethod))]", + "\n [Display(Order = 40)]", + "\n public InterpolationMethod InterpolationMethod { get; init; }", + "\n ", "\n}", "\n", "\npublic record InterDataNodeParameter : DataNodeParameter {", "\n [Required]", "\n [IdentityProperty]", "\n [Dimension(typeof(GroupOfContract))]", + "\n [Display(Order = 10)]", "\n public string LinkedDataNode { get; init; }", "\n ", "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", "\n public double ReinsuranceCoverage { get; init; }", "\n}" ], diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index d275d21a..95664866 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -74,7 +74,8 @@ "\n private Dictionary> amountTypesByEstimateType => GetAmountTypesByEstimateType(HierarchyCache);", "\n public HashSet TechnicalMarginEstimateTypes => GetTechnicalMarginEstimateType(); ", "\n public Dictionary> DimensionsWithExternalId;", - "\n ", + "\n public Dictionary> SingleDataNodeParametersByGoc { get; private set; }", + "\n", "\n // Partitions", "\n public PartitionByReportingNode TargetPartitionByReportingNode;", "\n public PartitionByReportingNodeAndPeriod TargetPartitionByReportingNodeAndPeriod;", @@ -141,6 +142,9 @@ "\n DataNodeDataBySystemName = args.ImportFormat == ImportFormats.Opening ", "\n ? (await LoadDataNodesAsync(dataSource, args)).Where(kvp => kvp.Value.Year == args.Year).ToDictionary(kvp => kvp.Key, kvp => kvp.Value)", "\n : await LoadDataNodesAsync(dataSource, args);", + "\n", + "\n SingleDataNodeParametersByGoc = await dataSource.LoadSingleDataNodeParametersAsync(args);", + "\n", "\n // Dimensions", "\n EstimateType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", "\n AmountType = (await dataSource.Query().Where(x =>!(x is DeferrableAmountType)).ToArrayAsync()).ToDictionary(x => x.SystemName);", @@ -185,7 +189,19 @@ "\n // Getters", "\n public bool IsDataNodeReinsurance(string goc) => DataNodeDataBySystemName[goc].IsReinsurance;", "\n public bool IsValidDataNode(string goc) => DataNodeDataBySystemName.ContainsKey(goc);", - "\n ", + "\n", + "\n public CashFlowPeriodicity GetCashFlowPeriodicity(string goc) {", + "\n if(!SingleDataNodeParametersByGoc.TryGetValue(goc, out var inner)) ", + "\n return CashFlowPeriodicity.Monthly;", + "\n return inner[CurrentPeriod].CashFlowPeriodicity; ", + "\n }", + "\n", + "\n public InterpolationMethod GetInterpolationMethod(string goc) {", + "\n if(!SingleDataNodeParametersByGoc.TryGetValue(goc, out var inner))", + "\n return InterpolationMethod.NotApplicable;", + "\n return inner[CurrentPeriod].InterpolationMethod; ", + "\n }", + "\n", "\n // Validations", "\n public string ValidateEstimateType(string et, string goc) {", "\n var allowedEstimateTypes = estimateTypes;", @@ -1102,7 +1118,10 @@ "\n if(Activity.HasErrors()) return Activity.Finish();", "\n var singleDataNode = new List();", "\n var interDataNode = new List<(string,string)>();", - "\n ", + "\n", + "\n var hasCashFlowPeriodicityColumn = dataSet.Tables[nameof(SingleDataNodeParameter)].Columns.Any(x => x.ColumnName == nameof(SingleDataNodeParameter.CashFlowPeriodicity));", + "\n var hasInterpolationMethodColumn = dataSet.Tables[nameof(SingleDataNodeParameter)].Columns.Any(x => x.ColumnName == nameof(SingleDataNodeParameter.InterpolationMethod));", + "\n", "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType( (dataset, datarow) => {", "\n", @@ -1114,6 +1133,21 @@ "\n if(singleDataNode.Contains(dataNode)) { ApplicationMessage.Log(Error.DuplicateSingleDataNode, dataNode); return null; }", "\n singleDataNode.Add(dataNode);", "\n ", + "\n CashFlowPeriodicity periodicity = default;", + "\n if (hasCashFlowPeriodicityColumn)", + "\n if ( Enum.TryParse(datarow.Field(nameof(SingleDataNodeParameter.CashFlowPeriodicity)), out CashFlowPeriodicity cfp))", + "\n periodicity = cfp;", + "\n else { ApplicationMessage.Log(Error.InvalidCashFlowPeriodicity, dataNode); return null; }", + "\n", + "\n InterpolationMethod interpolationMethod = default;", + "\n if(hasInterpolationMethodColumn)", + "\n {", + "\n var interpolationMethodInput = datarow.Field(nameof(SingleDataNodeParameter.InterpolationMethod));", + "\n if ( Enum.TryParse(interpolationMethodInput, out InterpolationMethod ipm)) ", + "\n interpolationMethod = ipm;", + "\n else if ( !(periodicity == (CashFlowPeriodicity)default && string.IsNullOrEmpty(interpolationMethodInput)) ) { ApplicationMessage.Log(Error.InvalidInterpolationMethod, dataNode); return null; }", + "\n }", + "\n", "\n //Instantiate SingleDataNodeParameter", "\n return new SingleDataNodeParameter {", "\n Year = args.Year,", @@ -1121,6 +1155,8 @@ "\n Scenario = args.Scenario,", "\n Partition = storage.TargetPartitionByReportingNode.Id,", "\n DataNode = dataNode,", + "\n CashFlowPeriodicity = periodicity,", + "\n InterpolationMethod = interpolationMethod,", "\n PremiumAllocation = (datarow.Field(nameof(SingleDataNodeParameter.PremiumAllocation)))", "\n .ToString().CheckStringForExponentialAndConvertToDouble(),", "\n };", @@ -1256,6 +1292,7 @@ "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var hasAccidentYearColumn = dataSet.Tables[ImportFormats.Cashflow].Columns.Any(x => x.ColumnName == nameof(RawVariable.AccidentYear));", + "\n ", "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType ( (dataset, datarow) => {", "\n var aocType = datarow.Field(nameof(RawVariable.AocType));", @@ -1288,7 +1325,7 @@ "\n values = values.Prune();", "\n if(values.Length == 0 && !parsingStorage.MandatoryAocSteps.Contains(new AocStep(aocType, novelty))) return null;", "\n }", - "\n ", + "\n ", "\n var item = new RawVariable {", "\n DataNode = dataNode,", "\n AocType = aocType,", @@ -1300,6 +1337,7 @@ "\n : (int?)null,", "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", "\n Values = Multiply(GetSign(ImportFormats.Cashflow, (aocType, valueType.AmountType, valueType.EstimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), values)", + "\n .Interpolate(parsingStorage.GetCashFlowPeriodicity(dataNode), parsingStorage.GetInterpolationMethod(dataNode))", "\n };", "\n return item;", "\n }, ImportFormats.Cashflow", diff --git a/ifrs17/Test/AggregateDoubleArrayTest.ipynb b/ifrs17/Test/AggregateInterpolateTest.ipynb similarity index 68% rename from ifrs17/Test/AggregateDoubleArrayTest.ipynb rename to ifrs17/Test/AggregateInterpolateTest.ipynb index 9d9a9b35..7b659c85 100644 --- a/ifrs17/Test/AggregateDoubleArrayTest.ipynb +++ b/ifrs17/Test/AggregateInterpolateTest.ipynb @@ -19,13 +19,22 @@ { "cell_type": "code", "source": [ - "#!import \"../Utils/Extensions\"", + "#!import \"../Utils/ImportCalculationMethods\"", "\n#!import \"../Utils/TestHelper\"" ], "metadata": {}, "execution_count": 0, "outputs": [] }, + { + "cell_type": "markdown", + "source": [ + "# Aggregation" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "code", "source": [ @@ -119,10 +128,51 @@ "execution_count": 0, "outputs": [] }, + { + "cell_type": "markdown", + "source": [ + "# Values Interpolation" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var cashflow = new double [] {120, 180} ;", + "\nvar yearly = cashflow.Interpolate(CashFlowPeriodicity.Yearly, InterpolationMethod.Uniform);", + "\n(yearly[0], yearly[11], yearly[12], yearly[23]).Should().Be((10, 10, 15, 15));" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var quarterly = cashflow.Interpolate(CashFlowPeriodicity.Quarterly, InterpolationMethod.Uniform);", + "\n(quarterly[0], quarterly[3], quarterly[4], quarterly[6]).Should().Be((30, 30, 45, 45));" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var monthly = cashflow.Interpolate(CashFlowPeriodicity.Monthly, InterpolationMethod.Uniform);", + "\n(monthly[0], monthly[1]).Should().Be((120,180));" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "code", "source": [ - "" + "var yearly = cashflow.Interpolate(CashFlowPeriodicity.Yearly, InterpolationMethod.NotApplicable);", + "\n(yearly[0], yearly[11], yearly[12], yearly[23]).Should().Be((10, 10, 15, 15));" ], "metadata": {}, "execution_count": 0, diff --git a/ifrs17/Test/Tests.ipynb b/ifrs17/Test/Tests.ipynb index 5a6b070d..31977d75 100644 --- a/ifrs17/Test/Tests.ipynb +++ b/ifrs17/Test/Tests.ipynb @@ -55,7 +55,7 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"AggregateDoubleArrayTest\"" + "#!eval-notebook \"AggregateInterpolateTest\"" ], "metadata": {}, "execution_count": 0, diff --git a/ifrs17/Utils/ImportCalculationMethods.ipynb b/ifrs17/Utils/ImportCalculationMethods.ipynb index c1c3de8a..7f04345b 100644 --- a/ifrs17/Utils/ImportCalculationMethods.ipynb +++ b/ifrs17/Utils/ImportCalculationMethods.ipynb @@ -206,6 +206,39 @@ "execution_count": 0, "outputs": [] }, + { + "cell_type": "markdown", + "source": [ + "## Interpolate" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "public static double[] Interpolate(this double[] cashflowValues, CashFlowPeriodicity periodicity, InterpolationMethod interpolationMethod)", + "\n{ ", + "\n if (periodicity == CashFlowPeriodicity.Monthly)", + "\n return cashflowValues;", + "\n ", + "\n var frequency = periodicity switch {", + "\n CashFlowPeriodicity.Yearly => 12,", + "\n CashFlowPeriodicity.Quarterly => 4,", + "\n _ => 1", + "\n };", + "\n ", + "\n return interpolationMethod switch {", + "\n InterpolationMethod.Uniform or _ => cashflowValues.SelectMany(v => Enumerable.Range(0, frequency).Select( _ => v / (double)frequency)).ToArray()", + "\n };", + "\n", + "\n}" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "markdown", "source": [ diff --git a/ifrs17/Utils/Queries.ipynb b/ifrs17/Utils/Queries.ipynb index 809fe695..e56cd20e 100644 --- a/ifrs17/Utils/Queries.ipynb +++ b/ifrs17/Utils/Queries.ipynb @@ -186,7 +186,7 @@ "\n", "\n{", "\n var lockedInYieldCurveByGoc = new Dictionary();", - "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", + "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach != ValuationApproaches.VFA))", "\n {", "\n var monthUpperLimit = args.Year == dn.Year ? args.Month : MonthInAYear;", "\n var argsNew = args with {Year = dn.Year, Month = monthUpperLimit, Scenario = args.Scenario};",