From 6d7c59e91f982729fe5f44b8337e3fc6e6e3b6e6 Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Wed, 28 Sep 2022 14:26:02 +0200 Subject: [PATCH 01/38] base code --- Constants/Consts.ipynb | 386 +++ Constants/Enums.ipynb | 269 ++ Constants/Validations.ipynb | 200 ++ DataModel/DataStructure.ipynb | 2139 ++++++++++++ Database/.gitignore | 1 + Database/Configure.ipynb | 131 + Database/Schema Delete.ipynb | 87 + Export/MapTemplate.ipynb | 338 ++ Files/300.ReportingNodes/ReportingNodes.csv | 10 + .../DataNodeParameters_CH_2020_12.csv | 22 + .../DataNodeStates_CH_2020_12.csv | 19 + Files/700.DataNodes/DataNodes_CH.csv | 36 + Files/800.Parameters/CreditDefaultRate.csv | 23 + Files/800.Parameters/ExchangeRate.csv | 14 + Files/800.Parameters/PartnerRating.csv | 4 + Files/800.Parameters/YieldCurve.csv | 11 + .../Actuals_CH_2020_12.csv | 33 + .../Actuals_CH_2021_3.csv | 62 + .../NominalCashflows_CH_2020_12.csv | 85 + .../NominalCashflows_CH_2021_3.csv | 158 + .../Openings_CH_2020_12.csv | 8 + Files/DimensionsAndPartitions.csv | 259 ++ Images/ActualFormat.png | Bin 0 -> 25544 bytes Images/CashflowFormat.png | Bin 0 -> 66204 bytes Images/OpeningFormat.png | Bin 0 -> 19729 bytes Images/SpecificationsCSM.PNG | Bin 0 -> 40913 bytes Images/SpecificationsImportActuals.PNG | Bin 0 -> 12211 bytes Images/SpecificationsImportCashflows.PNG | Bin 0 -> 38471 bytes Images/SpecificationsPL.PNG | Bin 0 -> 79272 bytes Images/Systemorph_logo.png | Bin 0 -> 17061 bytes Import/ImportResultPreview.ipynb | 344 ++ Import/ImportScopeCalculation.ipynb | 2296 +++++++++++++ Import/ImportStorage.ipynb | 387 +++ Import/Importers.ipynb | 1199 +++++++ .../InitSystemorphBaseToMemory.ipynb | 268 ++ Initialization/InitSystemorphToDatabase.ipynb | 314 ++ Initialization/InitSystemorphToMemory.ipynb | 147 + InputFormatDescription.ipynb | 113 + OverviewCalculationEngine.ipynb | 258 ++ Report/ReportConfigurationAndUtils.ipynb | 148 + Report/ReportScopes.ipynb | 1038 ++++++ Report/ReportStorage.ipynb | 241 ++ Report/Reports.ipynb | 516 +++ Test/AocStructureTest.ipynb | 704 ++++ Test/Data/CashflowComplex.csv | 9 + Test/Data/DataNodeParameter_Duplicate.csv | 13 + .../DataNodeParameter_InvalidDataNode.csv | 14 + .../DataNodeParameter_InvalidReinsCov.csv | 12 + .../BM_CH_2020_12_A.csv | 34 + .../BM_CH_2020_12_AA.csv | 8 + .../BM_CH_2020_12_APA.csv | 11 + .../BM_CH_2020_12_BE.csv | 181 + .../BM_CH_2020_12_BEPA.csv | 11 + .../BM_CH_2020_12_C.csv | 40 + .../BM_CH_2020_12_DA.csv | 21 + .../BM_CH_2020_12_F.csv | 17 + .../BM_CH_2020_12_OA.csv | 8 + .../BM_CH_2020_12_RA.csv | 94 + .../IfrsVariableBenchmarks/BM_CH_2021_3_A.csv | 39 + .../BM_CH_2021_3_AA.csv | 26 + .../BM_CH_2021_3_AAPA.csv | 11 + .../BM_CH_2021_3_APA.csv | 11 + .../BM_CH_2021_3_BE.csv | 471 +++ .../BM_CH_2021_3_BEPA.csv | 16 + .../IfrsVariableBenchmarks/BM_CH_2021_3_C.csv | 55 + .../BM_CH_2021_3_DA.csv | 25 + .../IfrsVariableBenchmarks/BM_CH_2021_3_F.csv | 17 + .../IfrsVariableBenchmarks/BM_CH_2021_3_L.csv | 22 + .../BM_CH_2021_3_LR.csv | 13 + .../BM_CH_2021_3_OA.csv | 26 + .../BM_CH_2021_3_OAPA.csv | 11 + .../BM_CH_2021_3_RA.csv | 215 ++ ...ableBenchmarks_2020_12_CH__Contractual.csv | 537 +++ ...iableBenchmarks_2021_3_CH__Contractual.csv | 1113 +++++++ Test/ExportIfrsVariable.ipynb | 124 + Test/ExportReportVariables.ipynb | 186 ++ Test/IfrsVariablesTest.ipynb | 327 ++ Test/ImportStorageTest.ipynb | 707 ++++ Test/MapTemplateAndImportTest.ipynb | 564 ++++ Test/QueriesTest.ipynb | 535 +++ Test/ReportStorageTest.ipynb | 127 + Test/ReportVariablesTest.ipynb | 256 ++ Test/ReportVariablesTestBase.ipynb | 161 + Test/SpecificationsFinancialPerformance.ipynb | 1692 ++++++++++ Test/SpecificationsImportActuals.ipynb | 705 ++++ Test/SpecificationsImportCashflows.ipynb | 2906 +++++++++++++++++ Test/SpecificationsSetup.ipynb | 137 + Test/SpecificationsTechnicalMargin.ipynb | 2576 +++++++++++++++ Test/TechnicalMarginTest.ipynb | 305 ++ Test/Tests.ipynb | 183 ++ Utils/ApplicationMessage.ipynb | 149 + Utils/UtilityMethods.ipynb | 1155 +++++++ 92 files changed, 28144 insertions(+) create mode 100644 Constants/Consts.ipynb create mode 100644 Constants/Enums.ipynb create mode 100644 Constants/Validations.ipynb create mode 100644 DataModel/DataStructure.ipynb create mode 100644 Database/.gitignore create mode 100644 Database/Configure.ipynb create mode 100644 Database/Schema Delete.ipynb create mode 100644 Export/MapTemplate.ipynb create mode 100644 Files/300.ReportingNodes/ReportingNodes.csv create mode 100644 Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv create mode 100644 Files/700.DataNodes/DataNodeStates_CH_2020_12.csv create mode 100644 Files/700.DataNodes/DataNodes_CH.csv create mode 100644 Files/800.Parameters/CreditDefaultRate.csv create mode 100644 Files/800.Parameters/ExchangeRate.csv create mode 100644 Files/800.Parameters/PartnerRating.csv create mode 100644 Files/800.Parameters/YieldCurve.csv create mode 100644 Files/900.TransactionalData/Actuals_CH_2020_12.csv create mode 100644 Files/900.TransactionalData/Actuals_CH_2021_3.csv create mode 100644 Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv create mode 100644 Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv create mode 100644 Files/900.TransactionalData/Openings_CH_2020_12.csv create mode 100644 Files/DimensionsAndPartitions.csv create mode 100644 Images/ActualFormat.png create mode 100644 Images/CashflowFormat.png create mode 100644 Images/OpeningFormat.png create mode 100644 Images/SpecificationsCSM.PNG create mode 100644 Images/SpecificationsImportActuals.PNG create mode 100644 Images/SpecificationsImportCashflows.PNG create mode 100644 Images/SpecificationsPL.PNG create mode 100644 Images/Systemorph_logo.png create mode 100644 Import/ImportResultPreview.ipynb create mode 100644 Import/ImportScopeCalculation.ipynb create mode 100644 Import/ImportStorage.ipynb create mode 100644 Import/Importers.ipynb create mode 100644 Initialization/InitSystemorphBaseToMemory.ipynb create mode 100644 Initialization/InitSystemorphToDatabase.ipynb create mode 100644 Initialization/InitSystemorphToMemory.ipynb create mode 100644 InputFormatDescription.ipynb create mode 100644 OverviewCalculationEngine.ipynb create mode 100644 Report/ReportConfigurationAndUtils.ipynb create mode 100644 Report/ReportScopes.ipynb create mode 100644 Report/ReportStorage.ipynb create mode 100644 Report/Reports.ipynb create mode 100644 Test/AocStructureTest.ipynb create mode 100644 Test/Data/CashflowComplex.csv create mode 100644 Test/Data/DataNodeParameter_Duplicate.csv create mode 100644 Test/Data/DataNodeParameter_InvalidDataNode.csv create mode 100644 Test/Data/DataNodeParameter_InvalidReinsCov.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv create mode 100644 Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv create mode 100644 Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv create mode 100644 Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv create mode 100644 Test/ExportIfrsVariable.ipynb create mode 100644 Test/ExportReportVariables.ipynb create mode 100644 Test/IfrsVariablesTest.ipynb create mode 100644 Test/ImportStorageTest.ipynb create mode 100644 Test/MapTemplateAndImportTest.ipynb create mode 100644 Test/QueriesTest.ipynb create mode 100644 Test/ReportStorageTest.ipynb create mode 100644 Test/ReportVariablesTest.ipynb create mode 100644 Test/ReportVariablesTestBase.ipynb create mode 100644 Test/SpecificationsFinancialPerformance.ipynb create mode 100644 Test/SpecificationsImportActuals.ipynb create mode 100644 Test/SpecificationsImportCashflows.ipynb create mode 100644 Test/SpecificationsSetup.ipynb create mode 100644 Test/SpecificationsTechnicalMargin.ipynb create mode 100644 Test/TechnicalMarginTest.ipynb create mode 100644 Test/Tests.ipynb create mode 100644 Utils/ApplicationMessage.ipynb create mode 100644 Utils/UtilityMethods.ipynb diff --git a/Constants/Consts.ipynb b/Constants/Consts.ipynb new file mode 100644 index 00000000..21850a86 --- /dev/null +++ b/Constants/Consts.ipynb @@ -0,0 +1,386 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "2kYu9e9ygUipdOuqA9Hk6A", + "cell_type": "markdown", + "source": [ + "

Consts

" + ], + "metadata": {} + }, + { + "id": "DmUpa-myfk6s7tnBoktcyw", + "cell_type": "markdown", + "source": [ + "# Numerical Precision" + ], + "metadata": {} + }, + { + "id": "KG3zmL2K_kGTNzWA2eQJvg", + "cell_type": "code", + "source": [ + "public const double Precision = 1E-5;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gMPLPUb7kUiJnLQWtEkkFA", + "cell_type": "code", + "source": [ + "public const double ProjectionPrecision = 1E-3;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gv0HnKTwuU--7Xo8e6UU2w", + "cell_type": "code", + "source": [ + "public const double BenchmarkPrecision = 1E-4;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gbuDd5t2Ike1Jq-lnVVIqg", + "cell_type": "markdown", + "source": [ + "# Time Period" + ], + "metadata": {} + }, + { + "id": "oX6yOw75DE-NwrYkdYTmzg", + "cell_type": "code", + "source": [ + "public const int CurrentPeriod = 0; " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2XFjLebnDEWBoNCyq6lKgg", + "cell_type": "code", + "source": [ + "public const int PreviousPeriod = -1; " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5ydvfd1abEm-CSTH-csz-g", + "cell_type": "code", + "source": [ + "public const int MonthInAYear = 12;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yhpv5BPDJUGKucF6Y_AVeQ", + "cell_type": "markdown", + "source": [ + "# Defaults" + ], + "metadata": {} + }, + { + "id": "uOfb6nvi8USI3mPOH8YvwQ", + "cell_type": "code", + "source": [ + "public const int DefaultDataNodeActivationMonth = 1;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZU5IN71RqEmHfRQSSCUvnw", + "cell_type": "code", + "source": [ + "public const double DefaultPremiumExperienceAdjustmentFactor = 1.0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KNUzhe58B0GBnCuZD1ATOg", + "cell_type": "markdown", + "source": [ + "# Names" + ], + "metadata": {} + }, + { + "id": "hZGPPDopiECnoXlB48cB2Q", + "cell_type": "code", + "source": [ + "public const string Main = nameof(Main);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "w5Zs2AGjxkWgRQfAGs8BIA", + "cell_type": "code", + "source": [ + "public const string Default = nameof(Default);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jAyhudwOJkmsPwMaZM1P4g", + "cell_type": "code", + "source": [ + "public const string ValueType = nameof(ValueType);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Aj_qnZxiqUeFHk088tNruA", + "cell_type": "markdown", + "source": [ + "GroupCurrency defines the SystemName (from Currency Dimension) to be used as the Group Currency." + ], + "metadata": {} + }, + { + "id": "pvlhKSXdW0Wt3dns45SWfQ", + "cell_type": "code", + "source": [ + "public const string GroupCurrency = \"CHF\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9SCJFj6zcUK_5Uczpicjjw", + "cell_type": "markdown", + "source": [ + "# Import Formats" + ], + "metadata": {} + }, + { + "id": "xEDrrk_AxUicpKHTSr6acA", + "cell_type": "code", + "source": [ + "public static class ImportFormats{", + "\n public const string Cashflow = nameof(Cashflow);", + "\n public const string Actual = nameof(Actual);", + "\n public const string DataNodeParameter = nameof(DataNodeParameter);", + "\n public const string SimpleValue = nameof(SimpleValue);", + "\n public const string Opening = nameof(Opening);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DQHpY4V8xUOGR8L84B7DTg", + "cell_type": "markdown", + "source": [ + "# IFRS specific" + ], + "metadata": {} + }, + { + "id": "YjgOf6OCyUuxcwR9IhoZvA", + "cell_type": "code", + "source": [ + "public static class ValuationApproaches{", + "\n public const string BBA = nameof(BBA); //Building Block Approach", + "\n public const string VFA = nameof(VFA); //Variable Fee Approach", + "\n public const string PAA = nameof(PAA); //Premium Allocation Approach", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pMhVfzvrjkyXcNpx0Tn4wA", + "cell_type": "code", + "source": [ + "public static class LiabilityTypes{", + "\n public const string LRC = nameof(LRC); //Liability for Remaining Coverage", + "\n public const string LIC = nameof(LIC); //Liability Incurred Claims", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1eDEjgoZmEOfPbRzZthlTQ", + "cell_type": "code", + "source": [ + "public static class CalculationTypes{", + "\n public const string BE = nameof(BE); //Best Estimate", + "\n public const string CU = nameof(CU); //Coverage Units", + "\n public const string RA = nameof(RA); //Risk Adjustment", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "b6cmqzNyQ0q0McHf-Rf5lw", + "cell_type": "code", + "source": [ + "public static class EstimateTypes{", + "\n public const string BE = nameof(BE); //Best Estimate", + "\n public const string RA = nameof(RA); //Risk Adjustment", + "\n public const string A = nameof(A); //Actuals", + "\n public const string AA = nameof(AA); //Advance Actuals", + "\n public const string OA = nameof(OA); //Overdue Actuals", + "\n public const string DA = nameof(DA); //Deferrable Actuals", + "\n public const string C = nameof(C); //Contractual Service Margin", + "\n public const string L = nameof(L); //Loss Component", + "\n public const string LR = nameof(LR); //Loss Recovery", + "\n public const string F = nameof(F); //factors", + "\n public const string FCF = nameof(FCF); //Fulfilment Cash flows", + "\n public const string BEPA = nameof(BEPA); //Experience Adjusted BE Premium to Csm", + "\n public const string APA = nameof(APA); //Experience Adjusted Written Actual Premium to Csm", + "\n public const string AAPA = nameof(AAPA); //Experience Adjusted Advance Actual Premium to Csm", + "\n public const string OAPA = nameof(OAPA); //Experience Adjusted Overdue Actual Premium to Csm", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vCJNvDF6D02HPepD8ay2pA", + "cell_type": "code", + "source": [ + "public static class AocTypes{", + "\n public const string BOP = nameof(BOP);", + "\n public const string MC = nameof(MC);", + "\n public const string RCU = nameof(RCU);", + "\n public const string CF = nameof(CF);", + "\n public const string IA = nameof(IA);", + "\n public const string YCU = nameof(YCU);", + "\n public const string CRU = nameof(CRU);", + "\n public const string WO = nameof(WO);", + "\n public const string EV = nameof(EV);", + "\n public const string CL = nameof(CL);", + "\n public const string EA = nameof(EA);", + "\n public const string AM = nameof(AM);", + "\n public const string FX = nameof(FX);", + "\n public const string EOP = nameof(EOP);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OE45Je2KUk6WlHo9upd5fA", + "cell_type": "code", + "source": [ + "public static class Novelties{", + "\n public const string I = nameof(I); //In-Force", + "\n public const string N = nameof(N); //New Business", + "\n public const string C = nameof(C); //All Novelties Combined", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BUPmJSTjdkuP8nR7MJyQiw", + "cell_type": "code", + "source": [ + "public static class EconomicBases{", + "\n public const string L = nameof(L); //Locked Interest Rates", + "\n public const string C = nameof(C); //Current Interest Rates", + "\n public const string N = nameof(N); //Nominal Interest Rates", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-cRhXT5tKE-834Umpyaudw", + "cell_type": "code", + "source": [ + "public static class AmountTypes{", + "\n public const string ACA = nameof(ACA); //Attributable Commissions Acquisition", + "\n public const string AEA = nameof(AEA); //Attributable Expenses Acquisition", + "\n public const string CDR = nameof(CDR); //Credit Default Risk", + "\n public const string CL = nameof(CL); //Claims", + "\n public const string PR = nameof(PR); //Premiums", + "\n public const string NIC = nameof(NIC); //Claims Non-Investment component", + "\n public const string ICO = nameof(ICO); //Claims Investment component", + "\n public const string NE = nameof(NE); //Non Attributable Expenses", + "\n public const string ACM = nameof(ACM); //Attributable Commissions Maintenance", + "\n public const string AEM = nameof(AEM); //Attributable Expenses Maintenance", + "\n public const string AC = nameof(AC); //Attributable Commissions", + "\n public const string AE = nameof(AE); //Attributable Expenses", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "e33hFwGm9kmVNOsShmvn4w", + "cell_type": "markdown", + "source": [ + "# Insurance specific" + ], + "metadata": {} + }, + { + "id": "9n2de6iCUEKECrkoUtSuiw", + "cell_type": "code", + "source": [ + "public static class LineOfBusinesses{", + "\n public const string LI = nameof(LI); //Life", + "\n public const string NL = nameof(NL); //Non-Life", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Constants/Enums.ipynb b/Constants/Enums.ipynb new file mode 100644 index 00000000..5700a892 --- /dev/null +++ b/Constants/Enums.ipynb @@ -0,0 +1,269 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "HUFgBXkmYU6rV0daYBo-nQ", + "cell_type": "markdown", + "source": [ + "# Enumerables", + "\n", + "\nIn the case of data which is not expected to change over time, it is convenient to introduce such data as variables of type \"enumerable\"." + ], + "metadata": {} + }, + { + "id": "ALWeaAkPh0uiwQ9SYb9Y-w", + "cell_type": "markdown", + "source": [ + "## Exchange Rates", + "\n", + "\nFor exchange rates, we set the type for which the rates apply:" + ], + "metadata": {} + }, + { + "id": "W6x_0Pa3_kOAd3N9CBgcgQ", + "cell_type": "code", + "source": [ + "public enum FxType { Spot, Average }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "r50zPe2AP0KrCOR-fgpccg", + "cell_type": "code", + "source": [ + "public enum FxPeriod { NotApplicable, BeginningOfPeriod, Average, EndOfPeriod }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YCF3tVHQB0eUa0yWpiRD0g", + "cell_type": "markdown", + "source": [ + "## Currency Types" + ], + "metadata": {} + }, + { + "id": "cF0fRptcGE64Vr1b058rqg", + "cell_type": "markdown", + "source": [ + "Currency Types define which currency is used as standard at different aggregation levels (in the Data Level hierarchy).", + "\n- Functional: this is the standard Currency Type at Reporting Node level", + "\n- Group: this is the standard Currency Type at Group level", + "\n- Contractual: this is the standard Currency Type at Data Node level", + "\n- Transactional: this is the standard Currency Type at Transactional level (used typically for Actuals)" + ], + "metadata": {} + }, + { + "id": "zj07LR0PT0CesH4nRl1Sig", + "cell_type": "code", + "source": [ + "public enum CurrencyType { Functional, Group, Contractual, Transactional }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wL17I9jyQ0eaeXrSdlvJyA", + "cell_type": "markdown", + "source": [ + "## Period Type" + ], + "metadata": {} + }, + { + "id": "3e3wVNw-rECnTHBTkVOfCQ", + "cell_type": "code", + "source": [ + "public enum PeriodType { NotApplicable, BeginningOfPeriod, EndOfPeriod }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Expd7Urm102om6-y2Skz4w", + "cell_type": "markdown", + "source": [ + "## Valuation Period" + ], + "metadata": {} + }, + { + "id": "dsJwHWIQPkOB29dEUCLHGg", + "cell_type": "code", + "source": [ + "public enum ValuationPeriod { NotApplicable, BeginningOfPeriod, MidOfPeriod, Delta, EndOfPeriod }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iejG0G0VJ0q_tAg2HGHuOw", + "cell_type": "markdown", + "source": [ + "## Portfolio View" + ], + "metadata": {} + }, + { + "id": "0Pdzxbnsx0SOaIiUb_X1YQ", + "cell_type": "code", + "source": [ + "[Flags] public enum PortfolioView { Gross = 1, Reinsurance = 2, Net = Gross | Reinsurance }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "v7NVqB0p1Ei4vilTCiErFg", + "cell_type": "markdown", + "source": [ + "## Structure Type" + ], + "metadata": {} + }, + { + "id": "Kge1fD31n0S7BW0EiClT0g", + "cell_type": "code", + "source": [ + "public enum StructureType { None, AoC }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "S49a3Gcz_0S7apcSmQy3JA", + "cell_type": "markdown", + "source": [ + "## State" + ], + "metadata": {} + }, + { + "id": "mJADknA9Q0KQjmTmf03Blw", + "cell_type": "markdown", + "source": [ + "State describes the state in which a Data Node can be - There are two types of states:", + "\n- Active: visible in reports and queries", + "\n- Inactive: not visible in reports and queries" + ], + "metadata": {} + }, + { + "id": "lsRYxseYzUaLMcAn7JB2Qw", + "cell_type": "code", + "source": [ + "public enum State { Active, Inactive }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kgMLZfJ4PkCFRU4kLKSGcw", + "cell_type": "markdown", + "source": [ + "## Periodicity" + ], + "metadata": {} + }, + { + "id": "iV_fcqBE2E6B12CgJq2ybg", + "cell_type": "code", + "source": [ + "public enum Periodicity { Monthly, Quarterly, Yearly }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ndV2D2lQL0icIY9VirJweQ", + "cell_type": "markdown", + "source": [ + "## Input Source" + ], + "metadata": {} + }, + { + "id": "z6t0m-civUGAcBEAW0C3Nw", + "cell_type": "code", + "source": [ + "[Flags]", + "\npublic enum InputSource {NotApplicable = 0, Opening = 1, Actual = 2, Cashflow = 4} ", + "\n//Opening + Actual = 3,", + "\n//Opening + Cashflow = 5", + "\n//Actual + Cashflow = 6", + "\n//Opening + Actual + Cashflow = 7" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "aEqUAtvxPESgt-FHx2e7yA", + "cell_type": "markdown", + "source": [ + "## Data Type" + ], + "metadata": {} + }, + { + "id": "LR7R7DUA0k6Ywl5WjSrEvg", + "cell_type": "code", + "source": [ + "public enum DataType { Optional, Mandatory, Calculated, CalculatedTelescopic }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "euBhm6zy1Uib521-G3w3eQ", + "cell_type": "markdown", + "source": [ + "## Import Scope" + ], + "metadata": {} + }, + { + "id": "4PP7M-Sv9k6_6MsJWS1bUg", + "cell_type": "code", + "source": [ + "public enum ImportScope { Primary, Secondary }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Constants/Validations.ipynb b/Constants/Validations.ipynb new file mode 100644 index 00000000..f58110a8 --- /dev/null +++ b/Constants/Validations.ipynb @@ -0,0 +1,200 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "LgEd-jVnbEGK9QI-QWcVQw", + "cell_type": "markdown", + "source": [ + "

Errors and Warnings

" + ], + "metadata": {} + }, + { + "id": "-scbNYag2kmx_38hEmkBgA", + "cell_type": "code", + "source": [ + "#!import \"Enums\"", + "\n#!import \"Consts\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8xjDwqEVm0WjJuTlC2QERA", + "cell_type": "markdown", + "source": [ + "# Codes" + ], + "metadata": {} + }, + { + "id": "9CPbuC0YV0aSt5wA3uOxnw", + "cell_type": "code", + "source": [ + "public enum Warning {", + "\n // Import", + "\n ActiveDataNodeWithCashflowBOPI,", + "\n // Default", + "\n Generic", + "\n}; " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QWAQV2xUcEigl3eydHTJaA", + "cell_type": "code", + "source": [ + "public enum Error { ", + "\n // Import", + "\n NoMainTab, IncompleteMainTab, ParsingScientificNotation, ValueTypeNotFound, ValueTypeNotValid, AocTypeNotValid,", + "\n // Partition", + "\n PartitionNotFound, ParsedPartitionNotFound, PartititionNameNotFound, PartitionTypeNotFound,", + "\n // Dimensions", + "\n AmountTypeNotFound, EstimateTypeNotFound,CalculationTypeNotFound, ReportingNodeNotFound, AocTypeMapNotFound, AocTypeNotFound, PortfolioGicNotFound, PortfolioGricNotFound, ", + "\n InvalidAmountTypeEstimateType, MultipleTechnicalMarginOpening,", + "\n // Exchange Rate", + "\n ExchangeRateNotFound, ExchangeRateCurrency,", + "\n // Data Note State", + "\n ChangeDataNodeState, InactiveDataNodeState,", + "\n // Parameters", + "\n ReinsuranceCoverageDataNode, DuplicateInterDataNode, DuplicateSingleDataNode, InvalidDataNode, ", + "\n // Storage", + "\n DataNodeNotFound, PartnerNotFound, RatingNotFound, CreditDefaultRateNotFound, MissingPremiumAllocation, ReinsuranceCoverage, ", + "\n YieldCurveNotFound, YieldCurvePeriodNotApplicable, EconomicBasisNotFound, AccountingVariableTypeNotFound,", + "\n // Scopes", + "\n NotSupportedAocStepReference, MultipleEoP,", + "\n // Data completeness", + "\n MissingDataAtPosting, MissingCombinedLiability, MissingCoverageUnit, ", + "\n // Default", + "\n Generic", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ThPESGETMUm31fuq-qS4_w", + "cell_type": "markdown", + "source": [ + "# Messages" + ], + "metadata": {} + }, + { + "id": "x3UlljewwEut3M0NRlUDDg", + "cell_type": "code", + "source": [ + "public static string Get (Error e, params string[] s) => (e, s.Length) switch ", + "\n{", + "\n // Import", + "\n (Error.NoMainTab , _) => $\"No Main tab in the parsed file.\",", + "\n (Error.IncompleteMainTab , _) => $\"Incomplete Main tab in the parsed file.\",", + "\n (Error.ParsingScientificNotation , 1) => $\"While parsing found real number in scientific notation: {s[0]}.\",", + "\n (Error.ValueTypeNotFound , _) => $\"Value Type not found.\",", + "\n (Error.ValueTypeNotValid , 1) => $\"The Value Type {s[0]} is invalid.\",", + "\n (Error.AocTypeNotValid , 1) => $\"The parsed AocType {s[0]} is invalid.\",", + "\n // Partition", + "\n (Error.PartitionNotFound , _) => $\"Partition do not found.\",", + "\n (Error.ParsedPartitionNotFound , 1) => $\"Parsed partition not available: ReportingNode {s[0]}.\",", + "\n (Error.ParsedPartitionNotFound , 4) => $\"Parsed partition not available: ReportingNode {s[0]}, Year {s[1]}, Month {s[2]}, Scenario {s[3]}.\",", + "\n (Error.PartitionTypeNotFound , 1) => $\"Partition type not found: {s[0]}.\",", + "\n // Dimensions", + "\n (Error.AmountTypeNotFound , 1) => $\"AmountType {s[0]} not found.\",", + "\n (Error.EstimateTypeNotFound , 1) => $\"EstimateType {s[0]} not found.\",", + "\n (Error.CalculationTypeNotFound , 1) => $\"CalculationType {s[0]} not found.\",", + "\n (Error.ReportingNodeNotFound , 1) => $\"Reporting Node {s[0]} not found.\",", + "\n (Error.AocTypeNotFound , 1) => $\"AocType {s[0]} not found.\",", + "\n (Error.AocTypeMapNotFound , 2) => $\"AocType {s[0]} and Novelty {s[1]} combination not defined in the mapping.\",", + "\n (Error.PortfolioGicNotFound , 2) => $\"Portfolio {s[0]} assigned to Group of Insurance Contract {s[1]} does not exist.\",", + "\n (Error.PortfolioGricNotFound , 2) => $\"Portfolio {s[0]} assigned to Group of Reinsurance Contract {s[1]} does not exist.\",", + "\n (Error.InvalidAmountTypeEstimateType , 2) => $\"Invalid combination of EstimateType {s[0]} and AmountType {s[1]}.\",", + "\n (Error.MultipleTechnicalMarginOpening , 1) => $\"Multiple opening for techincal margin are not allowed for DataNode {s[0]}.\",", + "\n // Exchange Rate", + "\n (Error.ExchangeRateNotFound , 2) => $\"Exchange Rate for {s[0]} {s[1]} is not present.\",", + "\n (Error.ExchangeRateCurrency , 1) => $\"{s[0]} does not have any Exchange Rate defined.\", ", + "\n // Data Node State", + "\n (Error.ChangeDataNodeState , 0) => $\"Data Node State can not change from Inactive state into Active state.\",", + "\n (Error.ChangeDataNodeState , 1) => $\"Data Node State for {s[0]} can not change from Inactive state into Active state.\",", + "\n (Error.ChangeDataNodeState , 3) => $\"Data Node State for {s[0]} can not change from {s[1]} state into {s[2]} state.\",", + "\n (Error.InactiveDataNodeState , 1) => $\"Data imported for inactive Data Node {s[0]}.\",", + "\n //Parameters", + "\n (Error.ReinsuranceCoverageDataNode , 2) => $\"Invalid Reinsurance Coverage parameter does not link a GroupOfReinsuranceContract to a GroupOfInsuranceContract. Provided GroupOfContracts are: {s[0]}, {s[1]}.\",", + "\n (Error.DuplicateInterDataNode , 2) => $\"Duplicated Inter-DataNode parameter for {s[0]}-{s[1]} is found.\",", + "\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 // Storage", + "\n (Error.DataNodeNotFound , 1) => $\"DataNode {s[0]} not found.\",", + "\n (Error.PartnerNotFound , 1) => $\"Partner not found for DataNode {s[0]}.\",", + "\n (Error.RatingNotFound , 1) => $\"Rating not found for Partner {s[0]}.\",", + "\n (Error.CreditDefaultRateNotFound , 1) => $\"Credit Default Rate not found for rating {s[0]}.\",", + "\n (Error.MissingPremiumAllocation , 1) => $\"Premium Allocation Rate not found for Group of Contract {s[0]}.\", // TODO: this is now a warning to be produced by a validation in the importers (default is 1)", + "\n (Error.ReinsuranceCoverage , 1) => $\"Reinsurance Allocation Rate not found for Group of Insurance Contract {s[0]}.\",", + "\n (Error.YieldCurveNotFound , 3) => $\"Yield Curve not found for currency {s[0]}, year {s[1]}, and month {s[2]}.\",", + "\n (Error.YieldCurvePeriodNotApplicable , 2) => $\"YieldCurve period NotApplicable not valid for AocStep with AocType {s[0]} and Novelty {s[1]}.\",", + "\n (Error.EconomicBasisNotFound , 1) => $\"EconomicBasis not valid for DataNode {s[0]}.\",", + "\n (Error.AccountingVariableTypeNotFound , 1) => $\"AccountingVariableType {s[0]} not found.\",", + "\n // Scopes", + "\n (Error.NotSupportedAocStepReference , 1) => $\"Unsupported reference Aoc Step for Aoc Type {s[0]}.\",", + "\n (Error.MultipleEoP , 0) => $\"Closing Balance for both Csm and Lc are computed.\",", + "\n // Data Completeness", + "\n (Error.MissingDataAtPosting , 1) => $\"Missing imported data for {s[0]} DataNode.\",", + "\n (Error.MissingCombinedLiability , 2) => $\"Missing Combined Liability Aoc Type for DataNode {s[0]} and AmountType {s[1]}.\",", + "\n (Error.MissingCoverageUnit , 1) => $\"Missing Coverage Unit cash flow for {s[0]} DataNode.\",", + "\n // Default", + "\n (Error.Generic , _) => $\"{s[0]}\",", + "\n (_ , _) => $\"Error not found.\"", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "PnguuqruSkaTERChlORdKw", + "cell_type": "code", + "source": [ + "public static string Get (Warning w, params string[] s) => (w, s.Length) switch {", + "\n // Import", + "\n (Warning.ActiveDataNodeWithCashflowBOPI , _) => $\"Cashflows for active DataNode has been parsed with AocType {AocTypes.BOP} and Novelty {Novelties.I} \",", + "\n // Default", + "\n (Warning.Generic , _) => $\"{s[0]}\",", + "\n (_ , _) => $\"Warning not found.\"", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "COxOqdqYwUqx0ozqRQof0w", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/DataModel/DataStructure.ipynb b/DataModel/DataStructure.ipynb new file mode 100644 index 00000000..1e65f8b1 --- /dev/null +++ b/DataModel/DataStructure.ipynb @@ -0,0 +1,2139 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "E3XGdKdQXkSFZwQ0OR8f9Q", + "cell_type": "markdown", + "source": [ + "", + "\n

Data Model

", + "\n", + "\nThis notebook has the main structures used to hold data - This is usually called the **data model**." + ], + "metadata": {} + }, + { + "id": "wIRyXTP_f0aojedzQ_2yaw", + "cell_type": "markdown", + "source": [ + "# References", + "\nThis section initializes libraries and code from other notebooks, which will be used here, as well as information needed for querying data from the database." + ], + "metadata": {} + }, + { + "id": "_ldA06bDKEyrEr1rDJpRng", + "cell_type": "markdown", + "source": [ + "## Libraries" + ], + "metadata": {} + }, + { + "id": "iVjxSwqCvkCRk9OnawoClw", + "cell_type": "code", + "source": [ + "#r \"nuget:Systemorph.Workspace,1.2.0\"", + "\n#r \"nuget:Systemorph.Scopes,1.2.4\"", + "\n#r \"nuget:Systemorph.Import,1.3.0\"", + "\n#r \"nuget:Systemorph.Test,1.2.4\"", + "\n#r \"nuget:Systemorph.Export,1.3.0\"", + "\n#r \"nuget:Systemorph.DataSetReader,1.3.0\"", + "\n#r \"nuget:Systemorph.DataSource,1.2.0\"", + "\n#r \"nuget:Systemorph.DataSource.Conversions,1.2.0\"", + "\n#r \"nuget:Systemorph.Reporting,1.2.4\"", + "\n#r \"nuget:Systemorph.DomainDesigner,1.3.0\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tVqfp6kjPEWcWTsE7nmIJQ", + "cell_type": "markdown", + "source": [ + "## Usings" + ], + "metadata": {} + }, + { + "id": "H4cEfQ5jnE-pcrbgue7FNA", + "cell_type": "code", + "source": [ + "using System.ComponentModel.DataAnnotations;", + "\nusing System.ComponentModel.DataAnnotations.Schema;", + "\nusing Systemorph.Vertex.Grid.Model;", + "\nusing static Systemorph.Vertex.Arithmetics.ArithmeticOperations;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "r7mAcZwhpEOp8xf82HvdyQ", + "cell_type": "markdown", + "source": [ + "## Notebooks" + ], + "metadata": {} + }, + { + "id": "wkcyVZzJ5kqKCJm_siKkNQ", + "cell_type": "code", + "source": [ + "#!import \"../Constants/Enums\"", + "\n#!import \"../Constants/Consts\"", + "\n#!import \"../Constants/Validations\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HTeT_yYbpUCPrWtjwe9fdQ", + "cell_type": "markdown", + "source": [ + "# Data Infrastructure" + ], + "metadata": {} + }, + { + "id": "HrfAYsLiM0SFRqKe6IIlxA", + "cell_type": "markdown", + "source": [ + "", + "\n## Base Interfaces", + "\nThe following interfaces are used to define the granularity at which data is stored.", + "\n", + "\nFor instance, the IKeyed interface corresponds to the lowest granularity which is simply a unique identifier for a certain generic piece of data:" + ], + "metadata": {} + }, + { + "id": "-JHURlI5Z0mY6_UxQ7gfGA", + "cell_type": "code", + "source": [ + "public interface IKeyed", + "\n{ ", + "\n public Guid Id { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TLXXKZET0E-dDwCIcdZXBg", + "cell_type": "markdown", + "source": [ + "The interface IPartition identifies the partitions in the system." + ], + "metadata": {} + }, + { + "id": "A-Onlfa3vkqOVvHu6-JMQg", + "cell_type": "code", + "source": [ + "public interface IPartition : IKeyed {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iF7QiEQqBE2pxD1M85J2Sw", + "cell_type": "markdown", + "source": [ + "The interface IPartitioned simply assigns a unique identifier for elements of a data partition - The exact definition of such elements can be found in the [partition](#partition) section below." + ], + "metadata": {} + }, + { + "id": "UI71Ps6BF0K27AoG-9UkDw", + "cell_type": "code", + "source": [ + "public interface IPartitioned", + "\n{", + "\n public Guid Partition { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mwvvs9R7IE6s7-QzaQ44Iw", + "cell_type": "markdown", + "source": [ + "The interface IHierarchy is used for modelling dimensions which have an hierarchical structure, such as [Amount Type](#amount-type)." + ], + "metadata": {} + }, + { + "id": "udn_BFvLkE-kpOBDTNrOzg", + "cell_type": "code", + "source": [ + "public interface IHierarchy", + "\n{", + "\n [Display(Order = 10)]", + "\n public string Name { get; init; }", + "\n ", + "\n [Display(Order = 20)]", + "\n public string Parent { get; init; }", + "\n ", + "\n [Display(Order = 30)]", + "\n public string Child { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qlvXHTn5VUmrP2f97WrtTw", + "cell_type": "markdown", + "source": [ + "The interface IWithYearAndMonth allows to speficy to which year and month a certain piece of data applies to:" + ], + "metadata": {} + }, + { + "id": "jD1t0fnTnUGMALFqTwsLHA", + "cell_type": "code", + "source": [ + "public interface IWithYearAndMonth", + "\n{", + "\n public int Year { get; init; }", + "\n ", + "\n public int Month { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WbhV6bUsy0ukIAm920fzwg", + "cell_type": "markdown", + "source": [ + "", + "\n## Abstract Classes", + "\nThese classes are not reflected in the database, i.e. are not persisted." + ], + "metadata": {} + }, + { + "id": "EVd9ytkY40OTYvjWp5aziA", + "cell_type": "code", + "source": [ + "public abstract record KeyedRecord : IKeyed {", + "\n [Key]", + "\n [NotVisible] ", + "\n public Guid Id { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "h-P8iuN2zUqCz2F1HgnXjQ", + "cell_type": "code", + "source": [ + "public abstract record KeyedDimension : INamed {", + "\n [Key]", + "\n [IdentityProperty]", + "\n [StringLength(16)]", + "\n [Display(Order = 1)]", + "\n public string SystemName { get; init; }", + "\n ", + "\n [Display(Order = 2)]", + "\n [NotVisible]", + "\n public string DisplayName { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q1r9nxY4cEudsXAFS_0LOA", + "cell_type": "code", + "source": [ + "public abstract record KeyedOrderedDimension : KeyedDimension, IOrdered {", + "\n [NotVisible]", + "\n public int Order { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "V0ZEujrm8EeHPz95bLGLOA", + "cell_type": "code", + "source": [ + "public abstract record KeyedOrderedDimensionWithExternalId : KeyedOrderedDimension {", + "\n [Display(Order = 100)]", + "\n [Conversion(typeof(JsonConverter))]", + "\n public string[] ExternalId { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1ZMlcc50Q0yVI7dZBvBCyQ", + "cell_type": "markdown", + "source": [ + "", + "\n# Dimensions", + "\n", + "\nDimensions are data which tipically can be given a short name, here called 'System Name'. They also change slowly with time. A typical example is currencies, and examples of System Names are EUR, CHF, etc.", + "\n", + "\nThe advantages of using Dimensions are:", + "\n- The data is easier to maintain (the data is said to be 'normalized');", + "\n- The business logic is easier to read;", + "\n- Easier scructuring of the data, e.g. in a data-cube." + ], + "metadata": {} + }, + { + "id": "Nh9SUewfGEisAbZfcpYfPA", + "cell_type": "markdown", + "source": [ + "", + "\n## Hierarchical Dimension With Level", + "\nHierarchical dimensions are useful to define for example the legal structure of a company (reporting nodes and their parents).", + "\n", + "\nBelow we introduce the concept of a hierarchical dimension with level, which is a simple way to keep track of the \"level\" in a hierarchical dimension." + ], + "metadata": {} + }, + { + "id": "4JGV542yw0KkgF5wA8Xc-A", + "cell_type": "code", + "source": [ + "//TODO: Should this be abstract or have a reference to the type?", + "\npublic record HierarchicalDimensionWithLevel(string SystemName, string DisplayName, string Parent, int Level) : IHierarchicalDimension;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3mdUv9EKwUaRHVRzBFxSNw", + "cell_type": "markdown", + "source": [ + "", + "\n## Amount Type" + ], + "metadata": {} + }, + { + "id": "oD4Rl6GEpEqnLIn_CUdivg", + "cell_type": "markdown", + "source": [ + "Amount Type is a dimension used to describe the nature of numbers. For example: Numbers associated to the payment of premiums have Amount Type 'Premiums'; Numbers associated to the payment of claims have Amount Type 'Claims'; Numbers associated to expenses have Amount Type 'Expenses'. ", + "\n", + "\nIt is defined as a hierarchical dimension so that higher-granularity types can be introduced. For example: 'Claim Expenses' have parent 'Claims'.", + "\n", + "\nAmount Types are a central piece in the IFRS 17 application and are used for instance to name the different types of cashflows. For example: There might be cashflows for 'Premiums'; Cashflows for 'Claims', etc. In case the mapping between cash flow and amount type is non-trivial, then specific mappings are introduced through the use of ExternalId." + ], + "metadata": {} + }, + { + "id": "ffEXk8fDRUSuFc1EOOWVXA", + "cell_type": "code", + "source": [ + "public record AmountType : KeyedOrderedDimensionWithExternalId, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(AmountType))]", + "\n public string Parent { get; init; }", + "\n ", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(PeriodType))]", + "\n public PeriodType PeriodType { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xY7Lv0cnPk2ZqR7zMUKVAQ", + "cell_type": "markdown", + "source": [ + "We distinguish between amount types used for cashflows and actuals (**Present Value Amount Types**), and amount types used for deferrable values (**Deferrable Amount Types**). In particular, deferrable amount types are for costs and expenses that can be deferred to the future. These amounts are treated separately from the Present Value Amount Types because they are not considered for the calculation of Contractual Service Margin and Loss Component." + ], + "metadata": {} + }, + { + "id": "u1zwrsAl_06VNVKVjqY52g", + "cell_type": "code", + "source": [ + "public record PvAmountType : AmountType {} //TODO Rename ", + "\n", + "\npublic record DeferrableAmountType : AmountType {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uCEMSSPR00Oh87NXjPpxaQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Calculation Type", + "\nThis dimension is used to distinguish between e.g. **Best Estimate** values and **Risk Adjustment** values:" + ], + "metadata": {} + }, + { + "id": "ZNlHEPmkHky4j1HvhgN88A", + "cell_type": "code", + "source": [ + "public record CalculationType : KeyedOrderedDimension {", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(PeriodType))]", + "\n public PeriodType PeriodType { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vKJfcG-udU2bWMy_nL8WSQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Risk Driver", + "\n", + "\nRisk drivers are used to distinguish between the different Risk Adjustment numbers. For instance: Mortality, Disability, Longevity, etc.", + "\n", + "\nWhen only total risk adjustment values are used, then there is no need to use risk drivers." + ], + "metadata": {} + }, + { + "id": "fa88nNjOdk6ESB_dqpM35w", + "cell_type": "code", + "source": [ + "public record RiskDriver : KeyedOrderedDimension, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(RiskDriver))]", + "\n public string Parent { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VkCT-HB9TkyWJJyAcX42QQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Estimate Type", + "\n", + "\nEstimate Type is a dimension used to distinguish the context to which numbers belong to. For instance: Numbers for present values have Estimate Type 'Present Value'; Numbers for Risk Adjustments have Estimate Type 'Risk Adjustment'." + ], + "metadata": {} + }, + { + "id": "PGODf3XfjEOJ2CfpWJNxvw", + "cell_type": "code", + "source": [ + "public record EstimateType : KeyedOrderedDimensionWithExternalId", + "\n{", + "\n [Display(Order = 110)]", + "\n public InputSource InputSource { get; init; }", + "\n ", + "\n [Display(Order = 120)]", + "\n public StructureType StructureType { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bo_ARw7-YEWDtJJsK8ODmA", + "cell_type": "markdown", + "source": [ + "", + "\n## Novelty", + "\n", + "\nNovelty is a [dimension](#dimensions) used to identity the novelty of the business. Typical examples of Novelty are New Busines, In-Force, and Combined." + ], + "metadata": {} + }, + { + "id": "mV4OXu-r_0e7k1vZthQ1IQ", + "cell_type": "code", + "source": [ + "public record Novelty : KeyedOrderedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "O-7_tXaPPEOL_eRj1Ev76g", + "cell_type": "markdown", + "source": [ + "", + "\n## Variable Type" + ], + "metadata": {} + }, + { + "id": "jFh4gN-zTEyK_KZ55DhlEw", + "cell_type": "code", + "source": [ + "public record VariableType : KeyedOrderedDimension, IHierarchicalDimension", + "\n{ ", + "\n [Display(Order = 10)]", + "\n public string Parent { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RJcV2vGuokmqX1cLgr8tcw", + "cell_type": "markdown", + "source": [ + "", + "\n### AoC Variable Type", + "\n", + "\nThe AocType describes the type of the Analysis of Change step - For example: Amortization, Cashflow, Combined Liabilities etc.", + "\n", + "\nThe **Combined Liability** AocType aims in capturing the difference between the sum of all relevant previous Aoc steps and the end of period Aoc step. Unexplained changes (not captured by any other defined AoC step), are then visible in this Aoc step. Note that the nominal cash flows input in the cashflow input file corresponds to cash flow projection for the end of period step.", + "\nIn addition, this step distinguishes itself from the others for:", + "\n- It is a mandatory AocType as it is used to trigger the Run off of the cashflow. This is achieved by providing a cash flow of 0s. ", + "\n- It is the first AocType for the Combined Novelty and therefore it carries the contribution of combining In force and New business.", + "\n- Its present value is computed as telescoping difference with the last AoC Step for the In-Force novelty and the New Business novelty.", + "\n- In the technical margin calculation it is used to merge the profitability of the In-Force and New business components, which may result in a forced switch." + ], + "metadata": {} + }, + { + "id": "uXawxEZ9akakX3cBhzIvkw", + "cell_type": "code", + "source": [ + "public record AocType : VariableType", + "\n{ ", + "\n [Display(Order = 30)]", + "\n [Dimension(typeof(AocType))]", + "\n public string Parent { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wURsJ4y22UClSsa-dgRVKg", + "cell_type": "code", + "source": [ + "public record AocStep(string AocType, string Novelty){}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9FQQEf3waUyPGTjoJ3kPvA", + "cell_type": "markdown", + "source": [ + "", + "\n### PnL Variable Type", + "\n", + "\nThe PnlVariableType is used to describe the various profit and loss sections and the corresponding hierarchy." + ], + "metadata": {} + }, + { + "id": "yXjDtNxmtUKCm7l4rInNRw", + "cell_type": "code", + "source": [ + "public record PnlVariableType : VariableType {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6TMaVeubb0yfDj0zHl3dNQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Balance Sheet Variable Type", + "\n", + "\nThe BsVariableType is used to descibe the Anlysis of change of the Balance Sheet reports." + ], + "metadata": {} + }, + { + "id": "kmnM353ouUSOXqQD4IcV7Q", + "cell_type": "code", + "source": [ + "public record BsVariableType : VariableType {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WglnqvLArU6Ahc29yVDgSQ", + "cell_type": "markdown", + "source": [ + "## Accounting Variable Type", + "\nThe AccountingVariableType is used to describe the accounting events that are posted in the accounting output file." + ], + "metadata": {} + }, + { + "id": "tqFR7uu7BkOnFUvISdLF1A", + "cell_type": "code", + "source": [ + "public record AccountingVariableType : VariableType {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gQILcufhBU6Gh3ZoHDRIYA", + "cell_type": "markdown", + "source": [ + "", + "\n## Scenario", + "\nThe Scenario record holds the various scenarios for which calculations should also be performed." + ], + "metadata": {} + }, + { + "id": "WKR88bI5G0qwjmpDyGZTsw", + "cell_type": "code", + "source": [ + "public record Scenario : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "c-cppckU8UeROzwpBdL44A", + "cell_type": "markdown", + "source": [ + " The 'neutral' Scenario (i.e. the default one, with no-stress situations applied) is designated as 'Best Estimate'." + ], + "metadata": {} + }, + { + "id": "ysCBY_ONbUmbRFL_KEXoXg", + "cell_type": "markdown", + "source": [ + "", + "\n## Line Of Business" + ], + "metadata": {} + }, + { + "id": "XPrjV3N-LE-TKVM80pV5yQ", + "cell_type": "markdown", + "source": [ + "Line Of Business is a dimension used to identity insurance business according to usual business classifications (usually a market or company-specific business classification representing a convolution of risk covered, 1st party / 3rd party cover type, product type, etc...)", + "\nTypical examples of Line of Business are Motor, Property, Endowment, etc... This is a hierarchical dimension." + ], + "metadata": {} + }, + { + "id": "VxLXh8klyEi6UhXPn1ZKKw", + "cell_type": "code", + "source": [ + "public record LineOfBusiness : KeyedOrderedDimension, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(LineOfBusiness))]", + "\n public string Parent { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pnCYzQI05UWCUkXGHAB9QA", + "cell_type": "markdown", + "source": [ + "", + "\n## Currency" + ], + "metadata": {} + }, + { + "id": "PZEeN2QhsEGXT0BQ4Rjlag", + "cell_type": "markdown", + "source": [ + "Currency is a dimension used to identity the currency.", + "\nTypical examples of Currency are EUR, CHF, USD, etc..." + ], + "metadata": {} + }, + { + "id": "TUEcu5Y_ZE6Nv_pUG-_COQ", + "cell_type": "code", + "source": [ + "public record Currency : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TUfMA1ybakuqVJ73ERA3ZQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Economic Basis", + "\n", + "\nThe Economic Basis defines the discount type which is used in calculations. Examples are: Nominal, Current and Locked." + ], + "metadata": {} + }, + { + "id": "rt_ieWyHpU29K0fpiBXLcQ", + "cell_type": "code", + "source": [ + "public record EconomicBasis : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CJjymwgpJEiBZhPYBoZV-w", + "cell_type": "markdown", + "source": [ + "", + "\n## Valuation Approach", + "\nThis dimension holds the various methodologies used in the calculations: BBA, VFA and PAA." + ], + "metadata": {} + }, + { + "id": "oPjqx6DSTkyk2Pi5v9Bgww", + "cell_type": "code", + "source": [ + "public record ValuationApproach : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "v5-cD3t8RkaWxWs7t5oTxg", + "cell_type": "markdown", + "source": [ + "", + "\n## Liability Type", + "\nThe Liability Type distinguishes betweeen e.g. liabilities for incurred claims and liabilities for remaining coverage." + ], + "metadata": {} + }, + { + "id": "zZBD3LVJqUSlsfat1_eEDw", + "cell_type": "code", + "source": [ + "public record LiabilityType : KeyedDimension, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(LiabilityType))]", + "\n public string Parent { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "JkEN-M0lnUaJ5FsC0QM6JQ", + "cell_type": "markdown", + "source": [ + "", + "\n## OCI Type", + "\nOther Comprehensive Income (OCI) Type describes how the financial contributions to the IFRS17 Financial Performance is apportioned between the P&L and the OCI sections." + ], + "metadata": {} + }, + { + "id": "pAjz1mAaPUGhHNTdyP54gw", + "cell_type": "code", + "source": [ + "public record OciType : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZvvcNAbtHki9DK9rkMj5PQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Profitability" + ], + "metadata": {} + }, + { + "id": "SpHNgrkn70WBckuZf-9rtA", + "cell_type": "markdown", + "source": [ + "Profitability is a dimension used in IFRS 17 to describe the profitability of a Group of Contracts (GIC/GRIC).", + "\nTypical examples of Profitability are Profitable, Non-Profitable, etc.." + ], + "metadata": {} + }, + { + "id": "rJS1Lqw9gUyBmW8LzFRIAw", + "cell_type": "code", + "source": [ + "public record Profitability : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5nzILMYUw06HnJmXUyLYgg", + "cell_type": "markdown", + "source": [ + "", + "\n## Partner", + "\nPartner is the counterparty of a reinsurance contract." + ], + "metadata": {} + }, + { + "id": "_vf2ckZDHkiTBUqDESRY7A", + "cell_type": "code", + "source": [ + "public record Partner : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "K48oHe7Yw0GIy27KBHbDtQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Credit Risk Rating", + "\nThis holds the credit risk rating of each Partner." + ], + "metadata": {} + }, + { + "id": "faZdNRqxWkqUXYnGZQNNLQ", + "cell_type": "code", + "source": [ + "public record CreditRiskRating : KeyedDimension {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LrcDCmrTYkiEFks8X5d5qQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Reporting Node", + "\nA Reporting Node is an element in the reporting structure of the company. It has a hierarchical structure and the end nodes is the level at which data is imported." + ], + "metadata": {} + }, + { + "id": "yfIk7Ocnc0SkfFXciN5yfQ", + "cell_type": "code", + "source": [ + "public record ReportingNode : KeyedDimension, IHierarchicalDimension ", + "\n{", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(ReportingNode))]", + "\n public string Parent { get; init; }", + "\n ", + "\n [Required]", + "\n [Display(Order = 40)]", + "\n [Dimension(typeof(Currency))]", + "\n public virtual string Currency { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dgSDvMwORkWAHKNhcKsOsQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Projection Configuration" + ], + "metadata": {} + }, + { + "id": "SXiQr9uXpEOar1SWj1NbHQ", + "cell_type": "markdown", + "source": [ + "Projections are configured by defining the following 2 parameters:", + "\n", + "\n- Shift defines how many months are in the cashflow file before the first value of the period in interest.
", + "\n- TimeStep defines how many months are in the period of interest.
", + "\n", + "\nBoth Shift and TimeStep are measured in terms of number of months.", + "\nFor instance, for the current year and year-to-date view we have $\\rm{Shift}=0$ and $TimeStep=3$ for the first quarter, $TimeStep=6$ for the 2nd quarter and so on." + ], + "metadata": {} + }, + { + "id": "5roF1i3RCkuAb120D2hlCw", + "cell_type": "code", + "source": [ + "public record ProjectionConfiguration : KeyedDimension", + "\n{", + "\n [IdentityProperty]", + "\n public int Shift { get; init; }", + "\n [IdentityProperty]", + "\n public int TimeStep { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0BJMDgWcZ0-7DaVBFvhhrg", + "cell_type": "markdown", + "source": [ + "", + "\n# Parameters" + ], + "metadata": {} + }, + { + "id": "lZdeQUGmGUmVPRibX3A4mQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Aoc Step Configuration" + ], + "metadata": {} + }, + { + "id": "NRbkQdbBAkSeX6wwNvqeLg", + "cell_type": "markdown", + "source": [ + "The record below holds parameters over time for each combination of AocType and Novelty. In particular:", + "\n- DataType identifies between Calculated aoc steps and Optional inputs or Mandatory inputs.", + "\n- InputSource identifies whether an aoc step is relevant for Actuals, Cashflow or both calculations.", + "\n- FxPeriod identifies which fx rate should be used.", + "\n- YcPeriod identifies which Yield Curve should be used (from current or previous period).", + "\n- CdrPeriod identifies which Credit Default Rate should be used (from current or previous period).", + "\n- ValuationPeriod identifies which value from the Cashflow corresponds to the Present Value.", + "\n- RcPeriod identifies which Reinsurance Coverage should be used (from current or previous period).", + "\n", + "\n
The values for each parameter can be found in [Enums Notebook](./Constants/Enums)." + ], + "metadata": {} + }, + { + "id": "fSKSGQxYvEWCjRwEU8Zp8A", + "cell_type": "code", + "source": [ + "public record AocConfiguration : KeyedRecord, IWithYearAndMonth, IOrdered", + "\n{", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 10)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Month { get; init; }", + "\n ", + "\n [IdentityProperty]", + "\n [Display(Order = 30)]", + "\n [Dimension(typeof(AocType))]", + "\n public string AocType { get; init; }", + "\n ", + "\n [IdentityProperty]", + "\n [Display(Order = 40)]", + "\n [Dimension(typeof(Novelty))]", + "\n public string Novelty { get; init; }", + "\n ", + "\n [Display(Order = 50)]", + "\n [Dimension(typeof(DataType))]", + "\n public DataType DataType { get; init; }", + "\n ", + "\n [Display(Order = 55)]", + "\n [Dimension(typeof(InputSource))]", + "\n public InputSource InputSource { get; init; }", + "\n ", + "\n [Display(Order = 60)]", + "\n [Dimension(typeof(FxPeriod))]", + "\n public FxPeriod FxPeriod { get; init; }", + "\n ", + "\n [Display(Order = 70)]", + "\n [Dimension(typeof(PeriodType), nameof(YcPeriod))]", + "\n public PeriodType YcPeriod { get; init; }", + "\n ", + "\n [Display(Order = 80)]", + "\n [Dimension(typeof(PeriodType), nameof(CdrPeriod))]", + "\n public PeriodType CdrPeriod { get; init; }", + "\n ", + "\n [Display(Order = 90)]", + "\n [Dimension(typeof(ValuationPeriod))]", + "\n public ValuationPeriod ValuationPeriod { get; init; }", + "\n ", + "\n [Display(Order = 100)]", + "\n [Dimension(typeof(PeriodType), nameof(RcPeriod))]", + "\n public PeriodType RcPeriod { get; init; }", + "\n ", + "\n [NotVisible]", + "\n public int Order { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9EDmAQK2o0CtkSqxrxadaw", + "cell_type": "markdown", + "source": [ + "", + "\n## Exchange Rate", + "\nThe record below holds the Exchange Rates over time and for each exchange type ([FxType](./Constants/Enums)). Exchange Rate must be updated every reporting period as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", + "\n", + "\nIn case the Exchange Rate for the current period is missing, an error is returned. " + ], + "metadata": {} + }, + { + "id": "0UriZBf9PkWxz4YC-Zj6jQ", + "cell_type": "code", + "source": [ + "public record ExchangeRate : KeyedRecord", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(Currency))]", + "\n public string Currency { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Month { get; init; }", + "\n", + "\n [IdentityProperty]", + "\n [Required]", + "\n [Display(Order = 40)]", + "\n public FxType FxType { get; init; }", + "\n", + "\n [Display(Order = 50)]", + "\n public double FxToGroupCurrency { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DqeuCXH1bkmJd_iD726ypg", + "cell_type": "markdown", + "source": [ + "", + "\n## Credit Default Rate", + "\nThe record below holds the Credit Default Rates over time for each [Credit Risk Rating](#credit-risk-rating). Credit Default Rate can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", + "\n", + "\nThe Credit Default Rate values must be entered with monthly granularity, i.e. every value corresponds to the default rate for a certain month. The first month entered in column Values0 always corresponds to January of the year entered in column Year. The last value is considered valid also for the following years (for which no value has been provided). ", + "\n", + "\nThe latest Credit Default Rate 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." + ], + "metadata": {} + }, + { + "id": "dGtfTrO3iUaqdptZ0yybYw", + "cell_type": "code", + "source": [ + "public record CreditDefaultRate : KeyedRecord, IWithYearAndMonth", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(CreditRiskRating))]", + "\n public string CreditRiskRating { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Month { get; init; }", + "\n ", + "\n [Conversion(typeof(PrimitiveArrayConverter))]", + "\n [Display(Order = 40)]", + "\n public double[] Values { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9_ycC9yzPkG8EqR3gTj3PA", + "cell_type": "markdown", + "source": [ + "", + "\n## Yield Curve", + "\nThe record below holds the Yield Curves across time for each [Currency](#currency) and [Scenario](#scenario).", + "\nYield curves can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", + "\n", + "\nThe Yield Curve values must be entered with **yearly** granularity, i.e. every value corresponds to the rate of the whole year starting from the year entered in column Year. The last value is considered valid also for the following years (for which no value has been provided). ", + "\n", + "\nWhen the current Yield Curve must be used in the calculation, the latest Yield Curve available in the system with Year and Month earlier or equal to Year and Month of the closing period will be used." + ], + "metadata": {} + }, + { + "id": "3TbdMYHKKk2Wan-Egtuetg", + "cell_type": "code", + "source": [ + "public record YieldCurve : KeyedRecord, IWithYearAndMonth", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(Currency))]", + "\n public string Currency { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Month { get; init; }", + "\n", + "\n [IdentityProperty]", + "\n [Display(Order = 35)]", + "\n public string Scenario { get; init; }", + "\n", + "\n [Conversion(typeof(PrimitiveArrayConverter))]", + "\n [Display(Order = 40)]", + "\n public double[] Values { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kR4nqN3MwkqRBS8Yeb4bOA", + "cell_type": "markdown", + "source": [ + "", + "\n## Partner Rating", + "\nThe record below holds the [Credit Risk Rating](#credit-risk-partner) for each [Partner](#partner) across time. Partner Rating can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. " + ], + "metadata": {} + }, + { + "id": "-yzxBGiz7U62zp3niNtqEA", + "cell_type": "code", + "source": [ + "public record PartnerRating : KeyedRecord, IWithYearAndMonth", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(Partner))]", + "\n public string Partner { get; init; }", + "\n", + "\n [Required]", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(CreditRiskRating))]", + "\n public string CreditRiskRating { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 40)]", + "\n public int Month { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4bFzr4BUxECkAZN1KK83Kg", + "cell_type": "markdown", + "source": [ + "", + "\n# Partitions", + "\nThe notion of Partition is used to define small but meaningful sets of data, called partitions. Partitions are then used to optimize the extraction of data from the database, i.e. only the data for a certain partition is retrieved." + ], + "metadata": {} + }, + { + "id": "lfo6j69S00S5MmeGEgWhWA", + "cell_type": "code", + "source": [ + "public abstract record IfrsPartition : IPartition {", + "\n [Key]", + "\n [PartitionId]", + "\n public Guid Id { get; init; }", + "\n", + "\n [Required]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(ReportingNode))]", + "\n [IdentityProperty]", + "\n public string ReportingNode { get; init; }", + "\n", + "\n [Display(Order = 50)]", + "\n [Dimension(typeof(Scenario))]", + "\n [IdentityProperty]", + "\n public string Scenario { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Oy6PSvNeAkOrHXzbWi144g", + "cell_type": "markdown", + "source": [ + "For instance, the data pertaining to a certain [Reporting Node](#reporting-node) for a certain [Scenario](#scenario) is called an IfrsPartition and assigned a unique identifier:" + ], + "metadata": {} + }, + { + "id": "YQl5TqjBQUui3Ao3FsgiUw", + "cell_type": "code", + "source": [ + "public record PartitionByReportingNode : IfrsPartition {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "M8p4dGJQHkC7dFwqXU4RXQ", + "cell_type": "markdown", + "source": [ + "The partition PartitionByReportingNodeAndPeriod is a further partition of the IfrsPartition sets - In particular, it defines sets for the data pertaining to a certain [Reporting Node](#reporting-node), [Scenario](#scenario), year and month. The value of the Month is the last month of the reporting period to which the data belongs to. " + ], + "metadata": {} + }, + { + "id": "a7nDH2imYUeP23B6WT5yZw", + "cell_type": "code", + "source": [ + "public record PartitionByReportingNodeAndPeriod : IfrsPartition {", + "\n [Display(Order = 30)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [IdentityProperty]", + "\n public int Year { get; init; }", + "\n", + "\n [Display(Order = 40)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [IdentityProperty]", + "\n public int Month { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TZvDAkF0M02LQtQKCZLJRA", + "cell_type": "markdown", + "source": [ + "", + "\n# Policy-related Data Structures", + "\n", + "\nThe data structures below are the pieces of the data model where policy-related data is held." + ], + "metadata": {} + }, + { + "id": "kjn-7dhJgEa7EDS2jG2CbA", + "cell_type": "markdown", + "source": [ + "", + "\n## Data Node", + "\n", + "\nA data node is basically a set of labels which identify data according to its:", + "\n- Reporting Node", + "\n- Scenario", + "\n- Contractual Currency", + "\n- FunctionalCurrency", + "\n- LineOfBusiness", + "\n- ValuationApproach", + "\n- OCI Type" + ], + "metadata": {} + }, + { + "id": "7I3_uOSDzkuHhcVJMukGlA", + "cell_type": "markdown", + "source": [ + "TODOs:", + "\n
    ", + "\n
  • Remove Scenario from Partition and include it as simple property (see Year, Month). Introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", + "\n
" + ], + "metadata": {} + }, + { + "id": "XlZfZAGgi0GjV_7P_tJtiQ", + "cell_type": "code", + "source": [ + "public record DataNode : KeyedDimension, IPartitioned {", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNode))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Currency))]", + "\n //[Required] // TODO: check", + "\n //[Immutable] // TODO: Not available yet", + "\n public string ContractualCurrency { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Currency))]", + "\n //[Required] // TODO: check", + "\n //[Immutable]", + "\n public string FunctionalCurrency { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(LineOfBusiness))]", + "\n //[Immutable]", + "\n public string LineOfBusiness { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(ValuationApproach))]", + "\n [Required]", + "\n //[Immutable]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(OciType))]", + "\n //[Immutable]", + "\n public string OciType { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0Zg-7p1UNU6Wdzok3kr-AA", + "cell_type": "markdown", + "source": [ + "", + "\n## Portfolios", + "\n", + "\nA Portfolio is a set of Group of Contracts. The relationship is set on the Group of Contracts (see below).", + "\n", + "\nPortfolios are of type DataNode and there are two types: Insurance Portfolio and Reinsurance Portfolios." + ], + "metadata": {} + }, + { + "id": "0P3rhAjUNUyBonuP1k9uHg", + "cell_type": "code", + "source": [ + "public record Portfolio : DataNode {}", + "\n", + "\npublic record InsurancePortfolio : Portfolio {}", + "\npublic record ReinsurancePortfolio : Portfolio {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xbAt9JzjCE614P7B97aiVA", + "cell_type": "markdown", + "source": [ + "", + "\n## Group of Contracts", + "\n", + "\nA Group of Contract is a set of contracts with the same Annual Cohort, Liability Type, Profitability and Partner (in case the contracts are done with a re-insurer).", + "\n", + "\nVarious Group of Contracts are put together into portfolios." + ], + "metadata": {} + }, + { + "id": "la_B6Lgw10-Y8UNDpmZ3gA", + "cell_type": "code", + "source": [ + "public record GroupOfContract : DataNode {", + "\n [NotVisible] ", + "\n [Dimension(typeof(int), nameof(AnnualCohort))]", + "\n //[Immutable]", + "\n public int AnnualCohort { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(LiabilityType))]", + "\n //[Immutable]", + "\n public string LiabilityType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Profitability))]", + "\n //[Immutable]", + "\n public string Profitability { get; init; }", + "\n ", + "\n [Required]", + "\n [NotVisible] ", + "\n [Dimension(typeof(Portfolio))]", + "\n //[Immutable]", + "\n public string Portfolio { get; init; }", + "\n ", + "\n public virtual string Partner { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qgBtX4_gZEeQFJWmImnXKg", + "cell_type": "markdown", + "source": [ + "A group of insurance contracts is called a **GIC** and has no information on Partner.", + "\n", + "\nOnly Groups of Reinsurance Contracts, defined below and usually called **GRIC**s, have Partner information.", + "\nAgain, there are Insurance GRICs and Reinsurance GRICs:" + ], + "metadata": {} + }, + { + "id": "IGY1DT71jECwSzukcliQKg", + "cell_type": "code", + "source": [ + "public record GroupOfInsuranceContract : GroupOfContract {", + "\n [Required]", + "\n [NotVisible] ", + "\n [Display(Name = \"InsurancePortfolio\")]", + "\n [Dimension(typeof(InsurancePortfolio))]", + "\n //[Immutable]", + "\n public string Portfolio { get => base.Portfolio; init => base.Portfolio = value; }", + "\n ", + "\n // TODO: for the case of internal reinsurance the Partner would be the reporting node, hence not null.", + "\n // If this is true we need the [Required] attribute here, add some validation at dataNode import ", + "\n // and to add logic in the GetNonPerformanceRiskRate method in ImportStorage.", + "\n [NotVisible] ", + "\n [NotMapped]", + "\n //[Immutable]", + "\n public override string Partner => null;", + "\n}", + "\n", + "\npublic record GroupOfReinsuranceContract : GroupOfContract {", + "\n [Required]", + "\n [NotVisible] ", + "\n [Display(Name = \"ReinsurancePortfolio\")]", + "\n [Dimension(typeof(ReinsurancePortfolio))]", + "\n //[Immutable]", + "\n public string Portfolio { get => base.Portfolio; init => base.Portfolio = value; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "STd2Dg5TnU-jBYDxq-VbnA", + "cell_type": "markdown", + "source": [ + "", + "\n## Data Node State", + "\n", + "\nThe Data State is used to track whether a GOC is Active or Inactive across time (year and month). ", + "\nIt is only possible to update the state of a Group of Contract from Active to Inactive." + ], + "metadata": {} + }, + { + "id": "l1RwYYRGQUuYklornedCUA", + "cell_type": "code", + "source": [ + "public record DataNodeState : KeyedRecord, IPartitioned, IWithYearAndMonth", + "\n{", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNode))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n public string DataNode { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n [DefaultValue(DefaultDataNodeActivationMonth)]", + "\n public int Month { get; init; } = DefaultDataNodeActivationMonth;", + "\n ", + "\n [Required]", + "\n [Display(Order = 40)]", + "\n [DefaultValue(State.Active)]", + "\n public State State { get; init; } = State.Active;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "siMZOfujgkCvYRhglSafRw", + "cell_type": "markdown", + "source": [ + "", + "\n## Data Node Parameters", + "\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 AocType of the Technical Margin and is valid only for Group of Insurance Contract with LiabilityType : Liability for Remaining Coverage.", + "\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.", + "\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." + ], + "metadata": {} + }, + { + "id": "Y9V4hdUwV0WlDgxhiVJ0lg", + "cell_type": "code", + "source": [ + "public record DataNodeParameter : KeyedRecord, IPartitioned, IWithYearAndMonth", + "\n{", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNode))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n [DefaultValue(DefaultDataNodeActivationMonth)]", + "\n public int Month { get; init; } = DefaultDataNodeActivationMonth;", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n public string DataNode { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Cnr2el8xg0OjF0x79bM9lQ", + "cell_type": "code", + "source": [ + "public record SingleDataNodeParameter : DataNodeParameter {", + "\n [DefaultValue(DefaultPremiumExperienceAdjustmentFactor)]", + "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n public double PremiumAllocation { get; init; } = DefaultPremiumExperienceAdjustmentFactor;", + "\n}", + "\n", + "\npublic record InterDataNodeParameter : DataNodeParameter {", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n public string LinkedDataNode { get; init; }", + "\n ", + "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n public double ReinsuranceCoverage { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WCZyCC4Qlkm0FjxSRHM0xw", + "cell_type": "markdown", + "source": [ + "## DataNodeData PocoType", + "\nThe DataNodeData type is not persisted (i.e. not stored in the database) and is used in order to hold Data Node data during data manipulations." + ], + "metadata": {} + }, + { + "id": "koNxFi27ZkuU4_2cCG2GMA", + "cell_type": "code", + "source": [ + "public record DataNodeData {", + "\n public string DataNode { get; init; }", + "\n ", + "\n //Portfolio", + "\n public string ContractualCurrency { get; init; }", + "\n public string FunctionalCurrency { get; init; }", + "\n public string LineOfBusiness { get; init; }", + "\n public string ValuationApproach { get; init; }", + "\n public string OciType { get; init; }", + "\n ", + "\n //GroupOfContract", + "\n public string Portfolio { get; init; }", + "\n public int AnnualCohort { get; init; }", + "\n public string LiabilityType { get; init; }", + "\n public string Profitability { get; init; }", + "\n public string Partner { get; init; }", + "\n ", + "\n //DataNodeState", + "\n public int Year { get; init; }", + "\n public int Month { get; init; }", + "\n public State State { get; init; }", + "\n public State PreviousState { get; init; }", + "\n ", + "\n public bool IsReinsurance { get; init; }", + "\n ", + "\n public DataNodeData(){}", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9zeoLgvZ8EKhCCDbihId8w", + "cell_type": "markdown", + "source": [ + "", + "\n## Raw Variables (Cashflows)", + "\n", + "\nRaw Variables are used to store **cashflows** on the database during import, i.e. *after* mappings are applied and *before* calculations are applied.", + "\n", + "\nThey are stored on the database for both audit and re-calculation purposes." + ], + "metadata": {} + }, + { + "id": "vy4oWvNmmUGJTicrwsX63Q", + "cell_type": "code", + "source": [ + "public abstract record BaseVariableIdentity {", + "\n [NotVisible]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n [IdentityProperty]", + "\n public string DataNode { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(AocType))]", + "\n [IdentityProperty]", + "\n public string AocType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Novelty))]", + "\n [IdentityProperty]", + "\n public string Novelty { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_bTxTL4-o0efG6zNvhuDjg", + "cell_type": "code", + "source": [ + "public abstract record BaseDataRecord : BaseVariableIdentity, IKeyed, IPartitioned {", + "\n [Key]", + "\n [NotVisible] ", + "\n public Guid Id { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNodeAndPeriod))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(AmountType))]", + "\n [IdentityProperty]", + "\n public string AmountType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(int),nameof(AccidentYear))]", + "\n [IdentityProperty]", + "\n public int? AccidentYear { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "X688yB4HTEm3riHh8lTrug", + "cell_type": "markdown", + "source": [ + "Basically, RawVariable is defined for a certain Reporting Node, Scenario, Year, Month, Amount Type and Calculation Type:" + ], + "metadata": {} + }, + { + "id": "kfbf0LwJSEGaxyUuPFnsKg", + "cell_type": "code", + "source": [ + "public record RawVariable : BaseDataRecord", + "\n{", + "\n [Conversion(typeof(PrimitiveArrayConverter))]", + "\n public double[] Values { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(CalculationType))]", + "\n [IdentityProperty]", + "\n public string CalculationType { get; init; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IeCO6PmNPEioYptDRrzHTA", + "cell_type": "markdown", + "source": [ + "", + "\n## Ifrs Variable", + "\n", + "\nIfrs Variables are used to store:", + "\n", + "\n- **Actual Values**", + "\n- **Present Values**", + "\n", + "\nPresent Values are calculated from the [raw variables](#raw-variables) during the import of cashflows.", + "\n", + "\nIfrs Variables are stored on the database, i.e. they are 'persisted', for performance purposes." + ], + "metadata": {} + }, + { + "id": "H9N-c0drk0GPoWh-VfRXzA", + "cell_type": "code", + "source": [ + "public record IfrsVariable : BaseDataRecord", + "\n{", + "\n public double Value { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(EstimateType))]", + "\n [IdentityProperty]", + "\n public string EstimateType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(EconomicBasis))]", + "\n [IdentityProperty]", + "\n public string EconomicBasis { get; init; }", + "\n ", + "\n public IfrsVariable (){}", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MCh8EtPVKUyEIcixf6Q_1Q", + "cell_type": "markdown", + "source": [ + "", + "\n## Import Identity", + "\nThe Import Identity contains the data elements used to determine the data sets which are used when performing data manipulations, e.g. during a [data import](./Import/ImportScopeCalculation) - In particular, an Import Identity is defined by: DataNode, AocType, Novelty, and whether it's reinsurance data or not:" + ], + "metadata": {} + }, + { + "id": "w5SSaFTyYE-3Xj0yy0eobw", + "cell_type": "code", + "source": [ + "public record ImportIdentity : BaseVariableIdentity {", + "\n ", + "\n [NotVisible]", + "\n public bool IsReinsurance { get; init; }", + "\n ", + "\n [NotVisible]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n [NotVisible]", + "\n public int ProjectionPeriod { get; init; }", + "\n ", + "\n public (string, string) AocStep => (AocType, Novelty);", + "\n ", + "\n public ImportScope ImportScope { get; init; }", + "\n ", + "\n public ImportIdentity(RawVariable rv){", + "\n DataNode = rv.DataNode;", + "\n AocType = rv.AocType;", + "\n Novelty = rv.Novelty;", + "\n }", + "\n ", + "\n public ImportIdentity(IfrsVariable iv){", + "\n DataNode = iv.DataNode;", + "\n AocType = iv.AocType;", + "\n Novelty = iv.Novelty;", + "\n }", + "\n", + "\n public ImportIdentity(){}", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "31-e-C4gwESKBN8E0Rr6gQ", + "cell_type": "markdown", + "source": [ + "", + "\n# Report Variable", + "\n", + "\nReport Variables are used to hold data after data manipulations and before being outputed in the form of a report. They are not persisted, i.e. they are not saved on the database." + ], + "metadata": {} + }, + { + "id": "2yvEMKViYE6wZPnuy7AClg", + "cell_type": "code", + "source": [ + "public record ReportVariable {", + "\n", + "\n [NotVisible]", + "\n [Dimension(typeof(ReportingNode))]", + "\n [IdentityProperty]", + "\n public string ReportingNode { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Scenario))]", + "\n [IdentityProperty]", + "\n public string Scenario { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Currency), nameof(FunctionalCurrency))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public string FunctionalCurrency { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Currency), nameof(ContractualCurrency))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public string ContractualCurrency { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n [IdentityProperty]", + "\n public string GroupOfContract { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Portfolio))]", + "\n [IdentityProperty]", + "\n public string Portfolio { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(LineOfBusiness))]", + "\n [IdentityProperty]", + "\n public string LineOfBusiness { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(LiabilityType))]", + "\n [IdentityProperty]", + "\n public string LiabilityType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Profitability), nameof(InitialProfitability))]", + "\n [IdentityProperty]", + "\n public string InitialProfitability { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(ValuationApproach))]", + "\n [IdentityProperty]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(AnnualCohort))]", + "\n [IdentityProperty]", + "\n public int AnnualCohort { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(OciType))]", + "\n [IdentityProperty]", + "\n public string OciType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Partner))]", + "\n [IdentityProperty]", + "\n public string Partner { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [IdentityProperty]", + "\n public bool IsReinsurance { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(AccidentYear))]", + "\n [IdentityProperty]", + "\n public int AccidentYear { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Projection))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public int Projection { get; init;}", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(VariableType))]", + "\n [IdentityProperty]", + "\n public string VariableType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Novelty))]", + "\n [IdentityProperty]", + "\n public string Novelty { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(AmountType))]", + "\n [IdentityProperty]", + "\n public string AmountType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(EstimateType))]", + "\n [IdentityProperty]", + "\n public string EstimateType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(EconomicBasis))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public string EconomicBasis { get; init; }", + "\n ", + "\n public double Value { get; init; }", + "\n ", + "\n public ReportVariable(){}", + "\n public ReportVariable(ReportVariable rv){", + "\n ReportingNode = rv.ReportingNode;", + "\n Scenario = rv.Scenario;", + "\n FunctionalCurrency = rv.FunctionalCurrency;", + "\n ContractualCurrency = rv.ContractualCurrency;", + "\n GroupOfContract = rv.GroupOfContract;", + "\n Portfolio = rv.Portfolio;", + "\n LineOfBusiness = rv.LineOfBusiness;", + "\n LiabilityType = rv.LiabilityType;", + "\n InitialProfitability = rv.InitialProfitability;", + "\n ValuationApproach = rv.ValuationApproach;", + "\n AnnualCohort = rv.AnnualCohort;", + "\n OciType = rv.OciType;", + "\n Partner = rv.Partner;", + "\n IsReinsurance = rv.IsReinsurance;", + "\n AccidentYear = rv.AccidentYear;", + "\n Projection = rv.Projection;", + "\n VariableType = rv.VariableType;", + "\n Novelty = rv.Novelty;", + "\n AmountType = rv.AmountType;", + "\n EstimateType = rv.EstimateType;", + "\n EconomicBasis = rv.EconomicBasis;", + "\n Value = rv.Value;", + "\n }", + "\n public ReportVariable(DataNodeData dn, IfrsVariable iv){", + "\n FunctionalCurrency = dn.FunctionalCurrency;", + "\n ContractualCurrency = dn.ContractualCurrency;", + "\n GroupOfContract = dn.DataNode;", + "\n Portfolio = dn.Portfolio;", + "\n LineOfBusiness = dn.LineOfBusiness;", + "\n LiabilityType = dn.LiabilityType;", + "\n InitialProfitability = dn.Profitability;", + "\n ValuationApproach = dn.ValuationApproach;", + "\n AnnualCohort = dn.AnnualCohort;", + "\n OciType = dn.OciType;", + "\n Partner = dn.Partner;", + "\n IsReinsurance = dn.IsReinsurance;", + "\n AccidentYear = iv.AccidentYear ?? default;", + "\n VariableType = iv.AocType;", + "\n Novelty = iv.Novelty;", + "\n AmountType = iv.AmountType;", + "\n EstimateType = iv.EstimateType;", + "\n EconomicBasis = iv.EconomicBasis;", + "\n Value = iv.Value;", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WtIFU8efQE2aUaVim03Iog", + "cell_type": "markdown", + "source": [ + "# Args" + ], + "metadata": {} + }, + { + "id": "i8WBwS3IuUqLxaV5XGKWsg", + "cell_type": "code", + "source": [ + "public record Args(string ReportingNode, int Year, int Month, Periodicity Periodicity, string Scenario){}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6FcgQqQpzE2yPeqwZNRfiQ", + "cell_type": "code", + "source": [ + "public record ImportArgs : Args", + "\n{", + "\n public string ImportFormat { get; init; }", + "\n ", + "\n public ImportArgs(string reportingNode, int year, int month, Periodicity periodicity, string scenario, string importFormat)", + "\n : base(reportingNode, year, month, periodicity, scenario)", + "\n {", + "\n ImportFormat = importFormat;", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mJUZ9khq1k-jUZcG-qZniQ", + "cell_type": "code", + "source": [ + "public record ReportArgs : Args", + "\n{", + "\n public string HierarchyName { get; init; }", + "\n ", + "\n public CurrencyType CurrencyType { get; init; }", + "\n ", + "\n public string ReportName { get; init; } // this is the key to which data to load (like loading behavior). If null, loads everything", + "\n ", + "\n public ReportArgs(string reportingNode, int year, int month, Periodicity periodicity, string scenario, string hierarchyName, CurrencyType currencyType)", + "\n : base(reportingNode, year, month, periodicity, scenario)", + "\n {", + "\n CurrencyType = currencyType;", + "\n HierarchyName = hierarchyName;", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Database/.gitignore b/Database/.gitignore new file mode 100644 index 00000000..34be061b --- /dev/null +++ b/Database/.gitignore @@ -0,0 +1 @@ +PersonalConnection.ipynb \ No newline at end of file diff --git a/Database/Configure.ipynb b/Database/Configure.ipynb new file mode 100644 index 00000000..2819a9af --- /dev/null +++ b/Database/Configure.ipynb @@ -0,0 +1,131 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "vWKQtrDv20CeZFovAj82Vw", + "cell_type": "markdown", + "source": [ + "

DataSource Configuration

" + ], + "metadata": {} + }, + { + "id": "ekOMREP2YkKF0vgtOn6cyQ", + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "eEI7AS2fc0-CFjAR_WzdHg", + "cell_type": "code", + "source": [ + "#!import \"PersonalConnection\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZoHg5nndvEWdxnUy6nU0aQ", + "cell_type": "code", + "source": [ + "using System.Reflection;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "V3sPPe7bkEOIAjZHtM5oTw", + "cell_type": "markdown", + "source": [ + "# Database Configure" + ], + "metadata": {} + }, + { + "id": "ZxIo5q84i02LBlbq4AQnNA", + "cell_type": "code", + "source": [ + "var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())", + "\n .Where(t => (t.IsAssignableTo(typeof(IKeyed)) || t.IsAssignableTo(typeof(KeyedDimension)))", + "\n && !t.IsInterface", + "\n && !t.IsAbstract", + "\n ).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Wi93Z_KSukSEMiLoOfsKXA", + "cell_type": "code", + "source": [ + "await DataSource.Configure().UseMsSql(opt => opt.WithConnectionString(connectionStringMsSql)", + "\n .WithTypes(allTypes)) .ConnectAsync();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4jSr3apQzEm6bXs7ot9uJQ", + "cell_type": "code", + "source": [ + "await DataSource.CommitAsync();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "SUiuO25f-0S6Uv5at0MehA", + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ], + "metadata": {} + }, + { + "id": "T0pNd11nrkuDwN6S0YgItg", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sAYMeiwmiUWC-T3QYXi7aw", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Database/Schema Delete.ipynb b/Database/Schema Delete.ipynb new file mode 100644 index 00000000..49792b90 --- /dev/null +++ b/Database/Schema Delete.ipynb @@ -0,0 +1,87 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "documentInfo": "{\r\n \"authors\": [\r\n \"Peter Kunszt\"\r\n ],\r\n \"contributors\": [],\r\n \"tags\": [\r\n \"storage\",\r\n \"database\",\r\n \"persistence\",\r\n \"dependency\"\r\n ],\r\n \"title\": \"Multiple Storages with Persistence\",\r\n \"description\": \"Demo the usage of database backend to resolve a data dependency.\",\r\n \"createdDate\": \"Jan. 2022\",\r\n \"publishedDate\": \"Jan. 2022\",\r\n \"changelog\": [\r\n {\r\n \"version\": \"1.0\",\r\n \"description\": \"Initial Notebook\"\r\n }\r\n ]\r\n }" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "XekEwxVoCk6YtMSTaBi_6A", + "cell_type": "code", + "source": [ + "#!import \"PersonalConnection\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "aMGWTiny-EO8ZtyaiC0M2A", + "cell_type": "code", + "source": [ + "#r \"nuget:SqlConnection,1.0.4\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dKBE6yQHq0CZbS4Oq7ZXag", + "cell_type": "code", + "source": [ + "string[] split = connectionStringMsSql.Split(new char[] { '=', ':', ',', ';' });", + "\n", + "\nstring serverName = split[2];", + "\nstring database = split[5];", + "\nstring userID = split[9];", + "\nstring password = split[11];" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BBbDUGWgHUywoxk289vQ2A", + "cell_type": "code", + "source": [ + "using SQLConnection;", + "\nusing System;", + "\nusing System.Data.SqlClient;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "S-_OArgE70qFUpEbX12H3Q", + "cell_type": "code", + "source": [ + "string query = \"DECLARE @sql NVARCHAR(max)='' SELECT @sql += ' Drop table ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) + '; 'FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' Exec Sp_executesql @sql\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oeQryPr0l0uflGqNrUvmLw", + "cell_type": "code", + "source": [ + "int rowAffect = SqlServer.AzureSqlConnection(serverName, database, userID, password, query);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Export/MapTemplate.ipynb b/Export/MapTemplate.ipynb new file mode 100644 index 00000000..c1fb9d01 --- /dev/null +++ b/Export/MapTemplate.ipynb @@ -0,0 +1,338 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "J7Lk0NfjhkC9DBXVAnd4ag", + "cell_type": "markdown", + "source": [ + "

Map Template

" + ], + "metadata": {} + }, + { + "id": "nJozo1XeSkeGCLiQXUPlzA", + "cell_type": "markdown", + "source": [ + "This Notebook exports the Data nodes, states, and parameters for the target partition to a spreadsheet file which can be read, modified, and is ready to be re-imported." + ], + "metadata": {} + }, + { + "id": "T4LYGKNFjke1IDEPU8E44Q", + "cell_type": "markdown", + "source": [ + "After setting the desired target Partition, the Data present in the workspace is ready to be exported. " + ], + "metadata": {} + }, + { + "id": "J3Om4qznT0qnFdizsJg6gA", + "cell_type": "markdown", + "source": [ + "# Import dependencies" + ], + "metadata": {} + }, + { + "id": "jz0ZzjaNNkyPlNjH7p_9CQ", + "cell_type": "code", + "source": [ + "#!import \"../Utils/UtilityMethods\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4kGmVeM2F0y1LR3iEJJAaA", + "cell_type": "markdown", + "source": [ + "# Select Initialization" + ], + "metadata": {} + }, + { + "id": "nVFGNWhtb0iw49kOFNKpUQ", + "cell_type": "markdown", + "source": [ + "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." + ], + "metadata": {} + }, + { + "id": "MbQiJg5acUurtMhQFZOPtw", + "cell_type": "code", + "source": [ + "/* The DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"Database/Configure\"", + "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", + "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Ma-JBoxkmUqAb81Pb2v8EA", + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ], + "metadata": {} + }, + { + "id": "zaO0K3_d3UOftmtrwhqrFg", + "cell_type": "markdown", + "source": [ + "Firstly, the Workspace is initialized with basic dimensions and with Data Nodes. For a list of the dimensions please refer to the DataModel/DataStructure notebook." + ], + "metadata": {} + }, + { + "id": "BP4HG8krfkul6dXSvdGHnw", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CirOR3dQA0iqxXipYfNcFQ", + "cell_type": "markdown", + "source": [ + "# Map Template: Data Node" + ], + "metadata": {} + }, + { + "id": "z1pGwBuU20ywRLjN6Gj5eg", + "cell_type": "markdown", + "source": [ + "## Set Partition" + ], + "metadata": {} + }, + { + "id": "8y9ezk2H7EetGACPthoNUw", + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNode() { ReportingNode = \"CH\" };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XFPlV7vwiUCUY7llRpEeEQ", + "cell_type": "code", + "source": [ + "await Workspace.Partition.SetAsync( partition );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7MTJTAXvjUCDuc6-sHSUQQ", + "cell_type": "markdown", + "source": [ + "## Export" + ], + "metadata": {} + }, + { + "id": "yBbsPeQ5XkO5M_mXJtkiTw", + "cell_type": "code", + "source": [ + "await Export.ToExcel(\"DataNodes\")", + "\n .WithSource(Workspace)", + "\n .PortfolioConfiguration()", + "\n .PortfolioConfiguration()", + "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", + "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "SG9iYPdfGkOJqrcbjN-cIQ", + "cell_type": "markdown", + "source": [ + "# Map Template: Data Node State" + ], + "metadata": {} + }, + { + "id": "go7LKWKxBECDgXOhv9Se8g", + "cell_type": "markdown", + "source": [ + "## Set Partition" + ], + "metadata": {} + }, + { + "id": "b7xD5r6TuE2QTO-J6L8q-Q", + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q1MIgSZcNE60Sx6cCGC9YA", + "cell_type": "code", + "source": [ + "await Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "reWr-I2FeUijpPeiXGdOCA", + "cell_type": "markdown", + "source": [ + "## Export" + ], + "metadata": {} + }, + { + "id": "iW-JFPjuS0q_aGWGSn4Ujg", + "cell_type": "code", + "source": [ + "var dataNodeStates = (await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", + "\n .GroupBy(x => x.DataNode)", + "\n .Select(x => x.OrderByDescending(y => y.Year).ThenByDescending(y => y.Month))", + "\n .Select(x => x.Last())", + "\n .ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "64_Gk6W_qkuh47zAJ1xcZw", + "cell_type": "code", + "source": [ + "await Export.ToExcel(\"DataNodeState\")", + "\n .WithSource(Workspace)", + "\n .StateEnumConfiguration() ", + "\n .DataNodeStateConfiguration(dataNodeStates)", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Aolg5llKGkWX3-v94jBP8A", + "cell_type": "markdown", + "source": [ + "# Map Template: Data Node Parameter" + ], + "metadata": {} + }, + { + "id": "amCy5h6BA0K6wxCh7NvZrg", + "cell_type": "markdown", + "source": [ + "## Set Partition" + ], + "metadata": {} + }, + { + "id": "kMTcDi7DFEC6FuMagh5uDg", + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-tmD3uOmwUmFUX_q78nD7A", + "cell_type": "code", + "source": [ + "await Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "z6pkleZXd0mZN82EQprS3w", + "cell_type": "markdown", + "source": [ + "## Export" + ], + "metadata": {} + }, + { + "id": "0zdLZPrPw0Sm4w1TjesGMQ", + "cell_type": "code", + "source": [ + "var dataNodeParameters = (await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", + "\n .GroupBy(x => x.GetType().Name)", + "\n .ToDictionary(x => x.Key, ", + "\n x => x.GroupBy(y => y.DataNode)", + "\n .Select(y => y.OrderByDescending(z => z.Year).ThenByDescending(z => z.Month))", + "\n .Select(y => y.Last())", + "\n .ToArray() );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xp0dlpVqC0mQfbqqrpn8Aw", + "cell_type": "code", + "source": [ + "await Export.ToExcel(\"DataNodeParameter\")", + "\n .WithSource(Workspace)", + "\n .DataNodeParameterConfiguration(dataNodeParameters)", + "\n .MainTabConfiguration(partition)", + "\n.ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3tf3mjl0gUqui_fD_X7OmQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Files/300.ReportingNodes/ReportingNodes.csv b/Files/300.ReportingNodes/ReportingNodes.csv new file mode 100644 index 00000000..ffaab637 --- /dev/null +++ b/Files/300.ReportingNodes/ReportingNodes.csv @@ -0,0 +1,10 @@ +@@ReportingNode,,,, +SystemName,DisplayName,Parent,Currency +G,Group,,CHF +CH,Switzerland,G,CHF +DE,Germany,G,EUR +ES,Spain,G,EUR +FR,France,G,EUR +IT,Italy,G,EUR +UK,United Kingdom,G,GBP +SK,Slovakia,G,EUR diff --git a/Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv b/Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv new file mode 100644 index 00000000..19a655dc --- /dev/null +++ b/Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv @@ -0,0 +1,22 @@ +@@Main,, +ReportingNode,Year,Month +CH,2020,12 +,, +@@SingleDataNodeParameter,, +DataNode,PremiumAllocation, +GicComplex,0.8, +DT1.1,0.8, +DT1.2,0.8, +DT1.3,1, +DT2.1,0.8, +DT2.2,0.8, +DT3.1,0.8, +DT4.1,0.8, +,, +@@InterDataNodeParameter,, +DataNode,LinkedDataNode,ReinsuranceCoverage +DT1.1,DTR1.1,1 +DT1.2,DTR1.2,1 +DT2.1,DTR2.1,1 +DT2.2,DTR2.2,1 +GricComplex,GicComplex,1 diff --git a/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv b/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv new file mode 100644 index 00000000..78802935 --- /dev/null +++ b/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv @@ -0,0 +1,19 @@ +@@Main,, +ReportingNode,Year,Month +CH,2020,12 +,, +@@DataNodeState,, +DataNode,State, +GicComplex,Active, +GricComplex,Active, +DT1.1,Active, +DT1.2,Active, +DT1.3,Active, +DT2.1,Active, +DT2.2,Active, +DT3.1,Active, +DT4.1,Active, +DTR1.1,Active, +DTR1.2,Active, +DTR2.1,Active, +DTR2.2,Active, diff --git a/Files/700.DataNodes/DataNodes_CH.csv b/Files/700.DataNodes/DataNodes_CH.csv new file mode 100644 index 00000000..54f5657f --- /dev/null +++ b/Files/700.DataNodes/DataNodes_CH.csv @@ -0,0 +1,36 @@ +@@Main,,,,,, +ReportingNode,,,,,, +CH,,,,,, +,,,,,, +@@InsurancePortfolio,,,,,, +SystemName,DisplayName,ContractualCurrency,LineOfBusiness,ValuationApproach,OciType, +DT,DT complex CF,USD,ANN,BBA,Default, +DT1,DT1 OCI,USD,ANN,BBA,Default, +DT2,DT2 NOCI,USD,ANN,BBA,, +DT3,DT3 RunOff,USD,ANN,BBA,Default, +DT4,DT4 OCI,USD,ANN,BBA,Default, +,,,,,, +@@GroupOfInsuranceContract,,,,,, +SystemName,DisplayName,InsurancePortfolio,AnnualCohort,LiabilityType,Profitability, +GicComplex,Gic test discounting,DT,2020,LRC,P, +DT1.1,DT1.1 OCI LRC PA 0.8,DT1,2020,LRC,P, +DT1.2,DT1.2 OCI LIC,DT1,2020,LIC,P, +DT1.3,DT1.3 OCI LRC PA 1,DT1,2020,LRC,P, +DT2.1,DT2.1 NOCI LRC PA 0.8,DT2,2020,LRC,P, +DT2.2,DT2.2 NOCI LIC,DT2,2020,LIC,P, +DT3.1,DT3.1 Runoff - PA 0.8,DT3,2020,LRC,P, +DT4.1,DT4.1 CSM PA 0.8,DT4,2020,LRC,P, +,,,,,, +@@ReinsurancePortfolio,,,,,, +SystemName,DisplayName,ContractualCurrency,LineOfBusiness,ValuationApproach,OciType, +DTR,DTR complex CF,USD,ANN,BBA,, +DTR1,DTR1 OCI,USD,ANN,BBA,Default, +DTR2,DTR2 NOCI,USD,ANN,BBA,, +,,,,,, +@@GroupOfReinsuranceContract,,,,,, +SystemName,DisplayName,ReinsurancePortfolio,AnnualCohort,LiabilityType,Profitability,Partner +GricComplex,Gric test for discounting,DTR,2020,LRC,P,PT1 +DTR1.1,DTR1.1 OCI LRC,DTR1,2020,LRC,P,PT1 +DTR1.2,DTR1.2 OCI LIC,DTR1,2020,LIC,P,PT1 +DTR2.1,DTR2.1 NOCI LRC,DTR2,2020,LRC,P,PT1 +DTR2.2,DTR2.2 NOCI LIC,DTR2,2020,LIC,P,PT1 diff --git a/Files/800.Parameters/CreditDefaultRate.csv b/Files/800.Parameters/CreditDefaultRate.csv new file mode 100644 index 00000000..b39c644e --- /dev/null +++ b/Files/800.Parameters/CreditDefaultRate.csv @@ -0,0 +1,23 @@ +@@CreditDefaultRate,,, +Year,Month,CreditRiskRating,Values0 +1900,12,AAA,0.00014 +1900,12,AA+,0.000242487 +1900,12,AA,0.00042 +1900,12,AA-,0.000469849 +1900,12,A+,0.000525615 +1900,12,A,0.000588 +1900,12,A-,0.000853615 +1900,12,BBB+,0.001239215 +1900,12,BBB,0.001799 +1900,12,BBB-,0.00297649 +1900,12,BB+,0.004924677 +1900,12,BB,0.008148 +1900,12,BB-,0.011522675 +1900,12,B+,0.016295046 +1900,12,B,0.023044 +1900,12,B-,0.031505634 +1900,12,CCC+,0.043074334 +1900,12,CCC,0.058891 +1900,12,CCC-,0.079972327 +1900,12,CC,0.108600179 +1900,12,C,0.147476 diff --git a/Files/800.Parameters/ExchangeRate.csv b/Files/800.Parameters/ExchangeRate.csv new file mode 100644 index 00000000..8ac834c7 --- /dev/null +++ b/Files/800.Parameters/ExchangeRate.csv @@ -0,0 +1,14 @@ +@@ExchangeRate +Currency,Year,Month,FxType,FxToGroupCurrency +EUR,2021,3,Average,1.2012 +EUR,2021,3,Spot,1.2013 +EUR,2020,12,Average,1.2014 +EUR,2020,12,Spot,1.2015 +USD,2021,3,Average,1.2016 +USD,2021,3,Spot,1.2017 +USD,2020,12,Average,1.2018 +USD,2020,12,Spot,1.2019 +GBP,2021,3,Average,1.4016 +GBP,2021,3,Spot,1.4017 +GBP,2020,12,Average,1.4018 +GBP,2020,12,Spot,1.4019 \ No newline at end of file diff --git a/Files/800.Parameters/PartnerRating.csv b/Files/800.Parameters/PartnerRating.csv new file mode 100644 index 00000000..8f9d717c --- /dev/null +++ b/Files/800.Parameters/PartnerRating.csv @@ -0,0 +1,4 @@ +@@PartnerRating +Partner,CreditRiskRating,Year,Month +PT1,AAA,2020,12 +PT1,BBB,2021,3 \ No newline at end of file diff --git a/Files/800.Parameters/YieldCurve.csv b/Files/800.Parameters/YieldCurve.csv new file mode 100644 index 00000000..892b7ee7 --- /dev/null +++ b/Files/800.Parameters/YieldCurve.csv @@ -0,0 +1,11 @@ +@@YieldCurve,,,,,, +Currency,Year,Month,Values0,Values1,Values2,Values3 +EUR,2020,3,0.008685495,0.008685495,0.018498471,0.019966839 +CHF,2020,3,0.002,0.002,0.002,0.002 +CHF,2021,3,0.1,0.1,0.1,0.1 +USD,2021,3,0.005,0.005,0.005,0.005 +USD,2020,12,0.002,0.002,0.002,0.002 +USD,2020,3,0.002,0.002,0.002,0.002 +USD,2020,1,0.002,0.002,0.002,0.002 +GBP,2021,3,0.005,0.005,0.005,0.005 +GBP,2020,3,0.002,0.002,0.002,0.002 diff --git a/Files/900.TransactionalData/Actuals_CH_2020_12.csv b/Files/900.TransactionalData/Actuals_CH_2020_12.csv new file mode 100644 index 00000000..12bfc994 --- /dev/null +++ b/Files/900.TransactionalData/Actuals_CH_2020_12.csv @@ -0,0 +1,33 @@ +@@Main,,,, +ReportingNode,Year,Month,, +CH,2020,12,, +@@Actual,,,, +DataNode,AocType,ValueType,AccidentYear,Value +DT1.1,CF,PR,,-400 +DT1.1,CF,NIC,,280 +DT1.1,CF,ACA,,10 +DT1.1,CF,AEA,,5 +DT1.2,CF,NIC,2020,280 +DT2.1,CF,PR,,-400 +DT2.1,CF,NIC,,280 +DT2.1,CF,ACA,,10 +DT2.1,CF,AEA,,5 +DT1.3,CF,PR,,-400 +DT1.3,CF,NIC,,280 +DT1.3,CF,ACA,,10 +DT1.3,CF,AEA,,5 +DT2.2,CF,NIC,2020,280 +DTR1.1,CF,PR,,200 +DTR1.1,CF,NIC,,-140 +DTR1.2,CF,NIC,2020,-140 +DTR2.1,CF,PR,,200 +DTR2.1,CF,NIC,,-140 +DTR2.2,CF,NIC,2020,-140 +DT3.1,CF,PR,,-400 +DT3.1,CF,NIC,,280 +DT3.1,CF,ACA,,10 +DT3.1,CF,AEA,,5 +DT4.1,CF,PR,,-400 +DT4.1,CF,NIC,,280 +DT4.1,CF,ACA,,10 +DT4.1,CF,AEA,,5 diff --git a/Files/900.TransactionalData/Actuals_CH_2021_3.csv b/Files/900.TransactionalData/Actuals_CH_2021_3.csv new file mode 100644 index 00000000..d52bae26 --- /dev/null +++ b/Files/900.TransactionalData/Actuals_CH_2021_3.csv @@ -0,0 +1,62 @@ +@@Main,,,, +ReportingNode,Year,Month,, +CH,2021,3,, +@@Actual,,,, +DataNode,AocType,ValueType,AccidentYear,Value +DT1.1,WO,PayablePR,,-4 +DT1.1,WO,ReceivablePR,,2 +DT1.1,CF,PayablePR,,5 +DT1.1,CF,ReceivablePR,,-3 +DT1.1,CF,PR,,-90 +DT1.1,CF,ICO,,6 +DT1.1,CF,NIC,,70 +DT1.1,CF,ACA,,10 +DT1.1,CF,AEA,,5 +DT1.2,CF,NIC,2020,76 +DT1.3,WO,PayablePR,,-4 +DT1.3,WO,ReceivablePR,,2 +DT1.3,CF,PayablePR,,5 +DT1.3,CF,ReceivablePR,,-3 +DT1.3,CF,PR,,-90 +DT1.3,CF,ICO,,6 +DT1.3,CF,NIC,,70 +DT1.3,CF,ACA,,10 +DT1.3,CF,AEA,,5 +DT2.1,WO,PayablePR,,-4 +DT2.1,WO,ReceivablePR,,2 +DT2.1,CF,PayablePR,,5 +DT2.1,CF,ReceivablePR,,-3 +DT2.1,CF,PR,,-90 +DT2.1,CF,ICO,,6 +DT2.1,CF,NIC,,70 +DT2.1,CF,ACA,,10 +DT2.1,CF,AEA,,5 +DT2.2,CF,NIC,2020,76 +DTR1.1,CF,PayablePR,,-2 +DTR1.1,CF,ReceivablePR,,1.5 +DTR1.1,CF,PR,,45 +DTR1.1,CF,NIC,,-35 +DTR1.2,CF,NIC,2020,-35 +DTR2.1,CF,PayablePR,,-2 +DTR2.1,CF,ReceivablePR,,1.5 +DTR2.1,CF,PR,,45 +DTR2.1,CF,NIC,,-35 +DTR2.2,CF,NIC,2020,-35 +DT3.1,WO,PayablePR,,-4 +DT3.1,WO,ReceivablePR,,2 +DT3.1,CF,PayablePR,,5 +DT3.1,CF,ReceivablePR,,-3 +DT3.1,CF,PR,,-90 +DT3.1,CF,ICO,,6 +DT3.1,CF,NIC,,70 +DT3.1,CF,ACA,,10 +DT3.1,CF,AEA,,5 +DT4.1,WO,PayablePR,,-4 +DT4.1,WO,ReceivablePR,,2 +DT4.1,CF,PayablePR,,5 +DT4.1,CF,ReceivablePR,,-3 +DT4.1,CF,PR,,-90 +DT4.1,CF,ICO,,6 +DT4.1,CF,NIC,,70 +DT4.1,CF,ACA,,10 +DT4.1,CF,AEA,,5 diff --git a/Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv b/Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv new file mode 100644 index 00000000..8808da31 --- /dev/null +++ b/Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv @@ -0,0 +1,85 @@ +@@Main,,,,,,,,,,,,,,,,,,,,,,,,,,,, +ReportingNode,Year,Month,Scenario,,,,,,,,,,,,,,,,,,,,,,,,, +CH,2020,12,,,,,,,,,,,,,,,,,,,,,,,,,, +@@Cashflow,,,,,,,,,,,,,,,,,,,,,,,,,,,, +DataNode,AmountType,AocType,Novelty,AccidentYear,Values0,Values1,Values2,Values3,Values4,Values5,Values6,Values7,Values8,Values9,Values10,Values11,Values12,Values13,Values14,Values15,Values16,Values17,Values18,Values19,Values20,Values21,Values22,Values23 +DT1.1,PR,BOP,N,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT1.1,NIC,BOP,N,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT1.1,CU,BOP,N,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT1.1,RA,BOP,N,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT1.1,PR,CL,C,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT1.1,NIC,CL,C,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT1.1,CU,CL,C,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT1.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT1.2,NIC,BOP,N,2020,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT1.2,CU,BOP,N,2020,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT1.2,RA,BOP,N,2020,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT1.2,NIC,CL,C,2020,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT1.2,CU,CL,C,2020,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT1.2,RA,CL,C,2020,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT1.3,PR,BOP,N,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT1.3,NIC,BOP,N,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT1.3,CU,BOP,N,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT1.3,RA,BOP,N,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT1.3,PR,CL,C,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT1.3,NIC,CL,C,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT1.3,CU,CL,C,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT1.3,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT2.1,PR,BOP,N,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT2.1,NIC,BOP,N,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT2.1,CU,BOP,N,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT2.1,RA,BOP,N,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT2.1,PR,CL,C,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT2.1,NIC,CL,C,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT2.1,CU,CL,C,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT2.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT2.2,NIC,BOP,N,2020,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT2.2,CU,BOP,N,2020,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT2.2,RA,BOP,N,2020,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT2.2,NIC,CL,C,2020,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT2.2,CU,CL,C,2020,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT2.2,RA,CL,C,2020,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DTR1.1,PR,BOP,N,,50,0,0,50,0,0,50,0,0,50,0,0,0,50,0,0,50,0,0,50,0,0,50,0 +DTR1.1,NIC,BOP,N,,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR1.1,CU,BOP,N,,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR1.1,RA,BOP,N,,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR1.1,PR,CL,C,,50,0,0,50,0,0,50,0,0,50,0,0,0,50,0,0,50,0,0,50,0,0,50,0 +DTR1.1,NIC,CL,C,,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR1.1,CU,CL,C,,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR1.1,RA,CL,C,,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR1.2,NIC,BOP,N,2020,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR1.2,CU,BOP,N,2020,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR1.2,RA,BOP,N,2020,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR1.2,NIC,CL,C,2020,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR1.2,CU,CL,C,2020,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR1.2,RA,CL,C,2020,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR2.1,PR,BOP,N,,50,0,0,50,0,0,50,0,0,50,0,0,0,50,0,0,50,0,0,50,0,0,50,0 +DTR2.1,NIC,BOP,N,,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR2.1,CU,BOP,N,,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR2.1,RA,BOP,N,,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR2.1,PR,CL,C,,50,0,0,50,0,0,50,0,0,50,0,0,0,50,0,0,50,0,0,50,0,0,50,0 +DTR2.1,NIC,CL,C,,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR2.1,CU,CL,C,,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR2.1,RA,CL,C,,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR2.2,NIC,BOP,N,2020,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR2.2,CU,BOP,N,2020,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR2.2,RA,BOP,N,2020,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DTR2.2,NIC,CL,C,2020,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5,-12.5 +DTR2.2,CU,CL,C,2020,5,5,5,5,5,5,5,5,5,5,5,5,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5 +DTR2.2,RA,CL,C,2020,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25 +DT3.1,PR,BOP,N,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT3.1,NIC,BOP,N,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT3.1,CU,BOP,N,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT3.1,RA,BOP,N,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT3.1,PR,CL,C,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT3.1,NIC,CL,C,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT3.1,CU,CL,C,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT3.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT4.1,PR,BOP,N,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT4.1,NIC,BOP,N,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT4.1,CU,BOP,N,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT4.1,RA,BOP,N,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 +DT4.1,PR,CL,C,,-100,0,0,-100,0,0,-100,0,0,-100,0,0,0,-100,0,0,-100,0,0,-100,0,0,-100,0 +DT4.1,NIC,CL,C,,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25,25 +DT4.1,CU,CL,C,,10,10,10,10,10,10,10,10,10,10,10,10,10,5,5,5,5,5,5,5,5,5,5,3 +DT4.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5 diff --git a/Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv b/Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv new file mode 100644 index 00000000..7bd3bdce --- /dev/null +++ b/Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv @@ -0,0 +1,158 @@ +@@Main,,,,,,,,,,,,,,,,,,,,,,,,, +ReportingNode,Year,Month,,,,,,,,,,,,,,,,,,,,,,, +CH,2021,3,,,,,,,,,,,,,,,,,,,,,,, +@@Cashflow,,,,,,,,,,,,,,,,,,,,,,,,, +DataNode,AmountType,AocType,Novelty,AccidentYear,Values0,Values1,Values2,Values3,Values4,Values5,Values6,Values7,Values8,Values9,Values10,Values11,Values12,Values13,Values14,Values15,Values16,Values17,Values18,Values19,Values20 +DT1.1,PR,MC,I,,0,-110,0,0,-110,0,0,-110,0,0,-110,0,0,0,0,0,0,0,0,0,0 +DT1.1,NIC,MC,I,,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT1.1,CU,MC,I,,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT1.1,RA,MC,I,,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT1.1,PR,BOP,N,,0,-10,0,0,-10,0,0,-10,0,0,-10,0,0,0,0,0,0,0,0,0,0 +DT1.1,ICO,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.1,NIC,BOP,N,,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0 +DT1.1,RA,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.1,PR,EV,N,,0,-5,0,0,-5,0,0,-5,0,0,-5,0,0,0,0,0,0,0,0,0,0 +DT1.1,ICO,EV,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.1,NIC,EV,N,,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0 +DT1.1,RA,EV,N,,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT1.1,PR,CL,C,,0,-115,0,0,-115,0,0,-115,0,0,-115,0,0,0,0,0,0,0,0,0,0 +DT1.1,ICO,CL,C,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.1,NIC,CL,C,,29,29,29,29,29,29,29,29,29,29,29,29,0,0,0,0,0,0,0,0,0 +DT1.1,CU,CL,C,,15,7,7,7,7,7,7,7,7,7,7,5,0,0,0,0,0,0,0,0,0 +DT1.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,0,0,0,0,0,0,0,0,0 +DT1.2,NIC,MC,I,2020,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT1.2,CU,MC,I,2020,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT1.2,RA,MC,I,2020,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT1.2,NIC,BOP,N,2020,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0 +DT1.2,RA,BOP,N,2020,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.2,NIC,EV,N,2020,10,10,10,10,10,10,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0 +DT1.2,RA,EV,N,2020,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT1.2,NIC,CL,C,2020,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,0,0,0 +DT1.2,CU,CL,C,2020,15,7,7,7,7,7,7,7,7,7,7,5,0,0,0,0,0,0,0,0,0 +DT1.2,RA,CL,C,2020,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,0,0,0,0,0,0,0,0,0 +DT1.3,PR,MC,I,,0,-110,0,0,-110,0,0,-110,0,0,-110,0,0,0,0,0,0,0,0,0,0 +DT1.3,NIC,MC,I,,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT1.3,CU,MC,I,,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT1.3,RA,MC,I,,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT1.3,PR,BOP,N,,0,-10,0,0,-10,0,0,-10,0,0,-10,0,0,0,0,0,0,0,0,0,0 +DT1.3,ICO,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.3,NIC,BOP,N,,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0 +DT1.3,RA,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.3,PR,EV,N,,0,-5,0,0,-5,0,0,-5,0,0,-5,0,0,0,0,0,0,0,0,0,0 +DT1.3,ICO,EV,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.3,NIC,EV,N,,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0 +DT1.3,RA,EV,N,,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT1.3,PR,CL,C,,0,-115,0,0,-115,0,0,-115,0,0,-115,0,0,0,0,0,0,0,0,0,0 +DT1.3,ICO,CL,C,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT1.3,NIC,CL,C,,29,29,29,29,29,29,29,29,29,29,29,29,0,0,0,0,0,0,0,0,0 +DT1.3,CU,CL,C,,15,7,7,7,7,7,7,7,7,7,7,5,0,0,0,0,0,0,0,0,0 +DT1.3,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,0,0,0,0,0,0,0,0,0 +DT2.1,PR,MC,I,,0,-110,0,0,-110,0,0,-110,0,0,-110,0,0,0,0,0,0,0,0,0,0 +DT2.1,NIC,MC,I,,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT2.1,CU,MC,I,,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT2.1,RA,MC,I,,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT2.1,PR,BOP,N,,0,-10,0,0,-10,0,0,-10,0,0,-10,0,0,0,0,0,0,0,0,0,0 +DT2.1,ICO,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT2.1,NIC,BOP,N,,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0 +DT2.1,RA,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT2.1,PR,EV,N,,0,-5,0,0,-5,0,0,-5,0,0,-5,0,0,0,0,0,0,0,0,0,0 +DT2.1,ICO,EV,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT2.1,NIC,EV,N,,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0 +DT2.1,RA,EV,N,,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT2.1,PR,CL,C,,0,-115,0,0,-115,0,0,-115,0,0,-115,0,0,0,0,0,0,0,0,0,0 +DT2.1,ICO,CL,C,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT2.1,NIC,CL,C,,29,29,29,29,29,29,29,29,29,29,29,29,0,0,0,0,0,0,0,0,0 +DT2.1,CU,CL,C,,15,7,7,7,7,7,7,7,7,7,7,5,0,0,0,0,0,0,0,0,0 +DT2.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,0,0,0,0,0,0,0,0,0 +DT2.2,NIC,MC,I,2020,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT2.2,CU,MC,I,2020,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT2.2,RA,MC,I,2020,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT2.2,NIC,BOP,N,2020,5,5,5,5,5,5,5,5,5,5,5,5,0,0,0,0,0,0,0,0,0 +DT2.2,RA,BOP,N,2020,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT2.2,NIC,EV,N,2020,10,10,10,10,10,10,10,10,10,10,10,10,0,0,0,0,0,0,0,0,0 +DT2.2,RA,EV,N,2020,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT2.2,NIC,CL,C,2020,30,30,30,30,30,30,30,30,30,30,30,30,0,0,0,0,0,0,0,0,0 +DT2.2,CU,CL,C,2020,15,7,7,7,7,7,7,7,7,7,7,5,0,0,0,0,0,0,0,0,0 +DT2.2,RA,CL,C,2020,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,0,0,0,0,0,0,0,0,0 +DTR1.1,PR,MC,I,,0,55,0,0,55,0,0,55,0,0,55,0,0,0,0,0,0,0,0,0,0 +DTR1.1,NIC,MC,I,,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,0,0,0,0,0,0,0,0,0 +DTR1.1,CU,MC,I,,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5,0,0,0,0,0,0,0,0,0 +DTR1.1,RA,MC,I,,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0 +DTR1.1,PR,BOP,N,,0,5,0,0,5,0,0,5,0,0,5,0,0,0,0,0,0,0,0,0,0 +DTR1.1,NIC,BOP,N,,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,0,0,0,0,0,0,0,0,0 +DTR1.1,RA,BOP,N,,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,0,0,0,0,0,0,0,0,0 +DTR1.1,PR,EV,N,,0,2.5,0,0,2.5,0,0,2.5,0,0,2.5,0,0,0,0,0,0,0,0,0,0 +DTR1.1,NIC,EV,N,,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,0,0,0,0,0,0,0,0,0 +DTR1.1,RA,EV,N,,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,0,0,0,0,0,0,0,0,0 +DTR1.1,PR,CL,C,,0,57.5,0,0,57.5,0,0,57.5,0,0,57.5,0,0,0,0,0,0,0,0,0,0 +DTR1.1,NIC,CL,C,,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,0,0,0,0,0,0,0,0,0 +DTR1.1,CU,CL,C,,7.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,2.5,0,0,0,0,0,0,0,0,0 +DTR1.1,RA,CL,C,,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,0,0,0,0,0,0,0,0,0 +DTR1.2,NIC,MC,I,2020,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,0,0,0,0,0,0,0,0,0 +DTR1.2,CU,MC,I,2020,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5,0,0,0,0,0,0,0,0,0 +DTR1.2,RA,MC,I,2020,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0 +DTR1.2,NIC,BOP,N,2020,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,0,0,0,0,0,0,0,0,0 +DTR1.2,RA,BOP,N,2020,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,0,0,0,0,0,0,0,0,0 +DTR1.2,NIC,EV,N,2020,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,0,0,0,0,0,0,0,0,0 +DTR1.2,RA,EV,N,2020,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,0,0,0,0,0,0,0,0,0 +DTR1.2,NIC,CL,C,2020,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,0,0,0,0,0,0,0,0,0 +DTR1.2,CU,CL,C,2020,7.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,2.5,0,0,0,0,0,0,0,0,0 +DTR1.2,RA,CL,C,2020,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,0,0,0,0,0,0,0,0,0 +DTR2.1,PR,MC,I,,0,55,0,0,55,0,0,55,0,0,55,0,0,0,0,0,0,0,0,0,0 +DTR2.1,NIC,MC,I,,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,0,0,0,0,0,0,0,0,0 +DTR2.1,CU,MC,I,,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5,0,0,0,0,0,0,0,0,0 +DTR2.1,RA,MC,I,,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0 +DTR2.1,PR,BOP,N,,0,5,0,0,5,0,0,5,0,0,5,0,0,0,0,0,0,0,0,0,0 +DTR2.1,NIC,BOP,N,,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,0,0,0,0,0,0,0,0,0 +DTR2.1,RA,BOP,N,,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,0,0,0,0,0,0,0,0,0 +DTR2.1,PR,EV,N,,0,2.5,0,0,2.5,0,0,2.5,0,0,2.5,0,0,0,0,0,0,0,0,0,0 +DTR2.1,NIC,EV,N,,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,0,0,0,0,0,0,0,0,0 +DTR2.1,RA,EV,N,,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,0,0,0,0,0,0,0,0,0 +DTR2.1,PR,CL,C,,0,57.5,0,0,57.5,0,0,57.5,0,0,57.5,0,0,0,0,0,0,0,0,0,0 +DTR2.1,NIC,CL,C,,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,0,0,0,0,0,0,0,0,0 +DTR2.1,CU,CL,C,,7.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,2.5,0,0,0,0,0,0,0,0,0 +DTR2.1,RA,CL,C,,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,0,0,0,0,0,0,0,0,0 +DTR2.2,NIC,MC,I,2020,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,-10,0,0,0,0,0,0,0,0,0 +DTR2.2,CU,MC,I,2020,5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,1.5,0,0,0,0,0,0,0,0,0 +DTR2.2,RA,MC,I,2020,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,0,0,0,0,0,0,0,0,0 +DTR2.2,NIC,BOP,N,2020,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,-2.5,0,0,0,0,0,0,0,0,0 +DTR2.2,RA,BOP,N,2020,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,-0.5,0,0,0,0,0,0,0,0,0 +DTR2.2,NIC,EV,N,2020,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,-5,0,0,0,0,0,0,0,0,0 +DTR2.2,RA,EV,N,2020,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,-0.25,0,0,0,0,0,0,0,0,0 +DTR2.2,NIC,CL,C,2020,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,-15,0,0,0,0,0,0,0,0,0 +DTR2.2,CU,CL,C,2020,7.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,3.5,2.5,0,0,0,0,0,0,0,0,0 +DTR2.2,RA,CL,C,2020,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,-1.25,0,0,0,0,0,0,0,0,0 +DT3.1,PR,MC,I,,0,-110,0,0,-110,0,0,-110,0,0,-110,0,0,0,0,0,0,0,0,0,0 +DT3.1,NIC,MC,I,,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT3.1,CU,MC,I,,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT3.1,RA,MC,I,,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT3.1,PR,BOP,N,,0,-10,0,0,-10,0,0,-10,0,0,-10,0,0,0,0,0,0,0,0,0,0 +DT3.1,ICO,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT3.1,NIC,BOP,N,,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0 +DT3.1,RA,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT3.1,PR,EV,N,,0,-5,0,0,-5,0,0,-5,0,0,-5,0,0,0,0,0,0,0,0,0,0 +DT3.1,ICO,EV,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT3.1,NIC,EV,N,,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0 +DT3.1,RA,EV,N,,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT3.1,PR,CL,C,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +DT3.1,ICO,CL,C,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +DT3.1,NIC,CL,C,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +DT3.1,CU,CL,C,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +DT3.1,RA,CL,C,,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0 +DT4.1,PR,MC,I,,0,-110,0,0,-110,0,0,-110,0,0,-110,0,0,0,0,0,0,0,0,0,0 +DT4.1,NIC,MC,I,,20,20,20,20,20,20,20,20,20,20,20,20,0,0,0,0,0,0,0,0,0 +DT4.1,CU,MC,I,,10,5,5,5,5,5,5,5,5,5,5,3,0,0,0,0,0,0,0,0,0 +DT4.1,RA,MC,I,,2,2,2,2,2,2,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0 +DT4.1,PR,BOP,N,,0,-20,0,0,-20,0,0,-20,0,0,-20,0,0,0,0,0,0,0,0,0,0 +DT4.1,ICO,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT4.1,NIC,BOP,N,,4,4,4,4,4,4,4,4,4,4,4,4,0,0,0,0,0,0,0,0,0 +DT4.1,RA,BOP,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT4.1,PR,EV,N,,0,-33,0,0,-33,0,0,-33,0,0,-33,0,0,0,0,0,0,0,0,0,0 +DT4.1,ICO,EV,N,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT4.1,NIC,EV,N,,9,9,9,9,9,9,9,9,9,9,9,9,0,0,0,0,0,0,0,0,0 +DT4.1,RA,EV,N,,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0.5,0,0,0,0,0,0,0,0,0 +DT4.1,PR,CL,C,,0,-143,0,0,-143,0,0,-143,0,0,-143,0,0,0,0,0,0,0,0,0,0 +DT4.1,ICO,CL,C,,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0 +DT4.1,NIC,CL,C,,29,29,29,29,29,29,29,29,29,29,29,29,0,0,0,0,0,0,0,0,0 +DT4.1,CU,CL,C,,15,7,7,7,7,7,7,7,7,7,7,5,0,0,0,0,0,0,0,0,0 +DT4.1,RA,CL,C,,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,2.5,0,0,0,0,0,0,0,0,0 diff --git a/Files/900.TransactionalData/Openings_CH_2020_12.csv b/Files/900.TransactionalData/Openings_CH_2020_12.csv new file mode 100644 index 00000000..b52ac64c --- /dev/null +++ b/Files/900.TransactionalData/Openings_CH_2020_12.csv @@ -0,0 +1,8 @@ +@@Main,,,, +ReportingNode,Year,Month,, +CH,2020,12,, +@@Opening,,,, +DataNode,EstimateType,AmountType,AccidentYear,Value +DT3.1,C,,,72.2 +DT3.1,AA,PR,,1.5 +DT3.1,OA,PR,,-1.5 diff --git a/Files/DimensionsAndPartitions.csv b/Files/DimensionsAndPartitions.csv new file mode 100644 index 00000000..80f592bd --- /dev/null +++ b/Files/DimensionsAndPartitions.csv @@ -0,0 +1,259 @@ +@@PvAmountType,,,,,,,,,,, +SystemName,DisplayName,Parent,Order,PeriodType,ExternalId0,ExternalId1,,,,, +PR,Premiums,,10,BeginningOfPeriod,PayablePR,ReceivablePR,,,,, +CL,Claims,,20,EndOfPeriod,,,,,,, +NIC,Non Investment Component,CL,30,EndOfPeriod,PayableNIC,ReceivableNIC,,,,, +ICO,Investment Component,CL,40,EndOfPeriod,PayableICO,ReceivableICO,,,,, +CDR,Credit Default Risk,CL,50,EndOfPeriod,,,,,,, +CE,Claim Expenses,CL,200,EndOfPeriod,,,,,,, +ALE,Allocated Loss Adjustment Expenses,CE,210,EndOfPeriod,,,,,,, +ULE,Unallocated Loss Adjustment Expenses,CE,220,EndOfPeriod,,,,,,, +AE,Attributable Expenses,,80,BeginningOfPeriod,,,,,,, +AEA,Aquisition,AE,90,BeginningOfPeriod,,,,,,, +AEM,Maintenance,AE,100,BeginningOfPeriod,,,,,,, +NE,Non Attributable Expenses,,110,BeginningOfPeriod,,,,,,, +AC,Attributable Commission,,120,BeginningOfPeriod,,,,,,, +ACA,Aquisition,AC,130,BeginningOfPeriod,,,,,,, +ACM,Maitenance,AC,140,BeginningOfPeriod,,,,,,, +,,,,,,,,,,, +@@DeferrableAmountType,,,,,,,,,,, +SystemName,DisplayName,Parent,Order,PeriodType,,,,,,, +DE,Deferrals,,10,EndOfPeriod,,,,,,, +DAE,Aquisition Expenses,DE,20,EndOfPeriod,,,,,,, +,,,,,,,,,,, +@@AocType,,,,,,,,,,, +SystemName,DisplayName,Parent,Order,,,,,,,, +BOP,Opening Balance,,10,,,,,,,, +MC,Model Correction,,20,,,,,,,, +PC,Portfolio Changes,,30,,,,,,,, +RCU,Reinsurance Coverage Update,PC,40,,,,,,,, +CF,Cash flow,,50,,,,,,,, +IA,Interest Accretion,,60,,,,,,,, +AU,Assumption Update,,70,,,,,,,, +FAU,Financial Assumption Update,,80,,,,,,,, +YCU,Yield Curve Update,FAU,90,,,,,,,, +CRU,Credit Risk Update,FAU,100,,,,,,,, +EV,Experience Variance,,110,,,,,,,, +WO,Write-Off,,120,,,,,,,, +CL,Combined Liabilities,,130,,,,,,,, +EA,Experience Adjustment,,140,,,,,,,, +AM,Amortization,,150,,,,,,,, +FX,FX Impact,,160,,,,,,,, +EOP,Closing Balance,,170,,,,,,,, +,,,,,,,,,,, +@@AocConfiguration,,,,,,,,,,, +AocType,Novelty,DataType,InputSource,FxPeriod,YcPeriod,CdrPeriod,ValuationPeriod,RcPeriod,Order,Year,Month +BOP,I,Optional,7,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,10,1900,1 +MC,I,Optional,4,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,20,1900,1 +RCU,I,Calculated,4,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,EndOfPeriod,30,1900,1 +CF,I,Calculated,4,Average,NotApplicable,BeginningOfPeriod,Delta,EndOfPeriod,40,1900,1 +IA,I,Calculated,5,Average,BeginningOfPeriod,BeginningOfPeriod,Delta,EndOfPeriod,50,1900,1 +AU,I,Optional,4,EndOfPeriod,BeginningOfPeriod,BeginningOfPeriod,EndOfPeriod,EndOfPeriod,60,1900,1 +YCU,I,CalculatedTelescopic,4,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,EndOfPeriod,70,1900,1 +CRU,I,CalculatedTelescopic,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,80,1900,1 +EV,I,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,90,1900,1 +BOP,N,Optional,4,Average,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,100,1900,1 +CF,N,Calculated,4,Average,NotApplicable,EndOfPeriod,Delta,EndOfPeriod,110,1900,1 +IA,N,Calculated,4,Average,EndOfPeriod,EndOfPeriod,Delta,EndOfPeriod,120,1900,1 +AU,N,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,130,1900,1 +EV,N,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,140,1900,1 +CF,C,Optional,2,Average,NotApplicable,NotApplicable,NotApplicable,NotApplicable,160,1900,1 +WO,C,Optional,2,Average,NotApplicable,NotApplicable,NotApplicable,NotApplicable,170,1900,1 +CL,C,Mandatory,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,180,1900,1 +EA,C,Calculated,4,EndOfPeriod,NotApplicable,NotApplicable,NotApplicable,EndOfPeriod,190,1900,1 +AM,C,Calculated,6,EndOfPeriod,NotApplicable,NotApplicable,NotApplicable,EndOfPeriod,200,1900,1 +FX,C,Calculated,0,NotApplicable,NotApplicable,NotApplicable,NotApplicable,NotApplicable,210,1900,1 +EOP,C,Calculated,6,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,220,1900,1 +,,,,,,,,,,, +@@CalculationType,,,,,,,,,,, +SystemName,DisplayName,PeriodType,Order,,,,,,,, +BE,Best Estimate,EndOfPeriod,10,,,,,,,, +RA,Risk Adjustment,EndOfPeriod,20,,,,,,,, +CU,Coverage Unit,EndOfPeriod,30,,,,,,,, +,,,,,,,,,,, +@@CreditRiskRating,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +AAA,AAA,,,,,,,,,, +AA+,AA+,,,,,,,,,, +AA,AA,,,,,,,,,, +AA-,AA-,,,,,,,,,, +A+,A+,,,,,,,,,, +A,A,,,,,,,,,, +A-,A-,,,,,,,,,, +BBB+,BBB+,,,,,,,,,, +BBB,BBB,,,,,,,,,, +BBB-,BBB-,,,,,,,,,, +BB+,BB+,,,,,,,,,, +BB,BB,,,,,,,,,, +BB-,BB-,,,,,,,,,, +B+,B+,,,,,,,,,, +B,B,,,,,,,,,, +B-,B-,,,,,,,,,, +CCC+,CCC+,,,,,,,,,, +CCC,CCC,,,,,,,,,, +CCC-,CCC-,,,,,,,,,, +CC,CC,,,,,,,,,, +C,C,,,,,,,,,, +I,I,,,,,,,,,, +,,,,,,,,,,, +@@Currency,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +USD,United States Dollar,,,,,,,,,, +CHF,Swiss Franc,,,,,,,,,, +DKK,Danish Krone,,,,,,,,,, +EUR,Euro,,,,,,,,,, +GBP,British Pound,,,,,,,,,, +HKD,Hong Kong Dollar,,,,,,,,,, +ITL,Italian Lira,,,,,,,,,, +PLN,Polish Zloty (since 01.01.95),,,,,,,,,, +SKK,Slovakian Krona,,,,,,,,,, +,,,,,,,,,,, +@@EconomicBasis,,,,,,,,,,, +SystemName,DisplayName,Order,,,,,,,,, +N,Nominal,1,,,,,,,,, +L,Locked-in,10,,,,,,,,, +C,Current,20,,,,,,,,, +,,,,,,,,,,, +@@EstimateType,,,,,,,,,,, +SystemName,DisplayName,Order,StructureType,InputSource,ExternalId0,ExternalId1,ExternalId2,,,, +BE,Best Estimate of Present Value,1,AoC,4,,,,,,, +RA,Risk Adjustment,10,AoC,4,,,,,,, +C,Contractual Service Margin,20,AoC,7,,,,,,, +L,Loss Component,30,AoC,7,,,,,,, +LR,Loss Recovery Component,40,AoC,7,,,,,,, +PL,Profit and Loss,50,None,7,,,,,,, +AA,Advance Actuals,60,AoC,3,PayablePR,ReceivableNIC,ReceivableICO,,,, +OA,Overdue Actuals,70,AoC,3,ReceivablePR,PayableNIC,PayableICO,,,, +DA,Deferrable Actuals,80,AoC,3,,,,,,, +A,Actuals,90,None,2,,,,,,, +F,Factors,100,None,4,,,,,,, +AAPA,Advance Actuals,110,None,2,,,,,,, +OAPA,Overdue Actuals,120,None,2,,,,,,, +APA,Actuals,130,None,2,,,,,,, +BEPA,Best Estimate of Present Value,140,None,4,,,,,,, +,,,,,,,,,,, +@@LiabilityType,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +LRC,Liability for Remaining Coverage,,,,,,,,,, +LIC,Liabilities for Incurred Claims,,,,,,,,,, +,,,,,,,,,,, +@@LineOfBusiness,,,,,,,,,,, +SystemName,DisplayName,Parent,,,,,,,,, +M,Multiline Life and Non-Life,,,,,,,,,, +LI,Life,M,,,,,,,,, +NL,Non-Life,M,,,,,,,,, +LIA,Liability,NL,,,,,,,,, +MAE,"Marine, Aviation & Energy",NL,,,,,,,,, +MOT,Motor,NL,,,,,,,,, +NAH,Non-Life Accident & Health,NL,,,,,,,,, +PEA,"Property, Engineering & Agriculture",NL,,,,,,,,, +ONL,Other Non-Life,NL,,,,,,,,, +ANN,Annuity,LI,,,,,,,,, +DIS,Disability,LI,,,,,,,,, +END,Endowment,LI,,,,,,,,, +HYB,Hybrid,LI,,,,,,,,, +ULI,Unit Linked,LI,,,,,,,,, +OLI,Other Life,LI,,,,,,,,, +,,,,,,,,,,, +@@Novelty,,,,,,,,,,, +SystemName,DisplayName,Order,,,,,,,,, +I,In Force,1,,,,,,,,, +N,New Business,10,,,,,,,,, +C,Combined,20,,,,,,,,, +,,,,,,,,,,, +@@OciType,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +Default,Default,,,,,,,,,, +,,,,,,,,,,, +@@Partner,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +PT1,Partner1,,,,,,,,,, +,,,,,,,,,,, +@@BsVariableType,,,,,,,,,,, +SystemName,DisplayName,Parent,Order,,,,,,,, +D,Changes in Balance,,10,,,,,,,, +,,,,,,,,,,, +@@PnlVariableType,,,,,,,,,,, +SystemName,DisplayName,Parent,Order,,,,,,,, +TCI,Total Comprehensive Income,,0,,,,,,,, +PNL,Profit and Loss,TCI,1,,,,,,,, +OCI,Other Comprehensive Income,TCI,2,,,,,,,, +ISR,Insurance Service Result,PNL,3,,,,,,,, +IR,Insurance Revenue,ISR,4,,,,,,,, +IR1,Premiums,IR,5,,,,,,,, +IR2,Exc. Investment Components,IR,6,,,,,,,, +IR3,CSM Amortization,IR,7,,,,,,,, +IR4,Acquistion Expenses Amortization,IR,8,,,,,,,, +IR5,Non-Financial LRC Changes (Exc. CSM Amortization),IR,9,,,,,,,, +IR6,Exc. Experience Adjustment on Premiums,IR,10,,,,,,,, +ISE,Insurance Service Expense,ISR,11,,,,,,,, +ISE1,Reinsurance Premiums,ISE,12,,,,,,,, +ISE2,Claims,ISE,13,,,,,,,, +ISE3,Expenses,ISE,14,,,,,,,, +ISE4,Commissions,ISE,15,,,,,,,, +ISE5,Exc. Investment Components,ISE,16,,,,,,,, +ISE6,Acquisition Expenses,ISE,17,,,,,,,, +ISE7,Reinsurance CSM Amortization,ISE,18,,,,,,,, +ISE8,LoReCo Release,ISE,19,,,,,,,, +ISE9,Loss Component Release,ISE,20,,,,,,,, +ISE10,Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo),ISE,21,,,,,,,, +ISE11,Loss Component / LoReCo Changes (Exc. Releases),ISE,22,,,,,,,, +ISE12,Non Financial LIC Changes,ISE,23,,,,,,,, +IFIE,Insurance Finance Income/Expense,PNL,24,,,,,,,, +IFIE1,Financial LRC Changes,IFIE,25,,,,,,,, +IFIE2,Financial LIC Changes,IFIE,26,,,,,,,, +OCI1,Financial LRC Changes,OCI,27,,,,,,,, +OCI2,Financial LIC Changes,OCI,28,,,,,,,, +,,,,,,,,,,, +@@Profitability,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +O,Onerous,,,,,,,,,, +P,Profitabile,,,,,,,,,, +U,Undetermined,,,,,,,,,, +,,,,,,,,,,, +@@RiskDriver,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +Default,Default,,,,,,,,,, +,,,,,,,,,,, +@@Scenario,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +BE,Best Estimate,,,,,,,,,, +,,,,,,,,,,, +@@ValuationApproach,,,,,,,,,,, +SystemName,DisplayName,,,,,,,,,, +BBA,Building Block Approach,,,,,,,,,, +,,,,,,,,,,, +@@PartitionByReportingNode,,,,,,,,,,, +ReportingNode,Id,,,,,,,,,, +CH,00000000-0000-0000-0000-000000000001,,,,,,,,,, +,,,,,,,,,,, +@@PartitionByReportingNodeAndPeriod,,,,,,,,,,, +ReportingNode,Year,Month,Id,,,,,,,, +CH,2020,12,10000000-0000-0000-0000-000000000000,,,,,,,, +CH,2021,3,20000000-0000-0000-0000-000000000000,,,,,,,, +CH,2021,9,30000000-0000-0000-0000-000000000000,,,,,,,, +CH,2021,12,35000000-0000-0000-0000-000000000000,,,,,,,, +CH,2022,3,40000000-0000-0000-0000-000000000000,,,,,,,, +,,,,,,,,,,, +@@ProjectionConfiguration,,,,,,,,,,, +SystemName,DisplayName,Shift,TimeStep,,,,,,,, +P0,End of January,0,1,,,,,,,, +P1,End of February,0,2,,,,,,,, +P2,End of March,0,3,,,,,,,, +P3,End of April,0,4,,,,,,,, +P4,End of May,0,5,,,,,,,, +P5,End of June,0,6,,,,,,,, +P6,End of July,0,7,,,,,,,, +P7,End of August,0,8,,,,,,,, +P8,End of September,0,9,,,,,,,, +P9,End of October,0,10,,,,,,,, +P10,End of November,0,11,,,,,,,, +P11,End of December,0,12,,,,,,,, +P12,End of Year+1,12,12,,,,,,,, +P13,End of Year+2,24,12,,,,,,,, +P14,End of Year+3,36,12,,,,,,,, +P15,End of Year+4,48,12,,,,,,,, +P16,Year+5 to Year+10,60,60,,,,,,,, +P17,Year+10 to Year+15,120,60,,,,,,,, +P18,Year+15 to Year+20,180,60,,,,,,,, +P19,Years Over +20,240,9999,,,,,,,, diff --git a/Images/ActualFormat.png b/Images/ActualFormat.png new file mode 100644 index 0000000000000000000000000000000000000000..e055a0a7fae2ea3eebedf69392d79299c25ab40b GIT binary patch literal 25544 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 literal 0 HcmV?d00001 diff --git a/Images/OpeningFormat.png b/Images/OpeningFormat.png new file mode 100644 index 0000000000000000000000000000000000000000..8bd3a0d7487a0a82cbdacf4dd0e68ec56e58278f GIT binary patch literal 19729 zcmeFYWn5d)(=G}WN}*6%+zM^6;uH%GEyW4$?(Pz-NDWG{;*dbm;O-W*K(XQuffknl z#UaSq^nc#>o_p{4dOqEoA0f%k&XQScX3aeFOt_kg93eh6J_ZH`p@RHd4Gat%;4Rk3 zgL}Zsc@C!)@Pg^7A@>HO>=*48@B!QQHTX3KMrF*yD|6shtYbB0Et%WfTW*b*y}iA| z!^8Rcc?1HnzrX+Y@88wc)w;U6+1c5yuCCG1(W9fIfq{X(zP|DC@y^c9i;Ih!o13ev ztCN!x6bf~Edb+fC>lo@7^URC-?XFA0HntFE4-m_%R?LATcrV=g*%92M1eQ zTWM)&(b3T>D=QNd6JNf3X>V^YDk^GeX^D%Ala-a#)6=uDu`xF{mywZia&lT+Tuewv z(9zMcwzig&lXGxz;OFND=2BT%iAJM8eE9JB^XK#P^Kak2ot>RQAP{YB?H@mWY;0_J zcz75Z8vgn7M?*uSqoZScd)wRFTT4qzQ&W?VkI&uR-N3+ri;F8NDyprm?f38BYinye zJ3HOo-D6{8>FMc4Mn)AC6)r9=xw*Lu3kw+;8JnA%p`oFfnVHqq)vm6t+1c5Cetwsi zmveJ-H8nL>R#stQVPaxpAP|UygTu$i$JyCgR8*9mo!!jL?E3mTFfdR`O3K&QS6NwE zK|#UP)HEa{1Plfb4-c!UsTC9y38jCgr@<>%+aV6cdYi0SF+p`jsrdwV-OyOfla zXV0E_dU~p>t2Z?@#mC1(q0okghTz~}X=!OiMMZyqe*po3s;a8q-d+ z@SdKY!NI}S*4AIYex;_S#>B+f+S-eZ|7 z-@iLLI?~b6F)=YcdGh4>^XFf`e#OSd&dSQd#l>Y|VR`)cF$oC?IXO840|O~3sT)rw zD=RA%6%_#i0U;qF4i3)!`}c{6h=9#w$;fE{yj*!{sAvNF|NpBGj0ykVAV3ayZu0t` z7#NSb?w**vt_6VQkpHgm_O+I;2?{Zgn4?T$H_$=L$xM)PLVC{)XT0Vhq?W%cns-^m zZ6%glt7w0p>v_1C?fwH^1}w$?7tcvExAQQ8hX4P^|8WU~-0EIPV&p%g{f4p6NE?Vj zpLeao$I&4otRw`>6zLqrJurX6HLI?GMJpdN`9cmk^2tw3V5gslC`W(VEd5gvNhWF0 zZ>JC2BiNMde-}7dM6Kz^OS~sIc09_&z&H;wvY^;{U>wRwPtUqR4IeD0W;emt-alh? zdsz+TaP*Y0R*BE$3ov#*;~(f1Uhs3h3mYl9_P^KLF$CaZfTz@eahQVbbA~nbqDkUH?!kL{8&h^SM|h6m0F5 zSy)$Oj8f+W`^q7gK^>%3$^QEZ`!cL#%m03s+&+2OiakTHC}#TSq|Og?i>qHBL1>Ox z?Lwd-tMU5LpYRXv1}PKW0!pt+cHTt?ZC~G-@VG8a(3A!9KM_32h$uUpH0Her^!oT2B?GgNyYdDfeQNzi~nHwSro^Evhk=7g3WYRgTiAnd6Y&lB}Q)d81y!`BB zsb%Q8uC_QKMB~;tuaTZb|G5bWxr%=-I6UNR2s@b*xGqg?Yl1Z9-PVNoQLM_|mp9V)iq+aW}f|bh3Zbe*`S&KY_8g z^F(pyrgBG3c%z=_HYB$;F3h3www&!<5ZDxr_}|5Mz>6aCvn*t0`*`2*56J%KBDNG_ zwJ6}sfZ~=yWjr#C9xLH&A}yvH>z$2g3NiAP#yJdt-YS9wlyT0f|BbN11R0Mp@9i{g zzl+{sq$<~+n9l~uJ2wO=AXpUsdOYnlsmdh%crA}}&Rc*%^clax0GWVs@&VGo;q2o$ z?>C7K=yJB7XfAQC7p&uOoaab((W7_;lOej{N-wZVV#vZ0BW7#&k7d~B%-`h+mHf1q zr!?O%E$Fc&ssu@3Q++6I$Wf9f8xj2QKkFF=h? !ko!SkQbywyi)w^~x(8-S(`S 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 literal 0 HcmV?d00001 diff --git a/Images/SpecificationsCSM.PNG b/Images/SpecificationsCSM.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a04d351d21e730028ab328c8311e70b0f77f19fa GIT binary patch literal 40913 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 literal 0 HcmV?d00001 diff --git a/Images/SpecificationsImportActuals.PNG b/Images/SpecificationsImportActuals.PNG new file mode 100644 index 0000000000000000000000000000000000000000..7f3d5d05a460fba884f58baaeeb41c84a4617c0b GIT binary patch literal 12211 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 z zGk``Oerpa(iPi<=r!C%E(Bbz8?*40 zeoXb7UBBkFJOmZ7Sr7aXI8pmYHhAhV-?@TD7n_EOm#&vg17*k=pqc|P4L49fAuLnJ zj;Vh4IM%R8F8Dd=3akpkoM~0Fxa1r6R}r}6LY+dm!+e3Dr7%;A?Y4=)x3HVQrv`M4 zf%qeXzRp_J3YdH2el00r&Z&calkacOWznvJDX@m}FfEHSP8A4lC+nE z5dGFOdbH}wALTKgsp1+Cvg>Y(IS^OP2?BKgziM*W(*=$t?zGIcX+fRTY4Fmk3XXR&Xt!;o&W|MH&CB0u&P zXb7(@QTJ7`-FKL*FDE<+JrS;mEjYCM3a`|U8R-C>_~}ng#C0;#)epZjDcwE6fbE*# zAa+jVuLJiSrEskmTFO-?!Uq>27J(tl*yO!qbq$V80J7)MIY+}Y)Gd!rBkfA$EfLgDvDy*dt5{PSOeV~~r2T*aW%fiou`tzM>_ ox%0PE;r~}h%K!V16_2fjnV)nRz3RMsoja$#4qUrL^XL2j3jj;*0{{R3 literal 0 HcmV?d00001 diff --git a/Images/SpecificationsImportCashflows.PNG b/Images/SpecificationsImportCashflows.PNG new file mode 100644 index 0000000000000000000000000000000000000000..bcb093c83f1aeed76336d9853ce6074735e120e8 GIT binary patch literal 38471 zcmcG$bzGC}`#(I8TR}kwsDR{DKuSWoWhznvA|)LPlG3>m>X25XL@5P{(b6?hLK=}C zFr`M<7_kx0HH_Q)^SQsz>xtj@4;ALF^E%I?kN5Guu28L8$~4E%9S4CxG%7c*-3Eb< zP=G+>PbiN9pSYS|<^%pAbGxmq1S;ranFD^Iu(_&n6$C1dKCx@@7w|jP!<&X~AkbM( z(jPLF+ZR_sptw<$Ygg}hn=bA7ZCFqHU_;h5OS;$%l_yZItvRh;?mmB=7x9+rN~`KX z$J%=1eXc8NY<{mdB9dJOY+3w@;vTM>XG&+V%-vU43&#D^3(69 zq5^gb0&$%{9R6$m(VX(f2h{%?AEr>k-^^S1T*>YYTu_ec__^Hvy5NE9z^$cz zO{3ELl)ERS=9Q~FcvSFN$BWO&dkoz4$jUXA1uJEru%H}|irKAMuI7X7w42?M!1&|% zznJ}1rsIcyyWi*hwbYI>O<|tvn2xESrI`PG-j_RrS<5~VS`5B`7+>9z{Qh{O%c~w| zFiaycD#UkXuTgWi(Z#WL{9u2JU0>hP5!1cf(aln!={s06F2;=Ol39^0VE>wWu#?)| zjB_l_UpLsgz`pa@1+R*?3XqD6a_LTydq31jkUq(Z>DM<)cI0l7BvfZsDeKN5bA>2c z-g<3&oaiYqsp(CJhRkFxq{I6#_YzFR7f>of6wIn)Q|4_8*YgmX$zn z{0sk%uLn)ToBG`2(1)k%{7`P#u8n+W7@yq1E)LgwUmG=VHYw^+27(r)_i3DbS8Lj6 zx7}y>Hm5*y49A#$xwHdp5R;;&*ey?79G1r@cY(L9(IYqOH3P)1!aj3k8^41rzZb8n z;tLwA+2Y0N%k9GLb*4=`%`njdkEUoMqS`B7IIxL#kNT?*M6-WF-ZJB~pu8>Zz4~nt z+E6j(iLT8s5shm8TDcGm8PfVU4YhIhtE%R!SB%HfX{p`LkD8*t%ZEd7=r22mv@)G~ z`N%jX^;OLjcBMV@9d*zYHuGRlUWTi4&`hP(Kb?v_~}S8DbEM>-w?|rZJs^ z)KN?!z4`J3%1#m0usG3s&@``E!K$g4jj0!!U24_WC)-Zvxn=$#+j)Uoa`-;?UKQ@n zir&RFo~+j*nE7aFd(nQkszZCcd!Mq@v0`yH0BNO?8)pbh?YaAsb6@17s-=~Q*?q^i zyRZ45cXyf)H*Qt8IT#ndqq&-+pf=KZ%?J8c(m?LTQhTI!MPbZ42g-t~nI!jvy{+yF z!qrK8He@g)J4n7ZUE$dhx}sYx>3iP$t|UDAqQ{Fzy}mqWHT=yC0%Hm^WGQz;FDyXP@Lft zZANlG+H(2Ir&!*QWgZi*o0JZ<^Wb z*+lA@u(Q@g@?Oo)T7RqIN%dwz!?Y#2?daF*Y+zez>&*|j@&E(>@yP|hEOz^D7_5hOnCmzvR_n{z`%)h6uJjBS5cA044NFH zCQB;GWh8Hn@#Ng7y4XKYd_2%5iin$@YT@Ht-!DIZh2CYk`n)-2_wD21S0{D8A~?2~ z$khfIc)B{Q2jzBP!UU)k>=rUYo;=y{>Vxfq-Uwce9$B*qo-;>;P9)COf@bb*Z7l@E?N}LRcq60Zh{Ad#hhqv3 zVe`FY60nEIbA~jtXn+*1hUTVI{OUCQY z+Zax8=HzROS!6@UrqW7Hr3<`e<3*{OJ{E@b$fph&I9QhGNIQk2*d+@53LNuv&PntF z7ShOsq4Cg@1xW}M3?_kaHW&vtS=Lh<&*sUzw-Wwz|M*F$&e)gfTYy zfL)|DRvKxk@WK-d!nk7eN(bQ;CNV$yf~>77bLlaU(^j(3opHo5iTgvyQKk zy4mkWJfMK6f34S3Drj+^>MRaoI}ADqKp~B+rpD)nQDz8-Hg(a&o`&Xr?^>$>&3+ zjfqW(GX~;bZ*vU9BBO+xA#WzXy7;PMGr60;_ITF=+Q}5Ne|5Oe*a;o{PBZ;My&5)i zo?j;G(8(y%xx~&ui@a9GH}Hi4u=+A--(;z^MtYlG`(V=}@pUPE*KvLR$R92v3Ix&U z;H-nCzoZj5sLV`N6Yrcgd$t$u<)A;`!c8Uar74>t%uFs5N+WYN;C2F`NOEX|NgjS9 z;$`Fldfp|@<$^|2?gMvO;drIuA`#Zq?AF*Jdv9be951NIA8pc(H1BvA9J|ibPGpm`b6O^dB^jLv`vq@)tZ+bup zJC0*IR(|e?cThbyLklyT#UavQCns3E1wojxa?v z4YmrK^2%B4QC+#HBV`I~bGWTSBJv|x5%%8&9au@jju-K*aDTqAS52@^6k~@drw*FQ z+0i5W*AkRuZ`E$L9Y%NF}cO(jvd>*hIdomjC-~Rs^l$ znbwdn?pyy|lmC#nD8B4%%Kw8ST-8xfpLx&@b{IYN;_Ck>81t3!x;W=ghK*6IGWSt( z7lu!Tj;wsSDMGdI#>cK+_XF7B5}+PPUcw&Z9r^$Y55~KBi!GZO+n)@OZ@3xo5_&*7 z2X{@&lVajytrtmQ5HP9JlJ?(T^|u!*cSL(GmdR&rpV;>JvJ2RRdKdVPM#OGmH1E~- zOWVjsC?HZTk2?PnJG*(hK}MROPAR*7g{gA7EnQ-nr?v)DTrQAdaoU7^lu!QbwJJetTgOu4basGnG`(E?q1F1*bCJ z;p*p1@zS8}Cgx(@mRGLhbPQ!@uHV_K;nTK>%uQ*3ZtFP+^Ll6hw@Nn%gZNho9y#`R zdFzzygK9)5;?0|^wN-A?Q(5;nUhGP@BNsajC|h@s?;Lsh60b0RYM@eZAXK*%Oc^(* zvD{)#xp7e^Ge2t{V-hNDe+O?YzUb|W#V4v?{X3La?yk3g{YN4{bN9q(9OQGIkc3Kq z<24Wek6{o=Rb8n0J+AOf&K}cw9Rthz1?X~tO)k{skMq}c<)Q~d`_Dtou}K)4doEFH zjGR}Fu5I(1-f+@zVEN?SB6X9Ko{mT>&VEqw>=i0~rwLY{-+X!L%6y)7zuR!n?ud|u ziOx^aia}RYfi2!aQ>z6P{bxOrKP#lYIX0yqHgvpmOCbeiT-z8XWKW1y3z9n5!aW8 zEalMg{NiW%kS~lF90xP866@Cww=%`DA2=p(ioI7FEZA4zDas zW!6XM+E3A4!qb{n>b5jT2@;g>Wf*SCbC?lZR5?u?aZ@*kbS}Y8&6cS${+D#QSgR~Y zb~6i==Xiz+8q9#@;@Vo?N9p3W{9+57KC4W?MDfs$t?hXG3|q8d%9Zn*%oT1}x0CkR zGc9fDp8L)hq6A&-xm|^UaznTKo(1miri31M^M2*^f_$@2qf!~L;?#S;V(k~O?BdC_ zLHq)7(`q^<Mc2w>%6S*X$K({mp^txnhmB1rj63YyvfHtc4OEQtf#t6 zm_N0*$QFe5tP$apo|m1ZRQDRicvw?uiL`q0IuTcs#d3WwpJ>vU6nJ|pVzTO)jHjc~ zVt>WF_imL=+)pL&oFjL^bxL%LQVhIoU)TRAQ2GH1I8(>9;Sq`kra*dR(<)yHsO9E;n;JjQtYCAcU08KnTCO;SGuBi( zZc9ydJxQz-uu3)<_8lhpEV6v5?=8OOZn|wfL|9#N_m{7C(Rf^TWx`W7RjtueX>v#E zF15c|dox2-37yA4_Iwrp=?Y#q1I}hd)5t(i*I&?RwY#46-oN629p&TkIMl&D5o@%U zX2xlXJ@%Ei?i>&fgeW$Hlhg{R{e*Q*-p0lnRs~pe*4biXE;tf}Et7l0QJvk*@1-a? zwe<=_@HudQ*LwyBdWDyPSem;Krxqa^keX)KB_FSJPd+7grQ&*o$*A})i|QKklXP(j zzBB*%%mcUfWGksV820F>D{QH4{k`3m&#}tfeTfhA1fjkoEK)$P110)v%LW4(7 zsl}=#=K#jCyHoqS4iKl9cxjWOl3?O#==&|`*bL`b+L~xVvsuWmUn^6`QCup@^$n)5XLHKGo|HKilo*_N+b!mYunPk4mgp%X6F+MTcb%~#xfQy7LAi(lP46EQSYSB@+G(yBM&|P)66-m zG#`VPO%3~cjz%J?#UiDe9up&mGM%5EcK>zQYLL=uH3aM%vTtujyj#6gj-KIMdgCHG zF0FqwVjY_Q(KqUoWda)$9)V0>Wuul9pq=z94RNSAmt>t3OfCS=!02$#?7n|7Rbz7ineML#o zlDGKW6^{Yi+=ZW+<_SbHC4?RB?a9~u4@feVpnIV46PL3xE%c7NQG&d#n|M2~S@kzC z2^2vj@O8WnwNOygn}FJ#9v%#m$M@;r&9g*ixaHtGh%?SHMY7=uLwQM<0b zs}0A#O4P4K4hs%pfa>kN*LK|O3I?T6x8BD0{-W7|z0veYp)XL&e9ucBL8g}ftb}+9 z84jV~KM#}L3^YVv-$u(PIo06@-1qQ<-SVgNi~>*BvJK%D+OD*qTfVr@a$OoK?{i0NCtmRCcINP}4bkiE{C z|GbC+0fLC?{{Q!V2l#lQ!hk8nVxg}ABPd5 zSULeTPe}l@J^8K#(i6R8Tby;CGpEY6ulA{j1Yx^HAq9}j+?CXwj>Rh!RWM+b(Rw@O zDTGllj;5h6c;ptbz$qJbQ$a12IZ729wJMc^xZWJ~}Zf&q)5c0mBBOW~IJLmhz$I(czugsmZ3k zIiCU{P9oAkn%~B*=G6pAR-8hBTvscOfuP5rT7lfF%Nzq^im%bfpdhJj^pU{yN03V& z=)Jwb3r-weOKzLPHr?=I`VXJ}7Z&F@VjctW-d$_4i9W?HFIz~a6Y^gNJ1IgI=GX_s z}P$o#W8B!w|6=z=NdhfCxiwEonJ$s#YA3OnOIFPZ+aA6tAT>+w@H zsrwsQRnnjq3whx|Y>@E)C94Oi!fh6bRUvRt;Scb+@2wWAWK};=Vl){!d7e+O z%i0w5-v}6;UkS&tb_V}m1n}7-P$7O`s+ji?%+hVYwd>)#_BvJLSVe&O*;Fnqg^+TB z-`eW{>BG_4Pdx+jb~UF&G{sUkWF71sNF+b}NOi?zE%Sg_2^&1<-?SoLmfTu299B_S zPwg&0s7T#6i|UubZQYX56P(Y2@2;>R6YLkJTX51ls6FRi)V=~-Ue3Q=;{B4V@AAG; z@5(+p0Op{+&=Li`oyx1Qmb@Zake}04JTD2ujObMnib^g;BBkeb(7KbAHyMK~ymyf7 zuV81t;g2~dCWwXuY4uzd&u^>zd$&P!Hfrity$@9KfzGYXl`6Nty>+lX&PPD?sfPUA z<+)8~IDSZY`r>4|FMPcCRO_a$oL*~;-%DD)ul{*;Dl_eyuV{_>ym;`Z(GOr*|Pe7PD31kW-&NnQrTxes9Ka2_V|R_=*-e!kE$5j9s% zK0eM?pra_r*LPwQIWIyc-_XrD#O3^O10?}gt@R+G;pX?|y9>B%)#G-yTUiWDUN9X+ z3hG8qp4S)y*A}m=ZS-dC`}j`V+jOf{U!8nl9Emy!MBR%yq)18z1WX}{PnLFw58Pj> zBX8W>_dHi4&0+YlnqQ@hXK;YehEiR=p?Od{Z6p6c~DmGuivI_PRVf$VQ!$_3BDqhkE;rBQcl79vE<<5xZD+fB!wKczkD87%)pa zX|ho>7stw;>WqK%@5_Gy&+-OxzOBx`anOQ164TGa*{a<>;tR|ZsxoBSHWQjx@5TpW z32kLxjF*mw7cS5Tm{b+H)`Zb&gs;f74H{+SoC{_*-WqmaJ#pY$-!FKqn>hG>CyyLR zK0x9H0^0|$;z{a;qQp0lXN%$xomy#*;riP#EMYyyN5m$)rf*gm6kT}PDS7-}0i*N?uO`m^&r@h|H=er zQW7L_@9c+E$5+lYCtx2cmz_EO(_l|fH>^?zY34D&+Mj8zCjfu53)a`H6vk(##9^a! z-8%clfGLNF=zTla7A>);a8UqE>BWw}GObz2-5DtAsTD;@|I3;Wse{H{qES%r%Ga&1 z3b`f>q-SWLLW0RR0izxiFle?u85h;x=B7_ot0LTlev)x$hD^bO>?1EtcRNst&NTF$ znz+2<|0#_R;5;YFH~w{_@E4nY&}Ta8t7;`^SJicWcGuSGgiT`oUNON{;r{El5^T4Z zJs~-EEDXT-;aeQ5O(whX!OqTr-Qw_j?qoP&ZZ6}+E$Oohz%U{+Sq90y7B1=k3Hy~# zKSd04_rH}|0x2@OyAj}oLhUuRo#kAYe{K@HYKKDMo7GkZ_=L^e?{TQY9z^Z81vhV* z9Xu%EI|f%T!#6irV;W=C<^{y7rpC-%o^pM9cTxPq3 z8#iv;1tztJaKCB&;)VRZ&AjceU9>0^(MNiXbvDo5;lixWcSC| z(1nkO+SF4jF(W%7I`r(a%)yW%u_D-)?O038?0U?~65E^j7_Nw1yA`6gx@w?mLgXYH$Kb6_Kwq070-1%`d^zI0?>V=1X0{H5On zL75A6zC;2FYTnI2KndJOK_4=qphahY$p-K+N;OH&R0H0*QrFh4eBa`F3u5iA_vU$v zFqLff!3v|e0-CF_(XY}Oy+4)lbHO7ovTu!6J~!Y#7nqAs+=l-)rD4G{W;>hMeCgRu z4!@Kl?DOnx|M$m}uomzfZ@HiKdmjzi)La`_QS4A>VUQl|F;iKh94^0q6_J)P`ij%z zi!2g8PWFfWALf5j{RxaAIZpQ7EG51vaQV}@KLS?rsYfIh|@+D#EJN;E< z0Ojp>mH+o5z`VnG#b@oxfn~jzx+$SUuxrNf%pW~MAPZx##i8zi(X8ZlRY2VDlw(R5 z^}`zVfB2(Q`1{_S;M)CfG;>V~XmQNBvq=dv`p5ot)jrayO=ihJ9s8`uU$pSQO1Tq< zQO%apG+<-K{oABMTvYA$Vr_<*X!MbT{jA|bX5yAn^zg@8jY6UH{$qN4vM82#H9OCa93kit&+&wixZOs#r)RfD19 zUu&pC72Sh!j1O&j`_Abc$kwfwy~qAS5&s8a&;)to%Jh31P~K*~KzWNL0dXhcbFlX= zga1_n{^&ux!xK=1;*H*_1HUBt!!%+7z6(MRxS zz4JSEc@ItL_1^bJaZw#`gT)ZdF*&|Lc)#EG3jsFBvBFIKiXS-H@0>*b+uAHBb6uw5 z7{1zj`HR*0H@%$eNx&!&^Mc?@+oWJCy}F|L(h<2E$9FK6moo1~_B+fnzJ(}`U1B(R z?dqtFYinXlPbXntzYp+fh(sPuU;7Dl{qHuv08{n7Oy5X8T4&HWPz1D%Xk zfU6VGIP}OVkkCbvntq}uM`xqncgy>2N-$))Qj>wGX#i2mxj-cjp)1gs3pUw{?FyM` zjptI*APB@rYTbM%5Kf197g;r@Dd)F&5QzFP?q&Tz!TzUDTMFn7F&b*XhJIi)99^I> zD}Aa;X%GlXDpaO&ejP({r4~o}_|e}VQ(x{Hbd=lU5G7;XZ$7wS6xDO%_zfyP{hyJU zx)&@Ppsgxs90^vkUF^k4A%Ampa<}u@6sd8`+hI`1I)1pz?^e>1;3jpfM#u{!5FOlsqM_4I8Z)- z1KAl={cd~#(sj0&1?3Hz-$!srf>eGBKB3j!mVZLY_RT+*9l8bu?G*#;)BEJXkNuv1bol4BK8$J^F3f2@miK* zm)G-bJJ?lVv!}lYvt1t1^RrL*y3bvh+POA`!ke)#KpiJ!Ine=x2Pk*rDr>jfM)DQ>slFfZ^yHa+^}2cFk9tggd&nJU&_7Z<^D z8QNV-9;06!wP(nzzAve|KABYf+-G&~GiX~}L?4b)xM5~`8j;qq(4Dohk)=~jWY2K_ z6p+{pJFr*vQ+U~1ucqTWHxp|LvqSctirz0=f+ety75WYy98*T;)Da#~{h@USx$jjB z3MwkwS|7k4VhsiXcC;>4tqE<Fr z3IGixg|mjt6!M)Z*Tk*rQ#+WBQ|=%^A|SoXO?;H%3<0Aj0K^P87M)d!Q&64TH@i8v zBQWVTRkjlqmR&zGc7RhRY6l2>_-$`G;uP_VH;z1PDp4t%NR^}4Up^K zCnf`=V_ZzdEczQwvIk929kgIdvO=Ma4p#Q!L5~$rJ>T++DdRWJ^X=fzi9>Mbqw3>5 z2ItMBxdNzf*9MylZ&t_&oCY#s3Q8!`=l}_5FiUyzE5*F>-WcIPek9=0Z}<2V3wT{$ zY%L8Fb;Gt0l!FHj41X*Kgeg?*1eSGQ==vp$I?zz42S9PDi31bSrN93$g zHP=_%&A$qlA4ovuniFe_d#w1(E>Sla$!@d*=HhjGB%rA_&7!YR-agIcT<~uneP>6> zFKiS)n|n*WAZ~TXE1)bNc|2bBRbyAOOf(;EGAG*hrsc;(H4fNEp5fhz?U+=X*J{hG z4y+-VXh?Q+GJE;0lu_T0MtN40@tl)VFUg9$`qe7F+?2l>zj4ctg}c7S^!8T(w%CkC z3r-V?tk#$EZY>`VhS`p&UnjBIeJ8b4y$;^Kt=MvJIASz8ii?hps^O9~`V|Ot#3-t) z1w!WU2vg){S&#I<<938gF%|DKzP#@MXV<4j16*lLkLPQ*%f->SP~o+sN1$4)G76{P zSDtl|yDn-M6J4=Xv9InDDG_v;CP>p;U}tM3u*JyvP78NGS3vZhG=igzdkkQ#FCpzI zJ3zw*VXrU)2P5S>Bge}50^o|kw9oBE;PTZqP1;*N!*TPk*MzZs{%iHnvU*LF0TbV9HtELiLF4v_>B`x*<`Pt%V zGh@y0LNf)V)xreLBfQm8Ue~*xOvok9ig=2I7*l*cOgx_5d6>n)3=rRp@gUe+=i(J> zT!mG|WGQ?}_1bjzshfb+DxY-boK}eM)v@V5A$?=g&cD;@I#;!8JLD&x9^5qBB*@hY zV?tK0Y|I0x~CA}F1<+MaV-`jHm=#>S%{oO!-!~gI= zL38eTfDC3fRC(OXosCcAOPtZkA7EKxE~Kc@!SD@IT6ivu%53zk@ESc3j>dzZ0Z%W0ha5js8ZTWx9os!URnde!9N6rF|anNV#jn z?mC&tcI(tumf7I!UL%nVB7`l{~tW z=9ur{BsY1Nin_tB1RZ#>4$T@6^1YDu1Yw2k01HwQGge-(ug7ySG=awL5PtY#>hGakWakLuKKl>SIq zqe3;~apm>YuL>VSvTrT>7a24&B2(s-{iP6T)$VZ|aOP(ToMZ7*&0g&qo(mBf@~}7T z)AT!+0U$JT(%GU-rRDW2o!Yx}*zZ;lff~DYaR3P&t;6pUJFqj%N3H_QemjxkIOH## zmH^Xw2cMm(yO-8VV5%QVF+X;<4(!f?>P<$AUdz+H?EL-&hs*G;{lr?~RjPWPiD+HN zd_n4~9D*gOy+p1?$Qd4Hr``(8PU|;}(JH<#)=jzXA zWdppay|aPxpJlFz7AB#Bgwo@X$9|eXH6-wU0~iRo5^gE?ZqPsjZ{!2idzk|#)o$2> zdSM|FYwYMBfEWmv=LdQK!}BzNCRvZVkcmDZ?ldcs$beyg019NHR0z-jz{m_r0_KcU zn2e37m$=BFH#-kf&ivUs+tN{!%HiZ9G5%}Gz+WCI{lQmE(2A8_J*@{Ju1*j(U&NN}_IRhr2^=RiFd z8OaTfQ8yd~Frl=Wd`S|FD0c<4W;EvB^r7Iis8XcStKXdnP^2YMKtT(EkRe5Y6f3(e zXhd8hBfb+p5bL#HtIG%Ax-)+^;(s6H4D{iaLLPoe&I14yX9cw-?o-wWOn=$Y`+I%{ z@JfNlw2FYLm)BfWg!E0~4!q54&WJCVA zR^y;B*3{3pzL&nw9Q4CA+Ff_^d1+BY&{d-K|E>7~Ez~Nr2u^ z6zo}BAhVGBsk~tu%H`M2qTvP9Lo4*6>s%D65Cirf6Vsj$NKfLs3Z_Riz+9DXYh5Kn zlOLA6ox#4fur7>9QvhfKKlRg5e{VK-=LT-JYCMHFcmsoItf0>SY2(0FzJL>>fK{#l z2wz{J<~&^M6P;RXk>6LCj3YANLJ&}dY*?|SeX;0u|J_VR%^I)47BrjR@ZATI{yvME zMBN!IXK8-%BC%OxUVr`G+Mw#Bf9=cCa=W(xM^Pbx8fCW5AFiWwC=+1{f&G&~MJU`2 zdE-2vbs36<^v3DM_uV&GZx-)AQrJGySK@zLoUNEDJHaVLnO&ET7yW*&^+?UJgDBV5B5lo`IdMz;hn0N&$%XwfdL;>nK zexGvuK1Bo#z+&w2v5WzDpK&jNBE&(J0(ejgc!EjJw6TXKh>hsR5yemuS&iT*cLv5s zN9};;J1Qn-2ht%rxPf<}c`P9JPEylcw>2(4Ta74#AHMMf%cyXkUM+4!NBQUGf!4oH`-M*+`T^-Ow4@ah<)m&1WuDP~7u%5iFULVudB2*pGf>Q%3s zS&}m~b*CB*Nd`QSOtAPw-O$Gv1JOEf-u(hPt^Zu_cA03BZ)Va(@hw=G*u`Hb5)W?b+*@ZfYBJJ4<){S~Oc zfS+>9C-s^rNMUA~NKXfn0pP?2kYDfaGFMaU=5({un zGN94^64L zqH2Y6Byw#K1OvTq#%C)wPiEa$p`mdD!}s z+C*nLm0e{Xxz!U!T;JcsM%9XAv}u39jPr$m9p3#pQ*iN{Mng?iY+)eb-Q{6dwYb~8oOx{->W8(wK1<_6bJX-2yk4f*_eg**L+tP zwc9#%n=r2DhyO|k_zj?;Gm=? z4qCr-lg|!DovAT7nET=wr?76XypRJwc6i7mS17VxySDLHJ&#pvu~u$PESJ+W3u{g4 zm&j3o!U(V!O)j<2__kfi5j_(HFFEnN4rETo8R#m2-BXi|0FSW)5Dg%!BO(-QII{TJ zZR-{~f9SggO!=E@vIF?gn6k2|FWg?@Df?S!UFsm`EJATtVj*~__`$xf!&+2vh4)L# zQJ8FpY}3%Wa`|`0i;Mok*P-AFWI+}ivg6`Jv5Gi1rV!&iNf7DB53y*hNuJ?mwQ;)j z@s-vKh4_1<h^g~V7${$AtG^W(af!bvuvR^ z4)V-WWWkF4g>zE}J1Y8lTN&%5U3N4hva-vQ&469LxLm4HO4qR4K-qDxvcAB=@gmeQ zucJBIt*cYHc&){$c-^fB&W`SN(Ir)Bhp5p>z}Y!~L6Gwebx-~r5r2_)Er|IR5lwX= znm9uxJ=M}XGcP_?3ivCWcapfSkKkb7WB=4kU^;uDe{ixoJ6SW>ZGiy`95~M=C+hpc zxhioN2ik5GR_G#M`B!1$<`;!GFQ=d8ecxCYYYPN4 zR~Msg__a}|umb9WyZ zwfM@5_5f<)Qu}X*QbWWDrY;V7QZ2oI+^G;XMJMpR-AyI=>E29p=ut(Y8`VrTbt{-L zUW>SWm%ZGXHaAOJepx;x(~Yx0fAlhE7jHXjY8z)jL{)Vad~)b~m&~C4MX!|RHPsf~ zzkp-_@EPrXxF{oedZTh^q(x|yrYFDQX0+xiBa$ z5xLOVTzHJ1%pu8@xI?*lHBvoooqn@y{W=sazBJVj|9RQ6Cr`V zK**&8o?B?;{#<-Y%}z}vFUEX9c`r9#GxmC(6;%c2_o|H1HuaJ6eHx&C+TM)MZlN%l zYA)Z|u_`Y&P2oi-CSHwE6$a**LyCuh=dm9l)r2v)I7Y4QyEjlj0^kmSXZ}h8TFp+a zK_Wm=efpO#ALbEn8BhDD*qVN-@jor^k8uC{>oknyeTA+IB{!?&d)(t>lzW~YqM|^6 z`jkXs;PnI^;=P9f3;0!B`Ip0zXneMA|HuDx_Q~Ws^wQ5jz(^ffhhg0fB5u2@4>ll7T>q;XtM&O$&gJ z?*d&7iGK?G*mItdoJ3|N2e`0j8^9paQ~>z6l#~tu-YW28+I1iulLi#P&jO@W1yEFh zAOAluE&7>MAOVz8A9WFm&26A8PFXqzVx&9V0-|bj#NOrxhw3!2!6Szo6skTB?hGsd zvq(NPH$4I}m;7-Aj^FbG(&0{QA96zjAwTv;RipZ$pA5t(a=2)Gku%E#Y1Y6*O5Y!y zjeUhaX*hTVycL$8qluE}86?g-7+*Y!#zzri+)OYZsg|%y#ur&zweJV=jC9+n57C zXQVx$hkbXm*mrPoRG7JaGe==*(A$H!jwAM^rn=?HE)OP-lvjsO5e0uxPk-#KN2~PG zaC{ePw%Z18ebSYvp;`{3OGR3hTr>*xaY9XX-gH8>62fo*e-O6VLfFKseFQrIl;~f( zT}OOqixooG%=xyAw^_#UA6c!(5c;jAt4Dy6<|Uz`(9n*p_|=0q5Vi}l4)G%^04TZ#o}aqF)kLep*e4%&3ip~N@Rx8r~-J2Dbq3J=4n z$$;4KYx{j!kX5T~dS18>$b4g`;AP4Ca3 z<0UAxt1B?|&s(@hrJB69-8?R)rm3lpF5!-IF&$y9urvDt&h99nYji&I5gbVJz`CLW zz#=-WZXy&z-FJDvTt_H+z*1wD!jE!ro6u@0IZ^pL=w}wbh7=(w#8H(PU{-4K^JJi> z)D7UN%~$>(^QR2&?GK#iyJF}A)ZsD0MW@cG>6wzQde&i`y)p_1hEKqd|IjQ!V5YZ_ zXL)r_#I>z`qcLfOVjJg-E`b*ye00A8#PLgRpr;Z2;Mhay7J99C7)3KtjlHqfr!4KB z2VOv9P1#q`5r$%=f`Zt7iV$?(N(^}Q0lMmW*#f_-pyERTXvmL3l`Q4;7#?e{y4S%Sas0K%fFZzS?J-`8f08WY)upyj3?ptD`gJmi10CJ(>z?p11_La)2l17>L5|_V zOu^EjwKM6}rp;W8;NW+%#0Q{j{Q-ksDMf9~xGKq*p%XO_Ph)BpxO)PiAyL%^#r>StA{5gZ3z(FlQG zF~Ff3qNQY05i~`onA$fV@S;slulw|i0B6dLfXmiw(kh#VcUaTCxM^YqkhINfrmR&=0b@{Sw|V_h7Mdv-Q`ul)XVMrbR${_AiIw(!k1 z+)}p8k*K=R!@wB4_T$+Mz=2*lQ1V-dxrSEvui^QH%dY8oSWaZ`$$uGuBduUbw6yUT z=K~H5Y*{d<6*QrwD!cQ|H4_h*S^Pz!xNq$xvNG}gZPz=Y$urC?z2&LVGtAg*>3zwG z*N!X~n(t&s7Sb2XTgqIBvS{2v4~2zbHustno9p`rHfhLy>SEf4AIMC@*3h)az1&V! z*W|cHKgLL?t-3bWmo3p7lx-35Lv+A_|o#T5R49;qh>DF=K9BbVarZ1JY{UJ|;Yi)vb{o`TzzSRkIg64JecJGz|5YAsI+K zNkfbx(^~7EybDlk1JCr4l~HuHa~I1)PM?E%L?rg)7U1c%UltaTe)pbwVemvn$shktzMG&Ta1UXigY51FWmEQRBt1# z#Wv5p7&5+Xf6tD2%V&b+EN4hKU2ku_LBS3`FjjPa!17jg(Y1xGr9#rjRXCKYoO`f^ zce@JBBAaQo32@@yRO%bPxI9b&O%rx+o4sq{TjC8p)zi zzoTJS=4cSSMBj5=B|oDDF=B){zggGt*ynAoj=E+B9WZp|Noi9|At79N_65LI zRM=cbNrmsojPFD(?r-f46tWp*`LWl?8C{N}ezK%bXXb@cM=WiH*2hf)G5_ce$sFT{ zuR)9Wzn3*?Ha33MdZ~FCrj*;L0o$gy741fqTo$^$e^H^nd~c{er8L3-L#JzH=r1e% zZYULS#rji`NEm$Ac+nCwvO+w)Ch33PDa;L*jWSS}z_QVMW4gLKXK1mL3$~_kvwr++ z7_dcO?AV0g{`G+U^1b_v6EfSIUG;TFW+JBtyqFPbeKu!+(AT+c;|;jU&^4&g#n@RM zmnZ!^OsDwR&y9m4;(!(Q%U^F_Mq##c6cn%qRb!Vg(tlf+0*?0yOv2C))54Mk)j}fu zCx|&!`NZ7w;V}KP2oS_dZZI{{p?9*P>@t8g9T$|&hwQu6Fi+mJfa+J+XQ(DtAv|GPc{frn2+zc~}N zT?<7xH}z(m8G0SB>N&Nd4*sv+zC0ev_I+EWCrTwMvZfl!8i^948j_{7ShGwaOAH~q zG1Y^Tn6ic#vS!UTV{4|eOp+x#gDLwq_OZ+u-fO6y=lQ2yoX2sTH6n1s0>CL@77&>65DUx8E3&LNDiFt`m$l2JF5jKad<4~fA%TN-pJa98 zI1hq%U_bZsbn7|><8I1mH<0%Bmp)-#3*65h?LUAb9|jdXC#hS< zer@ky?1u~N0?$u3&>Pv7)p}6jF9=AYghw#Cmn$ONDNC)7e_MSeTz2MGt61P|zKyB2 zp9T`Tdc7$pq1|xa$M*z$spq??%WY%*=NdIJB0!?CG!Cmmh<%x$HaKapdfUmh)7 zFU|py$M<{vhSF^)t>%m(z%lzNaY3 z4;A!c5<=3M#J=AV`?uEJA7PEXFQL9es@i1lL_t$}{?z`!x zrRHg~QYlKGPh~}liTuAcOw>%TL4Jxi%WMj5sP;GW{O%_=OnbzFB;mPyfe~2OwBYgnX&qo%Gfg zXankVP_zU6#3iz#%poRUG~ElxUcg*H0sb?@Y1DJ5e>hd?TACIIMA$XLP}k~eqkIXVOz?oeVFzI@ z;lXIzw)rq>SH2}t_S9iYPpK>3#!X(ezHl4?`#H7y8DakWDy#LbSOpDS2V#NcO^8*{9&|n zyRl6@aG^L-emvA?aq=xgI%#;2blHpk?fObkSLx2~(1Zucor$cg1RGy$E>%ApxWi)(hiQFA}wdnBvG;KFp`TRhju z=Qqf@46aIPjz1G)zRh%?YksY60JQ}@v2 z-U3W)fa}pi<~}@1;ynKHr{?cqaW^#Oc{ujPZ2=&#giRu>f z%R~n@WqoeO4HaRrYJ+_4%q)ap;b6xFqtd}}uHt!wuW(onre=YvY~VQYRHRc9OmbA= zwZ>vExcXkYPd;Hg!)%%2<~6udZatp^(pnbpJ8Xt*{t!j|8MjE!@gP#N8Zk_WoUT$E zS0trJ<}y-Qtc`HWLl7FxC0pCMRD3466)^(zQcY-3c9_5Z6)VFFuK9y*`;`8uR-a!w zp72al*&0=WM`cMES8xy-qq7)q&Kg{?;;FvwigTt27ze7#9E(e)4z2SjnV+-quWl70 zF0)e_>otbfl%J8H*7uyyQZ?>EKAAQ9cIyITA=Glm^p!?I?|Z;Cs!ZvAe~_5a5-ydP zN(j;SocewfJODqIZS+|lhVo{KG=&$}im7&wV5+1_pVdYHTc|B9mJ_-RThcXt?KEH1 zJ$vec5p~i?k4&3KBl$PhI1rfX77BMFRh^wi7pV@r zUBFYBRde07*h}hD9-=C=zR|=DX`1~$UiG>-8o?2{l21K@#WC8W_pO^h&vaI+WZrfs z6cv+Fsp@+d44hdBpPc@Ls?J!G)-xDddABn*eb@v55CG2T%mWacNx@zA7tsl=`f#d0 z#4IpOS37Lg^2fvqG1F4hek}iKZ8pSOe2J-xx4nwR?xWlk_9KAWS7*1qKwJGj60dkLGTLH4 zT74qD`03`WY6ZCB18qQK)Jcw8r|+YcU-O!BvIMdSmXn?e9|5IJQdBumWj4;&2NKs_ zqk1sYewjJ8dt>=cyPiSnfqH}!?vQ!xjvH53=5ap-qWI{t!<4%KRKYv@OqCH^2;}XR z9vh@BLTf&M5t1odP}iV-RLF$A{)Fg(i?Z()Y2^O2vbAMuXM^T?XR@q|bI@$F`}3S6 z?}Mu66yn0u?+JXHVJa+4?k~PyT>vgd3mzGSEsS{Y1&c_})N%Az7JF>Fe zH5<3Ol0q$TIhW@j*=2-xf=|)0#f=aZ{eh=}>2GT$6AndSrxCV4bbdlt4iX~eGy`7nT z$8+as%@;0fpO4aD8VI@2ti*xYd|tlag9{lE)HPEiXQH8}zGEy8)}rvY4=i_IXW>YQx_nn?Kb6O8A0ed<%{_~#r%pgf;Q=PUmZ+_STEf3ztQ4?(5MJon{ zz$)yo9T%`bWdGeE($_=t=r-&N-}B!4wt2Gv35$q3^w`bm09Pz#(=+V%0dUfy8>KFgn#Fp~M;}HRK8NSf)^8BNn-RMo;t8(;pV#S*&uF-B^?phaSgamM0bhOxEr* z{~Vl8;{WD!ve?|34frnl3^$#VjD_Zn%vK8Qpig{!P`wYU@p)!f;@9z=SU44IgC?G(&$ zVYRH;bI)n@jU~Moc>c9ly-fXvr4ooPPz|`ujR>vt0WhQ08`v9tXx9F`HZ>}V)iH89 z0$pnwdCcKDN904=z}T+(O0i1sihB+dH^4(eGcEF%V0a~3N<$WdjQ~cJzAj#cZ7k8_*}WnFYN1s;~J;OSV;3{H1(^ zd{k&T;*H2?SZ0tz%gCEh+$aLd_y zN?O67_N3uP9AV2=6@bI2v~YI%(Z#H9ZSI?CypK%_QjUH8;>%^F2AFO%*&A>uwBufDikl4Yjj=k|5H zqhCB5RU5}!Or;ET80Wy__J*mp>1O<-H` zX`akvxvVTDKgr~c`}l9-;9O=DoZ5X#kmY!-VAc3;(1<<&ooE5?_K?M^3DW0!L!w=+{p&yLJFfW%Zwr4n5LyLY<*QPFTIa`O z(!0A#f-_=2Dl zuvKk@^c4e`R3{bR+KLo@`GlIb<%xHz#(P*2x2HL>WhZD*w1dK?N$;$(A|^FUp_Y$L zAnbM3*9J0Wgtr}4gkx-pXFGjE)bsykKuIe#1GC^|ii7eXcCUiUuXu+q<;(-$Qcs#? zn;#*{FT`Ti0Tbdx(Ieu3J#=OJM&jnt z5iGBV6K#gpUKz-;Ud%68J4SwzQ(oONKHRRqv5F^IH8xT@9>*0Ur6rQE7MeovFz=Qe zUpl4ecRb!>o@hOAnn@4wzQYY1T)FNBy@0&>B$m97GGF^vOw_|b7xYHr5f&mY&P%e_NF{&xCE)YUV1dQen^%{>#)?P? zjyuoXqS%4FQxWQZmzmG%{!9`L2{>}HUn_>jSWJ-E5Kw_QxN|@39s9p-%wilLN#Dws z49OmTwEDWWkCR!N(<^fSrhMNEQE~J@(Ahd@OvjCc-F;gk$?r5Lgv!Pyb7C5>-nEa zUS-n1CP+*f)lAzqyN&_F^x&y8V#uj9bc(Ji-KqJ|IX}OH=X!T85IfeqX+62!~k^Zx=um{&?uvdwpK4!)ssd?OY5RgAjW5y&EC zAnlmpHDrMf-ALhj8e)d9frh~8nI&Ha}_N=h~T zm*x5OLCeq|>|(9DhpxIW*8B5LPdqkt$g0W@;{C$Ws`BK4&~#U!4ZfH!i+5{%aYM;JW_4#Y@O*75 z7Zd{6H_3C(@`YBJu}|qHms8xr^%{@B66ZwgFTw-Q4~)Og);`g$^hZ1zE40?rY6P;m z_{xs(BB@pV=b8C=-qOr>iYdAS2tN!Qz7|!W)?SO&Es#7kcQ=e`UmKMt(V9-FqyFH& zL4Gn`b*x^@`(>u)D|B*=NvqACxbh^{)1qw??>=+NhxGH0m_tIdUIz;aChHcZijSn{ z$sAJp>uv&vU z01b{rIk;Io_w_N^^@C*lx-(ZxU?L%S-#K>>co(B>8%nE8kt?UK!!y$hI`e2xjlQbj zbtm$~|GBssfcWxF%l057Kd{?qE`zmJEDU;KF6eC&R9o%}mW<;bS8Ok~(wTqGZmJx` zr5}D$n0O}ouI!B)8Qu_i58+d7#Ry8_z_pk~M&g)lgH8o66)4aEueHsHFx+xhsqOlu+6vG8b8J?e=NGXa|U?}rT_Myx9Bu$l;kC2 zms=M#U$k9+JUBrIV@vyl3$C)N7bBdF@U+W~N_-3Og-dPVP|&D{4@iF+j)KuG=EepF z!@n3AT9RgI#7|l>!7=_m7ttSOYDfbUZmA22px6 z)|<;I+6XD<0yzqdcM1@u#{iFzoen`%=XNLU|Y{$`{E}f zj*t5{9!l}Ei*jFQ)Q(!J!3MaI@TvL>g0MuZKH3bmf_(-Zpvd~E5hl0Vqc03=QvS!& z2FNG>cN^4yytDnsAG{fSXVoC%?mzB3AUNFz6W#}~xgbkn*#&sDcvnYJyE;M}E@rY7 zc2e-y#(T#h@I3jP6IqpffUmJo>!LwGrlyf_twT^|P#OTgWfG+_tMbvjUpPIv6HDCO zge=+8esdjwsnqeedN`z$DuN~x1f%87kpM`W`WL_aN*gTNqqHU-H2g+__1TqhFl~NW z(@XNKYreCxGqT0=9Sw><8dXu|U8NZa9|u5MZTU_9sIg-6y?B7z2oeW9#1pk&-9@NCmk>_|r7JJM!Gq}NNkrr$ct&Xc;^Zp)yeYdSQ)t z(=A}UN-kMT;4IJoA-egG_ke%>V3IxT;Xw%=-0`+Q<^D}X1tPeNLnn-3!I8mnhPk_y z%u7p>er)RcH(5CUF9fImI#B%o$g29ky(plAP4)Ox{)_$}ly^o0wk4ey^?*|I3WnGa zZ*IQ^F+bqi4L(2B@Jbbs>;Q4(e~e`JAM^M424{X$j#U7UOwmJI2{{Zv!`liTdX}b> z(Qv<&uWV`vG9LLC4Ug}V;TD&`?|{u0)3KrP-Vpyx7tTQ*WXy#fnlP#RyjrqIHlSSZb>v$U`I>>>zv`~qDgE&0wg!|vU7d2_uDG0Zq`|aP#e_yn18KUk{oM4YI&@oj zD=Iq~yWanvpgcibdJCe};Q^v_8^MaGNH!1?YrDx$!mco;4hf&jHIG=NdugsO+xSg& zt`U~FRlRzkWb83&OkA*Gypbl<0JA!|Qq3@gqv}YDfW44WGeE~Rd?Y34j+o;VRygs}n(AAtb_DoUpHnO08J# z4V{QK0$DiKUq9{BIA|EA4^K-96`669`UbaV>z}>%)rcrI>I}cicS@0`r7XYMkBqUR z>nTpvfuggu^;Sm|l+loiP9v|@X*6$FRE^8^89iU-Go7^1x+^cu(A>u|?Y#+lx{vNs z=4TIvH8pKoCT7<2=uE@D$upa2lKhAo?J^wp$xK#&T1|3ELt7K)#dJ7Y%pymw$nNYqhjbSL^I3 zWW9yUALMeGI2xUzy`~_b{Yjg>P)|G>a0uGXiTk--RCOuyq9>v&@+{c09ome>@_X^A z#P)`1T!A{c_R#kqip|0l&m-{+>U7#PerCL)=xl2`t(})I3ph|R_xHy?9*Wqa0n?<9 z#fZy3$j>+ZoM`OgR8iR7EK6ZgY{9D+^jR&<5-Ydtcwtiai9=YAp;S{Be&W&>>e!Gf zZ#>EAj}LvwrCP74!UN-#i$r8;sr)_(6|5JHcbQ>;1(KH zGBH!r@v3{dj-CM7{+nq;59!>*H{O`9XI2Kup{h$=&&mQ5gTNYmnKYVQ%q>C10JLz* zhc@(J9IpIojn+2}hy)szb~+*NH^6IVU~F5*`5Jg56#9QE1ikTak-J~2_$+=ME(HZ+ zuiAS65q+ojO{{h8&uqMMwC$}M*=n5xnByNJqJ#M9G>!`ucWWg=r-$gzU1w{3r0o{1 zKcfOa#l2nb+DT5AiFR?dJ7S>V0h|r;pV6c3z65^niZ<6KxUBtY*O3qnEYg!?QFrV1 zD|^gP!L@$9zDc`bw+;V@FhT>q;q?{&!ei@Gp3>hI*x#uv;y8!6T(X>&Dl}HCNMO+| zOGz+uZPOqq)iGD%S-+pKZB;CMqE~wDVZpM=C-$j$5 z7K4|fJ>810A;%;wl4GcLfFA> z*Ouuvxf=CTm?)lk0ghHnQTMRks#7Qf2J?lZ5aX>!*Rv+RSkGc?D@yPQva+u3C zgPmmYaP7|w+$_*-8-AJy*QXRJ_&H!sMt`{i%r7u;LPUiy#S5jtZhk3$W(behQwnvn zOeGrRD##tgPC2hLy)%1OJGI9=q`it><{dEOslOm>+y445#=#YE(GjGvoEec*&Govt zp#{cAk=#)qV(+Tp`bgx=8kX0`=B!q2@}fzBF-UzZ_{axjAcJe9M=s5;-0xnTvm{oL zxq8lE^*T6>7-2%i)$FTn)p(98sEpG(uR9BsS-ugHN;m>Kjnu(@u-NFDELhYt(syC2*(a>%?dwtNc7YRd?>m!PeMuw zYS(78;ufZ7NYSEe16$6L*_S*m8hNJEc!t9A=mB&(zcA7nug_E|0G|BqGoYsD&lM!9 z3cE(+lq@F;!yaCn2OnE*y6e+S(d8H!f0%UE&e82B>m^jIui(Z-x5@aaG}}tf&U4h@ zYXvz559@BUYQFGCpFiwW>XIkm%`lQS<^rO%V2OQk*CU z9OT3SBWAg0w{CjYv@v7HXZOiYSs%X>wFy}U>aHyUKs(N4XS8r0KWqBHB&hA%IwBEo z`KB}|@ciJ^*ivWgD+`N_Z~nCCwNhemn$^!Si*Fm~{`U+>>-%tw9}5eQ3`b0;`6G$p zy3mzQM5sA^DQ_w6kJz|jpkoIsb`cZ!A>nx>>m>)cw4K8_Y zx@Fzn?c%dqf=tVRCr7DAS@a_j+r1m(vS7n|kKh-0$_>`HoV=4KBu*2#9&te6>!Y9)$!MH+L-90YbR z2nM!zmUu08y)Ki~H*zGqFt;A#RLq(pt4Ja3pYtY1Nz?;ekIKJrt=D>X#c=`tDS>!lO zrFpQ65@Vrdq_`dSd$7DnZw5b)Mp9?Od(M&?K=%F4$$aF(m?E0&^}fvRrw22)A)T|z0w5vMd3g%sW2uHRs& z$2J2a%sqLifJFbCk7f4*SXeH71Wo>c1X8S*X^262udE;L&3{wQ@?EINJFNS}4IpU% zcd%2Si|lZ$i&OehmgZ{7BY6_wIiSQny-#JmN!(HeK&cy5MvCCKZAB!`9z18(tkN8q> z7oIL5P-j$--vPsDrm07ssPy}Imw|ESf!%dU)2C-TPm#0|AwdXQI!~9@qq+ncf z>wezH^)KW3uUoTCnt78Hy57_A6?U-is@HlVM4D!+pa+>I$%Tr_@wxaB`h3ohq*A2g z$kH&=V{;>sWKQ8cDe8qp44NJg=C0kJeBtC9k$2!rIPuChM_3Iv@64;`ajQ?ui}~`0YLAx=ANWpKnnC_h~n>lUW$&xSRo*7hQ?D` z0gGLTtEqSwa1?P0mpSN`F@n4`J$P)d#+rZ^>t}EVJe96P_7OP~p{es1zd&l&dOhfC zC>iY<1_HJgzuYqogh}JE*_a*yUlhO}=jp44iNk>BKgYDvE}8wtJhOTG^taY)x@Ixk zmIGe)NrAxIY+CGP>6s$OsY7+z$g#|TFL6L&dA8Y0WGKwJ-0U*BfqO}FO$b$PrZHVb z!mSKO@Y}oufgEQ4l}jgPql18fd1k)O%~P!XON2Qi+SPg!*KRc&J91fqnzx7TS4aSK zPHYskFss31#~?q@e6)z7dLBr)5L&Z;5*0Mwf+PgI-dNY^9+H%T*1G{{tym{MG|Ur0 zS2M?Po?vfeTzq#3-6L>}DmH(o=3@$_=ZQZfGUQAGA@h5kHj{L_k{{jd1fR3@ri3Vt zKp079ZKY#delc?^?;Hn`+6%a2YB$a$hl+3p)8tnDP6>PW?BCehfogZ&$y*dTZUUTH zH$J*~et~@Oi8RMYJzzon);1H^qW%aKYd+wizpnp1?OW%B-^9LOtN82q0^DKO9dKR3 z9M9e~GarL;GaEtq;k?)Dx4jorJBA@yk2Wdy8)@doxdg0EH!~A(w4jhq9;!xZ`SNKs z=06$3Os!=1HfGrKmVayh(uXV%iuQ&}(;8go!xl@Hu_L$|?*|Ijz{q8Tfn3SV`I%D! zZUQbdGyG#{cjcFBd3h*BZg=N9KcBp8m=EJ}K~X-1~s1TW*CtiWWW6i@}oT z9FD@ZGokp3whn^w^dn>PFS_^dasSS%=i|xR1iz1!g;r}xHt?9~x1rsp_vZ`8I;1^q z+oNd?AQIY)34hMx2*-sO;*v1byKxYKs4MIq!drH2z(LeE7*;;j3uXwPo2_ z&Sk{k;zYj^5z&E3QD z;RVPUfVSD+Y}0y_DF+6+=+_>7UZAhc!wVanw~{ro`O~Ij3-#oZ!~c{A)7@1g%{{*# z0vP1c=!8aD)`1PKd?L@D_fIQU-}C&v-^<2h``;+}{oC#TmuD`M_wg?25|-16fI}eO zAW0NBsOnUDI;o5G_VMuxTE=aHB+jH{;1vlc90>A4vD4i?UEm#8@ z;1?rpJm#7{c|ON`sp%bQ@#$u-g_irTjE%*kQy3o8S9V}l{k*9k_TEtXMZ?+a>ug9{ zw2S`AWct`~Z*D1x{GeX99rmuwB?uRW@bMrMUeX0^Zb9kb4P|5Sh zZT8KaYQ}dv_GgcPz63L*bSl-*kE__J|254Vq{iYWinUmk((XyLZZ~%Kx4d;^D|4t zVjI{?r4rT_j~1Fd6sq_h^}v&y2q z$AJDR=AJWMMH5T-umoEBpYvgkp5xs+Y?u?yl#0nZa()5rl7RE*0z*#v#~r~)c0eSsn`B!M@d++O5LRF~o7JzJQLM;jDn!16k;iTx4)d2!AIPwoAV$4AEKkq4Hl zog?IF4Cs~vT1ss-!$()tT5+fC60+nVFwO(U)@;fK9qq31r$>Pndi=|wt?;QlEXROB^I63cYMi;e-_69cbf(RHm$j zJ2l_}ALVk{n*S83%l!HyUq!YWp~>wj#+7foY>=;B_w+=P3F4buS`a0uqIQ zwHb-1XB6ht>8&aI!%&5!h?Up|{E6KnIUW(}iD5377b8X4SABQ%krg7s9nI#bJXA{f zx@ky(C*tZ9yKA+_bkO9PMti(6~^S3pWfCS!SS(0 zQTg>0WAY@1n`x)GNqfeErUtqkuIwq-w(^ou)}L-#@8lpG$dQASb2MnVrj;IG`ANVsEN|R zKJY$ygb<(bKGnRy>|*0}K(IfzDDVJCZ5pst-@-kyaI=<;*b8)WdB-XziqvXoyEF$d zoikD&i#%cigy>ZTnIcV#WimT00E#pRa^2`y5F@%yoMjXRw@f_Q)40okm@sm8>s3|8 zLKoJYe}V4@9A@x?`sb4toNjqa`=$ykKm^=7&^IEyP$ej?|BN%rH=XcIgfr6ynQh6j zvE4r`Yu(TBacSB|sh3)7&+K<^Neu0Br8B#yE>4qGWe`!lCQMP)W~kW0`N0J2BOu#x zdkgFUG-S$;BA56l*2VLme<*WWl!X2M(+`{vfWsKDSO6n`EK;(*OEGoC5#<7qH}?bG zWUcN$Vn-P8jJ31B_t(D-XUaAAiVSqF2Ow4tvNA!&MYJg_}6w`80>LvjHk3b z3EhxQCbMiFVsh%R8CO+CA+hi7X~rnJLW0pOgIDY=v|q~i*6mv|@*V-2YHV3r9%{(G z(3_@;TX$k~mbYl2ruSMij4;i)dDF^{d-%?^-;7y&o8aU#1~-+T=s?c~=%W0vx=5py zBX1q;8btZ?T1Uw1vzX69B)KaeIlnp{>h`b&&(qiK7W#e(49id>G_3t*G)A2}aXa&kO^9>p$dTC2BxtY~wS~;p7DK3V2cR+7l&)M3&w(UlX8Bjn&bFPAUFYV@EE2QW4TyEL z&-E&bBd=Fwjber=B>UA&!=2!~T_{d&%v&i=F87#Ds8(1iPF^(a0IDPng8M?+O1sO( zEd|K@VzDz~Ekoz#0&xEIa3sPJ=KkG9b}TLg-d@FnSv@kgdEopu#fOT#@b!_vk&ykJ z*V`M$PyE0ZsJqVI(j&-^WB}U~FYdcIDXEtI9L$#T)?~?JuHU&P{6)t?+0N%&IvD$49q!e2(F^KWhBO(O#-+*}0)Kf6}+W5{FQI!i#Qp z&iN9t`@&VN0;#j`YEHGGzIsD0r|IlCD~{DCt~tu0-QV^b#oHb~Mna2>CNM)d6`wk$ z443JtyQx)PxXb3E`SvOM8!V;zMgi+}qcGcA^Bx7@+IH&)`EFFK)|%FW9ov50b!iXj z6+=PHF@9Nhzw(GPGN)J*)PbvIkn27?Qu%5nu4TP@(MWl+=a#|<*w#X|E}hpb(9M1i zbir+D>a}iTg1#Zi?u*nnVY->FcSX&RO$T;6iM!036g4)UKayl)9`!189rUFdfmb2u597Qq+tZha}7!tLs`HjDc z8>Rh7?H7d4Hvu>Gk2)7}6R6+PMBdG=a9sFaAK|#h$V-bBA}Px79*pg%w^`NCAqB89 zkGv!q*kKE~45GNiouG0^q*mua1iyHpf77^{1s6#kd1&jozA#Ax1mD(5E_Xsrsk1ht zrj(70|H5a%R`#-AtoSaQUYZ)}dco8X$s`6LV{gyy!@P8q$aj;#gYyf!_on-((%a)M z!7k1>ua0k)I9fQX26bx9be1Qpo9c4;j0)^E5#VlFGrC`$mC_dN0AsqQ6(%)STrxOb ztz^-KJsxu6Yik!@ruogl^Xoo^FJY86w3wo~<0^QA1}830@IJm#>bUR5oC8jDWv{S3 zrnuN$L8G|C5_!C9Jmag*6NdZaXzI5jk4PU{0i|m18%%Cv-L@XU0fc)@p)MY;dA?NZGB=tx(x)$ zd2m=TA?Lb-jMjXp(w_O|?4mkA8NOb4^6+nn1m$QJ`eG3^xX+F~vn37mf~ z)^!e%^Ob)qyhA(f14m#q1@K2)3cUL`2luOTyk`P~jeRuFvUy#+ESc|*a@^ksd06s< z{@h*7l&61O0G1`rgd{obW0rBbpaw7)2G`YTK#)>ga?sURGkTnMkuTBvZ;j{Y4RmN& z8kHW}CIM{j{ihoTiG`L6gEfWoYPULgb-rbk19?{l ztuAc+7?!?vgETPm?O}Ns#SA=nCPc%84a2Q9v15Mo6v#X z?k(K_)@Y!bny3jCDFh_?hX#38Z2nl}RvUzcYLqYEJ#OwM(XmR-q6^Ob*9&vgd(g843 zrj64D&<1xS&^iHnHTX`G&}n9b^|poY(N3CAIx2AFYpQ$A@7HCM(+P~vf6ISuKXE3` zisRDQibXg+&H`Tuv0OkDTIWZdr7JZtmL_|}Ur%R$F+djI^r6l#8=$V3ADH=xcJ`jX z@sxA?A~564!_R1S`}D%ba#i0eAn8Tg&D-ETkqLb(m%C9*eGg`8r_&Aht{zT3s$u=p zN#mSux#xziC+^pmF;N*eFa{TMRnIdjh4#AM%WtMrd{oO_7e%akx2BZzR#4X|>jeAe z_ZU))Q0XXk;p-J2Yic=@UHAT4+Xg5pb&>5fm_O(P3@Q(x(*tN5Qv<$p^XLEF2kyTH zh5p-UlA{5Z2qd`tu&H_G^F7b=oZnx+^Etos%F{Q@8!CQ zy>c0(yk2d+f`Wpw<;C;%3JO1x6ciN8*R7GC0ru~^E&sC$VGla1P}Z?)LVoaLz!{q} z3JMjN4GX`nmLLCg^P(Fe5B-vBHt^YUAO1KroVov9BSA7{{Ol?b1#1%{O85P|DRm!_X|Rg z9`;@(m)+M_dWYSwLEn#F4;jm+`2EtWQ=o@+D?F1fkQSv(N3lOHjd_Gmr((laq#g9fUt)hf^z_%{ z!nQ5?vCuG_h3D|b8f5;UB!VGnD5sy_*X4|`S>psKvQDF&3q*f@;=SNrXC_R$bCjti zDs4-?p*O!GS+BP5_v(dp*E1mg}S z{n}gL@>Q4bJ#YS{tD8oIy3~EY0fSxXJ5*1(QSpvhKd~wtFHiA5-obedum&7(M;-TZ z3HD~lh+LGSZjWf6Qy~%_Q())fhVMDQ*cKt(d5y<%onzz6#$K&V>R$`&z4net1EoSp z$4SeWr8Ij7k{S4 z13;Rqcq0uhTd@1Re@rK@g()W716*>*(65Dh`&#?W`yVcrH%sfB=%qRct3vn1Q{Ir1Q+k+oO$00+&;zkuHq7B$@of28xRrIk()ri) z>k3HNlyWt2F5W_$Jv`{Hy-a$I!hsJ}6%e%-lYezyz8jfqew~}DC?A*J^0)S{1;uu8 zYY2sje8H>}v~IILn^55(ix}~V6=6sL{p)bHkjnUz*Md~zYf#ChOGJaO0{GhmEG*)v zY|NV5`|JVn{^?--VBb&0l0qMl#F!xn1+27e!)LHK2N3=$SS!%;9yUFtm6HQYd1KHIC? z|D~$U4)IxrQPBP^kgKd${D`p1ugkw(IoRE_z`o)cu3d_^C3tg~)BPan z+&*mEg!W@kO?0N7Knv#w9&<$7Yv_+xqMy&R(+z2!ZY%c(e^aRZf4MjP@5bM+bNv4$ zvwUA!P*Bj~lc)tcd})-iY@(oW=j>eEO!nf}%L*uCLPiD{uJ|lx@sZK;tk&XT1%*%6 z<9$o4fC$N?_ea^1SSwOk6eU$rP6 zL{6q-{TO2l*{ds@^M3BCeB9~PD`%BfhGlB5 zj4NI_d-vr-SH?ZNzjC)VE5k0Utc-J9Is1BL*z1Y^b(0{ff8skP4lC>>Q1Pr?rMc&5G9*inf<2o-Q^dD6XvsK{Ju?3A{l=2IHcH+ME6rrT22!Pj zi;q4Ezc62o?W=8#`V+h)A|aeP2!@wiy^EpCW$#}&w`Ybg8*Wc6N9Zzlh(ZnF_$Te= zP?ta^a@WvSayFu_8Z`6MKXoy5cX`}4iVwT@=a%(@RfG2K7bbAD!hn8v&s?_ASs#Sz z>i2nuc4NQN$6ZUywT1g38{?br0!u7f*rIL5jdpd3dlF$!VOT%OQ{=JdOE>iHV3qc& z?)AjEHA06rpv0}&D8JZ(8qa}&LIX!oF_-m}z+*Q*<}0~*4kU#NT!#VwG(MzaEq;%P zPPDc{XOJ-zMQU1MRFJ>XXo$_o3 zu!iX4vabYDPzjb5);J8*Wov$fNh}kJ1~@R-jmr1}8AO?0z_vl{Z#osYjaafpTGNL0v@1aT4#-^GZ1BQw3(Joa($}zQ7Ev4m$+hKVTC%T@*P>kNOm| zqyiVv7s%p=%d=I-W(8y+dgSdg|4B$*I3i+sUIo1@>!!_dmljE*Sw|g1d6qy)&f1^QB|2tV>?wR6$uv7${fG=Czyg)4AK}Vo(i+obR|SLS zhtt7E?=QYTT-lD_Q?vi7cd3=!94h>ePiDoKJ$l%(uzpTB)|GMS7a<$-h;n<^zBZOo z9vL$~s`i5D#;);0gP4(!qrt;W#)7Li)}}JsOmJlk$ld5Lpzq)miarOCd(glDt`>Pz zG93%O^b_4d&0h^pba6B=q&FvqxpJJw``w2*lLg@DI#CkzsGqxXQ2Y;{+5>!fzSN_b z;&~I_Bl)ZB+m5K()^HDHOo021v<=GJ2K4k@`3=VsN5ylVffzP)17ET|y2t?6-W&%$ zq+Klr^NOdV&18FpCB%X`ov#XwH4_|4F2&j+tm5K|I~<3guWyHCuWlzAk3{xGx3z5> z?><%OxhMMk8rw9Zl1C1K20dF;SL19Swc3+aaX+!1wp7>D#p2MY z!j6s0jxwBH50Y1b=ueMSZTIci*vsJyTn%=LJKk!({hhf0!Nv_gO^SUw$_G)rPHjvc zHKakdAkl3ASFpjD+`Z4ElP~UT8lTaJwBrYk5<7|_FDv@b-A-%{Mm1Ihl#ew0hR=q8 zWiLZ*nZP)4;rQ^Oc4P~BZ};x4d6>t)1)&Ylb9zk%cjXe-=CQ})Q`DY?hRxEk0LPrR zDLq{%txB_^>EfoEhVj|>r!9`k4~RTx^o9U9_mA#@+uFVfBkDj{2=Z}P_%Vv!-rDJ8 zvWj>zxm}`$I2@lZzhO4&cP1b;7B`{oP-Sq~?{wMd6mJaodJzA%TU}RsRyl*n!}hn_ zt~ZLpK0SCGY9O#-$2~}#(9^dfe0~an1;$F*9cncViJw`ch?nT_Jzfyc4Egx`dRz-aYqS&9Z!(oy^kHYjlXuZX zY62ko*BR4Ey(89iZ}V%c)k27W%S)WuSGmrM6WVk7NgmNP00dPx48$a%Y7$*JnY&>7{FDo@+?wCvfCcbv*>>EcY81VEvO!LN$E{ZDZfciE`lve_oiuME z^w*{M%#fWOE?rj&v%MaNoIXDs-I@%^l6%$L5cqvogGe*{#Bov(XgaUvZdhrT;{?#T z$f$6E9Y;OXNm5NIY+|3_#67@g`-3GsM}Ve&AW_$jZi>4;k4vVh#MS9C`twe~ zVpZ*$x+Z?)#4xlC_3M-u`nG&7uk8%>w!K*0SEVSfk(#iT9#MoZoxMSH@AwCXtF5U+ z1^QJ@zgA{)c8}H7CPQE_UIcjd_AWgSi;;-_>m_h4q+oaDi%v#fLrXR#Nq7hvUKp6w zW`@ee+vU;FsrkRUwlQl;;rINwgg)>;f zDC!Jz(Ox+{@k4EGq}7cqt;BgUz{6^$x2g=^1HGRx{ga*fzG7s{Tmy|Pnr`>A6KqB* z6Jo#IxEeH+FbIOJ5<2G{EP=moUbmAHme;U;)&LF5fLWZiVHhFEBvSXCO}JXNGg<)h zQByrlfX#_rvra8$`ge7M9bo9ex7~yDV`UyZ2bv(0FkF^-QQKOS|E7RU*1y*Fs#M;@e($G9C*@PPYjzKwhnH4#zS>EV7t&NMDH|pe@_zo9fE@iK3 zC#D@){Sok*Rio5cdh1I3L+jFeBIl~tlPj=OYFt@R21x#;hg|VO^eg74q)A*%zXdg{ z<~%@*?RWi!dt!Fr4CHl4;cvwVl6Z5YFJr-%8l=qWJ|%tu18f$6ln-aAV&QjKMjJW9 zP%AR&y1}dMp4pes8wzEwSX;mY9tK;W;D-xiYHf7_HuEU?&a}unHm2v3hd{5F0|InkDhh z0JcYXGH;6`+vQYXC-bz)Dj+k0u{dVzMd3r}w^N^9X-E_KpILMQ86jKsL8r+JEs3Qr&Ip_?C z2v{a~8kWYBxyc2hQJ2R4fu~dkVq)TS3j%+&%Ftl#EVhU)YdNk;p`&p>H;t{|^dOqKItmUr@r9pB$Ufo|903^~&A6IN?c0lOBpSa!7xR3E z;JDhf8bCAk%W#`MK4zDXm_A=F_d4ZX=%bU(hPYaPS4Zt<^4w>;(5J=q;w%xPw#y~j z_p2_N4n!q1orzprm)WF`S_v-!%_RH{Yu}u2)?e%coUM2VeHp^Lh>sOb6>XFk)Z&jN z^FDmX|M+5f!BpQ?z)Vt00Gka$8TBkC{(hs4bG|IPd`#UF84>W~H$|94m?=&wNn!7& z1lMdkxpo3CeI%6Dqp+!_OkTKz6WUJY8m#3<#1)T<+oPKs>YTONyr9GLU5(Jp5%8@% zqql}*R*3xIpk}P3AJ;PDj{%=nR+^y zq%G-of9;{TyxDDExzG!`jbMcXGDezNq78KES<+fp3EO>2utgs;OVmxA7>cy{NVFfj6Q~>v ztRxN!<)0CXuHPaL>95+p&+x?o-d>X@dw(p*GfW?Os&`5SCPK!|x@cP=$9DD{NneS8 z_-Z2q;1lS|sBc`$)YH;4ve?JmBATk*jMow!Y~zt9`wknI=gRfRt{be{4;_|ncL(YA z#2;%K6}7=m*j!i|(w!kS)E3xE)~twn)otZq16}3y8A^ap9Sfiz=JVM@s_KQ}dNqZb zvW*m0ZbVjv4q5-__%J3zZtdl0gq5#XP2Z@cT-+P-FnjUR#8(AISYIWcS1A+I6X-UO z5EMj?&~Wo-0J+H=Ik$*P5HO!ZZS(PEQgc9fdB8Aq*i4?t$c5eO{yOuGXx-{%w|zYc zKaPO=CtVHH^mXHRsvm`zG8e20|G+=5NS#bJPr6Q6<=FGbi^#|BX=BBBo265(02-ZS zQdG8o0+@82KX7dbe5+<^GqlKHwSg_k+kj#(n1066Se$iHMgGVrsM z+UCQaHL{~eZ z$PFm#lmcX5l?%V0GiNeNi@I0Vq2l_2AHqJ1xi%pcZYWAV}S+KtC%!Yej~ zx>|ZK5TWuiI7IGJk9m6s#(`qD#8{^>Ye&VKay|vJC@H{SxOcXo*rH}LyC#=qYzFUO z&m#M3?I;YX5n;w1cPFpS{;8cfkchgWd$r@edq~(J98Jv|+}qE?Ctm3>(6v#+X_B4e z)7xoGXPZ+i?(2ozXH7lh$i;7g2`ggU(<0eO+|fQ2hNqh2JlieHf#X96V^MH&sC6AH z6eAyqov1(icROwam^Fb*B#eHwkqBm`aZGkh!w%?D={-5Oihrb9D*q1B@+RDaN)jur zxm#YAt14)~*1R1KTQT>8QB+)#qrpw_No%Zty_-91A71vRA8*XXHfZxRT=X4heTuA@ zMjvatRV%cyY(IuqOV|oW*LI8!o7u&`F2L+#%TT_LShND2k2f9t50>|mrzL+wiN4K< zIzZnZ`aUZRc1jeV0T8Ee|C*rYk>>#BY#l<_ReeljAuL>2z$O~=hnL*tS&F#*9KeKc z8p5nA<OBESpK5N?%ZnB+2zVv+{OiJ%9P`TO1Gh#YS0mAM0^TgH<4_x{LeH{g?Q7A``>; zMyh>~J{MJUe7)h_Sz@J0ksGEMen0RzwdRBxN$M0|(Q)TR7{9?;A5Mv4vv-f>VV$C~ z{Dt~65An;;mFO|g|6;(-;-j>C&lRfKx@4&V+UhmcUm@g$suF7KS9vH?upok;#Yx4T zlef~37`aCqrq2dueaoxz>-?E9((RbWQsd+^A1UdLAMn3A*%)%l!=0Rw0-2#}N)eTk zA}pIR2!xcsn40?P0+RFeVgRBW7J!%VnAb;w56e+8kZP*T zjkBd#H_viI13@M`tOVt^fo1BU9*Q<774KQzL>*UpxmU=R1rU!JYYkCc*~uK4<|DQ&@3)963({tMWIAEu;|NPTZW`~&kfH4ppKy43B+&fHxDEs49q zX@W6JWYAOk*{;c5d38n8kCwG~Bi4I?^muN9_nH>x zQPr6PoN06SKRA;}5^Mgv0xB}tcTf=p?ou^^!QbxvD{c%gR8`mF`z)Q2;G>8{DKAwi zod|!S5r(oXX1FojwdCP&HvC39=R7^QQRw!)Xs)=<~KtB=so-v~Vpyw>74J{x*+8NaGiuWeg!9nl}8 zwkeFVp&NFZi+%@VpFCfN#Dev0OnRQX#38sxpKkZ1Mm(zd_>=kM&$sx zk|BfM8fTe}KR36RIkU*p9TeY%{I zMcQZpJRqVut{G!Ffnt?JvQ9VPouS9LU+kh_S|$$H=n8$;F8hUZEHq$%W^wxN7JIJW zX$X+;(=Xx%RhDWZvg~0$R`nO39#}dYO;mM8ngu?C#9d1MY~NHA)_!6Rtp>;V2F2pN zKX&aDW_LD(&gLqS-O5_3+rnWMVLjI0 z0iT}#dCxg$id-ul#dheWXn}>O`Fu}Aaa`HxfEDW{!Evju;4kZ!8uyfLzRthX)4tiw z7VQIVQ6R2yqSn;<4I<6Mr){R5bOM=o8UjQ$D44FmO<>j0G(Ox0=rA*Gjrv)Re5cnW zuD8ehh*>}E7e3My^I&+Xb6^(?85Cx99*tNsbTv^dK8L>8lS|dL=k}_8*zL6{jBWHw zd`@OgKef~JsK}0a%dyH|AlIMObhM6krGX(wDQ}m=eh6%*RlTuB3%|p&%`C04gH6eu zbt@Ni?U$KQp|<)zS!F*~fd2vKEIY^_bc%k#Hb3jr z99%O4-bwjT^`LQp1vvYWC~z2iVb7gIESdQX3KM%S@dWIf@=A|@9PZuf(XAF5hIKVK z3_{+1)H}Z9iLVb(T*PIg9k$A(ltWLJdZn4ZOWyo^KiV)KGCpO?-~hcO{DQZ{-1+gHugxaWrua zIHMmElwEr3)x+@R7a|>*9$8`muO<$aGB$o|SrOBiS512eXObb70S_D<8k^tuLlr^_ zK@Z^ec;+9puzXXn^)4kK;_7v zLk0$Su5K)(KFrIhkFZ!p?k|JKA82;Ddeq0yH({JS+*@LCUrKg%K48`sXZ_M}7xZP$ z;$2FYSj(%&-Twi<`%6`Jhtgn%#O;kdxr1B^d30W1`o-mzD1j=IJm* zunp^(bQR>4ppl+Ppv4V6%isnn|3uQl0qy}?d}wPPkROgeomZJEW#jufqRG;oMEdpN zL+<7?ebDz40mSEQ;$a#)EfZ6KvPBom0-k)Hmm|mj%2wq6ZOYzlwMGc`NB+5A-hCcn z284d?B>$r?&B+DUZ~d!zO)?~ry))%K=cD8?iLQJ@UeH0Y>e;3dRMFpWS@8@`Au7@* z=s9SsOzFALEX5&b=xZA^GduLxpgnWfug&BhZk9Ft`}fG(-4DEeqdY0wJtLf+kFR^E zX)|f?AfZKa8GU>IcemRVeo%are7}KFKW4<+9&T8{*krPgdrH)o_1((Oju-USkFTEv z&SZ1b!Q)-;fak{3BWC`&yyt2EcOw5ABw~olSuCK8EV}Tu3dVq^(FN%ruVdtR!|U%E zUC}(}Rps_ZDxd8U9+t;JEZQ!$n9rw{9urO2MoC?$=K{9z*r(;UTrud(WWA zex>>062|n82-xe%wJK+;{?NRD**(+qbp^zM11g6Y`!u8xFTA!c_r6M;&#ir+v}G}~ z9}nLvd5+%)Yn53CLQEkqCxE51>1dVkqaGHcPUU5%=)%Gi{9R$n-6si)J>P&tIeqc{nd`N^dE=W$(EVls zlDl;PZ@JJ6o;-EQTPk66-%HAj;r)w3o5GbCzLT$g$K`XZ}U31X-KH2v$hE8AhTf1HpE~e zBbsUI+lot-IXK$kL6@43CUa=zC5IY}lt7t5SJXsNy~&Hd$!Eg|VsT%Xzgd(2v_Xr| zi5`215zDI|0IB6P;b&{gtf4UK<-A(Xi0p=;xNGoBr~}EoVWwt3-_^q#fQj&w+%Srq zsWE(?P}XG61zDty9UQPlE`NGyxNp<}UmU#bKXmNie^HlKRXqz!Hx?Bv)(m1fHJQ?(?Ywtz`f2oT%t;erFS2 zS9~D+$FQ8+j6SogLG)CW>l+&)UTJA;($#R@bzptH6@|{;BWMoJ#{WXf+2>+*asKK4Y^N&8^rVrrVMoxdX7mZ;1Iz}L z_n4VbEz3`X8Kb@UX(fGQ2hz{m$5f0w=OB@EYeg3Ht zbWGI{HPiokP-c;HpRLw@J&Sym|&Ww6jK5*sw6mBhI*_j%qh&fzF$Dv;rjcB0<}274b6o-p;@ zQu-=4vis9h_7MizFJwCZRcQBam|f9TRRyLKR}Wxke@n!6qo46N24zL0SLt1ymlkIQ zbWTzP=Soz%!NcRi@SlkHB#9eGH#*Ng6`XJkO>N)8DVQn9gHQT-&!W0kZ-p|#n4vYv zew7+@O!UT~t@vm|ocPC0Nn@P|{q@cEeQW8UtR0q%oyf7CJ9Aadz_KBPTak_ru{KA@ zVvSal{b65&R=KTB0M+SP1z}~P@Wm8%3%Z2QzhsOqF;AM-7%FNFAfuw%zSx6hoB{#9 z+X7Kp!$>OA75S9Q(Z&+(tyWrq@|rj7xSU;8FqSZSLWHyg3oScJ#h~RcdnV?mxGLe( zg!b_pf0_tpUKUU&%&{(NuqvG>!_E%3j!k!oT=}x%DBxS-RANe#;UW39#L=Zu*MR>9 zImwEh3u&iYEFN{2M!2dj3a+Pq6=vE-tTs~g&E^m@(y8aB*Jb$ejgz?SwQf_yM7MUkz4usrFS6`Sg5s!J^$7X!f${$BNYjl;%yMgo`b%wMkR)1pe;1u|abrZKvbXvW z;&SWCfT(OAuc89|A@>zQ z%KZo$=zU`X6V2P~Cc#R-i!h}KYMWEgCCXcYry7y%1l7^YOnX+fAi#wb0Pr6g3-h{S z%%J4Rz(QTid8e4!(ql-fC?W(M=}a(NJi<3mAMcx}c25&bh;zrPtQ^cPl_I9}<;9$U zx*jrj1B!FbeMO{vOxcrZEo?PVq=g=waZekS5Hq=P@jD$;V{%N>ErEAg ziho`#3&<}B(TXESXXH~Sb{B^9u*S{}uUKk31?G^ec~j#?$eY+Ps+x7uM*a}B3+cHP znbY^Of6KZsG>hg~hFar}ReVH56K2hr@owGsye7bnyX&YX8`r+~y!-wcu^w~EcxS6# zQA2{X-x6}IG?TU_m;;V1i*$iyv9f zdGww)*TsWI<^IA=7G<|xt>}p1vqf(E?g`XIeT%&WJ5*T!6O*`-s!H7Gx-$p6aL2II z8jP4|+tu%~Jc_cp2g`GKlw_IRDAK(?3M9J*@kT;mA4}Z@IWt+)z)uJ(WWHGJ)?H(V z)0Ug&-i#q_0_1tX6YH%R$Itp`(W@G#0%|*@kPZPtP9}hZG&V!9hv_1!TZ*hST-#SW zD;Vp-_eGR3JX=sjRt{*nS>h$nr0M9cnbZPGRj3(OI?Yu-#BG5&4%mAlvm$8h3iqZ3erHUG3ubobA2i{S9kagEje)6pBJBN!5d{5)KQ034rMSv zLwVU8@@1(T2PAWW53>Bs|2= zoSdpMBu6?{NmR)+_VgJ;5H*xvb?VKa+Uw}GS)P-2bL(b-Q`uFh*Ms4dkmH;WR`*_C zg!ty)8`&MW&DXIm;po-01?-goZ2S+QoW2q(;T@1)_L(YiS@fAHWsQ!**-dKCP6ck8 zi|;mQ7HNJabIhJM^u;7F`^ll`{;laJ;X^r~{0ee8wEj75+&1Z&n~jw6|YJyKSdiQ zpFbp9c!948HF)K5cHSN)n4CL$V2*sSmx<@2R%beuo!j?1&PYrK*2Uc)02n`ZtH;zH zkW8yVw$-bMsOk`iMt+TSFeat#dIw>TF_a;Slj}>zu)vLmo0Pnmi9*wXVNnVFsVV*r&FD^PcoY-mY)_u8i<27RF$GJO z5G!_$XWr}QL5BqMZsh$Gl8{)}WoDApWNNaN=k7R4!Sm%U z%YwRW`R3!V7$dJUtSjgZVC*+fK4tJT{huppidnr@{r8wXT^ifVchkZ>6!QbRw5RMs zJiliRl*=2x)W5Ge6g{o>fUi(wvLL%agUy{P+|c0{@k%qbr0^cUgB)_e(QF#FMwle^ zJ7+aP00)+OEe`iE4z3;jYk{m?&}??c`V&WHr!>n`n~e?`O1w~ZlEhS*PYMI+sNJ%- zy=2m%DDm^3g8rC3tT?SP6E%psf-YXPr+|ORB(6ynH_VPwG9=f{J{ITHpgDT(9}OkJ z8muOdrj)V6LMzR*VuUG~y6@lC2Ng9Z-WZr1=^flG`gCjc{BakRNJcKGU%rK8wK6%4 zy(Eg;kP z&#>TVC-+N%bsd+r5r>tH(M~{20k52wHT&BU+CB_yD)fSy?L6wB&0czRza-+ZV@E8f zI6Hn&E72!35}h-v>fn<)UnF(x@SCgYsF1rIXJjSU)FXA~#iAc|>irF}+GcmK8#e$? zvZMZ}zaP@s-78o%?KXE2HK%F6>FJx8F2InA_FIn3B4$o|_QR5!WXS8g_V&!#mk-sS zF!Qx|age*6Fs5uabK^zt<3@mxU z7oU9CKdy9O%;ub>u(;xIpiOJ}?b;EIMX#=%-6{6yJT6@S?Vt;q7-q=e*Ef}!29;+7 zSR(tIw?M&Yd*ek9Wd{z$Ki_!;mErBW@(ORxo)GKr2>R)wil){fax`9Lr%Adi@XN%e z+_!NmHYOoV#hBKyHy5~q<2{y0WX$i=n?5##9hiGwOc1-ETNUvt-dO(4tkldH5J!8e z3w1zpk3BT9#5_Z7eUmO8*j%EVS}vON1ZeXoK$XH0y5 z@x${IH(zzIY;?RdZ$O`S0xj-fL}YQpdbXAF+&J6?uYAkrQr4K^>$$4&_Bash>m=yJ zL);zL+GzNhL@|!c;)U9_?ZRd>q5R#z+!kmPVUd1Y2*2#B+TwG^Ir&4Pc-$;SR+vm@On=;0zM03C zjee^}J?ylq2<`g$KO54n*F_WBeS@3lZ(mxom`6M1n_QBtTo8eR`95-Ld2LVa0#O}{ zx`k83NqE4!zWkl>S_lE&-GF4V&yhsa9Ti1x)ejeBJjx5FXgMui`cHx$L9bD0D*jsW zySsm8bIQHiA7FcYS~;*!lM@5%h0q|+zTTvNfy009GbrE5UyJ!6 zz>c1k$Zr3oDD>Vk-q*jyQJCQacxHa>BvG^ju>skN?%5-(S;{)mBHJgS3Ho6{kQssI zD?)|NKfHF*Gi3FDcAd2X)}Shcek525TRQR7S}`g@Pf&5IbI~j>ku7~v_t0dN+NHVq zgr}cIxI_@ zb$f2@q^RnLC7tNqHEb>b0mH~6gz$W`aFuwmO#r#j1Yu>5KJn@Se_~o?1~le$3M`Qt zwEn+#hTiEPrY`3_Gxt+G4S&U?WsG7pc>@R5j|%(Gk#L|El($?GZJ58^nY(wqvJhPIq zs3Qb=`NHH5zaj1qRD5s1I*tE9i)U^FLM`0aOLZ5w1YbQmN4YOn;`hiO4lRR)gD=ci z-cVk0I?BCk7x@7u#k&j2=?_dISwL6nK*_H;&AHny|bF^1}!H{ z8A|2o;;~%Dk#D8%e|ELdP6(?2k45cU*=@+}9P=YNc3_6HOQ-gf!Gn&y-^-aR<`q3g zjN*V+k!C~hpn*!2($OyIZ>WRwA1VhqZ+M5Hl!+DIo|87PX5QmpPSbHOSRZp+mmSGWtX70;W>lwafTk#rqa-w#nf~-%KSYt1eaR3=^sDnv3_z zs?(YGb}AQ_WB-kAWxw&T3@s5IF}E{3Mb4yse`kKCcRKt2(DcLte<*&-9sl?u$$Wc; zR*s1Kkx-agHU?XkQe_;wxbmiXW8YEQlkI33#bInou+6;DV z8N}OTq5-}7Z+3UnG+h_}?jIcyU4^@_9y40`^`O2RNvj;`IhXa1-B4)WnFPs~KR>vv z*TGBWlRo61NcDz5d;CuMyo-W4`VpszcdXEM_#QK0BK*yaMw1&7i{=?e?)7=uigLO$ zvu@_6=jO`yv(J6k+)b>!6Qf-L>e6oh>YyJy8 z?zIZHy_FGaYc2_tj;Pyb-FjagQIGZwlJBnVPmt#6_l;3Lo-FOCWEiIX>DEp>G-I3? zrM|=L@8seA5f#k`7XNHL{2zv()6&_3;kEQmSRWmAAOmw*Ef$VcQOct?<365|r%Gkl zbEUb}hTAN7SgsNnCEz!o>>yN48qm}3I3uiP&3=!n{Iu&^W0`%o%Jj}AwOF&?G|&7y z`ylYJItKe~j-qqmrwdB*XAVcIU*dvckM8+xJv>k~k*Z~x;z%oVL9|W1pxjCw9g^g$ z|0T~lE;OiRcctpVYL4%rgyG-1sZUiW7W$7#>kO`vMg-NhE@|S2e3xb6l3l%(@Oky5 z;QB^K(lE503<%|eG}2@z_5Bxf+*x{eh9k82g6n3Eq}k%5sR-JfQ-6O9D(YR&x1P3Q z$E>{3wD+I&dwDGPofT$EGr-vU_G{}ly6UWcN3OM?_EoY5X9w(6KS|w{lZI4QcVX{O z>P}q*HQsX0^2-V9V7Key^dL}(@&)`M_qG&{Go)Y3-CW%g7Yd^$V#NgMRCQU@G_4;| zPi5mwPdt9W(;j;^4fE!>FkG-U(QPQOh0}fpntEY^S{%v9urcy1{YXENG95XA_Z32I zwWj~BRh?{;x0n+DnI-K#iVGunKH2 zs7TFQYAh)jU=1=&^y#f+0s5n%sL5VaqQ^N`IpNeaDFYR&z0#Rby+k3_hOw(4e0^>gsKHq#lCKb2>r)C z43!iSNPpm#lyb9teA?`?iT^5BO!*#i>%Y@+4iYuq9*h&@$&4C;I^Oe#9D7Ie@-pDA+Ne;@%iFLc0`s13K??j;`EFf zKZd1hpJj?Q*>RBWM=X`OJ}YPGy;@L%Oop{v35sufvL$~Ot4NZ*=k%GQZ=yRd{MM&O7NYuZdRy(Vm{A@Y3;swPU~gMc8;dXurL>cQv)+n8Wj)1FxJHPZ zEPpQUD<&~MCjDCV$F^J99*3=vMPUUs({b`|Ga<pE@JF#8l>szMqj5S*d9jOzJ1vPdW zt(>VuGq~7U314)7BeLYVqKuFXbE* zGY0i{4?qrEI34afD-}&EBN@BF$x21l(1lS8>O%axFwnb89;*}OAl?MC;$h=2cj036 zwLtzhsXp%j(S9%>3b!w|WXw0Gl$K`hQ@33O^tG;g9$ zeEkw_=lN7|nYfo71vw*0`!~_jN@i2|Ra(Ez`-VI2I>v7gd~0#itc`=H6SnQP^HSF# zXT$FV(v7;^2XPau>-@$MnAF`b&-zYBrZ*SdSJ<8EUv;!#}wH zrwmL!&niO?lWvbBz5FT)egE@W6HMsx`y=Ph>-pg?NbA&`!NT~F-gBcC!8ro;YeDr1 zmLEOzQ-g;cYX#+z9k+h^d2se^KuDex&@R3Ca_&=mOf1zKb=tIEzJx`!(uv5vz*Ir; zEYKKA)$HmYM*Gg=Zdz4!{^v|3%QJ!0u^lG+zKz8Ic*oZjlJ{Fjq8PNr;IRa-=bR-3 z66_QWlSf3-=G~p5GN9_-6E!KIGk2ES-Z-z7sv>L64*C2)?7ewd(rNoQY&m7C*0gFa zmF=dMYc6PJX=SFSWiCiF?vh$6xgc6uV@)cVTW+Y4yTFtSiUL}VmK(W2qG*i)3IV19 z38K$eo9UkB{@w5M9Pe?w&+#75^ZU;O;S1+=p4Yj2uJbxSE}c<3E1HfaP(^%AJ8@d; zFAcw2Z32~i%ewyTOY_f^E&n|N7wz<6>$jA~A2E5DIJ+BtIxz6;f$@vkLBBMpBka43 z@T##iWJB@9#SYI?{&cjFRc+!N2g=w1e>(NYx);MS`Tx0ceVgrT`94Ya;g`R}sZ?gf7AO2WP#Db6ZhV zH%tH7L%9_Ui-{?_`EjuScm>($%w5SNn+jayQcvB-G!Pmeaua33b)<$k4l|O_L6E z?Yrq1mm2mEM8LjpNW*G@>>pG??{}-#-|l{H+h{x2*ut-+%tew&ivg zw)nlrN}KhCv5sew71<<1{0-=QrYLM<;2&Tteb2s$#EEp*N_JwK3lY;fNq$armzo%uD4i zZAt?Qn&a)X9+zzu#80+0P~Ic>T@!vjJUiSBs(3Yr34$qM7;X6}d`5bK{LeE=iWd6A z@RXF-aID2b_Z~8n%a(SABRQMInbPY%YX4>X>-s2>0#eCw&DJ>t0)BGpr>8)7glQg| ze3p9iq$PJ}X^r`ePqx0sSwXS>rylc%uCwdWfVyC6f$0`&E@X0cC?C_S>AmO3VAzH> zm1f;GrSukL_< zevL|N*?l#SA}JeoW5IY9{D=sFdyFEXt9Z5(&*H>cHfEw){8Qt%1%hJLD;5f)T)gn` z4%xBiivM9JNfX*ap%WXJH;dAgGzT6&-?i_8U1GS#yD9sXY9qiEYHQ?BPYaF&Mi*pQ zaOJ)Pn7&jO-tvT&$?ZNfR)$T*Aq~!ItT<>V#3&zIGyWVmaBmWIX-Ko-YGiouCl76~6X1;!eHhy?IN9tRd!UuPR zzMN35-?w1V9UU3Z75I19_%IgS9Rw?iMt9LS39EKBfMr0?k!nAeR9(s!x?$szQSoTf znIOABG^iw^xItIK5sA+Fx+Kz?p%>a*nfi_*E5uY(Se%v#3q4&}djS&OEtI|914Ci+ z4gYJ9@Y-EK;U|BNxHnbQrr=N{xJWH=Ih(kZ=ElUw-cdYm5jA_fM8GYwO)QPMcEJR% zU2#2Z3j>an94Fl+kbxb%>KHL-^V4JT+qMT%4h3sJzLZbeKXr`{!qnM@Noyg!Wt0mv zV|*!ybWukW(Ee|*5HHOo2r1DP0F`(M=EQC5K)Z(pT#q-%)bb>H2OCZ2N!U`?i9>9Q zarH_4fqjqYZw+Z4;*wrk>lKsH5fD4NKepTpZy58-WtGNw@+zS{tRW8w9&=a6KaK`B zY|Uf^b8|kLh7R-)p*%MwL851TmY@~IO^3HYClI^m;9d|e>G}@0ZvSO=umfGNdXjl% zzeyy~4w@Q#8Kp3w9c~*8M>1vA7x|5BM<$qdx_t~({<*wBz4T$fG16%qo`#4(fu;+k zrF8<6Z7R+geS{m-KY?_V9o>Vj$q*p@H~y`EoqAKtJZkF5G1IH#Sr4XW-#&erBrmV# z$N2!|IhMTiz;pzUyGI^~h*8gTNo-d)*#mmOC)yJIO#6}PR>#|++4~+b^_~Pptcpae ziLF$PC?i9s9_!)gy@tGo)N~z!tbX&c2wosrcYyW=u^Dh3*QA83kiCDdvmw4_e?IO| z0t|C^(u?YRll~(dGz2^0Z4l&HX;_~caC(D64&TG;H)Ocm72evegU7m7~Ho}vN3(BOe(A{;M z@sU~^#6-W45?=NBqKS6AZM|aGT``_1E$T*3aR}q6i>An9AaMhKH4ane9YJKgt1c)X zeqeN38;Q?!OB0`@vY`xt!J7$~MZX}%e)iRATb32g5MP_bw`Ee`17VhbEjSKnw`AN& z>eTL4pVoJb@aMxj#^}>#fAq|p29{s{TeT52Sy;^-0SXZAx_uR@s}4Zad)3xa`>M^YVFtA`fk0hf0jOHyzdAMlXrG6e9w| z8kH8;*aXAGeC_R>EMsN%GpC2ysM@A^7{n+05bpZ=UxH)qUu}b}E{0j9h)dskRmsv_ z>PB=cI+#I3zQ5YgqdCvlg$!Ch?mWR^IFW8C%j4;GRWb>t(J0R2nd+qc7^R`dc73+( zhJ!%7qJ_bO;P&8!n*FiC2Hkn_5UwbfR%L-~^0$HVW^vO8%j4q;&nr%Vd3OO>Pi;%YNyh2fy|MlkdGNII9J_$#oK=)(GLq;%ZmM`hKD5QxBlW4$sC zWqj26EBHq73sGA=MeK$pHx)F#_nHDd+-J?t?it!OQb5=ANPu;~u~Z%xM$vr}o&gIK zaB{{abv}wN$t*)=ooOUEH&T6W^zWKOtc zUAKMvVtY1(F+An=Q?TV1)QmuahTihR{nv{GSEN~}K1f$|U$ddt^YgONmJ0*)UFPd| z4HU_>@M!O?Xp9s`sfxq;J$t|%O%e;{%@X}Xo>;qS^BW5%%8fEm-WSYrs!ii^cMU{T z4=09<^y}h_rh>x%OwdqW!&8P`k%@iIhj38Cw-Iq*oN(2sv1A0edX}6%70C-u?eNRJ zK+D=|vXd*S6T`%+VP=|RI)*v4^xjjYJ(sik2k^f36^k*5#~e`&?6=H5OUU%g$6XBX zVP=&a#cM!Z z-Xly^eFzJ^Vp8UO1nk>)rK9?11Kh#l2j^8D^xAkox?V&&#E1|EyQM8{pqstQpDv;V z2G92JJ_q%_yIIb9g1rxNAJRXsfe`|t4hJ|?)z;bq9jMG3hfvO4zGnjo7CFd6_@j@w zL;6aO&iT?9PTU>f(cMe^%&>5~=?Q7QO3}gG6oPFQ)stL0(*%nv0&p&&Wz|72Wf`rK zm`fJa(DJFNaJOKtyV?U>rI+w`%Jw1wUZve1II^iuXT78BEi&9fDnZ<9fq4bWnnI9= zz8&K9D<~0Cu=TdK3%irLwZ6IYbXIIRpPu9C3VQtR@Sw`4v*@^DPeHHM>1C(YZ)nvz zR8%%vJW4QPNDt*6v+r+irQyxBY^HO<5cxLK1uY}@`ZEp7O$m|O3P}UUCq6!l2nA4x z1ul_9BbD{SdWhu)kA~EE%B9HV@KPG_J(n?rK!cu9sp`?)bq}YRvN~p0;2T&{gpc~L z0wbX|k6Ss7fii^Je_oe@#5QUOWxx~&Q&U8ZO<;XcaE7iuHfL0L2v^W{2n`>NW*CF} zPy-{^^9dz$(UuLN!Z3_< zN{-fY6|bQt7wQ%d4W@iq{{%~1_nPy?6RUq;wQKQ1$5*-&ycr{5b+h&m70(`9mvK?~)x>CibTL z2Qu>7!Y_)O(zzG=Y9lYkuTPXMK;AzQ=_lt!^rhIPHcDt;=$MAgbJUY@b_YD8mVreHN|<* zPRyoTiiVEc^=9wY1%u)rp; z@~EW>Qt}AVFD9VE+}kw2AsNM^XkDI(3Z!6Dx&^Q^wM*iY0FK2Ca& zE^z)3YqHIj)e;(UkSw}OpHz+Fb7Q&gk$+qJa-75snl&Y1%f@Qy)muY!nMPb##{_KQ zG+Nq=s1!@b2{rxQ%EHsqb5rWQM53#3u*$IA|DssR2-K;Zi^Hx0h2QCGGCnDugAuru z6q8i80`wBF(rA;;xt!1sN4ZdtZBpw~+`LJ=|A8){2`+liHyj%cih3*j*I8$xey)eb z%y!5&yI+p0=f%oReX#Ctj+~Gy_~p^`J@fIW)Z0J4QJ`Z%XMzce$){#P`;gYO3xFT= zViKTavj%&FJ##K5*<1s5j-S<=ubbg5bZ^kXJGXs&udP)1waczt8+rj2A-K_N1xASK zha;15D+}|VFF?7Kb>{37!4*86%ae0A0uNGf+&*II&1Rc(#w*q4iRVv9Us%IoyIlHS1WE)yENQp~F>IytQ={L;e6fgB7oL&zQwaVS zLdafU<4JOZP>A5k3gFGtUh)igqv9ra2&VWt{9uLvTS^eYkP)=vo;VF~*02&Y`Uk)j zq-C<=&d?JNmDXb6T@+s@@lD(Va|K`JRPyw6i0qiCEa(u<%?60i?Ee;UY5>QI`qzovHJflP`Noq93TlTqMWubHoudkA zI&ahaQHmyt*X~H(2~SyS5!J^pa1y3IE_;3!aUuRWC?gy)eQm!iv_adc znDo&!unEX^euM4oydDu=b>q1X(+PxrR&hT0CAX;d;!qA8(-3!l_L>(?cVc|x)OhNj z)f7oR%4}RT4V_sh7UUh)n#j%|BTX;ZQM~MewZIfZ5M?_19cYv>f8a5WwpVN&t!{;^ zp*$^afINyXO=(Z&3>fz0Z)%Dpgx}{@vQlx8WLhno;e}co(i1tlwl-;~g8gG)#3c`v zGy$A>21G~n{>P1;2OL0*k9@m1=^cV#6o&0QeDw*(YjaJ_V1bI6 zw!W&5kx5lRvyANYk@!o0+RYyF{lhjYnB0y5*}(=~aE^EgMbsRa@%VaA>ItcbXi(xb zYD3fbmiOJ@_e7&>fCdw^>UP?59W*ki_-gw7^aN%MBaE;P@6JB` zw_ngS4`)RNhn_~m!cB@@qctJ|HKzjt1*Z*Vmk=64imxaj@En?yjJ169?PRk@-F!Ue zKlKE(4#y~;lnQ>l-|Z51#j`_#(amsudw7O8qH;ZdQ7JKJ<6S$Ve-v7koRPhw9S8t+ zk-Bz3JP<5qLyz6Z>?^Lh)T+VjBiS{0;_~%j3{1gj@`8f*kcR04n2qJt_mxd-hy-)^p3O+@Akk!o;GzF-I zA)1iXd6GNW8N8{w3lntm%*e~#;t$#q3r;~-Z4BZ}2wAJzFC>{yvwip%`W-a|+|3t8 zEM4vUt~DUX16i25Z0DOJZfE2DKz~?t;PF1!28?rRelfDv20H^)g&%Ts+}Rz|!HZa# zD(+ODe(ifl!WPX8*n}G14(Sm)EtuoM9u<(;$~UZ|1B5*TMKz}T&d^S&L?gd-B29h- zCO2>=mb%}+2kY4x@{@D*u0h%|H({BylaBD$H?P6ybYmHw&v#oqDL_>roiLRQz~HIKQN;I`#y-pCSOs=-3Fog z|ATaklMbpQwK_5E)Iat9l@8!<3jedYmgu1^LmZm9{6Bfv|L0>9Mi*&~ZcbnLYrexj z^|eCon)cEyiho}d{~TaW#N@lL;~Jv3Esc%ITAcUr9g9J8?Zo2vhHu;m!@Y}N*!IK! z8ao2TKScJ)xM|xDfcZ`r`kO6&$q!3UL$wb}wk>?g9o4Uw(|Li9{S@Ehr4VJaL_GmL zFgZIySwP{fHUP{HN-=fbi_{BIhr-vs4_cg15P*|!rp=Pbvc%DqmU6BiaxElWI#-Tz z5A~T*9e-ze0eRLot`ENS>Gh!nJm3qFUs(XYFyxM~){Y9zM&aHaa)sun>{E@)~TB`{#<@4@UqFi4Tzg zO$$IOar5XR+sYB;<=X+8h{;BPE(YL@Xnwp%wDWk~vULCx1n|8})DTxX7b#uN{UQfE z_t0Dj@FGAZafG$VOS8{f4tUy@IAeey1z?NVzQp>Iw(BM!`5N+$uS60_i{w`~-)v}> zlRJKQbp2PQv@Wu>eD{L^dAG7k|Z_4Hc3Bvcy$hu37Ev;9O$dcw!tgFjjF%Q71pFvfm24dx@ov z{Wj5JW*0D^MrY@fYj^emZK6xubw%N;fbM_jy#uO6Z~o$}8&?JX8dur9#x~$NFbHJn z^QMWwUxZ)oz1Wy@_%AZM?#0Jpcm4O{{?A@JD2X(cfdf3QT(j9nw>v<3V0iMY`E|KQ zzF*`9ygBsw@ZU{_RcUr@k@~Bd7qu0z#EA79?`j&jJ@%L$P+KC9dw;|H!QadYGs{u* zTzvjDGt?=dxfg8x)pDt^Fa@2(*Xz|NyZ>ftP!d6Y+v4lPDgGM)`=)JhI(8!ME->MQ zaSLdE1_(7B{I7Kgk>6wEtRb5g;3w?~P%_9X(Xtk9Cs5cr()h z-RH!fmvi=`XJ6~7jP||@3oXNe)r+15DM7odA%{jWEmU@n__1lX(`|CnaFc9evUXZ zZvLP~cX3`)+>(`>ekyDL%$f4b?SmSbwAW#V?sczUq+@_@xB4nO7gX2{kbA=ng5D4~xrS?4je0-dDByVfVA_1>^`oOtA`lnV6l?TWF@7}9 zb{k_5uxc=!u)`7y>46Hj^g#G+dT}&oT4%0-Z5D$ESvdkmF zr#6Fmszfj-pN&_Mx0CL&KPuc$v-0M*KhB|zB5%V=AJF%AAq5&}Nv)_GJsXiL$)Qyb z_eO~wX`W;4hGozk-?S=!N{;$qA8sN%vtyR`x^~+V??OeBpTipV7MxllYC2n|MkiVT zMN(l~gpu})(uPYo8F+TlDj`SzWtHP!t+KUe=e2`!WiZY|zMyeuB=;7$#hO*wg1dbm zoA-FIl&&P)CC|@sU1nE;TjAixio#=|w)txZ@+WEwcK1z7+^=L;b)|KdoWsFz!bWuW zP%r)0Ak}`PM(~6+23_Kx!|96?QW!%!pJ30df1M?=R#B6XGQl}W&uThN=W=Auw7d7o+hTs61hEEJeZ4D$}0S5EUEoCbaZ>_?C7=ubiTfM&^=g94^ zUAHRec%85rwJbT|j*6V_ijZsvT8gNAZfQVwz(eiL7_E{go_F~@ZAbh8D z35|fCX}rLWJa}yj3ok&C$?a`Mc^{Qd7RXRmNM@ZV}v^8?f^tQ6l5_HW-6KnUOu_^!1J&+1eaP+`2Xa3^`4)QO+dFR`QV z*G5+?3qg$e+L5(j!T9Zm45PaAJR}c;E3i2z=0%8FBwpe9`HVq=hF%nf^z_UVLiM>v z&=RAdYmhbpw_Cu4+uv!Yehw+_p6ykwN`+R70e$I>_M%Wd?8D?60xScUUB@<=q=OFT zIW+mH4&3P{_{Jon?9h6!0**WOIu8n7I0px0qgO9p;UO<2lWGxfJz)w!pb6MezgaFq zK~%gmvf~z5!wg{UJm5==+w?@Q+94X0fWaK@%FhOkV7PQA_HOo>{<@$7z2K8#r>f%U z3pXFPV9I`Jb|;(ZEl_JQGEcf~c8MYOR;d3UJ_Op)HZOMLkQpr5M!HLyhIoTdes!RX z(r|5uiNaaR90@fGRsLyHfEKJtvySS)<%+mlz2Fd9^c$H=HXs>BBn311Md?oPw~X} z41S-IEQ;1SJ4jb3f_39b=UAVIsm&JRxpd~K;!us_ORtxJ3fY+5@^XSnskZ+vJr zq(8bt&!cQit*6VnEpvA01ysNVP3xg4ZgIT0GO?9Cr3NFWCV>v>jY3djI;ta*yP3b zUF)&@>EKw`O(2@7t@@ai5uq9V(Huv(hvf^y-Ryn1Q1B4lL9pvtvC^8jbew+O zNfrzOy&@o+xFqkPbY;qpNWNsHDp#lLgy}p_t})T;TVv=JJd z`>{Y2k{XcUSyGGpgm+ zg<=G+*(-s>PhP3EGap-6SVH;a>;+jdA|G=6*NN*8!}_|X%${KQA|JFB-|-UmaO z8YsDwv2)ZoC<**kE=pbk22mzuNM2AYa~!=nc$OC`DyrKR^c!CQjmtL8Hp^wlZl6paNopMJrh9PGxh-HEqRj7|y9Q^-yte7}3?XG8zz{CB zR%^S&8S-oJt6iTeZS3xHF96u+d|30wFwD%p{!1@|seo}^4R#=xP@aq=pz&+Dh(4lK z#)Jn-z8WyEncBK6l-WSU7CXv(Ogt6jDGn@Aro5yJiv7pjp2A)Nz`*Ph_%KnJz^X92 z2HIh}7?G}Y+yW&KC7-K0vs$dy&m1y*=n)gXw<8;a_|b6k!l;XdyzL6mnwoUiKoZFy z60ahF-j))V!S;59tPbkxHNPLUy}$YMX>x5`j`(mXv9Li%=Ty?M@Z+;V2q-|nty|uG zZd6n@*oD zndMFSsyhL~XM4&g2Wu}ZI(Wi=p~;x~k)>_sq4?=Zj=UjxIpF=e9{jreSEqS5gx(rb zL;!E<#>b`<7C&=Lt*Fq9`{~^dN7v_{eyr7nT9vRWu~sXQwo)(~wif*UP~A*XigU}= z5`Xu|_#4tA>vuYdtpUcml@qP0{c>j0?8^kwuiZzKnK&DYiVhyO@L=!QQ$3D!mC&1o z0E_$XsrIE>G**>yiLC*#;E`WN&!@VF0qd->)yF&+4LdR5D47k{om(NTDapl{bz!Fc}+~#hBs0J6i0sMph_ftTUYv&{hE~K1a9yHL+m3*lg^a{MI^nxPW!C$te>LDDD@EkBKo}(V0P;w*z_Oe z0ol{VA)%M*GoNADtXX;_3y8&+1h}(m&@5ZZJf@_eRWC-=kDxO*!jx8HfC~X`KyH}- z?}eESLjFwRxDI5mJZIgZQ&hLULx$G|DCawlhhWs5xzjriS4;YfO!_=*O^_$79On|}?@)zq-yO-r@VCr2GTo;AhOM>FGm1?ph8`7mvNzYuNkJ8R&h~lX;Addt7HJKs zOsGcI_Us_LfDsq0%B~=1TE8n!2*}UPq}fJz)BD(pJbg@Pq;6Hl7GSe-IzE98KBuTy zmt3qfk4&Ok&o&~;Evkgza8?|y_M-Ss9DfS5ma-e8`!5A2E>%GP4Uypge+W>)Z03Kr zoM!=4;p})d0INFwpnDBN`H!T3N6P#^@>+!cs{?gEOIn5(@zUDtrI-2qlTlme5k3GcyMC!Nz>kI%AHm~Z$NdJk}!2mue;OnmZ zz@j4l2{@VpQ=)+X9a$dEwfHCKn7?sx*1OzxfKf@~f0KAIAoASW0yta=F`hs!u_qtO z$y#8M=O2WU<{aWn?BgTi<^{5ML!V)RldyTTrK}t;PGnWu#YfCD;-#BH+e&34#R6uw zI0LmpWeCb{rwk)wr*WZuKk59JYc~9HSn`f6${pc1Y>c0^l%4Z9ZlqVfl;?yR3)7HX=|;TXnh@}U{!V>saiHNYpYvZV zs6w7~peO0uG{RwiA@pEILaUX5tp4#jC z8{_rvxy7VewfN3Al_t}k8^66B4RE-=l71fX`*n0@+N@{abEFZj5g*;HmuZ+elKFBt zhce=iov!fA@@g55vHZ>uimg?b;5h8;dj-ocH-arCJxE1+Y;~^3{5Ek^M={v%?R+ChcjX?7YG$6BH%C2^e8iXJXY31^fqM9-$;@?)OcCm zAAR9BQY}O?9pcNijWgI^;V`PzB@5euCX@R=?2JHOfB&pJZ)kuL;tDgtJeoF$(JD`& z%tmO7Z&S6}bP{eDh%nNVftq>+?;2ZCSp<~kTn{$LeC?=yg)?sgn48pvAvog=5aXVSm5xISX^wuBO>~u-Io!W#o zopu*FFFRWoxXG&jitVlB+Zjz*0Ry`{w-eWdwQF%+c|!4V1gPV{i{-N-UTL_v_u&ih$vVRUCh&tpC94%LRlx<961 z&_z2F&p*u@JZ*e)*!XDbu46u7`|6sg&a}8|bjL6x_#U8R|%1rh0fboi0uyEjttyPiqAuYHp!YW6a zK?7#f5?g(PHqeWr`E+Wn(++g=wL5H|lZHPJmjZkvu(9d6ft{B=P2^6#<669FHpAs+ zL!0h!Hh|q}wn$r^E_0KS*52N9*206h#&fi`NPuSd zYv^5!zdl5e3qqK6pwqgwm-x9QDp@cu8-1%D5PFK1_-Z!gha>yA-0}83iXlOhv}aU@ z6=7$GRH6tZ6*=sRU%(ofw++Z!9@2(gvvm(S4{kcysFTsbB^Xs$M>pze=EWQA-@>K= zSk3#m8-Xt-YEeC~4<-}6A{BUr^(^Cka{Id5_Suo06eP^aW(_N+p&IPy{?{uCN z=obkp&oJYtwMTU-XB0~#eQls0XAClkSc$~Fde(3;#WA&8f{B3iBH(#M)QLq*dBhO9 zGHc%WcgUO;1XKf%KyLd2VQndkn0VuEsaBXIdD48grAb~hSJhB1;;q4&b&VEfAz){@ zEEI5+$)j|25G4uRkA@wkjO zpz8&J;n(5sE(v*Y-|DE);l?f52dyOH*uu-2A84%DCN z|7D2V3wGr_Sbl!RMIDdwWrgxsrz_)OLc-8n*MXwuVJom~)o>Zkc6(P5Hkm%T9pBk_ zIX7)%keR*CiiZR5!`!{>^1RxP5_B?Ikp?27^du~j)^$O{?~i#{pdBJ&!9WQeo4p^m zpK**PdH@LB?eEx|p)o+D`uz@!cmXNxp3VuW`U7n4JuK>Vf9xbP+6a!fWkGV0n1DD> z2fTxgw`uPUS~oR9**!2!oA@kh?LX3ly-R5V*trX1P}`Z^rTwA#YKN`YBT#U}vHFIA zwjZ~24qmz7F`K%H<|+>mQU#>%o5~rzlbV{=k{ZWnwIcFA-?+)GSoTEvwpMVIst3^Q z`XtBdKUtZ?_y0>Y^Zg!eaXtk}*d5{z)Xz(YapY_|81`f}AoHQ(82Tjb+G`(q_ ztgV$jSu$r%pL^~W@hw^B&s%6oi&yb;vO*Ejfl z-I1J7akxR`dED4`@HSK$##=)ee6WjV3y)+0w!5=w2e-HW4*MY4PePYXNCpytdsUG1 zeS{jrIVUn9Qp|S}?_zh2ZOo=cp$K~5Ms$tlbT!+}q=H--c`!KGqV7@21^?SABfz!k zOSG8P_%ZVSEY<9npkVUW@5+W=tJPf>Bj3l+VyDsyRCC-}pIDi92WF*HpC2oKLUg z3aEae@%fAH2@@zgP|}4`c}-YQ3HLHSy9uU>=DvW1s7X^1yCc96t;0QrH%7U0z)`Cu zvXa~Q+9G9YcD|nwXaTT*l%lqr1%`qJlk15(!O1;ypBQMqHGd-|>vdCWaHMaDENO7M zN_9XG6Rvi5y>%*$#?tJWcZS2j{h3@`$s?{twta>3gi2(0gCkMJpCRVsUQ5rzi9@&w zS8jSqE=S}ZDIUOlU$m)x)wF)tjc~j1Yl1814s3Y4%n~=SlR?AR^?Z=Cskc|y^bX*Tj0Zb_DLeJJTf1|CgmBS&m7$#6jYXQ$lR(491CpO4)$oS9D0DTlRKMLI zt{8?e4!jyM>zO#YJq+hseWBg~eFI!)=kd~)E2{xEv+$$(n`eGrXaY1layDsD0xSwn z#(LhaIYX3iV)Pd1v3nR68>2BJ(i}6eE1}IgEP7!4p~|OMC|<5ih|0P_j1p@jIsN12Okd@7B%QA-wfs`V8_?vQJQ_lX3$egxR+Ek2dsrW<|tC_s= zcewbzW6qEYbFi`XtTPJ8nPVXl(vHB2>JnvPi?oJIb_AIiW5fH~G{tYXUM-C97NXQ^ z-6ljCB$}a6cUoltGXppGP76%4y!%%!Tngk5skT|hjd^07nTK{m5`~Iw=UJl=m zOib9lBFNDG7J7N5lW8;bx?F)xm;TS28dTEcS}A`79k*EieF%}?wwOsSmh-3`3N8%t z3^%6>6Div#=P6GtdLk2kDxq9FXMQZD;CF!Tn*F!#oQdYUi|{f~&|}y(8o&3*c*yG4 zS2xT$74tO>LIHGW{l5TUMshqXrRxQ1UW<)f zKjv=)<|;M(8!Ge>vRLO*mYTo<-ntc;S?8txO$Yy1wq%)Vj*9UMlew0%zIb5i=1LI0I<^uIOEb>CC0GHsf#Uih4~_|}oc?o|K) z;q~8W++s89VoTuv6l}aXJL0hL22WO+f1$K+JXcYU25`;(ml)#X-^H>)%W09@6C5~( zIUUaq4~_dHbS}e)H#mD2GCzp-UTCyj&<~anzf2m-e!)Yd>f(rY*d|@u0LuVK?3e=i znLXsh^lW3i08i4^wU}>=Ya8NXo#EKbTjBq}jIKOc#Ebxdl?zgh4L0<9zc-F+3jtt+ zsb95JR-?2OB>wMh7dT1`f7&;SPXzbPc5{^Vlm1pw1j zI51=*-lZd6bKk;|=Ol<^{6ZHF$tokwc{89IzxU=E?8eP19jy!@`i_yb3Z&J0kxoNo zCVrlUpExn9i!iWfhI>|c0B=73CG_*h*e`^(s<`@4LdmR0O!a~3wFumNzn)40=R$sW z<@Kaiu=p0+*{6UrJT5i0II5Qx3znW>K1ZrNnAf?)G7f@7gG$xFCSxXj?+6jX{p{MI zj%?THI(}g7M2uDr`!L)mFQ?jbQ!S>z)|)3P24Z!Fvxb2Y8{i}X;Y8u&#X%e}%cRy1 z#Qg9YgAsy1ICMn6!A24tJZA^3ko63>4Td8R+0QiGsjryeaN-uC^4(X76aDO3S+OZ5+_F5gBxz{GA_1F-#aGmr^LualImnG+9 z!W!c~0MlC5OF+NmO}~Q8`e#s%#@OExp{Lc9{j*TvCVFR2@;mr(?SfOHfhb%cDjjRl zhyXjs6D(W|Y*FD9hm@DIa|O%qg)|AhoQVXKtS_(p92Pnv_GlFt!U%1Ln&PX^XX(QQ zPNf6zmvD~=X;1jrvmoSb4&6~X*-ki=-njewv?O5(LtRWuMyy+$x5>>C64Y`xD+kaD zjpQp->N)JI)}vaGZBeUfX*9h9E^i-Ojiby%8by|Eml8g#o70OY%^p>;`+XL=gQTNZ z*uP!%J#D9v{T%GPM=ff90a=nmZWZW8vsQ(lH1<-v`X6#Zba=F^ycTR-t?*Ky#jKsFyoqAB-A^UzVlqpK-vq4g8_(y4b!#rQms*^}! zp?iTCHA&wgC?)I%3WPaLg7kcuMzno+;cU70l+2CYP2Fm-4Ff~fy1DABF8)!%qwL?3oo%?LOm76x?)^Vp&2k1?N)9_)rzDSEiSHP zN1)6_7anoz7>ihu5Y+g{s;FZeApg_mR!m6f#jfeDWx5{N2TnV5oYxoqO7ru%ZE|{R zG$K&ra5CKICZUtcU0kS!P#7t*bITaQ(H?ouL+_%gd|;r(o!*l~(xni=F~)g+`u)`V ze}oODuuu4S^$ELt39}l?Ff~*bO+}}|`lBHYW9Y@{Nd5ev*kt>_1VJ={HhLFE^d(hT zAoUC0cqKHkEXqCov5+nQC~y=PtKY?wF~NtM6)UM|?$4X+wTZk7*WV5d=mK~J{lI~9 z)F~gyk89+>ei$5dVhi4h9SD@J!AZ9nDcaD!f!Z3S%vN4B7XHe&Zn4CT?%HQ>s0OCJ zPTFjA)J*dy-g=duWMX6Hfv>ii6yAZ_j!Euds$U;*LR6qLH;#k`)_>d)syU|Z2A9WJ z3xn)0ww5V6O%vjFC7ho2wEqJ=7TFM@l*}=YLB{9~rBA89eJ4ZkH`Z#-Re!eFbT+HJ z-Zvkm{Jmhi{wCP_s+A9y1e?gYyrw%Tp&J|bf$*nfNfOd4cL=Rlix0^!?Sb{wKJ&Hc zyuc`_gf1z_fTB|^BrF0MYnl*Xrc0tcVg(!BY;K>)PsZ1hRy(9S1gE7$-8vQ>a;I+a?HurRZa*6VO`h zQ!O?!l>QKZX0NxMC3OAV)+b$91HmTVUQE6~2>}DS0#W|&@h$3KTQ6z(>*D6H&GikP zDCFLh<>2D`O-5_hq}7_AkNge4LTor1H{RRWz`3>%v|-V3gX_=v_wIp0#|m9ru6jY} z3U*^6a~kLmJrCRt;G=%>ry#+3WebvMpR23meZp!`e7HFEl(+S((2iBepD3uUcGCv{ z2g6Ge-RVLGT?3@Gq}&A%38`ksyQIFki(>&Zsf{VMv*(7DYF)dw;|pkqIMtHU*aqE{ zBuKp{zQ7hnz!Jq}uO$Ww*=^9mqcP`cR4aI!G=x$;HTVxSV)$aXmR6tto#s7 zd>OhUV&(0GV*u*0-2PdntyOMc2EN1jI;3%@gV5xFdiJIaCn*56SOo^Z^lNkfjZkNV zC9A00Nw4(p{{Sod%T|T-)aD^?mF!i(e79d#YcTaC0# zHYtMc78lT*06>lKJgKd^?KQ_SdZ60(lO4kItQ`Ra_nCWASy?h*iX1_|SeeP8j&z!% zY%%zPi<)EAPnw?CHU6WzwchbpbvyF1C3|_PHtqKV*E$OANBwh_FT~1guD@fTy!qbX zu?-|08>^q5??on@UJ*0U^pKCrlB%_e$CKPjMK&(nfS{xLj%pMOUU@v_6vFuk zG+|d)Mo`eZ^o_N=V#El0n!wlrj2ZHhclYa0n^o zyNzzz!ldc%UjK40L8>FJnvNdHC?W2dA+~bn{s(z)9+zbLK8)5(%Q#J|(_)KMrc9Pv zZn-l}j;5w&ikgZvshOfUinxQVQ-sADO zRC7{#VGq+tnE*+G2gguuIo)?#@z+!Q;~%HksIX`y&Yq~fX=c|N*pSB8U-|v`__?i! zdCBg0^_8Ko^tW;j+N1d~W05Ng;-byprdk&UQ<AS&cc=4X?G@as+N2R#?p(gmc)gyW}fV--7ytk>dFI} z*+pS1V+@XwDfcBN@sHZ3xBgAr4*hoMSAVGJH9LJ|K*iqBUH1*GXzxq)Swg1TNYydJ zvnE~6KJK<_jgA3wfw)_RS6v!y5X1M^+B0r2rv}tR`oS`%J^{EiZgok8J_gQ1zw%8HeJtAE9>;A#T zn+4=Zzm;uuzcxl04+@y1EVAp{9pL0-e1pUV7E6ogbvA$Woi$|qr$C`R-C&D9C zL$hP@PL19FN?YPK$S08wEng0cI;@yu;PJ8kSs=t==kkIHkxhRpO6$D5>NkxI`0_{2 z`y%s;{EpDZ6lFKR6=N#O)_zNbu{5BWIJW?^k(GgLu21!D`JXHOjwB#e=2|OB{r}{R zwl8W$%7cq98h1|rvJv}%-1v3O8Z46{g(_kQ-+rnzP`gMrQJeTJHK&#?k`FG+Lo62G zZLB@=bW1f|#MOykAcy3md7w7%KjrxVxXIK9LQnq@H+5NbKi@D65cm)JE8YGG z3&dct5}~|@CYk3gxAFSs%;N@g<$59fPL?)C2O@QgpKlFWAk{7e=M2X}$Gv2n>kFnMf2E* z>gs!~04E*(bJo^s|4)2rTuIL#@{r*l2#r9?u-cKS-I`H?PRZWcfOI8wwQtc%DqfSk zyv&0HwzVF&e26;HN!Th3At5qq>O15QVrOs7uE(wXtLyh|(nnOL0NEcK<}d8fbK?T@ zP5GVo{a{kHOLURfd~01^Y-fl~&#_&8ZG35?K1#|QxO=tXZvw2)>NgKy78QZwrz8P| zy}efkUjt(qR`~zTB_IFe-K%u8=@Htwb@x0!H2&=<_J0C7+6C1T-{=YAIb}gM9GH`L z4vu$%mfIlb$wEJeQPAZGOwPVh+$JVYdm-fH1Y@#n`XO#79TMotnk!X@$v(zbAbdnm z{>;w2E|@U&ICR;lvbosN`n47?H3!H>Xr`!~VR-Y(mrBvBjud{m|Aq@~)t#_`33U7p zUh(X^8d*ra61R0)>)}lNqGKFy(rc%v0~F9ACm|-SS&?})vD$YBebAM#%neDwLITu7 zpqD19Aw^eWCmAiQMS?5_Ha~JhG;(!7ZSsWo_O~_TJtw$#(^)ySFQcpCp|uosf+x=A zA|y$CRrV0D14Z&4%)N_?2$_>e(_UVJC*-O}tr=_7RprhLC({K6Gf*g04z^$p3OIykFj9z{(q{A2}Tl)wudV`{%Ig{cJat zwHNx`P0ThtEHkzyALH46bGqf|A=u?2w(D|^o7_#cfWH2n0o!!#(=iKPE2guZ+`f?5 zg|g7!Zj5ZdK1se{d&7Q3nuJpUr)rJpQ!}`6FfKyHsey;}kA=~1U5Vkjy)Cf|k99=2 zw?uKI7PH!-F2J*UvA{>at3J)^WFcgRH-LeS*J@}7eK_qUZY)j%$L&S*3}My)KifTZ zql%U|V`LBSC-dCkl{}vYLab*Ld6F|9(*~pmPZrCBxj?=P&GCh3if&y_u566SIo9yl z!c>UJ-7NgujnB$;pTsK;i8MC)ap=x*+?DHxNA@~hhAr_cn!l+yeMx{I*RE^cbLXIA zWHsVt;T|5KxI@`*K|j2-_BCEzMAowhaV1_ik%#xdE)@b(JC%~uTB5wrZ7B0VnYJ^3 zODykP52rZDpv@(tg&EV|zWeInmqb+Q)}-&{#k1TPW@r6te$lv?k+cEEH zma68+Gm{&F8@^=m!Q>_!Mff&s@huZ*+2u(GIdi+(nvr{jP!*B zgb&a(zV2TTv+obYpqH-*&Q+{Q-4GM_p!=N^QMv!~OaY_N>PqP8C+CQ8<_Vl;jVAH=JBF22b z{sE?X=iW!_$k$~9X-x|y0kJ=tGxxsXjK}mV@3EE{Gqiy$1&26Tu(a>uS9|)go5*S( z!KEqbYO+Lb6`)uGPA!?k7SLJ`?;6|bKh_e;uW8qRhdI*_`q&Za&o?jg?`J}|Q}yT6 zjwP8>c8&D}|GCoK#P`>O)6q)WY5C<^b%Q7rjJad{M>!RClsL!&5Nq|z#SF6WkRYQb zQUz}J6dW3JEdACbbRcD7Xf9}Q#P!1y{?@h0=-0NzXs*Z{b;L)I@#EVd=fk4!e~H|F zvUUy4jdg~_;Gge~%urFmI0!q%Z=wn1w zbH0G_6qL}FGw4(CN^f}E-^A?MPhysSi*E4cXVw)<+M6aP+xd3EMsJGz5YnA0o3un| zyO?2dW%QnWUPVS>2t2WGMr07S;lgXoBcP3G)CLh|Y!}RJkONx%^Ownz8m%YiJjNWw zFRhNl>}X6Y=UINk$CjlIan*v&z%k#Zdzw*$ z6JMQ)5cPzouz(^;H)Qw5(w>Y1GODHIC--!wkqPRez94@t4>N;KYv-ST2D%&B!Z5`s zG4XyE%+v<9{?!6}x%HEALq3mO$ZD)o^NQcz7%t+8@(p)eCVkf8bcb4Z22Ohn28NeT zG8MiZjR zBWC}|3)Ip5v$DQ)^S5b^RugtWCebjzU$tXL8uF@B_c5ZC?1w2;l_@yfGpm5i>8$bM z+m(SszOOHlX)vlGJ0)kN9e}(|qXc+MkTvBcl@uOTt7=STTKjKyF!7Te9JUo@S3wr6 zzjBK&v@kUI#Dxl2^a>6QO>~-aSRK|G*#oQ5X;g6zVO9{zv%XROhMC5ay#6JT9=Yes zBL*3CM=Oko)5A}g>~Oyu0wla?VM-8l$7&`$COslyiBf@X9_{<=fqW=Or&`PT>MU86 z7rz~3_g*0B$ex#8#NCVIYsd`xHV$~^#aPQCg9(dPL~)QeNc1}|j&UyBkzggXVyh8D z!^X1r0El}45cA}xRYC$!wC7pUu7t%J4ut!~T=EK)@U%Oi9 zbZ+9D!!Lo`??zToa#S7m49jVR3&yx9!a_V}$FTcSlAO(s14+aN- zT<YGV^rz_idw5ucAVwqZ_jscX6GB<5sHJj7a=gR-cO5bpYyY$$X2lj zCVBw2s)AV8U+?lDUY?H0H1t=Ob|(ST8Pc1h zR4W&V;rs#f?YJR}hycmoA~g3tCV#axrUBzmk9_%T2Hv~%@WJusp|{7MewF^3|A16H zICZOvP_fbOa{lMXSBEn>PP+{5v_|ONarCk4HhzCPRvTYWAe&xNMi1<{rs;@@Jq|Q2 zTtgw;My`kJt&KK6dq1{-SMhzD&lG~T5ltHN)Lnmw{4`59V6>aM8@655Z3<6enG>dN z9@cvi&G(3gcgKWP2j&_GysqZS!`WGm5<9qg?RkB0GoJNqFf3^DhQw0bgl5HDXTM&& z@GPDxi328A4LCn)dv^xHaZL_Q07Q8BX?$i`{G&!%Er}oQLA|HGz)+4>w0S%coTUmyOi3H9yS+q>zl~04&J|U9ARrOxYRAq(qdSEmdS9%i zez`L+>&kwh<<+W#Ki^4s@a%PQd}idP;W+GlD~SJ{u|)=%F&lG!q;OsGmRigkk>22r zlVM(2$8b%@J+^lzy)n`o>U3w4dFAV}%xPyGu1D}wQxcBBpk>^bHQSe@js z4KEPzoMV*8*i#Etk>w8z`HRIH2~T4n6{Hwgl-wHeWZ?tmNsQSx94URG(8m=6aCTSg*&J)8xkr14YLUEKLM=IMoL?D|P(Nh6RXPxWkh#Tz zTLM+*p4NA8BOwe6sj2|b+*LLG9)6%I7K346MagBc_t*frZT4B7Fq7=h{}Ld6!TH@w9!mLT zceK|Ln(F_pH#!Clw!n5~?^-4u?GbYRvZ-xjiiR}*o0q%%=VX%c=hEujW%H1YA6o?_ z{D8BDxvW3Bl!Mcbh8@sc+=``Q}+6c_nK&;QMu_2i@omzv_mW6sMV09G!k{udb_ zr1-g~%X6(Dna)xz@a}&|7y&)!WRVrYqwsUgccSH4?lK5?_qpti%1RW!A87scuQ8_o z2E|tYnfv~Kk*Re>ed+e{WWnH~s8+tQPrtX}81}=7kRsM{Tf00mgtq{a4?|*8)_gep z;jlu|{cE{hUpq)vyVyjNyxsz%Tc7x4TrY|D#h3NwYds{|?XFg+1=A(kay^?rI2$k5 z)9D=YNF-?Wsr7+yftO|uM+g07RlBtgzXd+08ZOj@%s&ai$}rY$f{vd{yQ+i3w-Voe z*opcD-OXRFT$T%CW97?B^5ypJ0kjtg+2L4&4zs`@+{JBy=G~IG^2M=1X)QL^eq3g) zUlEmVX82cw{{&cJ@QcU``EY5zIOYnS3R?T1DqwbTKJS|0gC))~-&)ZpD!L=T8nLL+ zs+Z--&;f~-cAI-X^X|K08#}e@+KSk>fk@0k3miME2ANR{?yLNByRwPriHcxZHNs;4 zmyIa^+7JEosk+j z**}d={V4%bGlB>_0dndzSWS&V_{^0afMskRStMIqS+y2J&I^DU&G)*0lHQ4Sfoth> z$7i4{L^OV`G~bNqDR-*WE)e!#ux_P9xa3ORW(5;nI|WZCU7}fUsrS1LP%>?xBTf)H z$BOlRKR7{pALQo@p9u!Rg^e*TZC1Au(@ZpYE#e+=;pw+hr^=39q126UlY7AI4l{b& zE%CKk(!=Rdth1+-?s+2y#O>oF+Pby@fE(9T5hUqjC*{m`24UeY8Eevy>Yei66%d0x z*dP3bs6$d*U!u<{5}nNgx7v8aWnUCcZWYD!ZzrH&Eex^1ejKPD04Dk-uO90$`=cn+ zUm z+gx+ur5dYrIFu3Z?ISsn*gR_C4n!af(HnxcjqWZSl)jC2sh4-m&pmBo0KG=MQM+}& zyw>G15D=)x-}1+By}*L>P|VvKLDoR0c)`kix&?1*Aeg`BU4&O;54fCTy-?lTSN@?_ z|Cm8=ID~Nu28Knd4qAJJh#F)sSV68T`G>Sxk1%;c5wt#q_oU646w)0@>q>G9_nVQH zR4cW(po;aVU;R6d1VaHq3LG_DPQCiX*1&0Z@4>y{Syvf5-}rADU(p#5aE`gxb80eX zY`Zo-_;#PedMgA$5Od6R?R^7x^zyZtitHMbZ%7)K2F07uRZ?TNQD=dA(3(-{e3tZn zG$JO)k(9u)_f>gE@7Pi9wcU82N)R!*+r^5joPS?`F6cpKwptRKReW~B9L_S9e7mQZ zzvb1>oSGfg9X@^v-xWr`Lx=F6OegH-{)F$zDM46taebDI|v&*bfn~X$ePP4`a5fr?u3Ah zF7B#Md0?1E{wi_lEUr7 z5$}&)_&L}Lb$Bmx=De&>x$7&>? zy}LZ`NG4?N#?qVqi4BA__;T&yVAaCZ^3pQN{LOdm->iUrcRBB>^IEvU$*p;Ne|}QD z0gk#HA9%!pHN7XsQi$upzqjJI2EGFtn#kIa#SUTL`c*Y&O_3IQq6 zI#l49Kx=~RtQ)|kc3<`czYuiZ#llHiD9^7!Kf$xRYDfq*uP0(_meo|DSFrztbSDy_ zA7YqLhEoM98!iM8OtRs#kA>HBx1VqNStW@zp;>IUm6eO>M#G$eFmcptSk{;WkTC;H zQlA317}%NgAAJZ>B4+pOF5Q{DUvz)-<@ zYu2laZNA#`YFG!jt`lOR4jn$FBWjf$W%W&woCe>|ibzw3Vel6rkXzcYa8&w8^C!?D z9W~6V#K|8sJEAI0OlPzXxBrmL44=JIQB!4@RY0XqHjj#s4rT+|!6ftX>4q(6@|#>e zcU}6t`!GsjpDh5y{vyX4Xjcd8%Jej(&e8Pl-l(NhbE)UTu0bwZBq#6Pmz-oK-#S*z9g#;kBc=8;*A*+h7`yLe)3 zpCX4QFWSSin0(4xSPvvGQpFFzty+4zzzrS26Szoh1^QusHx5jl1j?ZGX+*`XrugZ$ zQxWs6n|5hPYh)MM-+ZAjy-Dbt3F$LB#~;w&S=y7lgF8*l$5lhq$6il$pL^>kjyoLc zm}@fQ14VQ%h(%7IYy~eG?11lFzSySO%sVzTv!1NQP16pntt)JQq_>IVEvaX3vBQk_ zon_Sg#NH{d)~)Tx2+4@{0;;3q>%ztQ5hPFyr_!=j)Uaz z*S~Wgz1n9|_}&Tl3c5(Q^v;#v+7T6CLW3H5~YV3;>F0NA%P5 z6s6Il!i6Ydry1HPeoxmHgkKfzF2zpxVRwX|*_aas$lVIocg#5(GGlzUE3W#!Tf23} zSm;zH+})6tXs-?$$brx$0)kRGbcP%vlc2>SIXiCNX!fm==Pup(cXW^!R z1)>iJ`1D~H(4`U(~o$BaQ8-PTB9g_v&%U zOV*shEbdCH??GJBm+zt*EqeBPOfUvkry;GQ13k*~q^MH{%L5kB#V03oiZ{^G5DyJn z#oaZnx|z2fT4JuvOvJ3Ohvv2vJD$yDw;MMegH3u(@bvwzvC;i#4!KxtR}lov;@C8~ zSb$9(>b8G@17e8XtUibkmcmNn^QD9D7W*-}=j}4}-Kz(*!Ni3rI+ReQ zZ8oNDU(r@ouJ0Jg4j^{LTEgWRt&zq4su(X=-^KRly0NcGdY6!3pgqT!qVscj%%?yG zH8&1*;abw+wMf{JG!S@>`qgJ!AGg#sev4^(;B>z^_rm2XCq&1R40z}qAX3?qcggs3 zUy<_&DdY>K`$u8R!Oe+R{FuDGZiNscW#{^~N~+`5wKXEG^kk=>Yo1*gSeFSuyn4jr z>Q_q!8?i5eX)Ri_#mTQJVgo{8kPW zQ@Nh>eTM(F$tkIuaNoOF%iwPPchQseJpc|kNgt}IWFDDoTr{e?Bs#=8T(Wu^HzZ!~DnsudN- z?s+!;MT96aG+>wHsHh_;Jk<+8y9LzKH|4^P0n-@;+Am%Xj_S zq~*K6p5i|`t^D&V0p}lRm$DA%!2Boi{6|ZdeSg(Bza@YC6IpxQm&g5=C)h6!0V{s{ zNbj?;ZK;1nRb%AxC?q!aq9TGb{;42n^WV>pMSg^Eu)md z&8x87_<5n?<$(rIJU|$XB0J{~rTRZXwclFeTvs%1|I6`LPzh+;^S>19RVTw2*Fr>N zpM&O~-`|M&u!}ucJcELW@F6uH;Mj8e*fj)9+|&7EkR^7mbYQ;Ramh187;nCoF;{)j zF(3pTfNRTGV%IK5#8Gk%K~RvHckxvF8w)^>*uQak6#~WAi=V6(X$>U|@ z34Z+2iNWPZg5-9&|8f&+lJWf=(z#YqNRRG8i8$fL9 zayqyACmUbuR^&zrArbqTFk#VvEPCi&wlfvMBEz7?5^q?4!P7p$ zRt9#9S9Q&?rP*UkACUA^<(iCmKF}_zAl8&jV@RM@N{<8OTi+*l)XzJsDC<9M*wTPi zH!Bw9sZM}lc8ug<#Lc$1B?)zIc46zjYSOyIIuW*Rg|?%?5aUstte9y_<$MOfJ|w!s`Rr1Q^ZE+%xTywhZY~2WFkd+YwpPvg%6vEz zJyNd5YTb-+7(BW!G_71Vv0WWI!|1gF6N+OOU~MmZy22dpR*g`@p`Zjh?k@EJtwys+ z>&OAx3h#|gS}Q8dn3wpsYJ9@%K+DrYrZPwuVmv%U=cE%);6rL>DY;qKinX-yU`LZR zkd#Nco(+#zUBa2CQ!EBX4_wmd>?=@?JX6an*jO^zSw4L*GibmHUDOuEA?ESe0N!8TUm`oals)>`^9B}o{F&8OIw>3XjcV+mCGz@@+5C= zlEIQ(sY^?x&rOC-xHgeH&A0{hCr;+(;p%qO20RFU*4|5F_!Ch9sQ5sL@r4Sk7LIM3 zYX{13!7OCmsnPcJ&M@~d^vr>Xd=k~A)s^D7<#EaGtKr$DxsRs3gi|A@Y>=1t(N}+n z0qFmnTeQZ@ZEg?VQ_5CmY9D;S7?xH{-OLJ#K3~vuy>ACtMSDA&t8^P%-()A6yTw9) zh^7wT7AM?g$ttRI*oC>#R~{>sNb<@il|yu>+QJs))69Yh#4bkuF&=amU()(9r#sXsxK+zWRnIwJ;02wm)9>x}_zYP2 zRXITVt&zpp2%DeGVUdDdL9eC{#H|G#H*NN61oM4js3+R7!qG+ByB2!o5MkYvGrMjI zM&_?$X3}u7*O)$$b3PeD%V%gjx)mHcSVQ)GKd4C#tfm!<^SIvI`4Q|nJ$P(#<-m<@ zp@(VzB!}i-s^;>Iuh9OkpOR` zl;nyb&qPP}@LbR?{QRDls5np76)@3|AiEbnt6LnSN_Pr$f z@=?2Bwdt>XrjoxGRmM4d5qO`dT@>@oD|z5VUId00OELvHfhh0O`Mq;AU|!MPg*f7S zHC8fPlL`KEbkCqPvu#@Xxc4{A`hKrbKd~2M&6B zPvzNd3THT)piHaHz$?ov3h42V$cI#OY4`ix7D?~6c;*0^Wi*p4io&Di9NRZ&xe7Bz1^1HOk{cD2VCPd8g zJOTBgr_kcZ&mJ5qsHIlfIm}DbL+P}x(0Xndr8SlzoDr8g9`fSr3&cItw13JsK0=Z#)yz zpiXT9A~$a?cFGR_^DyM#J*NXc+qh(2${c;k^&NJGF55JhD!? zv@y6*SrhUu6(3K`^AKR(pEWm6MZb;X^oLDEKpWiYOmG^*dvWvLqN(ClHmqDH*5=;; zpDlHf@27e-1XTJAA}ZNG`$=4y3uA-Fdt^o1r{EHlTN@rr!nNdi=!}$++kL4z)Z_8~ z#gA!|uh}75l<-}njbX(MDw)4g%gwZ;g)ebO0NH$ zxkqjXiS)EHLI*v^3O=u{;ui!~V%kF=FDUNJ_(&Q2W~ zfOHW1iBCOPze36%X_ilqQ=hV2L)^63Cfm!42W>1_P?Z*;sG-ndi5J6Z;{X&^HO_Ss z7Vry@)ykn*qSF|wynWw4HEk?ln_;xNhTzI8?Z+Ntaa>}ssX5)4?~^cKHRU4n@vKZ> zx`OC6X79rG+d<5YJ1sPVX?tSAk`y^bX9NA z@TDdF9z36-$=Feow}{G~rpd)xTiQce%>$BQy^lC@GdE07EXey28{>?w;|`D+-ePI6 zV=ivDURB&8XP1KEY|iOJg!+3GQcqCl*mxh|q` zxmvYw(f0#kz|qXwuw0E$5Ok_OCwkfSpY}>6nD$ut>!X?YmTgQu~Um`=Cy$H-b|DwQ*G9l?5RzY=7)_k-ahRskfDl&&%EnLK1ArI zQ$6|KXa)HkOQ7hQW`QZCgxw4C7u=rLBM&m#^JN`qa_QTV=71AtT_#JY3a) z3r~tV`40S__6AQo}M~A2=^hQQjQd*uPD;d#w&5^vo3B?5 z3*^MyH-gbYCmDC#$Gekj?F{L#J`4Duw6ZUkeQ3m>c%~1R-Z1-cP-LPkv-HCVX0Yw) zquX`>#xLc@=(ZJJguv(M@BL3A10D#`{nif|!KOK@?qtOkCK0aH#fUXLn00y%Z3de= zLmQOv*s+@4Nj2I&$DJd--%O4)*?gsf^JEjVC0esxM{=}5xL5?eyELG`2fYbh8E2M8 z*j;bo214Y>tm1hI)E?j;-$F)WSX*%~dB^L^A`m%}?R?X)oW|<%$_*1WD2y&RaX1vp zBXtHBT9C)2E*g}lrAbg@_@Oceq!_^tCQ5@I+k3{;E|`RwT2Cg)&B{2^ieb8O*wlNV zu8GT?_Tt7K>R~b|_a1Rg;x*Mom6IQgleiM8+9Za7oig?2OU-ljkwL>LJ7)5GMy-M+by||^;5$$def{Ls3XbwY zYOC@A74Q#CygTxKIm$S=0K-c-S0G8rJ@R43YynSr6YyOY3rd_q!u>h%0u=Rov`fQd zztR#cj$b^2N~KnAdsgLHu*58_`OgC*M_ zQRvr95l`1614q4mobD)+x!!NT`wtGI+~K@n@s&z6oS1bs2`e4RGbVNZQ(Fx5CJ*qf z)m1-8C#83w!~8vQ2k0Wj{Y!314@Uc)*W7iJuFDHP7xg9%Ouufp*NVUQ?WuAdT&E_Y)pkAU z+b|8C^tiu}M{)QXrSmQw%Mii_PZg$mLeI3Masp8 zZaL{`qivD?#fl>ves?E7t=X2%DTAfn2IRzZqu=dU+pu+;H*Yot4o<6$HUQm9=B zZ<@3$EiK=3?2u={bbxj%694f0570Jk-du{(r~55);Y;~mOY~JMqQJjMFMf-q6FBPb>02#6x|8k8tmT=Ouo+1F$VTBL zX%6q?igx8{R@(>RQv*Yzsr_mI3cc(U_~9M@J^TS60XMM0`Xr|T-^5B)5H9-9)T#49s;35>LK>f?ioSmzL$vj~ zdoygy1hk3Nn_kt%A5p#_t&V9%=+N_pTb)0%S29WKaNL8lK)y|5N$00+f(J##{K&IR zN^LQCST%Uvek}Cg032<;7-ko5dbtZzTGbpaFUEU1cyYlEcfX!7nX(J+u~zGMRljajU69o1PDT@vKDVa1@dPrS9Wnj5_?$UwPDIaAN#CH@Ri}3+gqE z_k(PZHsFidb*a-fYT#;u4U&tSFB;I?H;O6D?#n{I&?+B&sMe&b%U8LcA~dPVdhL+GB5PNhqH0SQYL0j_-plsu z`cxpMgesc>)L%p?%Z2RCKeOpV&M6j=y;M$qR z3NB&5DuKB8HI#}gNqz;70VzlRCu(&yWn`bc715-%>~CrQ3m1GRZ2wpq;9wuP(>LlD z(-(la-wcpyxxCQNx=%LFxX5(;FIFNwKApiybuhG1r_V?=1D+P}i~B}}1I>;B3kP+n zU<;FvvGpH-OvCpfj1e@NrzGc%38xk~Yba3x-?NlOK1BRgZ>*)qJn%ML<)f+?ar# z;tvbO2v|^FIuB=H(YMXAroILYxX3CTz!ivp zN?L`s`6qOMbjSaL>lNw%FsA;-Rto*`|MarNmHg#d$np*NSKh$#o3G~9f1xgzXe-gGZ4{m$U0ibp_F>#ARsh(fDvZdYD0l=GXk1yuF^;pop+R4M;@ zCbR)?EX^EOT#CH%>#B;iZt|2?d~oW4mHh-TFwgWiJpia{%evV= zt3SmmQH1}dn*r{19ENW|7T;yme!Olw3!nn{nNdPWyo?QBT;xHPXLNuctT6gq!8I#Z zfE9=UMuWyFOoSCHvK15nZnkC>);2Jgb&G;-fLK=eCqN>x&9BRW{>MH%xX>0^Gyk?7 zE9Sx#%lx?J({c_9k^##t{JNaN!T=tg!a@P|a^Tm!C?e{>UhoPY06uK-Klb4oS-%iF z-IcpE*YYt_dg!bFH$eLvUgCtYgR`U1c2TChCR!FOs2ir?t~9vtx3 z^L1}yV)(gB6S+0O6i(ow{K^RHCI|z=MIWh+`b6yy=WBq(;&^rXE9XzV@$IKQy&5f` zMFoCj6NME5tdad~Tnzss%iAgbJH-4IX_plfW^=cA4lapl(VsqH`RgaH{qb$T@p(+l z?SgW}mfE-vN7L6_R7io3kAKuEz|Q;iiBiG=`%nlc#iR3X^GT#aFe#p4b+gYtn%oMx zWLb61dM{us|N3Nn0OX%S7%86VEvkSV{Pdyy`@LVN-BI`qAD=qA|CPUNaWq8U6M~th zQZT_RkbK;_mNOQzEDnjMFY@8b(teW#w|J3TBzs9pS(a{x0Lj*ZW=o%43g4&Zun*Ou zM~hlZ44T`xG_+ArzR*7?@7KXDj({@!fXHcnnDlKL-b2ERU*hFX-WDO^Ckwo=6k(Y) z&J75Z#Ls}^&!npuNMJ6qiDW3iKuZC1m@8&8tvK0qQXavAn%(dmlUqS=NIiIltb9L{ z@@j-n@p_Mf7)A|#I;NBX7n64t$s7331^qs{4Xc^6_}sLpXzHaHdnb118^+4j>JhfJ zGVE=?@YjJ|J%}&%?{E9W6T{$<1Ls?eN>A$+c!Fm~Ed#^8Zn5++X2Q}+nX8e?^uY4^${B0R=)us;W@PPK zx9k>TkRKAC9DJx$W7d#fZE`FWW0-D!CZjyT&kEY#=gl+L=rx(eZU%h0Py7uzYrj`> zWR-#AdGq6?{gwsycQ@#I;*Xf;Y-+KpRC-1#PhmQPqIENHj+)0ewFIf)0w}^q6q5n7 zvzTso79kp*habpZd@X;p`8q3+Gu-I97N|GP0o2hXA?c_Zy#%w0=t;WoKQ<`R?qeC}JNZdsTo zf<0%fuikB(y{4twhsF{f3^^=u>aN{4g${cGOeA{~rHu2jMu9Eosz^`UPO;nszfLWV; zn&RBnhIAIsBz*U@8Zh(uCcA#BJUOx(AW8-Dnf-zZkXLQ|#u0`xvDQUO#zml(vGP6D z8N&-{P?aK|o7`uxD(~<%=Ei>hT7bDmJ_?*+@a*G9n)oEVdr_047YJ;ixeLrTGMRf_0qE!yv+^XP3Q^%@VUu_WFVVg_C0fU9^$ETFxIsluE7bi!~RYeGxY2cyh z-Svp$z@~Oj6l5>nK{*-~M5fPZANU>!4``_KL-)7!^6aHKLQn@6g)0tQNB-vGcmnvvEYV zT`fh`N1g6UGQp_n`59-=Jj?}aa2UmGz?yxpzxWWy`F(qoR%1nfx|;kMG}7Y6!fv;* zCDIn%4o#J9%K2)+y{2tZiBfZTJk#I~We@e>5-jJ$F5x-|@LNCQ%iEJ09%1St3UkB4 zG(nzT8Oj;`m`)X1zsZ0TAO}Vm9fq$gQYX8JUJ<_o5rm9|T8&}ZwhsUe!1)^(6$&u2 zSM_Gip_L2fzrG2%k{2^l?%8zH-9d&^E;pNQ!_#{QdN&kZyU9wbU`2}48cbunO(m1f z4PUpv8(($IwA1nE#3R%W78lhEbL)sh(o%02YFwQ$R10pDy>7bQ8!wPWahL$(%^5D4 zYPXCXxW`V-J=yGN(ihcMh3j34TMUH-IU}vHnuxjz4B$k}-$JRdlFARViuhi#wuBe& z^H}kR@3SLDy;G+bn~909ZTyNx1Y|u+%WT$1#Z>25uk>pCnjQXrMUDm}6qDT@wf}2c zlWcm%-C`Hs=jg+`_;vk{b<#s)izAxNGH*9zfP?ZJ&-7N;JO#+oG22IXa}(h24K?vK zQRi)uBD~a0a>8L|^dmrOJVP3aZ*q&TAKK1#waM<)kYF4Pxrhghi1X1be3GMkeR&~h zSd4viXcw+Qb`$d;;#Ik8Lpm+RL11y7Q!|?qqacj5jq@aX{OP1!&JFFAb05zTf24yE zWL8_I>ErXlkSOzzQOb{7)-8Ne(TlzY4;#l4JP3{4CTj&ik8Ogp!yAID4yWVBaOYns zg<)9`jVq5z6D51V!J)%@G8$%PQj|Qo-h)kUpb$cdMW9=TMh_FO4*Sf$J@;SBx6xD#kb`eUC%6i^XXr__;px}6m9#MjM769Nr9sG-9kZL;DJ9MB zBDaj8RARB+C~$Jjer36`tdlPF!NUh!180<34L0`KU%X0)%>Fj|tagacXX=o*4{TtZ zn%JFc=?POw=-9z%-R&(9-5-iMeA9)=kt7VJ4v^XlvaqmtXyC9aErp(|NzG~ICRD%X z{j4W$O+npfPasYvmmlX<-mhpdd{tg=`R$@=iMxe{pz2h8Oc3_FZ@~UDUFV@Q8shIc z)+NAF{3ub=XbTE*9pGZj=ya5wDnDYkr(PRFW9awVJD{L!PAfLr2V}&C}+;ouO>~M2Ct$IL=`6E#-;8RMnQT zgpr#}Un6q+RI9QOkO`Y%?oyi`GIwX55Bi{*n8V zv*tNpGc9};vOl~;fF;#1q1QEbwfrLV(JQ`CKsd^h#3^UK^C3L&r*=e3cpW8G?VC#ntD zt@ofuEjkE@hK`~^lHx?RYjE^O8(?W`aH=P|9$i+MK8w!Iy=E4s(-ejEgI=g}V_v;^ zlO_4+IZWe2JCB&WyM=epRNfe>+i8Do@$pr{o12d2bu-a3HE9B{{4Q4Z#;faatnNB9K+WaSPv96Rfy9i)D#+wTf-;muFDrzb>Jf&AN zESRim&SXM9(d)39b>E%b`6hIoe6$AW!Ti=bcl5TSO|bbpHB_w6i-UxxRU3B+bE0y& zGYgBhY3+`;i*V>E-V%G9V^02XQfh%GJuc^>{rt>+IRR4cz4!fohbB7m;JS{uqT=zaIJB4N~^Nm z%Yxi8MTK?}H7OYGs^0WcI87=j8JX&~G(>i((4xb`R4CWAP@ZD)QQ+>+fQtsGgl7HV zsvJmFN1C1&$-My0*`T8QP*>H5DKR$QH;X@}OU8)``$J*xU)rjtGG?aTiRHGU5DvCD zZo8Vvh`|{Wg=06SFrq7vExk_yG5Lb!?7JpmT5dcDDAr%l5;fIap`FzdOi%k@ZCNMz zonXUn>`y+8-m)E>rt9EJw0Xe1cDP5){AfFVXwmnKA7MNa-_P-8+gBAUrD>$*;meGg zrlf+`BmKHPER`0Vx0*O50l`5Ecj7&^wbYe!(VhStyjcC{B1A>t{oMgq$$9rKy%8R@ z*({?>$~0F#MjXtz&G#`ket2K`z*(SUEr@@MR}xrEN^OLt+B6)?dXUfn17HdCpWDjQ zMb`QSIa4i)5mYdZ2Lp{)BJS3EE&_5sn?keZ9)%+?geFlo^5x&vVYWL=40RRmi83hl(C_&)6G zr0Ue4{@vjD@8F4l+T;HhF$NM|URf(MwT!#WlvA^ywR?xF|Bv>*JRIu&`&$uhlC+3W zS*8eytb-QCAQCfV?ItA}%Vg{ZN!f)&Wyw;Q!9+2ZVOoX>MQDud8L|wjXcQ4fR+w%5b< zNgmd6MFtgKBg=>TxFP8U><3i>6zrpmaX71!VC8?mTm7VUm-Aog{8xAWA6eFA!lpb9j+4<4ozrIj z6DwPsWDI6}U(6sZbW&>OYO$+hSX2d9KXRvxYmI*aM=&Wxc9s7f$K<04Q85M(9vMCC z-#&FfhI^*TI}XJDDz26!PU1BNz>R=;iwzucYp4*oU3;tB{XTtyN{uyU6o zMn0j7%5d~6T#E`KzJM#GFJ)^lWgA0|#9>fW6%;iJsAhSR(Jm6^(TV)+ySG2?Hw2KV zPZP%R+F=c6PJU+>ejLpoDt@rbk}&U2n1{$G_ARyJYPttRgEa3nm>)N)lKU6z0TRd& zR$5f>;q6dzUv4CN$0* z4bbopeJdaPx_PC0Y~hJ58ffY43GzeLQ)GH^ub~{4m8VszIK%gSitio#@fQ2qkKS>6 zIHm;I_-k?DK$Mw-Pz+?H(=H|ryhFT#iTa(a5?wzH4(S`#uT&NEhIy9ghAQz60N0|^ z;XI+_Q!j)^pzuqNRG-cwWZTr~xoBgb>O^axY@X$vRB)-JiRql-@dPhMnYi=NQ-gWy z8`r+#fp1l$tsFklUk1b!#xXv}o>IOSs=Q0>zf`gExG%;xnqpAC_diIec1S2%%~!(S z9<-x%g_yKU*ZK={830}aO1+H+7Pp*uH2;i1 z)p*IUm=11-U@cI}KcAZ2GhvX~LWGxOW%TN#lE=8X(lvJ*RNKv{g}aYG(|yP7%`)mt z&X5M-mD8Ai`x?5a@$}Pr;t+IKJ*P~PV(+(G61Z6fg6`Dnw3lsq#xVh*573FJVB`9H z%@qkN@;#%3eEI8P79KM_4x2c@b!;~`2b~p?!xS6VxjEGqht};g0w2xKArwY9h$WMa zzsq3;Edvsbm`CfMAw&sK2SLhkne%cyS10Dd^=t#7%H$5Tk}hWqm&p;JSk zq{HO7y5-nVjbh4kS*7D`UcSNKyv#UpMIyb|B;Gtn6cJi!zpTouIon|u;hVR^6MQ$3 z8z%CXuKg?)uV!(F zU6~$t8@$$+5UmA~S1KC;ASgp?Cz~R#r+b4M2dRfVe0r4fF4>!_K z=euL^)}9j`&i?0zt}?~;nFp^c0G=n(irgkLwfKmQag$$!6R(1IjMgdpR($D-BS}bK zA5gaXMi*vITkM-%JMBBg8iNMtw1Kj}!l4>}@F@2MU2anm=w;36B1dvI-6$N%dFpbD z~K6C6{HM`dU9CY^|A%;QbDgxE6iKueF$j+fVy*(eF{h6s}c~bOF|)F!3jCWUnq#?DQRU{?@5IfVf=45z=1+YNoy<(wx7@X)}jTBl*e?9>lWTkP+S*W z&FX;WcFMc@Lg^iEN`Z5;k-cjZk`fT>HtuL$q_6B-&?1>NSEm)pYq`&%qH_Q)8o|&l zyZq?OB!eGFd1+U-G;uT++aIR~%=@%fw_$Vh(L?8rouHftHN$obs4P_*^g4+ZksMjE z&sUrJHhonF4l{FZP@OC#OX;hSH3CE7o_(H)4FLtt$zyF^`;(X)W@tNd)1!>eU4Jfc z?<1nMaDo-R@g{@rtT4Wn2r5w$eUJTaDVCu}A1I`dKwn}=@+DdNt`Q60Y>Ui;%&B{R zmYmHYReyxajKGE|j{?CD8s_034qd=b@RkK5QVQuiZ?tA36)qR_VFn8?+N*>7XLRqJ zlxnFQgFrGN_DL7bZEQtBkqT-BEKFd!(^ziov&YArHIhvH!Syp<>UUR)Gxg-K8J%t? z_nXzpQWvCu3wE-^3Utd3>1+*vvFB{7@CZe9+M1qB}UhKAJn9eg)09#=$PQ>$q@G0k2hlzrONOekiZag6-=*bGm8o%$qQVs}6EHV#y3~NG z@sZc3pg;5i*qz2FIIjgqYzc4<)`!wL4zQ8Oxj5?y(PyP!=UnQ|MS7~cdus!PJ6|Vk zHP)%30qG!6n7Ciw`-u`{rbfrmC%>?wT5a^JS6+-vU%`=ASpRrGI+%OPnVks90GUuW5J=g|!hEvYByl-Xr;PTFMJ|zcgAfWKz$_$b0TZ!0$4=Z*j{Y~*_{2nI z5m%a?FR1vcgq-=40kyb@X925b%JVo-=LyhAthL6Nm|G&-{-Y==K^8>*Aa1N%UZ}5>-}h4CkWxZ7 zI$iLV|8(i6Ocpu-Rr#?|tisFF^%WSjU1sHuK61O3oA~hXEg)K~vfR$O;Pg-J@DGmX zxsSSTz{$yL559PRsaojxX4yE$lkZ#mJTB$|1=l=s&xIclm2XUCS2Dd1j5wvO&T$x` zYn%^$+YsB8t2O1d^k`Wkq0vCZ_yAZaNd(?@^A|IkqQOuf$LjdbIF`y0n*4=a`s75ME92IY4-Y5S81AfX=K%HZlhvW`GxmnTy$2vP0LgqkJh7pLx> zcJie)ej=V5v(Q#P%hAchW!Gjq3v!>C5$uvnZCtTk@yWt;`2m%Y$}-*Vd;WC_W+YoH zaV_l=t+FbvZWMy$q*jt##&VXGT=(681EMO(<=DLLbTs{!U9!>Dd~=gOCtv>Qj0}8a zL|W){O}f}iiEdfuvRX z*mqs$%9bRlB{u$Ie_#vwGcvm8Tq{O9F*BosrjCE!zCHdQo#pbNK@Uzm1*6 z?HSne+60Kmv3q4^)syVD)wa8&*vUYz@xe1_49a#hY$=MWcMT85L2s7kTMd^X+3Q{5 zep+|N|Hy_i=y&n)(vt(!k8t`!VR9j|I0!Ryy%JfJ+xc8$AL{IJ?IH88xf?M{*!OGB zaC?9DdM?M5F+Tf4*0I~cceFPiIr*Z^+j20j2M(9V(^Y+TS-~Sm($sn7piPw*_;KR$ zDo~A;j2J*i2T-{2RfE>;zZ$g*SsYtWrr{qR9o?Dnpnc&rlbD-4t3Ju910l_%P%E<3 zp^Cz{@P;jlrElu*uXIjQ7?UUamZJti#KY=y3rgPLCg)>MsUp4`4cVKjxgYOZ!KjF2 z(OBQS#w@B(?!Xzi3r~9x%W7HMY{Wgj8y$E4UQy5#Hz$n6#a;VZnU<1rGdqvER-JL5 zRoQ)Oej>2P}Q3Rklwccx!XKa1L`YF-~HRy3WoVqy)xlv!6+*%IfGtVVumI8yE|e!B0$?!X_yJG3DuaYcoo$ zM|F{vV*u~aba6p*NS8Qvwr=2mb8wYI_AdSWEgA`;dPLIu>gsl=PoKw>L|LZ<-j?&t zLeq;+i2WV_keZe{U?=!XO&zJl*t%c64c{~koyY@Cc)cYKZ1l;+$CrJPukKr7~j zumkzW&c|B_Hq9 zmp}rUipR7@f*%FyIMZfebfuQA_o>R&RxVBohd5kM-`VgUh|s1G)yw+(FYtx^S(3p5M-2Xc0N>zfJ#LAYc>>h4RA!o_mU&*;)pJ6fi} zCbQI;OL58mL8zl;kmDv3<$W@;WmVqsz*D>nLjY-kFx@VG?=h-T?uiDtk7rtS2roj){EFA3iV zMB7#V8_ys~Tqzl@moDiyPJ6kU&f9G1Ri@;7sb%hF=x(1uv`K!^(Sqd%nz4pTJP_Ec zDe2R#m5(k1Omxvs;}exNfpH_blkq8=YdYuCH;|eP)*k6oj|N^tpKp-9{}4SE8L{Z zXgwG_{D!P(05n$^iiGwa2vqqI?*t;_UH;SJ?yld=|NWx zL3=sXlSZfdI~Eu$S7Gv#uIFIPnN7QGn>`tL2ll$AZBjRUpR8^HXRggk{q)rd5zRmVk1$qOmF`RYT1^5i~=Sa*LI@Re4;2E zJ~sEYCc3T49O^!mw1N|R3H}l$~H^jEr zM><~=w{}ay??R~?z~B2^6yQQSg*vP`#=ZY3snU zESg|)SsaKOq#y`$m;yUGQxRz5t+!XZELo0kf}7ZM_B!yfKGg3Pdnq8_x~wE*Ua^B* z2%l|htaM0Zbl5Lr6wCt78o@uI%$fo(#W+~oXpPY&!{HVuAvX}gX}*3xZJ^RZQ{VJ9hhdi({X;Dh$YP(2f+)i2tL;=(Id5| zW84E5Z7RZf0z86@{Dwkc$=%Z>lQz1yW>sOpozg8PVCzBvdYacB2g%KLE^bBzQe1*W zg^z5>LYDYD$hZv?@5R)MQ*tRQhTT%4XAOmhxZ)dpg_H8@4ooI5C_Qp-HDK52eT)!& zG(S`Zp59$aOHlZ_TL4kqV_D<~ZIz+U5gCbHc5pgU0rI@8Dh^@aGSn=X@$oOhdl}uo z{e?6T&KM2U%YW*B!l$qlRDV0T-hZd~K&~a^hJa>4EMRaOVfPqX(m=d~$@( znmIfvbPy1Vx?v-#tG31LtIkEECSPr`LKPfJ5WC=--(20?ZCA6y-cEJ@%Kp8?6k+26J5Ar) z^NwW;^JqbsWajxP8qzyX?G3+O?!4_Vt{qu_$SpBh7#lZHuuC<*+?H@1qt&IM>?Y7P z3irI}E7lr;?lz+5s$YZWBA0HgNF+U^@xBL3Mfoh_jX}lsZ>6QG?bEbirG2Db6HP-e z*Mnh}iPuvge)*?lH5cRORPXz7!4*&JWCWj!I7x7@tezS5dLNz)=fx9Ss1_pZi>+F` z(=LO6U^e(c6$zYei*CW!QUMYDMvY!a%;Sg6WV@cB?>pHyy zJx79RudLV|cEok+s@xW-TuWB88KUKoF1IvF#eDhmK|QqW ze!h{b#87FtSl4s)*&R0y+!0ZWC9~Ne=Ypv~Mg?e-;@1eP=xwpGk&wtoNyMl>cQJ}2 zd*u36Pj+G5K9za7?v6_<<&$5p*5T!tx}q&oEYXHS#Yw!^;2{h=34=S#Nu>f$|U8;TtOz1qF)u$6$aMd+Fl zrq~*sgneT1e?Me+9-GT>@Ie($>=Hyx#CEMK4voEZB1;f7iI{eh7gdeTv-_+qzIGhs z34rKZwCY;u81Tu@c5Z|9mD?%xBKlxdu(oCwlYaR(3*SSH;Fc7!Cg#L)iwaqLhMth6 za7anrdsRJ_&uswABRB;88WKOw?SdvPe<+8GlV(Od3U&Y&C{TwmtV23LMU! z@C2^0GCH-4UQ53cOKzU%dGg}is~}3^{AlqLB{{6}wu#2TJOs4lU=~oFG&q=QQr+tf z##%nt8k@^jaO}P}HY$}YO^YaR^r8fZlVot6-{S#l#8%{8K%9jQ=OxO+W|tbV0b~}l z7?1i^p0nILBvaPzYp3SrBW%}Kx%XC8ERnOchcr;KxNz8?)Lv=_zt#0@S)tdoLJVLP zv$d32N=7>RV)wqoy2Hnr7oumJ9q!qQ0{4Bjv^-Qg|ToF4~bbalZs&z&)reSh|Bw&?9*6Pk((h#5_zxWs~3b_ZBvw%rtsH%;C7ge-RDRQ*o ztlW)b9VJHJ%NDC*Qb?}+RMrgvq}Wh>TZ-ne2}qpTl=ENhq>Mm8i&BBD`Vv!m?M!u$Qm)2_r))YG5@inKWbh75Kp7V2Qf9Wv;UD zglXgFc5lGoyvc%d6)h)^%v5irDf|`JkE7qH?YJuqK3-5V#u3kss?iLtD_m@1vo6v# z>-n9~hvvpa&j>M)9^#TDRU$0mAarAnFjiG9o1x!ZWKgh$lAL%LHSkn;-pAUkdNkM3 z)!>{V5ef?&oGUk?YiB&^&|b6%OE9-gZcbY|4=ewU*!XEVe<@G@)E2jw$=!(7V)eV| zpsE=kD4R)+`6C0+)xdiQ`^QHcD!Yco1&)(xD1((~BMHlt?`i&o7qUnOXVL z1_5!ZZXe2h8ci{u`0{qk8G6;2xEQ8jYDrpQkYNB@Zdsa4b!CPC_h;Cp%Q4hwTI@u) zUv&#|h<1jBVk&e19v-bQev3*gsRUh-T~nhoEPe7t;A+a|q^cY5U8Pe~l`A_Qug+b0 z%Xx}5TaxmA`bv&puDQ>ry#g1FVEJ0SFtdAoAKOa0flqtkPIDgN<8n;upRU|W$m9J zq{n{S@Q6|y64_853qIx9Dub&JJ(}-Dnn(?AosP!kk8nFpDwZA+iDWBT3An=qkYwirO3PsTKU{7qx0y%=>9;c1Mf?6yR1?>!piYv zNH2}%%(DINS)PuL3yALV{j4e{RiWe>>9d&a1b!Y^r*aZA_(d1U5v!a5qW#F)DZM>w zQo|;voZVwX(;CM3-3S6*nh`@>#s|!N4kq#lt&Z3o=pGL|@WSu<=g^~tv|Uao+GO|j zaD1f8nTHzC4JOtz)}NO?7$%?%9mq0xP+qjsnaXf+osZYbRH-(Ts#*1`l0N-18Q-G5 zpP``jSTMg%>rr8uS6&}@lA(p>vOLfXRXx2I$5f7sy^PNY2;3~@fQ-=rrm|cgSEQu% zbq8?8iDwiJZ(lbl4zb!FnG1${SXHp~ih0T9S;`5x6~OTWdnq#27VoW_sCOl+DY9u$D0R#0&20KSW)DiFu|8^y z+2aF_x4XxBT%CNZ)h~&*OSZ_)0Wc(Q4CQ;#h4ZwlI`yT6aOnrZ(;YWtB5>sP9XOJk za;5f+aIhBaa!gOEV3eB_TFWi5nYkB;O9U}45~fMaa`&stvY$yd!rBRIx+VBp_ZRFs zEXoB9HRL-#7tM)Xn0>&5>M=DEy+5u7G>=XxKXR?e{u=}!!j91g<>`-8HGdSLE%c=5s<^xy&Cz6^Ak&dZ9*c} z9I+9SSG_oT0`$#(AkQ9CxJTVJ$(&HGy}|{vmKyLeq776;(FPD-8R-f7i$_7MLZ;f~ zcCutZGy|M(je2JWpJ(pIZkTt};?9JdxgEn2m~}VCx0QBLE@?eqBSp!A+*2k$Trpec zIMbtf5MB@cw#Yskk8fNLy6lFh zX)o+DFqEJ;5b%_+10_VF*%%ke#6ljVUaTmGCxJWtSoF@T*1*Sz_l|lIm4|abv5=b< z{q+=GT?!P1m%B;nq(7vSyZD!zx<-d>zYoo1_dyAy;OQ?w_UGBk)L6_RIN0l}ew8Bc zNQ#3;Lv-ULpEXptT}9%>KCXcsKwz&UIp4<|3{VHKrhg4S?zti7h@8o~JiJBCp$dFv zKuHQ`A~>bX-o;(!l@Y+6^A+fvJSEWk&6&=PQu;;TjKG7G>mU&{=yB@nJllIrAq=H8 z<#>zWYq8R(Jkbdf+&!%)wc~Vv@4Uv8PDi0<(C6U`;D& zH0J_2gHbP$k*%6;x@<3oh6B2-rL7Q>12@x6dOhv?fpX8iYNn%}wV#G5!zEAiIwl(Vi+#oS>o>ZT@vU_RxnhThR0$jQLOoIadzxT>} zdh6JABE9p5uaWy=PsLVHblEN))IKv99X~2k2@VG)aZEFAXo%fI)p>8bC0rULYmShY zV%;f&E{>(ue)*G<;W&SgUA>CewlY=-G}3de=J^)^DU>?Tebyt;(Ei5GVN%btgww5! zvoGI99O?>uCI8UWrl=1XY%}hJXf(bL;k`&zP-Q?R`|)zF`@|v$W7MhZYaGd+CI>0- zaa*}&tunWedcWI`55Okk@nHWSu@v9{H7eR9v+wjJeGuzudujv`#U|@djpU={Zam|9 zl&I?u2=Vg+BEr`#n`mPAY76LHC8*9?H*8Koz!ZI!H4tK-oY$&F7In)Fbn4mzlozn2 z`e*=xSCPgZ&kvoy4KOdyEjEZn3BawWY70KUF5s{7i(Aiq1|%LPSnFSP)L!zx*3SZj zlzJ2>n$!AKI)4?`sF{L25C+C4HsUt|fzu=VO&sHZ`>;~DyO^QpnXxyd^hZ6OS1nKs zsL%G!inTyh-;^^Dg{c%g&`w&CF9rt5z!MRRVHigc;*yZ09I_&@^zh=oDR74ELcAyaR% znrI2!K#*9>mV@%<8$nWT;8SLoNLwU$_fnHP%p*>aho|+AOeI^BHus8b~>Fj}GXUX+b zi{N%ISvun@dG!SOsWHLja~XLF=(nI_Ow$hOVU_w>(;)A`+ya|5pyPmmvCyC@B#9^FEvHTr zmiwZpQZ4A&%I8FG#2zD9?S}St6j(5cpB?L}x2DVOFWdTy3>FT?xje9LMa0;EQ4xej zXTz^5Z(rF`cav!z52Aex4?*4JtR$21ODs9s*dVCTbcNFY;Ur2*U@g}r@W}e)%xun-ca`d>FMB0JswEo6;nB1tE z9?|u_T%Ocog$rqGQ%j~;rEp+EgP-x9P^9-xMMx1=PzA(dh{180p3p}8lOwjn=VN?h3>#uc~UpK?PG`J`^B!` zw8HU~{~l?qLbD>rZ1l8~9`Lw{0yY&9*XeJQq=aZSFjgBvI$uYTJ|U5z3b;dAB^A{@ z-VWeSQ4v#A!bjtL#$dbUKfvsV01{|^!2N%Z@C`=(VmJ;{=K*~Z-L;o=Myn3IsY zK1kl>B0BCXJOR?$AO-gMK))u0)5zM8+PRNLnOlsInbGsNZeJ!Fv#QV78~m&(ctEOnBalKy1+-(KXkDDF(8QFT{B+> z$njh2d{;`su;+4O`g+!l?pZ>lY5mVUSpZ?>Wf7MP(q;t&vpWnx!3AhI0 z*5K0r)Inf0u;mor--7w?a(?Qs_^)*Sr@F%gMgcWn?yc|NoqR^dEXI`6Sl{q_HPQaTKi&Pg{HTv09%s z#s1-S*ZM%MwO{n^T_1MF{$Z+YeO49wIT#nVHY1Du%z>9(pR&b%?uW0>sA4~JxNTdT liMICqfA@;#0gT%3d>d8s%gUu_PV7H~oHNoXI&@> z&pYqDpU2~I=g!=jxpSxPz2Clk7DjtU@C*b3p+Q6hq(LC0RS@XG!zakVFSRwq%)mbn zY@~(xK!ts;)`0&!G~kus1%Zk~P%gC|0snt$DWYTp0-?OP{rdnE8;=J9@o_)|cx4^c zw-WZkrdjtZ6oNlRc_nz!A*nqa1^=^gT~kBlqCfgn5i|bfF9@dV#*=*1&-jYKAIk>w z65-gHtr?={X#YG+%37yYL72Y)@q)k){!suX`~QCfk1rN&E_gh<2c1iK+;8OWM~42o zK3$kN+B@AGo2Pw?V$OiSi<>&uU+CwMdXg%c+OLyPouTz(?w`BSp1MLdA6?m*l#+_j zneU(-;z+&1oo^H+wW$rhRT)(J!k{MVnHQ7 zZ+>Lo53yv>Zb)L)Z8kWojyfhBK$+9;p ztmolcm`D7_UC&J>F;lB*663MhgL^7m{?V)~;|7_plg^P6Cu`kaKHJAdqK~_%hexhjQDs%|bPz)PaN(529J;rJ2}5^kx#c z@jZzTq|02tKa|S`#kK8mJ3pTz^1YI#eobauPI7Gmd3--6V>@ueQm50iT6``>!SNUD z9pr?t`>$HWOA8ykltpRmk~+V`OXtQMTP97qpWfm9Y{PHlJn0!iXy>>vjy2yD7_nct z1tBNkGToC6XV$P49I6c|3u%0uoV^ob2f?hXS-;3}=t%cmJ$|Ba-__T@U z{6)U|=%uRm!2Q$}pHb!#T(ohn9%L#VoT$eX$otJpb`#xCEffQ^z#s@ zW;OF_Us-^o@7Lk^2s9oDPtGj;nMS?hA%bZ|xuKLL-`m z8(q%_unm%tZioETH(C}c&!RAz+1^tbf*pTm^>z`7_d>rzC(Jy`*s5f4Ez`C5Zg8qsC^y}50k4dO}YGPEihXePkIxY*| zSH-t32Ly`K*%HfYO?Idna+q6*(;#D5wJ4y!gMe5)qgDD}6+jfmnmM~ANW|lQ)t~Iw z5Un9w5l(2_5Ba2Yv3Zt0U#e$t1%Tc552`7wS_tl7rr*%@`z6;GI1eSZhp$70pbZIc z4(}kEQ-`|9z@`s@7ub2THx@MSMn$6DK|ZZ)hJe*{%A^aE+O5?yQxjiybuozNAq`f%gL|6&;BnuHNwqWaA#By^BZ(LuWRn-Y zXOyUv1U->bxmLbB2XFZj6RmmuS2P}anN8*1~n2*fEkqCgKrUi8=PNu59JUH z46*n=S|ry~qumD%#k0Np*>ii%)~QzXK)>2FeC<6;&zTGd>P;!uJ(sJv4E`i)GQ(c6 zAB}@-`oK7xRd;|-H=7~--2B4kYV?6X zF_iOeB2%xcy&#M4&V#$1)|1FLAFm~b{$ydFX+L(j1CN8W-OXKPh68;2;UmZ&K87FG zoeX^=9@aYTe)jxsM6$+tQm&4H-GKY6W(Y^l9 zYNlm7hC@-vvN7{&e}Uy+2{UgdX6FO+%DKjxd9Ij~m9(KB?$E}uv^9BZma_@bl4$ev z=IahD|05W1wcE!ed}a6)`Z3XA_ADScqZQfe4(SKWar;;U?>fJNc06rX>u-^AtpDf{ z0MT&n^-;v?&?4fPaHrqYw0o`@IMkNab>G^@bDtFX{c{^tVfPz<{Pm*w z_SKe9VfP8GA8#OGb8%UHGT`)suvzcv3Qb__a5b0d`+y_$b*h>WOIs8l#qK~L#TVN8 zZbN12N`2m%$8~jWJN+7pUia2-8ePcBL-!)p=tjPU*>{b@-#w6_o#QToctWNYvhxWBK&7F}gHFpI+Y^%x}`;cHG1; z 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", + "\nGiven the current status of the implementation, in order to display Actual reports it is necessary to set Actual format in the Args while to display Cashflow it is necessary to set Cashflow format." + ], + "metadata": {} + }, + { + "id": "trcP0qut1kWbOQTgIF35cg", + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2m1t-aisOEiw325jWesNXQ", + "cell_type": "code", + "source": [ + "var UniversePreview = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "AbkLGXiDFk6sdSdWtinXjA", + "cell_type": "code", + "source": [ + "var importStorage = UniversePreview.GetStorage();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "k9qNkaSwjUqp_Y_vGf9RwA", + "cell_type": "markdown", + "source": [ + "# Import Preview" + ], + "metadata": {} + }, + { + "id": "5EP-6YDPFkeMJcxDTaO7qw", + "cell_type": "markdown", + "source": [ + "## Present Value" + ], + "metadata": {} + }, + { + "id": "XTFLl2lau0SjbCIEtOTHpA", + "cell_type": "code", + "source": [ + "var identities = UniversePreview.GetScopes(importStorage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yEjsrBVzEk26kz9jgLkJ-Q", + "cell_type": "code", + "source": [ + "var pvs = UniversePreview.GetScopes(identities, o => o.WithStorage(importStorage)).SelectMany(x => x.PvCurrent.Concat(x.PvLocked));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ck9xZbpeDUyh_Tw6FOoxKg", + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(pvs", + "\n //.Where(x => x.DataNode == \"DTR1.1\")", + "\n )", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n //.GroupColumnsBy(x => x.AmountType)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n //VariableType", + "\n //.GroupColumnsBy(x => x.DataNode)", + "\n //.GroupColumnsBy(x => x.Novelty)", + "\n .WithGridOptionsForIfrsVariable(720)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XIPJIPxfyEy6P4JYfRAXTA", + "cell_type": "markdown", + "source": [ + "## Risk Adjustment" + ], + "metadata": {} + }, + { + "id": "4bBaRnP3pE-ZbxPKKnxOCA", + "cell_type": "code", + "source": [ + "var ras = UniversePreview.GetScopes(identities).SelectMany(x => x.RaCurrent.Concat(x.RaLocked));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "AiOWaeI_Hku1SDbNB-xlXA", + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(ras)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n //.GroupRowsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n //VariableType", + "\n //.GroupColumnsBy(x => x.DataNode)", + "\n //.GroupColumnsBy(x => x.Novelty)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rqCr51d6kUGgBzGRAqrtXw", + "cell_type": "markdown", + "source": [ + "## Actuals" + ], + "metadata": {} + }, + { + "id": "vl8E9tTAT06fpVUcTfflbg", + "cell_type": "code", + "source": [ + "var actuals = UniversePreview.GetScopes(identities).SelectMany(x => x.Actual);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hQUJ7t1AB0O-L0PVYPqsVw", + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(actuals)", + "\n .WithQuerySource(Workspace)", + "\n .GroupRowsBy(x => x.AmountType)", + "\n //.GroupColumnsBy(x => x.DataNode)", + "\n .WithGridOptionsForIfrsVariable(550)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nwWJHZ5vTUuJsHqFTGwLQw", + "cell_type": "markdown", + "source": [ + "## Advance, Overdue Actuals" + ], + "metadata": {} + }, + { + "id": "UYvTQnP0NUe4pLm0fnYEAA", + "cell_type": "code", + "source": [ + "var aoActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.AdvanceActual.Concat(x.OverdueActual));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1v6tcALrVEGG-vdRDV7HIQ", + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(aoActuals)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupColumnsBy(x => x.EstimateType)", + "\n .GroupColumnsBy(x => x.AmountType)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable(300)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ab2P4J7DO0mkVrlsP09fhQ", + "cell_type": "markdown", + "source": [ + "## Deferrable Actuals" + ], + "metadata": {} + }, + { + "id": "KCZlxRFa10CYDduJ65KMHg", + "cell_type": "code", + "source": [ + "var deferrableActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.DeferrableActual);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zln4EOOdqUiUTFbwoqTirw", + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(deferrableActuals)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable(350)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "l5uZz5MhKUOYLsKpzNZwvQ", + "cell_type": "markdown", + "source": [ + "## Csm Lc LoReCo" + ], + "metadata": {} + }, + { + "id": "WZ_xvxUBtEKO2jingfCpRQ", + "cell_type": "code", + "source": [ + "var csm = UniversePreview.GetScopes(identities).SelectMany(x => x.Csms);", + "\nvar loss = UniversePreview.GetScopes(identities).SelectMany(x => x.Loss);", + "\nvar csmLcLoReCo = Enumerable.Empty().Concat(csm).Concat(loss);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RAN7qdbDLECNmb-kxUNx1A", + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(csmLcLoReCo", + "\n //.Where(x => x.DataNode == \"DT1.1\")", + "\n )", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupColumnsBy(x => x.EstimateType)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GszVX-_KiEa9h0m0P0rlhQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb new file mode 100644 index 00000000..175eb9d1 --- /dev/null +++ b/Import/ImportScopeCalculation.ipynb @@ -0,0 +1,2296 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "a6wbTgZMQ0q5Of99FfYD-A", + "cell_type": "markdown", + "source": [ + "", + "\n

Import Scopes (IFRS17 Methodology Business Logic)

", + "\n", + "\nThis notebook contains the logic used to perform calculations upon import of data (actuals and cashflows). This is also called 'Data Loading' and the concept of Scope is used here to define the logic and provide the means of executing the logic." + ], + "metadata": {} + }, + { + "id": "6qZO0vcpd0GtSc7GvLlgBQ", + "cell_type": "markdown", + "source": [ + "# References", + "\nLibraries and other notebooks which are needed for this notebook are imported below." + ], + "metadata": {} + }, + { + "id": "G75a3tlrBkqn_MN5as22Jw", + "cell_type": "markdown", + "source": [ + "## Notebooks" + ], + "metadata": {} + }, + { + "id": "HQwfAINEvUqJK5l5FV_SOg", + "cell_type": "code", + "source": [ + "#!import \"ImportStorage\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kd06OH9YcE2hGUtgERwXhA", + "cell_type": "markdown", + "source": [ + "", + "\n# Scopes", + "\nScopes are used to define and perform data handling in a structured and easy-to-read-through fashion.", + "\n", + "\nThe IModel interface below will be used to execute calculations (i.e. evaluate the scopes) based on imported data." + ], + "metadata": {} + }, + { + "id": "3ye2s5-hWEWsy3YLTe5R-w", + "cell_type": "code", + "source": [ + "public interface IModel : IMutableScopeWithStorage{}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LjnVkU0bq0yP61Cb1_EMxA", + "cell_type": "markdown", + "source": [ + "## Getting Existing Identities", + "\n", + "\nAn [Identity](../DataModel/DataStructure#import-identity) is a set of identifiers for a certain set of data. In particular, an identity consists of a certain [AoC Type](../DataModel/DataStructure#aoc-type), [Novelty](../DataModel/DataStructure#novelty), [Data Node](../DataModel/DataStructure#data-node), Accident Year, and information on whether the data is for reinsurance or not. ", + "\n", + "\nGiven a certain Data Node and Accident Year, the interface GetIdentities returns all the existing identities (e.g. for Actuals and Cashflows) which have that Data Node and Accident Year." + ], + "metadata": {} + }, + { + "id": "SyhE8EzOsECEpMzUSS6kGQ", + "cell_type": "code", + "source": [ + "public interface AllCfIdentities : IScope // string represents a DataNode", + "\n{", + "\n public IEnumerable ids => GetStorage().GetAllAocSteps(InputSource.Cashflow)", + "\n .Select(aocStep => new ImportIdentity {", + "\n AocType = aocStep.AocType,", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity", + "\n });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_LsQEeHMYE6G4pGS8dK4RQ", + "cell_type": "code", + "source": [ + "public interface GetIdentities : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity))", + "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Actual)", + "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Cashflow)", + "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Opening)", + "\n );", + "\n ", + "\n private IEnumerable computedIdentities => new string[]{AocTypes.EA, AocTypes.AM, AocTypes.EOP}", + "\n .Select(aocType => new ImportIdentity {", + "\n AocType = aocType,", + "\n Novelty = Novelties.C,", + "\n DataNode = Identity", + "\n });", + "\n private IEnumerable allIdentities => ParsedIdentities.Concat(computedIdentities).Concat(SpecialIdentities).ToHashSet(); ", + "\n ", + "\n IEnumerable ParsedIdentities => Enumerable.Empty(); ", + "\n IEnumerable SpecialIdentities => Enumerable.Empty();", + "\n ", + "\n //Set DataNode properties and ProjectionPeriod", + "\n IEnumerable Identities => allIdentities.Select(id => id with { IsReinsurance = GetStorage().DataNodeDataBySystemName[id.DataNode].IsReinsurance,", + "\n ValuationApproach = GetStorage().DataNodeDataBySystemName[id.DataNode].ValuationApproach", + "\n });", + "\n /* .SelectMany(id => Enumerable.Range(0,GetStorage().GetProjectionCount() + 1)", + "\n .Select(pp => id with {ProjectionPeriod = pp })", + "\n );*/", + "\n}", + "\n", + "\npublic interface AllCashflowIdentities : GetIdentities", + "\n{", + "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids;", + "\n}", + "\n", + "\n", + "\npublic interface GetActualIdentities : GetIdentities", + "\n{", + "\n private IEnumerable actualEstimateTypes => GetStorage().EstimateTypesByImportFormat[ImportFormats.Actual];", + "\n ", + "\n IEnumerable GetIdentities.ParsedIdentities => GetStorage().GetIfrsVariables(Identity).Where(iv => actualEstimateTypes.Contains(iv.EstimateType)).Select(v => new ImportIdentity(v));", + "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids", + "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Opening)", + "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity", + "\n }));", + "\n}", + "\n", + "\npublic interface GetCashflowIdentities : GetIdentities", + "\n{", + "\n private bool isReinsurance => GetStorage().DataNodeDataBySystemName[Identity].IsReinsurance; //clean up in the next PR", + "\n ", + "\n IEnumerable GetIdentities.ParsedIdentities => GetStorage().GetRawVariables(Identity).Select(v => new ImportIdentity(v));", + "\n ", + "\n IEnumerable GetIdentities.SpecialIdentities => ParsedIdentities.Where(id => id.Novelty != Novelties.C)", + "\n .Select(id => id.Novelty).ToHashSet()", + "\n .SelectMany(n => (n == Novelties.N ", + "\n ? new string[]{AocTypes.IA, AocTypes.CF} //Add IA, CF, for New Business", + "\n : isReinsurance ", + "\n ? new string[]{AocTypes.IA, AocTypes.CF, AocTypes.YCU, AocTypes.CRU, AocTypes.RCU} //Add IA, CF, YCU, CRU, RCU for in force", + "\n : new string[]{AocTypes.IA, AocTypes.CF, AocTypes.YCU}) //Add IA, CF, YCU,", + "\n .Select(aocType => new ImportIdentity {", + "\n AocType = aocType,", + "\n Novelty = n,", + "\n DataNode = Identity }))", + "\n .Concat(new ImportIdentity {", + "\n AocType = AocTypes.CF, //Add CF for Deferral", + "\n Novelty = Novelties.C,", + "\n DataNode = Identity", + "\n }.RepeatOnce()) ", + "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Opening)", + "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity", + "\n })); ", + "\n}", + "\n", + "\npublic interface GetAllIdentities : GetIdentities", + "\n{", + "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids", + "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Actual)", + "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity,", + "\n }));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZVtzxigEF0yEaftuPtLQlw", + "cell_type": "markdown", + "source": [ + "## Getting Amount Types", + "\n", + "\nSimilarly, given a certain Data Node and Accident Year, the interface ValidAmountType returns all the amount types which are used in imported data with that Data Node and Accident Year." + ], + "metadata": {} + }, + { + "id": "kE72GkEJNE2GPEnIe78RDA", + "cell_type": "code", + "source": [ + "public interface ValidAmountType : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow ||", + "\n x.GetStorage().IsSecondaryScope(x.Identity)));", + "\n ", + "\n IEnumerable BeAmountTypes => GetStorage().GetRawVariables(Identity)", + "\n .Where(rv => rv.AmountType != null)", + "\n .Select(x => x.AmountType)", + "\n .Concat(GetStorage().DataNodeDataBySystemName[Identity].IsReinsurance ? (AmountTypes.CDR).RepeatOnce() : Enumerable.Empty())", + "\n .ToHashSet();", + "\n ", + "\n ", + "\n IEnumerable ActualAmountTypes => GetStorage().GetIfrsVariables(Identity)", + "\n .Where(iv => GetStorage().EstimateTypesByImportFormat[ImportFormats.Actual].Contains(iv.EstimateType))", + "\n .Select(x => x.AmountType)", + "\n .ToHashSet();", + "\n}", + "\npublic interface BeAmountTypesFromIfrsVariables : ValidAmountType", + "\n{", + "\n IEnumerable ValidAmountType.BeAmountTypes => GetStorage().GetIfrsVariables(Identity)", + "\n .Where(iv => GetStorage().EstimateTypesByImportFormat[ImportFormats.Cashflow].Contains(iv.EstimateType) && iv.AmountType != null)", + "\n .Select(x => x.AmountType)", + "\n .ToHashSet();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OppPBfh8o0-NsCYyUGOVLg", + "cell_type": "markdown", + "source": [ + "", + "\n## AoC Step Structure", + "\n", + "\nThe Aoc step structure is constructed from the data which is delivered as input. It is assumed that it depends only on the Group of Contrat (i.e. it is invariant across Amount types or Accident Year). " + ], + "metadata": {} + }, + { + "id": "54mTUE9VgUG3fW8ov6K3Uw", + "cell_type": "markdown", + "source": [ + "### ParentAocStep ", + "\nThe **ParentAocStep** scope computes and provides an important piece of information for each [Identity](../DataModel/DataStructure#import-identity), i.e. for a certain [AocType](../DataModel/DataStructure#aoc-type) and [Novelty](../DataModel/DataStructure#novelty).", + "\n", + "\nIt provides the list of the adjacent AocSteps prior to Identity one. It can be more than one only for the step **CL** where a parent for each novelty is considered.", + "\nParentAocStep is critical when computing the *telescoping* differences. ", + "\n", + "\nThey are defined as follows:", + "\n", + "\n$$", + "\n\\text{ParentAocStep}(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{AoC step with AoC Type YCU and Novelty I} & \\text{if AocType CRU} \\\\", + "\n\\text{The last AoC step with Data Type != Calculated and same Novelty as the AocStep} & \\text{if AocType YCU} \\\\", + "\n\\text{The AoC step which comes before in terms of order (as defined by AocType)} & \\text{otherwise} \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n" + ], + "metadata": {} + }, + { + "id": "l9dack27s0Kc15M14T2vxg", + "cell_type": "code", + "source": [ + "public interface ParentAocStep : IScope<(ImportIdentity Id, string AmountType), ImportStorage>", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType != AmountTypes.CDR));", + "\n ", + "\n private HashSet ParsedAocSteps => GetScope(Identity.Id.DataNode).ParsedIdentities.Select(id => new AocStep(id.AocType, id.Novelty)).ToHashSet();", + "\n private IEnumerable OrderedParsedAocSteps => ParsedAocSteps.Concat(CalculatedTelescopicAocStep).OrderBy(x => GetStorage().AocConfigurationByAocStep[x].Order);", + "\n ", + "\n private Dictionary> ParentParsedIdentities => GetPreviousIdentities(OrderedParsedAocSteps);", + "\n private AocStep identityAocStep => new AocStep(Identity.Id.AocType, Identity.Id.Novelty);", + "\n ", + "\n IEnumerable CalculatedTelescopicAocStep => GetStorage().GetCalculatedTelescopicAocSteps();", + "\n ", + "\n IEnumerable Values => ", + "\n Identity.Id.AocType switch {", + "\n AocTypes.CRU => new AocStep(AocTypes.YCU, Novelties.I).RepeatOnce(),", + "\n AocTypes.YCU => OrderedParsedAocSteps.GetReferenceAocStepForCalculated(GetStorage().AocConfigurationByAocStep, identityAocStep).RepeatOnce(),", + "\n _ => ParentParsedIdentities.TryGetValue(identityAocStep, out var parents) ? parents : Enumerable.Empty(),", + "\n };", + "\n}", + "\n", + "\npublic interface ParentAocStepForCreditRisk : ParentAocStep", + "\n{", + "\n IEnumerable ParentAocStep.CalculatedTelescopicAocStep => ", + "\n GetStorage().GetCalculatedTelescopicAocSteps().Where(aoc => aoc.AocType != AocTypes.CRU);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5L-2OpNhxki8UNE8od5BLQ", + "cell_type": "markdown", + "source": [ + "### ReferenceAocStep", + "\n", + "\nThe **ReferenceAocStep** scope provides the AocStep from which to retrieve the data in order to compute its value (e.g. AoC step EA retrieves Present Values, while AoC step YCU retrieves Nominal).", + "\n", + "\nThey are defined as follows:", + "\n", + "\n$$", + "\n\\text{ReferenceAocStep}(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{self} & \\text{if AocStep InputSource is not Calculated} \\\\", + "\n\\text{The last AoC step with Data Type != Calculated and same Novelty as the input AocStep} ~, & \\text{if AocType } \\in \\text{\\{RCU, CF, IA, YCU, CRU\\}} \\\\", + "\n\\text{AoC step with AoC Type CF and Novelty as the AocStep} & \\text{if AocType EA} \\\\", + "\n\\text{AoC step with AoC Type CL and Novelty C} & \\text{if AocType $\\in$ \\{AM, EOP\\}} \\\\", + "\n\\text{empty} & \\text{if AocType is BOP} \\\\", + "\n\\text{log NotSupportedAocStepReference error} & \\text{otherwise} \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the last AocStep is obtained by ordering the AocSteps according to their order (as defined by its AocType) and taking the last one." + ], + "metadata": {} + }, + { + "id": "ItSTOo7qmE68A7gENSMguQ", + "cell_type": "code", + "source": [ + "public interface ReferenceAocStep : IScope ", + "\n{", + "\n private IEnumerable OrderedParsedAocSteps => GetScope(Identity.DataNode).ParsedIdentities", + "\n .Select(id => new AocStep(id.AocType, id.Novelty))", + "\n .Distinct()", + "\n .OrderBy(aocStep => GetStorage().AocConfigurationByAocStep[aocStep].Order);", + "\n private AocStep identityAocStep => new AocStep(Identity.AocType, Identity.Novelty);", + "\n private AocStep GetReferenceAocStep(string aocType) {", + "\n return aocType switch {", + "\n AocTypes.RCU or AocTypes.CF or AocTypes.IA or AocTypes.YCU or AocTypes.CRU => OrderedParsedAocSteps.GetReferenceAocStepForCalculated(GetStorage().AocConfigurationByAocStep, identityAocStep),", + "\n AocTypes.EA => new AocStep(AocTypes.CF, Identity.Novelty),", + "\n AocTypes.AM or AocTypes.EOP => new AocStep(AocTypes.CL, Novelties.C),", + "\n AocTypes.BOP => new AocStep(default, default), //BOP, C has DataType == Calculated. See ReferenceAocStep condition.", + "\n _ => (AocStep)ApplicationMessage.Log(Error.NotSupportedAocStepReference, Identity.AocType),", + "\n };", + "\n }", + "\n", + "\n // The Reference AocStep from which get data (Nominal or PV) to compute", + "\n AocStep Value => GetStorage().AocConfigurationByAocStep[identityAocStep].DataType == DataType.Calculated ", + "\n || GetStorage().AocConfigurationByAocStep[identityAocStep].DataType == DataType.CalculatedTelescopic ", + "\n ? GetReferenceAocStep(Identity.AocType)", + "\n : identityAocStep;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tzXoa0VDqUSEqPJLe4LCdA", + "cell_type": "markdown", + "source": [ + "### PreviousAocSteps", + "\nThe **PreviousAocSteps** scope computes and provides an other important piece of information for each [Identity](../DataModel/DataStructure#import-identity), i.e. for a certain [AocType](../DataModel/DataStructure#aoc-type) and [Novelty](../DataModel/DataStructure#novelty).", + "\n", + "\nIt provides the list of all previous AocSteps up to the **BOP** step, whereby a Combined novelty will branch into the InForce and New Business AocTypes.", + "\n", + "\nPreviousAocSteps is critical when computing aggregated values along the various dimensions (such as for example Line of Business) and ", + "\nis formed by the ParentAocStep and its parent and so on until there is no parent.", + "\n", + "\n$$", + "\n\\text{PreviousAocSteps}(\\rm{AocStep}) = \\{PAS_1, PAS_2, \\ldots\\}", + "\n$$", + "\nwhere", + "\n$$", + "\n\\rm{PAS}_1 = \\rm{ParentAocStep}(\\rm{AocStep})", + "\n$$", + "\n$$", + "\n\\rm{PAS}_2 = \\rm{ParentAocStep}(\\rm{PAS}_1).", + "\n$$", + "\n", + "\nThis scope depends on the InputSource (Actual or Cashflow) for which the PreviousSteps are requested due to the AocChain differences between Actual reports and the rest." + ], + "metadata": {} + }, + { + "id": "4AJrFGaLqEm52QmmXGl6pg", + "cell_type": "code", + "source": [ + "public interface PreviousAocSteps : IScope<(ImportIdentity Id, InputSource ScopeInputSource), ImportStorage> ", + "\n{ ", + "\n private AocStep identityAocStep => new AocStep(Identity.Id.AocType, Identity.Id.Novelty);", + "\n private int aocStepOrder => GetStorage().AocConfigurationByAocStep[identityAocStep].Order;", + "\n private HashSet allAocSteps => GetStorage().GetAllAocSteps(Identity.ScopeInputSource).ToHashSet();", + "\n IEnumerable Values => allAocSteps.Contains(identityAocStep)", + "\n ? GetScope(Identity.Id.DataNode).Identities", + "\n .Select(id => new AocStep(id.AocType, id.Novelty))", + "\n .Distinct()", + "\n .Where(aoc => allAocSteps.Contains(aoc) && ", + "\n GetStorage().AocConfigurationByAocStep[aoc].Order < aocStepOrder && ", + "\n (Identity.Id.Novelty != Novelties.C ? aoc.Novelty == Identity.Id.Novelty : true) )", + "\n .OrderBy(aoc => GetStorage().AocConfigurationByAocStep[aoc].Order)", + "\n : Enumerable.Empty();", + "\n} " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "JJ7sk4vUDUSWJJvVDpbZNw", + "cell_type": "markdown", + "source": [ + "The exact structure being return depends on the **order** of the AoC Steps (which is set by the [AoC Type](../DataModel/DataStructure#aoc-type)), and on which AoC steps exist.", + "\n", + "\nFor an example of the usage of the AocStep scope see [here](../Test/AocStructureTest)." + ], + "metadata": {} + }, + { + "id": "1qVdizG_x0OI3MI-IEVZKA", + "cell_type": "markdown", + "source": [ + "", + "\n## Discounting", + "\n", + "\nThe calculation of IFRS17 figures is based on cumulated discounted cashflows." + ], + "metadata": {} + }, + { + "id": "bKrNP0O7ZEOtm23hLJyEyg", + "cell_type": "markdown", + "source": [ + "", + "\n### Yield Curves", + "\n", + "\nThe Yield Curves used for the discounting calculations are functions of the [Currency](../DataModel/DataStructure#currency), the [Data Node](../DataModel/DataStructure#data-node) and the [Economic Basis](../DataModel/DataStructure#economic-basis).", + "\n", + "\nIn particular:", + "\n- For the **Locked-in** economic basis, the yield curve used is the latest available as per end of the DataNode's inception year;", + "\n- Whereas for the **Current** economic base, the yield curve used is the latest available as per the current period.", + "\n", + "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/UtilityMethods#yield-curve)." + ], + "metadata": {} + }, + { + "id": "DcHXuat1WUaOAFa_MsVSdQ", + "cell_type": "markdown", + "source": [ + "", + "\n### Interest and Discount Rates and Factors", + "\n", + "\nThe factors used for discounting have the same granularity as the cashflow, i.e. monthly. The yield curves have yearly granularity, so the annual Interest factor is 1 + interest rate. The monthly Interest Interest and Discount factors are obtained from the annual factors such that the product of 12 months results in the annual factors, as follows:", + "\n", + "\n$$", + "\n\\text{Discount}_i = ( 1 + \\text{YC}_i ) ^{-\\frac{1}{12}} ~,", + "\n$$", + "\nand ", + "\n$$", + "\n\\text{Interest}_i = ( 1 + \\text{YC}_i) ^{\\frac{1}{12}} ~,", + "\n$$", + "\n", + "\nwhere the index $i$ denotes years." + ], + "metadata": {} + }, + { + "id": "yCCcQcUwzEO1lzy3iwRM8Q", + "cell_type": "code", + "source": [ + "public interface MonthlyRate : IScope", + "\n{", + "\n private string EconomicBasis => GetContext();", + "\n ", + "\n private double[] YearlyYieldCurve => GetStorage().GetYearlyYieldCurve(Identity, EconomicBasis);", + "\n ", + "\n private double Perturbation => 0; //GetStorage().GetYieldCurvePerturbation(); => switch Args.Scenario { 10ptsU => 0.1, 10ptsD => -0.1, _ => default)", + "\n ", + "\n double[] Interest => YearlyYieldCurve.Select(rate => Math.Pow(1d + rate, 1d / 12d) + Perturbation).ToArray(); ", + "\n ", + "\n double[] Discount => Interest^(-1);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ON4hzALyrkapbo6dsJaCYA", + "cell_type": "markdown", + "source": [ + "For an example of these calculations see [here](../Test/DocumentationImportCashflowsTest#interest-and-discount-rates)." + ], + "metadata": {} + }, + { + "id": "wCY9O1rFG0OcsUmqNLVm4Q", + "cell_type": "markdown", + "source": [ + "", + "\n## Nominal Values", + "\n", + "\nThe nominal cashflow values correspond to the cashflows provided in the Cashflow input file. ", + "\n
These values are stored in the database as [RawVariable](../DataModel/DataStructure#raw-variables).", + "\n
Refer to the ReferenceAocStep of the AocStructure calculation to identify the correct AocType and Novelty to retrieve.", + "\n
Due to the Credit Default Risk of a reinsurance partner, the logic to compute the Nominal Cashflows for this Amount Type must be defined separately. " + ], + "metadata": {} + }, + { + "id": "YZrg-gGldUGe6pZF0Kh3Qw", + "cell_type": "code", + "source": [ + "public interface NominalCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR));", + "\n", + "\n AocStep referenceAocStep => GetScope(Identity.Id).Value;", + "\n double[] Values => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.AccidentYear);", + "\n}", + "\n", + "\npublic interface CreditDefaultRiskNominalCashflow : NominalCashflow", + "\n{", + "\n private double[] NominalClaimsCashflow => GetStorage().GetClaims()", + "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", + "\n .Aggregate();", + "\n ", + "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", + "\n ", + "\n private double[] PvCdrDecumulated { get {", + "\n var ret = new double[NominalClaimsCashflow.Length];", + "\n for (var i = NominalClaimsCashflow.Length - 1; i >= 0; i--)", + "\n ret[i] = Math.Exp(-nonPerformanceRiskRate) * ret.ElementAtOrDefault(i + 1) + NominalClaimsCashflow[i] - NominalClaimsCashflow.ElementAtOrDefault(i + 1);", + "\n return ret; } } ", + "\n ", + "\n double[] NominalCashflow.Values => PvCdrDecumulated - NominalClaimsCashflow;", + "\n}", + "\n", + "\npublic interface AllClaimsCashflow : NominalCashflow", + "\n{", + "\n double[] NominalCashflow.Values => GetStorage().GetClaims()", + "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", + "\n .Aggregate();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OPI-l8iwREuVVszAP89Hqw", + "cell_type": "markdown", + "source": [ + "For a given month $i$ they are denoted as $\\rm{Nominal}_i$." + ], + "metadata": {} + }, + { + "id": "7RRmYOmkFEuqu8yfOR-0rw", + "cell_type": "markdown", + "source": [ + "For an example of nominal cashflow values see [here](../Test/SpecificationsImportCashflows#nominal-cashflow)." + ], + "metadata": {} + }, + { + "id": "q0ZU9L_OMUqLUKUOUcLuAw", + "cell_type": "markdown", + "source": [ + "", + "\n## Present Values", + "\n", + "\nPresent Values are calculated during the import of the cashflows and stored on the database. They are computed for the relevant Economic Basis, depending on the Valuation Basis.", + "\n", + "\nTheir calculation is described in the following sections and is summarized in the $\\rm{PV}$ formula [below](#present-value)." + ], + "metadata": {} + }, + { + "id": "4SsmFu7Uo0aIEmes8Z4LoQ", + "cell_type": "markdown", + "source": [ + "", + "\n### Cumulated Discounted Cashflows", + "\n", + "\nCumulated and Discounted cashflows $\\rm{CDC}$ are computed using the monthly discount rates and in a recursive manner, as follows:", + "\n", + "\n$$", + "\n\\text{CDC}_i(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{Nominal}_i + \\text{CDC}_{i+1} \\cdot {\\text{Valid Discount}_{\\frac{i}{12}}} ~, & \\text{if Aoc Type's Period Type is Beginning Of Period} \\\\", + "\n\\big( \\text{Nominal}_i + \\text{CDC}_{i+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{i}{12}}} ~, & \\text{if Aoc Type's Period Type is End Of Period}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere Transaction Period depends on which Best Estimate value is being computed, in particular on what its [Amount Type](../DataModel/DataStructure#amount-type) is (each Amount Type has its own [Period Type](../Constants/Enums)); and $\\text{Valid Discount}$ stands for the fact that in case the Discount Curves are shorter than the required index, then their last element is returned.", + "\n", + "\n
Also here, the Credit Default Risk contribution is calculated separately. Since it is based on Claims, the Period Type is implicitly defined." + ], + "metadata": {} + }, + { + "id": "n0bMVVX8JUGCvXh-hcQi9g", + "cell_type": "code", + "source": [ + "public interface DiscountedCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", + "\n{", + "\n private PeriodType periodType => GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType); ", + "\n ", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR));", + "\n", + "\n [NotVisible]", + "\n string EconomicBasis => GetContext();", + "\n", + "\n [NotVisible]", + "\n double[] MonthlyDiscounting => GetScope(Identity.Id).Discount;", + "\n ", + "\n [NotVisible]", + "\n double[] NominalValues => GetScope(Identity).Values;", + "\n", + "\n double[] Values => NominalValues.ComputeDiscountAndCumulate(MonthlyDiscounting, periodType);", + "\n}", + "\n", + "\npublic interface DiscountedCreditRiskCashflow : DiscountedCashflow", + "\n{ ", + "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", + "\n ", + "\n double[] DiscountedCashflow.Values => NominalValues.ComputeDiscountAndCumulateWithCreditDefaultRisk(MonthlyDiscounting, nonPerformanceRiskRate);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "V8aa9nD9bUqsX54-bD1Hiw", + "cell_type": "markdown", + "source": [ + "For example calculations for Cumulated Discounted Cashflows see [here](../Test/SpecificationsImportCashflows#cumulated-discounted-cashflow)." + ], + "metadata": {} + }, + { + "id": "bYq1f5UE80q1fxb-AON3pA", + "cell_type": "markdown", + "source": [ + "", + "\n### Telescoping Difference", + "\n", + "\n", + "\nPresent Value figures for a specific period are typically reported through an analysis of change, where for each [AocStep](#aoc-steps-structure) the variation with respect to the preceding AocStep is shown.", + "\n", + "\nThe Telescoping Difference is basically the delta between two adjacent AoC steps, whereby the [ParentAocStep](#aoc-steps-structure) is used to determine the AoC step. ", + "\n", + "\nIt is defined as follows:", + "\n", + "\n$$", + "\n\\text{TelescopingDifference}_i = ", + "\n\\text{CDC}_{i}\\big(\\text{current AoC step}\\big) - \\text{CDC}_{i}\\big(\\text{parent AoC step}\\big)", + "\n$$", + "\n", + "\nwhere AocType is the AoC Type of the AoC Step for which the calculations are being performed." + ], + "metadata": {} + }, + { + "id": "cNNeXkyxjkiDODg6ARR5Zw", + "cell_type": "code", + "source": [ + "public interface TelescopicDifference : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", + "\n{", + "\n [NotVisible]", + "\n string EconomicBasis => GetContext();", + "\n private double[] CurrentValues => GetScope(Identity).Values;", + "\n ", + "\n private double[] PreviousValues => (GetScope((Identity.Id, Identity.AmountType)))", + "\n .Values", + "\n .Select(aoc => GetScope((Identity.Id with {AocType = aoc.AocType, Novelty = aoc.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.Accidentyear)).Values)", + "\n .Where(cf => cf.Count() > 0)", + "\n .Aggregate();", + "\n ", + "\n double[] Values => CurrentValues - PreviousValues;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cYmNPbah5UaC9Iu3db7pqA", + "cell_type": "markdown", + "source": [ + "Examples of Telescoping Difference calculations for different AoC steps start [here](../Test/SpecificationsImportCashflows#modelcorrections)." + ], + "metadata": {} + }, + { + "id": "Z42Ysovu4UmepvVo0U429w", + "cell_type": "markdown", + "source": [ + "", + "\n### Present Value", + "\n", + "\nThe present value ($\\rm{PV}$) can be determined by taking the appropriate elements of the cumulated discounted cashflows. This is done as function of the two [projection parameters](../DataModel/DataStructure#projection-configuration) $\\rm{Shift}$ ($S$) and $\\rm{TimeStep}$ ($TS$):", + "\n", + "\n$$", + "\n\\text{PV}(S, TS) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{PV Base}_{S} ~, & \\text{if Valuation Period is Beginning of Period} \\\\", + "\n\\text{PV Base}_{S+TS/2 -1} ~, & \\text{if Valuation Period is Mid of Period} \\\\", + "\n\\sum_{i=S}^{S + TS - 1}\\text{PV Base}_{i} ~, & \\text{if Valuation Period is Delta} \\\\", + "\n\\text{PV Base}_{S + TS} ~, & \\text{if Valuation Period is End of Period} \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere [PV Base](#present-value-base) is defined below, and the term $TS/2$ uses MidpointRounding.AwayFromZero (as defined by *https:[]()//docs.microsoft.com/en-us/dotnet/api/system.midpointrounding?view=net-6.0)*: rounding to the nearest number, away from zero in the exact halfway case. Furthermore, if the array is smaller than the index, then the last element is returned.", + "\n", + "\nFor instance, for the current year and year-to-date view we have $S=0$ and $TS=3$ for the first quarter, $TS=6$ for the 2nd quarter and so on.", + "\nFor the projection values of next year first quarter we would have $S=12$ and $TS=3$, etc." + ], + "metadata": {} + }, + { + "id": "a_j0Wz_NsEeWjap6zY-mDA", + "cell_type": "code", + "source": [ + "public interface IWithGetValueFromValues : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", + "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", + "\n ", + "\n public double GetValueFromValues(double[] Values)", + "\n {", + "\n return GetStorage().GetValuationPeriod(Identity.Id) switch {", + "\n ValuationPeriod.BeginningOfPeriod => Values.ElementAtOrDefault(shift),", + "\n ValuationPeriod.MidOfPeriod => Values.ElementAtOrDefault(shift + Convert.ToInt32(Math.Round(timeStep / 2d, MidpointRounding.AwayFromZero)) - 1),", + "\n ValuationPeriod.Delta => Values.Skip(shift).Take(timeStep).Sum(),", + "\n ValuationPeriod.EndOfPeriod => Values.ElementAtOrDefault(shift + timeStep),", + "\n ValuationPeriod.NotApplicable => default", + "\n };", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LX0IfHO1HkG3juJfHtyRsQ", + "cell_type": "markdown", + "source": [ + "An example of Projected Present Value calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." + ], + "metadata": {} + }, + { + "id": "JablJ7mjvkSSqXmjUWZ-mg", + "cell_type": "markdown", + "source": [ + "", + "\n### Interest Accretion", + "\n", + "\nSince the Interest Accretion cashflows are typically not provided as input (as they can be computed from its parent AocStep), its present values can be computed as follows:", + "\n", + "\n$$", + "\n\\text{InterestAccretion}_i(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\big(\\text{CDC}_i(\\text{Parent AoC step}) - \\text{Nominal}_i(\\text{parent AoC step}) \\big) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, & \\text{if Amount Type's Transaction Period is Beginning of Period} \\\\", + "\n\\text{CDC}_i(\\text{parent AoC step}) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\n
Due to the Credit Default Risk of a reinsurance partner, the logic to compute the Interest Accretion for this Amount Type must be defined separately. Since it is based on Claims, the Period Type is implicitly defined." + ], + "metadata": {} + }, + { + "id": "vGVQDaWg2UeXvSxdJ18zpA", + "cell_type": "code", + "source": [ + "public interface IWithInterestAccretion : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n private double[] parentDiscountedValues => GetScope(Identity).Values; ", + "\n private double[] parentNominalValues => GetScope(Identity).Values;", + "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", + "\n ", + "\n double[] GetInterestAccretion() ", + "\n {", + "\n var periodType = GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType);", + "\n var ret = new double[parentDiscountedValues.Length];", + "\n ", + "\n switch (periodType) {", + "\n case PeriodType.BeginningOfPeriod :", + "\n for (var i = 0; i < parentDiscountedValues.Length; i++)", + "\n ret[i] = (parentDiscountedValues[i] - parentNominalValues[i]) * (GetElementOrDefault(monthlyInterestFactor, i/12) - 1d );", + "\n break;", + "\n default :", + "\n for (var i = 0; i < parentDiscountedValues.Length; i++)", + "\n ret[i] = parentDiscountedValues[i] * (GetElementOrDefault(monthlyInterestFactor, i/12) - 1d );", + "\n break;", + "\n }", + "\n ", + "\n return ret;", + "\n }", + "\n}", + "\n", + "\npublic interface IWithInterestAccretionForCreditRisk : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n private double[] nominalClaimsCashflow => GetScope(Identity).Values;", + "\n private double[] nominalValuesCreditRisk => -1 * GetScope(Identity with {Id = Identity.Id with {AocType = AocTypes.CF}}).Values;", + "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", + "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", + "\n ", + "\n double[] GetInterestAccretion() ", + "\n {", + "\n var interestOnClaimsCashflow = new double[nominalClaimsCashflow.Length];", + "\n var interestOnClaimsCashflowCreditRisk = new double[nominalClaimsCashflow.Length];", + "\n var effectCreditRisk = new double[nominalClaimsCashflow.Length];", + "\n for (var i = nominalClaimsCashflow.Length - 1; i >= 0; i--) {", + "\n interestOnClaimsCashflow[i] = 1 / GetElementOrDefault(monthlyInterestFactor, i/12) * (interestOnClaimsCashflow.ElementAtOrDefault(i + 1) + nominalClaimsCashflow[i] - nominalClaimsCashflow.ElementAtOrDefault(i + 1));", + "\n interestOnClaimsCashflowCreditRisk[i] = 1 / GetElementOrDefault(monthlyInterestFactor, i/12) * (Math.Exp(-nonPerformanceRiskRate) * interestOnClaimsCashflowCreditRisk.ElementAtOrDefault(i + 1) + nominalClaimsCashflow[i] - nominalClaimsCashflow.ElementAtOrDefault(i + 1));", + "\n effectCreditRisk[i] = interestOnClaimsCashflow[i] - interestOnClaimsCashflowCreditRisk[i];", + "\n }", + "\n ", + "\n return effectCreditRisk - nominalValuesCreditRisk;", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "f_Nqjp76YUWFtL08hw0iTg", + "cell_type": "markdown", + "source": [ + "An example of the Interest Accretion calculations can be found [here](../Test/SpecificationsImportCashflows#interest-accretion)." + ], + "metadata": {} + }, + { + "id": "lWN9DuSvtkWi8KPDtnLcZA", + "cell_type": "markdown", + "source": [ + "", + "\n### Present Value Base", + "\n", + "\nThe PV Base values are valid for all choices of the [Economic Basis](../DataModel/DataStructure#economic-basis):", + "\n", + "\n$$", + "\n\\text{PV Base}_i (\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n\\text{CDC}_i ~, & \\text{if AoCType = BOP} \\\\", + "\n-\\text{Nominal}_i(\\text{Parent AoC step}) ~, & \\text{if AoCType = CF } \\\\", + "\n\\text{InterestAccretion}_i ~, & \\text{if AoCType = IA } \\\\", + "\n0 ~, & \\text{if AoCType = AM } \\\\\\", + "\n\\text{CDC}_i(\\text{Parent AoC step}) ~, & \\text{if AoCType = EOP } \\\\", + "\n\\text{TelescopingDifference}_i ~, & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere $i$ denotes the months, and the [$\\rm{TelescopingDifference}_i$](#telescopic-difference) and the [$\\rm{InterestAccretion}_i$](#interest-accretion) quantities are defined above." + ], + "metadata": {} + }, + { + "id": "NX2BdeLNxk2VWROO8E5pBg", + "cell_type": "code", + "source": [ + "public interface PvBase : IWithGetValueFromValues", + "\n{ ", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", + "\n || x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode))", + "\n .WithApplicability(x => (x.Identity.Id.AocType == AocTypes.BOP && x.Identity.Id.Novelty != Novelties.C) || x.Identity.Id.AocType == AocTypes.EOP)", + "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.IA)", + "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.IA)", + "\n .WithApplicability(x => new string[]{AocTypes.BOP, AocTypes.EA, AocTypes.AM, AocTypes.RCU}.Contains(x.Identity.Id.AocType) ) //add here combination CRU for At !CDR?", + "\n );", + "\n ", + "\n [NotVisible][IdentityProperty][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => GetContext();", + "\n ", + "\n [NotVisible]", + "\n double[] Values => GetScope(Identity).Values;", + "\n ", + "\n public double Value => GetValueFromValues(Values);", + "\n}", + "\n", + "\npublic interface ComputePvBaseWithIfrsVariable : PvBase", + "\n{", + "\n double PvBase.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.CalculationType, EconomicBasis, Identity.AccidentYear); //unify CalculationType and EstimateTypeGet", + "\n double[] PvBase.Values => Enumerable.Empty().ToArray();", + "\n}", + "\n", + "\npublic interface PvBaseFromDiscountedCashflow : PvBase", + "\n{", + "\n [NotVisible]", + "\n double[] PvBase.Values => GetScope(Identity).Values;", + "\n}", + "\n", + "\npublic interface CashflowAocStep : PvBase", + "\n{", + "\n [NotVisible]", + "\n double[] PvBase.Values => -1d * GetScope(Identity).Values;", + "\n}", + "\n", + "\npublic interface PvBaseWithInterestAccretion : PvBase, IWithInterestAccretion", + "\n{", + "\n [NotVisible]", + "\n double[] PvBase.Values => GetInterestAccretion();", + "\n}", + "\n", + "\npublic interface PvBaseWithInterestAccretionForCreditRisk : PvBase, IWithInterestAccretionForCreditRisk", + "\n{", + "\n [NotVisible]", + "\n double[] PvBase.Values => GetInterestAccretion();", + "\n}", + "\n", + "\npublic interface EmptyValuesAocStep : PvBase", + "\n{", + "\n [NotVisible]", + "\n double[] PvBase.Values => Enumerable.Empty().ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yZbP0Jm3ckC1XQBFERPm_g", + "cell_type": "markdown", + "source": [ + "An example of the Present Value Base calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." + ], + "metadata": {} + }, + { + "id": "lWMlf8gT5kGtPaXz4CcdLg", + "cell_type": "markdown", + "source": [ + "", + "\n### Current and Locked", + "\n", + "\nPV Current and PV Locked below basically hold the Present Values [PV](#present-value) computed using the **Current** yield curves and the **Locked** yield curves, respectively.", + "\n", + "\nValues are available for each AmountType (by calling PvLocked.ByAmountType):", + "\n", + "\n$$", + "\n\\text{PV Locked}(\\text{AoC step}, \\text{Amount Type}) = \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = L}}", + "\n$$", + "\n", + "\n$$", + "\n\\text{PV Current}(\\text{AoC step}, \\text{Amount Type}) = \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = C}}", + "\n$$", + "\n", + "\n", + "\nAnd aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type) (by calling PvLocked.Value):", + "\n", + "\n$$", + "\n\\text{PV Locked}(\\text{AoC step}) = \\sum_{\\text{Amount Types}} \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = L}}", + "\n$$", + "\n", + "\n$$", + "\n\\text{PV Current}(\\text{AoC step}) = \\sum_{\\text{Amount Types}} \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = C}}", + "\n$$", + "\n", + "\nThese are used in the BBA methodology, whereby in the CSM calculations only PV Locked is used, and both of them are stored in the database under the [IfrsVariable](../DataModel/DataStructure#ifrs-variable) data structure." + ], + "metadata": {} + }, + { + "id": "1wOqzclAjkaUcoGzwf1ldQ", + "cell_type": "code", + "source": [ + "public interface PvLocked : IScope", + "\n{ ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.L;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.BE;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", + "\n ", + "\n [NotVisible]", + "\n PvBase[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .ToArray();", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}", + "\n", + "\npublic interface PvCurrent : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.C;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.BE;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n PvBase[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .ToArray();", + "\n ", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6pCT1yWm30S4fz2w2Km62w", + "cell_type": "markdown", + "source": [ + "", + "\n## Risk Adjustment", + "\n", + "\nRisk Adjustment values ($\\rm{RA}$) are accessible from the [PV Base](#present-value-base) data and have [Calculation Type](../DataModel/DataStructure#calculation-type) $RA$. In particular, the Locked-In and Current values are given by:", + "\n", + "\n$$", + "\n\\text{RA Locked}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = L}}", + "\n$$", + "\n", + "\n$$", + "\n\\text{RA Current}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = C}}", + "\n$$", + "\n", + "\nwhere PV is defined [above](#present-value) and uses the input cashflows with Calculation Type = RA." + ], + "metadata": {} + }, + { + "id": "TrbvThWf6EergPrBDCULNQ", + "cell_type": "code", + "source": [ + "public interface RaLocked : IScope", + "\n{ ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.L;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.RA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", + "\n ", + "\n PvBase[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray();", + "\n ", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}", + "\npublic interface RaCurrent : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.C;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.RA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", + "\n ", + "\n PvBase[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n ", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lCTjmXtNM0anxWCIugOk1g", + "cell_type": "markdown", + "source": [ + "", + "\n## Amortization", + "\n", + "\nFor the Amortization AoC Step (AoC Type **AM**), the amortization factors to be used are defined below." + ], + "metadata": {} + }, + { + "id": "1EJRTEzTH02xfXBuVK6aQQ", + "cell_type": "markdown", + "source": [ + "", + "\n### Coverage Units", + "\n", + "\nThe coverage unit (CU) of a GIC is introduced in the standard as the quantity of the service provided in that GIC. The service is", + "\nmeasured by considering the quantity of benefits provided as well as the expected coverage period of the GIC.", + "\n", + "\nThe cashflows of coverage units are retrieved from the discounted cashflows with [Calculation Type](../DataModel/DataStructure#calculation-type) CU." + ], + "metadata": {} + }, + { + "id": "8s4nf1G3h0O5cmlvAC3QLw", + "cell_type": "code", + "source": [ + "public interface CoverageUnitCashflow : IScope", + "\n{ ", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.CU;", + "\n ", + "\n double[] Values => GetScope((Identity, (string)null, CalculationType, (int?)null)).Values;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BTET6Z8yrkOpMBOGK5Bu3g", + "cell_type": "markdown", + "source": [ + "", + "\n### Amortization Factor" + ], + "metadata": {} + }, + { + "id": "m1VQAxKwaEuv9KI6qEVFxA", + "cell_type": "markdown", + "source": [ + "For a certain GIC, the monthly Amortization Factors $\\text{Monthly }AF_i$ are computed from the cashflows of the underlying coverage unit for that GIC:", + "\n", + "\n$$", + "\n\\text{Monthly }AF_i = 1 - \\frac{ \\text{Nominal}_i(CL)} {\\text{CDC}_i(CL) } ~.", + "\n$$", + "\n", + "\nwhere:", + "\n- $i$ denotes a monthly period;", + "\n- the nominal cash flows $\\text{Nominal}_i(CL)$ are the nominal cashflows of the coverage unit for the AoC Step **Combined Liability** (CL) (input data);", + "\n- and the corresponding cumulated discounted cashflows $\\text{CDC}_i$ are defined [above](#cumulated-discounted-cashflows)." + ], + "metadata": {} + }, + { + "id": "ilj2SgcU7kOjz53Sf946cw", + "cell_type": "code", + "source": [ + "public interface MonthlyAmortizationFactorCashflow : IScope", + "\n{", + "\n private double[] NominalCuCashflow => GetScope((Identity with {AocType = AocTypes.CL}, (string)null, CalculationTypes.CU, (int?)null)).Values;", + "\n private double[] DiscountedCuCashflow => GetScope(Identity with {AocType = AocTypes.CL}, o => o.WithContext(EconomicBasis)).Values;", + "\n ", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n double[] MonthlyAmortizationFactors => Identity.AocType switch {", + "\n AocTypes.AM => NominalCuCashflow.Zip(DiscountedCuCashflow, //Extract to an other scope with month in the identity to avoid Zip?", + "\n (nominal, discountedCumulated) => discountedCumulated >= Precision ", + "\n ? 1 - nominal / discountedCumulated ", + "\n : 0).ToArray(),", + "\n _ => Enumerable.Empty().ToArray(),", + "\n };", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bqUlBh41xUCZmzV497BLug", + "cell_type": "markdown", + "source": [ + "For a certain projection period - defined by the Shift, $S$, and the Time-Step, $TS$, parameters - the Amortization Factor is then given by the product of the corresponding monthly amortization factors:", + "\n", + "\n$$", + "\nAF = \\prod _{i = S}^{TS} \\text{Monthly }AF_i ~.", + "\n$$", + "\n", + "\nEach GIC will have his own AF." + ], + "metadata": {} + }, + { + "id": "6OE1dyBDq0-W4sMSuAQoeQ", + "cell_type": "code", + "source": [ + "public interface CurrentPeriodAmortizationFactor : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => ", + "\n s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", + "\n || x.GetStorage().IsSecondaryScope(x.Identity.DataNode)));", + "\n ", + "\n private int shift => GetStorage().GetShift(0);//Identity.ProjectionPeriod", + "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.ProjectionPeriod", + "\n ", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n string EstimateType => EstimateTypes.F;", + "\n double Value => GetScope(Identity)", + "\n .MonthlyAmortizationFactors", + "\n .Skip(shift)", + "\n .Take(timeStep)", + "\n .Aggregate(1d, (x, y) => x * y);", + "\n}", + "\n", + "\npublic interface AmfFromIfrsVariable : CurrentPeriodAmortizationFactor", + "\n{", + "\n double CurrentPeriodAmortizationFactor.Value => GetStorage().GetValue(Identity, (string)null, EstimateType, EconomicBasis, (int?)null); //unify CalculationType and EstimateTypeGet", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jpW8fnmKpEi5m8fmZckqfA", + "cell_type": "markdown", + "source": [ + "", + "\n## Actual Values", + "\n", + "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", + "\n- Actuals (A)", + "\n- Advance Actuals (AA)", + "\n- Overdue Actuals (OA)", + "\n- Deferrable Actuals (DA)", + "\n", + "\nwith the Estimate Type's system name shown between parenthesis above.", + "\n", + "\nThe following simplified AoC Chain applies for Advance and Overdue Actuals:", + "\n
 BOP", + "\n
 Release", + "\n
 Write-off", + "\n
 EOP" + ], + "metadata": {} + }, + { + "id": "EBK-msISl0WxxcRgAvBDWQ", + "cell_type": "markdown", + "source": [ + "", + "\n### Actual Base", + "\n", + "\nThe Actual Base sets values for actual, advance, and overdue as follows:", + "\n", + "\n$$", + "\n\\text{Actual Base} (\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n0 ~, & \\text{if AoC Step's AoC Type = AM} \\\\", + "\n\\text{Actual Base}(\\rm{BOP}) + \\text{Actual Base}(\\rm{CF}) + \\text{Actual Base}(\\rm{WO}) ~, & \\text{if AoC Step's AoC Type = EOP and EstimateType is not A} \\\\", + "\n\\text{Imported Actual} ~, & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the value is also function of the [Estimate Type](../DataModel/DataStructure#EstimateType) and [Amount Type](../DataModel/DataStructure#AmountType), and the $\\text{Imported Actual}$ value is described [here]()." + ], + "metadata": {} + }, + { + "id": "_w7DsklRxEy1-gr0L3xnxQ", + "cell_type": "code", + "source": [ + "public interface ActualBase : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Actual ", + "\n && !x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode)", + "\n && x.Identity.Id.AocType == AocTypes.AM)", + "\n .WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow ", + "\n && !x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode)", + "\n && x.Identity.Id.AocType == AocTypes.EOP ", + "\n && x.Identity.EstimateType != EstimateTypes.A)", + "\n );", + "\n public double Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear); ", + "\n}", + "\n", + "\npublic interface EndOfPeriodActual : ActualBase", + "\n{", + "\n double ActualBase.Value => GetScope((Identity.Id, InputSource.Actual)).Values", + "\n .Sum(aocStep => GetScope((Identity.Id with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear)).Value);", + "\n}", + "\n", + "\npublic interface EmptyValuesActual : ActualBase", + "\n{", + "\n double ActualBase.Value => 0;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hZgnWCXsbEm7b3a_M5X91Q", + "cell_type": "markdown", + "source": [ + "An example of Actual Base figures can be found [here](../Test/SpecificationsImportActuals#base-actual)." + ], + "metadata": {} + }, + { + "id": "seP-q4-pNEKPbBJB6XWgGQ", + "cell_type": "markdown", + "source": [ + "", + "\n### Actuals", + "\nThe Actuals correspond to ActualBase values with estimate type $A$.", + "\nThe only valid Aoc step is Release:", + "\n", + "\n$$", + "\n\\text{Actual} (\\text{Release}) = \\text{Actual Base} (\\text{Release})|_{\\text{Estimate Type} = A}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "rA5FAU7rP0mVtOb_OMRAQQ", + "cell_type": "code", + "source": [ + "public interface Actual : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.A;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tQS8QPziAEWrDh1ztulzDw", + "cell_type": "markdown", + "source": [ + "", + "\n### Advance Actuals", + "\n", + "\n**Advance Actuals** are those cashflows with due date inside the reporting period but which occured *before* the reporting period - They include:", + "\n- Receivable Claims", + "\n- Receivable Expenses", + "\n- Payable Premiums", + "\n", + "\nAdvance Actuals are given by", + "\n", + "\n$$", + "\n\\text{Advance Actual} (\\text{AoC step}) = \\text{Actual Base} (\\text{AoC step})|_{\\text{Estimate Type} = AA}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "BGCY3AvaxkWvnU8Py4UK5w", + "cell_type": "code", + "source": [ + "public interface AdvanceActual : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.AA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "EDA0vEXMd0602tAx8vQ8Eg", + "cell_type": "markdown", + "source": [ + "", + "\n### Overdue Actuals", + "\n", + "\n**Overdue Actuals** are those cashflows with due date inside the reporting period but which occur *after* the reporting period - They contain:", + "\n- Payable Claims", + "\n- Payable Expenses", + "\n- Receivable Premiums", + "\n", + "\nThe sign convention is the inverse of the default behavior - In particular: Premiums have positive value, whereas Claims and Expenses have negative value.", + "\n", + "\nThe Overdue Actuals are given by", + "\n", + "\n$$", + "\n\\text{Overdue Actual} (\\text{AoC step}) = \\text{Actual Base} (\\text{AoC step})|_{\\text{Estimate Type} = OA}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "JhdC-O-53k-OPdsSNtyTqQ", + "cell_type": "code", + "source": [ + "public interface OverdueActual : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.OA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BU02PReB0UyuCXL3rgF7kw", + "cell_type": "markdown", + "source": [ + "", + "\n### Deferrable Actuals", + "\n", + "\nFinally, Deferrable Actuals are given by", + "\n", + "\n$$", + "\n\\text{Deferrable Actual} (\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n\\sum_{\\text{Amount Type}~\\in~\\text{\\{ACA, AEA}\\}}\\text{Actual Base}(\\rm{CF})|_{\\text{Estimate Type = A}} ~, & \\text{if AoC Step's AoC Type = CF } \\\\", + "\n- \\text{Amortization Factor} \\cdot \\big( \\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) \\big) ~, & \\text{if AoC Step's AoC Type = AM } \\\\", + "\n\\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) + \\text{Deferrable Actual}(\\rm{AM}) ~, & \\text{if AoC Step's AoC Type = EOP } \\\\", + "\n\\text{Input Actual}|_{\\text{Estimate Type = DA}} ~, & \\text{ otherwise } \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere $ACA$ and $AEA$ are *Aquisition* Amount Types from **Attributable Commission** and **Attributable Expenses**, respectively." + ], + "metadata": {} + }, + { + "id": "ydbJzjQG6kGLXvpaU9QqxQ", + "cell_type": "code", + "source": [ + "public interface DeferrableActual : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.VFA, ", + "\n p => p.ForMember(s => s.EconomicBasis))", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.AM)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)", + "\n );", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.DA;", + "\n ", + "\n [NotVisible] string EconomicBasis => EconomicBases.L;", + "\n ", + "\n public double Value => GetStorage().GetValue(Identity, (string)null, EstimateType, (int?)null);", + "\n}", + "\n", + "\npublic interface DeferrableActualForCurrentBasis : DeferrableActual", + "\n{", + "\n [NotVisible] string DeferrableActual.EconomicBasis => EconomicBases.C;", + "\n}", + "\n", + "\npublic interface ReleaseDeferrable : DeferrableActual", + "\n{", + "\n double DeferrableActual.Value => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(at => GetScope((Identity, at, EstimateTypes.A, (int?)null)).Value);", + "\n}", + "\n", + "\npublic interface AmortizationDeferrable : DeferrableActual", + "\n{", + "\n private double AmortizationFactor => GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;", + "\n private double AggregatedDeferrable => GetScope((Identity, InputSource.Actual)).Values", + "\n .Sum(aocStep => GetScope(Identity with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}).Value);", + "\n double DeferrableActual.Value => -1d * AggregatedDeferrable * AmortizationFactor;", + "\n}", + "\n", + "\npublic interface EndOfPeriodDeferrable : DeferrableActual", + "\n{", + "\n double DeferrableActual.Value => GetScope((Identity, InputSource.Actual)).Values", + "\n .Sum(aocStep => GetScope(Identity with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}).Value);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "p-VbKXd52UuaKecFYnE8iQ", + "cell_type": "markdown", + "source": [ + "An example of Deferrable Actual figures can be found [here](../Test/SpecificationsImportActuals#deferrable-actual)." + ], + "metadata": {} + }, + { + "id": "Mtf0XXuvUkS76O6DBZUr4A", + "cell_type": "markdown", + "source": [ + "", + "\n## Contractual Service Margin, Loss Component and Loss Recovery Component", + "\n", + "\nThe Contractual Service Margin ($CSM$) denotes the unearned profit from an insurance contract or group of insurance contracts and plays a critical role in the calculation of profit & loss values. Similarly, the unearned loss is denoted by Loss Component ($LC$), Loss Recovery Component in the case of reinsurance contracts." + ], + "metadata": {} + }, + { + "id": "Wq-e5YleykGCYEopzDLT4A", + "cell_type": "markdown", + "source": [ + "## Experience Adjustment on Premium" + ], + "metadata": {} + }, + { + "id": "JwOnE_oxnE6u4nU3ZQku3Q", + "cell_type": "markdown", + "source": [ + "The Experience Adjustment (EA) on Premiums weights the cash-flow (CF aocSteps) for premium amount types by the PremiumAllocationFactor input for each group of insurance contract. ", + "\nThe contributions of present values and actuals are computed separately.", + "\n", + "\n$$", + "\nEA (\\rm{PV}) = \\text{Premium Allocation Factor} \\cdot \\big( PV (\\text{AocType = CF}) \\big)~, \\\\", + "\n$$", + "\n$$", + "\nEA (\\text{Actual}) = \\text{Premium Allocation Factor} \\cdot \\big( \\text{Actual}(\\text{AocType = CF}) + \\text{Advance Actual}(\\text{AocType = CF})+ \\text{Overdue Actual}(\\text{AocType = CF}) \\big) ~,", + "\n$$", + "\nwhere amount type premium and its children are considered, novelties in-force and new business are considered for $PV$ whereas novelty combined is considered for Actual. The allocation is always done in the finest granularity (novelty, line of business, ..) possible." + ], + "metadata": {} + }, + { + "id": "pEi0POgs0UejZ_BJaXi_LQ", + "cell_type": "code", + "source": [ + "public interface BeExperienceAdjustmentForPremium : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s", + "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", + "\n", + "\n string EstimateType => EstimateTypes.BEPA;", + "\n string EconomicBasis => EconomicBases.L;", + "\n ", + "\n PvBase[] ByAmountType => GetStorage().GetPremiums().Select(pr => GetStorage().GetPremiumAllocationFactor(Identity) * GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n}", + "\n", + "\npublic interface DefaultValueBeExperienceAdjustmentForPremium : BeExperienceAdjustmentForPremium", + "\n{", + "\n PvBase[] BeExperienceAdjustmentForPremium.ByAmountType => Enumerable.Empty().ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CA2eQXhYYUevjiAr92nN6Q", + "cell_type": "code", + "source": [ + "public interface ActualExperienceAdjustmentForPremium : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s", + "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", + "\n ", + "\n public ActualBase[] ByAmountTypeAndEstimateType => GetStorage().GetPremiums().SelectMany(pr => ", + "\n GetStorage().ExperienceAdjustEstimateTypeMapping.Keys", + "\n .Select(et => GetStorage().GetPremiumAllocationFactor(Identity) * ", + "\n GetScope((Identity, pr, et, (int?)null)))).ToArray(); ", + "\n}", + "\n", + "\npublic interface DefaultValueActualExperienceAdjustmentForPremium : ActualExperienceAdjustmentForPremium", + "\n{", + "\n ActualBase[] ActualExperienceAdjustmentForPremium.ByAmountTypeAndEstimateType => Enumerable.Empty().ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "czmwLF-VTkKtolr0jqiX8w", + "cell_type": "markdown", + "source": [ + "", + "\n## Technical Margin", + "\n", + "\nFor the computation of the $CSM$ or $LC$ component values for each step of the [AoC Step Structure](#aoc-step-structure), it is convenient to introduce the ", + "\nnotion of technical margin $TM$. In the case of BBA methodology, the Locked-in interest rates discounting is applied to obtain the PV and RA values.", + "\n", + "\nThis can be summarized as follows:", + "\n", + "\n$$", + "\nTM(s) = \\left\\{", + "\n\\begin{array}{rl}", + "\nTM(\\rm{EOP}) \\text{ of the previous period} ~ & \\text{if }s = \\text{BOP and Novelty is In-Force}.", + "\n\\\\", + "\n0 ~ & \\text{if }s = \\text{CF}.", + "\n\\\\", + "\nIAF \\cdot~\\text{Aggregated}~TM(\\text{IA}) ~ & \\text{if }s = \\text{IA and Novelty is In-Force}.", + "\n\\\\", + "\n\\rm{Premiums} + \\text{Attributable Expense and Commissions} + \\text{Investment Claims} ~ & \\text{if }s = \\text{EA}.", + "\n\\\\", + "\n-AF \\cdot~\\text{Aggregated}~TM(\\text{AM})~ & \\text{if }s = \\text{AM}.", + "\n\\\\", + "\n\\text{PV}(\\text{s})\\bigg|_{\\substack{\\text{Non Attributable} \\\\ \\text{Amount Types} \\\\ \\text{excluded}}} ", + "\n+ \\text{RA}(\\text{s})~ & \\text{otherwise} ", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere", + "\n", + "\n$$", + "\n\\text{Aggregated}~TM (\\text{AoC step}) = \\sum_{s\\in\\text{ previous AoC steps}} TM(s)~.", + "\n$$", + "\n", + "\nand the Interest Accretion Factor ($IAF$) is given by", + "\n", + "\n$$", + "\nIAF = \\prod_{i=1}^{TS} \\text{Interest}_i - 1", + "\n$$", + "\n", + "\nwhere $\\text{Interest}_i$ is the monthly interest factor obtained from the [Yield Curve](#yield-curves) and $TS$ is the Time-Step.", + "\n", + "\nFinally, the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", + "\n", + "\n$$", + "\n\\rm{Premiums} = \\sum_{\\text{Amount Type}\\in\\{\\text{PR and its children}\\}}", + "\nEA(\\rm{PV}) - EA(\\text{Actual}) ~,", + "\n$$", + "\n", + "\n$$", + "\n\\text{Attributable Expense and Commissions} = \\sum_{\\text{Amount Type}\\in\\{\\rm{ACA}, \\rm{AEA}\\}}", + "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\text{Actual}_{\\text{Novelty=C}} ~,", + "\n$$", + "\n", + "\n$$", + "\n\\text{Investment Claims } = \\sum_{\\text{Amount Type}\\in\\{\\text{ICO and its children}\\}}", + "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}}+ \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~,", + "\n$$", + "\n", + "\nwhere the AoC Step **CF** is implicit for all formulas, $PV$ is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **AA**, and **OA** (see details [here](#actual-values))." + ], + "metadata": {} + }, + { + "id": "uWXzMWj2I0mfBjJ6P43ZFg", + "cell_type": "code", + "source": [ + "public interface TechnicalMargin : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.VFA, p => p.ForMember(s => s.EconomicBasis))", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP && x.Identity.Novelty == Novelties.I)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.IA && x.Identity.Novelty == Novelties.I)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EA && !x.Identity.IsReinsurance)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.AM)", + "\n );", + "\n ", + "\n [NotVisible] string EconomicBasis => EconomicBases.L;", + "\n ", + "\n double Value => GetScope(Identity.DataNode).BeAmountTypes", + "\n .Except(GetStorage().GetNonAttributableAmountType())", + "\n .Sum(at => GetScope((Identity, at, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", + "\n GetScope(Identity).Value;", + "\n ", + "\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values", + "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);", + "\n}", + "\n", + "\npublic interface TechnicalMarginForCurrentBasis : TechnicalMargin", + "\n{", + "\n [NotVisible] string TechnicalMargin.EconomicBasis => EconomicBases.C;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForBOP : TechnicalMargin", + "\n{", + "\n private double ValueCsm => GetStorage().GetValue(Identity, null, EstimateTypes.C, null);", + "\n private double ValueLc => GetStorage().GetValue(Identity, null, EstimateTypes.L, null);", + "\n private double ValueLr => GetStorage().GetValue(Identity, null, EstimateTypes.LR, null);", + "\n ", + "\n double TechnicalMargin.Value => -1d * ValueCsm + ValueLc + ValueLr;", + "\n}", + "\n", + "\npublic interface TechnicalMarginDefaultValue : TechnicalMargin", + "\n{", + "\n double TechnicalMargin.Value => default;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForIA : TechnicalMargin", + "\n{", + "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", + "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", + "\n ", + "\n private double[] monthlyInterestFactor => GetScope(Identity, o => o.WithContext(EconomicBasis)).Interest;", + "\n ", + "\n private double interestAccretionFactor => Enumerable.Range(shift,timeStep)", + "\n .Select(i => GetElementOrDefault(monthlyInterestFactor, i/12))", + "\n .Aggregate(1d, (x, y) => x * y ) - 1d;", + "\n ", + "\n double TechnicalMargin.Value => AggregatedValue * interestAccretionFactor;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForEA : TechnicalMargin", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilderInner(ApplicabilityBuilder builder) => ", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.IsReinsurance));", + "\n ", + "\n private string referenceAocType => GetScope(Identity).Value.AocType;", + "\n ", + "\n private double premiums => GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", + "\n .Sum(n => GetScope(Identity with {AocType = referenceAocType, Novelty = n}).ByAmountType.Sum(sc => sc.Value)) -", + "\n GetScope(Identity with {AocType = referenceAocType, Novelty = Novelties.C}).ByAmountTypeAndEstimateType.Sum(sc => sc.Value);", + "\n ", + "\n private double attributableExpenseAndCommissions => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(d =>", + "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, d, EstimateTypes.A, (int?)null)).Value);", + "\n", + "\n private double investmentClaims => GetStorage().GetInvestmentClaims().Sum(ic =>", + "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.A, (int?)null)).Value - ", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.AA, (int?)null)).Value -", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.OA, (int?)null)).Value);", + "\n ", + "\n double TechnicalMargin.Value => premiums + attributableExpenseAndCommissions + investmentClaims;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForAM : TechnicalMargin", + "\n{", + "\n double TechnicalMargin.Value => -1d * AggregatedValue * GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "eV_qYONYOU-QbM_aQVg7vg", + "cell_type": "markdown", + "source": [ + "", + "\n## Switch Logic", + "\n ", + "\nThe $CSM$ and $LC$ components are computed from the [technical margin](#technical-margin). In particular, for a given AoC step $s$, TM is allocated to the $LC$ when $\\text{Aggregated } TM$ is positive whereas it is allocated to the $CSM$ when $\\text{Aggregated } TM$ is negative:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\nCSM({\\text{Aoc step}}) = 0,~~ LC({\\text{AoC step}}) = TM({\\text{AoC step}}) ~ & \\text{if }\\text{Aggregated }TM({\\text{AoC step}}) > 0.", + "\n\\\\", + "\nCSM({\\text{Aoc step}}) = - TM({\\text{AoC step}}),~~ LC({\\text{AoC step}}) = 0 ~ & \\text{otherwise} ", + "\n\\end{array}", + "\n$$", + "\n", + "\n", + "\nThe figures reported under CSM are the opposite of the TM value in order to satisfy our sign convention.", + "\n", + "\nIt is possible to switch from $CSM$ to $LC$ and from $LC$ to $CSM$ at any AoC step $s$ with the only exception of **Amortization** where there is no switch from the previous step.", + "\nWhen a switch occurs the total contribution to the $CSM$ ($LC$) prior the switching step is brought to 0 and the remaing amount is allocated to $LC$ ($CSM$).", + "\n", + "\n", + "\n### Gross case (i.e. no reinsurance)", + "\n", + "\nThe switch logic is applied ***separately*** to the In-Force and New Business novelties. The Combined Liability Aoc Step **CL** will bring both contributions to CSM and LC together as the novelities are summed up.", + "\n", + "\nIn detail, and as we go through the AoC steps in the AoC chain, we have", + "\n", + "\n**A)** For the **BOP**:", + "\n$$", + "\n\\begin{array}{rl}", + "\nCSM(\\text{BOP}) &= CSM(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", + "\n\\\\", + "\nLC(\\text{BOP}) &= LC(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", + "\n\\end{array}", + "\n$$", + "\n", + "\n", + "\n**B)** For the **following AoC steps**, the switch logic is preferably formulated using the delta variations between steps, $\\Delta CSM$ and $\\Delta LC$ for the CSM and the LC respectively.", + "\n", + "\nThe switch logic for these AoC steps with the *exception* of Combined Liability is:", + "\n", + "\nIf $\\text{Aggregated }TM(\\text{AoC Step}) > 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\le 0$, then there is a switch from $LC$ to $CSM$:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\text{Aggregated } TM(\\text{AoC Step})", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= -\\text{Aggregated } TM(\\text{AoC Step}) ", + "\n\\end{array}", + "\n$$", + "\n", + "\nOn the other hand, if $\\text{Aggregated }TM(\\text{AoC Step}) \\le 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) > 0$, then the switch is from $CSM$ to $LC$:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= \\text{Aggregated } TM(\\text{AoC Step}) ", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= TM(\\text{AoC Step}) + \\text{Aggregated } TM(\\text{AoC Step}) ", + "\n\\end{array}", + "\n$$", + "\n", + "\nIf there is no switch from $CSM$, i.e. $\\text{Aggregated }TM(\\text{AoC Step}) \\le 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\le 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step})", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= 0", + "\n\\end{array}", + "\n$$", + "\n", + "\nAnd finally, if there is no switch from $LC$, i.e. $\\text{Aggregated }TM(\\text{AoC Step}) > 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\ge 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= 0", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= TM(\\text{AoC Step})", + "\n\\end{array}", + "\n$$", + "\n", + "\n**C)** For the AoC step Combined Liability **CL**, the switch logic is similar to the one above, except that a switch from $LC$ to $CSM$ can happen **because of New Business and despite of In-Force**, in which case we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\big(\\text{Aggregated } TM(\\text{Last In-Force AoC step})+TM(\\text{Last In-Force AoC step}) \\big)", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= -\\big(\\text{Aggregated } TM(\\text{Last In-Force AoC step}) + TM(\\text{Last In-Force AoC step}) \\big)", + "\n\\end{array}", + "\n$$", + "\n", + "\nIf, on the other hand, the switch from $LC$ to $CSM$ happens **because of In-Force and despite of New Business**, then we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\big(\\text{Aggregated } TM(\\text{Last NB AoC step})+TM(\\text{Last NB AoC step}) \\big)", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= -\\big(\\text{Aggregated } TM(\\text{Last NB AoC step}) + TM(\\text{Last NB AoC step}) \\big)", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor the switch in the other direction, i.e. from $CSM$ to $LC$ the formulas are similar except that LC and CSM are swapped.", + "\n", + "\n**D)** Finally, for the last AoC step, the **EOP**, we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\nCSM(\\text{EOP}) &= \\sum_{s~\\in~\\text{previous AoC steps}}\\Delta CSM(s)", + "\n\\\\", + "\nLC(\\text{EOP}) &= \\sum_{s~\\in~\\text{previous AoC steps}}\\Delta LC(s)", + "\n\\end{array}", + "\n$$", + "\n", + "\n", + "\n### Reinsurance case", + "\n", + "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the gross Technical Margins multiplied by the weights coming from the Reinsurance Coverage Parameter (see [Data Node Parameters](..\\DataModel/DataStructure#data-node-parameters)). In case a GRIC has multiple GICs, then these weighted $TM$s are aggregated." + ], + "metadata": {} + }, + { + "id": "UnZAtItpLkaBp5iMJesSzw", + "cell_type": "code", + "source": [ + "public interface AllocateTechnicalMargin: IScope", + "\n{", + "\n //Switch", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ", + "\n builder.ForScope(s => s", + "\n .WithApplicability(x => x.Identity.IsReinsurance && x.Identity.AocType == AocTypes.CL) ", + "\n .WithApplicability(x => x.Identity.IsReinsurance, ", + "\n p => p.ForMember(s => s.ComputedEstimateType)", + "\n .ForMember(s => s.HasSwitch))", + "\n .WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity.DataNode)) ", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CL)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)", + "\n );", + "\n ", + "\n [NotVisible] double AggregatedTechnicalMargin => GetScope(Identity).AggregatedValue; ", + "\n [NotVisible] double TechnicalMargin => GetScope(Identity).Value;", + "\n ", + "\n [NotVisible] string ComputedEstimateType => ComputeEstimateType(GetScope(Identity).AggregatedValue + TechnicalMargin);", + "\n [NotVisible] bool HasSwitch => ComputedEstimateType != ComputeEstimateType(GetScope(Identity).AggregatedValue);", + "\n ", + "\n //Allocate ", + "\n [NotVisible] string EstimateType => GetContext();", + "\n ", + "\n double Value => (HasSwitch, EstimateType == ComputedEstimateType) switch {", + "\n (true, true) => TechnicalMargin + AggregatedTechnicalMargin,", + "\n (true, false) => -1d * AggregatedTechnicalMargin,", + "\n (false, true) => TechnicalMargin,", + "\n _ => default", + "\n };", + "\n ", + "\n string ComputeEstimateType(double aggregatedTechnicalMargin) => aggregatedTechnicalMargin > Precision ? EstimateTypes.L : EstimateTypes.C;", + "\n}", + "\n", + "\npublic interface ComputeAllocateTechnicalMarginWithIfrsVariable : AllocateTechnicalMargin", + "\n{ ", + "\n double AllocateTechnicalMargin.TechnicalMargin => ComputeTechnicalMarginFromIfrsVariables(Identity);", + "\n double AllocateTechnicalMargin.AggregatedTechnicalMargin => GetScope((Identity, InputSource.Cashflow)).Values", + "\n .Sum(aoc => ComputeTechnicalMarginFromIfrsVariables(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}));", + "\n ", + "\n private double ComputeTechnicalMarginFromIfrsVariables(ImportIdentity id)", + "\n {", + "\n return GetStorage().GetValue(Identity, null, EstimateTypes.LR, null) +", + "\n GetStorage().GetValue(Identity, null, EstimateTypes.L, null) - ", + "\n GetStorage().GetValue(Identity, null, EstimateTypes.C, null);", + "\n }", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForReinsurance : AllocateTechnicalMargin", + "\n{ ", + "\n //TODO add Reinsurance Coverage Update (RCU, Novelty=I) AocStep", + "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);", + "\n ", + "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).TechnicalMargin);", + "\n ", + "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).AggregatedTechnicalMargin);", + "\n ", + "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;", + "\n ", + "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);", + "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => ComputedEstimateType != ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM); ", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForReinsuranceCL : AllocateTechnicalMargin", + "\n{ ", + "\n //In common1", + "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);", + "\n ", + "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).TechnicalMargin);", + "\n ", + "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).AggregatedTechnicalMargin);", + "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;", + "\n ", + "\n string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);", + "\n //In common2", + "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))", + "\n .Values", + "\n .GroupBy(x => x.Novelty)", + "\n .Select(g => g.Last())", + "\n .Sum(aoc => { ", + "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};", + "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ", + "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin", + "\n : (double)default; });", + "\n ", + "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;", + "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue; ", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForCl : AllocateTechnicalMargin", + "\n{", + "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))", + "\n .Values", + "\n .GroupBy(x => x.Novelty)", + "\n .Select(g => g.Last())", + "\n .Sum(aoc => { ", + "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};", + "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ", + "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin", + "\n : (double)default; });", + "\n", + "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;", + "\n ", + "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue;", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForBop : AllocateTechnicalMargin", + "\n{ ", + "\n bool AllocateTechnicalMargin.HasSwitch => false;", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForEop : AllocateTechnicalMargin", + "\n{", + "\n double AllocateTechnicalMargin.Value => GetScope((Identity, InputSource.Cashflow)).Values", + "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);", + "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeEstimateType(AggregatedTechnicalMargin);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vY4oXJJJ8ke97-m8ASMsAw", + "cell_type": "markdown", + "source": [ + "For the **Group of Reinsurance Contracts** (GRICs), the switch is computed within the underlying GIC context and $CSM$ and $LR$ are then computed in the same manner as for the underlying GICs CSM and LC." + ], + "metadata": {} + }, + { + "id": "DqGSuXbt6USNumZ69sErWg", + "cell_type": "markdown", + "source": [ + "The scopes below are simply used to set the appropriate Estimate Type (C for $CSM$, L for $LC$ and LR for $LCR$), as well as to set $CSM$ values to be positive:" + ], + "metadata": {} + }, + { + "id": "n2dT4_znvk2eUSMMef6OIg", + "cell_type": "code", + "source": [ + "public interface Csm : IScope", + "\n{", + "\n [NotVisible]string EstimateType => EstimateTypes.C;", + "\n ", + "\n double Value => -1d * GetScope(Identity, o => o.WithContext(EstimateType)).Value;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1fUoYZjlOki4f5GCvCmpoA", + "cell_type": "code", + "source": [ + "public interface Lc : IScope", + "\n{", + "\n [NotVisible]string EstimateType => EstimateTypes.L;", + "\n ", + "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TmqOsKRObkaw3PKUdp_lDw", + "cell_type": "code", + "source": [ + "public interface LoReCo : IScope", + "\n{ ", + "\n [NotVisible]string EstimateType => EstimateTypes.LR;", + "\n ", + "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_ejvWQaq-kSPyTqB4Y2n9Q", + "cell_type": "markdown", + "source": [ + "## Computing All Scopes", + "\n", + "\nSince all the calculations defined in the various scopes are to be performed together, it is useful to introduce the scope ComputeAllScopes below, which given a certain Import Identity and Import Storage, performs all the calculations (defined above) based on the corresponding data:" + ], + "metadata": {} + }, + { + "id": "68_d30x6ZUGoP_UjvJ9SBg", + "cell_type": "code", + "source": [ + "public interface ComputeAllScopes: IScope //ComputeIfrsVariable", + "\n{", + "\n IEnumerable PvLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable PvCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable RaCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = null,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable RaLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = null,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n private string EconomicBasis => Identity.ValuationApproach == ValuationApproaches.VFA ? EconomicBases.C : EconomicBases.L;", + "\n private IEnumerable amortizationFactor => Identity.AocType == AocTypes.AM", + "\n ? GetScope(Identity, o => o.WithContext(EconomicBasis))", + "\n .RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n EconomicBasis = x.EconomicBasis,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n })", + "\n : Enumerable.Empty();", + "\n IEnumerable Actual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", + "\n DataNode = x.Identity.Id.DataNode,", + "\n AocType = x.Identity.Id.AocType,", + "\n Novelty = x.Identity.Id.Novelty,", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable AdvanceActual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", + "\n DataNode = x.Identity.Id.DataNode,", + "\n AocType = x.Identity.Id.AocType,", + "\n Novelty = x.Identity.Id.Novelty,", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable OverdueActual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", + "\n DataNode = x.Identity.Id.DataNode,", + "\n AocType = x.Identity.Id.AocType,", + "\n Novelty = x.Identity.Id.Novelty,", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable DeferrableActual => GetScope(Identity).RepeatOnce().Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n AccidentYear = null,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n ", + "\n IEnumerable BeEAForPremium => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n || Identity.IsReinsurance", + "\n ? Enumerable.Empty()", + "\n : GetScope(Identity)", + "\n .ByAmountType", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(sc => new IfrsVariable{ EstimateType = GetScope(Identity).EstimateType, ", + "\n DataNode = sc.Identity.Id.DataNode, ", + "\n AocType = sc.Identity.Id.AocType, ", + "\n Novelty = sc.Identity.Id.Novelty, ", + "\n AccidentYear = sc.Identity.AccidentYear,", + "\n EconomicBasis = sc.EconomicBasis,", + "\n AmountType = sc.Identity.AmountType,", + "\n Value = sc.Value,", + "\n Partition = sc.GetStorage().TargetPartition });", + "\n ", + "\n IEnumerable ActEAForPremium => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n || Identity.IsReinsurance", + "\n ? Enumerable.Empty()", + "\n : GetScope(Identity)", + "\n .ByAmountTypeAndEstimateType", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(sc => new IfrsVariable{ EstimateType = GetStorage().ExperienceAdjustEstimateTypeMapping[sc.Identity.EstimateType], ", + "\n DataNode = sc.Identity.Id.DataNode, ", + "\n AocType = sc.Identity.Id.AocType, ", + "\n Novelty = sc.Identity.Id.Novelty, ", + "\n AccidentYear = sc.Identity.AccidentYear,", + "\n //EconomicBasis = scope.EconomicBasis,", + "\n AmountType = sc.Identity.AmountType,", + "\n Value = sc.Value,", + "\n Partition = GetStorage().TargetPartition });", + "\n ", + "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n ? Enumerable.Empty()", + "\n : GetScope(Identity).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n", + "\n IEnumerable Loss => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n ? Enumerable.Empty()", + "\n : Identity.IsReinsurance ", + "\n ? GetScope(Identity).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n })", + "\n : GetScope(Identity).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n", + "\n /*private double validateSingleEoP => Math.Abs(ValueCsm) > Precision && Math.Abs(ValueLc) > Precision ", + "\n ? (double)ApplicationMessage.Log(Error.MultipleEoP)", + "\n : default;", + "\n */", + "\n IEnumerable CalculatedIfrsVariables => GetStorage().ImportFormat switch {", + "\n ImportFormats.Actual => Actual.Concat(AdvanceActual).Concat(OverdueActual).Concat(ActEAForPremium)", + "\n .Concat(DeferrableActual).Concat(Csms).Concat(Loss),", + "\n ImportFormats.Cashflow => PvLocked.Concat(PvCurrent).Concat(RaCurrent).Concat(RaLocked)", + "\n .Concat(amortizationFactor).Concat(BeEAForPremium)", + "\n .Concat(DeferrableActual).Concat(Csms).Concat(Loss),", + "\n ImportFormats.Opening => AdvanceActual.Concat(OverdueActual).Concat(DeferrableActual)", + "\n .Concat(Csms).Concat(Loss),", + "\n };", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "I56SQek6SkukwZ49PojX-g", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb new file mode 100644 index 00000000..c1d8ede4 --- /dev/null +++ b/Import/ImportStorage.ipynb @@ -0,0 +1,387 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "zXp-Bu79BE-93BUbDiTYAg", + "cell_type": "markdown", + "source": [ + "", + "\n

Import Storage

", + "\n", + "\nThe Import Storage collects the following data upon import of a file:", + "\n", + "\n- Current Period (year, month)", + "\n- Previous Period", + "\n- [Partitions](../DataModel/DataStructure)", + "\n- [RawVariables](../DataModel/DataStructure)", + "\n- [IfrsVariables](../DataModel/DataStructure)", + "\n- [Projection Configuration](../DataModel/DataStructure)", + "\n- [YieldCurve](../DataModel/DataStructure)", + "\n- [AocType](../DataModel/DataStructure)", + "\n- [AmountType](../DataModel/DataStructure)", + "\n- [CalculationType](../DataModel/DataStructure)", + "\n- [DataNodes](../DataModel/DataStructure)", + "\n", + "\nSuch storage is then passed to calculations defined in the corresponding [Import Scopes](./ImportScopeCalculation)." + ], + "metadata": {} + }, + { + "id": "BBcl8VllBE2yH3necdNVxQ", + "cell_type": "code", + "source": [ + "#!import \"../Utils/UtilityMethods\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "aIs6_wKUtEKp2vLJAPpVpQ", + "cell_type": "markdown", + "source": [ + "# Import Storage" + ], + "metadata": {} + }, + { + "id": "kigCPC7MoEy40WWR1LAtFA", + "cell_type": "code", + "source": [ + "public class ImportStorage", + "\n{ ", + "\n private readonly IDataSource querySource; ", + "\n private readonly IWorkspace workspace;", + "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache;", + "\n private readonly ImportArgs args;", + "\n ", + "\n // Constants", + "\n private static int periodicityInMonths => 3; // Revisit", + "\n ", + "\n //Format", + "\n public string ImportFormat => args.ImportFormat; ", + "\n ", + "\n //Time Periods ", + "\n public (int Year, int Month) CurrentReportingPeriod => (args.Year, args.Month);", + "\n public (int Year, int Month) PreviousReportingPeriod => (args.Year - 1, MonthInAYear); // YTD Logic", + "\n", + "\n //Partitions", + "\n public Guid PartitionByRn;", + "\n public Guid TargetPartition;", + "\n public Guid DefaultPartition;", + "\n public Guid PreviousPeriodPartition; ", + "\n", + "\n //Projections", + "\n private ProjectionConfiguration[] ProjectionConfiguration;", + "\n ", + "\n //DataNodes", + "\n public IDictionary DataNodeDataBySystemName { get; private set; }", + "\n public IDictionary> DataNodesByImportScope { get; private set; }", + "\n public IDictionary> AccidentYearsByDataNode { get; private set; }", + "\n //Variables", + "\n public IDictionary> RawVariablesByImportIdentity { get; private set; }", + "\n public IDictionary> IfrsVariablesByImportIdentity { get; private set; }", + "\n ", + "\n //Parameters", + "\n public Dictionary LockedInYieldCurve { get; private set; }", + "\n public Dictionary> CurrentYieldCurve { get; private set; }", + "\n public Dictionary> PartnerRating { get; private set; }", + "\n public Dictionary> CreditDefaultRates { get; private set; }", + "\n public Dictionary> SingleDataNodeParametersByGoc { get; private set; }", + "\n public Dictionary>> InterDataNodeParametersByGoc { get; private set; }", + "\n public Dictionary AocConfigurationByAocStep { get; private set; }", + "\n ", + "\n private Dictionary> aocStepByInputSource;", + "\n ", + "\n //Dimensions", + "\n public Dictionary AmountTypeDimension { get; private set; }", + "\n public Dictionary NoveltyDimension { get; private set; }", + "\n public Dictionary CalculationTypeDimension { get; private set; }", + "\n public Dictionary EstimateTypeDimension { get; private set; }", + "\n public Dictionary> EstimateTypesByImportFormat { get; private set; }", + "\n public Dictionary ExperienceAdjustEstimateTypeMapping { get; private set; } ", + "\n ", + "\n //Constructor", + "\n public ImportStorage(ImportArgs args, IDataSource querySource, IWorkspace workspace)", + "\n {", + "\n this.querySource = querySource;", + "\n this.workspace = workspace;", + "\n hierarchyCache = workspace.ToHierarchicalDimensionCache();", + "\n this.args = args;", + "\n }", + "\n ", + "\n //Initialize", + "\n public async Task InitializeAsync()", + "\n { ", + "\n //Dimensions", + "\n var estimateTypes = (await workspace.Query().ToArrayAsync());", + "\n ", + "\n EstimateTypeDimension = estimateTypes.ToDictionary(x => x.SystemName);", + "\n AmountTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n NoveltyDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n CalculationTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n ", + "\n ExperienceAdjustEstimateTypeMapping = new Dictionary{{EstimateTypes.A, EstimateTypes.APA}, {EstimateTypes.AA, EstimateTypes.AAPA}, {EstimateTypes.OA, EstimateTypes.OAPA}}; //TODO move this logic", + "\n ", + "\n //Hierarchy Cache", + "\n hierarchyCache.Initialize();", + "\n ", + "\n //EstimateType to load and to update", + "\n EstimateTypesByImportFormat = new InputSource[] { InputSource.Opening, InputSource.Actual, InputSource.Cashflow,}", + "\n .ToDictionary(x => x.ToString(), ", + "\n x => estimateTypes", + "\n .Where(et => et.InputSource.Contains(x))", + "\n .Select(et => et.SystemName)", + "\n .ToHashSet());", + "\n ", + "\n //ProjectionConfiguration : Current Period + projection for every Quarter End for current Year and next Years as in projectionConfiguration.csv", + "\n ProjectionConfiguration = (await workspace.Query()", + "\n .Where(x => x.Shift > 0 || x.TimeStep == args.Month || (x.TimeStep > args.Month && x.TimeStep % periodicityInMonths == 0))", + "\n .OrderBy(x => x.Shift).ThenBy(x => x.TimeStep).ToArrayAsync());", + "\n ", + "\n //Get Partitions", + "\n PartitionByRn = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).Single().Id;", + "\n TargetPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == CurrentReportingPeriod.Year &&", + "\n p.Month == CurrentReportingPeriod.Month &&", + "\n p.Scenario == args.Scenario).ToArrayAsync()).Single().Id;", + "\n DefaultPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == CurrentReportingPeriod.Year &&", + "\n p.Month == CurrentReportingPeriod.Month &&", + "\n p.Scenario == null).ToArrayAsync()).Single().Id;", + "\n //Set Partitions", + "\n await querySource.Partition.SetAsync(PartitionByRn);", + "\n await workspace.Partition.SetAsync(PartitionByRn);", + "\n ", + "\n await querySource.Partition.SetAsync(TargetPartition);", + "\n await workspace.Partition.SetAsync(TargetPartition);", + "\n ", + "\n //Get data from Workspace (result of parsing)", + "\n var parsedRawVariables = await workspace.Query().ToArrayAsync();", + "\n var parsedIfrsVariables = await workspace.Query().ToArrayAsync();", + "\n ", + "\n //DataNodes", + "\n DataNodeDataBySystemName = await workspace.LoadDataNodesAsync(args);", + "\n ", + "\n //Accident Years", + "\n AccidentYearsByDataNode = (IDictionary>)", + "\n (ImportFormat == ImportFormats.Cashflow ? parsedRawVariables.Select(x => new {x.DataNode, x.AccidentYear}) : parsedIfrsVariables.Select(x => new {x.DataNode, x.AccidentYear}))", + "\n .ToDictionaryGrouped(x => x.DataNode, x => (ICollection)x.Select(y => y.AccidentYear).ToHashSet());", + "\n ", + "\n // Import Scopes and Data Node relationship parameters", + "\n InterDataNodeParametersByGoc = await workspace.LoadInterDataNodeParametersAsync(args);", + "\n ", + "\n var primaryScopeFromParsedVariables = (ImportFormat == ImportFormats.Cashflow ? parsedRawVariables.Select(x => x.DataNode) : parsedIfrsVariables.Select(x => x.DataNode)).ToHashSet();", + "\n var primaryScopeFromLinkedReinsurance = primaryScopeFromParsedVariables", + "\n .Where(goc => !DataNodeDataBySystemName[goc].IsReinsurance && DataNodeDataBySystemName[goc].LiabilityType == LiabilityTypes.LRC)", + "\n .SelectMany(goc => InterDataNodeParametersByGoc.TryGetValue(goc, out var interDataNodeParamByPeriod)", + "\n ? interDataNodeParamByPeriod[CurrentPeriod].Select(param => param.DataNode == goc ? param.LinkedDataNode : param.DataNode).Where(goc => !primaryScopeFromParsedVariables.Contains(goc))", + "\n : Enumerable.Empty())", + "\n .ToHashSet();", + "\n ", + "\n var primaryScope = primaryScopeFromParsedVariables.Concat(primaryScopeFromLinkedReinsurance).ToHashSet();", + "\n var secondaryScope = InterDataNodeParametersByGoc", + "\n .Where(kvp => primaryScope.Contains(kvp.Key))", + "\n .SelectMany(kvp => { var linkedGocs = kvp.Value[CurrentPeriod].Select(param => param.DataNode == kvp.Key ? param.LinkedDataNode : param.DataNode);", + "\n return linkedGocs.Where(goc => !primaryScope.Contains(goc));}).ToHashSet();", + "\n var allImportScopes = new HashSet(primaryScope.Concat(secondaryScope));", + "\n ", + "\n DataNodesByImportScope = new Dictionary> { { ImportScope.Primary, primaryScope }, { ImportScope.Secondary, secondaryScope } };", + "\n ", + "\n // Parameters", + "\n PartnerRating = await workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.Partner);", + "\n CreditDefaultRates = await workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.CreditRiskRating);", + "\n SingleDataNodeParametersByGoc = await workspace.LoadSingleDataNodeParametersAsync(args);", + "\n LockedInYieldCurve = await workspace.LoadLockedInYieldCurveAsync(args, allImportScopes.Select(dn => DataNodeDataBySystemName[dn]));", + "\n CurrentYieldCurve = await workspace.LoadCurrentYieldCurveAsync(args, allImportScopes.Select(dn => DataNodeDataBySystemName[dn])); //TODO Rename this variable", + "\n ", + "\n AocConfigurationByAocStep = await querySource.LoadAocStepConfigurationAsDictionaryAsync(args.Year, args.Month); ", + "\n aocStepByInputSource = ((InputSource[])Enum.GetValues(typeof(InputSource))).ToDictionary(x => x,", + "\n x => AocConfigurationByAocStep", + "\n .Where(kvp => kvp.Value.InputSource.Contains(x))", + "\n .Select(kvp => kvp.Key)", + "\n .ToHashSet());", + "\n ", + "\n //Previous Period", + "\n var openingRawVariables = Enumerable.Empty();", + "\n var openingIfrsVariables = Enumerable.Empty();", + "\n", + "\n if(allImportScopes.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year < args.Year)) {", + "\n PreviousPeriodPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == PreviousReportingPeriod.Year &&", + "\n p.Month == PreviousReportingPeriod.Month &&", + "\n p.Scenario == null).ToArrayAsync()).Single().Id;", + "\n ", + "\n await querySource.Partition.SetAsync(PreviousPeriodPartition);", + "\n ", + "\n //Perform queries to previous Period", + "\n openingRawVariables = (await querySource.Query()", + "\n .Where(rv => rv.Partition == PreviousPeriodPartition && rv.AocType == AocTypes.CL)", + "\n .Where(v => primaryScope.Contains(v.DataNode))", + "\n .ToArrayAsync())", + "\n .Select(rv => rv with {AocType = AocTypes.BOP, Novelty = Novelties.I, Values = rv.Values.Skip(MonthInAYear).ToArray(), Partition = TargetPartition});", + "\n ", + "\n openingIfrsVariables = (await querySource.Query()", + "\n .Where(iv => iv.Partition == PreviousPeriodPartition && iv.AocType == AocTypes.EOP)", + "\n .Where(v => allImportScopes.Contains(v.DataNode))", + "\n .ToArrayAsync())", + "\n .Select(iv => iv with {AocType = AocTypes.BOP, Novelty = Novelties.I, Partition = TargetPartition});", + "\n ", + "\n // TODO: print error if ", + "\n //openingRawVariables.Select(x => x.DataNode).ToHashSet() != dataNodesWithPreviousPeriod", + "\n }", + "\n ", + "\n //SetPartition to current Period", + "\n await querySource.Partition.SetAsync(TargetPartition);", + "\n ", + "\n if(primaryScope.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year == args.Year))", + "\n openingIfrsVariables = openingIfrsVariables.Concat(await querySource.Query()", + "\n .Where(iv => iv.Partition == TargetPartition && iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I)", + "\n .Where(iv => primaryScope.Contains(iv.DataNode) && EstimateTypesByImportFormat[InputSource.Opening.ToString()].Contains(iv.EstimateType) || secondaryScope.Contains(iv.DataNode))", + "\n .ToArrayAsync());", + "\n ", + "\n //Variables", + "\n var rawVariables = parsedRawVariables.Concat(openingRawVariables)", + "\n .Concat(await querySource.Query()", + "\n .Where(rv => rv.Partition == TargetPartition)", + "\n .Where(rv => primaryScopeFromLinkedReinsurance.Contains(rv.DataNode))", + "\n .ToArrayAsync());", + "\n RawVariablesByImportIdentity = (IDictionary>)rawVariables.ToDictionaryGrouped(v => v.DataNode, v => (ICollection)v.ToArray());", + "\n ", + "\n var ifrsVariables = parsedIfrsVariables.Concat(openingIfrsVariables)", + "\n .Concat(await querySource.Query()", + "\n .Where(iv => iv.Partition == TargetPartition && !(iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I))", + "\n .Where(iv => primaryScopeFromParsedVariables.Contains(iv.DataNode) && !EstimateTypesByImportFormat[ImportFormat].Contains(iv.EstimateType) ", + "\n || primaryScopeFromLinkedReinsurance.Contains(iv.DataNode) ", + "\n || secondaryScope.Contains(iv.DataNode))", + "\n .ToArrayAsync());", + "\n IfrsVariablesByImportIdentity = (IDictionary>)ifrsVariables.ToDictionaryGrouped(v => v.DataNode, v => (ICollection)v.ToArray());", + "\n }", + "\n ", + "\n //Getters", + "\n ", + "\n //Periods", + "\n public ValuationPeriod GetValuationPeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].ValuationPeriod;", + "\n public PeriodType GetYieldCurvePeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].YcPeriod;", + "\n public PeriodType GetCreditDefaultRiskPeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].CdrPeriod;", + "\n ", + "\n public IEnumerable GetAllAocSteps(InputSource source) => aocStepByInputSource[source];", + "\n public IEnumerable GetCalculatedTelescopicAocSteps() => AocConfigurationByAocStep.Where(kvp => kvp.Value.DataType == DataType.CalculatedTelescopic).Select(kvp => kvp.Key);", + "\n ", + "\n //YieldCurve", + "\n public double[] GetYearlyYieldCurve(ImportIdentity id, string economicBasis) {", + "\n var yc = GetYieldCurve(id, economicBasis);", + "\n return yc.Values.Skip(args.Year - yc.Year).ToArray(); //Check if the returned array is empty? Log Warning?", + "\n }", + "\n ", + "\n public YieldCurve GetYieldCurve(ImportIdentity id, string economicBasis) => (economicBasis, GetYieldCurvePeriod(id)) switch {", + "\n (EconomicBases.C, PeriodType.BeginningOfPeriod) => CurrentYieldCurve[DataNodeDataBySystemName[id.DataNode].ContractualCurrency][PreviousPeriod],", + "\n (EconomicBases.C, PeriodType.EndOfPeriod) => CurrentYieldCurve[DataNodeDataBySystemName[id.DataNode].ContractualCurrency][CurrentPeriod],", + "\n (EconomicBases.L, _ ) => LockedInYieldCurve[id.DataNode],", + "\n (_, PeriodType.NotApplicable) => (YieldCurve)ApplicationMessage.Log(Error.YieldCurvePeriodNotApplicable, id.AocType, id.Novelty),", + "\n (_, _) => (YieldCurve)ApplicationMessage.Log(Error.EconomicBasisNotFound, id.DataNode)", + "\n };", + "\n ", + "\n //int Identity.ProjectionPeriod ", + "\n public int GetProjectionCount() => ProjectionConfiguration.Count();", + "\n public int GetShift(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].Shift;", + "\n public int GetTimeStep(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].TimeStep;", + "\n ", + "\n public PeriodType GetPeriodType(string amountType, string calculationType) => ", + "\n amountType != null && AmountTypeDimension.TryGetValue(amountType, out var at) ", + "\n ? at.PeriodType", + "\n : calculationType != null && CalculationTypeDimension.TryGetValue(calculationType, out var ct) ", + "\n ? ct.PeriodType : PeriodType.EndOfPeriod;", + "\n", + "\n //Variables and Cashflows", + "\n public IEnumerable GetRawVariables(string dataNode) => RawVariablesByImportIdentity.TryGetValue(dataNode, out var variableCollection) ? variableCollection : Enumerable.Empty();", + "\n public IEnumerable GetIfrsVariables(string dataNode) => IfrsVariablesByImportIdentity.TryGetValue(dataNode, out var variableCollection) ? variableCollection : Enumerable.Empty();", + "\n ", + "\n public double[] GetValues(ImportIdentity id, Func whereClause) => GetRawVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Values ?? Enumerable.Empty().ToArray();", + "\n public double GetValue(ImportIdentity id, Func whereClause) => GetIfrsVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Value ?? 0;", + "\n ", + "\n public double[] GetValues(ImportIdentity id, string amountType, string calculationType, int? accidentYear) => GetValues(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.CalculationType == calculationType);", + "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType);", + "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, string economicBasis, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType && v.EconomicBasis == economicBasis);", + "\n ", + "\n //Novelty", + "\n private IEnumerable GetNoveltiesForAocType(string aocType, IEnumerable aocConfiguration) => aocConfiguration.Where(aocStep => aocStep.AocType == aocType).Select(aocStep => aocStep.Novelty);", + "\n public IEnumerable GetNovelties() => NoveltyDimension.Keys;", + "\n public IEnumerable GetNovelties(string aocType) => GetNoveltiesForAocType(aocType, AocConfigurationByAocStep.Keys);", + "\n public IEnumerable GetNovelties(string aocType, InputSource inputSource) => GetNoveltiesForAocType(aocType, aocStepByInputSource[inputSource]);", + "\n ", + "\n //Accident years", + "\n public IEnumerable GetAccidentYears(string dataNode) => AccidentYearsByDataNode.TryGetValue(dataNode, out var accidentYear) ? accidentYear : new int?[] { null };", + "\n ", + "\n // Parameters", + "\n public double GetNonPerformanceRiskRate (ImportIdentity identity) {", + "\n var period = GetCreditDefaultRiskPeriod(identity) == PeriodType.BeginningOfPeriod ? PreviousPeriod : CurrentPeriod;", + "\n ", + "\n if(!DataNodeDataBySystemName.TryGetValue(identity.DataNode, out var dataNodeData)) ApplicationMessage.Log(Error.DataNodeNotFound, identity.DataNode);", + "\n if(dataNodeData.Partner == null) ApplicationMessage.Log(Error.PartnerNotFound, identity.DataNode);", + "\n // if Partner == Internal then return 0;", + "\n if(!PartnerRating.TryGetValue(dataNodeData.Partner, out var rating)) ApplicationMessage.Log(Error.RatingNotFound, dataNodeData.Partner);", + "\n if(!CreditDefaultRates.TryGetValue(rating[period].CreditRiskRating, out var rate)) ApplicationMessage.Log(Error.CreditDefaultRateNotFound, rating[period].CreditRiskRating);", + "\n return rate[period].Values[0];", + "\n }", + "\n ", + "\n public double GetPremiumAllocationFactor(ImportIdentity id) => SingleDataNodeParametersByGoc.TryGetValue(id.DataNode, out var singleDataNodeParameter) ", + "\n ? singleDataNodeParameter[CurrentPeriod].PremiumAllocation : DefaultPremiumExperienceAdjustmentFactor;", + "\n ", + "\n // Data Node relationships", + "\n public IEnumerable GetUnderlyingGic(ImportIdentity id) => !InterDataNodeParametersByGoc.TryGetValue(id.DataNode, out var interDataNodeParameters)", + "\n ? Enumerable.Empty()", + "\n : interDataNodeParameters[CurrentPeriod].Select(x => x.DataNode != id.DataNode ? x.DataNode : x.LinkedDataNode).Where(goc => !DataNodeDataBySystemName[goc].IsReinsurance);", + "\n ", + "\n public double GetReinsuranceCoverage (ImportIdentity id, string gic) ", + "\n {", + "\n var targetPeriod = AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].RcPeriod == PeriodType.EndOfPeriod ? CurrentPeriod : PreviousPeriod;", + "\n return InterDataNodeParametersByGoc.TryGetValue(id.DataNode, out var interDataNodeParameters)", + "\n ? interDataNodeParameters[targetPeriod].FirstOrDefault(x => x.DataNode == gic || x.LinkedDataNode == gic).ReinsuranceCoverage", + "\n : (double)ApplicationMessage.Log(Error.ReinsuranceCoverage, id.DataNode);", + "\n }", + "\n ", + "\n // Import Scope", + "\n public bool IsPrimaryScope (string dataNode) => DataNodesByImportScope[ImportScope.Primary].Contains(dataNode);", + "\n public bool IsSecondaryScope (string dataNode) => DataNodesByImportScope[ImportScope.Secondary].Contains(dataNode);", + "\n ", + "\n // Other", + "\n public IEnumerable GetNonAttributableAmountType() => new string[]{AmountTypes.NE};", + "\n public IEnumerable GetAttributableExpenseAndCommissionAmountType() => new string[] {AmountTypes.ACA, AmountTypes.AEA}; //U+ specific", + "\n public IEnumerable GetInvestmentClaims() => hierarchyCache.Get(AmountTypes.ICO).Descendants(includeSelf : true).Select(x => x.SystemName);", + "\n public IEnumerable GetPremiums() => hierarchyCache.Get(AmountTypes.PR).Descendants(includeSelf : true).Select(x => x.SystemName);", + "\n public IEnumerable GetClaims() => hierarchyCache.Get(AmountTypes.CL).Descendants().Select(x => x.SystemName);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "AZV9Uq344ESUtVbb13Y6UA", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb new file mode 100644 index 00000000..843a7409 --- /dev/null +++ b/Import/Importers.ipynb @@ -0,0 +1,1199 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "atie2kRp5EK_Lok_1cKKnA", + "cell_type": "markdown", + "source": [ + "", + "\n

Importer Methods

", + "\n" + ], + "metadata": {} + }, + { + "id": "YHW5Ovles0y2T26fE8ZOLw", + "cell_type": "code", + "source": [ + "#!import \"ImportScopeCalculation\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Wraw7o21Pk2HmWk4UAqqsA", + "cell_type": "markdown", + "source": [ + "# Parsing Storage" + ], + "metadata": {} + }, + { + "id": "R427JwfBrEqXKnAMHrgizg", + "cell_type": "code", + "source": [ + "public class ParsingStorage", + "\n{", + "\n private readonly IDataSource dataSource;", + "\n private readonly IWorkspace workspace;", + "\n private readonly ImportArgs args;", + "\n ", + "\n //Hierarchy Cache", + "\n public Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache HierarchyCache;", + "\n ", + "\n public ReportingNode ReportingNode { get; protected set; }", + "\n ", + "\n public Dictionary DataNodeDataBySystemName;", + "\n ", + "\n // Dimensions", + "\n public Dictionary CalculationType;", + "\n public Dictionary PvAmountType; ", + "\n public HashSet AocTypeMap;", + "\n private HashSet estimateTypes;", + "\n private HashSet amountTypes;", + "\n private Dictionary> amountTypesByEstimateType => GetAmountTypesByEstimateType(HierarchyCache);", + "\n public HashSet TechnicalMarginEstimateTypes => GetTechnicalMarginEstimateType(); ", + "\n public Dictionary> DimensionsWithExternalId;", + "\n ", + "\n // Partitions", + "\n public PartitionByReportingNode TargetPartitionByReportingNode;", + "\n public PartitionByReportingNodeAndPeriod TargetPartitionByReportingNodeAndPeriod;", + "\n ", + "\n //Constructor", + "\n public ParsingStorage(ImportArgs args, IDataSource dataSource, IWorkspace workspace)", + "\n {", + "\n this.args = args;", + "\n this.dataSource = dataSource;", + "\n this.workspace = workspace;", + "\n }", + "\n ", + "\n // Initialize", + "\n public async Task InitializeAsync()", + "\n {", + "\n //Partition Workspace and DataSource", + "\n TargetPartitionByReportingNode = (await workspace.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).SingleOrDefault(); ", + "\n ", + "\n if(TargetPartitionByReportingNode == null) ", + "\n { ApplicationMessage.Log(Error.ParsedPartitionNotFound, args.ReportingNode); return; } ", + "\n ", + "\n await workspace.Partition.SetAsync(TargetPartitionByReportingNode.Id);", + "\n await dataSource.Partition.SetAsync(TargetPartitionByReportingNode.Id);", + "\n ", + "\n if(args.Year != default(int) && args.Month != default(int))", + "\n {", + "\n TargetPartitionByReportingNodeAndPeriod = (await workspace.Query()", + "\n .Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == args.Year &&", + "\n p.Month == args.Month &&", + "\n p.Scenario == args.Scenario).ToArrayAsync()).SingleOrDefault();", + "\n ", + "\n if(TargetPartitionByReportingNodeAndPeriod == null) ", + "\n { ApplicationMessage.Log(Error.ParsedPartitionNotFound, args.ReportingNode, args.Year.ToString(), args.Month.ToString(), args.Scenario); return; } ", + "\n ", + "\n await workspace.Partition.SetAsync(TargetPartitionByReportingNodeAndPeriod.Id);", + "\n await dataSource.Partition.SetAsync(TargetPartitionByReportingNodeAndPeriod.Id);", + "\n ", + "\n //Clean up the workspace", + "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", + "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", + "\n }", + "\n ", + "\n ReportingNode = (await dataSource.Query().Where(x => x.SystemName == args.ReportingNode).ToArrayAsync()).First();", + "\n var aocConfigurationByAocStep = await dataSource.LoadAocStepConfigurationAsync(args.Year, args.Month);", + "\n AocTypeMap = args.ImportFormat switch {", + "\n ImportFormats.Cashflow => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Cashflow) &&", + "\n !new DataType[]{DataType.Calculated, DataType.CalculatedTelescopic}.Contains(x.DataType) )", + "\n .GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", + "\n ImportFormats.Actual => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Actual) &&", + "\n !new DataType[]{DataType.Calculated, DataType.CalculatedTelescopic}.Contains(x.DataType) && ", + "\n new AocStep(x.AocType, x.Novelty) != new AocStep(AocTypes.BOP, Novelties.I))", + "\n .GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", + "\n ImportFormats.Opening => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Opening) && x.DataType == DataType.Optional).GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", + "\n ImportFormats.SimpleValue => aocConfigurationByAocStep.GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).Concat((await dataSource.Query().ToArrayAsync())", + "\n .Select(vt => new AocStep(vt.SystemName,null))).ToHashSet(),", + "\n _ => Enumerable.Empty().ToHashSet(),", + "\n };", + "\n ", + "\n //DataNodes", + "\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 // Dimensions", + "\n CalculationType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n PvAmountType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n amountTypes = (await dataSource.Query().ToArrayAsync()).Select(at => at.SystemName).ToHashSet();", + "\n estimateTypes = args.ImportFormat switch {", + "\n ImportFormats.SimpleValue => (await dataSource.Query().ToArrayAsync()).Select(et => et.SystemName).ToHashSet(),", + "\n ImportFormats.Opening => (await dataSource.Query().Where(et => et.StructureType == StructureType.AoC).ToArrayAsync())", + "\n .Where(et => et.InputSource.Contains(InputSource.Opening)) //This Contains overload cannot be used in DB", + "\n .Select(et => et.SystemName).ToHashSet(),", + "\n _ => Enumerable.Empty().ToHashSet(),", + "\n };", + "\n ", + "\n ", + "\n // DimensionsWithExternalId", + "\n DimensionsWithExternalId = new Dictionary>()", + "\n {", + "\n { typeof(PvAmountType), await GetDimensionWithExternalIdDictionaryAsync() },", + "\n { typeof(EstimateType), await GetDimensionWithExternalIdDictionaryAsync() }", + "\n };", + "\n ", + "\n //Hierarchy Cache", + "\n HierarchyCache = workspace.ToHierarchicalDimensionCache();", + "\n HierarchyCache.Initialize();", + "\n }", + "\n ", + "\n public async Task> GetDimensionWithExternalIdDictionaryAsync () where T : KeyedOrderedDimension", + "\n {", + "\n var dict = new Dictionary();", + "\n var items = await dataSource.Query().ToArrayAsync();", + "\n foreach (var item in items) {", + "\n dict.TryAdd(item.SystemName, item.SystemName);", + "\n if(typeof(T).IsAssignableTo(typeof(KeyedOrderedDimensionWithExternalId))) {", + "\n var externalIds = (string[])(typeof(T).GetProperty(nameof(KeyedOrderedDimensionWithExternalId.ExternalId)).GetValue(item));", + "\n if(externalIds == null) continue;", + "\n foreach (var extId in externalIds) ", + "\n dict.TryAdd(extId, item.SystemName);", + "\n }", + "\n }", + "\n return dict;", + "\n }", + "\n ", + "\n // Getters", + "\n public bool IsDataNodeReinsurance(string goc) => DataNodeDataBySystemName[goc].IsReinsurance;", + "\n public bool IsValidDataNode(string goc) => DataNodeDataBySystemName.ContainsKey(goc);", + "\n ", + "\n // Validations", + "\n public string ValidateEstimateType(string et, string goc) {", + "\n var allowedEstimateTypes = estimateTypes;", + "\n if (DataNodeDataBySystemName.TryGetValue(goc, out var dataNodeData) && dataNodeData.LiabilityType == LiabilityTypes.LIC)", + "\n estimateTypes.ExceptWith(TechnicalMarginEstimateTypes);", + "\n if(!allowedEstimateTypes.Contains(et))", + "\n ApplicationMessage.Log(Error.EstimateTypeNotFound, et);", + "\n return et;", + "\n }", + "\n ", + "\n public string ValidateAmountType(string at) {", + "\n if (at != null && !amountTypes.Contains(at))", + "\n ApplicationMessage.Log(Error.AmountTypeNotFound, at);", + "\n return at;", + "\n }", + "\n ", + "\n public AocStep ValidateAocStep(AocStep aoc) {", + "\n if (!AocTypeMap.Contains(aoc))", + "\n ApplicationMessage.Log(Error.AocTypeMapNotFound, aoc.AocType, aoc.Novelty);", + "\n return aoc;", + "\n }", + "\n ", + "\n public string ValidateDataNode(string goc) {", + "\n if (!DataNodeDataBySystemName.ContainsKey(goc))", + "\n ApplicationMessage.Log(Error.InvalidDataNode, goc);", + "\n return goc;", + "\n }", + "\n ", + "\n public void ValidateEstimateTypeAndAmountType(string estimateType, string amountType){", + "\n if (amountTypesByEstimateType.TryGetValue(estimateType, out var ats) && ats.Any() && !ats.Contains(amountType))", + "\n ApplicationMessage.Log(Error.InvalidAmountTypeEstimateType, estimateType, amountType);", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jLFF7eOl8EKi-EoKn60NkA", + "cell_type": "markdown", + "source": [ + "# Basics" + ], + "metadata": {} + }, + { + "id": "LAqrzcPzfU-9EsHmiVfxOg", + "cell_type": "markdown", + "source": [ + "## Clean the Database" + ], + "metadata": {} + }, + { + "id": "USkMObKefk2vtLjT3OjqKQ", + "cell_type": "code", + "source": [ + "async public Task CleanDatabaseAsync (Expression> filter = null) where T : class", + "\n{", + "\n var loadData = await DataSource.Query().Where(filter?? (Expression>)(x => true)).ToListAsync();", + "\n await DataSource.DeleteAsync(loadData);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mUaUxMr_ekW_ZKMYlwu6WQ", + "cell_type": "code", + "source": [ + "async public Task CleanDatabaseFromPartitionAsync (Guid partitionId, Func filter = null) where T : class, IPartitioned", + "\n{", + "\n var loadData = (await DataSource.Query().Where(x => x.Partition == partitionId).ToArrayAsync())", + "\n .Where(filter?? (Func)(x => true)).ToList();", + "\n await DataSource.DeleteAsync(loadData);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3CLQow7bjE67Fq14luFOrw", + "cell_type": "markdown", + "source": [ + "## Update the Database" + ], + "metadata": {} + }, + { + "id": "EQ--NVPYYEqya9DtvVVluw", + "cell_type": "code", + "source": [ + "async public Task CommitToDatabase (Guid partitionId, bool snapshot = true, Func filter = null) where T : class, IPartitioned", + "\n{", + "\n if(snapshot) await CleanDatabaseFromPartitionAsync(partitionId, filter);", + "\n await DataSource.UpdateAsync( await Workspace.Query().ToArrayAsync() );", + "\n await DataSource.CommitAsync();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "alZOFNV3nECY6mw1jPOg9g", + "cell_type": "markdown", + "source": [ + "## Data Node Factory" + ], + "metadata": {} + }, + { + "id": "x30peNSotU-F4HtmYwmRFg", + "cell_type": "code", + "source": [ + "// TODO: think of a better Factory to instantiate DataNode/State/Parameter simultaneously while avoiding public contructors (see Factory Patterns)", + "\n// ATTENTION: this Factory method provides default states and parameters so that it is not mandatory to import them (=> simpler calculation engine). ", + "\n// This method weakness is that these defaults aren't always replaced with the imported values, e,g, when Month > DefaultDataNodeActivationMonth.", + "\n// Therefore they will remain in the DataSource (hopefully without producing any harm).", + "\npublic async Task DataNodeFactoryAsync ()", + "\n{", + "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", + "\n var existingGroupOfContracts = await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync();", + "\n var importedGroupOfContracts = await Workspace.Query().ToArrayAsync();", + "\n var listOfPartitionsWithPeriod = new List();", + "\n ", + "\n foreach (var groupOfContract in importedGroupOfContracts)", + "\n {", + "\n var name = groupOfContract.SystemName;", + "\n if(!existingGroupOfContracts.Any(x => x.SystemName == name))", + "\n {", + "\n var state = new DataNodeState { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", + "\n var parameter = new SingleDataNodeParameter { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", + "\n await Workspace.UpdateAsync(state);", + "\n if(groupOfContract is GroupOfInsuranceContract) await Workspace.UpdateAsync(parameter);", + "\n }", + "\n }", + "\n ", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n //Hot fix: Disabling default as using Annual Cohort breakes Opening importer logic. ", + "\n //await CommitToDatabase(partition, snapshot: false);", + "\n //await CommitToDatabase(partition, snapshot: false);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "plZbdAKxhE2ZjyY7T43g-Q", + "cell_type": "markdown", + "source": [ + "# Importers" + ], + "metadata": {} + }, + { + "id": "6w4ObiZRmUaMLel1WMHQNA", + "cell_type": "markdown", + "source": [ + "## Parse and Upload: Dimensions" + ], + "metadata": {} + }, + { + "id": "hC50TsmYNkKo6cyJ1A0uRQ", + "cell_type": "code", + "source": [ + "public async Task UploadDimensionsAsync (string fileName) where T: class ", + "\n{", + "\n await CleanDatabaseAsync();", + "\n var importLog = await Import.FromFile(fileName).WithType().WithTarget(DataSource).ExecuteAsync();", + "\n return importLog;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zPGrABD22kCbEaJxlm9CYw", + "cell_type": "markdown", + "source": [ + "## Parse Main Tab and return Args" + ], + "metadata": {} + }, + { + "id": "l1JQnGEPfEylauUl-Y-Kqw", + "cell_type": "code", + "source": [ + "public async Task GetArgsFromMainAsync(string file)", + "\n{", + "\n var extension = System.IO.Path.GetExtension(file);", + "\n var stream = await Project.FileStorage.ReadAsync(file);", + "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[Main];", + "\n ", + "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", + "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", + "\n if(ApplicationMessage.HasErrors()) return null;", + "\n ", + "\n var main = mainTab.Rows.First();", + "\n var scenario = mainTab.Columns.Where(x => x.ColumnName == nameof(PartitionByReportingNode.Scenario)).Count() > 0? ", + "\n (string)main[nameof(PartitionByReportingNode.Scenario)] : default(string);", + "\n ", + "\n var partitionName = typeof(IPartition).Name switch ", + "\n {", + "\n nameof(PartitionByReportingNode) => new ImportArgs( (string)main[nameof(PartitionByReportingNode.ReportingNode)],", + "\n default(int),", + "\n default(int),", + "\n default(Periodicity),", + "\n scenario,", + "\n default(string)),", + "\n ", + "\n nameof(PartitionByReportingNodeAndPeriod) => new ImportArgs( (string)main[nameof(PartitionByReportingNodeAndPeriod.ReportingNode)], ", + "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Year)], typeof(int)),", + "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Month)], typeof(int)),", + "\n default(Periodicity),", + "\n scenario,", + "\n default(string)),", + "\n ", + "\n _ => null", + "\n };", + "\n ", + "\n if (partitionName == null) ApplicationMessage.Log(Error.PartitionTypeNotFound, typeof(IPartition).Name); ", + "\n return partitionName;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Nc8XqguDwEywNGHzIg3C4A", + "cell_type": "markdown", + "source": [ + "### Parse and Upload: Data Nodes" + ], + "metadata": {} + }, + { + "id": "TryM-sop6USTlvmWqP14CQ", + "cell_type": "markdown", + "source": [ + "### Portfolio and Group of contract" + ], + "metadata": {} + }, + { + "id": "XxwGlJ5PS02O5OtQsb1v8g", + "cell_type": "code", + "source": [ + "public async Task UploadDataNodesToWorkspaceAsync(string fileName)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var args = await GetArgsFromMainAsync(fileName);", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var storage = new ParsingStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var errors = new List();", + "\n var importLogPortfolios = await Import.FromFile(fileName)", + "\n .WithType((dataset, datarow) => new InsurancePortfolio {", + "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = datarow.Field(nameof(DataNode.ContractualCurrency)),", + "\n FunctionalCurrency = storage.ReportingNode.Currency,", + "\n LineOfBusiness = datarow.Field(nameof(DataNode.LineOfBusiness)),", + "\n ValuationApproach = datarow.Field(nameof(DataNode.ValuationApproach)),", + "\n OciType = datarow.Field(nameof(DataNode.OciType))", + "\n })", + "\n .WithType((dataset, datarow) =>new ReinsurancePortfolio {", + "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = datarow.Field(nameof(DataNode.ContractualCurrency)),", + "\n FunctionalCurrency = storage.ReportingNode.Currency,", + "\n LineOfBusiness = datarow.Field(nameof(DataNode.LineOfBusiness)),", + "\n ValuationApproach = datarow.Field(nameof(DataNode.ValuationApproach)),", + "\n OciType = datarow.Field(nameof(DataNode.OciType))", + "\n })", + "\n .WithTarget(Workspace)", + "\n .ExecuteAsync();", + "\n ", + "\n var portfolios = await Workspace.Query().ToDictionaryAsync(x => x.SystemName);", + "\n var importLogGroupOfContracts = await Import.FromFile(fileName)", + "\n .WithType((dataset, datarow) => {", + "\n var gicSystemName = datarow.Field(nameof(DataNode.SystemName));", + "\n var pf = datarow.Field(nameof(InsurancePortfolio));", + "\n if(!portfolios.TryGetValue(pf, out var portfolioData))", + "\n {", + "\n ApplicationMessage.Log(Error.PortfolioGicNotFound, pf, gicSystemName);", + "\n return null;", + "\n }", + "\n var gic = new GroupOfInsuranceContract {", + "\n SystemName = gicSystemName,", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = portfolioData.ContractualCurrency,", + "\n FunctionalCurrency = portfolioData.FunctionalCurrency,", + "\n LineOfBusiness = portfolioData.LineOfBusiness,", + "\n ValuationApproach = portfolioData.ValuationApproach,", + "\n OciType = portfolioData.OciType,", + "\n AnnualCohort = Convert.ToInt32(datarow.Field(nameof(GroupOfContract.AnnualCohort))),", + "\n LiabilityType = datarow.Field(nameof(GroupOfContract.LiabilityType)),", + "\n Profitability = datarow.Field(nameof(GroupOfContract.Profitability)),", + "\n Portfolio = pf", + "\n };", + "\n return ExtendGroupOfContract(gic, datarow);", + "\n })", + "\n .WithType((dataset, datarow) => {", + "\n var gricSystemName = datarow.Field(nameof(DataNode.SystemName));", + "\n var pf = datarow.Field(nameof(ReinsurancePortfolio));", + "\n if(!portfolios.TryGetValue(pf, out var portfolioData))", + "\n {", + "\n ApplicationMessage.Log(Error.PortfolioGicNotFound, pf, gricSystemName);", + "\n return null;", + "\n }", + "\n var gric = new GroupOfReinsuranceContract {", + "\n SystemName = gricSystemName,", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = portfolioData.ContractualCurrency,", + "\n FunctionalCurrency = portfolioData.FunctionalCurrency,", + "\n LineOfBusiness = portfolioData.LineOfBusiness,", + "\n ValuationApproach = portfolioData.ValuationApproach,", + "\n OciType = portfolioData.OciType,", + "\n AnnualCohort = Convert.ToInt32(datarow.Field(nameof(GroupOfContract.AnnualCohort))),", + "\n LiabilityType = datarow.Field(nameof(GroupOfContract.LiabilityType)),", + "\n Profitability = datarow.Field(nameof(GroupOfContract.Profitability)),", + "\n Portfolio = pf,", + "\n Partner = datarow.Field(nameof(GroupOfContract.Partner))", + "\n };", + "\n return ExtendGroupOfContract(gric, datarow);", + "\n })", + "\n .WithTarget(Workspace)", + "\n .ExecuteAsync();", + "\n ", + "\n return Activity.Finish().Merge(importLogPortfolios).Merge(importLogGroupOfContracts);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ek8lfAoNYUuv38Cg7Ld7UA", + "cell_type": "code", + "source": [ + "public async Task UploadDataNodesAsync(string fileName)", + "\n{", + "\n var log = await UploadDataNodesToWorkspaceAsync(fileName);", + "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", + "\n ", + "\n await DataNodeFactoryAsync(); ", + "\n return log;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "EWnSq0n9wkmoyganTsWoYw", + "cell_type": "markdown", + "source": [ + "### Data Node State" + ], + "metadata": {} + }, + { + "id": "GPjdrCFjTEiPfTQ_5EzELg", + "cell_type": "code", + "source": [ + "public async Task ValidateDataNodeStatesAsync(Dictionary persistentDataNodeByDataNode)", + "\n{", + "\n foreach(var importedDataNodeState in await Workspace.Query().ToArrayAsync())", + "\n {", + "\n if(persistentDataNodeByDataNode.TryGetValue(importedDataNodeState.DataNode, out var currentPersistentDataNode))", + "\n {", + "\n if(importedDataNodeState.State < currentPersistentDataNode.State)", + "\n ApplicationMessage.Log(Error.ChangeDataNodeState, importedDataNodeState.DataNode, ", + "\n currentPersistentDataNode.State.ToString(), ", + "\n importedDataNodeState.State.ToString());", + "\n", + "\n if(importedDataNodeState.State == currentPersistentDataNode.State)", + "\n await Workspace.DeleteAsync(importedDataNodeState);", + "\n }", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Onp_ZdRWQ0-oaDr1QwZdYg", + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeStateToWorkspaceAsync(string fileName)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", + "\n ", + "\n Activity.Start();", + "\n var args = await GetArgsFromMainAsync(fileName);", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var storage = new ParsingStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var importLog = await Import.FromFile(fileName).WithType(", + "\n (dataset, datarow) => new DataNodeState {", + "\n DataNode = datarow.Field(nameof(DataNodeState.DataNode)),", + "\n State = (State)Enum.Parse(typeof(State), datarow.Field(nameof(DataNodeState.State))),", + "\n Year = args.Year,", + "\n Month = args.Month,", + "\n Partition = storage.TargetPartitionByReportingNode.Id", + "\n }", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n", + "\n await ValidateDataNodeStatesAsync(storage.DataNodeDataBySystemName);", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LvFi94RVy0C36bUPNXZIuQ", + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeStateAsync(string fileName)", + "\n{", + "\n var log = await UploadDataNodeStateToWorkspaceAsync(fileName);", + "\n await CommitToDatabase((Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode)), snapshot: false); ", + "\n return log;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "l1yjjsQ6P0OSf1PWW_AL8w", + "cell_type": "markdown", + "source": [ + "### DataNode Parameters" + ], + "metadata": {} + }, + { + "id": "Q5PAOqsi5kOktzneex2EZA", + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeParameterToWorkspaceAsync(string fileName, Guid targetPartitionByReportingNodeId)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", + "\n ", + "\n Activity.Start();", + "\n var args = await GetArgsFromMainAsync(fileName) with {ImportFormat = ImportFormats.DataNodeParameter};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var storage = new ParsingStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var singleDataNode = new List();", + "\n var interDataNode = new List<(string,string)>();", + "\n ", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType( (dataset, datarow) => {", + "\n", + "\n //read and validate DataNodes", + "\n var dataNode = datarow.Field(nameof(DataNode));", + "\n if(!storage.IsValidDataNode(dataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, dataNode); return null; }", + "\n", + "\n //check for duplicates", + "\n if(singleDataNode.Contains(dataNode)) { ApplicationMessage.Log(Error.DuplicateSingleDataNode, dataNode); return null; }", + "\n singleDataNode.Add(dataNode);", + "\n ", + "\n //Instantiate SingleDataNodeParameter", + "\n return new SingleDataNodeParameter {", + "\n Year = args.Year,", + "\n Month = args.Month,", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n", + "\n DataNode = dataNode,", + "\n PremiumAllocation = (datarow.Field(nameof(SingleDataNodeParameter.PremiumAllocation)))", + "\n .ToString().CheckStringForExponentialAndConvertToDouble(),", + "\n };", + "\n })", + "\n .WithType( (dataset, datarow) => {", + "\n", + "\n //read and validate DataNodes", + "\n var dataNode = datarow.Field(nameof(InterDataNodeParameter.DataNode));", + "\n if(!storage.IsValidDataNode(dataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, dataNode); return null; }", + "\n", + "\n var linkedDataNode = datarow.Field(nameof(InterDataNodeParameter.LinkedDataNode));", + "\n if(!storage.IsValidDataNode(linkedDataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, linkedDataNode); return null; }", + "\n var dataNodes = new string[]{dataNode, linkedDataNode}.OrderBy(x => x).ToArray();", + "\n", + "\n //validate ReinsuranceGross Link", + "\n var isDn1Reinsurance = storage.IsDataNodeReinsurance(dataNodes[0]);", + "\n var isDn2Reinsurance = storage.IsDataNodeReinsurance(dataNodes[1]);", + "\n var isGrossReinsuranceLink = (isDn1Reinsurance && !isDn2Reinsurance) != (!isDn1Reinsurance && isDn2Reinsurance);", + "\n var reinsCov = (datarow.Field(nameof(InterDataNodeParameter.ReinsuranceCoverage)))", + "\n .ToString().CheckStringForExponentialAndConvertToDouble();", + "\n if(!isGrossReinsuranceLink && Math.Abs(reinsCov) > Precision )", + "\n ApplicationMessage.Log(Error.ReinsuranceCoverageDataNode, dataNodes[0], dataNodes[1]); // TODO: is this error or warning?", + "\n", + "\n //check for duplicates", + "\n if(interDataNode.Contains((dataNodes[0], dataNodes[1])) || interDataNode.Contains((dataNodes[1], dataNodes[0])))", + "\n ApplicationMessage.Log(Error.DuplicateInterDataNode, dataNodes[0], dataNodes[1]); // TODO: is this error or warning?", + "\n", + "\n interDataNode.Add((dataNodes[0], dataNodes[1])); ", + "\n //Instantiate InterDataNodeParameter", + "\n return new InterDataNodeParameter {", + "\n Year = args.Year,", + "\n Month = args.Month,", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n DataNode = dataNodes[0],", + "\n LinkedDataNode = dataNodes[1],", + "\n ReinsuranceCoverage = reinsCov,", + "\n };", + "\n })", + "\n .WithTarget(Workspace)", + "\n .ExecuteAsync();", + "\n ", + "\n targetPartitionByReportingNodeId = storage.TargetPartitionByReportingNode.Id;", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FpMgj56nhUWiJDn-bke8XQ", + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeParameterAsync(string fileName)", + "\n{", + "\n Guid partitionId = new Guid();", + "\n var log = await UploadDataNodeParameterToWorkspaceAsync(fileName, partitionId);", + "\n ", + "\n await CommitToDatabase(partitionId, snapshot: false);", + "\n await CommitToDatabase(partitionId, snapshot: false); ", + "\n ", + "\n return log;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "NayXrFB1fUCjVZsyuv3HCA", + "cell_type": "markdown", + "source": [ + "## Parse and Upload: Variables" + ], + "metadata": {} + }, + { + "id": "6nCpBsFe4kylRPgDYwMg9A", + "cell_type": "markdown", + "source": [ + "### Validation for Active Data Node States" + ], + "metadata": {} + }, + { + "id": "aVUxILOVD0WCQ3Kd9uMtaA", + "cell_type": "code", + "source": [ + "public async Task ValidateForDataNodeStateActiveAsync(Dictionary dataNodes) where T : BaseDataRecord", + "\n{ ", + "\n foreach(var item in (await Workspace.Query().ToArrayAsync()).GroupBy(x => x.DataNode))", + "\n if(!dataNodes.ContainsKey(item.First().DataNode))", + "\n ApplicationMessage.Log(Error.InactiveDataNodeState, item.First().DataNode);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WFAodnYhh0S4UQHkB4pFcQ", + "cell_type": "markdown", + "source": [ + "### Cashflow as Raw Variable and Ifrs Variable" + ], + "metadata": {} + }, + { + "id": "a2sXTTFuxk6by0RB9IyY5g", + "cell_type": "code", + "source": [ + "public async Task ParseCashflowsToWorkspaceAsync(string fileName, ImportArgs args)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", + "\n await parsingStorage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType ( (dataset, datarow) => {", + "\n var aocType = datarow.Field(nameof(RawVariable.AocType));", + "\n var novelty = datarow.Field(nameof(RawVariable.Novelty));", + "\n var dataNode = datarow.Field(nameof(DataNode));", + "\n ", + "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", + "\n ApplicationMessage.Log(Error.InvalidDataNode, dataNode);", + "\n return null;", + "\n }", + "\n ", + "\n // Error if AocType is not present in the mapping", + "\n if(!parsingStorage.AocTypeMap.Contains(new AocStep(aocType, novelty))) {", + "\n ApplicationMessage.Log(Error.AocTypeMapNotFound, aocType, novelty);", + "\n return null;", + "\n }", + "\n ", + "\n // Filter out cashflows for DataNode that were created in the past and are still active and come with AocType = BOPI", + "\n if(dataNodeData.Year < args.Year && aocType == AocTypes.BOP && novelty == Novelties.I) {", + "\n ApplicationMessage.Log(Warning.ActiveDataNodeWithCashflowBOPI);", + "\n return null;", + "\n }", + "\n ", + "\n var amountTypeFromFile = datarow.Field(nameof(RawVariable.AmountType));", + "\n var isCalculationType = parsingStorage.CalculationType.ContainsKey(amountTypeFromFile);", + "\n var amountType = isCalculationType ? null : amountTypeFromFile;", + "\n var calculationType = isCalculationType ? amountTypeFromFile : CalculationTypes.BE;", + "\n ", + "\n var values = datarow.Table.Columns.Where(c => c.ColumnName.StartsWith(nameof(RawVariable.Values))).OrderBy(c => c.ColumnName.Length).ThenBy(c => c.ColumnName)", + "\n .Select(x => datarow.Field(x.ColumnName).CheckStringForExponentialAndConvertToDouble()).Prune();", + "\n ", + "\n // Filter out empty raw variables for AocType != CL", + "\n if(values.Length == 0 && aocType != AocTypes.CL) return null; //TODO: extend this check for all mandatory step and not just for CL", + "\n ", + "\n var item = new RawVariable {", + "\n DataNode = dataNode,", + "\n AocType = aocType,", + "\n Novelty = novelty,", + "\n AmountType = amountType,", + "\n CalculationType = calculationType,", + "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(RawVariable.AccidentYear))), out var tempVal)? tempVal : (int?)null,", + "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", + "\n Values = Multiply(GetSign((aocType, amountType, calculationType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), values)", + "\n };", + "\n return item;", + "\n }, ImportFormats.Cashflow", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n ", + "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3iGcaiP12U-Jc2zU_pPCQw", + "cell_type": "code", + "source": [ + "public async Task UploadCashflowsAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Cashflow};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(fileName, args);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var storage = new ImportStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var universe = Scopes.ForStorage(storage).ToScope();", + "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", + "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n await Workspace.UpdateAsync(ivs);", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true, ", + "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Cashflow].Contains(x.EstimateType) && ", + "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode)); ", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true,", + "\n filter : x => storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", + "\n", + "\n return Activity.Finish().Merge(parsingLog); ", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BzW1jMILIk-dXDuU0pbd3w", + "cell_type": "markdown", + "source": [ + "### Actuals as Ifrs Variable" + ], + "metadata": {} + }, + { + "id": "4CYHZInVJUOfrmoLQKbolQ", + "cell_type": "code", + "source": [ + "public async Task ParseActualsToWorkspaceAsync(string fileName, ImportArgs args)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", + "\n await parsingStorage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType ( (dataset, datarow) => {", + "\n var dataNode = datarow.Field(nameof(DataNode));", + "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", + "\n ApplicationMessage.Log(Error.InvalidDataNode, dataNode);", + "\n return null;", + "\n }", + "\n ", + "\n var valueType = datarow.Field(ValueType);", + "\n if(valueType == null) { ", + "\n ApplicationMessage.Log(Error.ValueTypeNotFound); ", + "\n return null; ", + "\n }", + "\n ", + "\n var amountType = parsingStorage.DimensionsWithExternalId[typeof(PvAmountType)].TryGetValue(valueType, out var at)? at : null;", + "\n var isStdActual = parsingStorage.PvAmountType.ContainsKey(valueType);", + "\n var estimateType = isStdActual? EstimateTypes.A : parsingStorage.DimensionsWithExternalId[typeof(EstimateType)].TryGetValue(valueType, out var et)? et : null;", + "\n if(estimateType == null || amountType == null) { ", + "\n ApplicationMessage.Log(Error.ValueTypeNotValid, valueType);", + "\n return null;", + "\n }", + "\n ", + "\n var aocType = datarow.Field(nameof(IfrsVariable.AocType));", + "\n if((!isStdActual && aocType != AocTypes.CF && aocType != AocTypes.WO) || (isStdActual && aocType != AocTypes.CF) ) {", + "\n ApplicationMessage.Log(Error.AocTypeNotValid, aocType);", + "\n return null;", + "\n }", + "\n ", + "\n var item = new IfrsVariable {", + "\n DataNode = dataNode,", + "\n AocType = aocType,", + "\n Novelty = Novelties.C,", + "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(IfrsVariable.AccidentYear))), out var tempAccYear)? tempAccYear : (int?)null,", + "\n AmountType = amountType,", + "\n EstimateType = estimateType,", + "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", + "\n Value = Multiply(GetSign((aocType, amountType, estimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()),", + "\n };", + "\n return item;", + "\n }, ImportFormats.Actual", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n ", + "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xeJTsq8-HEqh4t1fxKDzcg", + "cell_type": "code", + "source": [ + "public async Task UploadActualAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Actual};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var parsingLog = await ParseActualsToWorkspaceAsync(fileName, args);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n var storage = new ImportStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n var universe = Scopes.ForStorage(storage).ToScope();", + "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", + "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n await Workspace.UpdateAsync(ivs);", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true, ", + "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Actual].Contains(x.EstimateType) && ", + "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", + "\n", + "\n return Activity.Finish().Merge(parsingLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GBB66l28v06C1ovuu7oKAA", + "cell_type": "markdown", + "source": [ + "# Simple Value Import" + ], + "metadata": {} + }, + { + "id": "0eUHQv8O1kSXjjquLKakNQ", + "cell_type": "markdown", + "source": [ + "## Simple Value to Workspace" + ], + "metadata": {} + }, + { + "id": "BdMAjdPmX0y00AXxMyx40w", + "cell_type": "code", + "source": [ + "public async Task ParseSimpleValueToWorkspaceAsync(string fileName, ImportArgs args, Guid targetPartitionByReportingNodeAndPeriodId)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var importFormat = args.ImportFormat;", + "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", + "\n await parsingStorage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish(); ", + "\n", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType ( (dataset, datarow) => {", + "\n var dataNode = parsingStorage.ValidateDataNode(datarow.Field(nameof(DataNode)));", + "\n var amountType = parsingStorage.ValidateAmountType(datarow.Field(nameof(IfrsVariable.AmountType)));", + "\n var estimateType = parsingStorage.ValidateEstimateType(datarow.Field(nameof(IfrsVariable.EstimateType)), dataNode); //TODO LIC/LRC dependence", + "\n var aocStep = importFormat == ImportFormats.SimpleValue ", + "\n ? parsingStorage.ValidateAocStep(new AocStep (datarow.Field(nameof(IfrsVariable.AocType)), ", + "\n datarow.Field(nameof(IfrsVariable.Novelty))))", + "\n : new AocStep(AocTypes.BOP, Novelties.I);", + "\n var economicBasis = importFormat == ImportFormats.SimpleValue ", + "\n ? datarow.Field(nameof(IfrsVariable.EconomicBasis)) ", + "\n : null;", + "\n ", + "\n parsingStorage.ValidateEstimateTypeAndAmountType(estimateType, amountType);", + "\n ", + "\n var iv = new IfrsVariable {", + "\n DataNode = dataNode,", + "\n AocType = aocStep.AocType,", + "\n Novelty = aocStep.Novelty,", + "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(IfrsVariable.AccidentYear))), out var accidentYear) ? accidentYear : (int?)null,", + "\n AmountType = amountType,", + "\n EstimateType = estimateType,", + "\n EconomicBasis = economicBasis,", + "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", + "\n Value = GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", + "\n * datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()", + "\n };", + "\n return iv;", + "\n }, importFormat", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n ", + "\n HashSet availableEstimateTypes = parsingStorage.TechnicalMarginEstimateTypes;", + "\n var multipleOp = await Workspace.Query().Where(iv => availableEstimateTypes.Contains(iv.EstimateType))", + "\n .GroupBy(iv => iv.DataNode)", + "\n .Where(g => g.Count() > 1).ToArrayAsync();", + "\n //.Select(g => ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, g.Key));", + "\n ", + "\n foreach (var op in multipleOp)", + "\n ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, op.Key);", + "\n ", + "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", + "\n targetPartitionByReportingNodeAndPeriodId = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id;", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9OUXaxBq9UWnDfTVkzZWxQ", + "cell_type": "markdown", + "source": [ + "## Simple Value as IfrsVariable" + ], + "metadata": {} + }, + { + "id": "LQsJefixt0iCd-c5YpFk0A", + "cell_type": "code", + "source": [ + "public async Task UploadSimpleValueAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.SimpleValue};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n Guid partitionId = new Guid();", + "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n Workspace.Query().Select(v => new {v.DataNode, v.AccidentYear}).Distinct();", + "\n ", + "\n await CommitToDatabase(partitionId, ", + "\n snapshot : true,", + "\n filter : x => Workspace.Query().Select(v => v.DataNode).Distinct().Contains(x.DataNode));", + "\n ", + "\n return Activity.Finish().Merge(parsingLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tyyiqAeFX0Gc5OKA_lmSEw", + "cell_type": "markdown", + "source": [ + "## Openings as IfrsVariable" + ], + "metadata": {} + }, + { + "id": "bkCo7-z9F0-_18aRV7Upqw", + "cell_type": "code", + "source": [ + "public async Task UploadOpeningAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Opening};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n Guid partitionId = new Guid();", + "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var storage = new ImportStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var universe = Scopes.ForStorage(storage).ToScope();", + "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", + "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n await Workspace.UpdateAsync(ivs);", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true,", + "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Opening].Contains(x.EstimateType) && ", + "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode ));", + "\n", + "\n return Activity.Finish().Merge(parsingLog);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YqhevtPH3EiTicAIQesk-g", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Initialization/InitSystemorphBaseToMemory.ipynb b/Initialization/InitSystemorphBaseToMemory.ipynb new file mode 100644 index 00000000..25f07ab0 --- /dev/null +++ b/Initialization/InitSystemorphBaseToMemory.ipynb @@ -0,0 +1,268 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "IsXau2AxIU6GrqDFBctd_g", + "cell_type": "markdown", + "source": [ + "

In Memory Initialization of unconfigured DataSource

", + "\n

Reference Data and DataNode

", + "\n", + "\n" + ], + "metadata": {} + }, + { + "id": "7UYbILtPnkuX3ekPtoWAWA", + "cell_type": "code", + "source": [ + "#!import \"../Import/Importers\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "X1GMcf7BW0mzdwq86kKuRQ", + "cell_type": "markdown", + "source": [ + "# Set default DataSource" + ], + "metadata": {} + }, + { + "id": "fVAqI420SkWAgNT6ijl6Fg", + "cell_type": "code", + "source": [ + "await DataSource.SetAsync();", + "\nDataSource.Reset(x => x.ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "82iGxa0-z0StnHV9TIuQDQ", + "cell_type": "markdown", + "source": [ + "# Initialize Workspace" + ], + "metadata": {} + }, + { + "id": "t74nFVf0AkOncugJ2F8jUQ", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "K898FO9wPUmvy-obSQrJ3Q", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QppbRvo4lUWN-7dYzi7zqw", + "cell_type": "markdown", + "source": [ + "# Import Dimensions, Partitions" + ], + "metadata": {} + }, + { + "id": "4T9Mtqgv8kuSz7Ro7CfcOw", + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DCmPy2JDPEqrwPZceL6ncA", + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/300.ReportingNodes/ReportingNodes.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pg7FYVPT8E-V8CHNAvl1Wg", + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RxTzyhca0kSB8pMpuzIcug", + "cell_type": "markdown", + "source": [ + "# Import Parameters" + ], + "metadata": {} + }, + { + "id": "zVvAMvAHzEWwm2mzvadTng", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KdJRkfTVH0KUAXsSPQetHg", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oxIQKMoo5UqjKAtjcdn32Q", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4CDsZoshXE6BZbDJYoXD_w", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uu3vipnW30CDEQcLQ1ezyA", + "cell_type": "markdown", + "source": [ + "# Import DataNodes and DataNodeParameters" + ], + "metadata": {} + }, + { + "id": "DzfZozeHJk-8yJ_uH5jKUA", + "cell_type": "code", + "source": [ + "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "A8AUrboHqESmsdhkjXLh_Q", + "cell_type": "code", + "source": [ + "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "p1m4aehU1kSmNpWDzIpE0A", + "cell_type": "code", + "source": [ + "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pEqNN1RpCkSiVxiqryS-vQ", + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ], + "metadata": {} + }, + { + "id": "pqpb7AWAy06nubi3ydQCPA", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Uc9njlRC-kiAccvmjSF5xw", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Initialization/InitSystemorphToDatabase.ipynb b/Initialization/InitSystemorphToDatabase.ipynb new file mode 100644 index 00000000..862b85ef --- /dev/null +++ b/Initialization/InitSystemorphToDatabase.ipynb @@ -0,0 +1,314 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "Cy8T4hrL4kO_Gfnm6Z5XTg", + "cell_type": "markdown", + "source": [ + "

Physical Database Initialization

" + ], + "metadata": {} + }, + { + "id": "TW3qAJFbN0GzvfZswIQD9g", + "cell_type": "code", + "source": [ + "#!import \"../Database/Configure\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WW6qYyWLN0CDzizR6oTSFw", + "cell_type": "code", + "source": [ + "#!import \"../Import/Importers\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MKwi685La0Shl61un7unGg", + "cell_type": "markdown", + "source": [ + "# Initialize Workspace" + ], + "metadata": {} + }, + { + "id": "19uyY1p_DEafziYCP4_ajg", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VaUXNeTpnkqp4qvlkZT1tA", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ujiYx54U70a1Lk7al17aNQ", + "cell_type": "markdown", + "source": [ + "# Import Dimensions, Partitions" + ], + "metadata": {} + }, + { + "id": "iHL9ANV_7EqKGUtvOzgh9A", + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WITsBPPMmkapIKK3ocjeCA", + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/300.ReportingNodes/ReportingNodes.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UBG4zPFBzEGM9I8BwyLHBg", + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "x_FX7ZmdQkqPWJ_8inZXIg", + "cell_type": "markdown", + "source": [ + "# Import Parameters" + ], + "metadata": {} + }, + { + "id": "OecjLAV7AkiT3KhjiiJnog", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Ii5PJHvCl0Cx2m89VaFSQg", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XRyJuiNql0mkE-hZETImsg", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bGA-LWJqmUmMqydPlYBymQ", + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UzoF3kC3bkSV0tPlgFIH4Q", + "cell_type": "markdown", + "source": [ + "# Import DataNodes and DataNodeParameters" + ], + "metadata": {} + }, + { + "id": "7D_GmV2jsUa_BlNeRX202w", + "cell_type": "code", + "source": [ + "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BNrbXnwP-USpPbMvCQJkQw", + "cell_type": "code", + "source": [ + "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Gbq1iNgL5ku27G-9ZCDgyw", + "cell_type": "code", + "source": [ + "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mIAgGfevFkSw8FcNW7S_Dw", + "cell_type": "markdown", + "source": [ + "# Import Cashflow and Actuals" + ], + "metadata": {} + }, + { + "id": "Dx3T6KwOi0-h1_MxtEvu0Q", + "cell_type": "code", + "source": [ + "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7rQXgufixki5Mr5wvIqvmg", + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9teVf5xzQ0Gkra1zUNiPVw", + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "teSj9-cIHEKxQBYlxrSUaw", + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "eopo9jQQJECpkYPGIcToIg", + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "I9rluX4YaE2AXRNtnwzghw", + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ], + "metadata": {} + }, + { + "id": "vjYLEV52S0yEzRX-hbQu5g", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CQDkkzwLSUi-ZedmBK9uVg", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Initialization/InitSystemorphToMemory.ipynb b/Initialization/InitSystemorphToMemory.ipynb new file mode 100644 index 00000000..211f88c1 --- /dev/null +++ b/Initialization/InitSystemorphToMemory.ipynb @@ -0,0 +1,147 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "p3DIOKsMYUawUuOBORa9iQ", + "cell_type": "markdown", + "source": [ + "

In Memory Initialization of unconfigured DataSource

", + "\n", + "\n" + ], + "metadata": {} + }, + { + "id": "M0C3GJVwOkKVrGYTzCLVXw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ekrl841-jk6Qu-cUbOdg9g", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "55NcBpz1JU2BhAj8tZAtbg", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oSjApvqd006sATOwdgj9fA", + "cell_type": "markdown", + "source": [ + "# Import of Transactional Data" + ], + "metadata": {} + }, + { + "id": "_44_VnWkr0KGvFIltkjYlw", + "cell_type": "code", + "source": [ + "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-lteFKun20qSXUvjgV0Rtw", + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "eZ5TTE-VyEqMqe4FJhoSxw", + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wvXE8jKoiE6GQKf0u2Ja5g", + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "y-vXTvD7pEuT7CEINzNlxg", + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CFPyThMEyUSs9Z01gQRMXg", + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ], + "metadata": {} + }, + { + "id": "6BRncOutP0KF8VwCVa1jYw", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qQmhez-Ep0G2G01ULLKy-g", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/InputFormatDescription.ipynb b/InputFormatDescription.ipynb new file mode 100644 index 00000000..edb44e59 --- /dev/null +++ b/InputFormatDescription.ipynb @@ -0,0 +1,113 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "l1JMz4NpDU2Lk2MWRSzYLA", + "cell_type": "markdown", + "source": [ + "

Structure of the Cashflows, Actuals and Openings Files

", + "\n", + "\nThis Notebook documents the structure of Cashflows, Actuals and Opening input files.", + "\n", + "\n", + "\n# The Cashflows File Structure ", + "\n", + "\n", + "\n
" + ], + "metadata": {} + }, + { + "id": "EHUOzfMOXkWnTeS5CUKVRg", + "cell_type": "markdown", + "source": [ + "A cashflow file is named **NominalCashflows** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Cashflow**.", + "\n", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month and Scenario for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partitions) to which the data belongs.", + "\n", + "\nThe **Cashflow** section contains the cash flow data. Several pieces of information are required to characterize a cash flow correctly:", + "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", + "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", + "\n- [Novelty](./DataModel/DataStructure#novelty) : entered with its SystemName,", + "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims.", + "\n", + "\nAll valid combinations of AocType and Novelty can be found in [AocConfiguration](./DataModel/DataStructure#aoc-configuration) with DataType Optional or Mandatory.", + "\n
The cash flow is entered in the columns named ValuesN where N goes from 0 to the lenght of cash flow. The Value0 corresponds to January of the Year entered in the **Main** section for every combination of AocType and Novelty. " + ], + "metadata": {} + }, + { + "id": "--aqUDIEv0Cij8PWGTssJg", + "cell_type": "markdown", + "source": [ + "", + "\n# The Actuals File Structure ", + "\n", + "\n", + "\n
" + ], + "metadata": {} + }, + { + "id": "auImDZLVDEy-rTLf8gfd_w", + "cell_type": "markdown", + "source": [ + "An Actuals file is named **Actuals** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Actual**.", + "\n", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", + "\n", + "\nThe **Actual** section contains the actuals data. Several pieces of information are required to to characterize an Actuals amount correctly:", + "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", + "\n- [ValueType](./DataModel/DataStructure#amount-type) : corresponds to AmountType SystemName extended with the ExternalId,", + "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." + ], + "metadata": {} + }, + { + "id": "7spVD7c5bkejHCPT5UwVTQ", + "cell_type": "markdown", + "source": [ + "", + "\n# The Openings File Structure ", + "\n", + "\n", + "\n
" + ], + "metadata": {} + }, + { + "id": "xvO-5fBVq0CNPmlNpqDGsw", + "cell_type": "markdown", + "source": [ + "An Openings file is named **Openings** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Opening**. In an AoC for one period, we only need one file with the year/month combination of the beginning of the period. Some GICs do not need any entries in Openings.", + "\n", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", + "\n", + "\nThe **Opening** section contains values at opening of an analysis. Several pieces of information are required to to characterize an Opening amount correctly:", + "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [EstimateType](./DataModel/DataStructure#estimate-type) : entered with its SystemName,", + "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", + "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." + ], + "metadata": {} + } + ] +} \ No newline at end of file diff --git a/OverviewCalculationEngine.ipynb b/OverviewCalculationEngine.ipynb new file mode 100644 index 00000000..8fe93bea --- /dev/null +++ b/OverviewCalculationEngine.ipynb @@ -0,0 +1,258 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "n-YC5c-J-Uq-NYiRZe6gCg", + "cell_type": "markdown", + "source": [ + "

IFRS17 Calculation Engine - an Overview

" + ], + "metadata": {} + }, + { + "id": "Z0Z4HkpVQUWm6q2GfAjRhg", + "cell_type": "markdown", + "source": [ + "Version of 01 Sep 2022" + ], + "metadata": {} + }, + { + "id": "YvapB2YH1029s0tnPiMdjg", + "cell_type": "markdown", + "source": [ + "# Introduction", + "\n", + "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key inpute: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\n", + "\nThis notebook provides an **overview** of Systemorph's IFRS 17 Calculation Engine with brief introductions to all the main steps.", + "\n", + "\nThere are numerous **links** to several notebooks of the Calculation Engine. These notebooks contain specifications, code and also some detailed explanations with formulas in markdown blocks. The most important ones in this respect are [DataModel/DataStructure](./DataModel/DataStructure#data-structure), [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) and [ReportScopes](./Report/ReportScopes#report-scopes)." + ], + "metadata": {} + }, + { + "id": "3xZL2IO6zkqknoPSVOK6AA", + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17", + "\n", + "\nIFRS 17 is a new accounting standard for insurance contracts. The previous standard IFRS 4, which is based on nominal accounting, is replaced by the economic accounting standard IFRS 17.", + "\n", + "\nExplanatory **videos** on **IFRS 17** and a **demo application** can be found on Systemorph's website. Some key points are repeated here briefly.", + "\n", + "\nIFRS 17 deals with insurance contracts which are on the liability side of the balance sheet. Other accounting standards deal with other parts of the business, primarily IFRS 9 for invested assets.", + "\n", + "\nInsurance policies need to be allocated to homogeneous groups of insurance contracts (GICs) according to high-level principles established by the IFRS 17 standard, such as contract type, line of business, annual cohort etc. Insurers have some degree of freedom to optmize those GICs, as long as they respect the high-level principles.", + "\n", + "\nInsurance contracts generate different types of cashflows. For example, **Amount Type** is a dimension refering to premiums, claims, expenses of different kinds, etc. for these cashflows. The Calculation Engine presented here expects input files of all the projected cashflows for each GIC, for different regular time points (quarterly or monthly, ...) and corresponding actual amounts observed for a given period. ", + "\n", + "\nEach cashflow is characterized by all the necessary attributes: business unit, start time, amount type, novelty of business etc. and projected cashflow amounts in a regular time grid until the final run-off of all contracts.", + "\n", + "\nIf the entered cashflows are nominal (the usual case), the the present value (PV) of each cashflow is computed using proper yield curves for discounting.", + "\n", + "\nA central element of IFRS 17 is the Analysis of Change (AoC). The present value of the business (future cashflows) changes from the beginning to the end of the accounting period due to different effects, each of them constituting a modeled AoC step.", + "\n", + "\nIn IFRS 17, the value of future profitable business has a component called the Contractual Service Margin (CSM), defined at GIC level. The profit measured as CSM is recognized slowly over time rather than immediately in financial performance statements. On the other hand, a GIC can be onerous and produce a Loss Component (LC) instead, which needs to be recognized immediately.", + "\n", + "\nSeveral reports on the valuation of cashflows, balance sheet and financial performance can be produced, each dealing with different aspects, such as", + "\n - Present Value of Future Cash Flows (PVFCF)", + "\n - Contractual Service Margin (CSM) and Loss Component (LC)", + "\n - Liability for Remaining Coverage (LRC)", + "\n - Liability for Incurred Claims (LIC)", + "\n - Financial Performance", + "\n - Accounting Events" + ], + "metadata": {} + }, + { + "id": "LcfKBqhuPEe9gyQfTle0Qg", + "cell_type": "markdown", + "source": [ + "", + "\n# Data Model, Data Input, Data Import", + "\n", + "\nThe IFRS 17 calculations are based on a well-defined **data model**. The data input files are set up according to the data model, and the data import and all the ensuing calculations up to the final report generation respect the data model.", + "\n", + "\nInput files as listed below are used to provide the necessary information on the business to be modeled. These files are part of the IFRS 17 Calculation Engine and can be used as templates for users intending to model their own business and adapt some files accordingly. ", + "\n", + "\nThe IFRS 17 calculations start by importing the data input files, and the more complex logic of the IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." + ], + "metadata": {} + }, + { + "id": "E1xdnYPKM0u0NqVxOjLBJw", + "cell_type": "markdown", + "source": [ + "", + "\n## Data Model", + "\n", + "\nThe data model includes the definition of reporting nodes and dimensions to be used, including identities, amount types, group of insurance contracts and many more.", + "\n", + "\nThe notebook [DataModel/DataStructure](./DataModel/DataStructure#data-structure) defines the data records, dimensions and interfaces of the data model. There is a long section on the many [dimensions](./DataModel/DataStructure#dimensions) used to characterize the business and its IFRS 17 model.", + "\n", + "\nThe [input files](#data-input-dim-nodes) ReportingNodes and especially DimensionsAndPartitions provide an overview of data structures actually used. Some dimensions are hierarchical, so some entries have parent entries.", + "\n", + "\nMany abbreviations and acronyms used later in the documentation and the code are the **system names**, where the corresponding display names can be found together with the attributes." + ], + "metadata": {} + }, + { + "id": "GGqaecTDuE6XUrAnYdsG-g", + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Reporting nodes, dimensions and partitions", + "\n", + "\nSee folders *Files* (DimensionsAndPartitions) and *Files/300.ReportingNodes* (ReportingNodes).", + "\n- **ReportingNodes**: List of business units, often per country, with system name and display name, currency and \"G\" for the whole group", + "\n- **DimensionsAndPartitions**: The many dimensions (21) required to characterize all of the data and results, with system names and display names. This information is quite stable, but some information related to partitions refers to the reporting nodes " + ], + "metadata": {} + }, + { + "id": "LhUX4L3Xc0C0rq4_Y9J6qQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Groups of insurance and reinsurance contracts", + "\n", + "\nSee folder Files/700.DataNodes. The information is about data nodes, that is Groups of Insurance Contracts (GICs) and Groups of Reinsurance Contracts (GRICs) and portfolios of these.", + "\n- **DataNodes**: List of all GICs and GRICs, each with several attributes and the portfolios to which they belong; an additional attribute of GRICs being the reinsurance partner", + "\n- **DataNodeParameters** *\\_* *\\_* *\\_*: List of those GICs and GRICs that are actually used for the given reporting node/year/month combination with few attributes; if needed, more such files may be added for other reporting node/year/month combinations", + "\n- **DataNodeStates** *\\_* *\\_* *\\_*: Switching data nodes on and off, the normal state is (\"Active\") for all the GICs and GRICs of the reporting node/year/month combination; if needed, more such files may be added for other reporting node/year/month combinations" + ], + "metadata": {} + }, + { + "id": "QMmg_-Sg9UOvWDKPIfPCqw", + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Parameters from financial markets", + "\n", + "\nSee folder Files/800.Parameters.", + "\n- **YieldCurve**: List of all yield curves to be used, for different currencies and as-of dates (year/month), using a yearly grid of interest rate maturities extending as far as needed", + "\n- **ExchangeRate**: List of exchange rates to be used, for different currencies and as-of dates (year/month), with a type (Spot/Average); defined as the value of 1 foreign unit expressed in the group currency of the insurance company ", + "\n- **CreditDefaultRate**: For relevant year/month combinations, each with a full list of all credit ratings in S&P notation with their default rate (= probabilty of default within 1 year)", + "\n- **PartnerRating**: For each reinsurance partner of a relevant GRIC, the rating in S&P notation with the as-of date (year/month)" + ], + "metadata": {} + }, + { + "id": "rVg0MlnQdkC77prbiq421A", + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Groups of insurance and reinsurance contracts", + "\n", + "\nSee folder Files/900.TransactionalData.", + "\n- **Actuals** *\\_* *\\_* *\\_*: List of all actual amounts for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types and other attributes; we need at least two such files for the two dates of the Analysis of Change", + "\n- **Openings** *\\_* *\\_* *\\_*: List of the opening amounts for some GICs that are used by the given reporting node. The year/month combination corresponds to the beginning of the planned Analysis of Change period, so only one such file is required. The entries are by EstimateType and AmountType.", + "\n- **NominalCashflows** *\\_* *\\_* *\\_*: List of all projected cash flows for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types, novelty types and other attributes, where the cash flow amounts are given in a regular sequence extending as far as needed; we need at least two such files for the two dates of the Analysis of Change", + "\n", + "\nThe structure of the [Actuals](./InputFormatDescription#actual), [Openings](./InputFormatDescription#opening) and [NominalCashflows](./InputFormatDescription#cashflow) files is explained in a special [notebook](./InputFormatDescription).", + "\n", + "\nThe less usual option of having discounted instead of nominal cash flows in the input is also supported." + ], + "metadata": {} + }, + { + "id": "JVl9TW0NJkS6zsxTFpcDXg", + "cell_type": "markdown", + "source": [ + "", + "\n## Data import and related calculations", + "\n", + "\nSeveral notebooks organize the data import. Methods for importing and accessing data are in the class [ImportStorage](./Import/ImportStorage#import-storage). Methods for further calculations to be done upon import are in [ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation).", + "\n", + "\nHowever, the import as such is conducted by other notebooks which use the methods of ImportStorage and ImportScopeCalculation in a chain of notebook imports:", + "\n", + "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) --> [InitSystemorphBaseToMemory](./Initialization/InitSystemorphBaseToMemory#init-base-to-memory) --> [InitSystemorphToMemory](./Initialization/InitSystemorphToMemory#init-base-to-memory).", + "\n", + "\nThe latter two notebooks initialize and store the imported and derived data in memory for further usage. To store the data in a physical database, [InitSystemorphToDatabase](./Initialization/InitSystemorphToDatabase#init-to-database) can be employed.", + "\n", + "\nThe calculations of ImportScopeCalculation cover a large part of the IFRS 17 methodology and are explained in the section below." + ], + "metadata": {} + }, + { + "id": "oey1-V5ihE2fKiURTRNp1A", + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17 Model Calculations", + "\n", + "\nThe notebook **[ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation)** has all the calculations to be executed upon data import. The methods used are explained there with formulas. The centerpiece is the Analysis of Change (AoC) of the insurance business over one period (here: quarter). The formulas often use acronyms (system names) as explained in the [section](#data-input-dim-nodes) on *DimensionsAndPartitions*.", + "\n", + "\nThe main concepts and parts of ImportScopeCalculation are listed here, with links.", + "\n- Structure and sequence of the **[Analysis of Change (AoC)](./Import/ImportScopeCalculation#aoc-step-structure)** steps for the given period", + "\n- **[Discounting](./Import/ImportScopeCalculation#discounting-calculation)** projected cash flows using [yield curves](#data-input-parameters) (current or locked in)", + "\n- **[Nominal](./Import/ImportScopeCalculation#nominal-values)** cash flow amounts per AoC step", + "\n- **[Present Values (PV)](./Import/ImportScopeCalculation#present-values)** of cash flow amounts for all AoC steps:", + "\n - [Cumulated discounted](./Import/ImportScopeCalculation#cumulated-discounted-cashflows) cash flow amounts for all AoC steps", + "\n - [Telescoping difference](./Import/ImportScopeCalculation#telescopic-difference) calculation of cumulated discounted cashflows per AoC step, where the total PV change over the period is the telescoping sum of all these differences", + "\n - [Present Value calculation](./Import/ImportScopeCalculation#present-value) at the beginning and end of the period, with its underlying [PV base](./Import/ImportScopeCalculation#present-value-base) calculations for different AoC types and for [current and locked-in](./Import/ImportScopeCalculation#current-and-locked) yield curves", + "\n - [Interest accretion](./Import/ImportScopeCalculation#interest-accretion) cash flow calculation (one of the AoC steps)", + "\n- **[Risk Adjustment (RA)](./Import/ImportScopeCalculation#risk-adjustment)** calculation, a requirement of the IFRS 17 standard", + "\n- **[Amortization](./Import/ImportScopeCalculation#amortization)**, the AoC step dealing with the reduction of the remaining exposure over the period:", + "\n - [Coverage Unit (CU)](./Import/ImportScopeCalculation#coverage-units), the quantity of services provided by a given GIC, considering one period (reflecting the run-off pattern of the GIC)", + "\n - [Amortization factor](./Import/ImportScopeCalculation#amortization-factor), the relative size of the amortization of a GIC, monthly and for a longer time interval", + "\n- **[Actuals](./Import/ImportScopeCalculation#actual-values)**, treatment of actual values per GIC or GRIC, distinguished according to by their Estimate Type: Ordinary Actuals, Advance Actuals, Overdue Actuals and Deferrable Actuals", + "\n - Calculation of [Actuals Base](./Import/ImportScopeCalculation#actual-base) values for a given GIC and per Estimate Type and Amount Type", + "\n - Different Estimate Types of Actuals and their calculations: Ordinary [Actuals](./Import/ImportScopeCalculation#actuals), [Advance Actuals](./Import/ImportScopeCalculation#advance-actuals) paid before the due date which is inside the AoC period, [Overdue Actuals](./Import/ImportScopeCalculation#overdue-actuals) paid after the AoC period, [Deferrable Actuals](./Import/ImportScopeCalculation#overdue-actuals) whose recognition is deferred (typically used for expenses of different kinds)", + "\n- **[Contractual Service Margin (CSM), Loss Component LC) and Loss Recovery Component (LRC)](./Import/ImportScopeCalculation#csm)**, modeling the treatment of unearned profits (CSM) and losses (LC, LRC) as required by the IFRS 17 standard, per GIC or GRIC:", + "\n - [Fulfillment Cashflow (FCF)](./Import/ImportScopeCalculation#fulfillment-cashflow), same as the aforementioned cumulated discounted cashflow, now adding the risk adjustment component as a basis for CSM and LC calculations", + "\n - [Technical Margin](./Import/ImportScopeCalculation#technical-margin), which is the FCF with special rules for different AoC steps including the Amortization step, also using and calculating the Interest Accretion Factor, Premiums, Deferrals and Investment Claims", + "\n - [Switch Logic for CSM and LC](./Import/ImportScopeCalculation#technical-margin), switching between CSM and LC for a given AoC step in the AoC period; one of the two is always zero depending on the sign of the Technical Margin; distinguishing the [gross case](./Import/ImportScopeCalculation#gross-case) (no reinsurance) from the [reinsurance case](./Import/ImportScopeCalculation#reinsurance-case) which applies reinsurance coverage weights" + ], + "metadata": {} + }, + { + "id": "BnM9Jki8OEedq18buCnW9A", + "cell_type": "markdown", + "source": [ + "", + "\n# Reports", + "\n", + "\nSeveral types of reports can be generated from the same model basis. The notebook **[ReportScopes](./Report/ReportScopes#report-scopes)** has many methods to produce different reports to be executed after the end of all data imports.", + "\n", + "\nThe reports are generated with the help of **DataCube**, a Systemorph tool that allows for the targeted retrieval of information from a large multi-dimensional (in-memory) database, selecting the desired categories, items and degrees of granularity and aggregation across different dimensions.", + "\n", + "\nSome reports of ReportScopes just present existing data from the database, namely the imported data and the results already calculated using the methods of [ImportScopes](#model-calc).", + "\n", + "\nSome other reports related to **[Financial Performance](./Report/ReportScopes#financial-performance)** (profit & loss) require further calculations provided by ReportScopes. An IFRS 17 financial performance report has at least four sections: Insurance Revenue, Insurance Service Expense, Insurance Finance Income/Expense and Other Comprehensive Income. Formulas are provided [here](./Report/ReportScopes#financial-performance).", + "\n", + "\nWhile the ReportScopes notebook provides the calculation formulas for different reports, the production of reports is done by a notebook such as **[Reports](./Report/Reports#report-production)** which imports ReportScopes." + ], + "metadata": {} + }, + { + "id": "au5gK98z6EWDe-C7Wm3Img", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Report/ReportConfigurationAndUtils.ipynb b/Report/ReportConfigurationAndUtils.ipynb new file mode 100644 index 00000000..628b0f04 --- /dev/null +++ b/Report/ReportConfigurationAndUtils.ipynb @@ -0,0 +1,148 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "RcqlbIqLC0GUIOHkkIM0fA", + "cell_type": "markdown", + "source": [ + "

Report Configuration And Utils

" + ], + "metadata": {} + }, + { + "id": "JWFelad9jEy9FfjxYAaBwA", + "cell_type": "code", + "source": [ + "#!import \"../Utils/UtilityMethods\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YyjCBXNsHk2Q8c-G2NlyIA", + "cell_type": "code", + "source": [ + "using Systemorph.Vertex.Pivot.Reporting.Builder;", + "\nusing System.Collections.Immutable;", + "\n", + "\npublic static DataCubeReportBuilder, TVariable, TVariable ,TVariable> ReportGridOptions(", + "\n this DataCubeReportBuilder, TVariable, TVariable, TVariable> reportBuilder,", + "\n int reportHeight = 700,", + "\n int valueColumnWidth = 250,", + "\n int headerColumnWidth = 250,", + "\n int groupDefaultExpanded = 2)", + "\n => reportBuilder.WithGridOptions(go => go", + "\n .WithColumns(cols => cols.Modify(\"Value\",c => c.WithWidth(valueColumnWidth).WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows", + "\n .Where(r => !(r.RowGroup.Coordinates.Last() == \"NullGroup\"))", + "\n .Select(r => r with { RowGroup = r.RowGroup with { Coordinates = r.RowGroup.Coordinates.Where(c => c != \"NullGroup\").ToImmutableList() } })", + "\n .ToArray())", + "\n .WithAutoGroupColumn(c => c.WithWidth(headerColumnWidth) with { Pinned = \"left\" })", + "\n with { Height = reportHeight, GroupDefaultExpanded = groupDefaultExpanded, OnGridReady = null } );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iBIqwkn9SUCQTW4I5tiVIg", + "cell_type": "code", + "source": [ + "public static string CurrencyGrouper(CurrencyType currencyType) => currencyType switch {", + "\n CurrencyType.Contractual => \"ContractualCurrency\",", + "\n CurrencyType.Functional => \"FunctionalCurrency\",", + "\n _ => string.Empty };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "M1TrAAwxbEaxJ2r5B3SSkw", + "cell_type": "markdown", + "source": [ + "# Queries" + ], + "metadata": {} + }, + { + "id": "K7EO5RzzdUq_sjJvMccxoA", + "cell_type": "markdown", + "source": [ + "## Query Report Variables" + ], + "metadata": {} + }, + { + "id": "bRSyLeKBd0KijXxUwm4o-w", + "cell_type": "code", + "source": [ + "public static async Task> QueryReportVariablesAsync(this IWorkspace workspace, (int Year, int Month, string ReportingNode, string Scenario) args ) {", + "\n ", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Year, Month = args.Month });", + "\n ", + "\n return await workspace.Query()", + "\n .Join(workspace.Query(),", + "\n dn => dn.SystemName,", + "\n iv => iv.DataNode,", + "\n (dn, iv) => new ReportVariable {", + "\n // From Args/Inputs", + "\n ReportingNode = args.ReportingNode,", + "\n Scenario = args.Scenario,", + "\n ", + "\n // From Data Node", + "\n Portfolio = dn.Portfolio,", + "\n GroupOfContract = dn.SystemName,", + "\n ", + "\n FunctionalCurrency = dn.FunctionalCurrency,", + "\n ContractualCurrency = dn.ContractualCurrency,", + "\n ", + "\n ValuationApproach = dn.ValuationApproach,", + "\n OciType = dn.OciType,", + "\n InitialProfitability = dn.Profitability,", + "\n LiabilityType = dn.LiabilityType,", + "\n AnnualCohort = dn.AnnualCohort,", + "\n LineOfBusiness = dn.LineOfBusiness,", + "\n ", + "\n // Reinsurance", + "\n IsReinsurance = dn is GroupOfReinsuranceContract, ", + "\n Partner = dn.Partner,", + "\n ", + "\n // From Variable", + "\n EstimateType = iv.EstimateType,", + "\n VariableType = iv.AocType,", + "\n Novelty = iv.Novelty,", + "\n AmountType = iv.AmountType,", + "\n EconomicBasis = iv.EconomicBasis,", + "\n ", + "\n //LIC", + "\n AccidentYear = iv.AccidentYear == null ? default : (int)iv.AccidentYear,", + "\n ", + "\n Value = iv.Value })", + "\n .ToArrayAsync();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Report/ReportScopes.ipynb b/Report/ReportScopes.ipynb new file mode 100644 index 00000000..534b3bc3 --- /dev/null +++ b/Report/ReportScopes.ipynb @@ -0,0 +1,1038 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "RC8Ga5S2p0C8yAmyjz_N-g", + "cell_type": "markdown", + "source": [ + "", + "\n

Report Scopes (IFRS17 Methodology Business Logic)

", + "\n", + "\nThis notebook contains the logic used to perform calculations upon reporting of data." + ], + "metadata": {} + }, + { + "id": "LVx2yOMaFE6N2gnro5w9Qg", + "cell_type": "markdown", + "source": [ + "# References", + "\nLibraries and other notebooks which are needed for this notebook are imported below." + ], + "metadata": {} + }, + { + "id": "9AZzZxEXwkCvLIoKhmBQlQ", + "cell_type": "markdown", + "source": [ + "## Notebooks" + ], + "metadata": {} + }, + { + "id": "MTpy2cXeG0GmCbe_aOWmBw", + "cell_type": "code", + "source": [ + "#!import \"ReportStorage\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "upikmN8zjU-hYfL_NTHY1A", + "cell_type": "markdown", + "source": [ + "# Scopes" + ], + "metadata": {} + }, + { + "id": "Zs3wCzFnZ0mgnoovzVtI4g", + "cell_type": "markdown", + "source": [ + "## Helper Scopes" + ], + "metadata": {} + }, + { + "id": "kMmCRDkymECPHAt_8qMONw", + "cell_type": "markdown", + "source": [ + "### Universe" + ], + "metadata": {} + }, + { + "id": "09cKY7l-c0WdVsk5Eqhscw", + "cell_type": "code", + "source": [ + "public interface IUniverse: IScopeWithStorage {}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KadX2iXWl02PhqX5WatT_A", + "cell_type": "markdown", + "source": [ + "## Data Transformation" + ], + "metadata": {} + }, + { + "id": "syVjSAh1tEazuQzXYkPajw", + "cell_type": "markdown", + "source": [ + "### Retrieve Raw Data" + ], + "metadata": {} + }, + { + "id": "MRPDIFQlykKNky6h_5dzzg", + "cell_type": "code", + "source": [ + "public interface Data: IScope<(ReportIdentity ReportIdentity, string EstimateType), ReportStorage>, IDataCube {", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", + "\n ", + "\n protected IDataCube RawData => GetStorage().GetVariables(Identity.ReportIdentity, Identity.EstimateType);", + "\n", + "\n private IDataCube RawEops => RawData.Filter((\"VariableType\", AocTypes.EOP));", + "\n private IDataCube NotEopsNotCls => RawData.Filter((\"VariableType\", \"!EOP\"),(\"VariableType\", \"!CL\")); // TODO negation must be hardcoded (also to avoid string concatenation)", + "\n ", + "\n private IDataCube CalculatedCl => (RawEops - NotEopsNotCls)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = AocTypes.CL });", + "\n ", + "\n private IDataCube CalculatedEops => (NotEopsNotCls + CalculatedCl)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => x with { VariableType = AocTypes.EOP, Novelty = Novelties.C });", + "\n ", + "\n IDataCube Data => NotEopsNotCls + CalculatedCl + CalculatedEops;", + "\n}", + "\npublic interface DataWrittenActual: Data {", + "\n IDataCube Data.Data => RawData;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yus8OX8BukyLFOjUwOQLLA", + "cell_type": "markdown", + "source": [ + "### Foreign Exchange (FX) Rates" + ], + "metadata": {} + }, + { + "id": "cJq9jrxRrEitDC2cNGnQLg", + "cell_type": "code", + "source": [ + "public interface Fx: IScope<(string ContractualCurrency, string FunctionalCurrency, FxPeriod FxPeriod, (int, int) Period, CurrencyType CurrencyType), ReportStorage> { ", + "\n private double groupFxRate => Identity.CurrencyType switch {", + "\n CurrencyType.Group => GetStorage().GetFx(Identity.Period, Identity.FunctionalCurrency, GroupCurrency, FxPeriod.Average),", + "\n _ => 1", + "\n };", + "\n ", + "\n private double GetFunctionalFxRate(FxPeriod fxPeriod) => Identity.CurrencyType switch {", + "\n CurrencyType.Contractual => 1,", + "\n _ => GetStorage().GetFx(Identity.Period, Identity.ContractualCurrency, Identity.FunctionalCurrency, fxPeriod)", + "\n };", + "\n ", + "\n double Fx => GetFunctionalFxRate(Identity.FxPeriod) * groupFxRate;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sFdrnO2l-kaXQVOwaTfu4Q", + "cell_type": "code", + "source": [ + "public interface FxData: IScope<(ReportIdentity ReportIdentity, CurrencyType CurrencyType, string EstimateType), ReportStorage>, IDataCube {", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", + "\n ", + "\n protected IDataCube Data => GetScope((Identity.ReportIdentity, Identity.EstimateType)).Data", + "\n .SelectToDataCube(x => GetScope((Identity.ReportIdentity.ContractualCurrency, ", + "\n Identity.ReportIdentity.FunctionalCurrency, ", + "\n GetStorage().GetFxPeriod(GetStorage().Args.Period, x.VariableType, x.Novelty),", + "\n (Identity.ReportIdentity.Year, Identity.ReportIdentity.Month),", + "\n Identity.CurrencyType", + "\n )).Fx * x);", + "\n ", + "\n private IDataCube Eops => Data.Filter((\"VariableType\", AocTypes.EOP));", + "\n private IDataCube NotEops => Data.Filter((\"VariableType\", \"!EOP\")); // TODO negation must be hardcoded (also to avoid string concatenation)", + "\n ", + "\n private IDataCube Fx => (Eops - NotEops)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = AocTypes.FX });", + "\n ", + "\n IDataCube FxData => Data + Fx;", + "\n}", + "\n", + "\npublic interface FxDataWrittenActual: FxData {", + "\n IDataCube FxData.FxData => Data;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "c-y9Rq20yU-c1k-zkJbtZA", + "cell_type": "markdown", + "source": [ + "## Present Value" + ], + "metadata": {} + }, + { + "id": "uD97mWuNn0i7IDWGmZcNvQ", + "cell_type": "markdown", + "source": [ + "", + "\n### Best Estimate", + "\n", + "\nBest Estimate of Present Value (PV) report includes contributions from the [Present Value](../Import/ImportScopeCalculation#current-and-locked) calculation. The result of the Locked-in calculation is used when the Valuation Approach is BBA and the flag for Oci is active." + ], + "metadata": {} + }, + { + "id": "JgpSiRtFuEmUmFnBtZdTRA", + "cell_type": "code", + "source": [ + "public interface BestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube BestEstimate => Identity.Id switch {", + "\n { ValuationApproach: ValuationApproaches.BBA, IsOci: true } => GetScope(Identity).LockedBestEstimate,", + "\n _ => GetScope(Identity).CurrentBestEstimate };", + "\n}", + "\n", + "\npublic interface LockedBestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube LockedBestEstimate => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BE)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.L));", + "\n}", + "\n", + "\npublic interface CurrentBestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube CurrentBestEstimate => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BE)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.C));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "o4YOxEue9U2IsUWtpQRwNg", + "cell_type": "markdown", + "source": [ + "", + "\n### Risk Adjustment", + "\n", + "\nRisk Adjustment (RA) report includes contributions from the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) calculation. The result of the Locked-in calculation is used when the Valuation Approach is BBA and the flag for Oci is active." + ], + "metadata": {} + }, + { + "id": "j6tStuZslUWvsTYy34vFCQ", + "cell_type": "code", + "source": [ + "public interface RiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube RiskAdjustment => Identity.Id switch {", + "\n { ValuationApproach: ValuationApproaches.BBA, IsOci: true } => GetScope(Identity).LockedRiskAdjustment,", + "\n _ => GetScope(Identity).CurrentRiskAdjustment };", + "\n}", + "\n", + "\npublic interface LockedRiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube LockedRiskAdjustment => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.RA)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.L));", + "\n}", + "\n", + "\npublic interface CurrentRiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube CurrentRiskAdjustment => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.RA)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.C));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "P-vfX_L3rkW_9Lmf31RxpA", + "cell_type": "markdown", + "source": [ + "", + "\n## Fulfillment Cashflows", + "\nFulfillment Cashflows (FCF) report includes contributions from the [Best Estimate](#best-estimate) of Present Value and [Risk Adjustment](#risk-adjustment) Present Value." + ], + "metadata": {} + }, + { + "id": "KK0mF25Mf0aFBgqRlpZL9g", + "cell_type": "code", + "source": [ + "public interface Fcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube BestEstimate => GetScope(Identity).BestEstimate;", + "\n private IDataCube RiskAdjustment => GetScope(Identity).RiskAdjustment;", + "\n ", + "\n IDataCube Fcf => BestEstimate + RiskAdjustment;", + "\n}", + "\n", + "\npublic interface CurrentFcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube { ", + "\n private IDataCube BestEstimate => GetScope(Identity).CurrentBestEstimate;", + "\n private IDataCube RiskAdjustment => GetScope(Identity).CurrentRiskAdjustment;", + "\n ", + "\n IDataCube CurrentFcf => BestEstimate + RiskAdjustment;", + "\n}", + "\n", + "\npublic interface LockedFcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube { ", + "\n private IDataCube BestEstimate => GetScope(Identity).LockedBestEstimate;", + "\n private IDataCube RiskAdjustment => GetScope(Identity).LockedRiskAdjustment;", + "\n ", + "\n IDataCube LockedFcf => BestEstimate + RiskAdjustment;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BnSosIcbCUqw1lbDI0LxPw", + "cell_type": "markdown", + "source": [ + "", + "\n## LRC Technical Margin: CSM, LC, LoReCo", + "\n", + "\nContractual Service Margin (CSM), Loss Component (LC), Loss Recovery Component (LoReCo) reports of the Liability for Remaining Coverage (LRC) include contributions from the calculation of [CSM](../Import/ImportScopeCalculation#csm), [LC](../Import/ImportScopeCalculation#csm), and [LoReCo](../Import/ImportScopeCalculation#csm), respectively." + ], + "metadata": {} + }, + { + "id": "ZPTctq2WjkinG6niMamqoA", + "cell_type": "code", + "source": [ + "public interface Csm: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Csm => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.C)).FxData;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cG4TSd1LZ0iIWMjgLaB7iA", + "cell_type": "code", + "source": [ + "public interface Lc: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Lc => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.L)).FxData;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2pNl3ECznUOsfhcu-OWIPQ", + "cell_type": "code", + "source": [ + "public interface Loreco: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Loreco => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.LR)).FxData;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "t2D8_dXH90uK90VYE8I_Fg", + "cell_type": "code", + "source": [ + "public interface LrcTechnicalMargin: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube Csm => GetScope(Identity).Csm;", + "\n private IDataCube Lc => GetScope(Identity).Lc;", + "\n private IDataCube Loreco => GetScope(Identity).Loreco;", + "\n ", + "\n IDataCube LrcTechnicalMargin => Lc + Loreco - 1 * Csm;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QXA-wNeyfkStz-eabLqYkw", + "cell_type": "markdown", + "source": [ + "", + "\n## Written, Accruals and Deferrals ", + "\n", + "\nWritten Actual (Actual) report includes contributions from the [Actual](../Import/ImportScopeCalculation#actuals) import. ", + "\n
Accrual Actuals (Advance, Overdue Actual) report includes contributions from the [Advance](../Import/ImportScopeCalculation#advance-actuals) and [Overdue](../Import/ImportScopeCalculation#overdue-actuals) Actual calculation.", + "\n
Deferral (Deferral Actual) report includes contributions from the calculation of [Deferral](../Import/ImportScopeCalculation#deferrable-actuals) Actual." + ], + "metadata": {} + }, + { + "id": "6oQzlalJiEKtr4FVgbf30g", + "cell_type": "code", + "source": [ + "public interface WrittenAndAccruals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Written => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.A)).FxData;", + "\n IDataCube Advance => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.AA)).FxData;", + "\n IDataCube Overdue => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.OA)).FxData;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ezZf5dedgUuHkuUp-bBDDg", + "cell_type": "code", + "source": [ + "public interface Deferrals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Deferrals => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.DA)).FxData;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FSsDY7cH70S2Lu3yXeXw3w", + "cell_type": "markdown", + "source": [ + "## Experience Adjustment", + "\n", + "\nExperience Adjustment (EA) report includes contributions from the [Written](#written-accrual-deferral) Actual report and the [Best Estimate](#best-estimate) of Present Value report (only the *Cash flow* AocStep). " + ], + "metadata": {} + }, + { + "id": "JRn9_o5AL06364MC1z7Fkg", + "cell_type": "code", + "source": [ + "public interface ExperienceAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube WrittenCashflow => GetScope(Identity).Written", + "\n .Filter((\"VariableType\", AocTypes.CF));", + "\n ", + "\n private IDataCube BestEstimateCashflow => GetScope(Identity).BestEstimate", + "\n .Filter((\"VariableType\", AocTypes.CF))", + "\n .SelectToDataCube(rv => rv with { EconomicBasis = null, Novelty = Novelties.C });", + "\n", + "\n IDataCube ActuarialExperienceAdjustment => WrittenCashflow - BestEstimateCashflow;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9YDqvT60sUuBmJmZL-tF7w", + "cell_type": "markdown", + "source": [ + "", + "\n## LIC Actuarial (Actuarial Liability for Incurred Claims)", + "\n", + "\nLiability of Incurred Claims (LIC Actuarial) report includes the contributions from [Fulfillment cashflow](#fulfillment-cashflows)." + ], + "metadata": {} + }, + { + "id": "N9PQzPef10meQscdc39AtQ", + "cell_type": "code", + "source": [ + "public interface LicActuarial: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube LicActuarial => GetScope(Identity).CurrentFcf.Filter((\"LiabilityType\", LiabilityTypes.LIC));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BWNVgJ7kVUuivi0spCqfcw", + "cell_type": "markdown", + "source": [ + "## LIC (Liability for Incurred Claims)", + "\n", + "\nLiability of Incurred Claims (LIC) report includes the contributions from [Lic Actuarial](#lic-actuarial) (Fullfilment Cashflow), [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." + ], + "metadata": {} + }, + { + "id": "TDQUKQ-ZLEuPyI1q0ZU9yg", + "cell_type": "code", + "source": [ + "public interface Lic: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube licActuarial => GetScope(Identity).LicActuarial;", + "\n private IDataCube accrual => GetScope(Identity).Advance.Filter((\"LiabilityType\", LiabilityTypes.LIC)) + ", + "\n GetScope(Identity).Overdue.Filter((\"LiabilityType\", LiabilityTypes.LIC));", + "\n private IDataCube licData => licActuarial + accrual;", + "\n ", + "\n private IDataCube bop => licData.Filter((\"VariableType\", AocTypes.BOP));", + "\n private IDataCube delta => licData.Filter((\"VariableType\",\"!BOP\"),(\"VariableType\",\"!EOP\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = \"D\" });", + "\n private IDataCube eop => licData.Filter((\"VariableType\",AocTypes.EOP));", + "\n ", + "\n IDataCube Lic => bop + delta + eop;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jFBlyVq-A0G7tmw5YdUm2Q", + "cell_type": "markdown", + "source": [ + "", + "\n## LRC Actuarial (Actuarial Liability for Remaining Coverage)", + "\n", + "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [Fulfillment cashflow](#fulfillment-cashflows), [Contructual Sevice Margin](#technical-margin), [Loss Component](#technical-margin), and [Loss Recovery Component](#technical-margin)." + ], + "metadata": {} + }, + { + "id": "Nh6Na96xYkGFXBLGuTXAWQ", + "cell_type": "code", + "source": [ + "public interface LrcActuarial: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube Fcf => GetScope(Identity).CurrentFcf.Filter((\"LiabilityType\", LiabilityTypes.LRC));", + "\n private IDataCube Csm => GetScope(Identity).Csm;", + "\n private IDataCube Loreco => GetScope(Identity).Loreco;", + "\n ", + "\n IDataCube LrcActuarial => Fcf + Csm + Loreco;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ivAB2SOatESuXm7mpgcW5w", + "cell_type": "markdown", + "source": [ + "## LRC (Liability for Remaining Coverage)", + "\n", + "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [LRC Actuarial](#lrc-actuarial) (Fulfillment Cashflow, Contructual Sevice Margin, Loss Component, Loss Recovery Component) and, [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." + ], + "metadata": {} + }, + { + "id": "G1fG1yC8kEyGuJfovw39HA", + "cell_type": "code", + "source": [ + "public interface Lrc: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube lrcActuarial => GetScope(Identity).LrcActuarial;", + "\n private IDataCube accrual => GetScope(Identity).Advance.Filter((\"LiabilityType\", LiabilityTypes.LRC)) + ", + "\n GetScope(Identity).Overdue.Filter((\"LiabilityType\", LiabilityTypes.LRC));", + "\n private IDataCube lrcData => lrcActuarial + accrual;", + "\n ", + "\n private IDataCube bop => lrcData.Filter((\"VariableType\",AocTypes.BOP));", + "\n private IDataCube delta => lrcData.Filter((\"VariableType\",\"!BOP\"),(\"VariableType\",\"!EOP\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = \"D\" });", + "\n private IDataCube eop => lrcData.Filter((\"VariableType\",AocTypes.EOP));", + "\n ", + "\n IDataCube Lrc => bop + delta + eop;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q-X5STJu20-7PdTNWxysqg", + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17 Financial Performance" + ], + "metadata": {} + }, + { + "id": "_F85lUYI8USa7GLuh0CFYA", + "cell_type": "markdown", + "source": [ + "The IFRS 17 Financial Performance aims at disclosing the deltas (i.e. difference between EoP and BoP, or the Change in Estimate) of the IFRS 17 Balance Sheet items (LRC, LIC) and the relevant incurred cashflows (Premiums, Claims, Expenses, etc...) for the given period.", + "\n", + "\nIn addition, the IFRS 17 Financial Performance must split the results into at least 4 distinct sections:", + "\n - Insurance Revenue ($IR$)", + "\n - Insurance Service Expense ($ISE$)", + "\n - Insurance Finance Income/Expense ($IFIE$)", + "\n - Other Comprehensive Income ($OCI$)", + "\n", + "\nThese can be structured in a hierarchy, such that aggregation and intermediate results can be shown separately.", + "\nAlso the granularity for some relevant items (e.g. Gross LRC vs Reinsurance LRC) must be split into the different sections, as the notion of Insurance Revenue and Insurance Service Expense must be consistent.", + "\n", + "\nThe overall formulas for each of the sections above are as follows:", + "\n$$", + "\n\\begin{array}{rl}", + "\nIR =& -\\Delta \\text{ Gross Non-Financial LRC } - \\text{ Incurred Incoming Cashflows } - \\text{ Claims Investment Component } + \\text{ Amortization of the Insurance Acquisition Cashflows} - \\text{ Experience Adjustment On Premium }", + "\n\\\\", + "\nISE =& -\\Delta \\text{ Reinsurance Non-Financial LRC } - \\Delta \\text{ Non-Financial LIC } - \\Delta \\text{ Loss Component } - \\text{ Incurred Outgoing Cashflows } - \\text{ Amortization of the Insurance Acquisition Cashflows}", + "\n\\\\", + "\nIFIE =& -\\Delta \\text{ Financial LRC } - \\Delta \\text{ Financial LIC }", + "\n\\\\", + "\nOCI =& \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Valuation Rates } + \\Delta \\text{ LIC at Valuation Rates } - \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Current Rates } - \\Delta \\text{ LIC at Current Rates }", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor CSM, LC and LoReCo (and implicit Amortization Factors / Coverage Units), the yield curve used is according to the methodology choice (e.g. BBA uses Locked-In rates). ", + "\n", + "\nThe Fulfillment Cashflows components for LIC and LRC are discounted using the appropriate yield curve (Locked-In or Current) according to the choice of the OCI option and methodology. We can distinguish 2 cases for the Building Block approach (BBA):", + "\n - BBA, OCI option ***disabled***: FCF computed using Current rates", + "\n - BBA, OCI option ***enabled***: FCF computed using Locked-In rates", + "\n", + "\nIn the case when the OCI option is disabled, the OCI contribution is zero. Otherwise, we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\nOCI =& \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Locked-In Rates } + \\Delta \\text{ LIC at Locked-In Rates } - \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Current Rates } - \\Delta \\text{ LIC at Current Rates }", + "\n\\end{array}", + "\n$$", + "\n", + "\nUsually, some more details on the items above are desired (e.g. separating the LRC into its components FCF, RA, CSM/LC or explicitly showing the CSM Amortization vs. other financial/non-financial adjustments to the CSM estimation). These are specific to each implementation and depend on the data granularity (e.g. how the Amount Types, AoC steps are detailed and structured). This level of detail is omitted from the generic documentation presented here, but are implicit to the way each item above is calculated. Nevertheless, this extra granularity is available when the reports are generated and sliced by the corresponding dimensions. " + ], + "metadata": {} + }, + { + "id": "yUjR-vS6yUm5Enx3ZvkzIA", + "cell_type": "markdown", + "source": [ + "## Fulfillment Cashflows (excluding the Loss Component)" + ], + "metadata": {} + }, + { + "id": "y-_vkbeDdk-drcNsqFxKgw", + "cell_type": "markdown", + "source": [ + "Let us first describe the Balance Sheet items, where we need to disclose the Changes in Estimate in the Financial Performance.", + "\nAs mentioned, often the LRC and LIC contributions are broken down into smaller parts for disclosure and reconciliation purposes.", + "\n", + "\nThe Fulfillment Cashflows (which may include onerous contributions in some interpretations when a Loss Component is defined) contributions to the Financial Performance (Insurance Result and OCI) are detailed below.", + "\nThe main requisite is to ensure the right mapping of its non-financial and financial components into the appropriate sections of the Financial Performance.", + "\n", + "\nFurthermore, we also need to distinguish the Reinsurance contributions to the LRC, as they are considered to be expenses and not revenue.", + "\nThe OCI contribution is also performed here, as the only contributions to the OCI come from the FCF under the current methodology assumptions.", + "\nTo all contributions a sign flip is applied. ", + "\n", + "\nIn particular: ", + "\n- Financial component includes the AocType Interest Accreation, Yield Curve Update, and Credit Risk Update,", + "\n- Non-Financial component includes all the remaining AocTypes.", + "\n- Oci component includes the difference between the movement occured in the period computed applying the discounting with the current yield curve and the discounting with the locked-in yield curve.", + "\n", + "\nThe Financial contributions are reported in 'Financial LIC Changes' for a Group of Contract with Liability Type LIC and to 'Financial LRC Changes' for a Group of Contract with Liability Type LRC.", + "\n
The Non Financial contributions are reported in 'Non Financial LIC Changes' for a Group of Contract with Liability Type LIC. For a Group of Contract with Liability Type LRC, they are reported in 'Non-Financial LRC Changes (Exc. CSM Amortization)' for a Group of Insurance Contract and in 'Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo)' for a Group of Reinsurance Contract.", + "\n
The Oci contributions are reported in the 'Other Comprehensive Income' section under 'Financial LIC Changes' or a Group of Contract with Liability Type LIC and to 'Financial LRC Changes' for a Group of Contract with Liability Type LRC." + ], + "metadata": {} + }, + { + "id": "WkhNSKUFjkaCCaIOupDs4w", + "cell_type": "code", + "source": [ + "public interface FcfChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube FcfDeltas => GetScope(Identity).Fcf.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Fcf.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n private IDataCube CurrentFcfDeltas => GetScope(Identity).CurrentFcf.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).CurrentFcf.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n", + "\n // Non-Financial Fp", + "\n private string variableTypeNonFinancial => Identity.Id switch {", + "\n { LiabilityType: LiabilityTypes.LRC, IsReinsurance: false } => \"IR5\",", + "\n { LiabilityType: LiabilityTypes.LRC, IsReinsurance: true } => \"ISE10\",", + "\n { LiabilityType: LiabilityTypes.LIC } => \"ISE12\"", + "\n };", + "\n ", + "\n private IDataCube NonFinancialFcfDeltas => FcfDeltas", + "\n .Filter((\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")); ", + "\n ", + "\n IDataCube FpNonFinancial => -1 * NonFinancialFcfDeltas", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeNonFinancial }); ", + "\n ", + "\n // Financial Fp", + "\n private string variableTypeFpFinancial => Identity.Id switch {", + "\n { LiabilityType: LiabilityTypes.LRC } => \"IFIE1\",", + "\n { LiabilityType: LiabilityTypes.LIC } => \"IFIE2\",", + "\n };", + "\n ", + "\n // OCI ", + "\n private string variableTypeOciFinancial => Identity.Id switch {", + "\n { LiabilityType: LiabilityTypes.LRC } => \"OCI1\",", + "\n { LiabilityType: LiabilityTypes.LIC } => \"OCI2\",", + "\n };", + "\n ", + "\n private IDataCube FinancialFcfDeltas => FcfDeltas.Filter((\"VariableType\", AocTypes.IA)) + ", + "\n FcfDeltas.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n FcfDeltas.Filter((\"VariableType\", AocTypes.CRU));", + "\n ", + "\n IDataCube FpFinancial => -1 * FinancialFcfDeltas", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeFpFinancial});", + "\n", + "\n IDataCube OciFinancial => (FcfDeltas - CurrentFcfDeltas)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeOciFinancial});", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MlJhmth_qkiiKsC8XSxAdw", + "cell_type": "markdown", + "source": [ + "Subsequently, the Contractual Service Margin (CSM), Loss Component (LC) and Loss Recovery Component (LoReCo) are also divided into non-financial and financial components. In addition the corresponding amortization/releases (CSM Amortization, LC Release and LoReCo Release) are also explicitly shown." + ], + "metadata": {} + }, + { + "id": "yqLNUINQEk2fACiFnKzGhg", + "cell_type": "markdown", + "source": [ + "## Contractual Service Margin (CSM)", + "\n", + "\nCsm contributes to the 'Insurance Revenue' in the case of a Group of Insurance Contract and to the 'Insurance Service Expense' in the case of a Group of Reinsurance Contract and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", + "\nIn particular, the CSM figures are separated in three cathegories: ", + "\n- Amortization (including to AocType Amortization),", + "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", + "\n- Non Financial contributions (including all the remaining AocTypes).", + "\n", + "\n
The Amortization contribution is reported in 'Insurance Revenue' under 'CSM Amortization' or in 'Insurance Service Expense' under 'Reinsurance CSM Amortization' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively. ", + "\n
The Financial contributions are reported in 'Financial LRC Changes'.", + "\n
The Non Financial contributions are reported in 'Non-Financial LRC Changes (Exc. CSM Amortization)' and 'Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo)' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively. " + ], + "metadata": {} + }, + { + "id": "JZhM9-mDEUKaqcD8QoIvCg", + "cell_type": "code", + "source": [ + "public interface CsmChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private (string amortization, string nonFinancial) variableType => Identity.Id switch {", + "\n { IsReinsurance: false} => (\"IR3\", \"IR5\"),", + "\n { IsReinsurance: true } => (\"ISE7\", \"ISE10\")", + "\n };", + "\n ", + "\n private IDataCube Csm => GetScope(Identity).Csm.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Csm.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n IDataCube Amortization => -1 * Csm.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = variableType.amortization });", + "\n ", + "\n IDataCube NonFinancialChanges => -1 * Csm", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = variableType.nonFinancial });", + "\n ", + "\n IDataCube FinancialChanges => -1 * (Csm.Filter((\"VariableType\", AocTypes.IA)) +", + "\n Csm.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n Csm.Filter((\"VariableType\", AocTypes.CRU)) )", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yylNI472I0u4OuR1Bllheg", + "cell_type": "markdown", + "source": [ + "## Loss Component (LC)", + "\n", + "\nLC contributes to the 'Insurance Service Expense' and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", + "\nIn particular, the LC figures are separated in three cathegories: ", + "\n- Amortization (including to AocType Amortization),", + "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", + "\n- Non Financial contributions (including all the remaining AocTypes).", + "\n", + "\n
The Amortization contribution is reported in 'Loss Component Release'.", + "\n
The Financial contributions are reported in 'Financial LRC Changes'.", + "\n
The Non Financial contributions are reported in 'Loss Component / LoReCo Changes (Exc. Releases)'." + ], + "metadata": {} + }, + { + "id": "52YpETmY1kmKN_CcZj4cpw", + "cell_type": "code", + "source": [ + "public interface LcChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private IDataCube Lc => GetScope(Identity).Lc.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Lc.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n IDataCube Amortization => -1 * Lc.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE9\" });", + "\n ", + "\n IDataCube NonFinancialChanges => -1 * Lc", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", + "\n ", + "\n IDataCube FinancialChanges => -1 * (Lc.Filter((\"VariableType\", AocTypes.IA)) +", + "\n Lc.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n Lc.Filter((\"VariableType\", AocTypes.CRU)) )", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1-0UxQCxX0-LKLJ0MCCYUw", + "cell_type": "markdown", + "source": [ + "## Loss Recovery Component (LoReCo)", + "\n", + "\nLoReCo contributes to the 'Insurance Service Expense' and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", + "\nIn particular, the LoReCo figures are separated in three cathegories: ", + "\n- Amortization (including to AocType Amortization),", + "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", + "\n- Non Financial contributions (including all the remaining AocTypes).", + "\n", + "\n
The Amortization contribution is reported in 'LoReCo Release'.", + "\n
The Financial contributions are reported in 'Financial LRC Changes'.", + "\n
The Non Financial contributions are reported in 'Loss Component / LoReCo Changes (Exc. Releases)'." + ], + "metadata": {} + }, + { + "id": "d6UE4RWht0uRmVVVLSV2VA", + "cell_type": "code", + "source": [ + "public interface LorecoChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private IDataCube Loreco => GetScope(Identity).Loreco.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Loreco.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n IDataCube Amortization => -1 * Loreco.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE8\" });", + "\n ", + "\n IDataCube NonFinancialChanges => -1 * Loreco", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", + "\n ", + "\n IDataCube FinancialChanges => -1 * (Loreco.Filter((\"VariableType\", AocTypes.IA)) +", + "\n Loreco.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n Loreco.Filter((\"VariableType\", AocTypes.CRU)) )", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Ugt3GrQOf0Or0r17sFKx6Q", + "cell_type": "markdown", + "source": [ + "## Incurred Actuals" + ], + "metadata": {} + }, + { + "id": "zhrluPCsVUSl09Ib5324jA", + "cell_type": "markdown", + "source": [ + "After the main Balance Sheet items, we need to disclose the Incurred Cashflows (i.e. Actuals) for the period in the Financial Performance (which includes the effect of Advance and Overdue Accruals, but Write-Off amounts are not taken into account).", + "\nAs another requirement, we exclude any investment components explicitly.", + "\n", + "\nThese contributions are splitted by Amount Type to the following sections:", + "\n- Premiums contributions are reported under 'Insurance Revenue' in 'Premiums' section or in 'Insurance Service Expense' under 'Reinsurance Premiums' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively,", + "\n- Claims Non-Investment Component contributions are reported under 'Insurance Revenue' in 'Claims' section,", + "\n- Claims Investment Component contributions are reported under 'Insurance Service Expense' in 'Acquisition Expenses' section and under 'Insurance Revenue' in 'Exc. Investment Components' section with a sign change,", + "\n- Expenses contributions are reported under 'Insurance Service Expense' in 'Expenses' section,", + "\n- Commissions contributions are reported under 'Insurance Service Expense' in 'Commissions' section." + ], + "metadata": {} + }, + { + "id": "UfES8juT2kSi22gODGLDCw", + "cell_type": "code", + "source": [ + "public interface IncurredActuals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube WrittenAndAccruals => GetScope(Identity).Filter((\"VariableType\", \"CF\"));", + "\n ", + "\n private string premiumsVariableType => Identity.Id switch {", + "\n { IsReinsurance: false} => \"IR1\",", + "\n { IsReinsurance: true } => \"ISE1\"", + "\n }; ", + "\n ", + "\n IDataCube Premiums => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.PR))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = premiumsVariableType });", + "\n ", + "\n IDataCube ClaimsNic => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.NIC))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE2\" });", + "\n ", + "\n private IEnumerable ClaimsIco => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO));", + "\n ", + "\n IDataCube ClaimsIcoToIr => ClaimsIco.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR2\" });", + "\n IDataCube ClaimsIcoToIse => (-1 * ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", + "\n ", + "\n IDataCube Expenses => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AE))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE3\" });", + "\n", + "\n IDataCube Commissions => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AC))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE4\" });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LwsvN0yOSkCOVRXLN381JQ", + "cell_type": "markdown", + "source": [ + "## Incurred Deferrals and Acquisition Expenses" + ], + "metadata": {} + }, + { + "id": "wiPCBpKmKUq9k5vGf5XfNg", + "cell_type": "markdown", + "source": [ + "The next item are the Deferrals, where the Amortization is the only contribution explicitly shown, but these do not have any direct impact on the Financial Performance under the current methodology assumptions. The Amortization contribution is here considered with its sign changed. This contribution is allocated under 'Insurance Service Expense' in 'Acquisition Expenses' section and under 'Insurance Revenue' in 'Acquistion Expenses Amortization' section with a sign change. " + ], + "metadata": {} + }, + { + "id": "aSfW_K2sMkiui5Kyu0MiDA", + "cell_type": "code", + "source": [ + "public interface IncurredDeferrals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube Deferrals => GetScope(Identity).Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\"));", + "\n ", + "\n private IDataCube Amortization => -1 * Deferrals", + "\n .Filter((\"VariableType\", AocTypes.AM));", + "\n ", + "\n IDataCube AmortizationToIr => (-1 * Amortization).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR4\" });", + "\n IDataCube AmortizationToIse => Amortization.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE6\" });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "SOtkVo0ffEKckF0hH2Q6YQ", + "cell_type": "markdown", + "source": [ + "## Experience Adjustment on Premium (allocation to CSM vs P&L recognition)" + ], + "metadata": {} + }, + { + "id": "Pgc61JA6rU6RdoGTvHFhIQ", + "cell_type": "markdown", + "source": [ + "The figures disclosed in the Financial Performance as described above consider full Premiums for past, current and future services (for Best Estimate and Actuals).", + "\nHowever, we applied the Premium Allocation factor in the CSM computations to adjust for the experience. To correct this, we need to exclude the Experience Adjustment on Premium part in the Financial Performance to avoid double counting and it is allocated under 'Insurance Revenue' in the 'Exc. Experience Adjustment on Premiums' section." + ], + "metadata": {} + }, + { + "id": "3rmklNkYPkSHioMl14xxiw", + "cell_type": "code", + "source": [ + "public interface ExperienceAdjustmentOnPremium: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube WrittenPremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.APA)).FxData;", + "\n private IDataCube AdvancePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.AAPA)).FxData;", + "\n private IDataCube OverduePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.OAPA)).FxData;", + "\n private IDataCube BestEstimatePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BEPA)).FxData;", + "\n ", + "\n IDataCube ExperienceAdjustmentOnPremium => (WrittenPremiumToCsm + AdvancePremiumToCsm + OverduePremiumToCsm - BestEstimatePremiumToCsm)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR6\" });", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zr-GVPs8uUWdzPGwaINBrQ", + "cell_type": "markdown", + "source": [ + "## Financial Performance" + ], + "metadata": {} + }, + { + "id": "-aWqJjLyD0qw69pCfTydUg", + "cell_type": "markdown", + "source": [ + "As the last step, all the contributions above are calculated and combined into the Financial Performance, which will be used to generate the final report." + ], + "metadata": {} + }, + { + "id": "3eqY3uzwA0aCp5NOV-TpWw", + "cell_type": "code", + "source": [ + "public interface FinancialPerformance: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private IDataCube FcfChangeInEstimate => GetScope(Identity);", + "\n private IDataCube CsmChangeInEstimate => GetScope(Identity);", + "\n private IDataCube LcChangeInEstimate => GetScope(Identity);", + "\n private IDataCube LorecoChangeInEstimate => GetScope(Identity);", + "\n private IDataCube IncurredActuals => GetScope(Identity);", + "\n private IDataCube IncurredDeferrals => GetScope(Identity);", + "\n private IDataCube ExperienceAdjustmentOnPremium => GetScope(Identity);", + "\n ", + "\n IDataCube FinancialPerformance => FcfChangeInEstimate + CsmChangeInEstimate + LcChangeInEstimate + LorecoChangeInEstimate + IncurredActuals + IncurredDeferrals + ExperienceAdjustmentOnPremium;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xgem_L0voUyElSD53tj9BQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Report/ReportStorage.ipynb b/Report/ReportStorage.ipynb new file mode 100644 index 00000000..7eea19f9 --- /dev/null +++ b/Report/ReportStorage.ipynb @@ -0,0 +1,241 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "HEuASoWo4UGVdx8dGf6u_A", + "cell_type": "markdown", + "source": [ + "", + "\n

Report Storage and Identity

", + "\n", + "\nThe Report Identity is a record collecting all information needed to define the granularity in which the calculation are performed.", + "\n", + "\nThe Report Storage collects the required data and parameters used in the calculations.", + "\n", + "\nBoth Storage and Identity are defined to support the calculations defined in the corresponding [Report Scopes](./ReportScopes)." + ], + "metadata": {} + }, + { + "id": "lH7xWMjez0q8ciCz4Qykww", + "cell_type": "code", + "source": [ + "#!import \"ReportConfigurationAndUtils\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2dj3bWBcRkGx9h4euZjMZA", + "cell_type": "markdown", + "source": [ + "# Report Identity" + ], + "metadata": {} + }, + { + "id": "XYiuv9tTxk218jeGK45wwg", + "cell_type": "code", + "source": [ + "[IdentityAggregationBehaviour(IdentityAggregationBehaviour.Aggregate)]", + "\npublic record ReportIdentity {", + "\n ", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n public int Year { get; init; }", + "\n", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n public int Month { get; init; }", + "\n", + "\n [Dimension(typeof(ReportingNode))]", + "\n public string ReportingNode { get; init; }", + "\n ", + "\n [Dimension(typeof(Scenario))]", + "\n public string Scenario { get; init; }", + "\n", + "\n [Dimension(typeof(Currency), nameof(ContractualCurrency))]", + "\n public string ContractualCurrency { get; init; }", + "\n ", + "\n [Dimension(typeof(Currency), nameof(FunctionalCurrency))]", + "\n public string FunctionalCurrency { get; init; }", + "\n", + "\n [NotAggregated]", + "\n [Dimension(typeof(int), nameof(Projection))]", + "\n public int Projection { get; init; }", + "\n", + "\n [Dimension(typeof(LiabilityType))]", + "\n public string LiabilityType { get; init; }", + "\n ", + "\n [Dimension(typeof(ValuationApproach))]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n public bool IsReinsurance { get; init; } //TODO use ReinsuranceType", + "\n ", + "\n public bool IsOci { get; init; } ", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Xp1yqkllkEeactK1U1Wfbw", + "cell_type": "markdown", + "source": [ + "# Report Storage" + ], + "metadata": {} + }, + { + "id": "vXC3nuN1jUaN-35vvZ9pWA", + "cell_type": "code", + "source": [ + "public class ReportStorage {", + "\n protected readonly IWorkspace workspace;", + "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchicalDimensionCache;", + "\n private readonly Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory;", + "\n ", + "\n // Current Storage Settings", + "\n public ((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args {get; private set;}", + "\n ", + "\n // Cache for Aux Data ", + "\n private Dictionary<(int year, int month), Dictionary>> exchangeRatesByCurrencyByFxTypeAndPeriod = new(); // Fx Rates", + "\n private Dictionary<(int year, int month), Dictionary> fxPeriodsByAocStepAndPeriod = new(); // FxParameter", + "\n ", + "\n public HashSet EstimateTypesWithoutAoc {get; private set;}", + "\n ", + "\n // Cache for Variables and Parameters", + "\n private Dictionary<((int year, int month) period, string reportingNode, string scenario), Dictionary>>> variablesDictionary = new();", + "\n ", + "\n // Constructor", + "\n public ReportStorage(IWorkspace workspace, Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory) {", + "\n this.workspace = workspace;", + "\n this.hierarchicalDimensionCache = workspace.ToHierarchicalDimensionCache();", + "\n this.reportFactory = reportFactory;", + "\n }", + "\n ", + "\n // Initializers", + "\n public async Task InitializeReportIndependentCacheAsync() {", + "\n // Hierarchical Dimensions", + "\n hierarchicalDimensionCache.Initialize();", + "\n hierarchicalDimensionCache.Initialize(); ", + "\n hierarchicalDimensionCache.Initialize();", + "\n hierarchicalDimensionCache.Initialize();", + "\n }", + "\n ", + "\n public async Task InitializeAsync((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType) {", + "\n // Report Dependent Cache", + "\n", + "\n // Setting the Args --> Temp for the moment", + "\n Args = (period, reportingNode, scenario, currencyType);", + "\n ", + "\n EstimateTypesWithoutAoc = (await workspace.Query().Where(x => x.StructureType != StructureType.AoC).Select(x => x.SystemName).ToArrayAsync()).ToHashSet();", + "\n ", + "\n // FX && Fx Parameters", + "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType) || !fxPeriodsByAocStepAndPeriod.TryGetValue(period, out var fxPeriodsByAocStep)) {", + "\n exchangeRatesByCurrencyByFxType = await workspace.GetExchangeRatesDictionaryAsync(period.year, period.month);", + "\n exchangeRatesByCurrencyByFxTypeAndPeriod.Add(period, exchangeRatesByCurrencyByFxType);", + "\n fxPeriodsByAocStep = (await workspace.LoadAocStepConfigurationAsync(period.year, period.month)).Where(x => x.FxPeriod != FxPeriod.NotApplicable).ToDictionary(x => new AocStep(x.AocType, x.Novelty), x => (FxPeriod)x.FxPeriod);", + "\n fxPeriodsByAocStepAndPeriod.Add(period, fxPeriodsByAocStep);", + "\n }", + "\n ", + "\n // Variables", + "\n foreach(var rn in GetLeaves(reportingNode)) { ", + "\n if(!variablesDictionary.TryGetValue((period, rn, scenario), out var variablesByIdentity)) {", + "\n variablesByIdentity = (await workspace.QueryReportVariablesAsync((period.year, period.month, rn, scenario)))", + "\n .ToDictionaryGrouped(x => new ReportIdentity {", + "\n Year = period.year,", + "\n Month = period.month,", + "\n ReportingNode = x.ReportingNode,", + "\n Scenario = x.Scenario,", + "\n Projection = x.Projection,", + "\n ContractualCurrency = x.ContractualCurrency,", + "\n FunctionalCurrency = x.FunctionalCurrency,", + "\n ValuationApproach = x.ValuationApproach,", + "\n LiabilityType = x.LiabilityType,", + "\n IsReinsurance = x.IsReinsurance,", + "\n IsOci = !string.IsNullOrWhiteSpace(x.OciType) },", + "\n x => x.ToDictionaryGrouped(y => y.EstimateType,", + "\n y => y.ToArray().ToDataCube()));", + "\n ", + "\n variablesDictionary.Add((period, rn, scenario), variablesByIdentity);", + "\n }", + "\n }", + "\n }", + "\n ", + "\n // Getters for Data", + "\n public IDataCube GetVariables(ReportIdentity reportIdentity, params string[] estimateTypes)", + "\n => (!variablesDictionary.TryGetValue(((reportIdentity.Year, reportIdentity.Month), reportIdentity.ReportingNode, reportIdentity.Scenario), out var variablesByIdentity) || !variablesByIdentity.TryGetValue(reportIdentity, out var variablesByEstimateType))", + "\n ? Enumerable.Empty().ToDataCube()", + "\n : estimateTypes.Length switch {", + "\n 0 => variablesByEstimateType.SelectMany(x => x.Value).ToDataCube(),", + "\n 1 => variablesByEstimateType.TryGetValue(estimateTypes.First(), out var variables)", + "\n ? variables.ToDataCube()", + "\n : Enumerable.Empty().ToDataCube(),", + "\n _ => estimateTypes.Select(et => variablesByEstimateType.TryGetValue(et, out var variables)", + "\n ? variables.ToDataCube()", + "\n : Enumerable.Empty())", + "\n .Aggregate((x, y) => x.Concat(y))", + "\n .ToDataCube()", + "\n };", + "\n ", + "\n // Other getters", + "\n public IWorkspace Workspace => workspace;", + "\n public Systemorph.Vertex.Pivot.Reporting.IReportFactory Report => reportFactory;", + "\n", + "\n public Systemorph.Vertex.Hierarchies.IHierarchy GetHierarchy() where T : class, IHierarchicalDimension => hierarchicalDimensionCache.Get();", + "\n ", + "\n public HashSet<(ReportIdentity, CurrencyType)> GetIdentities((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType)", + "\n => GetLeaves(reportingNode)", + "\n .SelectMany(rn => variablesDictionary.TryGetValue((period, rn, scenario), out var inner) ? inner.Keys.Select(x => (x, currencyType)) : Enumerable.Empty<(ReportIdentity, CurrencyType)>())", + "\n .ToHashSet();", + "\n ", + "\n public double GetFx((int year, int month) period, string currentCurrency, string targetCurrency, FxPeriod fxPeriod) {", + "\n if (currentCurrency == targetCurrency) return 1;", + "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType))", + "\n throw new Exception ($\"No exchange rates for Period {period} were found.\");", + "\n return GetCurrencyToGroupFx(exchangeRatesByCurrencyByFxType, currentCurrency, fxPeriod, GroupCurrency)", + "\n / GetCurrencyToGroupFx(exchangeRatesByCurrencyByFxType, targetCurrency, fxPeriod, GroupCurrency);", + "\n }", + "\n ", + "\n public FxPeriod GetFxPeriod((int year, int month) period, string aocType, string novelty) => fxPeriodsByAocStepAndPeriod[period][new AocStep(aocType, novelty)];", + "\n ", + "\n // Helpers", + "\n public HashSet GetLeaves(string systemName) where T : class, IHierarchicalDimension {", + "\n var descendants = hierarchicalDimensionCache.Get(systemName).Descendants(includeSelf: true);", + "\n return descendants.Where(x => !descendants.Select(y => y.Parent).Contains(x.SystemName)).Select(x => x.SystemName).ToHashSet();", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Gl9OQV-72kGG19Hx1igOHw", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Report/Reports.ipynb b/Report/Reports.ipynb new file mode 100644 index 00000000..99f0a490 --- /dev/null +++ b/Report/Reports.ipynb @@ -0,0 +1,516 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "1U3-hU_f80qwkFwNsbnfIQ", + "cell_type": "markdown", + "source": [ + "

Reports

", + "\n", + "\n" + ], + "metadata": {} + }, + { + "id": "me2hD-9UBkqUzPChAMdGSA", + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ], + "metadata": {} + }, + { + "id": "u0H8pAlgYkS1PDtJ2VPLCw", + "cell_type": "markdown", + "source": [ + "## Initialize data" + ], + "metadata": {} + }, + { + "id": "uGtbh5xjQkit56ozbyiS5g", + "cell_type": "code", + "source": [ + "/* DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"../Database/Configure\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TDC5BXyEaEeRJ3z9MmQClw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jZ-XCFkJ2kqGHwxkU5vMWA", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QyUqnd2bSkOLW_SKU1cJBw", + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ], + "metadata": {} + }, + { + "id": "I99Rcm-9LUmvvSjstjY9Hw", + "cell_type": "code", + "source": [ + "#!import \"ReportScopes\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LpptbT8Q_ESVOFAw3M1HQg", + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();", + "\nvar mostRecentPartition = (await Workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last();", + "\nvar reportingNodeRoot = (await Workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName;", + "\nawait reportStorage.InitializeAsync((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);", + "\nvar identities = reportStorage.GetIdentities((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "COjZVjOdgkSk8q3E6JHEgg", + "cell_type": "markdown", + "source": [ + "## Calling Scope" + ], + "metadata": {} + }, + { + "id": "SMyYdCikXUua1hdjbI4OmA", + "cell_type": "code", + "source": [ + "var universe = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "538kYx9ba0GWU4_h7XqOqA", + "cell_type": "markdown", + "source": [ + "# Report Settings and Storage Update" + ], + "metadata": {} + }, + { + "id": "UuYESB0ub0-pmUPR8T6jIQ", + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", + "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n //((2021, 12), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", + "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", + "\n ;", + "\n", + "\nawait reportStorage.InitializeAsync(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);", + "\nidentities = reportStorage.GetIdentities(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "spXqsA5i2k-QnXdIiPiN8g", + "cell_type": "markdown", + "source": [ + "# Present Value" + ], + "metadata": {} + }, + { + "id": "D2Y8VUl5EkSZ6EaxxjHxQw", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedBestEstimate + universe.GetScopes(identities).Aggregate().CurrentBestEstimate)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IB3NvnT2k0uFqLZP9EBMAw", + "cell_type": "markdown", + "source": [ + "# Risk Adjustment" + ], + "metadata": {} + }, + { + "id": "Vx4bYAkCsE2OfLFbPg380w", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedRiskAdjustment + universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"EconomicBasis\", \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ncU2iZ7tvEy2fxjWmU3Iqg", + "cell_type": "markdown", + "source": [ + "# Actuals" + ], + "metadata": {} + }, + { + "id": "lUNkYQ-KvUqVSA4cxDP-cg", + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Written", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"AmountType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 450)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5p79FR5-wUKCtkk4E1UKsQ", + "cell_type": "markdown", + "source": [ + "## Advance, Overdue Actuals" + ], + "metadata": {} + }, + { + "id": "9xxC0nELUk6ZaH6064_mqw", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Advance + universe.GetScopes(identities).Aggregate().Overdue)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions(reportHeight: 400)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5wuvd2c6O02jxhFkFp49GA", + "cell_type": "markdown", + "source": [ + "## Deferrable Actuals" + ], + "metadata": {} + }, + { + "id": "FlZFgvuEikyv4qcH6xvZYw", + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Deferrals", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 400)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MAO2KskzTEeZSNhRJLd0Zg", + "cell_type": "markdown", + "source": [ + "# Fulfilment Cashflow" + ], + "metadata": {} + }, + { + "id": "yQAAlgUfUkuF5u60nLLPcw", + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Fcf ", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")//, \"EstimateType\")//, \"AmountType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uF8DY0mc7UqiiYqQ6l6uxQ", + "cell_type": "markdown", + "source": [ + "# Actuarial Experience Adjustment" + ], + "metadata": {} + }, + { + "id": "HhH_UKImy0CsdcsI6-f6NA", + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().ActuarialExperienceAdjustment", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"AmountType\" )//\"LiabilityType\", \"EstimateType\")", + "\n .ReportGridOptions(reportHeight: 300, headerColumnWidth: 300)", + "\n .ToReport() " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4P1Lq_n2rkC67MsvbYyLeg", + "cell_type": "markdown", + "source": [ + "# LRC Technical Margin" + ], + "metadata": {} + }, + { + "id": "2qHsCZAs806CvGJgBNEVVQ", + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().LrcTechnicalMargin", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 600)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3F3PhlQxqkWBa0AnU5W6mA", + "cell_type": "markdown", + "source": [ + "# Contractual Service Margin / Loss Component / Loss Recovery Component" + ], + "metadata": {} + }, + { + "id": "gs0gMZiNAk2Jx8IKLuVcvA", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Csm + universe.GetScopes(identities).Aggregate().Lc + universe.GetScopes(identities).Aggregate().Loreco)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "39j6UxhSA0uSJNFLzSMRYg", + "cell_type": "markdown", + "source": [ + "# LRC Actuarial" + ], + "metadata": {} + }, + { + "id": "4kG8l2FHpkCjcnv-q5Rwkw", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LrcActuarial)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"LiabilityType\",\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Igfu5McpcUa4ORph4McI6g", + "cell_type": "markdown", + "source": [ + "# LRC" + ], + "metadata": {} + }, + { + "id": "jQtxFjgD9U2imsZ5CiVx2g", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lrc)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType),\"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions(300)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dZ8KVTA4WkuJZdxC09iuiQ", + "cell_type": "markdown", + "source": [ + "# LIC Actuarial" + ], + "metadata": {} + }, + { + "id": "CAXoAvfKdk6VKSgwRZplgA", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LicActuarial)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q1RxJxSTCk2zVjInVNdAzg", + "cell_type": "markdown", + "source": [ + "# LIC" + ], + "metadata": {} + }, + { + "id": "rc1o2W9lvUOBLnbn-MxRRw", + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lic)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions(300)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dI-BtkhyEkOSQkwJRxs0dQ", + "cell_type": "markdown", + "source": [ + "# Financial Performance" + ], + "metadata": {} + }, + { + "id": "e7jpS8lNhE2913hj-FXjxw", + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().FinancialPerformance", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CIY_4o8vO0KJafPttQEQcA", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/AocStructureTest.ipynb b/Test/AocStructureTest.ipynb new file mode 100644 index 00000000..b2411ca2 --- /dev/null +++ b/Test/AocStructureTest.ipynb @@ -0,0 +1,704 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "htuauFORRUW_vpe-m5qdCw", + "cell_type": "markdown", + "source": [ + "

Test Aoc Management

" + ], + "metadata": {} + }, + { + "id": "PeSv4LBGr0qLd08ewzJ6WA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6hiubyTezEuZjfp-gctWmw", + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ], + "metadata": {} + }, + { + "id": "54oSWDPLHEuTAVk-tNUBfA", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "JNf9Tz4s4UG65OvUoirk8Q", + "cell_type": "markdown", + "source": [ + "# Test" + ], + "metadata": {} + }, + { + "id": "LYX1kYxLHEyxrah6NZumRA", + "cell_type": "code", + "source": [ + "var args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", + "\nvar partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MfcAgK-1_ECiXK9qP48R_Q", + "cell_type": "code", + "source": [ + "public async Task CheckAocStepStructureAsync(IEnumerable inputVariables, ", + "\n Dictionary> parentBm, ", + "\n Dictionary referenceBm, ", + "\n Dictionary> fullAocBm,", + "\n Dictionary> parentBmCdr = null)", + "\n{", + "\n //Save test input data", + "\n var importFormat = ImportFormats.Cashflow;", + "\n var inputSource = InputSource.Cashflow;", + "\n if (inputVariables.First() is RawVariable)", + "\n {", + "\n await Workspace.UpdateAsync(inputVariables.Cast());", + "\n }", + "\n if (inputVariables.First() is IfrsVariable)", + "\n {", + "\n await Workspace.UpdateAsync(inputVariables.Cast());", + "\n importFormat = ImportFormats.Actual;", + "\n inputSource = InputSource.Actual;", + "\n }", + "\n ", + "\n var newArgs = args with {ImportFormat = importFormat };", + "\n //Set up import storage and test universe", + "\n var testStorage = new ImportStorage(newArgs, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n var isReinsurance = testStorage.DataNodeDataBySystemName[inputVariables.First().DataNode].IsReinsurance;", + "\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();", + "\n //Clean up Workspace", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", + "\n ", + "\n var errors = new List();", + "\n ", + "\n var goc = inputVariables.First().DataNode;", + "\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == goc)).SelectMany(s => s.Identities);", + "\n ", + "\n //Assert Parents", + "\n if (importFormat != ImportFormats.Actual)", + "\n {", + "\n var parents = testUniverse.GetScopes(identities.Select(id => (object)(id, \"PR\")), o => o.WithStorage(testStorage)).Where(x => x.Values != Enumerable.Empty()).ToArray();", + "\n if (parentBm.Count() != parents.Count()) ", + "\n {", + "\n var computedIds = parents.Select(s => $\"AocType:{s.Identity.Id.AocType}, Novelty:{s.Identity.Id.Novelty}\");", + "\n var expectedIds = parentBm.Keys.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n errors.Add( $\"Parent count does not match expected: \\n Computed {parents.Count()} \\n {string.Join(\"\\n\", computedIds)} \\n Expected {parentBm.Count()} \\n {string.Join(\"\\n\", expectedIds)}.\" );", + "\n }", + "\n ", + "\n foreach(var kvp in parentBm)", + "\n {", + "\n var scopeParents = parents.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", + "\n if(scopeParents.Count() != 1)", + "\n errors.Add( $\"Parent not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", + "\n else{", + "\n var scopeParent = scopeParents.First();", + "\n if( kvp.Value.Intersect(scopeParent.Values).Count() != kvp.Value.Count() ||", + "\n kvp.Value.Intersect(scopeParent.Values).Count() != scopeParent.Values.Count()){", + "\n var computedAocSteps = scopeParent.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", + "\n errors.Add( $\"Parents of {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed: \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", + "\n }", + "\n }", + "\n }", + "\n ", + "\n //Parents for CDR", + "\n if(isReinsurance)", + "\n {", + "\n var parentsCdr = testUniverse.GetScopes(identities.Select(id => (object)(id, AmountTypes.CDR)), o => o.WithStorage(testStorage));", + "\n ", + "\n var countP = parentsCdr.Where(x => x.Values != Enumerable.Empty()).Count();", + "\n if (parentBmCdr.Count() != countP) ", + "\n errors.Add( $\"Parent count for AmountType CDR does not match expected: \\n Computed {countP} \\n Expected {parentBm.Count()}.\" );", + "\n ", + "\n foreach(var kvp in parentBmCdr)", + "\n {", + "\n var scopeParents = parentsCdr.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", + "\n if(scopeParents.Count() != 1)", + "\n errors.Add( $\"Parent for CDR not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", + "\n else{", + "\n var scopeParent = scopeParents.First();", + "\n if( kvp.Value.Intersect(scopeParent.Values).Count() != kvp.Value.Count() || ", + "\n kvp.Value.Intersect(scopeParent.Values).Count() != scopeParent.Values.Count() ){", + "\n var computedAocSteps = scopeParent.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", + "\n errors.Add( $\"Parents of {kvp.Key.AocType}, {kvp.Key.Novelty} for AmountType CDR do not match expected value: \\n Computed: \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", + "\n }", + "\n }", + "\n } ", + "\n }", + "\n }", + "\n ", + "\n //Assert Reference", + "\n if (importFormat != ImportFormats.Actual)", + "\n {", + "\n var reference = testUniverse.GetScopes(identities, o => o.WithStorage(testStorage)).ToArray();", + "\n var countR = reference.Select(x => x.Value).Count();", + "\n if (referenceBm.Count() != countR) ", + "\n errors.Add( $\"Reference count does not match expected: \\n Computed {countR} \\n Expected {referenceBm.Count()}.\" );", + "\n ", + "\n foreach(var kvp in referenceBm)", + "\n {", + "\n var scopeReferences = reference.Where(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", + "\n if(scopeReferences.Count() != 1)", + "\n errors.Add( $\"Reference not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", + "\n else{", + "\n var scopeReference = scopeReferences.First();", + "\n if( kvp.Value.AocType != scopeReference.Value.AocType || kvp.Value.Novelty != scopeReference.Value.Novelty )", + "\n errors.Add( $\"Reference of {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed {scopeReference.Value} \\n Expected {kvp.Value}.\" );", + "\n }", + "\n }", + "\n }", + "\n ", + "\n //Assert FullAoc", + "\n var fullAoc = testUniverse.GetScopes(identities.Select(id => (object)(id, inputSource)), o => o.WithStorage(testStorage)).Where(s => s.Values.Any());", + "\n var count = fullAoc.Count();", + "\n if (fullAocBm.Count() != count)", + "\n {", + "\n var computedAocSteps = fullAoc.Select(x => $\"AocType:{x.Identity.Id.AocType}, Novelty:{x.Identity.Id.Novelty}\");", + "\n var benchmarkKeys = fullAocBm.Keys.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n errors.Add( $\"Full Aoc count does not match expected: \\n Computed {count} \\n Expected {fullAocBm.Count()}.\" ); ", + "\n errors.Add( $\"In particular, \\n Computed Identities \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected \\n {string.Join(\"\\n\", benchmarkKeys)}.\" ); ", + "\n }", + "\n ", + "\n foreach(var kvp in fullAocBm)", + "\n {", + "\n var scopeAocFulls = fullAoc.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", + "\n if(scopeAocFulls.Count() != 1){", + "\n errors.Add( $\"Full AocStep not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");}", + "\n else{", + "\n var scopeAocFull = scopeAocFulls.First();", + "\n if( kvp.Value.Intersect(scopeAocFull.Values).Count() != kvp.Value.Count() || ", + "\n kvp.Value.Intersect(scopeAocFull.Values).Count() != scopeAocFull.Values.Count() ){", + "\n var computedAocSteps = scopeAocFull.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", + "\n errors.Add( $\"AocFull for {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", + "\n }", + "\n }", + "\n }", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}", + "\n" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sEcSO-bqzkGlpQkC24-htw", + "cell_type": "markdown", + "source": [ + "# Use Cases" + ], + "metadata": {} + }, + { + "id": "sFPFk32D7kKGHRGhl37IyA", + "cell_type": "markdown", + "source": [ + "## Gross Cashflow: InForce, NewBusiness, and Combined" + ], + "metadata": {} + }, + { + "id": "_X2FswBBHkucp_w7bEqyxQ", + "cell_type": "code", + "source": [ + "var groupOfContract = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6ZmdltQ8CUOJk6c8XSMxMg", + "cell_type": "code", + "source": [ + "var inputRawVariables = new RawVariable[]{", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "EMS3W2YP1EqkmV577yS3hg", + "cell_type": "code", + "source": [ + "var parentBm = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cgrcf9GgL0qpSZnalLTzEw", + "cell_type": "code", + "source": [ + "var referenceBm = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"BOP\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep(\"EV\",\"N\")},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Wpd4fY5nQkmaPPkyvSEzSQ", + "cell_type": "code", + "source": [ + "var fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"IA\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n //{new AocStep(\"BOP\",\"N\"), Enumerable.Empty()},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\")}},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\")}},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"),", + "\n }},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), ", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", + "\n ", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oYv6SIpvrU6FXuQerivFwg", + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zbuVbeynlkiuaJciPMHc-A", + "cell_type": "markdown", + "source": [ + "## Reinsurance Cashflow: InForce, NewBusiness, and Combined" + ], + "metadata": {} + }, + { + "id": "lEAJ2MIIVkKmGnzEBLjE5g", + "cell_type": "code", + "source": [ + "groupOfContract = \"DTR1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jeehsZ9rD0uLhdYDkJo9sQ", + "cell_type": "code", + "source": [ + "inputRawVariables = new RawVariable[]{", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2Oou9pdvEU65Hdaz4jGLnw", + "cell_type": "code", + "source": [ + "parentBm = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}}, ", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fd9Sd0Ya9kSZbiDpI3tpJw", + "cell_type": "code", + "source": [ + "var parentBm_CDR = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}}, ", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"CRU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "naCBsHzkPk60cOaBsv40Fg", + "cell_type": "code", + "source": [ + "referenceBm = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"RCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"BOP\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep(\"EV\",\"N\")},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "A_BMNMYCE0irAqOEzK1Beg", + "cell_type": "code", + "source": [ + "fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"RCU\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"IA\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n //{new AocStep(\"BOP\",\"N\"), Enumerable.Empty()},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\")}},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\")}},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"),", + "\n }},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", + "\n ", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ThWShXVvcUeceCGqOsJthQ", + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm, parentBm_CDR)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8u10a9u8l0yb0XI7eilD8A", + "cell_type": "markdown", + "source": [ + "## Cashflow: InForce, and Combined" + ], + "metadata": {} + }, + { + "id": "BCk5iXiD6UiLl7KNQkQ1-Q", + "cell_type": "code", + "source": [ + "var groupOfContract = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_XL2aS8gh02VveW4LpykZQ", + "cell_type": "code", + "source": [ + "inputRawVariables = new RawVariable[]{", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Qd3QDM8xY0WrVZsN4inIDg", + "cell_type": "code", + "source": [ + "parentBm = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lf7sWYGVQEijVikbiCG9oQ", + "cell_type": "code", + "source": [ + "referenceBm = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "B6t0lIf3ik-YHWgWpyX0YQ", + "cell_type": "code", + "source": [ + "fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\")}},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"), ", + "\n }},", + "\n ", + "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"CL\",\"C\"),}},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"CL\",\"C\"), new AocStep(\"EA\",\"C\"),}},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"CL\",\"C\"), new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"),}},", + "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qceSk87wOEOmawmXy5Vdag", + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lo7SItfxOEOhFjgPs9KTHQ", + "cell_type": "markdown", + "source": [ + "## Actual" + ], + "metadata": {} + }, + { + "id": "LLQgmrk5cUamp-TV5Bw0MA", + "cell_type": "code", + "source": [ + "var groupOfContract = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HHKnGuczVE-EGxdD1vi1JQ", + "cell_type": "code", + "source": [ + "var inputIfrsVariables = new IfrsVariable[]{", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"AA\"},", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"CF\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"AA\"},", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"CF\", Novelty = \"C\", AccidentYear = null, AmountType = \"ACA\", EstimateType = \"A\"},", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"WO\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"OA\"},", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yv06kc8H40iji3wgMDEmEg", + "cell_type": "code", + "source": [ + "parentBm = null;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "E62fDv7kNkeH__lCPrFn8g", + "cell_type": "code", + "source": [ + "referenceBm = null;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xNjIoqwi4kqov8CpJoZu5A", + "cell_type": "code", + "source": [ + "fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"),}},", + "\n {new AocStep(\"WO\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"),}},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"), new AocStep(\"WO\",\"C\"),}},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"), new AocStep(\"WO\",\"C\"), new AocStep(\"AM\",\"C\"),}},", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cokUNY_q6Eai_BLP8RbvEA", + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputIfrsVariables, parentBm, referenceBm, fullAocBm)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QwRsslb8LE-OzVKMQJyfJQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/Data/CashflowComplex.csv b/Test/Data/CashflowComplex.csv new file mode 100644 index 00000000..150c4a31 --- /dev/null +++ b/Test/Data/CashflowComplex.csv @@ -0,0 +1,9 @@ +@@Main,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +ReportingNode,Year,Month,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +CH,2021,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +@@Cashflow,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,, +DataNode,AmountType,AocType,Novelty,AccidentYear,Values0,Values1,Values2,Values3,Values4,Values5,Values6,Values7,Values8,Values9,Values10,Values11,Values12,Values13,Values14,Values15,Values16,Values17,Values18,Values19,Values20,Values21,Values22,Values23,Values24,Values25,Values26,Values27,Values28,Values29,Values30,Values31,Values32,Values33,Values34,Values35,Values36,Values37,Values38,Values39,Values40,Values41,Values42,Values43,Values44,Values45,Values46,Values47,Values48,Values49,Values50,Values51,Values52,Values53,Values54,Values55,Values56,Values57,Values58,Values59,Values60,Values61,Values62,Values63,Values64,Values65,Values66,Values67,Values68,Values69,Values70,Values71,Values72,Values73,Values74,Values75,Values76,Values77,Values78,Values79,Values80,Values81,Values82,Values83,Values84,Values85,Values86,Values87,Values88,Values89,Values90,Values91,Values92,Values93,Values94,Values95,Values96,Values97,Values98,Values99,Values100,Values101,Values102,Values103,Values104,Values105,Values106,Values107,Values108,Values109,Values110,Values111,Values112,Values113,Values114,Values115,Values116,Values117,Values118,Values119,Values120,Values121,Values122,Values123,Values124,Values125,Values126,Values127,Values128,Values129,Values130,Values131,Values132,Values133,Values134,Values135,Values136,Values137,Values138,Values139,Values140,Values141,Values142,Values143,Values144,Values145,Values146,Values147,Values148,Values149,Values150,Values151,Values152,Values153,Values154,Values155,Values156,Values157,Values158,Values159,Values160,Values161,Values162,Values163,Values164,Values165,Values166,Values167,Values168,Values169,Values170,Values171,Values172,Values173,Values174,Values175,Values176,Values177,Values178,Values179,Values180,Values181,Values182,Values183,Values184,Values185,Values186,Values187,Values188,Values189,Values190,Values191,Values192,Values193,Values194,Values195,Values196,Values197,Values198,Values199,Values200,Values201,Values202,Values203,Values204,Values205,Values206,Values207,Values208,Values209,Values210,Values211,Values212,Values213,Values214,Values215,Values216,Values217,Values218,Values219,Values220,Values221,Values222,Values223,Values224,Values225,Values226,Values227,Values228,Values229,Values230,Values231,Values232,Values233,Values234,Values235,Values236,Values237,Values238,Values239,Values240,Values241,Values242,Values243,Values244,Values245,Values246,Values247,Values248,Values249,Values250,Values251,Values252,Values253,Values254,Values255,Values256,Values257,Values258,Values259,Values260,Values261,Values262,Values263,Values264,Values265,Values266,Values267,Values268,Values269,Values270,Values271,Values272,Values273,Values274,Values275,Values276,Values277,Values278,Values279,Values280,Values281,Values282,Values283,Values284,Values285,Values286,Values287,Values288,Values289,Values290,Values291,Values292,Values293,Values294,Values295,Values296,Values297,Values298,Values299,Values300,Values301,Values302,Values303,Values304,Values305,Values306,Values307,Values308,Values309,Values310,Values311,Values312,Values313,Values314,Values315,Values316,Values317,Values318,Values319,Values320,Values321,Values322,Values323,Values324,Values325,Values326,Values327,Values328,Values329,Values330,Values331,Values332,Values333,Values334,Values335,Values336,Values337,Values338,Values339,Values340,Values341,Values342,Values343,Values344,Values345,Values346,Values347,Values348,Values349,Values350,Values351,Values352,Values353,Values354,Values355,Values356,Values357,Values358,Values359,Values360,Values361,Values362,Values363,Values364,Values365,Values366,Values367,Values368,Values369,Values370,Values371,Values372,Values373,Values374,Values375,Values376,Values377,Values378,Values379,Values380,Values381,Values382,Values383,Values384,Values385,Values386,Values387,Values388,Values389,Values390,Values391,Values392,Values393,Values394,Values395,Values396,Values397,Values398,Values399,Values400,Values401,Values402,Values403,Values404,Values405,Values406,Values407,Values408,Values409,Values410,Values411,Values412,Values413,Values414,Values415,Values416,Values417,Values418,Values419,Values420,Values421,Values422,Values423,Values424,Values425,Values426,Values427,Values428,Values429,Values430,Values431,Values432,Values433,Values434,Values435,Values436,Values437,Values438,Values439,Values440,Values441,Values442,Values443,Values444,Values445,Values446,Values447,Values448,Values449,Values450,Values451,Values452,Values453,Values454,Values455,Values456,Values457,Values458,Values459,Values460,Values461,Values462,Values463,Values464,Values465,Values466,Values467,Values468,Values469,Values470,Values471,Values472,Values473,Values474,Values475,Values476,Values477,Values478,Values479,Values480,Values481,Values482,Values483,Values484,Values485,Values486,Values487,Values488,Values489,Values490,Values491,Values492,Values493,Values494,Values495,Values496,Values497,Values498,Values499,Values500,Values501,Values502,Values503,Values504,Values505,Values506,Values507,Values508,Values509,Values510,Values511,Values512,Values513,Values514,Values515,Values516,Values517,Values518,Values519,Values520,Values521,Values522,Values523,Values524,Values525,Values526,Values527,Values528,Values529,Values530,Values531,Values532,Values533,Values534,Values535,Values536,Values537,Values538,Values539,Values540,Values541,Values542,Values543,Values544,Values545,Values546,Values547,Values548,Values549,Values550,Values551,Values552,Values553,Values554,Values555,Values556,Values557,Values558,Values559,Values560,Values561,Values562,Values563,Values564,Values565,Values566,Values567,Values568,Values569,Values570,Values571,Values572,Values573,Values574,Values575,Values576,Values577,Values578,Values579,Values580,Values581,Values582,Values583,Values584,Values585,Values586,Values587,Values588,Values589,Values590,Values591,Values592,Values593,Values594,Values595,Values596,Values597,Values598,Values599,Values600,Values601,Values602,Values603,Values604,Values605,Values606,Values607,Values608,Values609,Values610,Values611,Values612,Values613,Values614,Values615,Values616,Values617,Values618,Values619,Values620,Values621,Values622,Values623,Values624,Values625,Values626,Values627,Values628,Values629,Values630,Values631,Values632,Values633,Values634,Values635,Values636,Values637,Values638,Values639,Values640,Values641,Values642,Values643,Values644,Values645,Values646,Values647,Values648,Values649,Values650,Values651,Values652,Values653,Values654,Values655,Values656,Values657,Values658,Values659,Values660,Values661,Values662,Values663,Values664,Values665,Values666,Values667,Values668,Values669,Values670,Values671,Values672,Values673,Values674,Values675,Values676,Values677,Values678,Values679,Values680,Values681,Values682,Values683,Values684,Values685,Values686,Values687,Values688,Values689,Values690,Values691,Values692,Values693,Values694,Values695,Values696,Values697,Values698,Values699,Values700,Values701,Values702,Values703,Values704,Values705,Values706,Values707,Values708,Values709,Values710 +GricComplex,PR,CL,C,,2535,2529.591892,2500.971466,2430.585538,2407.863515,2388.488278,2368.366653,2339.830977,2320.140291,2273.265222,2260.159425,2238.704077,2196.317904,2183.379553,2150.583114,2081.624057,2054.038174,2029.380502,2004.867,1973.795957,1951.298307,1906.807541,1891.795768,1871.415088,1834.717693,1824.096114,1798.843011,1746.456017,1728.414842,1712.811725,1696.919127,1675.202665,1660.273625,1626.338933,1617.051755,1602.551809,1573.50648,1566.223126,1545.642015,1500.618943,1485.101264,1471.691271,1458.024238,1439.336088,1426.49893,1397.342507,1389.349718,1376.874475,1351.917587,1345.631534,1327.947885,1289.256361,1275.909196,1264.385251,1252.632234,1236.549581,1225.511406,1200.462439,1193.584031,1182.850738,1161.408247,1155.981809,1140.790031,1107.541577,1096.061618,1086.15935,1076.052965,1062.2116,1052.720985,1031.202771,1025.283378,1016.04856,997.627389,992.941506,979.891922,951.322487,941.448188,932.939999,924.249948,912.335664,904.175567,885.693476,880.598899,872.653466,856.829492,852.780943,841.573815,817.027071,808.533905,801.224309,793.752395,783.496234,776.480692,760.608477,756.223418,749.387426,735.795916,732.295962,722.67351,701.585003,694.279654,687.487246,680.310694,671.245483,665.234157,650.624971,646.397834,640.31947,628.457131,624.279582,613.950308,595.920763,589.722054,584.413043,578.971894,571.235961,566.135054,554.303845,550.929183,545.954891,536.01646,533.082302,525.872489,510.402366,505.085981,500.542004,495.878976,489.420143,485.047928,475.084784,472.137592,467.536806,459.019242,456.837145,450.500103,437.226131,432.664523,428.773768,424.77577,418.758891,415.479018,406.937395,404.160412,400.789774,393.334791,390.583535,385.733524,374.347985,370.021735,367.106731,363.680719,358.247179,355.176172,347.862729,345.225915,342.204272,335.571645,333.598321,329.333118,319.580314,315.883566,313.39974,310.356707,305.93402,303.428411,297.054395,294.688864,292.127447,286.680988,284.243411,279.403322,271.073443,267.937598,265.843591,263.369511,259.501629,257.382104,251.95089,250.074808,247.62104,242.893904,241.278094,238.096766,230.968585,228.294465,226.515106,224.40864,221.099932,218.874233,214.239531,212.3946,210.381112,206.346581,204.908511,201.969429,195.882317,193.613658,192.113106,190.330955,187.02216,185.69914,181.53645,180.261133,178.547194,174.840502,172.671425,170.305844,165.12151,163.209808,161.827249,160.272358,157.526774,156.424373,153.136609,151.828351,150.20211,147.296501,145.8847,143.987564,139.567059,137.950795,136.733595,135.31309,132.667487,131.690934,128.524939,127.489555,125.899557,123.042852,121.573681,119.597167,115.856644,114.51792,113.568523,112.442615,110.485137,109.739054,107.254266,106.355763,105.175668,103.109102,101.916002,100.383355,97.204395,96.081872,95.334515,94.391918,92.087043,91.843203,89.705346,88.926952,88.088462,86.076229,85.170848,83.91389,81.216869,80.279748,79.599023,78.850524,76.969043,76.74736,74.811335,74.09963,73.436294,71.777863,71.064435,69.729808,67.447501,66.670563,66.171247,65.55432,64.079762,64.002865,62.418998,61.860578,61.085223,59.525951,58.938565,58.147296,56.213338,55.566483,55.155117,54.520921,53.052354,52.8323,51.312151,50.641714,49.564211,48.413012,47.575887,46.603098,44.923331,44.339567,44.120779,43.637844,42.567534,42.510234,41.348922,40.937179,40.323123,39.644633,39.254046,38.61007,37.189927,36.705286,36.589741,36.228865,35.381056,35.30749,34.400439,34.088652,33.639242,32.858583,32.597263,31.814357,30.616207,30.216112,30.083814,29.659393,29.006568,28.838553,28.123609,27.82572,27.505515,26.881867,26.514412,26.016861,25.155379,24.783384,24.724873,24.375525,23.809376,23.694684,23.0923,22.814353,22.446277,21.87896,21.665012,21.052249,20.330607,20.001897,19.806058,19.270405,18.776857,18.402442,17.600043,16.98997,16.349945,15.585697,15.296223,14.332207,13.910344,13.730037,13.618621,13.315707,13.062009,13.074016,12.610448,12.450154,12.180972,11.861997,11.66443,11.472037,11.120686,10.976256,10.907613,10.656991,10.477164,10.488239,10.115394,9.989199,9.785769,9.525763,9.404736,9.245715,8.952039,8.835588,8.779592,8.564791,8.433803,8.471712,8.150164,8.074549,7.897652,7.659182,7.527585,7.370979,7.126355,7.033467,6.97567,6.812404,6.710878,6.724247,6.448918,6.383495,6.247768,6.021226,5.894113,5.830816,5.627456,5.553957,5.509868,5.370177,5.277645,5.283421,5.043569,4.992218,4.886959,4.714544,4.570135,4.467831,4.300496,4.244234,4.218879,4.09173,4.004928,4.040279,3.858655,3.781702,3.749967,3.612046,3.489492,3.438379,3.300169,3.256925,3.231102,3.144557,3.083374,3.10631,2.971356,2.900361,2.858999,2.728992,2.658252,2.605795,2.491918,2.459196,2.434088,2.360742,2.319218,2.335527,2.217669,2.162964,2.131048,2.040739,1.939135,1.927354,1.833922,1.809807,1.810205,1.750119,1.709149,1.723628,1.608383,1.54343,1.513679,1.446362,1.387593,1.363856,1.287713,1.268321,1.253607,1.224893,1.206252,1.232444,1.14952,1.114651,1.094043,1.055615,1.000988,0.966047,0.90364,0.891716,0.881553,0.861573,0.841638,0.853611,0.785267,0.759584,0.73874,0.718652,0.682821,0.676818,0.642906,0.634406,0.626018,0.613798,0.603837,0.61164,0.569702,0.556739,0.543796,0.527619,0.499177,0.476766,0.4491,0.443143,0.435551,0.42298,0.412787,0.42408,0.392718,0.381038,0.364958,0.33691,0.309739,0.305352,0.283063,0.279303,0.274289,0.26919,0.262734,0.274897,0.251743,0.246111,0.237415,0.229053,0.214244,0.206365,0.195721,0.193113,0.19054,0.186816,0.184327,0.188109,0.170697,0.161307,0.155606,0.144367,0.136746,0.127205,0.118752,0.117156,0.115582,0.113181,0.110597,0.114376,0.102565,9.707382,9.182816,8.869774,8.168963,7.884605,7.201829,7.104195,7.007888,6.912886,6.727616,7.175704,6.456904,6.369242,6.112679,5.856798,5.529753,5.257648,4.693818,4.629154,0.045653,4.432051,4.371011,4.771019,4.251425,4.133046,4.010365,3.765305,3.553587,3.252025,3.207362,3.163315,3.050608,3.008676,2.967323,0.028673,2.827956,2.789061,2.750681,2.549613,2.51453,2.368616,2.33583,2.3035,2.271619,2.240181,2.209179,2.178603,0.021119,2.082789,1.961219,1.847835,1.731422,1.615505,1.593216,1.571235,1.549559,1.528183,1.507103,1.48631,1.465801,1.414554,1.352859,1.334246,1.279065,1.183801,1.167469,1.151362,1.135478,1.119814,1.104366,1.089128,1.074097,1.059257,9.760279,9.625791,8.918206,7.073597,6.97569,6.87914,6.783928,6.690036,6.270355,6.183604,6.098022,6.0135,5.93012,5.539274,4.289967,3.9598,3.904416,3.849807,3.795962,3.742871,3.690523,3.638907,3.587987,3.266077,3.220245,3.175056,3.130471,2.825156,2.785268,2.745943,2.707174,2.668953,2.631272,2.594123,2.111307,2.081558,2.052229,2.023313,1.542083,1.323224,1.304528,1.286097,1.267927,1.250013,1.232353,1.214942,1.197747,1.180766,1.164026,1.147523,9.583019,9.447679,9.314252,9.182708,9.053023,8.925169,8.799121,8.674854,8.55194,8.430371,8.310531,8.192395,8.07572,7.960083,7.846102,7.733753,7.623013,7.513858,7.406267,7.300217,7.195393,7.091786,6.989671,6.889027,6.78962,6.691044,6.593899,6.498165,6.403821,6.310848,6.219224,6.12893,6.039656,5.951393,5.864421,5.778721,5.69399,5.609986,5.527223,5.44568,5.365341,5.286187,5.208201,4.133606,3.086537,3.041284,2.996695,2.95276,9.915302,9.770027 +GricComplex,NIC,CL,C,,33535.87259,34226.13899,35866.8437,35451.31356,35047.2134,34735.40594,34456.75704,34290.73436,34184.26867,34067.66181,33994.19262,33936.81916,33860.23049,33920.99342,34447.17073,33915.76595,33396.41408,32951.02441,32515.54295,32160.3836,31854.40643,31562.14214,31317.65217,31095.08164,30891.30473,30761.34018,30916.75429,30528.19887,30146.88478,29800.17738,29459.8904,29163.23988,28896.67459,28621.88906,28369.72013,28127.44566,27894.52205,27679.31593,27624.1548,27276.62774,26937.26122,26624.25065,26325.40601,26055.3607,25818.43841,25580.76237,25355.67277,25145.04585,24942.23209,24769.52397,24724.29188,24412.87144,24107.27116,23820.83727,23546.77522,23302.623,23091.58515,22872.75656,22675.67512,22489.47881,22302.92252,22149.52562,22106.50014,21827.77828,21554.12559,21302.92909,21055.59979,20842.8176,20659.53343,20465.65555,20279.55591,20109.01245,19941.65289,19791.90948,19753.28503,19503.97108,19259.59753,19042.15141,18826.21936,18632.40376,18457.89799,18291.10043,18136.50295,17986.12736,17841.87427,17727.47016,17690.69409,17467.10495,17247.85766,17047.24234,16851.69196,16673.37397,16523.58274,16368.79309,16228.6635,16096.61305,15965.2048,15853.77126,15813.40766,15613.25065,15418.04039,15237.28332,15067.06796,14909.10818,14768.29743,14614.78308,14479.09815,14356.39748,14217.62335,14103.06012,14021.76677,13844.26502,13670.43639,13511.50902,13356.7006,13209.84121,13087.7532,12946.23175,12826.76079,12718.33045,12586.42694,12487.13981,12415.53739,12258.22962,12104.29653,11962.02898,11826.69161,11702.41869,11591.32992,11480.98248,11364.62507,11258.96336,11162.58296,11066.01657,11020.3166,10880.47425,10743.60366,10615.7354,10494.77672,10373.85063,10272.08981,10167.1258,10075.84734,9976.617737,9873.784291,9793.452834,9738.535436,9614.811563,9493.715955,9382.712349,9274.120706,9168.392271,9074.563452,8983.408475,8890.638889,8802.914628,8712.391834,8645.726124,8604.581385,8495.071966,8388.406094,8286.821547,8189.952954,8099.64263,8017.649133,7929.116104,7845.784672,7758.150379,7673.791533,7593.141781,7510.084844,7414.380573,7320.724307,7234.631513,7148.337636,7069.788214,6992.803322,6924.043065,6852.525872,6758.490391,6683.379481,6624.230727,6579.863813,6495.901093,6413.806703,6337.205467,6264.267111,6186.39002,6100.370234,6037.623325,5964.328582,5898.777579,5833.708765,5778.623149,5728.834826,5655.631174,5584.076607,5513.152398,5445.663212,5377.151901,5314.735844,5248.599168,5179.96521,5121.775037,5058.276758,4988.743097,4918.971964,4855.969474,4794.410997,4737.409332,4675.744516,4619.399207,4558.72763,4512.149916,4448.987656,4388.083355,4342.966868,4293.099344,4252.139077,4197.590645,4144.629682,4086.409605,4031.800661,3969.929594,3911.509996,3851.614416,3806.620608,3742.262477,3684.059481,3632.872153,3592.936223,3546.782022,3501.720716,3457.274233,3412.905514,3368.660208,3324.01036,3284.486945,3231.366847,3186.241729,3149.002801,3110.773438,3074.784295,3035.213888,2996.699751,2960.901906,2918.577258,2874.197674,2829.695919,2789.890863,2752.980964,2714.702217,2670.822059,2639.805393,2597.739454,2564.243761,2531.670974,2497.48136,2468.053663,2426.584729,2391.711248,2351.881112,2313.196028,2286.160467,2253.866916,2226.436184,2184.120775,2155.907698,2128.51922,2100.795774,2073.148231,2048.385659,2025.0897,1995.021858,1966.142097,1930.739863,1893.495615,1874.22198,1853.132371,1829.1403,1805.929023,1783.971081,1757.858364,1727.577513,1703.181775,1672.825172,1639.266949,1601.521186,1571.858572,1534.683048,1505.050081,1485.623051,1466.682836,1446.644697,1427.94535,1406.641458,1380.213187,1358.234732,1335.820374,1316.060212,1300.382785,1277.871789,1254.12873,1237.883891,1222.070044,1207.890021,1192.094125,1176.797243,1158.235032,1141.262466,1124.673342,1108.547008,1089.592557,1069.433382,1046.398207,1032.81553,1019.603188,1003.756714,990.580559,975.374562,960.605272,943.730653,929.188024,916.631898,903.500041,888.276223,870.430324,859.148348,848.120185,837.186224,824.094522,812.208099,799.647175,787.628456,774.914754,757.705942,743.065376,731.779311,711.699468,702.45661,690.424631,678.580749,663.166238,648.618608,624.12076,603.565108,582.415702,559.277957,536.857092,520.484869,487.114615,480.778456,474.492534,467.261587,460.788758,452.467662,444.594102,437.455104,429.308789,421.390702,414.833113,408.435316,398.075146,392.88443,387.738115,382.52232,376.978509,369.09776,362.613226,354.1242,348.567925,343.38234,337.629242,331.182311,323.169908,318.947206,314.758993,310.803,306.10757,301.699621,297.798319,292.506665,287.051657,280.419845,274.590526,268.561197,260.363862,256.954353,253.571647,248.912245,245.972759,242.285135,237.854082,232.551795,227.333399,223.05758,217.063713,212.668939,206.22415,203.517097,200.82965,196.943179,193.159049,189.440226,185.240484,180.479086,177.397226,174.091408,170.434345,165.720877,158.087694,156.010706,153.946704,150.716587,147.17816,143.581596,141.471073,138.177806,135.060287,132.934619,129.859753,124.758217,119.040288,117.474331,115.916152,112.88817,111.446444,109.246746,106.67424,105.223314,102.406054,99.84368,96.512743,93.082381,87.401628,86.249419,85.102088,83.036783,81.908159,80.497321,78.817502,77.447286,75.581881,73.670299,71.123444,67.132175,64.043847,63.197561,62.352608,61.414085,60.151507,58.497989,56.533312,54.59964,52.108631,50.228226,48.816235,46.713061,44.472247,43.886278,43.299438,42.365887,41.664588,41.009714,40.185602,39.079098,38.209455,37.332986,36.278399,34.431733,31.318798,30.906184,30.499117,30.016918,29.413235,28.669802,27.495236,26.078926,25.109785,24.294291,23.732585,21.892021,20.914212,20.637655,20.364776,20.104216,19.730784,19.398678,18.821077,18.516932,18.272469,17.801747,17.412207,16.49007,14.133229,13.946084,13.761491,13.501017,13.048942,12.709121,12.403982,12.147019,11.744218,11.191513,10.354495,9.258459,8.690802,8.576092,8.46293,8.341174,8.162127,7.875185,7.677418,7.586228,7.439121,7.231159,7.009123,6.547528,5.653089,5.577711,5.503344,5.432088,5.274719,5.210844,5.048875,4.521423,4.149387,3.964219,3.670722,3.351165,2.692363,2.656459,2.621038,2.587918,2.533526,2.463246,2.414022,2.261357,2.095748,1.940548,1.821631,1.445258,1.186766,1.170793,1.15504,1.141303,1.127417,1.045521,1.033222,1.002319,0.991524,0.887035,0.830358,0.80995,0.680213,0.670895,0.661709,0.654246,0.628288,0.619713,0.61292,0.607171,0.588391,0.583136,0.563105,0.529856,0.479119,0.472379,0.465753,0.431571,0.425476,0.420386,0.394927,0.391603,0.388046,0.384942,0.34191,0.34595,0.325343,0.320682,0.316088,0.31156,0.307097,0.303571,0.29969,0.287254,0.284454,0.260042,0.240548,0.226147,0.209627,0.206612,0.203641,0.200713,0.197827,0.195702,0.193167,0.191584,0.180651,0.16699,0.164965,0.14469,0.135317,0.133384,0.131479,0.129602,0.127751,0.126552,0.125021,0.12449,0.123074,0.109451,0.108542,8.537432,7.357732,7.254752,7.153214,7.053098,0.069555,6.089561,0.060267,0.060421,5.98855,5.904967,5.482401,5.117382,5.078674,5.007237,4.936807,4.867367,4.798905,4.731406,0.046841,0.047027,4.140964,4.082453,4.038134,4.083926,3.896083,3.840664,3.786034,3.732181,3.679096,3.626766,3.596725,0.028608,2.820268,2.780233,2.753741,2.094079,1.680325,1.656335,1.632689,1.60938,1.586404,0.015637,0.015608,1.560503,1.538159,1.516135,1.506607,0.01074,1.058866,0.010438,1.029138,1.014589,1.000245,9.861044,9.951639,1.006313,9.919704,9.77832,9.186752,9.333788,9.199741,9.06762,8.937397,8.809044,8.682534,8.557841,8.618284,8.698998,8.573137,8.449098,8.423441,8.599279,8.47406,8.350664,8.229066,8.109238,7.991155,7.874793,7.917113,7.969885,7.852826,7.737487,7.714442,7.789579,7.674303,7.560733,7.448843,7.33861,7.230009,7.126934,5.441094,3.574384,3.521814,3.470017,3.509319,1.046458,1.031126 +GicComplex,PR,CL,C,,2535,2529.591892,2500.971466,2430.585538,2407.863515,2388.488278,2368.366653,2339.830977,2320.140291,2273.265222,2260.159425,2238.704077,2196.317904,2183.379553,2150.583114,2081.624057,2054.038174,2029.380502,2004.867,1973.795957,1951.298307,1906.807541,1891.795768,1871.415088,1834.717693,1824.096114,1798.843011,1746.456017,1728.414842,1712.811725,1696.919127,1675.202665,1660.273625,1626.338933,1617.051755,1602.551809,1573.50648,1566.223126,1545.642015,1500.618943,1485.101264,1471.691271,1458.024238,1439.336088,1426.49893,1397.342507,1389.349718,1376.874475,1351.917587,1345.631534,1327.947885,1289.256361,1275.909196,1264.385251,1252.632234,1236.549581,1225.511406,1200.462439,1193.584031,1182.850738,1161.408247,1155.981809,1140.790031,1107.541577,1096.061618,1086.15935,1076.052965,1062.2116,1052.720985,1031.202771,1025.283378,1016.04856,997.627389,992.941506,979.891922,951.322487,941.448188,932.939999,924.249948,912.335664,904.175567,885.693476,880.598899,872.653466,856.829492,852.780943,841.573815,817.027071,808.533905,801.224309,793.752395,783.496234,776.480692,760.608477,756.223418,749.387426,735.795916,732.295962,722.67351,701.585003,694.279654,687.487246,680.310694,671.245483,665.234157,650.624971,646.397834,640.31947,628.457131,624.279582,613.950308,595.920763,589.722054,584.413043,578.971894,571.235961,566.135054,554.303845,550.929183,545.954891,536.01646,533.082302,525.872489,510.402366,505.085981,500.542004,495.878976,489.420143,485.047928,475.084784,472.137592,467.536806,459.019242,456.837145,450.500103,437.226131,432.664523,428.773768,424.77577,418.758891,415.479018,406.937395,404.160412,400.789774,393.334791,390.583535,385.733524,374.347985,370.021735,367.106731,363.680719,358.247179,355.176172,347.862729,345.225915,342.204272,335.571645,333.598321,329.333118,319.580314,315.883566,313.39974,310.356707,305.93402,303.428411,297.054395,294.688864,292.127447,286.680988,284.243411,279.403322,271.073443,267.937598,265.843591,263.369511,259.501629,257.382104,251.95089,250.074808,247.62104,242.893904,241.278094,238.096766,230.968585,228.294465,226.515106,224.40864,221.099932,218.874233,214.239531,212.3946,210.381112,206.346581,204.908511,201.969429,195.882317,193.613658,192.113106,190.330955,187.02216,185.69914,181.53645,180.261133,178.547194,174.840502,172.671425,170.305844,165.12151,163.209808,161.827249,160.272358,157.526774,156.424373,153.136609,151.828351,150.20211,147.296501,145.8847,143.987564,139.567059,137.950795,136.733595,135.31309,132.667487,131.690934,128.524939,127.489555,125.899557,123.042852,121.573681,119.597167,115.856644,114.51792,113.568523,112.442615,110.485137,109.739054,107.254266,106.355763,105.175668,103.109102,101.916002,100.383355,97.204395,96.081872,95.334515,94.391918,92.087043,91.843203,89.705346,88.926952,88.088462,86.076229,85.170848,83.91389,81.216869,80.279748,79.599023,78.850524,76.969043,76.74736,74.811335,74.09963,73.436294,71.777863,71.064435,69.729808,67.447501,66.670563,66.171247,65.55432,64.079762,64.002865,62.418998,61.860578,61.085223,59.525951,58.938565,58.147296,56.213338,55.566483,55.155117,54.520921,53.052354,52.8323,51.312151,50.641714,49.564211,48.413012,47.575887,46.603098,44.923331,44.339567,44.120779,43.637844,42.567534,42.510234,41.348922,40.937179,40.323123,39.644633,39.254046,38.61007,37.189927,36.705286,36.589741,36.228865,35.381056,35.30749,34.400439,34.088652,33.639242,32.858583,32.597263,31.814357,30.616207,30.216112,30.083814,29.659393,29.006568,28.838553,28.123609,27.82572,27.505515,26.881867,26.514412,26.016861,25.155379,24.783384,24.724873,24.375525,23.809376,23.694684,23.0923,22.814353,22.446277,21.87896,21.665012,21.052249,20.330607,20.001897,19.806058,19.270405,18.776857,18.402442,17.600043,16.98997,16.349945,15.585697,15.296223,14.332207,13.910344,13.730037,13.618621,13.315707,13.062009,13.074016,12.610448,12.450154,12.180972,11.861997,11.66443,11.472037,11.120686,10.976256,10.907613,10.656991,10.477164,10.488239,10.115394,9.989199,9.785769,9.525763,9.404736,9.245715,8.952039,8.835588,8.779592,8.564791,8.433803,8.471712,8.150164,8.074549,7.897652,7.659182,7.527585,7.370979,7.126355,7.033467,6.97567,6.812404,6.710878,6.724247,6.448918,6.383495,6.247768,6.021226,5.894113,5.830816,5.627456,5.553957,5.509868,5.370177,5.277645,5.283421,5.043569,4.992218,4.886959,4.714544,4.570135,4.467831,4.300496,4.244234,4.218879,4.09173,4.004928,4.040279,3.858655,3.781702,3.749967,3.612046,3.489492,3.438379,3.300169,3.256925,3.231102,3.144557,3.083374,3.10631,2.971356,2.900361,2.858999,2.728992,2.658252,2.605795,2.491918,2.459196,2.434088,2.360742,2.319218,2.335527,2.217669,2.162964,2.131048,2.040739,1.939135,1.927354,1.833922,1.809807,1.810205,1.750119,1.709149,1.723628,1.608383,1.54343,1.513679,1.446362,1.387593,1.363856,1.287713,1.268321,1.253607,1.224893,1.206252,1.232444,1.14952,1.114651,1.094043,1.055615,1.000988,0.966047,0.90364,0.891716,0.881553,0.861573,0.841638,0.853611,0.785267,0.759584,0.73874,0.718652,0.682821,0.676818,0.642906,0.634406,0.626018,0.613798,0.603837,0.61164,0.569702,0.556739,0.543796,0.527619,0.499177,0.476766,0.4491,0.443143,0.435551,0.42298,0.412787,0.42408,0.392718,0.381038,0.364958,0.33691,0.309739,0.305352,0.283063,0.279303,0.274289,0.26919,0.262734,0.274897,0.251743,0.246111,0.237415,0.229053,0.214244,0.206365,0.195721,0.193113,0.19054,0.186816,0.184327,0.188109,0.170697,0.161307,0.155606,0.144367,0.136746,0.127205,0.118752,0.117156,0.115582,0.113181,0.110597,0.114376,0.102565,9.707382,9.182816,8.869774,8.168963,7.884605,7.201829,7.104195,7.007888,6.912886,6.727616,7.175704,6.456904,6.369242,6.112679,5.856798,5.529753,5.257648,4.693818,4.629154,0.045653,4.432051,4.371011,4.771019,4.251425,4.133046,4.010365,3.765305,3.553587,3.252025,3.207362,3.163315,3.050608,3.008676,2.967323,0.028673,2.827956,2.789061,2.750681,2.549613,2.51453,2.368616,2.33583,2.3035,2.271619,2.240181,2.209179,2.178603,0.021119,2.082789,1.961219,1.847835,1.731422,1.615505,1.593216,1.571235,1.549559,1.528183,1.507103,1.48631,1.465801,1.414554,1.352859,1.334246,1.279065,1.183801,1.167469,1.151362,1.135478,1.119814,1.104366,1.089128,1.074097,1.059257,9.760279,9.625791,8.918206,7.073597,6.97569,6.87914,6.783928,6.690036,6.270355,6.183604,6.098022,6.0135,5.93012,5.539274,4.289967,3.9598,3.904416,3.849807,3.795962,3.742871,3.690523,3.638907,3.587987,3.266077,3.220245,3.175056,3.130471,2.825156,2.785268,2.745943,2.707174,2.668953,2.631272,2.594123,2.111307,2.081558,2.052229,2.023313,1.542083,1.323224,1.304528,1.286097,1.267927,1.250013,1.232353,1.214942,1.197747,1.180766,1.164026,1.147523,9.583019,9.447679,9.314252,9.182708,9.053023,8.925169,8.799121,8.674854,8.55194,8.430371,8.310531,8.192395,8.07572,7.960083,7.846102,7.733753,7.623013,7.513858,7.406267,7.300217,7.195393,7.091786,6.989671,6.889027,6.78962,6.691044,6.593899,6.498165,6.403821,6.310848,6.219224,6.12893,6.039656,5.951393,5.864421,5.778721,5.69399,5.609986,5.527223,5.44568,5.365341,5.286187,5.208201,4.133606,3.086537,3.041284,2.996695,2.95276,9.915302,9.770027 +GicComplex,NIC,CL,C,,33535.87259,34226.13899,35866.8437,35451.31356,35047.2134,34735.40594,34456.75704,34290.73436,34184.26867,34067.66181,33994.19262,33936.81916,33860.23049,33920.99342,34447.17073,33915.76595,33396.41408,32951.02441,32515.54295,32160.3836,31854.40643,31562.14214,31317.65217,31095.08164,30891.30473,30761.34018,30916.75429,30528.19887,30146.88478,29800.17738,29459.8904,29163.23988,28896.67459,28621.88906,28369.72013,28127.44566,27894.52205,27679.31593,27624.1548,27276.62774,26937.26122,26624.25065,26325.40601,26055.3607,25818.43841,25580.76237,25355.67277,25145.04585,24942.23209,24769.52397,24724.29188,24412.87144,24107.27116,23820.83727,23546.77522,23302.623,23091.58515,22872.75656,22675.67512,22489.47881,22302.92252,22149.52562,22106.50014,21827.77828,21554.12559,21302.92909,21055.59979,20842.8176,20659.53343,20465.65555,20279.55591,20109.01245,19941.65289,19791.90948,19753.28503,19503.97108,19259.59753,19042.15141,18826.21936,18632.40376,18457.89799,18291.10043,18136.50295,17986.12736,17841.87427,17727.47016,17690.69409,17467.10495,17247.85766,17047.24234,16851.69196,16673.37397,16523.58274,16368.79309,16228.6635,16096.61305,15965.2048,15853.77126,15813.40766,15613.25065,15418.04039,15237.28332,15067.06796,14909.10818,14768.29743,14614.78308,14479.09815,14356.39748,14217.62335,14103.06012,14021.76677,13844.26502,13670.43639,13511.50902,13356.7006,13209.84121,13087.7532,12946.23175,12826.76079,12718.33045,12586.42694,12487.13981,12415.53739,12258.22962,12104.29653,11962.02898,11826.69161,11702.41869,11591.32992,11480.98248,11364.62507,11258.96336,11162.58296,11066.01657,11020.3166,10880.47425,10743.60366,10615.7354,10494.77672,10373.85063,10272.08981,10167.1258,10075.84734,9976.617737,9873.784291,9793.452834,9738.535436,9614.811563,9493.715955,9382.712349,9274.120706,9168.392271,9074.563452,8983.408475,8890.638889,8802.914628,8712.391834,8645.726124,8604.581385,8495.071966,8388.406094,8286.821547,8189.952954,8099.64263,8017.649133,7929.116104,7845.784672,7758.150379,7673.791533,7593.141781,7510.084844,7414.380573,7320.724307,7234.631513,7148.337636,7069.788214,6992.803322,6924.043065,6852.525872,6758.490391,6683.379481,6624.230727,6579.863813,6495.901093,6413.806703,6337.205467,6264.267111,6186.39002,6100.370234,6037.623325,5964.328582,5898.777579,5833.708765,5778.623149,5728.834826,5655.631174,5584.076607,5513.152398,5445.663212,5377.151901,5314.735844,5248.599168,5179.96521,5121.775037,5058.276758,4988.743097,4918.971964,4855.969474,4794.410997,4737.409332,4675.744516,4619.399207,4558.72763,4512.149916,4448.987656,4388.083355,4342.966868,4293.099344,4252.139077,4197.590645,4144.629682,4086.409605,4031.800661,3969.929594,3911.509996,3851.614416,3806.620608,3742.262477,3684.059481,3632.872153,3592.936223,3546.782022,3501.720716,3457.274233,3412.905514,3368.660208,3324.01036,3284.486945,3231.366847,3186.241729,3149.002801,3110.773438,3074.784295,3035.213888,2996.699751,2960.901906,2918.577258,2874.197674,2829.695919,2789.890863,2752.980964,2714.702217,2670.822059,2639.805393,2597.739454,2564.243761,2531.670974,2497.48136,2468.053663,2426.584729,2391.711248,2351.881112,2313.196028,2286.160467,2253.866916,2226.436184,2184.120775,2155.907698,2128.51922,2100.795774,2073.148231,2048.385659,2025.0897,1995.021858,1966.142097,1930.739863,1893.495615,1874.22198,1853.132371,1829.1403,1805.929023,1783.971081,1757.858364,1727.577513,1703.181775,1672.825172,1639.266949,1601.521186,1571.858572,1534.683048,1505.050081,1485.623051,1466.682836,1446.644697,1427.94535,1406.641458,1380.213187,1358.234732,1335.820374,1316.060212,1300.382785,1277.871789,1254.12873,1237.883891,1222.070044,1207.890021,1192.094125,1176.797243,1158.235032,1141.262466,1124.673342,1108.547008,1089.592557,1069.433382,1046.398207,1032.81553,1019.603188,1003.756714,990.580559,975.374562,960.605272,943.730653,929.188024,916.631898,903.500041,888.276223,870.430324,859.148348,848.120185,837.186224,824.094522,812.208099,799.647175,787.628456,774.914754,757.705942,743.065376,731.779311,711.699468,702.45661,690.424631,678.580749,663.166238,648.618608,624.12076,603.565108,582.415702,559.277957,536.857092,520.484869,487.114615,480.778456,474.492534,467.261587,460.788758,452.467662,444.594102,437.455104,429.308789,421.390702,414.833113,408.435316,398.075146,392.88443,387.738115,382.52232,376.978509,369.09776,362.613226,354.1242,348.567925,343.38234,337.629242,331.182311,323.169908,318.947206,314.758993,310.803,306.10757,301.699621,297.798319,292.506665,287.051657,280.419845,274.590526,268.561197,260.363862,256.954353,253.571647,248.912245,245.972759,242.285135,237.854082,232.551795,227.333399,223.05758,217.063713,212.668939,206.22415,203.517097,200.82965,196.943179,193.159049,189.440226,185.240484,180.479086,177.397226,174.091408,170.434345,165.720877,158.087694,156.010706,153.946704,150.716587,147.17816,143.581596,141.471073,138.177806,135.060287,132.934619,129.859753,124.758217,119.040288,117.474331,115.916152,112.88817,111.446444,109.246746,106.67424,105.223314,102.406054,99.84368,96.512743,93.082381,87.401628,86.249419,85.102088,83.036783,81.908159,80.497321,78.817502,77.447286,75.581881,73.670299,71.123444,67.132175,64.043847,63.197561,62.352608,61.414085,60.151507,58.497989,56.533312,54.59964,52.108631,50.228226,48.816235,46.713061,44.472247,43.886278,43.299438,42.365887,41.664588,41.009714,40.185602,39.079098,38.209455,37.332986,36.278399,34.431733,31.318798,30.906184,30.499117,30.016918,29.413235,28.669802,27.495236,26.078926,25.109785,24.294291,23.732585,21.892021,20.914212,20.637655,20.364776,20.104216,19.730784,19.398678,18.821077,18.516932,18.272469,17.801747,17.412207,16.49007,14.133229,13.946084,13.761491,13.501017,13.048942,12.709121,12.403982,12.147019,11.744218,11.191513,10.354495,9.258459,8.690802,8.576092,8.46293,8.341174,8.162127,7.875185,7.677418,7.586228,7.439121,7.231159,7.009123,6.547528,5.653089,5.577711,5.503344,5.432088,5.274719,5.210844,5.048875,4.521423,4.149387,3.964219,3.670722,3.351165,2.692363,2.656459,2.621038,2.587918,2.533526,2.463246,2.414022,2.261357,2.095748,1.940548,1.821631,1.445258,1.186766,1.170793,1.15504,1.141303,1.127417,1.045521,1.033222,1.002319,0.991524,0.887035,0.830358,0.80995,0.680213,0.670895,0.661709,0.654246,0.628288,0.619713,0.61292,0.607171,0.588391,0.583136,0.563105,0.529856,0.479119,0.472379,0.465753,0.431571,0.425476,0.420386,0.394927,0.391603,0.388046,0.384942,0.34191,0.34595,0.325343,0.320682,0.316088,0.31156,0.307097,0.303571,0.29969,0.287254,0.284454,0.260042,0.240548,0.226147,0.209627,0.206612,0.203641,0.200713,0.197827,0.195702,0.193167,0.191584,0.180651,0.16699,0.164965,0.14469,0.135317,0.133384,0.131479,0.129602,0.127751,0.126552,0.125021,0.12449,0.123074,0.109451,0.108542,8.537432,7.357732,7.254752,7.153214,7.053098,0.069555,6.089561,0.060267,0.060421,5.98855,5.904967,5.482401,5.117382,5.078674,5.007237,4.936807,4.867367,4.798905,4.731406,0.046841,0.047027,4.140964,4.082453,4.038134,4.083926,3.896083,3.840664,3.786034,3.732181,3.679096,3.626766,3.596725,0.028608,2.820268,2.780233,2.753741,2.094079,1.680325,1.656335,1.632689,1.60938,1.586404,0.015637,0.015608,1.560503,1.538159,1.516135,1.506607,0.01074,1.058866,0.010438,1.029138,1.014589,1.000245,9.861044,9.951639,1.006313,9.919704,9.77832,9.186752,9.333788,9.199741,9.06762,8.937397,8.809044,8.682534,8.557841,8.618284,8.698998,8.573137,8.449098,8.423441,8.599279,8.47406,8.350664,8.229066,8.109238,7.991155,7.874793,7.917113,7.969885,7.852826,7.737487,7.714442,7.789579,7.674303,7.560733,7.448843,7.33861,7.230009,7.126934,5.441094,3.574384,3.521814,3.470017,3.509319,1.046458,1.031126 diff --git a/Test/Data/DataNodeParameter_Duplicate.csv b/Test/Data/DataNodeParameter_Duplicate.csv new file mode 100644 index 00000000..2c844eef --- /dev/null +++ b/Test/Data/DataNodeParameter_Duplicate.csv @@ -0,0 +1,13 @@ +@@Main +ReportingNode,Year,Month +CH,2020,12 + +@@SingleDataNodeParameter +DataNode,PremiumAllocation +DT1.1,0.9 +DT1.1,0.9 + +@@InterDataNodeParameter +DataNode,LinkedDataNode,ReinsuranceCoverage +DTR1.1,DT1.1,1 +DT1.1,DTR1.1,1 diff --git a/Test/Data/DataNodeParameter_InvalidDataNode.csv b/Test/Data/DataNodeParameter_InvalidDataNode.csv new file mode 100644 index 00000000..681a63c5 --- /dev/null +++ b/Test/Data/DataNodeParameter_InvalidDataNode.csv @@ -0,0 +1,14 @@ +@@Main +ReportingNode,Year,Month +CH,2020,12 + +@@SingleDataNodeParameter +DataNode,PremiumAllocation +DT1.1,0.9 +DataNodeInvalid0,0.85 + +@@InterDataNodeParameter +DataNode,LinkedDataNode,ReinsuranceCoverage +DTR1.1,DT1.1,1 +DataNodeInvalid1,DTR1.1,1 +DTR1.1,DataNodeInvalid2,1 diff --git a/Test/Data/DataNodeParameter_InvalidReinsCov.csv b/Test/Data/DataNodeParameter_InvalidReinsCov.csv new file mode 100644 index 00000000..802ab7b7 --- /dev/null +++ b/Test/Data/DataNodeParameter_InvalidReinsCov.csv @@ -0,0 +1,12 @@ +@@Main +ReportingNode,Year,Month +CH,2020,12 + +@@SingleDataNodeParameter +DataNode,PremiumAllocation +DT1.1,0.9 + +@@InterDataNodeParameter +DataNode,LinkedDataNode,ReinsuranceCoverage +DT1.1,DT1.1,1 + diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv new file mode 100644 index 00000000..1a81ddf9 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv @@ -0,0 +1,34 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@A +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,NIC,CF,DTR1.1,,A,C,140 +,PR,CF,DTR1.1,,A,C,-200 +2020,NIC,CF,DT2.2,,A,C,-280 +,AEA,CF,DT1.3,,A,C,-5 +,ACA,CF,DT1.3,,A,C,-10 +,NIC,CF,DT1.3,,A,C,-280 +,PR,CF,DT1.1,,A,C,400 +,NIC,CF,DT1.1,,A,C,-280 +,ACA,CF,DT1.1,,A,C,-10 +,AEA,CF,DT1.1,,A,C,-5 +2020,NIC,CF,DT1.2,,A,C,-280 +,PR,CF,DT2.1,,A,C,400 +,NIC,CF,DT2.1,,A,C,-280 +,ACA,CF,DT2.1,,A,C,-10 +,AEA,CF,DT2.1,,A,C,-5 +,PR,CF,DT1.3,,A,C,400 +2020,NIC,CF,DTR1.2,,A,C,140 +,PR,CF,DTR2.1,,A,C,-200 +,NIC,CF,DTR2.1,,A,C,140 +2020,NIC,CF,DTR2.2,,A,C,140 +,PR,CF,DT3.1,,A,C,400 +,NIC,CF,DT3.1,,A,C,-280 +,ACA,CF,DT3.1,,A,C,-10 +,AEA,CF,DT3.1,,A,C,-5 +,PR,CF,DT4.1,,A,C,400 +,NIC,CF,DT4.1,,A,C,-280 +,ACA,CF,DT4.1,,A,C,-10 +,AEA,CF,DT4.1,,A,C,-5 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv new file mode 100644 index 00000000..d0c36f7e --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv @@ -0,0 +1,8 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@AA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,BOP,DT3.1,,AA,I,-1.5 +,PR,EOP,DT3.1,,AA,C,-1.5 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv new file mode 100644 index 00000000..28224af3 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv @@ -0,0 +1,11 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@APA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,CF,DT1.3,,APA,C,400 +,PR,CF,DT1.1,,APA,C,320 +,PR,CF,DT2.1,,APA,C,320 +,PR,CF,DT3.1,,APA,C,320 +,PR,CF,DT4.1,,APA,C,320 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv new file mode 100644 index 00000000..8dbc1e48 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv @@ -0,0 +1,181 @@ +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@BE +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,BOP,DT1.1,C,BE,N,-798.536731161375 +,NIC,BOP,DT1.1,L,BE,N,598.7529445986629 +,PR,BOP,DT1.1,L,BE,N,-798.536731161375 +,NIC,BOP,DT1.1,C,BE,N,598.7529445986629 +,PR,EOP,DT1.1,L,BE,C,-399.63392949885525 +,NIC,EOP,DT1.1,L,BE,C,299.67554969423594 +,PR,EOP,DT1.1,C,BE,C,-399.63392949885525 +,NIC,EOP,DT1.1,C,BE,C,299.67554969423594 +,PR,IA,DT1.1,L,BE,N,-1.0971983374806105 +,NIC,IA,DT1.1,L,BE,N,0.9226050955731167 +,PR,IA,DT1.1,C,BE,N,-1.0971983374806105 +,NIC,IA,DT1.1,C,BE,N,0.9226050955731167 +,PR,CF,DT1.1,L,BE,N,400 +,NIC,CF,DT1.1,L,BE,N,-300 +,PR,CF,DT1.1,C,BE,N,400 +,NIC,CF,DT1.1,C,BE,N,-300 +2020,NIC,BOP,DT1.2,L,BE,N,598.7529445986629 +2020,NIC,BOP,DT1.2,C,BE,N,598.7529445986629 +2020,NIC,EOP,DT1.2,L,BE,C,299.67554969423594 +2020,NIC,EOP,DT1.2,C,BE,C,299.67554969423594 +2020,NIC,IA,DT1.2,L,BE,N,0.9226050955731167 +2020,NIC,IA,DT1.2,C,BE,N,0.9226050955731167 +2020,NIC,CF,DT1.2,L,BE,N,-300 +2020,NIC,CF,DT1.2,C,BE,N,-300 +,PR,BOP,DT1.3,L,BE,N,-798.536731161375 +,NIC,BOP,DT1.3,L,BE,N,598.7529445986629 +,PR,BOP,DT1.3,C,BE,N,-798.536731161375 +,NIC,BOP,DT1.3,C,BE,N,598.7529445986629 +,PR,EOP,DT1.3,L,BE,C,-399.63392949885525 +,NIC,EOP,DT1.3,L,BE,C,299.67554969423594 +,PR,EOP,DT1.3,C,BE,C,-399.63392949885525 +,NIC,EOP,DT1.3,C,BE,C,299.67554969423594 +,PR,IA,DT1.3,L,BE,N,-1.0971983374806105 +,NIC,IA,DT1.3,L,BE,N,0.9226050955731167 +,PR,IA,DT1.3,C,BE,N,-1.0971983374806105 +,NIC,IA,DT1.3,C,BE,N,0.9226050955731167 +,PR,CF,DT1.3,L,BE,N,400 +,NIC,CF,DT1.3,L,BE,N,-300 +,PR,CF,DT1.3,C,BE,N,400 +,NIC,CF,DT1.3,C,BE,N,-300 +,PR,BOP,DT2.1,L,BE,N,-798.536731161375 +,NIC,BOP,DT2.1,L,BE,N,598.7529445986629 +,PR,BOP,DT2.1,C,BE,N,-798.536731161375 +,NIC,BOP,DT2.1,C,BE,N,598.7529445986629 +,PR,EOP,DT2.1,L,BE,C,-399.63392949885525 +,NIC,EOP,DT2.1,L,BE,C,299.67554969423594 +,PR,EOP,DT2.1,C,BE,C,-399.63392949885525 +,NIC,EOP,DT2.1,C,BE,C,299.67554969423594 +,PR,IA,DT2.1,L,BE,N,-1.0971983374806105 +,NIC,IA,DT2.1,L,BE,N,0.9226050955731167 +,PR,IA,DT2.1,C,BE,N,-1.0971983374806105 +,NIC,IA,DT2.1,C,BE,N,0.9226050955731167 +,PR,CF,DT2.1,L,BE,N,400 +,NIC,CF,DT2.1,L,BE,N,-300 +,PR,CF,DT2.1,C,BE,N,400 +,NIC,CF,DT2.1,C,BE,N,-300 +2020,NIC,BOP,DT2.2,L,BE,N,598.7529445986629 +2020,NIC,BOP,DT2.2,C,BE,N,598.7529445986629 +2020,NIC,EOP,DT2.2,L,BE,C,299.67554969423594 +2020,NIC,EOP,DT2.2,C,BE,C,299.67554969423594 +2020,NIC,IA,DT2.2,L,BE,N,0.9226050955731167 +2020,NIC,IA,DT2.2,C,BE,N,0.9226050955731167 +2020,NIC,CF,DT2.2,L,BE,N,-300 +2020,NIC,CF,DT2.2,C,BE,N,-300 +,PR,BOP,DTR1.1,L,BE,N,399.2683655806875 +,NIC,BOP,DTR1.1,L,BE,N,-299.37647229933145 +,CDR,BOP,DTR1.1,L,BE,N,0.4811341181992343 +,PR,BOP,DTR1.1,C,BE,N,399.2683655806875 +,NIC,BOP,DTR1.1,C,BE,N,-299.37647229933145 +,CDR,BOP,DTR1.1,C,BE,N,0.4811341181992343 +,PR,EOP,DTR1.1,L,BE,C,199.81696474942763 +,NIC,EOP,DTR1.1,L,BE,C,-149.83777484711797 +,CDR,EOP,DTR1.1,L,BE,C,0.11527160395198197 +,PR,EOP,DTR1.1,C,BE,C,199.81696474942763 +,NIC,EOP,DTR1.1,C,BE,C,-149.83777484711797 +,CDR,EOP,DTR1.1,C,BE,C,0.11527160395198197 +,PR,IA,DTR1.1,L,BE,N,0.5485991687403052 +,NIC,IA,DTR1.1,L,BE,N,-0.4613025477865583 +,CDR,IA,DTR1.1,L,BE,N,0.0011701910454977593 +,PR,IA,DTR1.1,C,BE,N,0.5485991687403052 +,NIC,IA,DTR1.1,C,BE,N,-0.4613025477865583 +,CDR,IA,DTR1.1,C,BE,N,0.0011701910454977593 +,PR,CF,DTR1.1,L,BE,N,-200 +,NIC,CF,DTR1.1,L,BE,N,150 +,CDR,CF,DTR1.1,L,BE,N,-0.36703270529272203 +,PR,CF,DTR1.1,C,BE,N,-200 +,NIC,CF,DTR1.1,C,BE,N,150 +,CDR,CF,DTR1.1,C,BE,N,-0.36703270529272203 +2020,NIC,BOP,DTR1.2,L,BE,N,-299.37647229933145 +2020,CDR,BOP,DTR1.2,L,BE,N,0.4811341181992343 +2020,NIC,BOP,DTR1.2,C,BE,N,-299.37647229933145 +2020,CDR,BOP,DTR1.2,C,BE,N,0.4811341181992343 +2020,NIC,EOP,DTR1.2,L,BE,C,-149.83777484711797 +2020,CDR,EOP,DTR1.2,L,BE,C,0.11527160395198197 +2020,NIC,EOP,DTR1.2,C,BE,C,-149.83777484711797 +2020,CDR,EOP,DTR1.2,C,BE,C,0.11527160395198197 +2020,NIC,IA,DTR1.2,L,BE,N,-0.4613025477865583 +2020,CDR,IA,DTR1.2,L,BE,N,0.0011701910454977593 +2020,NIC,IA,DTR1.2,C,BE,N,-0.4613025477865583 +2020,CDR,IA,DTR1.2,C,BE,N,0.0011701910454977593 +2020,NIC,CF,DTR1.2,L,BE,N,150 +2020,CDR,CF,DTR1.2,L,BE,N,-0.36703270529272203 +2020,NIC,CF,DTR1.2,C,BE,N,150 +2020,CDR,CF,DTR1.2,C,BE,N,-0.36703270529272203 +,PR,BOP,DTR2.1,L,BE,N,399.2683655806875 +,NIC,BOP,DTR2.1,L,BE,N,-299.37647229933145 +,CDR,BOP,DTR2.1,L,BE,N,0.4811341181992343 +,PR,BOP,DTR2.1,C,BE,N,399.2683655806875 +,NIC,BOP,DTR2.1,C,BE,N,-299.37647229933145 +,CDR,BOP,DTR2.1,C,BE,N,0.4811341181992343 +,PR,EOP,DTR2.1,L,BE,C,199.81696474942763 +,NIC,EOP,DTR2.1,L,BE,C,-149.83777484711797 +,CDR,EOP,DTR2.1,L,BE,C,0.11527160395198197 +,PR,EOP,DTR2.1,C,BE,C,199.81696474942763 +,NIC,EOP,DTR2.1,C,BE,C,-149.83777484711797 +,CDR,EOP,DTR2.1,C,BE,C,0.11527160395198197 +,PR,IA,DTR2.1,L,BE,N,0.5485991687403052 +,NIC,IA,DTR2.1,L,BE,N,-0.4613025477865583 +,CDR,IA,DTR2.1,L,BE,N,0.0011701910454977593 +,PR,IA,DTR2.1,C,BE,N,0.5485991687403052 +,NIC,IA,DTR2.1,C,BE,N,-0.4613025477865583 +,CDR,IA,DTR2.1,C,BE,N,0.0011701910454977593 +,PR,CF,DTR2.1,L,BE,N,-200 +,NIC,CF,DTR2.1,L,BE,N,150 +,CDR,CF,DTR2.1,L,BE,N,-0.36703270529272203 +,PR,CF,DTR2.1,C,BE,N,-200 +,NIC,CF,DTR2.1,C,BE,N,150 +,CDR,CF,DTR2.1,C,BE,N,-0.36703270529272203 +2020,NIC,BOP,DTR2.2,L,BE,N,-299.37647229933145 +2020,CDR,BOP,DTR2.2,L,BE,N,0.4811341181992343 +2020,NIC,BOP,DTR2.2,C,BE,N,-299.37647229933145 +2020,CDR,BOP,DTR2.2,C,BE,N,0.4811341181992343 +2020,NIC,EOP,DTR2.2,L,BE,C,-149.83777484711797 +2020,CDR,EOP,DTR2.2,L,BE,C,0.11527160395198197 +2020,NIC,EOP,DTR2.2,C,BE,C,-149.83777484711797 +2020,CDR,EOP,DTR2.2,C,BE,C,0.11527160395198197 +2020,NIC,IA,DTR2.2,L,BE,N,-0.4613025477865583 +2020,CDR,IA,DTR2.2,L,BE,N,0.0011701910454977593 +2020,NIC,IA,DTR2.2,C,BE,N,-0.4613025477865583 +2020,CDR,IA,DTR2.2,C,BE,N,0.0011701910454977593 +2020,NIC,CF,DTR2.2,L,BE,N,150 +2020,CDR,CF,DTR2.2,L,BE,N,-0.36703270529272203 +2020,NIC,CF,DTR2.2,C,BE,N,150 +2020,CDR,CF,DTR2.2,C,BE,N,-0.36703270529272203 +,PR,BOP,DT3.1,L,BE,N,-798.536731161375 +,NIC,BOP,DT3.1,L,BE,N,598.7529445986629 +,PR,BOP,DT3.1,C,BE,N,-798.536731161375 +,NIC,BOP,DT3.1,C,BE,N,598.7529445986629 +,PR,EOP,DT3.1,L,BE,C,-399.63392949885525 +,NIC,EOP,DT3.1,L,BE,C,299.67554969423594 +,PR,EOP,DT3.1,C,BE,C,-399.63392949885525 +,NIC,EOP,DT3.1,C,BE,C,299.67554969423594 +,PR,IA,DT3.1,L,BE,N,-1.0971983374806105 +,NIC,IA,DT3.1,L,BE,N,0.9226050955731167 +,PR,IA,DT3.1,C,BE,N,-1.0971983374806105 +,NIC,IA,DT3.1,C,BE,N,0.9226050955731167 +,PR,CF,DT3.1,L,BE,N,400 +,NIC,CF,DT3.1,L,BE,N,-300 +,PR,CF,DT3.1,C,BE,N,400 +,NIC,CF,DT3.1,C,BE,N,-300 +,PR,BOP,DT4.1,L,BE,N,-798.536731161375 +,NIC,BOP,DT4.1,L,BE,N,598.7529445986629 +,PR,BOP,DT4.1,C,BE,N,-798.536731161375 +,NIC,BOP,DT4.1,C,BE,N,598.7529445986629 +,PR,EOP,DT4.1,L,BE,C,-399.63392949885525 +,NIC,EOP,DT4.1,L,BE,C,299.67554969423594 +,PR,EOP,DT4.1,C,BE,C,-399.63392949885525 +,NIC,EOP,DT4.1,C,BE,C,299.67554969423594 +,PR,IA,DT4.1,L,BE,N,-1.0971983374806105 +,NIC,IA,DT4.1,L,BE,N,0.9226050955731167 +,PR,IA,DT4.1,C,BE,N,-1.0971983374806105 +,NIC,IA,DT4.1,C,BE,N,0.9226050955731167 +,PR,CF,DT4.1,L,BE,N,400 +,NIC,CF,DT4.1,L,BE,N,-300 +,PR,CF,DT4.1,C,BE,N,400 +,NIC,CF,DT4.1,C,BE,N,-300 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv new file mode 100644 index 00000000..66ec38ea --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv @@ -0,0 +1,11 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@BEPA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,CF,DT1.1,L,BEPA,N,320 +,PR,CF,DT1.3,L,BEPA,N,400 +,PR,CF,DT2.1,L,BEPA,N,320 +,PR,CF,DT3.1,L,BEPA,N,320 +,PR,CF,DT4.1,L,BEPA,N,320 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv new file mode 100644 index 00000000..cf8c8f5f --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv @@ -0,0 +1,40 @@ +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@C +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,AM,DTR1.1,,C,C,24.228134693791258 +,,IA,DT1.3,,C,N,0.08233273235018213 +,,BOP,DT1.3,,C,N,139.90849210284577 +,,EOP,DT1.3,,C,C,82.02271122089925 +,,AM,DT1.3,,C,C,-42.968113614296705 +,,EA,DT1.3,,C,C,-15 +,,EA,DT1.1,,C,C,-15 +,,AM,DT1.1,,C,C,-42.968113614296705 +,,EOP,DT1.1,,C,C,82.02271122089925 +,,BOP,DT1.1,,C,N,139.90849210284577 +,,IA,DT1.1,,C,N,0.08233273235018213 +,,EA,DT2.1,,C,C,-15 +,,AM,DT2.1,,C,C,-42.968113614296705 +,,EOP,DT2.1,,C,C,82.02271122089925 +,,BOP,DT2.1,,C,N,139.90849210284577 +,,IA,DT2.1,,C,N,0.08233273235018213 +,,EOP,DTR1.1,,C,C,-46.24958203305145 +,,BOP,DTR1.1,,C,N,-70.43538016962212 +,,IA,DTR1.1,,C,N,-0.04233655722058882 +,,AM,DTR2.1,,C,C,24.228134693791258 +,,EOP,DTR2.1,,C,C,-46.24958203305145 +,,BOP,DTR2.1,,C,N,-70.43538016962212 +,,IA,DTR2.1,,C,N,-0.04233655722058882 +,,BOP,DT3.1,,C,I,72.2 +,,EA,DT3.1,,C,C,-15 +,,AM,DT3.1,,C,C,-67.83795828214956 +,,EOP,DT3.1,,C,C,129.49726655304642 +,,IA,DT3.1,,C,I,0.14440000000001615 +,,BOP,DT3.1,,C,N,139.90849210284577 +,,IA,DT3.1,,C,N,0.08233273235018213 +,,EA,DT4.1,,C,C,-15 +,,AM,DT4.1,,C,C,-42.968113614296705 +,,EOP,DT4.1,,C,C,82.02271122089925 +,,BOP,DT4.1,,C,N,139.90849210284577 +,,IA,DT4.1,,C,N,0.08233273235018213 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv new file mode 100644 index 00000000..0b2eb99d --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv @@ -0,0 +1,21 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@DA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,EOP,DT1.3,,DA,C,-9.843447868559382 +,,AM,DT1.3,,DA,C,5.156552131440618 +,,CF,DT1.3,,DA,C,-15 +,,CF,DT1.1,,DA,C,-15 +,,AM,DT1.1,,DA,C,5.156552131440618 +,,EOP,DT1.1,,DA,C,-9.843447868559382 +,,CF,DT2.1,,DA,C,-15 +,,AM,DT2.1,,DA,C,5.156552131440618 +,,EOP,DT2.1,,DA,C,-9.843447868559382 +,,CF,DT3.1,,DA,C,-15 +,,AM,DT3.1,,DA,C,5.156552131440618 +,,EOP,DT3.1,,DA,C,-9.843447868559382 +,,CF,DT4.1,,DA,C,-15 +,,AM,DT4.1,,DA,C,5.156552131440618 +,,EOP,DT4.1,,DA,C,-9.843447868559382 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv new file mode 100644 index 00000000..91b1b7f4 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv @@ -0,0 +1,17 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@F +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,AM,DT1.1,L,F,C,0.3437701420960412 +,,AM,DT1.2,L,F,C,1 +,,AM,DT1.3,L,F,C,0.3437701420960412 +,,AM,DT2.1,L,F,C,0.3437701420960412 +,,AM,DT2.2,L,F,C,1 +,,AM,DTR1.1,L,F,C,0.3437701420960412 +,,AM,DTR1.2,L,F,C,1 +,,AM,DTR2.1,L,F,C,0.3437701420960412 +,,AM,DTR2.2,L,F,C,1 +,,AM,DT3.1,L,F,C,0.3437701420960412 +,,AM,DT4.1,L,F,C,0.3437701420960412 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv new file mode 100644 index 00000000..08356dd2 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv @@ -0,0 +1,8 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@OA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,BOP,DT3.1,,OA,I,1.5 +,PR,EOP,DT3.1,,OA,C,1.5 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv new file mode 100644 index 00000000..d61cc7d7 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv @@ -0,0 +1,94 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@RA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,BOP,DT1.1,C,RA,N,59.8752944598663 +,,BOP,DT1.1,L,RA,N,59.8752944598663 +,,EOP,DT1.1,C,RA,C,29.967554969423595 +,,EOP,DT1.1,L,RA,C,29.967554969423595 +,,IA,DT1.1,C,RA,N,0.09226050955731169 +,,IA,DT1.1,L,RA,N,0.09226050955731169 +,,CF,DT1.1,C,RA,N,-30 +,,CF,DT1.1,L,RA,N,-30 +2020,,BOP,DT1.2,C,RA,N,59.8752944598663 +2020,,BOP,DT1.2,L,RA,N,59.8752944598663 +2020,,EOP,DT1.2,C,RA,C,29.967554969423595 +2020,,EOP,DT1.2,L,RA,C,29.967554969423595 +2020,,IA,DT1.2,C,RA,N,0.09226050955731169 +2020,,IA,DT1.2,L,RA,N,0.09226050955731169 +2020,,CF,DT1.2,C,RA,N,-30 +2020,,CF,DT1.2,L,RA,N,-30 +,,BOP,DT1.3,C,RA,N,59.8752944598663 +,,BOP,DT1.3,L,RA,N,59.8752944598663 +,,EOP,DT1.3,C,RA,C,29.967554969423595 +,,EOP,DT1.3,L,RA,C,29.967554969423595 +,,IA,DT1.3,C,RA,N,0.09226050955731169 +,,IA,DT1.3,L,RA,N,0.09226050955731169 +,,CF,DT1.3,C,RA,N,-30 +,,CF,DT1.3,L,RA,N,-30 +,,BOP,DT2.1,C,RA,N,59.8752944598663 +,,BOP,DT2.1,L,RA,N,59.8752944598663 +,,EOP,DT2.1,C,RA,C,29.967554969423595 +,,EOP,DT2.1,L,RA,C,29.967554969423595 +,,IA,DT2.1,C,RA,N,0.09226050955731169 +,,IA,DT2.1,L,RA,N,0.09226050955731169 +,,CF,DT2.1,C,RA,N,-30 +,,CF,DT2.1,L,RA,N,-30 +2020,,BOP,DT2.2,C,RA,N,59.8752944598663 +2020,,BOP,DT2.2,L,RA,N,59.8752944598663 +2020,,EOP,DT2.2,C,RA,C,29.967554969423595 +2020,,EOP,DT2.2,L,RA,C,29.967554969423595 +2020,,IA,DT2.2,C,RA,N,0.09226050955731169 +2020,,IA,DT2.2,L,RA,N,0.09226050955731169 +2020,,CF,DT2.2,C,RA,N,-30 +2020,,CF,DT2.2,L,RA,N,-30 +,,BOP,DTR1.1,C,RA,N,-29.93764722993315 +,,BOP,DTR1.1,L,RA,N,-29.93764722993315 +,,EOP,DTR1.1,C,RA,C,-14.983777484711798 +,,EOP,DTR1.1,L,RA,C,-14.983777484711798 +,,IA,DTR1.1,C,RA,N,-0.046130254778655844 +,,IA,DTR1.1,L,RA,N,-0.046130254778655844 +,,CF,DTR1.1,C,RA,N,15 +,,CF,DTR1.1,L,RA,N,15 +2020,,BOP,DTR1.2,C,RA,N,-29.93764722993315 +2020,,BOP,DTR1.2,L,RA,N,-29.93764722993315 +2020,,EOP,DTR1.2,C,RA,C,-14.983777484711798 +2020,,EOP,DTR1.2,L,RA,C,-14.983777484711798 +2020,,IA,DTR1.2,C,RA,N,-0.046130254778655844 +2020,,IA,DTR1.2,L,RA,N,-0.046130254778655844 +2020,,CF,DTR1.2,C,RA,N,15 +2020,,CF,DTR1.2,L,RA,N,15 +,,BOP,DTR2.1,C,RA,N,-29.93764722993315 +,,BOP,DTR2.1,L,RA,N,-29.93764722993315 +,,EOP,DTR2.1,C,RA,C,-14.983777484711798 +,,EOP,DTR2.1,L,RA,C,-14.983777484711798 +,,IA,DTR2.1,C,RA,N,-0.046130254778655844 +,,IA,DTR2.1,L,RA,N,-0.046130254778655844 +,,CF,DTR2.1,C,RA,N,15 +,,CF,DTR2.1,L,RA,N,15 +2020,,BOP,DTR2.2,C,RA,N,-29.93764722993315 +2020,,BOP,DTR2.2,L,RA,N,-29.93764722993315 +2020,,EOP,DTR2.2,C,RA,C,-14.983777484711798 +2020,,EOP,DTR2.2,L,RA,C,-14.983777484711798 +2020,,IA,DTR2.2,C,RA,N,-0.046130254778655844 +2020,,IA,DTR2.2,L,RA,N,-0.046130254778655844 +2020,,CF,DTR2.2,C,RA,N,15 +2020,,CF,DTR2.2,L,RA,N,15 +,,BOP,DT3.1,C,RA,N,59.8752944598663 +,,BOP,DT3.1,L,RA,N,59.8752944598663 +,,EOP,DT3.1,C,RA,C,29.967554969423595 +,,EOP,DT3.1,L,RA,C,29.967554969423595 +,,IA,DT3.1,C,RA,N,0.09226050955731169 +,,IA,DT3.1,L,RA,N,0.09226050955731169 +,,CF,DT3.1,C,RA,N,-30 +,,CF,DT3.1,L,RA,N,-30 +,,BOP,DT4.1,C,RA,N,59.8752944598663 +,,BOP,DT4.1,L,RA,N,59.8752944598663 +,,EOP,DT4.1,C,RA,C,29.967554969423595 +,,EOP,DT4.1,L,RA,C,29.967554969423595 +,,IA,DT4.1,C,RA,N,0.09226050955731169 +,,IA,DT4.1,L,RA,N,0.09226050955731169 +,,CF,DT4.1,C,RA,N,-30 +,,CF,DT4.1,L,RA,N,-30 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv new file mode 100644 index 00000000..4411cdfd --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv @@ -0,0 +1,39 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@A +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +2020,NIC,CF,DT2.2,,A,C,-76 +,AEA,CF,DT2.1,,A,C,-5 +,ACA,CF,DT2.1,,A,C,-10 +,NIC,CF,DT2.1,,A,C,-70 +,ICO,CF,DT2.1,,A,C,-6 +,PR,CF,DT2.1,,A,C,90 +,PR,CF,DT1.1,,A,C,90 +,ICO,CF,DT1.1,,A,C,-6 +,NIC,CF,DT1.1,,A,C,-70 +,ACA,CF,DT1.1,,A,C,-10 +,AEA,CF,DT1.1,,A,C,-5 +,PR,CF,DT1.3,,A,C,90 +,ICO,CF,DT1.3,,A,C,-6 +,NIC,CF,DT1.3,,A,C,-70 +,ACA,CF,DT1.3,,A,C,-10 +2020,NIC,CF,DT1.2,,A,C,-76 +,AEA,CF,DT1.3,,A,C,-5 +,PR,CF,DTR1.1,,A,C,-45 +,NIC,CF,DTR1.1,,A,C,35 +2020,NIC,CF,DTR1.2,,A,C,35 +,PR,CF,DTR2.1,,A,C,-45 +,NIC,CF,DTR2.1,,A,C,35 +2020,NIC,CF,DTR2.2,,A,C,35 +,PR,CF,DT3.1,,A,C,90 +,ICO,CF,DT3.1,,A,C,-6 +,NIC,CF,DT3.1,,A,C,-70 +,ACA,CF,DT3.1,,A,C,-10 +,AEA,CF,DT3.1,,A,C,-5 +,PR,CF,DT4.1,,A,C,90 +,ICO,CF,DT4.1,,A,C,-6 +,NIC,CF,DT4.1,,A,C,-70 +,ACA,CF,DT4.1,,A,C,-10 +,AEA,CF,DT4.1,,A,C,-5 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv new file mode 100644 index 00000000..4364bf3b --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv @@ -0,0 +1,26 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@AA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,EOP,DT2.1,,AA,C,-1 +,PR,CF,DT2.1,,AA,C,-5 +,PR,WO,DT2.1,,AA,C,4 +,PR,WO,DT1.1,,AA,C,4 +,PR,CF,DT1.1,,AA,C,-5 +,PR,EOP,DT1.1,,AA,C,-1 +,PR,WO,DT1.3,,AA,C,4 +,PR,CF,DT1.3,,AA,C,-5 +,PR,EOP,DT1.3,,AA,C,-1 +,PR,CF,DTR1.1,,AA,C,2 +,PR,EOP,DTR1.1,,AA,C,2 +,PR,CF,DTR2.1,,AA,C,2 +,PR,EOP,DTR2.1,,AA,C,2 +,PR,WO,DT3.1,,AA,C,4 +,PR,CF,DT3.1,,AA,C,-5 +,PR,BOP,DT3.1,,AA,I,-1.5 +,PR,EOP,DT3.1,,AA,C,-2.5 +,PR,WO,DT4.1,,AA,C,4 +,PR,CF,DT4.1,,AA,C,-5 +,PR,EOP,DT4.1,,AA,C,-1 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv new file mode 100644 index 00000000..f489cba8 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv @@ -0,0 +1,11 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@AAPA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,CF,DT2.1,,AAPA,C,-4 +,PR,CF,DT1.1,,AAPA,C,-4 +,PR,CF,DT1.3,,AAPA,C,-5 +,PR,CF,DT3.1,,AAPA,C,-4 +,PR,CF,DT4.1,,AAPA,C,-4 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv new file mode 100644 index 00000000..e25da1c5 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv @@ -0,0 +1,11 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@APA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,CF,DT2.1,,APA,C,72 +,PR,CF,DT1.1,,APA,C,72 +,PR,CF,DT1.3,,APA,C,90 +,PR,CF,DT3.1,,APA,C,72 +,PR,CF,DT4.1,,APA,C,72 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv new file mode 100644 index 00000000..e367c61e --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv @@ -0,0 +1,471 @@ +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@BE +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,MC,DT1.1,L,BE,I,-39.963392949885474 +,NIC,MC,DT1.1,L,BE,I,-59.93510993884718 +,PR,MC,DT1.1,C,BE,I,-39.963392949885474 +,NIC,MC,DT1.1,C,BE,I,-59.93510993884718 +,PR,BOP,DT1.1,L,BE,N,-39.963392949885524 +,NIC,BOP,DT1.1,L,BE,N,47.94808795107775 +,ICO,BOP,DT1.1,L,BE,N,11.987021987769438 +,PR,BOP,DT1.1,C,BE,N,-39.908704950657615 +,NIC,BOP,DT1.1,C,BE,N,47.87054820092061 +,ICO,BOP,DT1.1,C,BE,N,11.967637050230152 +,PR,EV,DT1.1,L,BE,N,14.990014559301141 +,NIC,EV,DT1.1,L,BE,N,44.96255719444398 +,PR,EV,DT1.1,C,BE,N,14.975090771307462 +,NIC,EV,DT1.1,C,BE,N,44.906606557852164 +,PR,BOP,DT1.1,L,BE,I,-399.63392949885525 +,NIC,BOP,DT1.1,L,BE,I,299.67554969423594 +,PR,BOP,DT1.1,C,BE,I,-399.63392949885525 +,NIC,BOP,DT1.1,C,BE,I,299.67554969423594 +,PR,EOP,DT1.1,L,BE,C,-344.7703348639262 +,NIC,EOP,DT1.1,L,BE,C,260.78283172777515 +,ICO,EOP,DT1.1,L,BE,C,8.992511438888796 +,PR,EOP,DT1.1,C,BE,C,-344.42708774007167 +,NIC,EOP,DT1.1,C,BE,C,260.4583180355426 +,ICO,EOP,DT1.1,C,BE,C,8.981321311570435 +,PR,IA,DT1.1,L,BE,I,-0.18299785588431194 +,NIC,IA,DT1.1,L,BE,I,0.10978902238720895 +,PR,IA,DT1.1,C,BE,I,-0.18299785588431194 +,NIC,IA,DT1.1,C,BE,I,0.10978902238720895 +,PR,CF,DT1.1,L,BE,I,110 +,NIC,CF,DT1.1,L,BE,I,-60 +,PR,CF,DT1.1,C,BE,I,110 +,NIC,CF,DT1.1,C,BE,I,-60 +,PR,YCU,DT1.1,C,BE,I,0.3283233358608868 +,NIC,YCU,DT1.1,C,BE,I,-0.22380254636726704 +,PR,IA,DT1.1,L,BE,N,-0.016636168716755634 +,NIC,IA,DT1.1,L,BE,N,0.021957804477441785 +,ICO,IA,DT1.1,L,BE,N,0.005489451119360446 +,PR,IA,DT1.1,C,BE,N,-0.04147659195731423 +,NIC,IA,DT1.1,C,BE,N,0.05473704536112062 +,ICO,IA,DT1.1,C,BE,N,0.013684261340280154 +,PR,CF,DT1.1,L,BE,N,10 +,NIC,CF,DT1.1,L,BE,N,-12 +,ICO,CF,DT1.1,L,BE,N,-3 +,PR,CF,DT1.1,C,BE,N,10 +,NIC,CF,DT1.1,C,BE,N,-12 +,ICO,CF,DT1.1,C,BE,N,-3 +2020,NIC,MC,DT1.2,L,BE,I,-59.93510993884718 +2020,NIC,MC,DT1.2,C,BE,I,-59.93510993884718 +2020,NIC,BOP,DT1.2,L,BE,N,59.93510993884719 +2020,NIC,BOP,DT1.2,C,BE,N,59.83818525115076 +2020,NIC,EV,DT1.2,L,BE,N,44.96255719444399 +2020,NIC,EV,DT1.2,C,BE,N,44.90660655785217 +2020,NIC,BOP,DT1.2,L,BE,I,299.67554969423594 +2020,NIC,BOP,DT1.2,C,BE,I,299.67554969423594 +2020,NIC,EOP,DT1.2,L,BE,C,269.7753431666639 +2020,NIC,EOP,DT1.2,C,BE,C,269.43963934711303 +2020,NIC,IA,DT1.2,L,BE,I,0.10978902238720895 +2020,NIC,IA,DT1.2,C,BE,I,0.10978902238720895 +2020,NIC,CF,DT1.2,L,BE,I,-60 +2020,NIC,CF,DT1.2,C,BE,I,-60 +2020,NIC,YCU,DT1.2,C,BE,I,-0.22380254636726704 +2020,NIC,IA,DT1.2,L,BE,N,0.027447255596802236 +2020,NIC,IA,DT1.2,C,BE,N,0.06842130670140079 +2020,NIC,CF,DT1.2,L,BE,N,-15 +2020,NIC,CF,DT1.2,C,BE,N,-15 +,PR,MC,DT1.3,L,BE,I,-39.963392949885474 +,NIC,MC,DT1.3,L,BE,I,-59.93510993884718 +,PR,MC,DT1.3,C,BE,I,-39.963392949885474 +,NIC,MC,DT1.3,C,BE,I,-59.93510993884718 +,PR,BOP,DT1.3,L,BE,N,-39.963392949885524 +,NIC,BOP,DT1.3,L,BE,N,47.94808795107775 +,ICO,BOP,DT1.3,L,BE,N,11.987021987769438 +,PR,BOP,DT1.3,C,BE,N,-39.908704950657615 +,NIC,BOP,DT1.3,C,BE,N,47.87054820092061 +,ICO,BOP,DT1.3,C,BE,N,11.967637050230152 +,PR,EV,DT1.3,L,BE,N,14.990014559301141 +,NIC,EV,DT1.3,L,BE,N,44.96255719444398 +,PR,EV,DT1.3,C,BE,N,14.975090771307462 +,NIC,EV,DT1.3,C,BE,N,44.906606557852164 +,PR,BOP,DT1.3,L,BE,I,-399.63392949885525 +,NIC,BOP,DT1.3,L,BE,I,299.67554969423594 +,PR,BOP,DT1.3,C,BE,I,-399.63392949885525 +,NIC,BOP,DT1.3,C,BE,I,299.67554969423594 +,PR,EOP,DT1.3,L,BE,C,-344.7703348639262 +,NIC,EOP,DT1.3,L,BE,C,260.78283172777515 +,ICO,EOP,DT1.3,L,BE,C,8.992511438888796 +,PR,EOP,DT1.3,C,BE,C,-344.42708774007167 +,NIC,EOP,DT1.3,C,BE,C,260.4583180355426 +,ICO,EOP,DT1.3,C,BE,C,8.981321311570435 +,PR,IA,DT1.3,L,BE,I,-0.18299785588431194 +,NIC,IA,DT1.3,L,BE,I,0.10978902238720895 +,PR,IA,DT1.3,C,BE,I,-0.18299785588431194 +,NIC,IA,DT1.3,C,BE,I,0.10978902238720895 +,PR,CF,DT1.3,L,BE,I,110 +,NIC,CF,DT1.3,L,BE,I,-60 +,PR,CF,DT1.3,C,BE,I,110 +,NIC,CF,DT1.3,C,BE,I,-60 +,PR,YCU,DT1.3,C,BE,I,0.3283233358608868 +,NIC,YCU,DT1.3,C,BE,I,-0.22380254636726704 +,PR,IA,DT1.3,L,BE,N,-0.016636168716755634 +,NIC,IA,DT1.3,L,BE,N,0.021957804477441785 +,ICO,IA,DT1.3,L,BE,N,0.005489451119360446 +,PR,IA,DT1.3,C,BE,N,-0.04147659195731423 +,NIC,IA,DT1.3,C,BE,N,0.05473704536112062 +,ICO,IA,DT1.3,C,BE,N,0.013684261340280154 +,PR,CF,DT1.3,L,BE,N,10 +,NIC,CF,DT1.3,L,BE,N,-12 +,ICO,CF,DT1.3,L,BE,N,-3 +,PR,CF,DT1.3,C,BE,N,10 +,NIC,CF,DT1.3,C,BE,N,-12 +,ICO,CF,DT1.3,C,BE,N,-3 +,PR,MC,DT2.1,L,BE,I,-39.963392949885474 +,NIC,MC,DT2.1,L,BE,I,-59.93510993884718 +,PR,MC,DT2.1,C,BE,I,-39.963392949885474 +,NIC,MC,DT2.1,C,BE,I,-59.93510993884718 +,PR,BOP,DT2.1,L,BE,N,-39.963392949885524 +,NIC,BOP,DT2.1,L,BE,N,47.94808795107775 +,ICO,BOP,DT2.1,L,BE,N,11.987021987769438 +,PR,BOP,DT2.1,C,BE,N,-39.908704950657615 +,NIC,BOP,DT2.1,C,BE,N,47.87054820092061 +,ICO,BOP,DT2.1,C,BE,N,11.967637050230152 +,PR,EV,DT2.1,L,BE,N,14.990014559301141 +,NIC,EV,DT2.1,L,BE,N,44.96255719444398 +,PR,EV,DT2.1,C,BE,N,14.975090771307462 +,NIC,EV,DT2.1,C,BE,N,44.906606557852164 +,PR,BOP,DT2.1,L,BE,I,-399.63392949885525 +,NIC,BOP,DT2.1,L,BE,I,299.67554969423594 +,PR,BOP,DT2.1,C,BE,I,-399.63392949885525 +,NIC,BOP,DT2.1,C,BE,I,299.67554969423594 +,PR,EOP,DT2.1,L,BE,C,-344.7703348639262 +,NIC,EOP,DT2.1,L,BE,C,260.78283172777515 +,ICO,EOP,DT2.1,L,BE,C,8.992511438888796 +,PR,EOP,DT2.1,C,BE,C,-344.42708774007167 +,NIC,EOP,DT2.1,C,BE,C,260.4583180355426 +,ICO,EOP,DT2.1,C,BE,C,8.981321311570435 +,PR,IA,DT2.1,L,BE,I,-0.18299785588431194 +,NIC,IA,DT2.1,L,BE,I,0.10978902238720895 +,PR,IA,DT2.1,C,BE,I,-0.18299785588431194 +,NIC,IA,DT2.1,C,BE,I,0.10978902238720895 +,PR,CF,DT2.1,L,BE,I,110 +,NIC,CF,DT2.1,L,BE,I,-60 +,PR,CF,DT2.1,C,BE,I,110 +,NIC,CF,DT2.1,C,BE,I,-60 +,PR,YCU,DT2.1,C,BE,I,0.3283233358608868 +,NIC,YCU,DT2.1,C,BE,I,-0.22380254636726704 +,PR,IA,DT2.1,L,BE,N,-0.016636168716755634 +,NIC,IA,DT2.1,L,BE,N,0.021957804477441785 +,ICO,IA,DT2.1,L,BE,N,0.005489451119360446 +,PR,IA,DT2.1,C,BE,N,-0.04147659195731423 +,NIC,IA,DT2.1,C,BE,N,0.05473704536112062 +,ICO,IA,DT2.1,C,BE,N,0.013684261340280154 +,PR,CF,DT2.1,L,BE,N,10 +,NIC,CF,DT2.1,L,BE,N,-12 +,ICO,CF,DT2.1,L,BE,N,-3 +,PR,CF,DT2.1,C,BE,N,10 +,NIC,CF,DT2.1,C,BE,N,-12 +,ICO,CF,DT2.1,C,BE,N,-3 +2020,NIC,MC,DT2.2,L,BE,I,-59.93510993884718 +2020,NIC,MC,DT2.2,C,BE,I,-59.93510993884718 +2020,NIC,BOP,DT2.2,L,BE,N,59.93510993884719 +2020,NIC,BOP,DT2.2,C,BE,N,59.83818525115076 +2020,NIC,EV,DT2.2,L,BE,N,44.96255719444399 +2020,NIC,EV,DT2.2,C,BE,N,44.90660655785217 +2020,NIC,BOP,DT2.2,L,BE,I,299.67554969423594 +2020,NIC,BOP,DT2.2,C,BE,I,299.67554969423594 +2020,NIC,EOP,DT2.2,L,BE,C,269.7753431666639 +2020,NIC,EOP,DT2.2,C,BE,C,269.43963934711303 +2020,NIC,IA,DT2.2,L,BE,I,0.10978902238720895 +2020,NIC,IA,DT2.2,C,BE,I,0.10978902238720895 +2020,NIC,CF,DT2.2,L,BE,I,-60 +2020,NIC,CF,DT2.2,C,BE,I,-60 +2020,NIC,YCU,DT2.2,C,BE,I,-0.22380254636726704 +2020,NIC,IA,DT2.2,L,BE,N,0.027447255596802236 +2020,NIC,IA,DT2.2,C,BE,N,0.06842130670140079 +2020,NIC,CF,DT2.2,L,BE,N,-15 +2020,NIC,CF,DT2.2,C,BE,N,-15 +,PR,MC,DTR1.1,L,BE,I,19.981696474942737 +,NIC,MC,DTR1.1,L,BE,I,29.96755496942359 +,CDR,MC,DTR1.1,L,BE,I,-0.023054320790396418 +,PR,MC,DTR1.1,C,BE,I,19.981696474942737 +,NIC,MC,DTR1.1,C,BE,I,29.96755496942359 +,CDR,MC,DTR1.1,C,BE,I,-0.023054320790396418 +,PR,BOP,DTR1.1,L,BE,N,19.981696474942762 +,NIC,BOP,DTR1.1,L,BE,N,-29.967554969423595 +,CDR,BOP,DTR1.1,L,BE,N,0.29437375980433944 +,PR,BOP,DTR1.1,C,BE,N,19.954352475328808 +,NIC,BOP,DTR1.1,C,BE,N,-29.91909262557538 +,CDR,BOP,DTR1.1,C,BE,N,0.29373948854293713 +,PR,EV,DTR1.1,L,BE,N,-7.4950072796505705 +,NIC,EV,DTR1.1,L,BE,N,-22.481278597221994 +,CDR,EV,DTR1.1,L,BE,N,0.16090924598518777 +,PR,EV,DTR1.1,C,BE,N,-7.487545385653731 +,NIC,EV,DTR1.1,C,BE,N,-22.453303278926086 +,CDR,EV,DTR1.1,C,BE,N,0.16064240608443553 +,PR,BOP,DTR1.1,L,BE,I,199.81696474942763 +,NIC,BOP,DTR1.1,L,BE,I,-149.83777484711797 +,CDR,BOP,DTR1.1,L,BE,I,0.11527160395198197 +,PR,BOP,DTR1.1,C,BE,I,199.81696474942763 +,NIC,BOP,DTR1.1,C,BE,I,-149.83777484711797 +,CDR,BOP,DTR1.1,C,BE,I,0.11527160395198197 +,PR,EOP,DTR1.1,L,BE,C,172.3851674319631 +,NIC,EOP,DTR1.1,L,BE,C,-134.88767158333195 +,CDR,EOP,DTR1.1,L,BE,C,0.9654554759111266 +,PR,EOP,DTR1.1,C,BE,C,172.21354387003583 +,NIC,EOP,DTR1.1,C,BE,C,-134.71981967355651 +,CDR,EOP,DTR1.1,C,BE,C,0.9638544365066131 +,PR,IA,DTR1.1,L,BE,I,0.09149892794215597 +,NIC,IA,DTR1.1,L,BE,I,-0.05489451119360447 +,CDR,IA,DTR1.1,L,BE,I,7.726288250786695E-05 +,PR,IA,DTR1.1,C,BE,I,0.09149892794215597 +,NIC,IA,DTR1.1,C,BE,I,-0.05489451119360447 +,CDR,IA,DTR1.1,C,BE,I,7.726288250786695E-05 +,PR,CF,DTR1.1,L,BE,I,-55 +,NIC,CF,DTR1.1,L,BE,I,30 +,CDR,CF,DTR1.1,L,BE,I,-0.041970417989396935 +,PR,CF,DTR1.1,C,BE,I,-55 +,NIC,CF,DTR1.1,C,BE,I,30 +,CDR,CF,DTR1.1,C,BE,I,-0.041970417989396935 +,PR,YCU,DTR1.1,C,BE,I,-0.1641616679304434 +,NIC,YCU,DTR1.1,C,BE,I,0.11190127318363352 +,CDR,YCU,DTR1.1,C,BE,I,-8.349412781047394E-05 +,CDR,CRU,DTR1.1,L,BE,I,0.5933128558860402 +,CDR,CRU,DTR1.1,C,BE,I,0.5923289904108416 +,PR,IA,DTR1.1,L,BE,N,0.008318084358377817 +,NIC,IA,DTR1.1,L,BE,N,-0.013723627798401118 +,CDR,IA,DTR1.1,L,BE,N,0.0002461342988846482 +,PR,IA,DTR1.1,C,BE,N,0.020738295978657114 +,NIC,IA,DTR1.1,C,BE,N,-0.03421065335070039 +,CDR,IA,DTR1.1,C,BE,N,0.0006135656595298578 +,PR,CF,DTR1.1,L,BE,N,-5 +,NIC,CF,DTR1.1,L,BE,N,7.5 +,CDR,CF,DTR1.1,L,BE,N,-0.1337106481180328 +,PR,CF,DTR1.1,C,BE,N,-5 +,NIC,CF,DTR1.1,C,BE,N,7.5 +,CDR,CF,DTR1.1,C,BE,N,-0.1337106481180328 +2020,NIC,MC,DTR1.2,L,BE,I,29.96755496942359 +2020,CDR,MC,DTR1.2,L,BE,I,-0.023054320790396418 +2020,NIC,MC,DTR1.2,C,BE,I,29.96755496942359 +2020,CDR,MC,DTR1.2,C,BE,I,-0.023054320790396418 +2020,NIC,BOP,DTR1.2,L,BE,N,-29.967554969423595 +2020,CDR,BOP,DTR1.2,L,BE,N,0.29437375980433944 +2020,NIC,BOP,DTR1.2,C,BE,N,-29.91909262557538 +2020,CDR,BOP,DTR1.2,C,BE,N,0.29373948854293713 +2020,NIC,EV,DTR1.2,L,BE,N,-22.481278597221994 +2020,CDR,EV,DTR1.2,L,BE,N,0.16090924598518777 +2020,NIC,EV,DTR1.2,C,BE,N,-22.453303278926086 +2020,CDR,EV,DTR1.2,C,BE,N,0.16064240608443553 +2020,NIC,BOP,DTR1.2,L,BE,I,-149.83777484711797 +2020,CDR,BOP,DTR1.2,L,BE,I,0.11527160395198197 +2020,NIC,BOP,DTR1.2,C,BE,I,-149.83777484711797 +2020,CDR,BOP,DTR1.2,C,BE,I,0.11527160395198197 +2020,NIC,EOP,DTR1.2,L,BE,C,-134.88767158333195 +2020,CDR,EOP,DTR1.2,L,BE,C,0.9654554759111266 +2020,NIC,EOP,DTR1.2,C,BE,C,-134.71981967355651 +2020,CDR,EOP,DTR1.2,C,BE,C,0.9638544365066131 +2020,NIC,IA,DTR1.2,L,BE,I,-0.05489451119360447 +2020,CDR,IA,DTR1.2,L,BE,I,7.726288250786695E-05 +2020,NIC,IA,DTR1.2,C,BE,I,-0.05489451119360447 +2020,CDR,IA,DTR1.2,C,BE,I,7.726288250786695E-05 +2020,NIC,CF,DTR1.2,L,BE,I,30 +2020,CDR,CF,DTR1.2,L,BE,I,-0.041970417989396935 +2020,NIC,CF,DTR1.2,C,BE,I,30 +2020,CDR,CF,DTR1.2,C,BE,I,-0.041970417989396935 +2020,NIC,YCU,DTR1.2,C,BE,I,0.11190127318363352 +2020,CDR,YCU,DTR1.2,C,BE,I,-8.349412781047394E-05 +2020,CDR,CRU,DTR1.2,L,BE,I,0.5933128558860402 +2020,CDR,CRU,DTR1.2,C,BE,I,0.5923289904108416 +2020,NIC,IA,DTR1.2,L,BE,N,-0.013723627798401118 +2020,CDR,IA,DTR1.2,L,BE,N,0.0002461342988846482 +2020,NIC,IA,DTR1.2,C,BE,N,-0.03421065335070039 +2020,CDR,IA,DTR1.2,C,BE,N,0.0006135656595298578 +2020,NIC,CF,DTR1.2,L,BE,N,7.5 +2020,CDR,CF,DTR1.2,L,BE,N,-0.1337106481180328 +2020,NIC,CF,DTR1.2,C,BE,N,7.5 +2020,CDR,CF,DTR1.2,C,BE,N,-0.1337106481180328 +,PR,MC,DTR2.1,L,BE,I,19.981696474942737 +,NIC,MC,DTR2.1,L,BE,I,29.96755496942359 +,CDR,MC,DTR2.1,L,BE,I,-0.023054320790396418 +,PR,MC,DTR2.1,C,BE,I,19.981696474942737 +,NIC,MC,DTR2.1,C,BE,I,29.96755496942359 +,CDR,MC,DTR2.1,C,BE,I,-0.023054320790396418 +,PR,BOP,DTR2.1,L,BE,N,19.981696474942762 +,NIC,BOP,DTR2.1,L,BE,N,-29.967554969423595 +,CDR,BOP,DTR2.1,L,BE,N,0.29437375980433944 +,PR,BOP,DTR2.1,C,BE,N,19.954352475328808 +,NIC,BOP,DTR2.1,C,BE,N,-29.91909262557538 +,CDR,BOP,DTR2.1,C,BE,N,0.29373948854293713 +,PR,EV,DTR2.1,L,BE,N,-7.4950072796505705 +,NIC,EV,DTR2.1,L,BE,N,-22.481278597221994 +,CDR,EV,DTR2.1,L,BE,N,0.16090924598518777 +,PR,EV,DTR2.1,C,BE,N,-7.487545385653731 +,NIC,EV,DTR2.1,C,BE,N,-22.453303278926086 +,CDR,EV,DTR2.1,C,BE,N,0.16064240608443553 +,PR,BOP,DTR2.1,L,BE,I,199.81696474942763 +,NIC,BOP,DTR2.1,L,BE,I,-149.83777484711797 +,CDR,BOP,DTR2.1,L,BE,I,0.11527160395198197 +,PR,BOP,DTR2.1,C,BE,I,199.81696474942763 +,NIC,BOP,DTR2.1,C,BE,I,-149.83777484711797 +,CDR,BOP,DTR2.1,C,BE,I,0.11527160395198197 +,PR,EOP,DTR2.1,L,BE,C,172.3851674319631 +,NIC,EOP,DTR2.1,L,BE,C,-134.88767158333195 +,CDR,EOP,DTR2.1,L,BE,C,0.9654554759111266 +,PR,EOP,DTR2.1,C,BE,C,172.21354387003583 +,NIC,EOP,DTR2.1,C,BE,C,-134.71981967355651 +,CDR,EOP,DTR2.1,C,BE,C,0.9638544365066131 +,PR,IA,DTR2.1,L,BE,I,0.09149892794215597 +,NIC,IA,DTR2.1,L,BE,I,-0.05489451119360447 +,CDR,IA,DTR2.1,L,BE,I,7.726288250786695E-05 +,PR,IA,DTR2.1,C,BE,I,0.09149892794215597 +,NIC,IA,DTR2.1,C,BE,I,-0.05489451119360447 +,CDR,IA,DTR2.1,C,BE,I,7.726288250786695E-05 +,PR,CF,DTR2.1,L,BE,I,-55 +,NIC,CF,DTR2.1,L,BE,I,30 +,CDR,CF,DTR2.1,L,BE,I,-0.041970417989396935 +,PR,CF,DTR2.1,C,BE,I,-55 +,NIC,CF,DTR2.1,C,BE,I,30 +,CDR,CF,DTR2.1,C,BE,I,-0.041970417989396935 +,PR,YCU,DTR2.1,C,BE,I,-0.1641616679304434 +,NIC,YCU,DTR2.1,C,BE,I,0.11190127318363352 +,CDR,YCU,DTR2.1,C,BE,I,-8.349412781047394E-05 +,CDR,CRU,DTR2.1,L,BE,I,0.5933128558860402 +,CDR,CRU,DTR2.1,C,BE,I,0.5923289904108416 +,PR,IA,DTR2.1,L,BE,N,0.008318084358377817 +,NIC,IA,DTR2.1,L,BE,N,-0.013723627798401118 +,CDR,IA,DTR2.1,L,BE,N,0.0002461342988846482 +,PR,IA,DTR2.1,C,BE,N,0.020738295978657114 +,NIC,IA,DTR2.1,C,BE,N,-0.03421065335070039 +,CDR,IA,DTR2.1,C,BE,N,0.0006135656595298578 +,PR,CF,DTR2.1,L,BE,N,-5 +,NIC,CF,DTR2.1,L,BE,N,7.5 +,CDR,CF,DTR2.1,L,BE,N,-0.1337106481180328 +,PR,CF,DTR2.1,C,BE,N,-5 +,NIC,CF,DTR2.1,C,BE,N,7.5 +,CDR,CF,DTR2.1,C,BE,N,-0.1337106481180328 +2020,NIC,MC,DTR2.2,L,BE,I,29.96755496942359 +2020,CDR,MC,DTR2.2,L,BE,I,-0.023054320790396418 +2020,NIC,MC,DTR2.2,C,BE,I,29.96755496942359 +2020,CDR,MC,DTR2.2,C,BE,I,-0.023054320790396418 +2020,NIC,BOP,DTR2.2,L,BE,N,-29.967554969423595 +2020,CDR,BOP,DTR2.2,L,BE,N,0.29437375980433944 +2020,NIC,BOP,DTR2.2,C,BE,N,-29.91909262557538 +2020,CDR,BOP,DTR2.2,C,BE,N,0.29373948854293713 +2020,NIC,EV,DTR2.2,L,BE,N,-22.481278597221994 +2020,CDR,EV,DTR2.2,L,BE,N,0.16090924598518777 +2020,NIC,EV,DTR2.2,C,BE,N,-22.453303278926086 +2020,CDR,EV,DTR2.2,C,BE,N,0.16064240608443553 +2020,NIC,BOP,DTR2.2,L,BE,I,-149.83777484711797 +2020,CDR,BOP,DTR2.2,L,BE,I,0.11527160395198197 +2020,NIC,BOP,DTR2.2,C,BE,I,-149.83777484711797 +2020,CDR,BOP,DTR2.2,C,BE,I,0.11527160395198197 +2020,NIC,EOP,DTR2.2,L,BE,C,-134.88767158333195 +2020,CDR,EOP,DTR2.2,L,BE,C,0.9654554759111266 +2020,NIC,EOP,DTR2.2,C,BE,C,-134.71981967355651 +2020,CDR,EOP,DTR2.2,C,BE,C,0.9638544365066131 +2020,NIC,IA,DTR2.2,L,BE,I,-0.05489451119360447 +2020,CDR,IA,DTR2.2,L,BE,I,7.726288250786695E-05 +2020,NIC,IA,DTR2.2,C,BE,I,-0.05489451119360447 +2020,CDR,IA,DTR2.2,C,BE,I,7.726288250786695E-05 +2020,NIC,CF,DTR2.2,L,BE,I,30 +2020,CDR,CF,DTR2.2,L,BE,I,-0.041970417989396935 +2020,NIC,CF,DTR2.2,C,BE,I,30 +2020,CDR,CF,DTR2.2,C,BE,I,-0.041970417989396935 +2020,NIC,YCU,DTR2.2,C,BE,I,0.11190127318363352 +2020,CDR,YCU,DTR2.2,C,BE,I,-8.349412781047394E-05 +2020,CDR,CRU,DTR2.2,L,BE,I,0.5933128558860402 +2020,CDR,CRU,DTR2.2,C,BE,I,0.5923289904108416 +2020,NIC,IA,DTR2.2,L,BE,N,-0.013723627798401118 +2020,CDR,IA,DTR2.2,L,BE,N,0.0002461342988846482 +2020,NIC,IA,DTR2.2,C,BE,N,-0.03421065335070039 +2020,CDR,IA,DTR2.2,C,BE,N,0.0006135656595298578 +2020,NIC,CF,DTR2.2,L,BE,N,7.5 +2020,CDR,CF,DTR2.2,L,BE,N,-0.1337106481180328 +2020,NIC,CF,DTR2.2,C,BE,N,7.5 +2020,CDR,CF,DTR2.2,C,BE,N,-0.1337106481180328 +,PR,MC,DT3.1,L,BE,I,-39.963392949885474 +,NIC,MC,DT3.1,L,BE,I,-59.93510993884718 +,PR,MC,DT3.1,C,BE,I,-39.963392949885474 +,NIC,MC,DT3.1,C,BE,I,-59.93510993884718 +,PR,BOP,DT3.1,L,BE,N,-39.963392949885524 +,NIC,BOP,DT3.1,L,BE,N,47.94808795107775 +,ICO,BOP,DT3.1,L,BE,N,11.987021987769438 +,PR,BOP,DT3.1,C,BE,N,-39.908704950657615 +,NIC,BOP,DT3.1,C,BE,N,47.87054820092061 +,ICO,BOP,DT3.1,C,BE,N,11.967637050230152 +,PR,EV,DT3.1,L,BE,N,14.990014559301141 +,NIC,EV,DT3.1,L,BE,N,44.96255719444398 +,PR,EV,DT3.1,C,BE,N,14.975090771307462 +,NIC,EV,DT3.1,C,BE,N,44.906606557852164 +,PR,CL,DT3.1,L,BE,C,344.77033486392617 +,NIC,CL,DT3.1,L,BE,C,-260.78283172777515 +,ICO,CL,DT3.1,L,BE,C,-8.992511438888796 +,PR,CL,DT3.1,C,BE,C,344.4270877400716 +,NIC,CL,DT3.1,C,BE,C,-260.45831803554256 +,ICO,CL,DT3.1,C,BE,C,-8.981321311570435 +,PR,BOP,DT3.1,L,BE,I,-399.63392949885525 +,NIC,BOP,DT3.1,L,BE,I,299.67554969423594 +,PR,BOP,DT3.1,C,BE,I,-399.63392949885525 +,NIC,BOP,DT3.1,C,BE,I,299.67554969423594 +,PR,IA,DT3.1,L,BE,I,-0.18299785588431194 +,NIC,IA,DT3.1,L,BE,I,0.10978902238720895 +,PR,IA,DT3.1,C,BE,I,-0.18299785588431194 +,NIC,IA,DT3.1,C,BE,I,0.10978902238720895 +,PR,CF,DT3.1,L,BE,I,110 +,NIC,CF,DT3.1,L,BE,I,-60 +,PR,CF,DT3.1,C,BE,I,110 +,NIC,CF,DT3.1,C,BE,I,-60 +,PR,YCU,DT3.1,C,BE,I,0.3283233358608868 +,NIC,YCU,DT3.1,C,BE,I,-0.22380254636726704 +,PR,IA,DT3.1,L,BE,N,-0.016636168716755634 +,NIC,IA,DT3.1,L,BE,N,0.021957804477441785 +,ICO,IA,DT3.1,L,BE,N,0.005489451119360446 +,PR,IA,DT3.1,C,BE,N,-0.04147659195731423 +,NIC,IA,DT3.1,C,BE,N,0.05473704536112062 +,ICO,IA,DT3.1,C,BE,N,0.013684261340280154 +,PR,CF,DT3.1,L,BE,N,10 +,NIC,CF,DT3.1,L,BE,N,-12 +,ICO,CF,DT3.1,L,BE,N,-3 +,PR,CF,DT3.1,C,BE,N,10 +,NIC,CF,DT3.1,C,BE,N,-12 +,ICO,CF,DT3.1,C,BE,N,-3 +,PR,MC,DT4.1,L,BE,I,-39.963392949885474 +,NIC,MC,DT4.1,L,BE,I,-59.93510993884718 +,PR,MC,DT4.1,C,BE,I,-39.963392949885474 +,NIC,MC,DT4.1,C,BE,I,-59.93510993884718 +,PR,BOP,DT4.1,L,BE,N,-79.92678589977105 +,NIC,BOP,DT4.1,L,BE,N,47.94808795107775 +,ICO,BOP,DT4.1,L,BE,N,11.987021987769438 +,PR,BOP,DT4.1,C,BE,N,-79.81740990131523 +,NIC,BOP,DT4.1,C,BE,N,47.87054820092061 +,ICO,BOP,DT4.1,C,BE,N,11.967637050230152 +,PR,EV,DT4.1,L,BE,N,-38.97403785418295 +,NIC,EV,DT4.1,L,BE,N,44.96255719444398 +,PR,EV,DT4.1,C,BE,N,-38.93523600539941 +,NIC,EV,DT4.1,C,BE,N,44.906606557852164 +,PR,BOP,DT4.1,L,BE,I,-399.63392949885525 +,NIC,BOP,DT4.1,L,BE,I,299.67554969423594 +,PR,BOP,DT4.1,C,BE,I,-399.63392949885525 +,NIC,BOP,DT4.1,C,BE,I,299.67554969423594 +,PR,EOP,DT4.1,L,BE,C,-428.7144163960126 +,NIC,EOP,DT4.1,L,BE,C,260.78283172777515 +,ICO,EOP,DT4.1,L,BE,C,8.992511438888796 +,PR,EOP,DT4.1,C,BE,C,-428.2875960593934 +,NIC,EOP,DT4.1,C,BE,C,260.4583180355426 +,ICO,EOP,DT4.1,C,BE,C,8.981321311570435 +,PR,IA,DT4.1,L,BE,I,-0.18299785588431194 +,NIC,IA,DT4.1,L,BE,I,0.10978902238720895 +,PR,IA,DT4.1,C,BE,I,-0.18299785588431194 +,NIC,IA,DT4.1,C,BE,I,0.10978902238720895 +,PR,CF,DT4.1,L,BE,I,110 +,NIC,CF,DT4.1,L,BE,I,-60 +,PR,CF,DT4.1,C,BE,I,110 +,NIC,CF,DT4.1,C,BE,I,-60 +,PR,YCU,DT4.1,C,BE,I,0.3283233358608868 +,NIC,YCU,DT4.1,C,BE,I,-0.22380254636726704 +,PR,IA,DT4.1,L,BE,N,-0.03327233743351127 +,NIC,IA,DT4.1,L,BE,N,0.021957804477441785 +,ICO,IA,DT4.1,L,BE,N,0.005489451119360446 +,PR,IA,DT4.1,C,BE,N,-0.08295318391462846 +,NIC,IA,DT4.1,C,BE,N,0.05473704536112062 +,ICO,IA,DT4.1,C,BE,N,0.013684261340280154 +,PR,CF,DT4.1,L,BE,N,20 +,NIC,CF,DT4.1,L,BE,N,-12 +,ICO,CF,DT4.1,L,BE,N,-3 +,PR,CF,DT4.1,C,BE,N,20 +,NIC,CF,DT4.1,C,BE,N,-12 +,ICO,CF,DT4.1,C,BE,N,-3 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv new file mode 100644 index 00000000..61c6344a --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv @@ -0,0 +1,16 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@BEPA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,CF,DT1.1,L,BEPA,I,88 +,PR,CF,DT1.1,L,BEPA,N,8 +,PR,CF,DT1.3,L,BEPA,I,110 +,PR,CF,DT1.3,L,BEPA,N,10 +,PR,CF,DT2.1,L,BEPA,I,88 +,PR,CF,DT2.1,L,BEPA,N,8 +,PR,CF,DT3.1,L,BEPA,I,88 +,PR,CF,DT3.1,L,BEPA,N,8 +,PR,CF,DT4.1,L,BEPA,I,88 +,PR,CF,DT4.1,L,BEPA,N,16 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv new file mode 100644 index 00000000..965e5e6f --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv @@ -0,0 +1,55 @@ +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@C +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,CL,DT2.1,,C,C,-87.43135554903122 +,,IA,DT2.1,,C,I,0.09388697662967685 +,,MC,DT2.1,,C,I,105.89201388261736 +,,EOP,DT2.1,,C,C,18.374757965777995 +,,AM,DT2.1,,C,C,-38.60249856533708 +,,EA,DT2.1,,C,C,-43.599999999999994 +,,BOP,DT2.1,,C,I,82.02271122089925 +,,CL,DT1.3,,C,C,-87.43135554903122 +,,BOP,DT1.1,,C,I,82.02271122089925 +,,EA,DT1.1,,C,C,-43.599999999999994 +,,AM,DT1.1,,C,C,-38.60249856533708 +,,EOP,DT1.1,,C,C,18.374757965777995 +,,MC,DT1.1,,C,I,105.89201388261736 +,,IA,DT1.1,,C,I,0.09388697662967685 +,,CL,DT1.1,,C,C,-87.43135554903122 +,,BOP,DT1.3,,C,I,82.02271122089925 +,,EA,DT1.3,,C,C,-50 +,,AM,DT1.3,,C,C,-34.26645281902704 +,,EOP,DT1.3,,C,C,16.31080371208803 +,,MC,DT1.3,,C,I,105.89201388261736 +,,IA,DT1.3,,C,I,0.09388697662967685 +,,BOP,DTR1.1,,C,I,-46.24958203305145 +,,AM,DTR1.1,,C,C,38.316584766326955 +,,EOP,DTR1.1,,C,C,-18.238663229656325 +,,MC,DTR1.1,,C,I,-52.92295262051829 +,,IA,DTR1.1,,C,I,-0.04954912095471157 +,,CRU,DTR1.1,,C,I,-0.5933128558860402 +,,CL,DTR1.1,,C,C,43.26014863442721 +,,BOP,DTR2.1,,C,I,-46.24958203305145 +,,AM,DTR2.1,,C,C,38.316584766326955 +,,EOP,DTR2.1,,C,C,-18.238663229656325 +,,MC,DTR2.1,,C,I,-52.92295262051829 +,,IA,DTR2.1,,C,I,-0.04954912095471157 +,,CRU,DTR2.1,,C,I,-0.5933128558860402 +,,CL,DTR2.1,,C,C,43.26014863442721 +,,BOP,DT3.1,,C,I,129.49726655304642 +,,EA,DT3.1,,C,C,-43.599999999999994 +,,AM,DT3.1,,C,C,-51.96181825867143 +,,MC,DT3.1,,C,I,105.89201388261736 +,,IA,DT3.1,,C,I,0.11760647207910604 +,,CL,DT3.1,,C,C,-139.94506864907146 +,,BOP,DT4.1,,C,I,82.02271122089925 +,,EA,DT4.1,,C,C,-51.599999999999994 +,,AM,DT4.1,,C,C,-96.83022811966929 +,,EOP,DT4.1,,C,C,46.091109943532146 +,,MC,DT4.1,,C,I,105.89201388261736 +,,IA,DT4.1,,C,I,0.09388697662967685 +,,BOP,DT4.1,,C,N,8.004653973154419 +,,IA,DT4.1,,C,N,0.0003356307173485902 +,,EV,DT4.1,,C,N,-1.4922636208166304 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv new file mode 100644 index 00000000..437c7cf1 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv @@ -0,0 +1,25 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@DA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,EOP,DT2.1,,DA,C,-8.011834360099684 +,,AM,DT2.1,,DA,C,16.831613508459697 +,,BOP,DT2.1,,DA,I,-9.843447868559382 +,,CF,DT2.1,,DA,C,-15 +,,CF,DT1.1,,DA,C,-15 +,,BOP,DT1.1,,DA,I,-9.843447868559382 +,,AM,DT1.1,,DA,C,16.831613508459697 +,,EOP,DT1.1,,DA,C,-8.011834360099684 +,,CF,DT1.3,,DA,C,-15 +,,BOP,DT1.3,,DA,I,-9.843447868559382 +,,AM,DT1.3,,DA,C,16.831613508459697 +,,EOP,DT1.3,,DA,C,-8.011834360099684 +,,CF,DT3.1,,DA,C,-15 +,,BOP,DT3.1,,DA,I,-9.843447868559382 +,,AM,DT3.1,,DA,C,24.84344786855938 +,,CF,DT4.1,,DA,C,-15 +,,BOP,DT4.1,,DA,I,-9.843447868559382 +,,AM,DT4.1,,DA,C,16.831613508459697 +,,EOP,DT4.1,,DA,C,-8.011834360099684 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv new file mode 100644 index 00000000..c443cf93 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv @@ -0,0 +1,17 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@F +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,AM,DT1.1,L,F,C,0.6775071478609433 +,,AM,DT1.2,L,F,C,1 +,,AM,DT1.3,L,F,C,0.6775071478609433 +,,AM,DT2.1,L,F,C,0.6775071478609433 +,,AM,DT2.2,L,F,C,1 +,,AM,DTR1.1,L,F,C,0.6775071478609433 +,,AM,DTR1.2,L,F,C,1 +,,AM,DTR2.1,L,F,C,0.6775071478609433 +,,AM,DTR2.2,L,F,C,1 +,,AM,DT3.1,L,F,C,1 +,,AM,DT4.1,L,F,C,0.6775071478609433 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv new file mode 100644 index 00000000..b4ae0c7e --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv @@ -0,0 +1,22 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@L +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,CL,DT2.1,,L,C,-87.43135554903122 +,,EV,DT2.1,,L,N,55.45631603430072 +,,IA,DT2.1,,L,N,0.016300537999407044 +,,BOP,DT2.1,,L,N,31.958738976731105 +,,CL,DT1.3,,L,C,-87.43135554903122 +,,EV,DT1.1,,L,N,55.45631603430072 +,,BOP,DT1.1,,L,N,31.958738976731105 +,,IA,DT1.1,,L,N,0.016300537999407044 +,,CL,DT1.1,,L,C,-87.43135554903122 +,,BOP,DT1.3,,L,N,31.958738976731105 +,,IA,DT1.3,,L,N,0.016300537999407044 +,,EV,DT1.3,,L,N,55.45631603430072 +,,BOP,DT3.1,,L,N,31.958738976731105 +,,IA,DT3.1,,L,N,0.016300537999407044 +,,EV,DT3.1,,L,N,55.45631603430072 +,,CL,DT3.1,,L,C,-87.43135554903122 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv new file mode 100644 index 00000000..93205b6d --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv @@ -0,0 +1,13 @@ +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@LR +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,BOP,DTR1.1,,LR,N,-15.684995728561214 +,,IA,DTR1.1,,LR,N,-0.007904134700818875 +,,EV,DTR1.1,,LR,N,-27.56724877116518 +,,CL,DTR1.1,,LR,C,43.26014863442721 +,,BOP,DTR2.1,,LR,N,-15.684995728561214 +,,IA,DTR2.1,,LR,N,-0.007904134700818875 +,,EV,DTR2.1,,LR,N,-27.56724877116518 +,,CL,DTR2.1,,LR,C,43.26014863442721 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv new file mode 100644 index 00000000..0b556852 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv @@ -0,0 +1,26 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@OA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,EOP,DT2.1,,OA,C,1 +,PR,CF,DT2.1,,OA,C,3 +,PR,WO,DT2.1,,OA,C,-2 +,PR,WO,DT1.1,,OA,C,-2 +,PR,CF,DT1.1,,OA,C,3 +,PR,EOP,DT1.1,,OA,C,1 +,PR,WO,DT1.3,,OA,C,-2 +,PR,CF,DT1.3,,OA,C,3 +,PR,EOP,DT1.3,,OA,C,1 +,PR,CF,DTR1.1,,OA,C,-1.5 +,PR,EOP,DTR1.1,,OA,C,-1.5 +,PR,CF,DTR2.1,,OA,C,-1.5 +,PR,EOP,DTR2.1,,OA,C,-1.5 +,PR,WO,DT3.1,,OA,C,-2 +,PR,CF,DT3.1,,OA,C,3 +,PR,BOP,DT3.1,,OA,I,1.5 +,PR,EOP,DT3.1,,OA,C,2.5 +,PR,WO,DT4.1,,OA,C,-2 +,PR,CF,DT4.1,,OA,C,3 +,PR,EOP,DT4.1,,OA,C,1 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv new file mode 100644 index 00000000..8e8b0328 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv @@ -0,0 +1,11 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@OAPA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,CF,DT2.1,,OAPA,C,2.4000000000000004 +,PR,CF,DT1.1,,OAPA,C,2.4000000000000004 +,PR,CF,DT1.3,,OAPA,C,3 +,PR,CF,DT3.1,,OAPA,C,2.4000000000000004 +,PR,CF,DT4.1,,OAPA,C,2.4000000000000004 \ No newline at end of file diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv new file mode 100644 index 00000000..8009c335 --- /dev/null +++ b/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv @@ -0,0 +1,215 @@ +$$Default +@@Main +Month,ReportingNode,Scenario,Year +3,CH,,2021 +@@RA +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,,MC,DT1.1,C,RA,I,-5.993510993884719 +,,MC,DT1.1,L,RA,I,-5.993510993884719 +,,BOP,DT1.1,C,RA,N,11.967637050230152 +,,BOP,DT1.1,L,RA,N,11.987021987769438 +,,EV,DT1.1,C,RA,N,-4.490660655785217 +,,EV,DT1.1,L,RA,N,-4.496255719444398 +,,BOP,DT1.1,C,RA,I,29.967554969423595 +,,BOP,DT1.1,L,RA,I,29.967554969423595 +,,EOP,DT1.1,C,RA,C,22.453303278926086 +,,EOP,DT1.1,L,RA,C,22.481278597221994 +,,IA,DT1.1,C,RA,I,0.010978902238720892 +,,IA,DT1.1,L,RA,I,0.010978902238720892 +,,CF,DT1.1,C,RA,I,-6 +,,CF,DT1.1,L,RA,I,-6 +,,YCU,DT1.1,C,RA,I,-0.02238025463672244 +,,IA,DT1.1,C,RA,N,0.013684261340280154 +,,IA,DT1.1,L,RA,N,0.005489451119360446 +,,CF,DT1.1,C,RA,N,-3 +,,CF,DT1.1,L,RA,N,-3 +2020,,MC,DT1.2,C,RA,I,-5.993510993884719 +2020,,MC,DT1.2,L,RA,I,-5.993510993884719 +2020,,BOP,DT1.2,C,RA,N,11.967637050230152 +2020,,BOP,DT1.2,L,RA,N,11.987021987769438 +2020,,EV,DT1.2,C,RA,N,-4.490660655785217 +2020,,EV,DT1.2,L,RA,N,-4.496255719444398 +2020,,BOP,DT1.2,C,RA,I,29.967554969423595 +2020,,BOP,DT1.2,L,RA,I,29.967554969423595 +2020,,EOP,DT1.2,C,RA,C,22.453303278926086 +2020,,EOP,DT1.2,L,RA,C,22.481278597221994 +2020,,IA,DT1.2,C,RA,I,0.010978902238720892 +2020,,IA,DT1.2,L,RA,I,0.010978902238720892 +2020,,CF,DT1.2,C,RA,I,-6 +2020,,CF,DT1.2,L,RA,I,-6 +2020,,YCU,DT1.2,C,RA,I,-0.02238025463672244 +2020,,IA,DT1.2,C,RA,N,0.013684261340280154 +2020,,IA,DT1.2,L,RA,N,0.005489451119360446 +2020,,CF,DT1.2,C,RA,N,-3 +2020,,CF,DT1.2,L,RA,N,-3 +,,MC,DT1.3,C,RA,I,-5.993510993884719 +,,MC,DT1.3,L,RA,I,-5.993510993884719 +,,BOP,DT1.3,C,RA,N,11.967637050230152 +,,BOP,DT1.3,L,RA,N,11.987021987769438 +,,EV,DT1.3,C,RA,N,-4.490660655785217 +,,EV,DT1.3,L,RA,N,-4.496255719444398 +,,BOP,DT1.3,C,RA,I,29.967554969423595 +,,BOP,DT1.3,L,RA,I,29.967554969423595 +,,EOP,DT1.3,C,RA,C,22.453303278926086 +,,EOP,DT1.3,L,RA,C,22.481278597221994 +,,IA,DT1.3,C,RA,I,0.010978902238720892 +,,IA,DT1.3,L,RA,I,0.010978902238720892 +,,CF,DT1.3,C,RA,I,-6 +,,CF,DT1.3,L,RA,I,-6 +,,YCU,DT1.3,C,RA,I,-0.02238025463672244 +,,IA,DT1.3,C,RA,N,0.013684261340280154 +,,IA,DT1.3,L,RA,N,0.005489451119360446 +,,CF,DT1.3,C,RA,N,-3 +,,CF,DT1.3,L,RA,N,-3 +,,MC,DT2.1,C,RA,I,-5.993510993884719 +,,MC,DT2.1,L,RA,I,-5.993510993884719 +,,BOP,DT2.1,C,RA,N,11.967637050230152 +,,BOP,DT2.1,L,RA,N,11.987021987769438 +,,EV,DT2.1,C,RA,N,-4.490660655785217 +,,EV,DT2.1,L,RA,N,-4.496255719444398 +,,BOP,DT2.1,C,RA,I,29.967554969423595 +,,BOP,DT2.1,L,RA,I,29.967554969423595 +,,EOP,DT2.1,C,RA,C,22.453303278926086 +,,EOP,DT2.1,L,RA,C,22.481278597221994 +,,IA,DT2.1,C,RA,I,0.010978902238720892 +,,IA,DT2.1,L,RA,I,0.010978902238720892 +,,CF,DT2.1,C,RA,I,-6 +,,CF,DT2.1,L,RA,I,-6 +,,YCU,DT2.1,C,RA,I,-0.02238025463672244 +,,IA,DT2.1,C,RA,N,0.013684261340280154 +,,IA,DT2.1,L,RA,N,0.005489451119360446 +,,CF,DT2.1,C,RA,N,-3 +,,CF,DT2.1,L,RA,N,-3 +2020,,MC,DT2.2,C,RA,I,-5.993510993884719 +2020,,MC,DT2.2,L,RA,I,-5.993510993884719 +2020,,BOP,DT2.2,C,RA,N,11.967637050230152 +2020,,BOP,DT2.2,L,RA,N,11.987021987769438 +2020,,EV,DT2.2,C,RA,N,-4.490660655785217 +2020,,EV,DT2.2,L,RA,N,-4.496255719444398 +2020,,BOP,DT2.2,C,RA,I,29.967554969423595 +2020,,BOP,DT2.2,L,RA,I,29.967554969423595 +2020,,EOP,DT2.2,C,RA,C,22.453303278926086 +2020,,EOP,DT2.2,L,RA,C,22.481278597221994 +2020,,IA,DT2.2,C,RA,I,0.010978902238720892 +2020,,IA,DT2.2,L,RA,I,0.010978902238720892 +2020,,CF,DT2.2,C,RA,I,-6 +2020,,CF,DT2.2,L,RA,I,-6 +2020,,YCU,DT2.2,C,RA,I,-0.02238025463672244 +2020,,IA,DT2.2,C,RA,N,0.013684261340280154 +2020,,IA,DT2.2,L,RA,N,0.005489451119360446 +2020,,CF,DT2.2,C,RA,N,-3 +2020,,CF,DT2.2,L,RA,N,-3 +,,MC,DTR1.1,C,RA,I,2.9967554969423595 +,,MC,DTR1.1,L,RA,I,2.9967554969423595 +,,BOP,DTR1.1,C,RA,N,-5.983818525115076 +,,BOP,DTR1.1,L,RA,N,-5.993510993884719 +,,EV,DTR1.1,C,RA,N,2.2453303278926087 +,,EV,DTR1.1,L,RA,N,2.248127859722199 +,,BOP,DTR1.1,C,RA,I,-14.983777484711798 +,,BOP,DTR1.1,L,RA,I,-14.983777484711798 +,,EOP,DTR1.1,C,RA,C,-11.226651639463043 +,,EOP,DTR1.1,L,RA,C,-11.240639298610997 +,,IA,DTR1.1,C,RA,I,-0.005489451119360446 +,,IA,DTR1.1,L,RA,I,-0.005489451119360446 +,,CF,DTR1.1,C,RA,I,3 +,,CF,DTR1.1,L,RA,I,3 +,,YCU,DTR1.1,C,RA,I,0.01119012731836122 +,,IA,DTR1.1,C,RA,N,-0.006842130670140077 +,,IA,DTR1.1,L,RA,N,-0.002744725559680223 +,,CF,DTR1.1,C,RA,N,1.5 +,,CF,DTR1.1,L,RA,N,1.5 +2020,,MC,DTR1.2,C,RA,I,2.9967554969423595 +2020,,MC,DTR1.2,L,RA,I,2.9967554969423595 +2020,,BOP,DTR1.2,C,RA,N,-5.983818525115076 +2020,,BOP,DTR1.2,L,RA,N,-5.993510993884719 +2020,,EV,DTR1.2,C,RA,N,2.2453303278926087 +2020,,EV,DTR1.2,L,RA,N,2.248127859722199 +2020,,BOP,DTR1.2,C,RA,I,-14.983777484711798 +2020,,BOP,DTR1.2,L,RA,I,-14.983777484711798 +2020,,EOP,DTR1.2,C,RA,C,-11.226651639463043 +2020,,EOP,DTR1.2,L,RA,C,-11.240639298610997 +2020,,IA,DTR1.2,C,RA,I,-0.005489451119360446 +2020,,IA,DTR1.2,L,RA,I,-0.005489451119360446 +2020,,CF,DTR1.2,C,RA,I,3 +2020,,CF,DTR1.2,L,RA,I,3 +2020,,YCU,DTR1.2,C,RA,I,0.01119012731836122 +2020,,IA,DTR1.2,C,RA,N,-0.006842130670140077 +2020,,IA,DTR1.2,L,RA,N,-0.002744725559680223 +2020,,CF,DTR1.2,C,RA,N,1.5 +2020,,CF,DTR1.2,L,RA,N,1.5 +,,MC,DTR2.1,C,RA,I,2.9967554969423595 +,,MC,DTR2.1,L,RA,I,2.9967554969423595 +,,BOP,DTR2.1,C,RA,N,-5.983818525115076 +,,BOP,DTR2.1,L,RA,N,-5.993510993884719 +,,EV,DTR2.1,C,RA,N,2.2453303278926087 +,,EV,DTR2.1,L,RA,N,2.248127859722199 +,,BOP,DTR2.1,C,RA,I,-14.983777484711798 +,,BOP,DTR2.1,L,RA,I,-14.983777484711798 +,,EOP,DTR2.1,C,RA,C,-11.226651639463043 +,,EOP,DTR2.1,L,RA,C,-11.240639298610997 +,,IA,DTR2.1,C,RA,I,-0.005489451119360446 +,,IA,DTR2.1,L,RA,I,-0.005489451119360446 +,,CF,DTR2.1,C,RA,I,3 +,,CF,DTR2.1,L,RA,I,3 +,,YCU,DTR2.1,C,RA,I,0.01119012731836122 +,,IA,DTR2.1,C,RA,N,-0.006842130670140077 +,,IA,DTR2.1,L,RA,N,-0.002744725559680223 +,,CF,DTR2.1,C,RA,N,1.5 +,,CF,DTR2.1,L,RA,N,1.5 +2020,,MC,DTR2.2,C,RA,I,2.9967554969423595 +2020,,MC,DTR2.2,L,RA,I,2.9967554969423595 +2020,,BOP,DTR2.2,C,RA,N,-5.983818525115076 +2020,,BOP,DTR2.2,L,RA,N,-5.993510993884719 +2020,,EV,DTR2.2,C,RA,N,2.2453303278926087 +2020,,EV,DTR2.2,L,RA,N,2.248127859722199 +2020,,BOP,DTR2.2,C,RA,I,-14.983777484711798 +2020,,BOP,DTR2.2,L,RA,I,-14.983777484711798 +2020,,EOP,DTR2.2,C,RA,C,-11.226651639463043 +2020,,EOP,DTR2.2,L,RA,C,-11.240639298610997 +2020,,IA,DTR2.2,C,RA,I,-0.005489451119360446 +2020,,IA,DTR2.2,L,RA,I,-0.005489451119360446 +2020,,CF,DTR2.2,C,RA,I,3 +2020,,CF,DTR2.2,L,RA,I,3 +2020,,YCU,DTR2.2,C,RA,I,0.01119012731836122 +2020,,IA,DTR2.2,C,RA,N,-0.006842130670140077 +2020,,IA,DTR2.2,L,RA,N,-0.002744725559680223 +2020,,CF,DTR2.2,C,RA,N,1.5 +2020,,CF,DTR2.2,L,RA,N,1.5 +,,MC,DT3.1,C,RA,I,-5.993510993884719 +,,MC,DT3.1,L,RA,I,-5.993510993884719 +,,BOP,DT3.1,C,RA,N,11.967637050230152 +,,BOP,DT3.1,L,RA,N,11.987021987769438 +,,EV,DT3.1,C,RA,N,-4.490660655785217 +,,EV,DT3.1,L,RA,N,-4.496255719444398 +,,CL,DT3.1,C,RA,C,-22.453303278926086 +,,CL,DT3.1,L,RA,C,-22.48127859722199 +,,BOP,DT3.1,C,RA,I,29.967554969423595 +,,BOP,DT3.1,L,RA,I,29.967554969423595 +,,IA,DT3.1,C,RA,I,0.010978902238720892 +,,IA,DT3.1,L,RA,I,0.010978902238720892 +,,CF,DT3.1,C,RA,I,-6 +,,CF,DT3.1,L,RA,I,-6 +,,YCU,DT3.1,C,RA,I,-0.02238025463672244 +,,IA,DT3.1,C,RA,N,0.013684261340280154 +,,IA,DT3.1,L,RA,N,0.005489451119360446 +,,CF,DT3.1,C,RA,N,-3 +,,CF,DT3.1,L,RA,N,-3 +,,MC,DT4.1,C,RA,I,-5.993510993884719 +,,MC,DT4.1,L,RA,I,-5.993510993884719 +,,BOP,DT4.1,C,RA,N,11.967637050230152 +,,BOP,DT4.1,L,RA,N,11.987021987769438 +,,EV,DT4.1,C,RA,N,-4.490660655785217 +,,EV,DT4.1,L,RA,N,-4.496255719444398 +,,BOP,DT4.1,C,RA,I,29.967554969423595 +,,BOP,DT4.1,L,RA,I,29.967554969423595 +,,EOP,DT4.1,C,RA,C,22.453303278926086 +,,EOP,DT4.1,L,RA,C,22.481278597221994 +,,IA,DT4.1,C,RA,I,0.010978902238720892 +,,IA,DT4.1,L,RA,I,0.010978902238720892 +,,CF,DT4.1,C,RA,I,-6 +,,CF,DT4.1,L,RA,I,-6 +,,YCU,DT4.1,C,RA,I,-0.02238025463672244 +,,IA,DT4.1,C,RA,N,0.013684261340280154 +,,IA,DT4.1,L,RA,N,0.005489451119360446 +,,CF,DT4.1,C,RA,N,-3 +,,CF,DT4.1,L,RA,N,-3 \ No newline at end of file diff --git a/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv b/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv new file mode 100644 index 00000000..8b78df02 --- /dev/null +++ b/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv @@ -0,0 +1,537 @@ +@@ReportVariable +AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateType,FunctionalCurrency,GroupOfContract,InitialProfitability,IsReinsurance,LiabilityType,LineOfBusiness,Novelty,OciType,Partner,Portfolio,Projection,ReportingNode,Scenario,ValuationApproach,Value,VariableType +0,PR,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,400,CF +0,NIC,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-280,CF +0,ACA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,400,IR1 +0,NIC,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-280,ISE2 +0,AEA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,ISE4 +0,PR,2020,USD,,APA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-320,IR6 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-798.536731161375,BOP +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,400,CF +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-300,CF +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,400,CF +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-300,CF +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-399.63392949885554,EOP +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,1.0971983374806105,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.9226050955731167,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,398.536731161375,IR5 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-298.7529445986629,IR5 +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-399.6339294988556,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,OCI1 +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,399.6339294988556,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-299.675549694236,OCI1 +0,PR,2020,USD,L,BEPA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,320,IR6 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,139.90849210284577,BOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,EA +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.08233273235018213,IA +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.08233273235018213,IFIE1 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-124.90849210284577,IR5 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-9.843447868559382,EOP +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,IR4 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09226050955731169,IFIE1 +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-29.875294459866303,IR5 +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,OCI1 +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-29.967554969423617,OCI1 +2020,NIC,2020,USD,,A,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-280,CF +2020,NIC,2020,USD,,A,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-280,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,598.7529445986629,BOP +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,598.7529445986629,BOP +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-300,CF +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-300,CF +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,EOP +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,EOP +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.9226050955731167,IA +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.9226050955731167,IA +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-0.9226050955731167,IFIE2 +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-298.7529445986629,ISE12 +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-299.675549694236,OCI2 +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,EOP +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,EOP +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.09226050955731169,IA +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.09226050955731169,IA +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09226050955731169,IFIE2 +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-29.875294459866303,ISE12 +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,OCI2 +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-29.967554969423617,OCI2 +0,AEA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,CF +0,ACA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,CF +0,NIC,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-280,CF +0,PR,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,400,CF +0,PR,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,400,IR1 +0,NIC,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-280,ISE2 +0,AEA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,ISE4 +0,PR,2020,USD,,APA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-400,IR6 +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,400,CF +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-300,CF +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,400,CF +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-300,CF +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,1.0971983374806105,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.9226050955731167,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,398.536731161375,IR5 +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-298.7529445986629,IR5 +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-399.6339294988556,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,299.675549694236,OCI1 +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,399.6339294988556,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-299.675549694236,OCI1 +0,PR,2020,USD,L,BEPA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,400,IR6 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,139.90849210284577,BOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,EA +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.08233273235018213,IA +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.08233273235018213,IFIE1 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-124.90849210284577,IR5 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-9.843447868559382,EOP +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,IR4 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09226050955731169,IFIE1 +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-29.875294459866303,IR5 +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,29.967554969423617,OCI1 +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-29.967554969423617,OCI1 +0,PR,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,400,CF +0,NIC,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-280,CF +0,ACA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,400,IR1 +0,NIC,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-280,ISE2 +0,AEA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-10,ISE4 +0,PR,2020,USD,,APA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-320,IR6 +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,400,CF +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-300,CF +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,400,CF +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-300,CF +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,1.0971983374806105,IFIE1 +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.9226050955731167,IFIE1 +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,398.536731161375,IR5 +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-298.7529445986629,IR5 +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 +0,PR,2020,USD,L,BEPA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,320,IR6 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,139.90849210284577,BOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-15,EA +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.08233273235018213,IA +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.08233273235018213,IFIE1 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-124.90849210284577,IR5 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-9.843447868559382,EOP +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,5.156552131440618,IR4 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-30,CF +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-30,CF +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.09226050955731169,IFIE1 +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-29.875294459866303,IR5 +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 +2020,NIC,2020,USD,,A,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-280,CF +2020,NIC,2020,USD,,A,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-280,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,598.7529445986629,BOP +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,598.7529445986629,BOP +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-300,CF +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-300,CF +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,299.675549694236,EOP +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,299.675549694236,EOP +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.9226050955731167,IA +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.9226050955731167,IA +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-0.9226050955731167,IFIE2 +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-298.7529445986629,ISE12 +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,0,OCI2 +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,59.8752944598663,BOP +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,59.8752944598663,BOP +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-30,CF +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-30,CF +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,29.967554969423617,EOP +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,29.967554969423617,EOP +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.09226050955731169,IA +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.09226050955731169,IA +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-0.09226050955731169,IFIE2 +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-29.875294459866303,ISE12 +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,0,OCI2 +0,PR,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,400,CF +0,NIC,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-280,CF +0,ACA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,400,IR1 +0,NIC,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-280,ISE2 +0,AEA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-10,ISE4 +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-1.5,BOP +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-1.5,EOP +0,PR,2020,USD,,APA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-320,IR6 +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,400,CF +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-300,CF +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,400,CF +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-300,CF +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,1.0971983374806105,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.9226050955731167,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,398.536731161375,IR5 +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-298.7529445986629,IR5 +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-399.6339294988556,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,299.675549694236,OCI1 +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,399.6339294988556,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-299.675549694236,OCI1 +0,PR,2020,USD,L,BEPA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,320,IR6 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-67.83795828214956,AM +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,72.2,BOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,139.90849210284577,BOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-15,EA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,129.49726655304642,EOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.14440000000001615,IA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.08233273235018213,IA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.22673273235019828,IFIE1 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,67.83795828214956,IR3 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-124.90849210284577,IR5 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-9.843447868559382,EOP +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,5.156552131440618,IR4 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5.156552131440618,ISE6 +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,1.5,BOP +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,1.5,EOP +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-30,CF +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-30,CF +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.09226050955731169,IFIE1 +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-29.875294459866303,IR5 +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,29.967554969423617,OCI1 +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-29.967554969423617,OCI1 +0,PR,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,400,CF +0,NIC,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-280,CF +0,ACA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,400,IR1 +0,NIC,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-280,ISE2 +0,AEA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-10,ISE4 +0,PR,2020,USD,,APA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-320,IR6 +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-798.536731161375,BOP +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,598.7529445986629,BOP +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,400,CF +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-300,CF +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,400,CF +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-300,CF +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-399.63392949885554,EOP +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,299.675549694236,EOP +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-1.0971983374806105,IA +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.9226050955731167,IA +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,1.0971983374806105,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.9226050955731167,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,398.536731161375,IR5 +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-298.7529445986629,IR5 +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-399.6339294988556,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,299.675549694236,OCI1 +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,399.6339294988556,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-299.675549694236,OCI1 +0,PR,2020,USD,L,BEPA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,320,IR6 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,139.90849210284577,BOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-15,EA +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.08233273235018213,IA +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.08233273235018213,IFIE1 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-124.90849210284577,IR5 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-9.843447868559382,EOP +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,5.156552131440618,IR4 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,59.8752944598663,BOP +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-30,CF +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-30,CF +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,29.967554969423617,EOP +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.09226050955731169,IA +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.09226050955731169,IFIE1 +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-29.875294459866303,IR5 +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,29.967554969423617,OCI1 +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-29.967554969423617,OCI1 +0,NIC,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,140,CF +0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-200,CF +0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-200,ISE1 +0,NIC,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,140,ISE2 +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,399.2683655806875,BOP +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-299.37647229933145,BOP +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.4811341181992343,BOP +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,399.2683655806875,BOP +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-299.37647229933145,BOP +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.4811341181992343,BOP +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-200,CF +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,150,CF +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.36703270529272203,CF +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-200,CF +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,150,CF +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.36703270529272203,CF +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,199.81696474942777,EOP +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-149.837774847118,EOP +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.11527160395201003,EOP +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,199.81696474942777,EOP +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-149.837774847118,EOP +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.11527160395201003,EOP +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.5485991687403052,IA +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.4613025477865583,IA +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0011701910454977593,IA +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.5485991687403052,IA +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.4613025477865583,IA +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0011701910454977593,IA +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.5485991687403052,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.4613025477865583,IFIE1 +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.0011701910454977593,IFIE1 +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-199.2683655806875,ISE10 +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,149.37647229933145,ISE10 +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.11410141290651227,ISE10 +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,199.8169647494278,OCI1 +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-149.837774847118,OCI1 +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.11527160395201003,OCI1 +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-199.8169647494278,OCI1 +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,149.837774847118,OCI1 +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.11527160395201003,OCI1 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,24.228134693791258,AM +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-70.43538016962212,BOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-46.249582033051446,EOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.04233655722058882,IA +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.04233655722058882,IFIE1 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,70.43538016962212,ISE10 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-24.228134693791258,ISE7 +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.93764722993315,BOP +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.93764722993315,BOP +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,15,CF +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,15,CF +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711808,EOP +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711808,EOP +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.046130254778655844,IA +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.046130254778655844,IA +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.046130254778655844,IFIE1 +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,14.937647229933152,ISE10 +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711808,OCI1 +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,14.983777484711808,OCI1 +2020,NIC,2020,USD,,A,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,140,CF +2020,NIC,2020,USD,,A,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,140,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-299.37647229933145,BOP +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.4811341181992343,BOP +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-299.37647229933145,BOP +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.4811341181992343,BOP +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,150,CF +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.36703270529272203,CF +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,150,CF +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.36703270529272203,CF +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-149.837774847118,EOP +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.11527160395201003,EOP +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-149.837774847118,EOP +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.11527160395201003,EOP +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.4613025477865583,IA +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0011701910454977593,IA +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.4613025477865583,IA +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0011701910454977593,IA +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.4613025477865583,IFIE2 +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.0011701910454977593,IFIE2 +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,149.37647229933145,ISE12 +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.11410141290651227,ISE12 +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-149.837774847118,OCI2 +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.11527160395201003,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,149.837774847118,OCI2 +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.11527160395201003,OCI2 +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.93764722993315,BOP +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.93764722993315,BOP +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,15,CF +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,15,CF +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711808,EOP +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711808,EOP +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.046130254778655844,IA +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.046130254778655844,IA +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.046130254778655844,IFIE2 +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,14.937647229933152,ISE12 +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711808,OCI2 +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,14.983777484711808,OCI2 +0,PR,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-200,CF +0,NIC,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,140,CF +0,PR,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-200,ISE1 +0,NIC,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,140,ISE2 +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,399.2683655806875,BOP +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-299.37647229933145,BOP +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.4811341181992343,BOP +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,399.2683655806875,BOP +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-299.37647229933145,BOP +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.4811341181992343,BOP +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-200,CF +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,150,CF +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.36703270529272203,CF +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-200,CF +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,150,CF +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.36703270529272203,CF +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,199.81696474942777,EOP +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-149.837774847118,EOP +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.11527160395201003,EOP +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,199.81696474942777,EOP +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-149.837774847118,EOP +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.11527160395201003,EOP +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.5485991687403052,IA +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.4613025477865583,IA +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0011701910454977593,IA +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.5485991687403052,IA +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.4613025477865583,IA +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0011701910454977593,IA +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.5485991687403052,IFIE1 +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.4613025477865583,IFIE1 +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.0011701910454977593,IFIE1 +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-199.2683655806875,ISE10 +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,149.37647229933145,ISE10 +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.11410141290651227,ISE10 +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,24.228134693791258,AM +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-70.43538016962212,BOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-46.249582033051446,EOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.04233655722058882,IA +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.04233655722058882,IFIE1 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,70.43538016962212,ISE10 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-24.228134693791258,ISE7 +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.93764722993315,BOP +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.93764722993315,BOP +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,15,CF +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,15,CF +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-14.983777484711808,EOP +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-14.983777484711808,EOP +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.046130254778655844,IA +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.046130254778655844,IA +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.046130254778655844,IFIE1 +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,14.937647229933152,ISE10 +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 +2020,NIC,2020,USD,,A,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,140,CF +2020,NIC,2020,USD,,A,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,140,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-299.37647229933145,BOP +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.4811341181992343,BOP +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-299.37647229933145,BOP +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.4811341181992343,BOP +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,150,CF +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.36703270529272203,CF +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,150,CF +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.36703270529272203,CF +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-149.837774847118,EOP +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.11527160395201003,EOP +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-149.837774847118,EOP +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.11527160395201003,EOP +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.4613025477865583,IA +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0011701910454977593,IA +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.4613025477865583,IA +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0011701910454977593,IA +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.4613025477865583,IFIE2 +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.0011701910454977593,IFIE2 +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,149.37647229933145,ISE12 +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.11410141290651227,ISE12 +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI2 +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI2 +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.93764722993315,BOP +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.93764722993315,BOP +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,15,CF +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,15,CF +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-14.983777484711808,EOP +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-14.983777484711808,EOP +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.046130254778655844,IA +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.046130254778655844,IA +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.046130254778655844,IFIE2 +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,14.937647229933152,ISE12 +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI2 \ No newline at end of file diff --git a/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv b/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv new file mode 100644 index 00000000..f9cba291 --- /dev/null +++ b/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv @@ -0,0 +1,1113 @@ +@@ReportVariable +AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateType,FunctionalCurrency,GroupOfContract,InitialProfitability,IsReinsurance,LiabilityType,LineOfBusiness,Novelty,OciType,Partner,Portfolio,Projection,ReportingNode,Scenario,ValuationApproach,Value,VariableType +0,PR,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,90,CF +0,ICO,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-6,CF +0,NIC,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-70,CF +0,ACA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,90,IR1 +0,ICO,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-6,IR2 +0,NIC,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-70,ISE2 +0,AEA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,ISE4 +0,ICO,2020,USD,,A,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,6,ISE5 +0,PR,2020,USD,,AA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,CF +0,PR,2020,USD,,AA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-1,EOP +0,PR,2020,USD,,AA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,IR1 +0,PR,2020,USD,,AA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,4,WO +0,PR,2020,USD,,AAPA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,4,IR6 +0,PR,2020,USD,,APA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-72,IR6 +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-39.963392949885524,BOP +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,47.94808795107775,BOP +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.987021987769438,BOP +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-39.908704950657615,BOP +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,47.87054820092061,BOP +0,ICO,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.967637050230152,BOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,110,CF +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-60,CF +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,110,CF +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-60,CF +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,10,CF +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-12,CF +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,10,CF +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-12,CF +0,ICO,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-344.77033486392617,EOP +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,260.78283172777515,EOP +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,8.9925114388888,EOP +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-344.4270877400716,EOP +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,260.45831803554256,EOP +0,ICO,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,8.981321311570433,EOP +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,14.990014559301141,EV +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,44.96255719444398,EV +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,14.975090771307462,EV +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,44.906606557852164,EV +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-0.016636168716755634,IA +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.021957804477441785,IA +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.005489451119360446,IA +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-0.04147659195731423,IA +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.05473704536112062,IA +0,ICO,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.013684261340280154,IA +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0.19963402460106758,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.13174682686465072,IFIE1 +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.005489451119360446,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-55.06322865953015,IR5 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,39.02446479332545,IR5 +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.987021987769438,IR5 +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,54.863594634929065,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-38.89271796646079,OCI1 +0,ICO,2020,USD,L,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,8.992511438888798,OCI1 +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-55.20684175878363,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,39.217231658693336,OCI1 +0,ICO,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.981321311570433,OCI1 +0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.3283233358608868,YCU +0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.22380254636726704,YCU +0,PR,2020,USD,L,BEPA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,96,IR6 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-38.60249856533708,AM +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,82.02271122089925,BOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-43.599999999999994,EA +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,18.374757965778002,EOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.09388697662967685,IA +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09388697662967685,IFIE1 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,38.60249856533708,IR3 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,25.139341666413856,IR5 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,105.89201388261736,MC +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,AM +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.011834360099684,EOP +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,IR4 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,31.958738976731105,BOP +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903124,CL +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0,EOP +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,55.45631603430072,EV +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.016300537999407044,IA +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.016300537999407044,IFIE1 +0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0.016300537999413223,ISE11 +0,PR,2020,USD,,OA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,3,CF +0,PR,2020,USD,,OA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,1,EOP +0,PR,2020,USD,,OA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,3,IR1 +0,PR,2020,USD,,OA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-2,WO +0,PR,2020,USD,,OAPA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-2.4000000000000004,IR6 +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.987021987769438,BOP +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.967637050230152,BOP +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-6,CF +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-6,CF +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,22.481278597221998,EOP +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,22.453303278926093,EOP +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-4.496255719444398,EV +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-4.490660655785217,EV +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.013684261340280154,IA +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.01646835335808134,IFIE1 +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,7.50274472555968,IR5 +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-7.486276372201601,OCI1 +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,7.5142516904975025,OCI1 +0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.02238025463672244,YCU +2020,NIC,2020,USD,,A,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-76,CF +2020,NIC,2020,USD,,A,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-76,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,299.67554969423594,BOP +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,299.67554969423594,BOP +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,59.93510993884719,BOP +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,59.83818525115076,BOP +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-60,CF +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-60,CF +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-15,CF +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-15,CF +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,269.77534316666396,EOP +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,269.43963934711303,EOP +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,44.96255719444399,EV +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,44.90660655785217,EV +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,0.10978902238720895,IA +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,0.10978902238720895,IA +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.027447255596802236,IA +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.06842130670140079,IA +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-0.13723627798401117,IFIE2 +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,30.037442805555997,ISE12 +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-59.93510993884718,MC +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-59.93510993884718,MC +2020,NIC,2020,USD,L,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-29.900206527571996,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,30.23591034712291,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-0.22380254636726704,YCU +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,29.967554969423595,BOP +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,29.967554969423595,BOP +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,11.987021987769438,BOP +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,11.967637050230152,BOP +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-6,CF +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-6,CF +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,22.481278597221998,EOP +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,22.453303278926093,EOP +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-4.496255719444398,EV +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,-4.490660655785217,EV +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,0.010978902238720892,IA +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,0.010978902238720892,IA +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.005489451119360446,IA +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,N,Default,,DT1,0,CH,,BBA,0.013684261340280154,IA +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-0.01646835335808134,IFIE2 +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,7.50274472555968,ISE12 +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-5.993510993884719,MC +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-5.993510993884719,MC +2020,,2020,USD,L,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,-7.486276372201601,OCI2 +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,C,Default,,DT1,0,CH,,BBA,7.5142516904975025,OCI2 +2020,,2020,USD,C,RA,CHF,DT1.2,P,False,LIC,ANN,I,Default,,DT1,0,CH,,BBA,-0.02238025463672244,YCU +0,PR,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,90,CF +0,ICO,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-6,CF +0,NIC,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-70,CF +0,ACA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,90,IR1 +0,ICO,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-6,IR2 +0,NIC,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-70,ISE2 +0,AEA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-10,ISE4 +0,ICO,2020,USD,,A,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,6,ISE5 +0,PR,2020,USD,,AA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,CF +0,PR,2020,USD,,AA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-1,EOP +0,PR,2020,USD,,AA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5,IR1 +0,PR,2020,USD,,AA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,4,WO +0,PR,2020,USD,,AAPA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5,IR6 +0,PR,2020,USD,,APA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-90,IR6 +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-39.963392949885524,BOP +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,47.94808795107775,BOP +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.987021987769438,BOP +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-39.908704950657615,BOP +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,47.87054820092061,BOP +0,ICO,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.967637050230152,BOP +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,110,CF +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-60,CF +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,110,CF +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-60,CF +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,10,CF +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-12,CF +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,10,CF +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-12,CF +0,ICO,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-344.77033486392617,EOP +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,260.78283172777515,EOP +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,8.9925114388888,EOP +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-344.4270877400716,EOP +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,260.45831803554256,EOP +0,ICO,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,8.981321311570433,EOP +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,14.990014559301141,EV +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,44.96255719444398,EV +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,14.975090771307462,EV +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,44.906606557852164,EV +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-0.016636168716755634,IA +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.021957804477441785,IA +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.005489451119360446,IA +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-0.04147659195731423,IA +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.05473704536112062,IA +0,ICO,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.013684261340280154,IA +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0.19963402460106758,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.13174682686465072,IFIE1 +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.005489451119360446,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-55.06322865953015,IR5 +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,39.02446479332545,IR5 +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.987021987769438,IR5 +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,54.863594634929065,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-38.89271796646079,OCI1 +0,ICO,2020,USD,L,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,8.992511438888798,OCI1 +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-55.20684175878363,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,39.217231658693336,OCI1 +0,ICO,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.981321311570433,OCI1 +0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.3283233358608868,YCU +0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.22380254636726704,YCU +0,PR,2020,USD,L,BEPA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,120,IR6 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-34.26645281902704,AM +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,82.02271122089925,BOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-50,EA +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.31080371208803,EOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.09388697662967685,IA +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09388697662967685,IFIE1 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,34.26645281902704,IR3 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,31.53934166641386,IR5 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,105.89201388261736,MC +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,AM +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.011834360099684,EOP +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,IR4 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,31.958738976731105,BOP +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0,EOP +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,55.45631603430072,EV +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.016300537999407044,IA +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.016300537999407044,IFIE1 +0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0.016300537999399012,ISE11 +0,PR,2020,USD,,OA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,3,CF +0,PR,2020,USD,,OA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,1,EOP +0,PR,2020,USD,,OA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,3,IR1 +0,PR,2020,USD,,OA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-2,WO +0,PR,2020,USD,,OAPA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-3,IR6 +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.987021987769438,BOP +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,11.967637050230152,BOP +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-6,CF +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-6,CF +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-3,CF +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,22.481278597221998,EOP +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,22.453303278926093,EOP +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-4.496255719444398,EV +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-4.490660655785217,EV +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.013684261340280154,IA +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.01646835335808134,IFIE1 +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,7.50274472555968,IR5 +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-7.486276372201601,OCI1 +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,7.5142516904975025,OCI1 +0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.02238025463672244,YCU +0,AEA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5,CF +0,ACA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-10,CF +0,NIC,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-70,CF +0,ICO,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-6,CF +0,PR,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,90,CF +0,PR,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,90,IR1 +0,ICO,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-6,IR2 +0,NIC,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-70,ISE2 +0,AEA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-10,ISE4 +0,ICO,2020,USD,,A,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,6,ISE5 +0,PR,2020,USD,,AA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5,CF +0,PR,2020,USD,,AA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-1,EOP +0,PR,2020,USD,,AA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5,IR1 +0,PR,2020,USD,,AA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,4,WO +0,PR,2020,USD,,AAPA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,4,IR6 +0,PR,2020,USD,,APA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-72,IR6 +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-39.963392949885524,BOP +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,47.94808795107775,BOP +0,ICO,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,11.987021987769438,BOP +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-39.908704950657615,BOP +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,47.87054820092061,BOP +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,11.967637050230152,BOP +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,110,CF +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-60,CF +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,110,CF +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-60,CF +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,10,CF +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-12,CF +0,ICO,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-3,CF +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,10,CF +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-12,CF +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-3,CF +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-344.77033486392617,EOP +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,260.78283172777515,EOP +0,ICO,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,8.9925114388888,EOP +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-344.4270877400716,EOP +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,260.45831803554256,EOP +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,8.981321311570433,EOP +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,14.990014559301141,EV +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,44.96255719444398,EV +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,14.975090771307462,EV +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,44.906606557852164,EV +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-0.016636168716755634,IA +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.021957804477441785,IA +0,ICO,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.005489451119360446,IA +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-0.04147659195731423,IA +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.05473704536112062,IA +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.013684261340280154,IA +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.10384888801926062,IFIE1 +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0.05927647861893748,IFIE1 +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.013684261340280154,IFIE1 +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-55.102992870764375,IR5 +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,39.157955180074396,IR5 +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-8.967637050230152,IR5 +0,PR,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,L,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 +0,ICO,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 +0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.3283233358608868,YCU +0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-0.22380254636726704,YCU +0,PR,2020,USD,L,BEPA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,96,IR6 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-38.60249856533708,AM +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,82.02271122089925,BOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-43.599999999999994,EA +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,18.374757965778002,EOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.09388697662967685,IA +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.09388697662967685,IFIE1 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,38.60249856533708,IR3 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,25.139341666413856,IR5 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,105.89201388261736,MC +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,16.831613508459697,AM +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-8.011834360099686,EOP +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,16.831613508459697,IR4 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,31.958738976731105,BOP +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,EOP +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,55.45631603430072,EV +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.016300537999407044,IA +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.016300537999407044,IFIE1 +0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0.016300537999399012,ISE11 +0,PR,2020,USD,,OA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,3,CF +0,PR,2020,USD,,OA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,1,EOP +0,PR,2020,USD,,OA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,3,IR1 +0,PR,2020,USD,,OA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-2,WO +0,PR,2020,USD,,OAPA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-2.4000000000000004,IR6 +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,11.987021987769438,BOP +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,11.967637050230152,BOP +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-6,CF +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-6,CF +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-3,CF +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-3,CF +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,22.481278597221998,EOP +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,22.453303278926093,EOP +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-4.496255719444398,EV +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-4.490660655785217,EV +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.013684261340280154,IA +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.002282908942278606,IFIE1 +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,7.516534599439783,IR5 +0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,3.552713678800501E-15,OCI1 +0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-0.02238025463672244,YCU +2020,NIC,2020,USD,,A,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-76,CF +2020,NIC,2020,USD,,A,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-76,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,299.67554969423594,BOP +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,299.67554969423594,BOP +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,59.93510993884719,BOP +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,59.83818525115076,BOP +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-60,CF +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-60,CF +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-15,CF +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-15,CF +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,269.77534316666396,EOP +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,269.43963934711303,EOP +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,44.96255719444399,EV +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,44.90660655785217,EV +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,0.10978902238720895,IA +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,0.10978902238720895,IA +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.027447255596802236,IA +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.06842130670140079,IA +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,0.04559221727865731,IFIE2 +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,30.190318129844243,ISE12 +2020,NIC,2020,USD,L,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-59.93510993884718,MC +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-59.93510993884718,MC +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-1.4210854715202004E-14,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-0.22380254636726704,YCU +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,29.967554969423595,BOP +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,29.967554969423595,BOP +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,11.987021987769438,BOP +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,11.967637050230152,BOP +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-6,CF +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-6,CF +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-3,CF +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-3,CF +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,22.481278597221998,EOP +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,22.453303278926093,EOP +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-4.496255719444398,EV +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,-4.490660655785217,EV +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,0.010978902238720892,IA +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,0.010978902238720892,IA +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.005489451119360446,IA +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,N,,,DT2,0,CH,,BBA,0.013684261340280154,IA +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,-0.002282908942278606,IFIE2 +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,7.516534599439783,ISE12 +2020,,2020,USD,L,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-5.993510993884719,MC +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-5.993510993884719,MC +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,C,,,DT2,0,CH,,BBA,3.552713678800501E-15,OCI2 +2020,,2020,USD,C,RA,CHF,DT2.2,P,False,LIC,ANN,I,,,DT2,0,CH,,BBA,-0.02238025463672244,YCU +0,PR,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,90,CF +0,ICO,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-6,CF +0,NIC,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-70,CF +0,ACA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,90,IR1 +0,ICO,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-6,IR2 +0,NIC,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-70,ISE2 +0,AEA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-10,ISE4 +0,ICO,2020,USD,,A,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,6,ISE5 +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-1.5,BOP +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5,CF +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-2.5,EOP +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5,IR1 +0,PR,2020,USD,,AA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,4,WO +0,PR,2020,USD,,AAPA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,4,IR6 +0,PR,2020,USD,,APA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-72,IR6 +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-39.963392949885524,BOP +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,47.94808795107775,BOP +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,11.987021987769438,BOP +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-39.908704950657615,BOP +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,47.87054820092061,BOP +0,ICO,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,11.967637050230152,BOP +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,110,CF +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-60,CF +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,110,CF +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-60,CF +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,10,CF +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-12,CF +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-3,CF +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,10,CF +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-12,CF +0,ICO,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-3,CF +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,344.77033486392617,CL +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-260.78283172777515,CL +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-8.9925114388888,CL +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,344.4270877400716,CL +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-260.45831803554256,CL +0,ICO,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-8.981321311570433,CL +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,ICO,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,14.990014559301141,EV +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,44.96255719444398,EV +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,14.975090771307462,EV +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,44.906606557852164,EV +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-0.016636168716755634,IA +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.021957804477441785,IA +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.005489451119360446,IA +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-0.04147659195731423,IA +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.05473704536112062,IA +0,ICO,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.013684261340280154,IA +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0.19963402460106758,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.13174682686465072,IFIE1 +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.005489451119360446,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-399.8335635234563,IR5 +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,299.80729652110057,IR5 +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0.005489451119361277,IR5 +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,399.63392949885525,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-299.67554969423594,OCI1 +0,ICO,2020,USD,L,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,OCI1 +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-399.63392949885525,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,299.6755496942359,OCI1 +0,ICO,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,OCI1 +0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.3283233358608868,YCU +0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-0.22380254636726704,YCU +0,PR,2020,USD,L,BEPA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,96,IR6 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-51.96181825867143,AM +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,129.49726655304642,BOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-139.94506864907146,CL +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-43.599999999999994,EA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.11760647207910604,IA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.11760647207910604,IFIE1 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,51.96181825867143,IR3 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,77.65305476645409,IR5 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,105.89201388261736,MC +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,24.84344786855938,AM +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,24.84344786855938,IR4 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-24.84344786855938,ISE6 +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,31.958738976731105,BOP +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,55.45631603430072,EV +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.016300537999407044,IA +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.016300537999407044,IFIE1 +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0.016300537999399012,ISE11 +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,1.5,BOP +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,3,CF +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,2.5,EOP +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,3,IR1 +0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-2,WO +0,PR,2020,USD,,OAPA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-2.4000000000000004,IR6 +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,11.987021987769438,BOP +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,11.967637050230152,BOP +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-6,CF +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-6,CF +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-3,CF +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-3,CF +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-22.481278597221998,CL +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-22.453303278926093,CL +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-4.496255719444398,EV +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,-4.490660655785217,EV +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.013684261340280154,IA +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.01646835335808134,IFIE1 +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,29.98402332278168,IR5 +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-29.967554969423603,OCI1 +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,29.967554969423595,OCI1 +0,,2020,USD,C,RA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-0.02238025463672244,YCU +0,PR,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,90,CF +0,ICO,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-6,CF +0,NIC,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-70,CF +0,ACA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-10,CF +0,AEA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5,CF +0,PR,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,90,IR1 +0,ICO,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-6,IR2 +0,NIC,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-70,ISE2 +0,AEA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5,ISE3 +0,ACA,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-10,ISE4 +0,ICO,2020,USD,,A,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,6,ISE5 +0,PR,2020,USD,,AA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5,CF +0,PR,2020,USD,,AA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-1,EOP +0,PR,2020,USD,,AA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5,IR1 +0,PR,2020,USD,,AA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,4,WO +0,PR,2020,USD,,AAPA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,4,IR6 +0,PR,2020,USD,,APA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-72,IR6 +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-399.63392949885525,BOP +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,299.67554969423594,BOP +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-79.92678589977105,BOP +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,47.94808795107775,BOP +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,11.987021987769438,BOP +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-79.81740990131523,BOP +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,47.87054820092061,BOP +0,ICO,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,11.967637050230152,BOP +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,110,CF +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-60,CF +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,110,CF +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-60,CF +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,20,CF +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-12,CF +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-3,CF +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,20,CF +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-12,CF +0,ICO,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-3,CF +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-428.7144163960125,EOP +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,260.78283172777515,EOP +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,8.9925114388888,EOP +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-428.28759605939337,EOP +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,260.45831803554256,EOP +0,ICO,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,8.981321311570433,EOP +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-38.97403785418295,EV +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,44.96255719444398,EV +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-38.93523600539941,EV +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,44.906606557852164,EV +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-0.18299785588431194,IA +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.10978902238720895,IA +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-0.03327233743351127,IA +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.021957804477441785,IA +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.005489451119360446,IA +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-0.08295318391462846,IA +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.05473704536112062,IA +0,ICO,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.013684261340280154,IA +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,0.2162701933178232,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.13174682686465072,IFIE1 +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.005489451119360446,IFIE1 +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,28.864216703839475,IR5 +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,39.02446479332545,IR5 +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-8.987021987769438,IR5 +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-39.963392949885474,MC +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-59.93510993884718,MC +0,PR,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-29.0804868971573,OCI1 +0,NIC,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-38.89271796646079,OCI1 +0,ICO,2020,USD,L,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,8.992511438888798,OCI1 +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,28.65366656053817,OCI1 +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,39.217231658693336,OCI1 +0,ICO,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-8.981321311570433,OCI1 +0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.3283233358608868,YCU +0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-0.22380254636726704,YCU +0,PR,2020,USD,L,BEPA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,104,IR6 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-96.83022811966929,AM +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,82.02271122089925,BOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,8.004653973154419,BOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-51.599999999999994,EA +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,46.09110994353215,EOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-1.4922636208166304,EV +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.09388697662967685,IA +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.0003356307173485902,IA +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.09422260734702544,IFIE1 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,96.83022811966929,IR3 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-60.80440423495516,IR5 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,105.89201388261736,MC +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,16.831613508459697,AM +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-15,CF +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-8.011834360099684,EOP +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,16.831613508459697,IR4 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-16.831613508459697,ISE6 +0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,3,CF +0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,1,EOP +0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,3,IR1 +0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-2,WO +0,PR,2020,USD,,OAPA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-2.4000000000000004,IR6 +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,29.967554969423595,BOP +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,11.987021987769438,BOP +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,11.967637050230152,BOP +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-6,CF +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-6,CF +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-3,CF +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-3,CF +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,22.481278597221998,EOP +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,22.453303278926093,EOP +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-4.496255719444398,EV +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-4.490660655785217,EV +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.010978902238720892,IA +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.013684261340280154,IA +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.01646835335808134,IFIE1 +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,7.50274472555968,IR5 +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-5.993510993884719,MC +0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-7.486276372201601,OCI1 +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,7.5142516904975025,OCI1 +0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-0.02238025463672244,YCU +0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-45,CF +0,NIC,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,35,CF +0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-45,ISE1 +0,NIC,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,35,ISE2 +0,PR,2020,USD,,AA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,2,CF +0,PR,2020,USD,,AA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,2,EOP +0,PR,2020,USD,,AA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,2,ISE1 +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,199.81696474942763,BOP +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-149.83777484711797,BOP +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11527160395198197,BOP +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,199.81696474942763,BOP +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-149.83777484711797,BOP +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11527160395198197,BOP +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,19.981696474942762,BOP +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.967554969423595,BOP +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.29437375980433944,BOP +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,19.954352475328808,BOP +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.91909262557538,BOP +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.29373948854293713,BOP +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-55,CF +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,30,CF +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.041970417989396935,CF +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-55,CF +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,30,CF +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.041970417989396935,CF +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-5,CF +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,7.5,CF +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.1337106481180328,CF +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-5,CF +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,7.5,CF +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.1337106481180328,CF +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.5933128558860402,CRU +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.5923289904108416,CRU +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,172.38516743196308,EOP +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-134.88767158333198,EOP +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.9654554759111158,EOP +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,172.2135438700358,EOP +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-134.71981967355651,EOP +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.9638544365065973,EOP +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-7.4950072796505705,EV +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-22.481278597221994,EV +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.16090924598518777,EV +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-7.487545385653731,EV +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-22.453303278926086,EV +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.16064240608443553,EV +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.09149892794215597,IA +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.05489451119360447,IA +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,7.726288250786695E-05,IA +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.09149892794215597,IA +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.05489451119360447,IA +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,7.726288250786695E-05,IA +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.008318084358377817,IA +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.013723627798401118,IA +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0002461342988846482,IA +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.020738295978657114,IA +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.03421065335070039,IA +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0006135656595298578,IA +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.09981701230053379,IFIE1 +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.06861813899200558,IFIE1 +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.5936362530674327,IFIE1 +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,27.531614329765073,ISE10 +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-15.018721402777999,ISE10 +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.2565476188917011,ISE10 +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,19.981696474942737,MC +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,29.96755496942359,MC +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.023054320790396418,MC +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,19.981696474942737,MC +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,29.96755496942359,MC +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.023054320790396418,MC +0,PR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-27.431797317464532,OCI1 +0,NIC,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,14.950103263785998,OCI1 +0,CDR,2020,USD,L,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.8501838719591338,OCI1 +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,27.603420879391816,OCI1 +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-15.117955173561455,OCI1 +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.8485828325546154,OCI1 +0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.1641616679304434,YCU +0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11190127318363352,YCU +0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-8.349412781047394E-05,YCU +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,38.316584766326955,AM +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-46.24958203305145,BOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,43.26014863442721,CL +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.5933128558860402,CRU +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-18.238663229656325,EOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.04954912095471157,IA +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.6428619768407517,IFIE1 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,9.662803986091077,ISE10 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-38.316584766326955,ISE7 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-52.92295262051829,MC +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-15.684995728561214,BOP +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,43.26014863442721,CL +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0,EOP +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-27.56724877116518,EV +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.007904134700818875,IA +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.007904134700818875,IFIE1 +0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.007904134700817522,ISE11 +0,PR,2020,USD,,OA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-1.5,CF +0,PR,2020,USD,,OA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-1.5,EOP +0,PR,2020,USD,,OA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-1.5,ISE1 +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711798,BOP +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711798,BOP +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-5.993510993884719,BOP +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-5.983818525115076,BOP +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,3,CF +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,3,CF +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,1.5,CF +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,1.5,CF +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-11.240639298610999,EOP +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-11.226651639463046,EOP +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,2.248127859722199,EV +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,2.2453303278926087,EV +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.005489451119360446,IA +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.002744725559680223,IA +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.006842130670140077,IA +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.00823417667904067,IFIE1 +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-3.75137236277984,ISE10 +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,2.9967554969423595,MC +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,2.9967554969423595,MC +0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,3.7431381861008006,OCI1 +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-3.7571258452487513,OCI1 +0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.01119012731836122,YCU +2020,NIC,2020,USD,,A,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,35,CF +2020,NIC,2020,USD,,A,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,35,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-149.83777484711797,BOP +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11527160395198197,BOP +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-149.83777484711797,BOP +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11527160395198197,BOP +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.967554969423595,BOP +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.29437375980433944,BOP +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.91909262557538,BOP +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.29373948854293713,BOP +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,30,CF +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.041970417989396935,CF +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,30,CF +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.041970417989396935,CF +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,7.5,CF +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.1337106481180328,CF +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,7.5,CF +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.1337106481180328,CF +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.5933128558860402,CRU +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.5923289904108416,CRU +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-134.88767158333198,EOP +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.9654554759111158,EOP +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-134.71981967355651,EOP +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.9638544365065973,EOP +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-22.481278597221994,EV +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.16090924598518777,EV +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-22.453303278926086,EV +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.16064240608443553,EV +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.05489451119360447,IA +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,7.726288250786695E-05,IA +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.05489451119360447,IA +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,7.726288250786695E-05,IA +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.013723627798401118,IA +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0002461342988846482,IA +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.03421065335070039,IA +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,0.0006135656595298578,IA +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.06861813899200558,IFIE2 +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.5936362530674327,IFIE2 +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-15.018721402777999,ISE12 +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.2565476188917011,ISE12 +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,29.96755496942359,MC +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.023054320790396418,MC +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,29.96755496942359,MC +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.023054320790396418,MC +2020,NIC,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,14.950103263785998,OCI2 +2020,CDR,2020,USD,L,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.8501838719591338,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-15.117955173561455,OCI2 +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.8485828325546154,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11190127318363352,YCU +2020,CDR,2020,USD,C,BE,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-8.349412781047394E-05,YCU +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711798,BOP +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-14.983777484711798,BOP +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-5.993510993884719,BOP +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-5.983818525115076,BOP +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,3,CF +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,3,CF +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,1.5,CF +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,1.5,CF +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-11.240639298610999,EOP +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-11.226651639463046,EOP +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,2.248127859722199,EV +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,2.2453303278926087,EV +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.005489451119360446,IA +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.005489451119360446,IA +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.002744725559680223,IA +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.006842130670140077,IA +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.00823417667904067,IFIE2 +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-3.75137236277984,ISE12 +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,2.9967554969423595,MC +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,2.9967554969423595,MC +2020,,2020,USD,L,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,3.7431381861008006,OCI2 +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-3.7571258452487513,OCI2 +2020,,2020,USD,C,RA,CHF,DTR1.2,P,True,LIC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.01119012731836122,YCU +0,PR,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-45,CF +0,NIC,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,35,CF +0,PR,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-45,ISE1 +0,NIC,2020,USD,,A,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,35,ISE2 +0,PR,2020,USD,,AA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,2,CF +0,PR,2020,USD,,AA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,2,EOP +0,PR,2020,USD,,AA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,2,ISE1 +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,199.81696474942763,BOP +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-149.83777484711797,BOP +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11527160395198197,BOP +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,199.81696474942763,BOP +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-149.83777484711797,BOP +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11527160395198197,BOP +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,19.981696474942762,BOP +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.967554969423595,BOP +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.29437375980433944,BOP +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,19.954352475328808,BOP +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.91909262557538,BOP +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.29373948854293713,BOP +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-55,CF +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,30,CF +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.041970417989396935,CF +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-55,CF +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,30,CF +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.041970417989396935,CF +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-5,CF +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,7.5,CF +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.1337106481180328,CF +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-5,CF +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,7.5,CF +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.1337106481180328,CF +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.5933128558860402,CRU +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.5923289904108416,CRU +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,172.38516743196308,EOP +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-134.88767158333198,EOP +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.9654554759111158,EOP +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,172.2135438700358,EOP +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-134.71981967355651,EOP +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.9638544365065973,EOP +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-7.4950072796505705,EV +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-22.481278597221994,EV +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.16090924598518777,EV +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-7.487545385653731,EV +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-22.453303278926086,EV +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.16064240608443553,EV +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.09149892794215597,IA +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.05489451119360447,IA +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,7.726288250786695E-05,IA +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.09149892794215597,IA +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.05489451119360447,IA +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,7.726288250786695E-05,IA +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.008318084358377817,IA +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.013723627798401118,IA +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0002461342988846482,IA +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.020738295978657114,IA +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.03421065335070039,IA +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0006135656595298578,IA +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.05192444400963031,IFIE1 +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.022796108639328655,IFIE1 +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.5929363248250689,IFIE1 +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,27.551496435382187,ISE10 +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-15.095159064922122,ISE10 +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.2556465077295465,ISE10 +0,PR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,19.981696474942737,MC +0,NIC,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,29.96755496942359,MC +0,CDR,2020,USD,L,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.023054320790396418,MC +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,19.981696474942737,MC +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,29.96755496942359,MC +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.023054320790396418,MC +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,7.105427357601002E-15,OCI1 +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-5.551115123125783E-17,OCI1 +0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.1641616679304434,YCU +0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11190127318363352,YCU +0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-8.349412781047394E-05,YCU +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,38.316584766326955,AM +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-46.24958203305145,BOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,43.26014863442721,CL +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.5933128558860402,CRU +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-18.238663229656325,EOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.04954912095471157,IA +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.6428619768407517,IFIE1 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,9.662803986091077,ISE10 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-38.316584766326955,ISE7 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-52.92295262051829,MC +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-15.684995728561214,BOP +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,43.26014863442721,CL +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,EOP +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-27.56724877116518,EV +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.007904134700818875,IA +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.007904134700818875,IFIE1 +0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.007904134700817522,ISE11 +0,PR,2020,USD,,OA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-1.5,CF +0,PR,2020,USD,,OA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-1.5,EOP +0,PR,2020,USD,,OA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-1.5,ISE1 +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-14.983777484711798,BOP +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-14.983777484711798,BOP +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-5.993510993884719,BOP +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-5.983818525115076,BOP +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,3,CF +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,3,CF +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,1.5,CF +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,1.5,CF +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-11.240639298610999,EOP +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-11.226651639463046,EOP +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,2.248127859722199,EV +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,2.2453303278926087,EV +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.005489451119360446,IA +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.005489451119360446,IA +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.002744725559680223,IA +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.006842130670140077,IA +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.001141454471139303,IFIE1 +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-3.7582672997198916,ISE10 +0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,2.9967554969423595,MC +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,2.9967554969423595,MC +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-1.7763568394002505E-15,OCI1 +0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.01119012731836122,YCU +2020,NIC,2020,USD,,A,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,35,CF +2020,NIC,2020,USD,,A,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,35,ISE2 +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-149.83777484711797,BOP +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11527160395198197,BOP +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-149.83777484711797,BOP +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11527160395198197,BOP +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.967554969423595,BOP +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.29437375980433944,BOP +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.91909262557538,BOP +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.29373948854293713,BOP +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,30,CF +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.041970417989396935,CF +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,30,CF +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.041970417989396935,CF +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,7.5,CF +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.1337106481180328,CF +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,7.5,CF +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.1337106481180328,CF +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.5933128558860402,CRU +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.5923289904108416,CRU +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-134.88767158333198,EOP +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.9654554759111158,EOP +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-134.71981967355651,EOP +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.9638544365065973,EOP +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-22.481278597221994,EV +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.16090924598518777,EV +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-22.453303278926086,EV +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.16064240608443553,EV +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.05489451119360447,IA +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,7.726288250786695E-05,IA +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.05489451119360447,IA +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,7.726288250786695E-05,IA +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.013723627798401118,IA +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0002461342988846482,IA +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.03421065335070039,IA +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,0.0006135656595298578,IA +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.022796108639328655,IFIE2 +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.5929363248250689,IFIE2 +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-15.095159064922122,ISE12 +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-0.2556465077295465,ISE12 +2020,NIC,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,29.96755496942359,MC +2020,CDR,2020,USD,L,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.023054320790396418,MC +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,29.96755496942359,MC +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.023054320790396418,MC +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,7.105427357601002E-15,OCI2 +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-5.551115123125783E-17,OCI2 +2020,NIC,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11190127318363352,YCU +2020,CDR,2020,USD,C,BE,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-8.349412781047394E-05,YCU +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-14.983777484711798,BOP +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-14.983777484711798,BOP +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-5.993510993884719,BOP +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-5.983818525115076,BOP +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,3,CF +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,3,CF +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,1.5,CF +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,1.5,CF +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-11.240639298610999,EOP +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-11.226651639463046,EOP +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,2.248127859722199,EV +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,2.2453303278926087,EV +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.005489451119360446,IA +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.005489451119360446,IA +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.002744725559680223,IA +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.006842130670140077,IA +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.001141454471139303,IFIE2 +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-3.7582672997198916,ISE12 +2020,,2020,USD,L,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,2.9967554969423595,MC +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,2.9967554969423595,MC +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,C,,PT1,DTR2,0,CH,,BBA,-1.7763568394002505E-15,OCI2 +2020,,2020,USD,C,RA,CHF,DTR2.2,P,True,LIC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.01119012731836122,YCU \ No newline at end of file diff --git a/Test/ExportIfrsVariable.ipynb b/Test/ExportIfrsVariable.ipynb new file mode 100644 index 00000000..21cad454 --- /dev/null +++ b/Test/ExportIfrsVariable.ipynb @@ -0,0 +1,124 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "1fnxMsytI0SV8h59pqZxDQ", + "cell_type": "markdown", + "source": [ + "

Test Reports

" + ], + "metadata": {} + }, + { + "id": "sY2AQGDoZUaMYR5JiSxcjQ", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-xiQumLe30mD77Pvhijxtw", + "cell_type": "markdown", + "source": [ + "# BenchMarks" + ], + "metadata": {} + }, + { + "id": "jOHCgtzBxke3Wk8c8QC1Ug", + "cell_type": "code", + "source": [ + "var pathToBm = \"./Data/ReportBenchmarks/\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LvvPQ9tBmU-4pDW_tCG-1g", + "cell_type": "code", + "source": [ + "var argsArray = new ImportArgs[]{", + "\n new ImportArgs (\"CH\", 2020, 12, Periodicity.Quarterly, null, null),", + "\n new ImportArgs (\"CH\", 2021, 3, Periodicity.Quarterly, null, null)", + "\n };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CnPCEWt_aUe8ts0COdm3ZA", + "cell_type": "code", + "source": [ + "public async Task ExportBenchmarks(ImportArgs args)", + "\n{", + "\n await DataSource.Partition.SetAsync(new {ReportingNode = args.ReportingNode, Year= args.Year, Month = args.Month, Scenario = args.Scenario});", + "\n var computedVariables = (await DataSource.Query().ToArrayAsync()).ToDictionaryGrouped(x => x.EstimateType, x => x.ToArray());", + "\n", + "\n foreach (var estimateType in computedVariables.Keys)", + "\n {", + "\n await Export.ToCsv(pathToBm+\"BM_\"+args.ReportingNode+\"_\"+args.Year.ToString()+\"_\"+args.Month.ToString()+\"_\"+estimateType)", + "\n .WithTable(tableConfig => tableConfig", + "\n .AtBeginning()", + "\n .WithName(Main)", + "\n .WithSource(source => args.RepeatOnce().AsQueryable())", + "\n .WithColumn(x => x.Periodicity, x => x.Delete())", + "\n .WithColumn(x => x.ImportFormat, x => x.Delete())", + "\n )", + "\n .WithTable(tableConfig => tableConfig", + "\n .WithSource(source => computedVariables[estimateType].AsQueryable())", + "\n .WithName(estimateType)", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n )", + "\n .ExecuteAsync();", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "aa_A6kszrU67Ghv0nf-m_g", + "cell_type": "code", + "source": [ + "foreach (var args in argsArray)", + "\n await ExportBenchmarks(args);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "snRElFsmF0OjFLQvRzQNhA", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/ExportReportVariables.ipynb b/Test/ExportReportVariables.ipynb new file mode 100644 index 00000000..a8002ecb --- /dev/null +++ b/Test/ExportReportVariables.ipynb @@ -0,0 +1,186 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "TG_x9dWCM0usAoORaJW0wA", + "cell_type": "markdown", + "source": [ + "

Report Variable Exporter

" + ], + "metadata": {} + }, + { + "id": "Y25XYadyL0aU_Fzz5elNMQ", + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ], + "metadata": {} + }, + { + "id": "cfjgktx4p0-NVKhru0UtHg", + "cell_type": "markdown", + "source": [ + "## Initialize Workspace" + ], + "metadata": {} + }, + { + "id": "LsMvspLNjUSjzwV8dPfvYA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1HOdfKtqgEyoCXzmZfFBXw", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_REnUbsBBkCMFwqQyGWg5Q", + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ], + "metadata": {} + }, + { + "id": "txVLamtljU-DLHzCcz9PnQ", + "cell_type": "code", + "source": [ + "#!import \"ReportVariablesTestBase\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zzDardBj_kKdArEdeDsDNQ", + "cell_type": "markdown", + "source": [ + "## Storage" + ], + "metadata": {} + }, + { + "id": "37AwAO8feEOU3Vi9qBbP4Q", + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iFTfudfp-EetHuW8yU6YCg", + "cell_type": "markdown", + "source": [ + "## Configurations" + ], + "metadata": {} + }, + { + "id": "2qOI8dJxZ0WPMJf28ue31g", + "cell_type": "code", + "source": [ + "var path = \"./Data/ReportVariableBenchmarks/\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kXndb4zG_UO9VKIhnleT1A", + "cell_type": "markdown", + "source": [ + "# Defining Scope for the Reports and Tests" + ], + "metadata": {} + }, + { + "id": "ZC_lDkxtFEeOujJtQdnaUg", + "cell_type": "markdown", + "source": [ + "### Defining the Period and Reporting Node (...) for the Reports" + ], + "metadata": {} + }, + { + "id": "JIbgXj_2n0K5dfj-X2RJ5A", + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType)[] exportScope = {", + "\n ((2020, 12), \"CH\", null, CurrencyType.Contractual),", + "\n// ((2020, 12), \"CH\", null, CurrencyType.Functional),", + "\n// ((2020, 12), \"CH\", null, CurrencyType.Group),", + "\n ", + "\n ((2021, 3), \"CH\", null, CurrencyType.Contractual),", + "\n// ((2021, 3), \"CH\", null, CurrencyType.Functional),", + "\n// ((2021, 3), \"CH\", null, CurrencyType.Group),", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OJE_pdhJBEKChAxri8wv9A", + "cell_type": "markdown", + "source": [ + "# Export" + ], + "metadata": {} + }, + { + "id": "hYzcfGQt4kGKYbKgl9vmqw", + "cell_type": "code", + "source": [ + "foreach(var args in exportScope){", + "\n var scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", + "\n var bmFileName = benchmarkFileNamePrefix + GetBenchmarkFileName(args) + \".csv\";", + "\n await Export.ToCsv(path + bmFileName).WithTable(tableConfig => tableConfig.WithSource(source => scopesData.AsQueryable())).ExecuteAsync(); ", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "plmvGTRjsU60fGgbLWHM3g", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/IfrsVariablesTest.ipynb b/Test/IfrsVariablesTest.ipynb new file mode 100644 index 00000000..7046979f --- /dev/null +++ b/Test/IfrsVariablesTest.ipynb @@ -0,0 +1,327 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "kqZuH1dEnke7hR4QHKoNog", + "cell_type": "markdown", + "source": [ + "

Ifrs Variable

" + ], + "metadata": {} + }, + { + "id": "LjWUwb9UEkuNT2p5nWP59g", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3aLFpM2sG0yzvGW-O9CBrA", + "cell_type": "markdown", + "source": [ + "# BenchMarks" + ], + "metadata": {} + }, + { + "id": "wHzw3mkXwUaee_GWJCqXKA", + "cell_type": "code", + "source": [ + "var pathToBm = \"./Data/IfrsVariableBenchmarks/\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "A-1s2TjE8U2lTB5-1UldnA", + "cell_type": "code", + "source": [ + "public record BenchmarkMetadata(string FileName, string ReportingNode, int Year, int Month){} " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "efhvDjD2pU6uboXYUAfYxw", + "cell_type": "code", + "source": [ + "var bmFiles = new BenchmarkMetadata[]{", + "\n //2020 Q4", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_A.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_AA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_APA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_BE.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_BEPA.csv\", \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_C.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_DA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_F.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_OA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_RA.csv\" , \"CH\", 2020, 12),", + "\n //2021 Q1", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_A.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_AA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_AAPA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_APA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_BE.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_BEPA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_C.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_DA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_F.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_L.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_LR.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_OA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_OAPA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_RA.csv\" , \"CH\", 2021, 3),", + "\n};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Q7pARj6RR0K30yyk_I3omg", + "cell_type": "markdown", + "source": [ + "# Functions" + ], + "metadata": {} + }, + { + "id": "iHhg-4yNYEGh4h62o8W5zA", + "cell_type": "code", + "source": [ + "public static NumberStyles AllowedNumberStyles = NumberStyles.Float | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign | NumberStyles.AllowDecimalPoint;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jMFEw9p2r0iOR_Ru9wkGmg", + "cell_type": "code", + "source": [ + "public IfrsVariable CreateVariable (IDataRow row, Guid partition)", + "\n{", + "\n if (!double.TryParse(row[nameof(IfrsVariable.Value)]?.ToString(), AllowedNumberStyles, CultureInfo.InvariantCulture, out var doubleValue))", + "\n throw new Exception(\"Value cannot be parsed.\");", + "\n ", + "\n return new IfrsVariable(){AocType = row.Field(nameof(IfrsVariable.AocType)),", + "\n Partition = partition,", + "\n Novelty = row.Field(nameof(IfrsVariable.Novelty)),", + "\n DataNode = row.Field(nameof(IfrsVariable.DataNode)),", + "\n EstimateType = row.Field(nameof(IfrsVariable.EstimateType)),", + "\n AmountType = row.Field(nameof(IfrsVariable.AmountType)),", + "\n AccidentYear = Int32.TryParse((row.Field(nameof(IfrsVariable.AccidentYear))), out var accidentYear) ? accidentYear : (int?)null,", + "\n EconomicBasis = row.Field(nameof(IfrsVariable.EconomicBasis)),", + "\n Value = (-1.0) * doubleValue,", + "\n };", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nLcASZMlEEmL_nI0yYamvw", + "cell_type": "code", + "source": [ + "public class BenchmarkTestResult", + "\n{", + "\n public string ErrorMessage {get; set;}", + "\n public double ExpectedValue {get; set;}", + "\n public double ComputedValue {get; set;}", + "\n public BenchmarkTestResult (string message)", + "\n {", + "\n ErrorMessage = message;", + "\n }", + "\n public BenchmarkTestResult (string message, double expValue, double compValue)", + "\n {", + "\n ErrorMessage = message;", + "\n ExpectedValue = expValue;", + "\n ComputedValue = compValue; ", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LEHT1hqQo0W96ERHvf4L3A", + "cell_type": "code", + "source": [ + "public List CompareAgainstBm (List errors, IEnumerable expected, IEnumerable computed)", + "\n{", + "\n var expectedNotComputed = expected.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(computed.Select(x => x.ToIdentityString()));", + "\n var computedNotExpected = computed.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(expected.Select(x => x.ToIdentityString()));", + "\n if (expectedNotComputed.Any())", + "\n {", + "\n foreach (var error in expectedNotComputed)", + "\n {", + "\n var message = error.ToIdentityString();", + "\n errors.Add(new BenchmarkTestResult(\"Extra expected variable for: \"+ message));", + "\n }", + "\n }", + "\n if (computedNotExpected.Any())", + "\n {", + "\n foreach (var error in computedNotExpected)", + "\n {", + "\n var message = error.ToIdentityString();", + "\n errors.Add(new BenchmarkTestResult(\"Extra computed variable for: \"+ message));", + "\n }", + "\n }", + "\n ", + "\n var misMatchedVariables = expected.Concat(computed).AggregateOver().Where(x => Math.Abs(x.Value) > BenchmarkPrecision);", + "\n if (misMatchedVariables.Any())", + "\n {", + "\n foreach (var variable in misMatchedVariables)", + "\n {", + "\n var message = variable.ToIdentityString();", + "\n var bmValue = expected.FirstOrDefault(x => x.AocType == variable.AocType && ", + "\n x.Novelty == variable.Novelty &&", + "\n x.DataNode == variable.DataNode && ", + "\n x.EstimateType == variable.EstimateType && ", + "\n x.AmountType == variable.AmountType && ", + "\n x.EconomicBasis == variable.EconomicBasis && ", + "\n x.AccidentYear == variable.AccidentYear", + "\n )?.Value ?? 0.0d;", + "\n var computedValue = computed.FirstOrDefault(x => x.AocType == variable.AocType && ", + "\n x.Novelty == variable.Novelty &&", + "\n x.DataNode == variable.DataNode && ", + "\n x.EstimateType == variable.EstimateType && ", + "\n x.AmountType == variable.AmountType && ", + "\n x.EconomicBasis == variable.EconomicBasis && ", + "\n x.AccidentYear == variable.AccidentYear", + "\n )?.Value ?? 0.0d;", + "\n errors.Add(new BenchmarkTestResult(\"Value does not match for Variable: \" + message, -bmValue, computedValue));", + "\n }", + "\n }", + "\n return errors;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_OGAdCYiJ0WN7EbtgA4faQ", + "cell_type": "markdown", + "source": [ + "# Test Runner" + ], + "metadata": {} + }, + { + "id": "a5OzvwT_d0Gm2H4gGqcvEA", + "cell_type": "code", + "source": [ + "public bool ValidateMainTab(IDataRow mainRow, string reportingNode, int year, int month)", + "\n{", + "\n if (!int.TryParse(mainRow[nameof(PartitionByReportingNodeAndPeriod.Year)]?.ToString(), NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite , CultureInfo.InvariantCulture, out var mainYear))", + "\n throw new Exception(\"Value Year cannot be parsed.\"); ", + "\n if (!int.TryParse(mainRow[nameof(PartitionByReportingNodeAndPeriod.Month)]?.ToString(), NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite , CultureInfo.InvariantCulture, out var mainMonth))", + "\n throw new Exception(\"Value Month cannot be parsed.\"); ", + "\n var mainReportingNode = mainRow[nameof(PartitionByReportingNodeAndPeriod.ReportingNode)].ToString();", + "\n ", + "\n return reportingNode == mainReportingNode && year == mainYear && month == mainMonth;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HeqY0awSAUWsxllqn3M_AQ", + "cell_type": "code", + "source": [ + "var errorList = new List();", + "\n", + "\nforeach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", + "\n{", + "\n var reportingNode = g.Key.ReportingNode;", + "\n var year = g.Key.Year;", + "\n var month = g.Key.Month;", + "\n string scenario = null;", + "\n ", + "\n //Set up Args and storage", + "\n await DataSource.Partition.SetAsync(new {ReportingNode = reportingNode, ", + "\n Year= year, ", + "\n Month = month, ", + "\n Scenario = scenario});", + "\n var partition = (await DataSource.Query().ToArrayAsync())", + "\n .SingleOrDefault(x => x.ReportingNode == reportingNode && x.Year== year && x.Month == month && x.Scenario == scenario)?.Id ?? new Guid();", + "\n ", + "\n var computedVariablesByEstimateType = (await DataSource.Query().ToArrayAsync()).ToDictionaryGrouped(x => x.EstimateType, x => x.ToArray());", + "\n", + "\n foreach (var bmfile in g)", + "\n {", + "\n var extension = System.IO.Path.GetExtension(bmfile.FileName);", + "\n var stream = await Project.FileStorage.ReadAsync(bmfile.FileName);", + "\n //Read Bm csv", + "\n var bmDataTable = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync());", + "\n", + "\n var mainTab = bmDataTable.Tables[Main].Rows.First();", + "\n if(!ValidateMainTab(mainTab, reportingNode, year, month))", + "\n throw new Exception(\"Metadata and main tab of the Benchmark are different.\");", + "\n ", + "\n var bmTableName = bmDataTable.Tables.Single(x => x.TableName != Main).TableName;", + "\n var bmVariables = bmDataTable.Tables[bmTableName].Rows.Select(x => CreateVariable(x, partition));", + "\n ", + "\n //Get the computed Data", + "\n var computedVariables = computedVariablesByEstimateType.TryGetValue(bmTableName, out var ret) ? ret : Enumerable.Empty();", + "\n ", + "\n //CompareAgainstBm", + "\n if (bmVariables.Any() || computedVariables.Any()) //TODO we are adding duplicates here", + "\n errorList = errorList.Concat(CompareAgainstBm(errorList, bmVariables, computedVariables)).ToList();", + "\n }", + "\n}", + "\nerrorList = errorList.Distinct().ToList();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9p0HZCWtX0SPrElo9W915Q", + "cell_type": "code", + "source": [ + "errorList.Count().Should().Be(0)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "EBnAVHo3qEK4kPd1D8kPOw", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/ImportStorageTest.ipynb b/Test/ImportStorageTest.ipynb new file mode 100644 index 00000000..93d24cd9 --- /dev/null +++ b/Test/ImportStorageTest.ipynb @@ -0,0 +1,707 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "hKqEq5tZqUm8XFAYsSBT8A", + "cell_type": "markdown", + "source": [ + "

Import Storage Test

" + ], + "metadata": {} + }, + { + "id": "a__Hz48NY0-0cWKJL87Vzg", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hLZ53C2rWEanpIfkyRA2Rg", + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ], + "metadata": {} + }, + { + "id": "8-W8hpcYnEm17E9gRTCLnQ", + "cell_type": "code", + "source": [ + "Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Dpy4U4VA5U-HxqmmZfHkmw", + "cell_type": "markdown", + "source": [ + "# Test IfrsVariables Query" + ], + "metadata": {} + }, + { + "id": "irUVLmmRJEyCsUkl3sPquQ", + "cell_type": "code", + "source": [ + "var gic = \"DT1.1\";", + "\nvar gric = \"DTR1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dihIAZaujUK6GuXDUo7Y_A", + "cell_type": "code", + "source": [ + "//Define partition", + "\nvar args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Actual);", + "\nvar partition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);", + "\n", + "\nvar previousPeriodPartition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year - 1 && ", + "\n x.Month == MonthInAYear && x.Scenario == args.Scenario);", + "\nif(previousPeriodPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "N8Yf6JjnRU6Q4jUFGmqn3Q", + "cell_type": "code", + "source": [ + "public async Task CheckIfrsVariablesFromImportStorageAsync(string importFormat, IEnumerable inputDataSetForWorkspace, IEnumerable inputDataSetForDataSource, IEnumerable ivsBenchmark)", + "\n{", + "\n //Prepare Workspace and DataSource", + "\n await Workspace.UpdateAsync(inputDataSetForWorkspace);", + "\n await DataSource.UpdateAsync(inputDataSetForDataSource);", + "\n ", + "\n //Set up import storage and test universe", + "\n var testStorage = new ImportStorage(args with {ImportFormat = importFormat}, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var ivs = testStorage.IfrsVariablesByImportIdentity.SelectMany(x => x.Value);", + "\n ", + "\n //Clean up Workspace", + "\n //Workspace.Reset(); ", + "\n await Workspace.DeleteAsync(inputDataSetForWorkspace); ", + "\n await DataSource.DeleteAsync(inputDataSetForDataSource); ", + "\n ", + "\n var errors = new List();", + "\n ", + "\n var extraVariablesInStorage = ivs.Except(ivsBenchmark).Select(x => x.ToIdentityString()).ToArray();", + "\n if(extraVariablesInStorage.Any()) errors.Add( $\"IfrsVariables in the storage contain the following items that are not present in the benchmark:\\n{string.Join(\"\\n\",extraVariablesInStorage)}.\" );", + "\n ", + "\n var extraVariablesInBenchmark = ivsBenchmark.Except(ivs).Select(x => x.ToIdentityString()).ToArray();", + "\n if(extraVariablesInBenchmark.Count() > 0) errors.Add( $\"IfrsVariables in the benchmark contain the following items that are not present in the storage:\\n{string.Join(\"\\n\",extraVariablesInBenchmark)}.\" );", + "\n ", + "\n //find duplicates in storage", + "\n var ivsByIdentityString = ivs.GroupBy(x => x.ToIdentityString()).Where(x => x.Count() > 1).Select(x => x.Key);", + "\n if(ivsByIdentityString.Any()) errors.Add($\"IfrsVariables in the storage have duplicated items for:\\n{string.Join(\"\\n\",ivsByIdentityString)}.\");", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bcPOId_540aVhl-n5wKQCA", + "cell_type": "code", + "source": [ + "//There is a previous year, and it's the first time Actuals are imported for the current year", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BqLp5tAfAUO_fcHJmxq2_A", + "cell_type": "code", + "source": [ + "//There is a previous year, and it's the second time Actuals are imported for the current year (reimport)", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 150.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 200.0},", + "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 450.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1RKRtwQOPkKisKG03fEbnQ", + "cell_type": "code", + "source": [ + "//There is a previous year, Cashflows were already imported and Actuals are imported for the first time", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.I, EstimateType = EstimateTypes.BE};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -20.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.AA, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -20.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jxo0gCLAhUWGDdD50PTpxA", + "cell_type": "code", + "source": [ + "//There is a previous year, Cashflows and Actuals were already imported and Actuals are imported again", + "\nvar basicAdvanceActualIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar basicBeIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.I, EstimateType = EstimateTypes.BE};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicBeIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 1000.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n basicAdvanceActualIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicAdvanceActualIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = 150.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = 200.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.EOP, Value = 450.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicBeIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0BeFF1dpdEmZVGTCvBJgaw", + "cell_type": "code", + "source": [ + "//There is a previous year for Primary Scope (GRIC10) ", + "\n//There is a previous and current year for Secondary Scope (GIC10), ", + "\n//It's the first time Actuals are imported for the current year", + "\n", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gric, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n //Year", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.CL, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 666.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.CL, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 666.0},", + "\n //Year -1", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n //From previous Period", + "\n //Actuals", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n //Cashflow", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 1000.0},", + "\n ", + "\n //From current Period", + "\n //from DB", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n ", + "\n //from workspace", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XRCB3ZClf0-ZJpfkzljWUg", + "cell_type": "markdown", + "source": [ + "# Data Node Parameter related logic" + ], + "metadata": {} + }, + { + "id": "JbLy2z9stkeeonRZwUG3yQ", + "cell_type": "markdown", + "source": [ + "## Data Preparation" + ], + "metadata": {} + }, + { + "id": "RjbciW5_FECXbQhnQZ4DwQ", + "cell_type": "code", + "source": [ + "//Define partition", + "\nvar args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", + "\n", + "\nvar reportingNodePartition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Scenario == args.Scenario);", + "\nif(reportingNodePartition == null) ApplicationMessage.Log(Error.PartitionNotFound);", + "\n", + "\n", + "\nvar currentPartition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(currentPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);", + "\n", + "\n", + "\nvar previousPeriodPartition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year - 1 && ", + "\n x.Month == MonthInAYear && x.Scenario == args.Scenario);", + "\nif(previousPeriodPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "E09b-uWxcUa8abPa94ONVA", + "cell_type": "code", + "source": [ + "var sampleGic = new GroupOfInsuranceContract(){Portfolio = \"P1\"};", + "\nvar inputDataGic = new GroupOfInsuranceContract[]{ sampleGic with {SystemName = \"Gross1\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGic with {SystemName = \"Gross2\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGic with {SystemName = \"Gross3\", LiabilityType = LiabilityTypes.LRC},", + "\n };", + "\n", + "\nvar sampleGric = new GroupOfReinsuranceContract(){Portfolio = \"ReP1\"};", + "\nvar inputDataGric = new GroupOfReinsuranceContract[]{ sampleGric with {SystemName = \"Reins1\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGric with {SystemName = \"Reins2\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGric with {SystemName = \"Reins3\", LiabilityType = LiabilityTypes.LRC},", + "\n };", + "\nvar sampleDnState = new DataNodeState {Partition = reportingNodePartition.Id, Year = args.Year, Month = args.Month, State = State.Active};", + "\nvar inputDataState = new DataNodeState[]{ sampleDnState with {DataNode = \"Gross1\"} ,", + "\n sampleDnState with {DataNode = \"Gross2\"} ,", + "\n sampleDnState with {DataNode = \"Gross3\"} ,", + "\n sampleDnState with {DataNode = \"Reins1\"} ,", + "\n sampleDnState with {DataNode = \"Reins2\"} ,", + "\n sampleDnState with {DataNode = \"Reins3\"} ,", + "\n };", + "\n", + "\nvar samplePreviousDnParam = new InterDataNodeParameter {Partition = reportingNodePartition.Id, ReinsuranceCoverage = 1, Year = args.Year -1, Month = args.Month};", + "\nvar sampleCurrentDnParam = new InterDataNodeParameter {Partition = reportingNodePartition.Id, ReinsuranceCoverage = 1, Year = args.Year, Month = args.Month};", + "\nvar inputDataParameter = new InterDataNodeParameter[]{", + "\n samplePreviousDnParam with {DataNode = \"Gross3\", LinkedDataNode = \"Reins3\", ReinsuranceCoverage = 1},", + "\n samplePreviousDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins1\", ReinsuranceCoverage = 0.1},", + "\n samplePreviousDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.2},", + "\n samplePreviousDnParam with {DataNode = \"Gross2\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.3},", + "\n sampleCurrentDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins1\", ReinsuranceCoverage = 0.5},", + "\n sampleCurrentDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.6},", + "\n sampleCurrentDnParam with {DataNode = \"Gross2\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.7},", + "\n sampleCurrentDnParam with {DataNode = \"Gross3\", LinkedDataNode = \"Reins3\", ReinsuranceCoverage = 1.0},", + "\n };", + "\n", + "\nvar sampleRawVar = new RawVariable{AmountType = AmountTypes.PR, AocType = AocTypes.CL, Novelty = Novelties.C, Partition = currentPartition.Id};" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "o8JTuDpfTkGmD7Wt0jogsQ", + "cell_type": "code", + "source": [ + "public async Task PrepareWorkspaceDataNodes()", + "\n{", + "\n await Workspace.UpdateAsync(inputDataGic);", + "\n await Workspace.UpdateAsync(inputDataGric);", + "\n await Workspace.UpdateAsync(inputDataState);", + "\n await Workspace.UpdateAsync(inputDataParameter);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Ozbv22ctukacRUyws-K7bw", + "cell_type": "code", + "source": [ + "public async Task CleanWorkspaceDataNodes()", + "\n{", + "\n await Workspace.DeleteAsync(inputDataGic);", + "\n await Workspace.DeleteAsync(inputDataGric);", + "\n await Workspace.DeleteAsync(inputDataState);", + "\n await Workspace.DeleteAsync(inputDataParameter);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZYnBpUzNEkWsk0zRWkUu-g", + "cell_type": "markdown", + "source": [ + "## Get Underlying Gic" + ], + "metadata": {} + }, + { + "id": "P-7XAjZPD0i7yEALKAwsnA", + "cell_type": "code", + "source": [ + "public async Task CheckGetUnderlyingGicsAsync(RawVariable[] inputDataVariable, Dictionary> underlyingGicBm)", + "\n{", + "\n var errors = new List();", + "\n ", + "\n await PrepareWorkspaceDataNodes();", + "\n await Workspace.UpdateAsync(inputDataVariable);", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", + "\n ", + "\n foreach (var dn in primaryScopeDn)", + "\n {", + "\n var id = new ImportIdentity(){DataNode = dn};", + "\n if ( underlyingGicBm[dn].Except(testStorage.GetUnderlyingGic(id)).Count() != 0 )", + "\n errors.Add( $\"Underlying Gics for DataNode {dn} not matching with BM. Computed: \\n{string.Join(\"\\n\",testStorage.GetUnderlyingGic(id))} \\n Expected : \\n{string.Join(\"\\n\",underlyingGicBm[dn])}\" );", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query());", + "\n await CleanWorkspaceDataNodes();", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gr9n4fPaC0-7JF_Wv00Nzw", + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar underlyingGicBm = new Dictionary>(){", + "\n {\"Reins1\",new string[]{\"Gross1\"}},", + "\n {\"Reins2\",new string[]{\"Gross1\",\"Gross2\"}},", + "\n};", + "\n", + "\nawait CheckGetUnderlyingGicsAsync(inputDataVariable, underlyingGicBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "z4P2iM4Dwk2p49Y6p3nVKw", + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar underlyingGicBm = new Dictionary>(){", + "\n {\"Reins2\",new string[]{\"Gross1\",\"Gross2\"}},", + "\n};", + "\n", + "\nawait CheckGetUnderlyingGicsAsync(inputDataVariable, underlyingGicBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-L7jFDaEmkyVlAyPPIHFHQ", + "cell_type": "markdown", + "source": [ + "## Get Reinsurance Coverage" + ], + "metadata": {} + }, + { + "id": "YwMf2AGd8kWzNmNK5TaXeA", + "cell_type": "code", + "source": [ + "public async Task CheckGetReinsuranceCoverageAsync(RawVariable[] inputDataVariable, ", + "\n Dictionary<(string, string),double> reinsCovBoPBm, ", + "\n Dictionary<(string, string),double> reinsCovEoPBm)", + "\n{", + "\n var errors = new List();", + "\n", + "\n await PrepareWorkspaceDataNodes();", + "\n await Workspace.UpdateAsync(inputDataVariable);", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", + "\n ", + "\n foreach (var dn in primaryScopeDn)", + "\n {", + "\n var aocTypes = new AocStep[]{ new AocStep(AocTypes.BOP, Novelties.I), new AocStep(AocTypes.RCU, Novelties.I) };", + "\n foreach (var aoc in aocTypes)", + "\n {", + "\n var bm = aoc.AocType == AocTypes.BOP ? reinsCovBoPBm : reinsCovEoPBm;", + "\n var id = new ImportIdentity(){DataNode = dn, AocType = aoc.AocType, Novelty = aoc.Novelty};", + "\n ", + "\n var computedReinsCov = testStorage.GetUnderlyingGic(id)", + "\n .Select(gic => (g: gic, value: testStorage.GetReinsuranceCoverage(id, gic)))", + "\n .ToDictionary(x => (dn,x.g), x => x.value);", + "\n ", + "\n if( bm.Keys.Where(x => x.Item1 == dn).Except(computedReinsCov.Keys).Count() != 0)", + "\n errors.Add( $\"Gric-Gic links not matching with BM for DataNode {dn} and AocType {aoc.AocType}. \\n Computed: \\n{string.Join(\"\\n\",computedReinsCov.Keys)} \\n Expected: \\n{string.Join(\"\\n\",bm.Keys)}\" );", + "\n ", + "\n foreach (var reinsCov in computedReinsCov)", + "\n {", + "\n var bmKvp = bm.Single(x => x.Key.Item1 == reinsCov.Key.Item1 && x.Key.Item2 == reinsCov.Key.Item2); ", + "\n if( Math.Abs(bmKvp.Value - reinsCov.Value) > Precision )", + "\n errors.Add( $\"{dn}-{reinsCov.Key.Item2} Reinsurance Coverage not matching with BM for AocType {aoc.AocType}: \\n Computed: {reinsCov.Value} \\n Expected: {bmKvp.Value}\");", + "\n }", + "\n }", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query());", + "\n await CleanWorkspaceDataNodes();", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bVG2ah0oSUimPFlFmvkYwg", + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar reinsCovBoPBm = new Dictionary<(string, string),double>(){", + "\n {(\"Reins1\",\"Gross1\"),0.1},", + "\n {(\"Reins2\",\"Gross1\"),0.2},", + "\n {(\"Reins2\",\"Gross2\"),0.3},", + "\n};", + "\n", + "\nvar reinsCovEoPBm = new Dictionary<(string, string),double>(){", + "\n {(\"Reins1\",\"Gross1\"),0.5},", + "\n {(\"Reins2\",\"Gross1\"),0.6},", + "\n {(\"Reins2\",\"Gross2\"),0.7},", + "\n};", + "\n", + "\nawait CheckGetReinsuranceCoverageAsync(inputDataVariable, reinsCovBoPBm, reinsCovEoPBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2DHkaQC6A0eHln9BqSBrLA", + "cell_type": "markdown", + "source": [ + "## Primary and Secondary Scope" + ], + "metadata": {} + }, + { + "id": "QxMSzO5gJU2IlukS0y4uIg", + "cell_type": "code", + "source": [ + "public async Task CheckSecondaryScopeAsync(RawVariable[] inputDataVariable, string[] primaryScopeBm, string[] secondaryScopeBm)", + "\n{", + "\n var errors = new List();", + "\n ", + "\n await PrepareWorkspaceDataNodes();", + "\n await Workspace.UpdateAsync(inputDataVariable);", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var activeDn = (await Workspace.Query().ToArrayAsync()).Select(x => x.DataNode);", + "\n ", + "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", + "\n ", + "\n foreach (var dn in activeDn)", + "\n {", + "\n //PrimaryScope", + "\n if ( primaryScopeBm.Contains(dn) && !primaryScopeDn.Contains(dn))", + "\n errors.Add( $\"DataNode {dn} is not added to the primary scope.\" );", + "\n if( !primaryScopeBm.Contains(dn) && primaryScopeDn.Contains(dn))", + "\n errors.Add( $\"DataNode {dn} is added to the primary scope but should have not.\" );", + "\n ", + "\n //SecondaryScope", + "\n if ( secondaryScopeBm.Contains(dn) && !testStorage.IsSecondaryScope(dn))", + "\n errors.Add( $\"DataNode {dn} is not added to the secondary scope.\" );", + "\n if( !secondaryScopeBm.Contains(dn) && testStorage.IsSecondaryScope(dn))", + "\n errors.Add( $\"DataNode {dn} is added to the secondary scope but should have not.\" );", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query());", + "\n await CleanWorkspaceDataNodes();", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ky7k1tjYZkuJI5AN4f01_g", + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar primaryScopeBm = new string[]{\"Reins1\", \"Reins2\"};", + "\nvar secondaryScopeBm = new string[]{\"Gross1\", \"Gross2\"};", + "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Q7y5fkIm8Em2WkXn5-f3XA", + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n };", + "\nvar primaryScopeBm = new string[]{\"Reins1\"};", + "\nvar secondaryScopeBm = new string[]{\"Gross1\"};", + "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kwq8FSvW2EOvmcWpP4NtmA", + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Gross1\"},", + "\n };", + "\nvar primaryScopeBm = new string[]{\"Reins1\",\"Gross1\",\"Reins2\"};", + "\nvar secondaryScopeBm = new string[]{\"Gross2\"};", + "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DXx87fO500-tCJcptCKJTw", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/MapTemplateAndImportTest.ipynb b/Test/MapTemplateAndImportTest.ipynb new file mode 100644 index 00000000..faec8763 --- /dev/null +++ b/Test/MapTemplateAndImportTest.ipynb @@ -0,0 +1,564 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "wmh8VD39zE-Ey7EfKLRdmQ", + "cell_type": "markdown", + "source": [ + "

Test Map Template Export and Import

" + ], + "metadata": {} + }, + { + "id": "Eo2BObmmzkiC0vc1-cdonA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Utils/UtilityMethods\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vtn0keYdmU6rEcmTON0UwQ", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CQ_YlVaPK0qoXE3iHNGsUg", + "cell_type": "markdown", + "source": [ + "# Test Empty Database" + ], + "metadata": {} + }, + { + "id": "DGQyghJ1AEyT_RB_hXzB1Q", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7R24zOJDXk2KI7i6-FH_2g", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q9WzUZfKq06UWRvmoF38IA", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "U3QNuXi7wECZryFP8aqCyw", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LBo4BnS_u02vMgAJhq45-Q", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1eQBRJgPu0ei17Q9Re_f5g", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4uAB9H_tcEq0wQ9u2feWZw", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_I6QcbDYvEW7cP4LqHyMDQ", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3o3EdNofI0Sb7P0VjQv3TA", + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6EGAGpWhukuN5vjCcTs51Q", + "cell_type": "markdown", + "source": [ + "# Test Map Template" + ], + "metadata": {} + }, + { + "id": "9s3hXWWbyU-1iykcDAJ-XA", + "cell_type": "markdown", + "source": [ + "## Data Node" + ], + "metadata": {} + }, + { + "id": "m6tebAPzHkaRzelYIbeZOg", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\n", + "\nstatic var partition = new PartitionByReportingNode() { ReportingNode = \"CH\" };", + "\nstatic var filename = \"TestMapTemplateDataNode\";", + "\n", + "\nWorkspace.InitializeFrom(DataSource);", + "\nawait Workspace.Partition.SetAsync( partition );", + "\n", + "\nvar ips = Workspace.Query().ToArray();", + "\nvar rps = Workspace.Query().ToArray();", + "\nvar gics = Workspace.Query().ToArray();", + "\nvar grics = Workspace.Query().ToArray();", + "\n", + "\nvar exportResult = await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .PortfolioConfiguration()", + "\n .PortfolioConfiguration()", + "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", + "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync();", + "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", + "\n", + "\n// check that exporter generates only the desired columns ", + "\nvar extension = \".xlsx\";", + "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", + "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar mainCols = new[]{nameof(PartitionByReportingNode.ReportingNode)};", + "\nvar portfolioCols = new[]{nameof(Portfolio.SystemName),nameof(Portfolio.DisplayName),nameof(Portfolio.ContractualCurrency),", + "\n nameof(Portfolio.LineOfBusiness),nameof(Portfolio.OciType),nameof(Portfolio.ValuationApproach)};", + "\nvar gicCols = new[]{nameof(GroupOfContract.SystemName),nameof(GroupOfContract.DisplayName),nameof(GroupOfContract.AnnualCohort),", + "\n nameof(GroupOfContract.LiabilityType),nameof(InsurancePortfolio),nameof(GroupOfContract.Profitability)};", + "\nvar gricCols = new[]{nameof(GroupOfContract.SystemName),nameof(GroupOfContract.DisplayName),nameof(GroupOfContract.AnnualCohort),", + "\n nameof(GroupOfContract.LiabilityType),nameof(ReinsurancePortfolio),nameof(GroupOfContract.Profitability),nameof(GroupOfContract.Partner)};", + "\n", + "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", + "\nportfolioCols.Intersect(tables.Tables[nameof(InsurancePortfolio)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(portfolioCols.Length); ", + "\nportfolioCols.Intersect(tables.Tables[nameof(ReinsurancePortfolio)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(portfolioCols.Length); ", + "\ngicCols.Intersect(tables.Tables[nameof(GroupOfInsuranceContract)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(gicCols.Length); ", + "\ngricCols.Intersect(tables.Tables[nameof(GroupOfReinsuranceContract)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(gricCols.Length); ", + "\n", + "\n// check that imported data matches the exported data", + "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", + "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", + "\nawait storage.InitializeAsync();", + "\n", + "\nawait UploadDataNodesToWorkspaceAsync(filename+\".xlsx\");", + "\nUtils.EqualityComparer(ips, Workspace.Query().ToArray());", + "\nUtils.EqualityComparer(rps, Workspace.Query().ToArray());", + "\nUtils.EqualityComparer(gics, Workspace.Query().ToArray());", + "\nUtils.EqualityComparer(grics, Workspace.Query().ToArray());", + "\n", + "\n" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zOGhxg1IhESG_D1THv63sA", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nRI-ZaELKE6ClMkV4BLEUg", + "cell_type": "markdown", + "source": [ + "## Data Node State" + ], + "metadata": {} + }, + { + "id": "CrT3UgfIWEucISLJOkDARA", + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2021, Month = 3 };", + "\nstatic var filename = \"TestMapTemplateDataNodeState\";", + "\n", + "\nWorkspace.InitializeFrom(DataSource);", + "\nawait Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );", + "\nawait Workspace.Partition.SetAsync( partition );", + "\n", + "\nvar dataNodeStates = await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year)", + "\n .GroupBy(x => x.DataNode)", + "\n .Select(x => x.OrderByDescending(y => y.Year).ThenByDescending(y => y.Month))", + "\n .Select(x => x.Last())", + "\n .ToArrayAsync();", + "\n", + "\nvar exportResult = await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .StateEnumConfiguration() ", + "\n .DataNodeStateConfiguration(dataNodeStates)", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync();", + "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", + "\n", + "\n// check that exporter generates only the desired columns ", + "\nvar extension = \".xlsx\";", + "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", + "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", + "\n nameof(PartitionByReportingNodeAndPeriod.Year),", + "\n nameof(PartitionByReportingNodeAndPeriod.Month)};", + "\nvar dataNodeStateCols = new[]{nameof(DataNodeState.DataNode),nameof(DataNodeState.State)};", + "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", + "\ndataNodeStateCols.Intersect(tables.Tables[\"DataNodeState\"].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(dataNodeStateCols.Length);", + "\n", + "\n// check that imported data matches the exported data ", + "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", + "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", + "\nawait storage.InitializeAsync();", + "\n", + "\nawait UploadDataNodeStateToWorkspaceAsync(filename+\".xlsx\");", + "\n", + "\n// Workspace is empty because ValidateDataNodeStatesAsync removes the entry, since this is already present in the DataSource.", + "\nWorkspace.Query().ToArray().Should().BeEmpty();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QNDCIM7e2UWjQM13S1JZ8A", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WVvsogjgCkGlxke3IAGi_g", + "cell_type": "markdown", + "source": [ + "## DataNodeParameter" + ], + "metadata": {} + }, + { + "id": "4U2oeNzYEEKxoH98EmjOxg", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\nstatic var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };", + "\nvar partitionByReportingNode = (await DataSource.Query().Where(x => x.ReportingNode == partition.ReportingNode).ToArrayAsync()).Single();", + "\nstatic var filename = \"TestMapTemplateDataNodeParameter\";", + "\nvar singleDataNodeParamBm = await DataSource.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month && x.Partition == partitionByReportingNode.Id ).ToArrayAsync();", + "\nvar interDataNodeParamBm = await DataSource.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month && x.Partition == partitionByReportingNode.Id ).ToArrayAsync();", + "\nawait Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );", + "\nawait Workspace.Partition.SetAsync( partition );", + "\n//--------------------Export Map Template--------------------------", + "\n//--------------------From MapTemplate NB--------------------------", + "\nvar dataNodeParameters = (await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", + "\n .GroupBy(x => x.GetType().Name)", + "\n .ToDictionary(x => x.Key, ", + "\n x => x.GroupBy(y => y.DataNode)", + "\n .Select(y => y.OrderByDescending(z => z.Year).ThenByDescending(z => z.Month))", + "\n .Select(y => y.First())", + "\n .ToArray() );", + "\nvar exportResult = await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .DataNodeParameterConfiguration(dataNodeParameters)", + "\n .MainTabConfiguration(partition)", + "\n.ExecuteAsync();", + "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", + "\n//-----------------------------------------------------------------", + "\n// check that exporter generates only the desired columns ", + "\nvar extension = \".xlsx\";", + "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", + "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", + "\n nameof(PartitionByReportingNodeAndPeriod.Year),", + "\n nameof(PartitionByReportingNodeAndPeriod.Month),", + "\n nameof(PartitionByReportingNodeAndPeriod.Scenario)};", + "\nvar singleDataNodeParamCols = new[]{nameof(DataNode),", + "\n nameof(SingleDataNodeParameter.PremiumAllocation)};", + "\nvar interDataNodeParamCols = new[]{nameof(DataNodeParameter.DataNode),", + "\n nameof(InterDataNodeParameter.LinkedDataNode),", + "\n nameof(InterDataNodeParameter.ReinsuranceCoverage)};", + "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", + "\nsingleDataNodeParamCols.Intersect(tables.Tables[nameof(SingleDataNodeParameter)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(singleDataNodeParamCols.Length);", + "\ninterDataNodeParamCols.Intersect(tables.Tables[nameof(InterDataNodeParameter)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(interDataNodeParamCols.Length);", + "\n// check that imported data matches the exported data ", + "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", + "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", + "\nvar targetPartitionByReportingNodeId = new Guid();", + "\nawait storage.InitializeAsync();", + "\nawait UploadDataNodeParameterToWorkspaceAsync(filename+\".xlsx\", targetPartitionByReportingNodeId);", + "\nvar expectedSingleDataNodeParamBm = Workspace.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month).ToArray();", + "\nvar expectedInterDataNodeParamBm = Workspace.Query().ToArray();", + "\nUtils.EqualityComparer(singleDataNodeParamBm, expectedSingleDataNodeParamBm);", + "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "va-MijisUkepqmVMOLJj1Q", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "x-al4I6dSk6STwc4oylwCg", + "cell_type": "markdown", + "source": [ + "# Test Import Validation" + ], + "metadata": {} + }, + { + "id": "LG8H5pXCv0iU38uHNCvxEA", + "cell_type": "markdown", + "source": [ + "## Data Node State: entries cannot be imported which change status from Inactive to Active" + ], + "metadata": {} + }, + { + "id": "nmuP0vEnLEqamwIsJpCSfQ", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\nvar partition = Workspace.Query().Where(x => x.ReportingNode == \"CH\").ToArray().FirstOrDefault();", + "\nawait Workspace.Partition.SetAsync(partition);", + "\n", + "\nvar itemInactive = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Inactive, Partition = partition.Id };", + "\nvar itemActive = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", + "\n", + "\n// Define GIC1 State as Inactive", + "\nvar persistentDataNodeDataByDataNode = new Dictionary ", + "\n{", + "\n [\"GIC1\"] = new DataNodeData() {DataNode = \"GIC1\", State = itemInactive.State, Year = itemInactive.Year, Month = itemInactive.Month},", + "\n};", + "\n", + "\n// Set GIC1 from Inactive into Active", + "\nawait Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\nawait Workspace.UpdateAsync(itemActive);", + "\n", + "\n// Test Validation", + "\nActivity.Start();", + "\nawait ValidateDataNodeStatesAsync(persistentDataNodeDataByDataNode);", + "\nActivity.HasErrors().Should().Be(true);", + "\nvar log = Activity.Finish().Errors.First().ToString().Substring(40);", + "\n(log.Substring(0,log.Length-2) == Get(Error.ChangeDataNodeState, \"GIC1\")).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "i9-3PyG3uEW-g1CBte_ePA", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "19OZTLJqEkywyseKKCm4Uw", + "cell_type": "markdown", + "source": [ + "## Data Node State: Validation removes the entry when the DataSource already contains a previous version " + ], + "metadata": {} + }, + { + "id": "_ezSKNws4E-nHzlCVI0fIg", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\nvar partition = Workspace.Query().Where(x => x.ReportingNode == \"CH\").ToArray().FirstOrDefault();", + "\nawait Workspace.Partition.SetAsync(partition);", + "\n", + "\nvar itemPrevious = new DataNodeState { Year = 2022, Month = 3, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", + "\nvar itemImport = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", + "\n", + "\n// Define persisted Data Node State", + "\nvar persistentDataNodeDataByDataNode = new Dictionary", + "\n{", + "\n [\"GIC1\"] = new DataNodeData() {DataNode = itemPrevious.DataNode, State = itemPrevious.State, Year = itemPrevious.Year, Month = itemPrevious.Month},", + "\n};", + "\n", + "\n// Reimport Data Node State for GIC1 with State unchanged", + "\nawait Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\nawait Workspace.UpdateAsync(itemImport);", + "\n", + "\nawait ValidateDataNodeStatesAsync(persistentDataNodeDataByDataNode);", + "\n", + "\n// Check that the new redundant State is removed from the Workspace", + "\nWorkspace.Query().ToArray().Should().BeEmpty();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Pou7Chyva0qd3qanB75kiQ", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KyDTS_jfUkOIkYt3INVPtA", + "cell_type": "markdown", + "source": [ + "## Data Node Parameters : Validations" + ], + "metadata": {} + }, + { + "id": "vkBb3hOe3UuG2RuMIIoUfg", + "cell_type": "code", + "source": [ + "public async Task CheckErrors(string inputFileName, List errorBms)", + "\n{", + "\n var partitionId = new Guid();", + "\n var log = await UploadDataNodeParameterToWorkspaceAsync(inputFileName, partitionId);", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n errorBms.Intersect(log.Errors.Select(x => x.ToString().Substring(0,x.ToString().Length-2).Substring(40)).ToArray()).Count().Should().Be(errorBms.Count());", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZSI2-sVTMkuZTg61UVXucg", + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_InvalidDataNode.csv\";", + "\nvar errorsBm = new List(){Get(Error.InvalidDataNode, \"DataNodeInvalid0\"),", + "\n Get(Error.InvalidDataNode, \"DataNodeInvalid1\"),", + "\n Get(Error.InvalidDataNode, \"DataNodeInvalid2\")};", + "\nawait CheckErrors(inputFileName, errorsBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2unWYjVwA0mJbyzeVCVg8A", + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_Duplicate.csv\";", + "\nvar errorsBm = new List(){Get(Error.DuplicateSingleDataNode, \"DT1.1\"),", + "\n Get(Error.DuplicateInterDataNode, \"DT1.1\",\"DTR1.1\"),};", + "\nawait CheckErrors(inputFileName, errorsBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uH8Fn9T2-EGO0hSWBk1Yxg", + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_InvalidReinsCov.csv\";", + "\nvar errorsBm = new List(){Get(Error.ReinsuranceCoverageDataNode, \"DT1.1\",\"DT1.1\")};", + "\nawait CheckErrors(inputFileName, errorsBm);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lkXchyRo9U6x7lnhcliuTg", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/QueriesTest.ipynb b/Test/QueriesTest.ipynb new file mode 100644 index 00000000..c91c0f6b --- /dev/null +++ b/Test/QueriesTest.ipynb @@ -0,0 +1,535 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "_IqpJ1KMUEGYZFSIeqTQfg", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Utils/UtilityMethods\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6-FaBdsHfk2QsR8mnBirig", + "cell_type": "code", + "source": [ + "var gic = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lpSLXRR8SUWTReUAPXdCGw", + "cell_type": "markdown", + "source": [ + "# Test Load Current and Previous Parameter for Yield Curve" + ], + "metadata": {} + }, + { + "id": "MSTglT9520GqkMaeJVIboA", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vuGCdF-iCU6ZaQX6iiwCaA", + "cell_type": "code", + "source": [ + "public async Task CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(Args args, IEnumerable testData, ", + "\n (int Year, int Month) expectedCurrentPeriod, ", + "\n (int Year, int Month) expectedPreviousPeriod)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n var eurCurrentAndPreviousYieldCurve = (await Workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.Currency))[\"EUR\"];", + "\n ", + "\n //Check Current Period", + "\n eurCurrentAndPreviousYieldCurve[CurrentPeriod].Year.Should().Be(expectedCurrentPeriod.Year);", + "\n eurCurrentAndPreviousYieldCurve[CurrentPeriod].Month.Should().Be(expectedCurrentPeriod.Month);", + "\n ", + "\n //Check Previous Period", + "\n eurCurrentAndPreviousYieldCurve[PreviousPeriod].Year.Should().Be(expectedPreviousPeriod.Year);", + "\n eurCurrentAndPreviousYieldCurve[PreviousPeriod].Month.Should().Be(expectedPreviousPeriod.Month);", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RUfdhTU15EaPkO5FVp6qdw", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData.RepeatOnce(), (2020, 9),(2020, 9));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5lBUg6REDUqpF8AFQaSVMw", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData.RepeatOnce(), (2019, 12), (2019, 12));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yvs_kK9a6U-p4_zPj-yeTA", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2020, 6));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9KEHlyMSzEaR6u7TcXWcnQ", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 9), (2020, 9));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TbyTWCzxOEKJ84ZrZjk0ug", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 9}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 9), (2019, 9));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "B0cbAHylv0aRbz8NpHnX7w", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 9}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 12), (2019, 12));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mGbDxghxXkqBy6nh62h5wg", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2018, Month = 9}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 12), (2019, 12));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-aimZbUkbE69ujpiBCQHeg", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 9},", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 6}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 6), (2019, 6));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "z7N6H3nrE0ib9q25l-HOLw", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2015, Month = 9},", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2016, 3));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "G1sMs6vn7UCUx9PcNnX0Zg", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2021, Month = 9},", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3}};", + "\n", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2016, 3));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bTtGvgxoRUuqc2eYUgyavQ", + "cell_type": "markdown", + "source": [ + "# Test Data Node State Query" + ], + "metadata": {} + }, + { + "id": "m6puoprjyUGBYqt7aPTc4A", + "cell_type": "code", + "source": [ + "public async Task CheckLoadDataNodeStateAsync(Args args, IEnumerable testData, bool isExpectedToBeActive)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n var isActive = (await Workspace.LoadDataNodeStateAsync(args)).Keys.Contains(gic);", + "\n ", + "\n isActive.Should().Be(isExpectedToBeActive);", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1rUvJm2L4k-qth-62yWJcA", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,12,Periodicity.Monthly,null);", + "\nvar testData = new DataNodeState[] {new DataNodeState{ DataNode = gic, Year = 2019, Month = 12, State = State.Active },", + "\n new DataNodeState{ DataNode = gic, Year = 2020, Month = 6, State = State.Inactive }};", + "\nawait CheckLoadDataNodeStateAsync(args, testData, false);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "n8zP0mcxgUiGDxpciWfdUQ", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,12,Periodicity.Monthly,null);", + "\nvar testData = new DataNodeState[] {new DataNodeState{ DataNode = gic, Year = 2020, Month = 3, State = State.Active },", + "\n new DataNodeState{ DataNode = gic, Year = 2020, Month = 9, State = State.Inactive }};", + "\nawait CheckLoadDataNodeStateAsync(args, testData, false);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Bm1_QjQMz0GO56QnUrVqwg", + "cell_type": "markdown", + "source": [ + "# Test Load Yield Curve" + ], + "metadata": {} + }, + { + "id": "wAmKPPOo7kGNh3r-uijhJg", + "cell_type": "code", + "source": [ + "public async Task CheckLoadYieldCurveAsync(Args args, IEnumerable testData, ", + "\n (int year , int month) dataNodeYearAndMonth, ", + "\n double expectedCurrentPreviousFirstYcValue,", + "\n double expectedCurrentFirstYcValue,", + "\n double expectedLockedFirstYcValue)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n await Workspace.UpdateAsync(new ReportingNode[]{new ReportingNode{Currency=\"EUR\",SystemName=\"CH\"}});", + "\n ", + "\n var dataNodes = new DataNodeData[]{new DataNodeData{ValuationApproach=\"BBA\", Year = dataNodeYearAndMonth.year, Month = dataNodeYearAndMonth.month, DataNode = gic, ContractualCurrency = \"EUR\"}};", + "\n var eurLockedYieldCurve = (await LoadLockedInYieldCurveAsync(Workspace, args, dataNodes));", + "\n var eurCurrentYieldCurve = (await LoadCurrentYieldCurveAsync(Workspace, args, dataNodes));", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n ", + "\n var errors = new List();", + "\n var currentPrevPeriod = eurCurrentYieldCurve[\"EUR\"][PreviousPeriod].Values.First();", + "\n if(Math.Abs(currentPrevPeriod - expectedCurrentPreviousFirstYcValue) > 1E-8)", + "\n errors.Add( $\"Current YieldCurve for Previous Period not matching:\\n Expected {expectedCurrentPreviousFirstYcValue} \\n Computed {currentPrevPeriod}.\" );", + "\n ", + "\n var currentCurrPeriod = eurCurrentYieldCurve[\"EUR\"][CurrentPeriod].Values.First();", + "\n if(Math.Abs(currentCurrPeriod - expectedCurrentFirstYcValue) > 1E-8)", + "\n errors.Add( $\"Current YieldCurve for Current Period not matching:\\n Expected {expectedCurrentFirstYcValue} \\n Computed {currentCurrPeriod}.\" );", + "\n ", + "\n var lockedYc = eurLockedYieldCurve[gic].Values.First();", + "\n if(Math.Abs(lockedYc - expectedLockedFirstYcValue) > 1E-8)", + "\n errors.Add( $\"LockedIn YieldCurve not matching:\\n Expected {expectedLockedFirstYcValue} \\n Computed {lockedYc}.\" );", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors)); ", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vRCMvk2zpk6YeQlQuLXkRQ", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6, Values = new double[]{0.1,0.2,0.3,0.4,0.5,0.6} }, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3, Values = new double[]{2.1,2.2,2.3,2.4,2.5,2.6} }, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2021, Month = 9, Values = new double[]{4.1,4.2,4.3,4.4,4.5,4.6} },", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3, Values = new double[]{6.1,6.2,6.3,6.4,6.5,6.6} }};", + "\n", + "\nawait CheckLoadYieldCurveAsync(args, testData, (2016, 6), 6.1, 0.1, 6.1);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZL_HAd63MUGyojndKeoyPA", + "cell_type": "markdown", + "source": [ + "# Test Load Data Node Parameter" + ], + "metadata": {} + }, + { + "id": "HHu8-DR7E0Gl3YlOdR0eWA", + "cell_type": "code", + "source": [ + "var gic2 = \"gic2\";", + "\nvar xgic = \"xgic\";", + "\nvar gric1 = \"gric1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VArCCnA-XEWWYph2oPfxmQ", + "cell_type": "code", + "source": [ + "public async Task CheckLoadInterDataNodeParameterAsync(Args args, IEnumerable testData, ", + "\n int previousYear,", + "\n int? currentYear = null)", + "\n{", + "\n currentYear = currentYear ?? previousYear;", + "\n await Workspace.UpdateAsync(testData);", + "\n ", + "\n var interDataNodeParameters = await LoadInterDataNodeParametersAsync(Workspace, args);", + "\n ", + "\n //Check Keys", + "\n var uniqueLinks = testData.Select(x => x.DataNode).Concat(testData.Select(x => x.LinkedDataNode)).ToHashSet();", + "\n uniqueLinks.Intersect(interDataNodeParameters.Keys).Count().Should().Be(uniqueLinks.Count());", + "\n ", + "\n //CheckInnerDictionaries", + "\n var currentYearData = testData.Where(x => x.Year == currentYear);", + "\n var previousYearData = testData.Where(x => x.Year == previousYear);", + "\n ", + "\n var errors = new List();", + "\n foreach(var dn in uniqueLinks)", + "\n {", + "\n //Set up BM counts", + "\n var currentLinks = currentYearData.Select(x => x.DataNode).Concat(currentYearData.Select(x => x.LinkedDataNode));", + "\n var currentLinksCount = currentLinks.Where(x => x == dn).Count();", + "\n var prevlinks = previousYearData.Select(x => x.DataNode).Concat(previousYearData.Select(x => x.LinkedDataNode));", + "\n var previousLinksCount = prevlinks.Where(x => x == dn).Count();", + "\n ", + "\n //Current Period", + "\n var computedCount = interDataNodeParameters[dn][CurrentPeriod].Count();", + "\n", + "\n if (currentYearData.Any())", + "\n {", + "\n if(computedCount != currentLinksCount)", + "\n errors.Add( $\"Current DataNode parameter count for {dn} not matching:\\n Expected {currentLinksCount} \\n Computed {computedCount}.\" );", + "\n }", + "\n else if(computedCount != previousLinksCount)", + "\n errors.Add( $\"Current DataNode parameter count for {dn} not matching:\\n Expected {previousLinksCount} \\n Computed {computedCount}.\" );", + "\n ", + "\n foreach (var param in interDataNodeParameters[dn][CurrentPeriod])", + "\n {", + "\n var linkedDn = param.DataNode == dn ? param.LinkedDataNode : param.DataNode;", + "\n var isLinkInPrevPeriod = previousYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn);", + "\n var isLinkInCurrPeriod = currentYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn); ", + "\n ", + "\n if(isLinkInPrevPeriod && !isLinkInCurrPeriod)", + "\n { ", + "\n if (param.ReinsuranceCoverage != ((double)previousYear)/1000)", + "\n errors.Add( $\"Current Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)previousYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n else if( param.ReinsuranceCoverage != ((double)currentYear)/1000)", + "\n errors.Add( $\"Current Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)currentYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n", + "\n //Previous Period", + "\n computedCount = interDataNodeParameters[dn][PreviousPeriod].Count();", + "\n ", + "\n if (currentYearData.Any())", + "\n {", + "\n if(computedCount != currentLinksCount)", + "\n errors.Add( $\"Previous DataNode parameter count for {dn} not matching:\\n Expected {currentLinksCount} \\n Computed {computedCount}.\" );", + "\n }", + "\n else if(computedCount != previousLinksCount)", + "\n errors.Add( $\"Previous DataNode parameter count for {dn} not matching:\\n Expected {previousLinksCount} \\n Computed {computedCount}.\" );", + "\n ", + "\n foreach (var param in interDataNodeParameters[dn][PreviousPeriod])", + "\n {", + "\n var linkedDn = param.DataNode == dn ? param.LinkedDataNode : param.DataNode;", + "\n var isLinkInPrevPeriod = previousYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn);", + "\n var isLinkInCurrPeriod = currentYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn); ", + "\n ", + "\n if(!isLinkInPrevPeriod && isLinkInCurrPeriod)", + "\n { ", + "\n if (param.ReinsuranceCoverage != ((double)currentYear)/1000)", + "\n errors.Add( $\"Previous Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)currentYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n else if( param.ReinsuranceCoverage != ((double)previousYear)/1000)", + "\n errors.Add( $\"Previous Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)previousYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "aOH89OGU5Eqn4PeSnUbJrw", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gic2, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cT_97C9oW0KF2qH_aG7Scw", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nint currentYear = 2020;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9},", + "\n new InterDataNodeParameter{ DataNode = gic2, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kJbew987pkum2Ge25tpsHQ", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nint currentYear = 2020;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IWMBAFYZpUaB-vgsMrm8dg", + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nint currentYear = 2020;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 3}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jtX2WSn4c02WOwMQ-oKUqQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/ReportStorageTest.ipynb b/Test/ReportStorageTest.ipynb new file mode 100644 index 00000000..58850654 --- /dev/null +++ b/Test/ReportStorageTest.ipynb @@ -0,0 +1,127 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "-CZo3x5cFEuDFZgs0uV9Bg", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Report/ReportStorage\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uXciD3hgUUqyPIiuAEQo3g", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tdRjnVvg9UaWMh368aBZ3g", + "cell_type": "markdown", + "source": [ + "# Test Exchange Rate Query" + ], + "metadata": {} + }, + { + "id": "j4bt5YUenkeFF2iakkxvgg", + "cell_type": "code", + "source": [ + "Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bd3JNWC5Nk2uaw14n6g2xQ", + "cell_type": "code", + "source": [ + "public async Task CheckGetFx(string currentCurrency, string targetCurrency, int year, int month, IEnumerable testData, double fxBOPBenchmark, double fxAVGBenchmark, double fxEOPBenchmark)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n ", + "\n //Create report storage", + "\n var period = (year, month);", + "\n var reportStorage = new ReportStorage(Workspace, Report);", + "\n await reportStorage.InitializeReportIndependentCacheAsync();", + "\n await reportStorage.InitializeAsync(period, \"G\", null, CurrencyType.Contractual);", + "\n ", + "\n var fxBOP = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.BeginningOfPeriod);", + "\n var fxAVG = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.Average);", + "\n var fxEOP = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.EndOfPeriod);", + "\n ", + "\n //Check FX rates", + "\n fxBOP.Should().Be(fxBOPBenchmark);", + "\n fxAVG.Should().Be(fxAVGBenchmark);", + "\n fxEOP.Should().Be(fxEOPBenchmark);", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "P6Lb3Bg1-ECmcI2_hG1fyQ", + "cell_type": "code", + "source": [ + "var testData = new ExchangeRate[] {new ExchangeRate{ Currency = \"EUR\", Year = 2020, Month = 12, FxType = FxType.Spot, FxToGroupCurrency = 10 }, ", + "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 3, FxType = FxType.Spot, FxToGroupCurrency = 15 },", + "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 6, FxType = FxType.Average, FxToGroupCurrency = 20 },", + "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 6, FxType = FxType.Spot, FxToGroupCurrency = 30 },", + "\n new ExchangeRate{ Currency = \"USD\", Year = 2020, Month = 12, FxType = FxType.Spot, FxToGroupCurrency = 5 },", + "\n new ExchangeRate{ Currency = \"USD\", Year = 2021, Month = 6, FxType = FxType.Average, FxToGroupCurrency = 2 },", + "\n new ExchangeRate{ Currency = \"USD\", Year = 2021, Month = 6, FxType = FxType.Spot, FxToGroupCurrency = 0.5 }};", + "\nawait CheckGetFx(\"EUR\", \"USD\", 2021, 6, testData, 2, 10, 60);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OncbMvm_E0OazTHlWRs1yQ", + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "h7lqAB05-0eTTOzD9xJS2g", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/ReportVariablesTest.ipynb b/Test/ReportVariablesTest.ipynb new file mode 100644 index 00000000..343f3835 --- /dev/null +++ b/Test/ReportVariablesTest.ipynb @@ -0,0 +1,256 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "LQUN8dM-FUOLRRCNCCfefg", + "cell_type": "markdown", + "source": [ + "

Test Reports

" + ], + "metadata": {} + }, + { + "id": "FeOU5sOWxUCzzbh-gAXjpQ", + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ], + "metadata": {} + }, + { + "id": "eULpl26ryUODapYZKqPsAg", + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ], + "metadata": {} + }, + { + "id": "v68OhAZHnkmBFLc4VS_Wsg", + "cell_type": "code", + "source": [ + "#r \"nuget:FluentAssertions\" " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "S5Jab8aqL0q_0yz2NvANCg", + "cell_type": "code", + "source": [ + "#!import \"ReportVariablesTestBase\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "T5-epYkxdESEdRkeQzPZ-Q", + "cell_type": "markdown", + "source": [ + "## Initialize Workspace" + ], + "metadata": {} + }, + { + "id": "MjO2BvvAS0e4HFtBefzQiQ", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WYaoK2llRES_PV3X7rt7dw", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LPEQPX6GkU6oZRTDNeu9gg", + "cell_type": "markdown", + "source": [ + "## Storage" + ], + "metadata": {} + }, + { + "id": "iyzfnUDQkE-IFlJDJhToWg", + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "PFEVTLIKUE6H0KLbPCp60w", + "cell_type": "markdown", + "source": [ + "## Configurations" + ], + "metadata": {} + }, + { + "id": "0JhPAc6LX0Wa6M-BQfsrPw", + "cell_type": "code", + "source": [ + "var path = \"./Data/ReportVariableBenchmarks/\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XutzHhUA00KlM1bajdW_IQ", + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args;", + "\nICollection scopesData;", + "\nICollection benchmarkData;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WTg65cXwoUC2csjHSFzPfw", + "cell_type": "markdown", + "source": [ + "# Test Cases" + ], + "metadata": {} + }, + { + "id": "7rnaJC3nVkGkge79ibM8KA", + "cell_type": "markdown", + "source": [ + "## ((2020, 12), \"CH\", null, CurrencyType.Contractual)" + ], + "metadata": {} + }, + { + "id": "E34nYeT2ckKrYWP3mxgc2g", + "cell_type": "code", + "source": [ + "args = ((2020, 12), \"CH\", null, CurrencyType.Contractual);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uBf_ViTSUUe1CC5J5UfWHA", + "cell_type": "code", + "source": [ + "scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", + "\nbenchmarkData = await GetBenchmarkDataAsync(args, path, Workspace, Import);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZB0QEVnuHUWzFbp6xXyVdg", + "cell_type": "code", + "source": [ + "scopesData.Should().BeEquivalentTo(benchmarkData,", + "\n options => options", + "\n //.ComparingRecordsByValue()", + "\n .ComparingRecordsByMembers() ", + "\n //.ComparingByMembers()", + "\n //.ComparingByValue()", + "\n //.Excluding(o => o.Value)", + "\n .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, BenchmarkPrecision))", + "\n .WhenTypeIs()", + "\n );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "g026nTeHy0a1vC2J5XM87g", + "cell_type": "markdown", + "source": [ + "## ((2021, 3), \"CH\", null, CurrencyType.Contractual)" + ], + "metadata": {} + }, + { + "id": "D7qV0NdVHE2Kdk6uavXIKw", + "cell_type": "code", + "source": [ + "args = ((2021, 3), \"CH\", null, CurrencyType.Contractual);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZYBQRO7yZ02UzX2eYt7Vnw", + "cell_type": "code", + "source": [ + "scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", + "\nbenchmarkData = await GetBenchmarkDataAsync(args, path, Workspace, Import);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "age1izMU1EmhYYO6S_LhWw", + "cell_type": "code", + "source": [ + "scopesData.Should().BeEquivalentTo(benchmarkData,", + "\n options => options", + "\n //.ComparingRecordsByValue()", + "\n .ComparingRecordsByMembers() ", + "\n //.ComparingByMembers()", + "\n //.ComparingByValue()", + "\n //.Excluding(o => o.Value)", + "\n .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, Precision))", + "\n .WhenTypeIs()", + "\n );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dl7B6Z5qnEWoD8LTXhUAYw", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/ReportVariablesTestBase.ipynb b/Test/ReportVariablesTestBase.ipynb new file mode 100644 index 00000000..e031e8d0 --- /dev/null +++ b/Test/ReportVariablesTestBase.ipynb @@ -0,0 +1,161 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "FYwy37yMNEeDl1kHPRFpKg", + "cell_type": "markdown", + "source": [ + "

Report Variable Test Base

" + ], + "metadata": {} + }, + { + "id": "3ZyHFOIosEyHCIUotySSVQ", + "cell_type": "code", + "source": [ + "#!import \"../Report/ReportScopes\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "injwhNjFM0Gd0wGXOWk0iw", + "cell_type": "markdown", + "source": [ + "# Helpers" + ], + "metadata": {} + }, + { + "id": "16zJY8-HwUWXMwwH0PDnKA", + "cell_type": "code", + "source": [ + "const string benchmarkFileNamePrefix = \"ReportVariableBenchmarks_\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "w93TGY8caEWby3AEWexMfw", + "cell_type": "code", + "source": [ + "static string GetBenchmarkFileName(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args) => args.ToString().Replace(\"(\", \"\").Replace(\")\", \"\").Replace(\" \", \"\").Replace(\",\", \"_\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FN-2epLYEEi0XlPqNMZBmQ", + "cell_type": "markdown", + "source": [ + "# Calculated" + ], + "metadata": {} + }, + { + "id": "lpbvuOTZvkeSAcnrEI9kXQ", + "cell_type": "code", + "source": [ + "static ICollection GetScopesData(Systemorph.Vertex.Scopes.IScopeWithStorage universe, ICollection<(ReportIdentity, CurrencyType)> identities) {", + "\n ", + "\n var lockedBePvs = universe.GetScopes(identities).Aggregate().LockedBestEstimate;", + "\n var currentBePvs = universe.GetScopes(identities).Aggregate().CurrentBestEstimate; ", + "\n", + "\n var lockedRaPvs = universe.GetScopes(identities).Aggregate().LockedRiskAdjustment;", + "\n var currentRaPvs = universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment;", + "\n", + "\n var writtenActuals = universe.GetScopes(identities).Aggregate().Written;", + "\n var advanceActuals = universe.GetScopes(identities).Aggregate().Advance;", + "\n var overdueActuals = universe.GetScopes(identities).Aggregate().Overdue;", + "\n", + "\n var deferrableActuals = universe.GetScopes(identities).Aggregate().Deferrals;", + "\n", + "\n var csm = universe.GetScopes(identities).Aggregate().Csm;", + "\n var lc = universe.GetScopes(identities).Aggregate().Lc;", + "\n var loreco = universe.GetScopes(identities).Aggregate().Loreco;", + "\n", + "\n var fp = universe.GetScopes(identities).Aggregate().FinancialPerformance;", + "\n ", + "\n return Enumerable.Empty()", + "\n .Concat(lockedBePvs) ", + "\n .Concat(currentBePvs)", + "\n .Concat(lockedRaPvs)", + "\n .Concat(currentRaPvs)", + "\n .Concat(writtenActuals)", + "\n .Concat(advanceActuals)", + "\n .Concat(overdueActuals)", + "\n .Concat(deferrableActuals)", + "\n .Concat(csm)", + "\n .Concat(lc)", + "\n .Concat(loreco)", + "\n .Concat(fp)", + "\n .OrderBy(v => v.GroupOfContract).ThenBy(v => v.Scenario).ThenBy(v => v.Projection).ThenBy(v => v.AccidentYear).ThenBy(v => v.EstimateType).ThenBy(v => (v.VariableType, v.Novelty))", + "\n .ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GBx1EE3IREu7RPWu8iZFbg", + "cell_type": "code", + "source": [ + "static async Task> GetScopesDataAsync(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args, ReportStorage reportStorage, Systemorph.Vertex.Scopes.Proxy.IScopeFactory scopes ) {", + "\n await reportStorage.InitializeAsync(args.Period, args.ReportingNode, args.Scenario, args.CurrencyType);", + "\n var identities = reportStorage.GetIdentities(args.Period, args.ReportingNode, args.Scenario, args.CurrencyType);", + "\n var universe = scopes.ForSingleton().WithStorage(reportStorage).ToScope();", + "\n return GetScopesData(universe, identities);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fkOXnPgChECva8WmF0hbaQ", + "cell_type": "markdown", + "source": [ + "# Benchmarks" + ], + "metadata": {} + }, + { + "id": "BJVbgmFieEGNehAotQ38Eg", + "cell_type": "code", + "source": [ + "static async Task> GetBenchmarkDataAsync(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args, string path, IWorkspace workspace, IImportVariable importVariable) {", + "\n var bmFileName = benchmarkFileNamePrefix + GetBenchmarkFileName(args) + \".csv\";", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Period.Year, Month = args.Period.Month });", + "\n await importVariable.FromFile(path + bmFileName).WithType(x => x.SnapshotMode()).WithTarget(workspace).ExecuteAsync();", + "\n var ret = await workspace.Query().ToArrayAsync();", + "\n workspace.Reset(x => x.ResetCurrentPartitions().ResetType());", + "\n return ret;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/Test/SpecificationsFinancialPerformance.ipynb new file mode 100644 index 00000000..70570b54 --- /dev/null +++ b/Test/SpecificationsFinancialPerformance.ipynb @@ -0,0 +1,1692 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "5nO38HYGpkascixiTUO0gw", + "cell_type": "markdown", + "source": [ + "

Financial Performance Specifications

" + ], + "metadata": {} + }, + { + "id": "YiqIuEZ5Ika8lHG2QytiBg", + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the Financial Performance reporting system. The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ], + "metadata": {} + }, + { + "id": "I_4NcYOLg0-FT87qtmCw5g", + "cell_type": "markdown", + "source": [ + "In the following the Dimensions, Parameters, Nominal Cashflows, and Actuals are imported from the corresponding csv files in Initialization/Systemorph/" + ], + "metadata": {} + }, + { + "id": "G0Y5GVas3k6z7nhLhKYi2A", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "SZwhFp3mkUKWwRMH8wcnKw", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "FCPPVD5qb0edgdnX8gE5TA", + "cell_type": "markdown", + "source": [ + "# Process Data" + ], + "metadata": {} + }, + { + "id": "8kQa9wme2E2KwZMXm_jkRQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period, Reporting Node and Currency Type" + ], + "metadata": {} + }, + { + "id": "9Mil10I7XUKS9qwodcQnJQ", + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" + ], + "metadata": {} + }, + { + "id": "jycgHCLPSU6SsnQh_NqdXQ", + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Q1ptu1Ih6UqNipHCM9wrFw", + "cell_type": "markdown", + "source": [ + "and the type of Currency among Contractual, Functional, and Group" + ], + "metadata": {} + }, + { + "id": "W_q-kxke4kSXENWTI_sTDg", + "cell_type": "code", + "source": [ + "var currencyType = CurrencyType.Contractual ;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Z5gPrgd79kaIdxevViMb5Q", + "cell_type": "markdown", + "source": [ + "Import the Report definitions, initialize the Workspace and the Test Suite:" + ], + "metadata": {} + }, + { + "id": "jZs86CqBw0S_Ms4QvU6Yhg", + "cell_type": "code", + "source": [ + "#!import \"../Report/ReportScopes\"", + "\n#!import \"../Report/ReportConfigurationAndUtils\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fsDoELzhOEKHVk0LvwG8lg", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FwJCyVQlg0iyVa9GIObOVA", + "cell_type": "code", + "source": [ + "var period = (year, month) ;", + "\nvar reportStorage = new ReportStorage(Workspace, Report) ;", + "\nvar Test = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0H5JBXBojEmJX2J4YxoSKQ", + "cell_type": "code", + "source": [ + "await reportStorage.InitializeReportIndependentCacheAsync();", + "\nawait reportStorage.InitializeAsync(period, reportingNode, null, currencyType);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ljauWn5bzkePv8oz0hmmcw", + "cell_type": "markdown", + "source": [ + "## View list of Identities" + ], + "metadata": {} + }, + { + "id": "ROlx1yHrOkOcN8NoaWg_kQ", + "cell_type": "markdown", + "source": [ + "Based on the Cashflows imported, the list of all possible identities, i.e. combinations of valid Contractual and Functional Currencies, Liability Types, (Re)Insurance and Oci, is contructed and reported here below:" + ], + "metadata": {} + }, + { + "id": "FWlyPQurk0e7MxUr1_Vh4Q", + "cell_type": "code", + "source": [ + "var identities = reportStorage.GetIdentities(period, reportingNode, null, currencyType);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dQr4xO85AkW_XOGwRhp3Wg", + "cell_type": "code", + "source": [ + "identities" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8WK3-WqoVkKWxMmrunWCPw", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Report" + ], + "metadata": {} + }, + { + "id": "6SapvCdFR0Wa-5iw2O7bmA", + "cell_type": "markdown", + "source": [ + "Please select here below the target Data Node for executing the tests below:" + ], + "metadata": {} + }, + { + "id": "tnnSkBvTP0OcTweKBHRVwA", + "cell_type": "code", + "source": [ + "var dataNode = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MaxaD_pix0qUJSHQFYw_Yg", + "cell_type": "markdown", + "source": [ + "The Group of Contract selected is:" + ], + "metadata": {} + }, + { + "id": "ojOHd0ltR0ysyqjaXBV7fA", + "cell_type": "code", + "source": [ + "var groupOfContract = (await Workspace.Query().Where(x => x.SystemName == dataNode).ToArrayAsync()).FirstOrDefault();", + "\ngroupOfContract" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2wrq4ud_nUywAVYp0c16ng", + "cell_type": "markdown", + "source": [ + "where ", + "\n- the **OciType** can be Default for contracts with non-zero OCI, and null otherwise, ", + "\n- the **Liability Type** can be LRC for Liability for Remaining Coverage, and LIC for Liability of Incurred Claims,", + "\n- the **Partner** can be null for Insurance contracts, or equal to the Partner System Name for Reinsurance contracts." + ], + "metadata": {} + }, + { + "id": "FLplPZmhH0uHoByRc9jzyw", + "cell_type": "markdown", + "source": [ + "The summary of the Financial Performance report is shown below" + ], + "metadata": {} + }, + { + "id": "PPVlpKTvE0utqi7d_6hsOA", + "cell_type": "code", + "source": [ + "Report.ForDataCube( Test.GetScopes(identities).Aggregate().FinancialPerformance.Filter((\"GroupOfContract\", dataNode)) )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(currencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", + "\n .ToReport() with { Height = 600 }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Y6ExKbo35kizVyUzucL8tg", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Inspection" + ], + "metadata": {} + }, + { + "id": "mljPLFn_Vk699EW8NxaqFQ", + "cell_type": "markdown", + "source": [ + "## Fulfillment Cashflows" + ], + "metadata": {} + }, + { + "id": "fXAJiiBobE-8cIFXnwQW_g", + "cell_type": "markdown", + "source": [ + "The Fulfillment Cashflow (FCF) corresponds to the sum of the Best Estimate [Present Value](../Import/ImportScopeCalculation#current-and-locked) (PV) and the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) (RA), both summed over Amounty Types, and both discounted with the Locked-In curve in the BBA valuation approach:", + "\n", + "\n$$", + "\n\\text{FCF}(\\text{AoC}) = \\text{PV Locked}(\\text{AoC})", + "\n\\bigg|_{\\substack{\\text{Non Attributable} \\\\ \\text{Amount Types} \\\\ \\text{excluded}}} ", + "\n+ \\text{RA Locked}(\\text{AoC}) ~.", + "\n$$" + ], + "metadata": {} + }, + { + "id": "EIByt77nt02vKJ6M7fbYPA", + "cell_type": "markdown", + "source": [ + "### Non Financial" + ], + "metadata": {} + }, + { + "id": "BeRPnXRcr0KgXSe9gOqr0w", + "cell_type": "markdown", + "source": [ + "The computed value for the non financial contribution to the FCF is" + ], + "metadata": {} + }, + { + "id": "Tpu5SaZ9GEGA3y-zQW_yHw", + "cell_type": "code", + "source": [ + "var computedDeltaFCF_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .FpNonFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1lQULEdowk-gnCueOrvJrg", + "cell_type": "code", + "source": [ + "computedDeltaFCF_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "i4QyAGfVmEGE_5Igb2Z-LQ", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full list of FCFs" + ], + "metadata": {} + }, + { + "id": "qqBotvtEjE22aC7q0898qw", + "cell_type": "code", + "source": [ + "var FCFs = Test.GetScopes(identities).Aggregate().Fcf.Filter((\"GroupOfContract\", dataNode));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VzFxq-PplkGMBBeSgTqoVg", + "cell_type": "code", + "source": [ + "var deltaFCF = FCFs.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n FCFs.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iNXYCe0l-U2neY7wtMwZ0Q", + "cell_type": "code", + "source": [ + "deltaFCF.Aggregate().Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yI_ySCVJT06znmYYyfM3zQ", + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_nonFinancial = deltaFCF.Filter((\"VariableType\", \"!IA\"), ", + "\n (\"VariableType\", \"!YCU\"), ", + "\n (\"VariableType\", \"!CRU\") ).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kYVlMOqOrEeCvRN9BdzD5Q", + "cell_type": "code", + "source": [ + "expectedDeltaFCF_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vLdRwY5WPEeVSdEZ6mq5eg", + "cell_type": "markdown", + "source": [ + "For consistency, this term is taken with the minus sign" + ], + "metadata": {} + }, + { + "id": "1z_-jBHxPECdPV59L1zu3w", + "cell_type": "code", + "source": [ + "expectedDeltaFCF_nonFinancial.CheckEquality( -computedDeltaFCF_nonFinancial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zLC_x5tXRkqCJb8ko1k1pw", + "cell_type": "markdown", + "source": [ + "### Financial" + ], + "metadata": {} + }, + { + "id": "8q-L68QoyUWnE_1p9I8GrQ", + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial contribution to the Fulfillment Cashflows (FCF) is" + ], + "metadata": {} + }, + { + "id": "unbfg7yEZkajmEbeDpLGbw", + "cell_type": "code", + "source": [ + "var computedDeltaFCF_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FpFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1Z9AZCSrsUqNaYXcDtgG9g", + "cell_type": "code", + "source": [ + "computedDeltaFCF_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QUKtT16YKECBrRssqHJ7iA", + "cell_type": "markdown", + "source": [ + "The independent recalculation of this value reads" + ], + "metadata": {} + }, + { + "id": "DBD46hb6jkmOuS8fF8AzNg", + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_Financial = (deltaFCF.Filter((\"VariableType\", \"IA\")) +", + "\n deltaFCF.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaFCF.Filter((\"VariableType\", \"CRU\")) ).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3Pml-0__90GYfwqGIkh8hA", + "cell_type": "code", + "source": [ + "expectedDeltaFCF_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WeeGHMbfv0yDqvE0uspuwA", + "cell_type": "markdown", + "source": [ + "taking the minus sign into account" + ], + "metadata": {} + }, + { + "id": "Jy8LN1Jl9UW7ZFn61_0E7g", + "cell_type": "code", + "source": [ + "expectedDeltaFCF_Financial.CheckEquality( -computedDeltaFCF_Financial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KdafoHd6V0WcBY3w-7FCNg", + "cell_type": "markdown", + "source": [ + "### Other Comprehensive Income" + ], + "metadata": {} + }, + { + "id": "WTWsM2t8ske9c6Qp4Sw6tw", + "cell_type": "markdown", + "source": [ + "The Other Comprehensive Income (OCI) term is by definition the sum of the financial contributions not related to the insurance sector.", + "\n", + "\nThe Default method to compute the OCI term is by subtracting the FCF computed with the *Locked-In* rates and the FCF computed with the *Current* rates. In this way the non insurance financial volatiliy of the economic input is relegated to the OCI. " + ], + "metadata": {} + }, + { + "id": "HFvK3TQALEyxtaqOa072RA", + "cell_type": "code", + "source": [ + "var computedDeltaFCF_OCI = Test.GetScopes(identities).Aggregate()", + "\n .OciFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KlV-XHswLUm60jAtrKXRxw", + "cell_type": "code", + "source": [ + "computedDeltaFCF_OCI" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wLYM_5_Cw0agX8ngdpiJNw", + "cell_type": "markdown", + "source": [ + "The OCI contribution is zero when the OCI option is disabled for the [target Group of Contract](#report).", + "\n", + "\nHere below we follow the steps to calculate independently the OCI contribution " + ], + "metadata": {} + }, + { + "id": "jExIPgxaoEKHbQ0n1CCDlg", + "cell_type": "code", + "source": [ + "var DeltaFCF_Locked = deltaFCF.Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Fi1WFLVNokSI8kGpGrtSgg", + "cell_type": "code", + "source": [ + "var FCFs_current = Test.GetScopes(identities).Aggregate().CurrentFcf.Filter((\"GroupOfContract\", dataNode));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "08PqnzK1VkqrjayuXu29Gw", + "cell_type": "code", + "source": [ + "var DeltaFCF_Current = FCFs_current.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n FCFs_current.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2H7J_REURECEUakkHg3uZQ", + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_OCI = DeltaFCF_Locked - DeltaFCF_Current.Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0bDk7FRhN0C2sRCzbkIzrQ", + "cell_type": "code", + "source": [ + "DeltaFCF_Locked" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FG-gv68W_E2X5Duxt7tKlw", + "cell_type": "code", + "source": [ + "DeltaFCF_Current.Aggregate().Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HOaaRyAoI0CC6BerqeJ41Q", + "cell_type": "code", + "source": [ + "expectedDeltaFCF_OCI" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uTbfa8NPIUqm-o4eZSU8fw", + "cell_type": "code", + "source": [ + "expectedDeltaFCF_OCI.CheckEquality( computedDeltaFCF_OCI ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1IZSRJ3t_0CNXpp4ywd9VQ", + "cell_type": "markdown", + "source": [ + "## Contractual Service Margin" + ], + "metadata": {} + }, + { + "id": "5bsUEITa6kuGaTRVkZ084A", + "cell_type": "markdown", + "source": [ + "### Non Financial" + ], + "metadata": {} + }, + { + "id": "JTfLDJSJQEOWT2i89grUSQ", + "cell_type": "markdown", + "source": [ + "The computed value for the non financial change of the CSM is" + ], + "metadata": {} + }, + { + "id": "8ILRJFbhBUC62g15t754iQ", + "cell_type": "code", + "source": [ + "var computedDeltaCSM_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WKz0gPwLNU-dpX_9pel6qQ", + "cell_type": "code", + "source": [ + "computedDeltaCSM_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "M-zez2dNKEqoEuSnVmQOAQ", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full CSM data from which the delta can be computed:" + ], + "metadata": {} + }, + { + "id": "u3qO33HX2EWTdU-FsXV1DQ", + "cell_type": "code", + "source": [ + "var CSM = Test.GetScopes(identities).Aggregate().Csm.Filter((\"GroupOfContract\", dataNode));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sUzTJENNQE2vyUAMH18-Fg", + "cell_type": "code", + "source": [ + "var deltaCSM = CSM.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n CSM.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YE8SeJsLGkigzdsg2lrthg", + "cell_type": "code", + "source": [ + "deltaCSM.Aggregate().Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "APgQnfCAvUGZOS1alGD76A", + "cell_type": "markdown", + "source": [ + "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + ], + "metadata": {} + }, + { + "id": "RtFAIsTtqkKptF872l2QOA", + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_nonFinancial = deltaCSM.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QIAfXjMAUkKl824oTIpkxg", + "cell_type": "code", + "source": [ + "expectedDeltaCSM_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ROYdG5qKq0WskXY9TubsCw", + "cell_type": "code", + "source": [ + "expectedDeltaCSM_nonFinancial.CheckEquality( -computedDeltaCSM_nonFinancial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "B3v_a4ACR0aaHYEIZ5Efmw", + "cell_type": "markdown", + "source": [ + "### Financial" + ], + "metadata": {} + }, + { + "id": "XUhfK022zUq-fhkyjtdiRA", + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial change of the CSM is" + ], + "metadata": {} + }, + { + "id": "ni56W_02FkyqpCsEn8POig", + "cell_type": "code", + "source": [ + "var computedDeltaCSM_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UBEJvfmS9UOcouMKcyVlSA", + "cell_type": "code", + "source": [ + "computedDeltaCSM_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TqRsmZIHlUqsIwggU5ok1w", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + ], + "metadata": {} + }, + { + "id": "60OowsZamEOXwPfjqtKINg", + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_Financial = ( deltaCSM.Filter((\"VariableType\", \"IA\")) +", + "\n deltaCSM.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaCSM.Filter((\"VariableType\", \"CRU\")) )", + "\n .Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "d89jwj04Ak-rvKD6GrFThw", + "cell_type": "code", + "source": [ + "expectedDeltaCSM_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HZ5FzlG01U-9aaQvlx_cCQ", + "cell_type": "code", + "source": [ + "expectedDeltaCSM_Financial.CheckEquality( -computedDeltaCSM_Financial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q-EaVofzPkeq9BLkL6Pk2w", + "cell_type": "markdown", + "source": [ + "## Loss Component" + ], + "metadata": {} + }, + { + "id": "LE5bZlbq_UWJBvszrykzuA", + "cell_type": "markdown", + "source": [ + "### Non Financial" + ], + "metadata": {} + }, + { + "id": "lFKLvci1FUOz6Q0a40u2-A", + "cell_type": "markdown", + "source": [ + "The computed value for the non financial change of the LC is" + ], + "metadata": {} + }, + { + "id": "NA8SeqEo5EiJhDQHBuTtjg", + "cell_type": "code", + "source": [ + "var computedDeltaLC_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yoNwfY6O-EGOYvwfX9CXKw", + "cell_type": "code", + "source": [ + "computedDeltaLC_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wQpKhvuttU2S-2T2XqWz9g", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full CSM data from which the delta can be computed:" + ], + "metadata": {} + }, + { + "id": "ZnNiktkIsEmVeTAPp4eq0Q", + "cell_type": "code", + "source": [ + "var LC = Test.GetScopes(identities).Aggregate().Lc.Filter((\"GroupOfContract\", dataNode));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XRtrMck4ak-bF1LUNbR-bw", + "cell_type": "code", + "source": [ + "var deltaLC = LC.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n LC.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rUaX0OrwkUuo2_xNMVz34g", + "cell_type": "code", + "source": [ + "deltaLC.Aggregate().Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Xv4auAOkAE6oXxsy4JGUBw", + "cell_type": "markdown", + "source": [ + "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + ], + "metadata": {} + }, + { + "id": "c95lLlyhYU2YCY4HE8ZVIg", + "cell_type": "code", + "source": [ + "var expectedDeltaLC_nonFinancial = deltaLC.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qmlrXNV4n0iOMmSFHVe7wA", + "cell_type": "code", + "source": [ + "expectedDeltaLC_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "k_hU6dAGrEmzN3vI30De0A", + "cell_type": "code", + "source": [ + "expectedDeltaLC_nonFinancial.CheckEquality( -computedDeltaLC_nonFinancial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q0Cm5RmXxUa4oQVQ1fuHjw", + "cell_type": "markdown", + "source": [ + "### Financial" + ], + "metadata": {} + }, + { + "id": "cAJ4Q4Rx60aaCC-Nt-gdpQ", + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial change of the LC is" + ], + "metadata": {} + }, + { + "id": "MtdwhbqZiU-TOLVfW0DFDg", + "cell_type": "code", + "source": [ + "var computedDeltaLC_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cWArdm8iMESr118b9tDMkQ", + "cell_type": "code", + "source": [ + "computedDeltaLC_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "q2pAhq-A_0aROq8zEDtVCA", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + ], + "metadata": {} + }, + { + "id": "fxZPPdSMCkG-mV0CjyLK4g", + "cell_type": "code", + "source": [ + "var expectedDeltaLC_Financial = ( deltaLC.Filter((\"VariableType\", \"IA\")) +", + "\n deltaLC.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaLC.Filter((\"VariableType\", \"CRU\")) )", + "\n .Aggregate().Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WYqhArIhB0aUgSAq2pl4Ag", + "cell_type": "code", + "source": [ + "expectedDeltaLC_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IzddiJL3oUewH76M1wgr1w", + "cell_type": "code", + "source": [ + "expectedDeltaLC_Financial.CheckEquality( -computedDeltaLC_Financial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ktY-cyI15E-U1ahdw6cDuA", + "cell_type": "markdown", + "source": [ + "## Loss Recovery Component" + ], + "metadata": {} + }, + { + "id": "Jj5QAJYtR0mPDZsLbwt82w", + "cell_type": "markdown", + "source": [ + "### Non Financial" + ], + "metadata": {} + }, + { + "id": "MNr136KdUEWkl6QE99H-tQ", + "cell_type": "markdown", + "source": [ + "If the [target Group of Contract](#report) is not of type Re-Insurance, the result of the following will return null.", + "\n", + "\nThe computed value for the non financial change of the LoReCo is" + ], + "metadata": {} + }, + { + "id": "vheo4pqpoUC636g-YZNg7w", + "cell_type": "code", + "source": [ + "var computedDeltaLORECO_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gcye9gWqLUSp2DBeuZK5JA", + "cell_type": "code", + "source": [ + "computedDeltaLORECO_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1h9DSjP030GvgF_-V2wXEQ", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full LoReCo data from which the delta can be computed:" + ], + "metadata": {} + }, + { + "id": "toras9Yo70eeiatIr1j9fw", + "cell_type": "code", + "source": [ + "var LORECO = Test.GetScopes(identities).Aggregate().Loreco.Filter((\"GroupOfContract\", dataNode));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uT9D_Ku9WkS7lCo1nrxs0Q", + "cell_type": "code", + "source": [ + "var deltaLORECO = LORECO.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n LORECO.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Qhxfbqq4OEaXyYoe5rfTUg", + "cell_type": "code", + "source": [ + "deltaLORECO.Aggregate()?.Value?? 0" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_uTlE0FJFEOI34sBONg8Mw", + "cell_type": "markdown", + "source": [ + "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + ], + "metadata": {} + }, + { + "id": "qmBrKRZP8U-13Lup_I2e5Q", + "cell_type": "code", + "source": [ + "var expectedDeltaLORECO_nonFinancial = deltaLORECO.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tMMjF_m4D0aRpukRYlpdLA", + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_nonFinancial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "in3E9cuYDEymJ4n3r_iWPA", + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_nonFinancial.CheckEquality( -computedDeltaLORECO_nonFinancial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OaAYtHkPf0CohNZ6dPoGGA", + "cell_type": "markdown", + "source": [ + "### Financial" + ], + "metadata": {} + }, + { + "id": "gHC-7-HgtEWWHf6ZCY6dDQ", + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial change of the LoReCo is" + ], + "metadata": {} + }, + { + "id": "Y9twZB0o6ESo6PY18cZj9g", + "cell_type": "code", + "source": [ + "var computedDeltaLORECO_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3wLUoygmE0CXCU5UFkL41Q", + "cell_type": "code", + "source": [ + "computedDeltaLORECO_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "j5qJfGmdMkGwoFc1yb_X3Q", + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + ], + "metadata": {} + }, + { + "id": "3UGSj5-MYUSI-mW2tMJXVg", + "cell_type": "code", + "source": [ + "var expectedDeltaLORECO_Financial = ( deltaLORECO.Filter((\"VariableType\", \"IA\")) +", + "\n deltaLORECO.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaLORECO.Filter((\"VariableType\", \"CRU\")) )", + "\n .Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_Yk_rP1ZHEqRB6g3yMCUMg", + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_Financial" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dDZLX-mHFEyX5X2GNKLW7Q", + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_Financial.CheckEquality( -computedDeltaLORECO_Financial ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "S8TFuLo4eUeNTC-d5f9GjA", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Reconciliation" + ], + "metadata": {} + }, + { + "id": "GEzn2LZBRkSr7oqQsmzPDA", + "cell_type": "markdown", + "source": [ + "Based on the results calculated in Section 3, we check here the consistency of the [Financial Performance Report](#report). ", + "\n", + "\nFiner granular reconciliations can be performed by following the datails of how each report contributes to the Financial Performance Report. Please, refer to the [Report documentation](../Report/ReportScopes#financial-performance) for all the details. " + ], + "metadata": {} + }, + { + "id": "a6N6B4TD8kuk12aZT40KVg", + "cell_type": "markdown", + "source": [ + "## Insurance Revenue" + ], + "metadata": {} + }, + { + "id": "6MZPkbR47EmeDYqsSV4urQ", + "cell_type": "markdown", + "source": [ + "The Insurance Revenue (IR) contributions vary from Insurance to Re-Insurance and depend on the Liability Type of the [target Group of Contract](#report). This can be summarized by the formulas below", + "\n", + "\n$$", + "\n\\text{IR} = \\left\\{ ", + "\n\\begin{array}{ll}", + "\n\\Delta\\text{FCF Gross Non Financial} + \\Delta\\text{CSM Non Financial} + \\Delta\\text{CSM Release} \\\\", + "\n+ \\text{Incurred Incoming Cashflows} + \\text{Claims ICO} + \\text{Incurred Deferrals} \\\\", + "\n+ \\text{Exc. Experience Adjustment on Premiums} ~~,", + "\n& \\text{for LRC Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{CSM Non Financial} + \\Delta\\text{CSM Release} \\\\", + "\n+ \\text{Incurred Incoming Cashflows} + \\text{Claims ICO} + \\text{Incurred Deferrals} ~~,", + "\n& \\text{for LIC Insurance contracts} \\\\[0.2cm]", + "\n\\text{Claims ICO} + \\text{Incurred Deferrals} ~~,", + "\n& \\text{for Re-Insurance contracts}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nHere below we recompute the IR term:" + ], + "metadata": {} + }, + { + "id": "dFWCtF0eBkqXubXgarv3IA", + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_release = deltaCSM.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cnXGdn9kHkaAPsUUjaffrg", + "cell_type": "code", + "source": [ + "var expectedIncurredIncomingCashflows = Test.GetScopes(identities).Aggregate().Premiums", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "d5AwPz1_ZUiGBL5xhIKZ4g", + "cell_type": "code", + "source": [ + "var expectedIncurredDeferralsIr = Test.GetScopes(identities).Aggregate().AmortizationToIr", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YsUQO-5qx0mI-Ze0xAxR2g", + "cell_type": "code", + "source": [ + "var expectedClaimsICO = Test.GetScopes(identities).Aggregate().ClaimsIcoToIr", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uEta4W7kvEGPG1QyEoMh7w", + "cell_type": "code", + "source": [ + "var expectedExcExperienceAdjPremiums = Test.GetScopes(identities).Aggregate().ExperienceAdjustmentOnPremium", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zOT5DeoAmUCB4VCKdUJ2lw", + "cell_type": "code", + "source": [ + "double IR = 0;", + "\nif(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LRC\")", + "\n IR = - expectedDeltaFCF_nonFinancial ", + "\n - expectedDeltaCSM_nonFinancial ", + "\n - expectedDeltaCSM_release ", + "\n + expectedIncurredIncomingCashflows", + "\n + expectedClaimsICO", + "\n + expectedIncurredDeferralsIr", + "\n + expectedExcExperienceAdjPremiums;", + "\nelse if(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LIC\")", + "\n IR = - expectedDeltaCSM_nonFinancial", + "\n - expectedDeltaCSM_release", + "\n + expectedIncurredIncomingCashflows", + "\n + expectedClaimsICO", + "\n + expectedIncurredDeferralsIr ", + "\n + expectedExcExperienceAdjPremiums;", + "\nelse if(groupOfContract.Partner != null)", + "\n IR = + expectedClaimsICO", + "\n + expectedIncurredDeferralsIr", + "\n + expectedExcExperienceAdjPremiums;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gPU-YBlmbU-CuZWTrFnM-Q", + "cell_type": "code", + "source": [ + "IR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yE-6MD2uiE6ttfKjHLsQlg", + "cell_type": "markdown", + "source": [ + "## Insurance Service Expenses" + ], + "metadata": {} + }, + { + "id": "Obp_9f3AZkCH8Lap4aYmFg", + "cell_type": "markdown", + "source": [ + "Analogously, the Insurance Service Expenses (ISE) read", + "\n", + "\n$$", + "\n\\text{ISE} = \\left\\{ ", + "\n\\begin{array}{ll}", + "\n\\Delta\\text{LC Non Financial}", + "\n+ \\Delta\\text{LC Release}", + "\n+ \\text{Incurred ClaimsNIC} \\\\", + "\n+ \\text{Incurred Expenses}", + "\n+ \\text{Incurred Commissions}", + "\n+ \\text{Incurred Deferrals}", + "\n& \\text{for LRC Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{FCF Reinsurance Non Financial}", + "\n+ \\Delta\\text{LC Non Financial}", + "\n+ \\Delta\\text{LC Release}", + "\n+ \\text{Incurred ClaimsNIC} \\\\", + "\n+ \\text{Incurred Expenses} ", + "\n+ \\text{Incurred Commissions}", + "\n+ \\text{Incurred Deferrals}", + "\n& \\text{for LIC Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{FCF Reinsurance Non Financial} ", + "\n+ \\Delta\\text{CSM Non Financial} ", + "\n+ \\Delta\\text{CSM Release} \\\\", + "\n+ \\Delta\\text{LC Non Financial} ", + "\n+ \\Delta\\text{LC Release} ", + "\n+ \\Delta\\text{LoReCo Non Financial} \\\\", + "\n+ \\text{Incurred Incoming Cashflows} ", + "\n+ \\text{Incurred ClaimsNIC} ", + "\n+ \\text{Incurred Expenses} \\\\", + "\n+ \\text{Incurred Commissions}", + "\n+ \\text{Incurred Deferrals}", + "\n& \\text{for Re-Insurance contracts}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nHere below we recompute the ISE term:" + ], + "metadata": {} + }, + { + "id": "JL2Q7lsrlEucGEc4EjA_oA", + "cell_type": "code", + "source": [ + "var expectedDeltaLC_release = deltaLC.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "O9r-rlZ5hky9sOj-zExurg", + "cell_type": "code", + "source": [ + "var expectedDeltaLoReCo_release = deltaLORECO.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bL0MmHokbUmpt_-xEliEwg", + "cell_type": "code", + "source": [ + "var expectedIncurredClaimsNIC = Test.GetScopes(identities).Aggregate().ClaimsNic", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pV3DTg_19k2Hvp6dPqucww", + "cell_type": "code", + "source": [ + "var expectedIncurredExpenses = Test.GetScopes(identities).Aggregate().Expenses", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KKkpsRFmHUiTPE7WDhV5LQ", + "cell_type": "code", + "source": [ + "var expectedIncurredCommissions = Test.GetScopes(identities).Aggregate().Commissions", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZoXGr9AuiUiZ9G1X4jUa8Q", + "cell_type": "code", + "source": [ + "var expectedIncurredClaimsICO = Test.GetScopes(identities).Aggregate().ClaimsIcoToIse", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "80_7zlUU90-JspeAvDJ9lQ", + "cell_type": "code", + "source": [ + "var expectedIncurredDeferralsIse = Test.GetScopes(identities).Aggregate().AmortizationToIse", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Cekx0MB6YkyVgxkvslykvQ", + "cell_type": "code", + "source": [ + "double ISE = 0;", + "\nif(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LRC\")", + "\n ISE = - expectedDeltaLC_nonFinancial ", + "\n - expectedDeltaLC_release", + "\n + expectedIncurredClaimsNIC ", + "\n + expectedIncurredExpenses ", + "\n + expectedIncurredClaimsICO", + "\n + expectedIncurredCommissions", + "\n + expectedIncurredDeferralsIse;", + "\nelse if(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LIC\")", + "\n ISE = - expectedDeltaFCF_nonFinancial", + "\n - expectedDeltaLC_nonFinancial ", + "\n - expectedDeltaLC_release", + "\n + expectedIncurredClaimsNIC ", + "\n + expectedIncurredExpenses ", + "\n + expectedIncurredClaimsICO", + "\n + expectedIncurredCommissions", + "\n + expectedIncurredDeferralsIse;", + "\nelse if(groupOfContract.Partner != null)", + "\n ISE = - expectedDeltaFCF_nonFinancial", + "\n - expectedDeltaCSM_nonFinancial", + "\n - expectedDeltaCSM_release", + "\n - expectedDeltaLC_nonFinancial ", + "\n - expectedDeltaLC_release", + "\n - expectedDeltaLoReCo_release", + "\n + expectedIncurredIncomingCashflows", + "\n + expectedIncurredClaimsNIC ", + "\n + expectedIncurredExpenses ", + "\n + expectedIncurredClaimsICO", + "\n + expectedIncurredCommissions", + "\n + expectedIncurredDeferralsIse;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "081ToSk3WESb6183HlFQlA", + "cell_type": "code", + "source": [ + "ISE" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "83VrYmGYX0uHykId27aWOQ", + "cell_type": "markdown", + "source": [ + "## Insurance Finance Income/Expenses" + ], + "metadata": {} + }, + { + "id": "NAkWvaF6NUG6tYDPqEbVNA", + "cell_type": "markdown", + "source": [ + "The Financial part associated to the Insurance business encompassing both the Income and Expenses is denoted IFIE from the initials marked in capital letters. The ", + "\n", + "\n$$", + "\n\\text{IFIE} = \\left\\{", + "\n\\begin{array}{ll}", + "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ~~,", + "\n& \\text{for Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ", + "\n+ \\Delta\\text{LoReCo Financial} ~~, ", + "\n& \\text{for Re-Insurance contracts}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nHere below we recompute the IFIE term:" + ], + "metadata": {} + }, + { + "id": "JkwONyKiakC4XpVgxusdRg", + "cell_type": "code", + "source": [ + "double IFIE = 0;", + "\nif(groupOfContract.Partner == null) ", + "\n IFIE = - expectedDeltaFCF_Financial ", + "\n - expectedDeltaCSM_Financial", + "\n - expectedDeltaLC_Financial;", + "\nelse", + "\n IFIE = - expectedDeltaFCF_Financial ", + "\n - expectedDeltaCSM_Financial", + "\n - expectedDeltaLC_Financial", + "\n - expectedDeltaLORECO_Financial;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "grefaMt7BEaTJ7dsa0AUQA", + "cell_type": "code", + "source": [ + "IFIE" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6_E3dWyyF0COz4xLh1e-xA", + "cell_type": "markdown", + "source": [ + "## Other Comprehensive Income" + ], + "metadata": {} + }, + { + "id": "jK3nTYcm30KoVUioi71r4g", + "cell_type": "markdown", + "source": [ + "The Other Comprehensive Income (OCI) can be non-zero only when the OCI is enabled for [target Group of Contract](#report), that is, Oci Type = Default.", + "\n", + "\n$$", + "\n\\text{OCI} = \\Delta\\text{FCF} \\big|_{\\text{Locked-in}} - \\Delta\\text{FCF} \\big|_{\\text{Current}} ~~.", + "\n$$", + "\n", + "\nHere below we recompute the OCI term:" + ], + "metadata": {} + }, + { + "id": "j2wpd2OAuUmjvKWQoew9jQ", + "cell_type": "code", + "source": [ + "var OCI = expectedDeltaFCF_OCI;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7R8qKIIsGU6fcW8M2M2M5g", + "cell_type": "code", + "source": [ + "OCI" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_BPpLy2cnUKTaE-9tgr-UQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/SpecificationsImportActuals.ipynb b/Test/SpecificationsImportActuals.ipynb new file mode 100644 index 00000000..b803db6b --- /dev/null +++ b/Test/SpecificationsImportActuals.ipynb @@ -0,0 +1,705 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "1O9abtyGKUeDiX_VyaeaAQ", + "cell_type": "markdown", + "source": [ + "

Import Actuals Specifications

" + ], + "metadata": {} + }, + { + "id": "mgxNtYdjh027T2LccTaWsA", + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the calculations taking place when importing the Actuals. For this documentation notebook the Data is imported from the corresponding csv files located in the following path Initialization/Systemorph/. The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ], + "metadata": {} + }, + { + "id": "9sXMifQXi0yuys7dMnvmmA", + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ], + "metadata": {} + }, + { + "id": "TYI7B_9JxEm9gBQSiHP7Tw", + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sQZ9EDWrRUCqjDaDiUaslg", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "9VuASxTZcE64BWvOvV6Y0A", + "cell_type": "markdown", + "source": [ + "# Import Data" + ], + "metadata": {} + }, + { + "id": "cb5PqhqcY0eWhhsN18hk8Q", + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period" + ], + "metadata": {} + }, + { + "id": "AYwuUnm7D0OvGFWfuLCS0g", + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month), Reporting Node, Economic Basis, and Data Node based on the imported data:" + ], + "metadata": {} + }, + { + "id": "e0LWvI9K1U-qRdDpHJWU3Q", + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;", + "\nvar dataNode = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MfXiwU7pSkeiWLcmqQJytA", + "cell_type": "markdown", + "source": [ + "Import the Dimensions, Yield Curves and Nominal Cashflows from the corresponding csv files in Initialization/Systemorph/" + ], + "metadata": {} + }, + { + "id": "VckQZIZagUGxLJK_kIkJzA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Epv9604EmEmVeKtkGt_iqA", + "cell_type": "markdown", + "source": [ + "Initialization of the Test Suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ], + "metadata": {} + }, + { + "id": "UWRWl2pRz0eA8IvYfBeXbQ", + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Actual);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Ball02llF0KmddCeo9vhsw", + "cell_type": "markdown", + "source": [ + "", + "\n## View imported Actuals" + ], + "metadata": {} + }, + { + "id": "XiBDlMNVEk-oEido9aLDsA", + "cell_type": "markdown", + "source": [ + "Here the imported Actuals from csv are visualized " + ], + "metadata": {} + }, + { + "id": "CaVs88CPvEuA-lj1QXbU4A", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetIfrsVariables(dataNode)", + "\n .Where(x => new string[] {EstimateTypes.A, EstimateTypes.AA, EstimateTypes.OA}.Contains(x.EstimateType))", + "\n .Where(x => x.AocType != \"EOP\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "J2FGEyUHWk-y2N3yq7bQGQ", + "cell_type": "markdown", + "source": [ + "where the filter is selecting only those *estimate types* associated to the imported Actuals, hence excluding the IFRS variables calculated when [importing the cashflows](SpecificationsImportCashflows)." + ], + "metadata": {} + }, + { + "id": "ZFf-ptMOJUaVX3hg-LJRPA", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Base Actuals" + ], + "metadata": {} + }, + { + "id": "q2ZSjwzGV0iSYC2rHoNKBQ", + "cell_type": "markdown", + "source": [ + "The following simplified AoC Chain applies for Advance and Overdue Actuals:", + "\n1. Beginning of Period (BOP)", + "\n2. Cash flow (CF)", + "\n3. Amortization (AM) ", + "\n4. End of Period (EOP) ", + "\n", + "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", + "\n- Actuals (A)", + "\n- Advance Actuals (AA)", + "\n- Overdue Actuals (OA)", + "\n- Deferrable Actuals (DA)", + "\n", + "\nwith the Estimate Type's system name shown between parenthesis above.", + "\nThey are computed by the so-called Actual Base **Scope**", + "\n", + "\n$$", + "\n\\text{Actual Base} (\\text{AoC}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n0 & \\text{if AoC step is AM,} \\\\", + "\n\\text{Actual Base}(\\rm{BOP}) + \\text{Actual Base}(\\rm{CF}) + \\text{Actual Base}(\\rm{WO}) & \\text{if AoC step is EOP and Estimate Type is not A,} \\\\", + "\n\\text{Imported Actual} & \\text{otherwise.}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nWe start by selecting one of the [imported Actual](#view-imported-actuals) and we pick up an available data node, novelty, and amount type. Then, we can retrieve the corresponding actual (if any) with AoC type BOP, R, and WO. ", + "\n", + "\nNote that the **Identity** for Actual Base contains information about the target data node, AoC type, novelty, amount type and estimate type." + ], + "metadata": {} + }, + { + "id": "3mz_ogsNkUOQiwgPjhzFSw", + "cell_type": "markdown", + "source": [ + "## End of Period" + ], + "metadata": {} + }, + { + "id": "1gmNQIcnYkWzuw3POkhHTg", + "cell_type": "markdown", + "source": [ + "The imported actuals for the AoC steps BOP, CF, and WO are:" + ], + "metadata": {} + }, + { + "id": "m0tpSB8gxUyDD338Zgkb2Q", + "cell_type": "code", + "source": [ + "var actualBaseBOP = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" }, \"PR\", \"AA\", (int?)null) ); ", + "\nactualBaseBOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dJten8gq_kyMKh4S8U_dzw", + "cell_type": "code", + "source": [ + "var actualBaseCF = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) );", + "\nactualBaseCF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YmaBzLIDzU-jXeSLLeah2Q", + "cell_type": "code", + "source": [ + "var actualBaseWO = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"WO\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) ); ", + "\nactualBaseWO" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kkzVuYU0TUq_BrtrZbS2Cg", + "cell_type": "markdown", + "source": [ + "Based on the imported actuals and according to the [formula above](#base-actual), the computed actual for AoC step EOP reads" + ], + "metadata": {} + }, + { + "id": "rJlipm8F8UqWjrerzqNxHw", + "cell_type": "code", + "source": [ + "var computedActualBaseEOP = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"EOP\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) ); ", + "\ncomputedActualBaseEOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "agUQcE0dMkGmHLSL3ckUNA", + "cell_type": "markdown", + "source": [ + "The computed value can be compared with the expected value" + ], + "metadata": {} + }, + { + "id": "iNuhJJEj4UukayFi6gCk5Q", + "cell_type": "code", + "source": [ + "computedActualBaseEOP.Value == actualBaseBOP.Value + actualBaseCF.Value + actualBaseWO.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LoHEbpUBtUKZRzu41Eyo1g", + "cell_type": "code", + "source": [ + "computedActualBaseEOP.Value.Should().Be( actualBaseBOP.Value + actualBaseCF.Value + actualBaseWO.Value );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "g-rX5A35Bk67CAhSb5UMBw", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Deferrable Actuals" + ], + "metadata": {} + }, + { + "id": "Yb0BdsMIdEmyenFYmcNP0g", + "cell_type": "markdown", + "source": [ + "The Deferrable Actuals (DA) are computed as follows", + "\n", + "\n$$", + "\n\\text{Deferrable Actual} (\\text{AoC}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{Actual Base}_{\\substack{\\text{Estimate Type}=\\text{A} \\\\ \\text{Amount Type}=\\text{ACA}}} (\\text{CF})", + "\n +\\text{Actual Base}_{\\substack{\\text{Estimate Type}=\\text{A} \\\\ \\text{Amount Type}=\\text{AEA}}} (\\text{CF}) & \\text{if AoC step is CF } \\\\", + "\n-\\text{AMF} \\cdot \\big( \\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) \\big) & \\text{if AoC step is AM } \\\\", + "\n\\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) + \\text{Deferrable Actual}(\\rm{AM}) & \\text{if AoC step is EOP } \\\\", + "\n\\text{Input Actual}_{\\text{Estimate Type}=\\text{DA}} (\\text{BOP}) & \\text{if AoC step is BOP } \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere ACA and AEA are *Aquisition* Amount Types from *Attributable Commission* and *Attributable Expenses*, respectively.", + "\n", + "\nNote that the **Identity** of Deferrable Actual is encompassing solely data node, Aoc type, and novelty." + ], + "metadata": {} + }, + { + "id": "dIh2Kt3mwEOjtIdYsSQLpw", + "cell_type": "markdown", + "source": [ + "## Beginning of Period" + ], + "metadata": {} + }, + { + "id": "ZwwOl_GoSEyoQi2486bksw", + "cell_type": "code", + "source": [ + "var computedDeferrableActualBOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" } );", + "\ncomputedDeferrableActualBOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rwIPbApkqk20YefMttJaBQ", + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being BOP is simply the EOP Actual of the previous period. In fact, if the latter exists among the [imported Actuals](#view-imported-actuals), it is reported here below as the BOP of the current period:" + ], + "metadata": {} + }, + { + "id": "ECOpAU6G40ecEEPHz210UQ", + "cell_type": "code", + "source": [ + "var expectedDeferrableActualBOP = Test.GetStorage().GetValue(new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" }, (string)null, EstimateTypes.DA, (int?)null);", + "\nexpectedDeferrableActualBOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "F_RpeDiSsk2xnjvgkmQyfA", + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ], + "metadata": {} + }, + { + "id": "RAI7Dd_j4kaqQJENtCDH2Q", + "cell_type": "code", + "source": [ + "computedDeferrableActualBOP.Value == expectedDeferrableActualBOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Xj5YWVMuskWq5g578_rF3g", + "cell_type": "code", + "source": [ + "computedDeferrableActualBOP.Value.Should().Be(expectedDeferrableActualBOP);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VE3a5lAE40OUqsCPrC8OkQ", + "cell_type": "markdown", + "source": [ + "## Cash flow" + ], + "metadata": {} + }, + { + "id": "KCDTqi_VaEeLnsXIQtuFfw", + "cell_type": "code", + "source": [ + "var computedDeferrableActualCF = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" } );", + "\ncomputedDeferrableActualCF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-npyFyfnKU2HKSBOkmaWqw", + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being CF is the sum of the base Actuals with Amount Type ACA and AEA:" + ], + "metadata": {} + }, + { + "id": "DMXlh_BdV0m-gGATOlCmXw", + "cell_type": "code", + "source": [ + "var actualBaseAEA = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"AEA\", \"A\", (int?)null) );", + "\nactualBaseAEA" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0bhhirWn60Sa22kkJBKxPA", + "cell_type": "code", + "source": [ + "var actualBaseACA = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"ACA\", \"A\", (int?)null) );", + "\nactualBaseACA" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "s5th00fR9km5T_Jn7WG_Tw", + "cell_type": "code", + "source": [ + "var expectedDeferrableActualCF = actualBaseAEA.Value + actualBaseACA.Value;", + "\nexpectedDeferrableActualCF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nTo3qqybYkKSKmR3F1ElOA", + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ], + "metadata": {} + }, + { + "id": "focF1ZcZDUOXSSNLlZkfFg", + "cell_type": "code", + "source": [ + "computedDeferrableActualCF.Value == expectedDeferrableActualCF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zj2ipSnC_UqYHMXCw093xg", + "cell_type": "code", + "source": [ + "computedDeferrableActualCF.Value.Should().Be(expectedDeferrableActualCF);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RQuw7gToOkS4hInnv9Kzww", + "cell_type": "markdown", + "source": [ + "## Amortization" + ], + "metadata": {} + }, + { + "id": "_MvSo7kpmEO8Lx_8g70chg", + "cell_type": "code", + "source": [ + "var computedDeferrableActualAM = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", + "\ncomputedDeferrableActualAM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GxyMep7IRUuKq-XPTZaSoA", + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being AM is the sum of the deferrable Actuals for AoC step BOP and CF multiplied by the current period amortization factor:" + ], + "metadata": {} + }, + { + "id": "YxvqYPNNPkGTrfpko0P9tg", + "cell_type": "code", + "source": [ + "var currentPeriodAmortizationFactor = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", + "\ncurrentPeriodAmortizationFactor" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CcAeUSZHEUy_ZLSZOjwWNQ", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetValue(new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" }, (string)null, \"F\", \"L\", (int?)null)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "R7RYD25pIkyzpVtr4bTYZQ", + "cell_type": "code", + "source": [ + "var expectedDeferrableActualAM = -currentPeriodAmortizationFactor.Value * (expectedDeferrableActualBOP + expectedDeferrableActualCF);", + "\nexpectedDeferrableActualAM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "57FkYeaQNEGS22T303mszw", + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ], + "metadata": {} + }, + { + "id": "vj4ilsvlW0Kd_W6yb9M_LA", + "cell_type": "code", + "source": [ + "computedDeferrableActualAM.Value == expectedDeferrableActualAM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-ZnJyECl70mF5zHLrrMwJA", + "cell_type": "code", + "source": [ + "computedDeferrableActualAM.Value.Should().Be( expectedDeferrableActualAM );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xc8raQB2aECcY5vJIlfnXw", + "cell_type": "markdown", + "source": [ + "## End of Period" + ], + "metadata": {} + }, + { + "id": "LVj_SAEOeEy1V78xmool1w", + "cell_type": "code", + "source": [ + "var computedDeferrableActualEOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"EOP\", Novelty = \"C\" } );", + "\ncomputedDeferrableActualEOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4thR0prSO0KUITk7bFfW2g", + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being EOP is the sum of the deferrable Actuals for AoC step BOP, CF, and AM:" + ], + "metadata": {} + }, + { + "id": "KCOAQSqabUmBYKvz1FRHWQ", + "cell_type": "code", + "source": [ + "var deferrableActualBOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" } );", + "\ndeferrableActualBOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-goqiLAXmEa7aVplCpRGjQ", + "cell_type": "code", + "source": [ + "var deferrableActualCF = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" } );", + "\ndeferrableActualCF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IW3UXfNFZ0CCML8Omp0uKQ", + "cell_type": "code", + "source": [ + "var deferrableActualAM = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", + "\ndeferrableActualAM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LbrMeCRVTEGd8XazzJK4UQ", + "cell_type": "code", + "source": [ + "var expectedDeferrableActualEOP = deferrableActualBOP.Value + deferrableActualCF.Value + deferrableActualAM.Value;", + "\nexpectedDeferrableActualEOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bq4Rfl5WFEejDIWSCzYAgA", + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ], + "metadata": {} + }, + { + "id": "hKN5tE4QmkuzwXxOyxc9xQ", + "cell_type": "code", + "source": [ + "computedDeferrableActualEOP.Value == expectedDeferrableActualEOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BrWWx3tS2UK7lsbEDU4TOg", + "cell_type": "code", + "source": [ + "computedDeferrableActualEOP.Value.Should().Be(expectedDeferrableActualEOP);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Rn9tO4dA3kGJWgSdp5k-hA", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/SpecificationsImportCashflows.ipynb b/Test/SpecificationsImportCashflows.ipynb new file mode 100644 index 00000000..ad03bfe5 --- /dev/null +++ b/Test/SpecificationsImportCashflows.ipynb @@ -0,0 +1,2906 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showtags": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "lI4yThFtAkGBL2c6iGY6NA", + "cell_type": "markdown", + "source": [ + "

Import Cashflows Specifications

" + ], + "metadata": {} + }, + { + "id": "XPSBZvgeJUWm3KfISi0_kw", + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the calculation of the Present Values and Amortization Factors starting from the nominal Cashflows and the Yearly Yield Curve. These starting data is imported from the corresponding csv files located in the following path Initialization/Systemorph/. The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ], + "metadata": {} + }, + { + "id": "KuBokOZnNEKyeai5pecD_A", + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ], + "metadata": {} + }, + { + "id": "ymRDCUIfokuZuGhcIgRC2Q", + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "K2nnKAzJ1kWqqKCw6hgCpg", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "vDUrjRR4W0Cab2XwoLh66g", + "cell_type": "markdown", + "source": [ + "# Import Data" + ], + "metadata": {} + }, + { + "id": "25t6_azELkmmpL2KrlobIg", + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period" + ], + "metadata": {} + }, + { + "id": "p89NHTl7QUan7LJZcHQ7CA", + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month), Reporting Node, Economic Basis, and Data Node based on the imported data:" + ], + "metadata": {} + }, + { + "id": "1AQXjlCH5UqQtZhHE_ToWA", + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"C\" ;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "C7KE2ugMTEeeZXpow5IctQ", + "cell_type": "markdown", + "source": [ + "Import the Dimensions, Yield Curves and Nominal Cashflows from the corresponding csv files in Initialization/Systemorph/" + ], + "metadata": {} + }, + { + "id": "o-K6Iedo20-WGrgowVvxNA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Kd4etWIfVECgbQOUwpJjng", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wRwk6MvytEO_Ynh6H4re9g", + "cell_type": "markdown", + "source": [ + "At this point reference data are loaded. Import now a cashfow file with a 720 elements." + ], + "metadata": {} + }, + { + "id": "u4C4qyNFokyVYXTnBsqhGw", + "cell_type": "code", + "source": [ + "var groupOfContract = \"GricComplex\";", + "\nawait UploadCashflowsAsync(\"Data/CashflowComplex.csv\")" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5qP7HJWjK0K-tb_-qAYFaw", + "cell_type": "markdown", + "source": [ + "Initialization of the Test suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ], + "metadata": {} + }, + { + "id": "_NJvnl5PKE6FQXhN5Pr_tw", + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "raVSJGuqL0i16HubdvKRSQ", + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Data Nodes" + ], + "metadata": {} + }, + { + "id": "C-jrvc1_akme8Lq4zXXNnA", + "cell_type": "markdown", + "source": [ + "The imported active Data Nodes from Initialization/Systemorph/DataNodes.csv are " + ], + "metadata": {} + }, + { + "id": "ayPI03mGFEuJqDditI5Zcg", + "cell_type": "code", + "source": [ + "Test.GetStorage().DataNodeDataBySystemName" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "PNkJZPN3D0OTE4K9m7yhtw", + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Yearly Yield Curve" + ], + "metadata": {} + }, + { + "id": "449EmK-s0EC-qvpkUic0Ng", + "cell_type": "markdown", + "source": [ + "Here the correct Yield Curve is chosen among those imported from Initialization/Systemorph/Data.csv according to the [current period](#year-and-period) and the Aoc Step according the [Aoc Configuration](../DataModel/DataStructure#aoc-configuration). In the following we retrieve the desired identity." + ], + "metadata": {} + }, + { + "id": "GFBbfoECXkyIOhUvzUj1YA", + "cell_type": "code", + "source": [ + "var aocType = \"CL\";", + "\nvar novelty = \"C\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Xh9Ph958zUaWPoHyXTfa7g", + "cell_type": "code", + "source": [ + "var id = Test.GetIdentity(groupOfContract, aocType, novelty);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LSypuaGSnkmcuusalSOIMw", + "cell_type": "code", + "source": [ + "var yearlyYieldCurve = Test.GetStorage().GetYearlyYieldCurve(id, economicBasis);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZVGOGlL470Cv6pGp5K4TQA", + "cell_type": "code", + "source": [ + "yearlyYieldCurve" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YHtOWxQvJUygOp9bM9DnOg", + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Nominal Cashflows" + ], + "metadata": {} + }, + { + "id": "nuWozOR2zUqFJgmjZjSpSw", + "cell_type": "markdown", + "source": [ + "The nominal Cashflows for the current period are loaded together with last period Cashflows for Group of Contract that were already existent. ", + "\n", + "\nThe relative files are located in: Files/.", + "\n", + "\nThe result is showed in the following list to be compared with the entries of the csv files" + ], + "metadata": {} + }, + { + "id": "5XHFiMOI_k6ZLxFuzYGObA", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetRawVariables(groupOfContract)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "i5XQoNnkHkCwFkZK-wvzeg", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Interest and Discount Rates" + ], + "metadata": {} + }, + { + "id": "QvPW08NJs0mc35ufVdJITA", + "cell_type": "markdown", + "source": [ + "The Yield Curve ${\\text{YC}_i}$ associated to the the [selected period](#year-and-period) and target currency of the Group of Contract Reporting Node is [displayed above](#view-loaded-yearly-yield-curve) and used in this section to calculate the Interest and Discount factors", + "\n", + "\n$$", + "\n\\text{Interest}_i = \\big( 1 + \\text{YC}_i \\big) ^{\\frac{1}{12}} ~,", + "\n$$", + "\n", + "\nand", + "\n", + "\n\\begin{align}", + "\n\\text{Discount}_i = \\big( 1 + \\text{YC}_i \\big) ^{-\\frac{1}{12}} ~.", + "\n\\end{align}" + ], + "metadata": {} + }, + { + "id": "Tx3o3lO8s0m5gv72S8Okfw", + "cell_type": "markdown", + "source": [ + "In the Scope named *MonthlyRate* the Interest and Discount factors are computed" + ], + "metadata": {} + }, + { + "id": "WjCiyKVx3UKysYDWgLig9w", + "cell_type": "code", + "source": [ + "var computedMonthlyRates = Test.GetScope( id );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Q4y_soImlkyK0gLglSALsQ", + "cell_type": "code", + "source": [ + "computedMonthlyRates" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fl25D0dZKk6SeRoszzGp6Q", + "cell_type": "markdown", + "source": [ + "## Interest" + ], + "metadata": {} + }, + { + "id": "Z9R5ky64QUmw-BnZLN2Jug", + "cell_type": "markdown", + "source": [ + "In the following, the Interest factors computed by the application are recalculated independently according to the formula above in two different ways" + ], + "metadata": {} + }, + { + "id": "JAjIqFrQ-UizVR9ENdEB5Q", + "cell_type": "code", + "source": [ + "var expectedInterest = yearlyYieldCurve.Select( yc => (1 + yc)^( 1.0 / 12.0) );", + "\nexpectedInterest" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KHb-pVU5lkKoPw1Yx6IOLw", + "cell_type": "code", + "source": [ + "from yc in yearlyYieldCurve select (1 + yc)^( 1.0 / 12.0 ) " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "eWIhGYRQQUSp9YT53BxCgw", + "cell_type": "code", + "source": [ + "computedMonthlyRates.Interest.CheckEquality( expectedInterest ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Pt64D8ANL06gXx9he1WVzw", + "cell_type": "markdown", + "source": [ + "## Discount" + ], + "metadata": {} + }, + { + "id": "TPUopwWBTUG3gPPmb2B5Nw", + "cell_type": "markdown", + "source": [ + "The following recalculates the Discount factors to be compared with the computed values" + ], + "metadata": {} + }, + { + "id": "YtUiQ2xnzE2FfAa6LlAcfw", + "cell_type": "code", + "source": [ + "var expectedDiscount = yearlyYieldCurve.Select( yc => (1 + yc)^( -1.0 / 12.0) );", + "\nexpectedDiscount" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZGVBiwBOUk-I3JmXZnK4JA", + "cell_type": "code", + "source": [ + "computedMonthlyRates.Discount.CheckEquality( expectedDiscount ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lMyTCC6GPUW45Cvx6U3JRw", + "cell_type": "markdown", + "source": [ + "## Test method: Get Valid Element" + ], + "metadata": {} + }, + { + "id": "FZ9_fdXlIECy7PDdcDlH1Q", + "cell_type": "markdown", + "source": [ + "Given the present Yield Curve array has finite *length*, the extrapolation implemented is taking the last element for all successive years. This behavior is given by the function *GetValidElement*. The test in this section assures that constant extrapolation is taken for *index* > *length*" + ], + "metadata": {} + }, + { + "id": "IfoqWI9zGkGc-Po9tnOcoQ", + "cell_type": "code", + "source": [ + "expectedDiscount.GetValidElement( 120 )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Z5ZpUs9wmUWbGWk6GcxNeA", + "cell_type": "code", + "source": [ + "expectedDiscount.GetValidElement( 120 ).Should().Be( expectedDiscount.Last() );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-KgziQbrF0mQYRsvkSkeGw", + "cell_type": "markdown", + "source": [ + "

", + "\n# Cashflows" + ], + "metadata": {} + }, + { + "id": "ITDv12Ph90ObEuoxNIr45w", + "cell_type": "markdown", + "source": [ + "This section deals with the calculation of the *Cumulated Discounted Cashflows* (CDC) starting from the nominal Cashflows. " + ], + "metadata": {} + }, + { + "id": "Isggf5h2S0unL3O7pgAirQ", + "cell_type": "markdown", + "source": [ + "## Choose identity" + ], + "metadata": {} + }, + { + "id": "pwQ4TMUvhUK-StHJEDFlCg", + "cell_type": "markdown", + "source": [ + "Each loaded nominal Cashflows is assigned to a so-called *Identity* which uniquely identifies it based on the *Data Node*, *Aoc Type*, and *Novelty*. In the following cells we retrieve the desired Identity:" + ], + "metadata": {} + }, + { + "id": "3MHGdD0V1k6cXBNxvaUgHA", + "cell_type": "code", + "source": [ + "var aocType = \"CL\";", + "\nvar novelty = \"C\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gPX1Ygo_DECIrwFPBvRXSQ", + "cell_type": "code", + "source": [ + "var id = Test.GetIdentity(groupOfContract, aocType, novelty);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KOWB-LuZSE6jCwSkVWLqLQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Nominal Cashflow" + ], + "metadata": {} + }, + { + "id": "7wA9Mo5SWkGRA9UpDIfDug", + "cell_type": "markdown", + "source": [ + "Consider the two Amount Type *PR* and *NIC*, with Transaction Period being *Beginning of Period* (BOP) and *End of Period* (EOP), respectively. The corresponding nominal Cashflows are deposited in the Scopes named *NominalCashflow* with the Identity provided above, Calculation Type *BE*, and the aforementioned Amount Types. These nominal Cashflows correspond with those [loaded from the csv files](#view-loaded-nominal-cashflows). " + ], + "metadata": {} + }, + { + "id": "mlWZ7mpOFkSD2Ru1TCl59g", + "cell_type": "code", + "source": [ + "var amountTypePR = \"PR\";", + "\nvar amountTypeNIC = \"NIC\";", + "\nvar calculationType = \"BE\";", + "\nvar accidentYear = (int?)null;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9TXHMp0XEEKq8LfUzqH9CA", + "cell_type": "code", + "source": [ + "var nominalPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WlEihYtxbECHWuuKVgue_w", + "cell_type": "code", + "source": [ + "nominalPR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "NERNBoD-OkiRREaV55ijeA", + "cell_type": "code", + "source": [ + "var nominalNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hFfWM0bKxkW3mOhIZgZ5AQ", + "cell_type": "code", + "source": [ + "nominalNIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "765s5aL5Z0K0t5ZLuyCojg", + "cell_type": "markdown", + "source": [ + "", + "\n## Cumulated Discounted Cashflow" + ], + "metadata": {} + }, + { + "id": "JT4SSHYyVkK6kvw6pm1RYQ", + "cell_type": "markdown", + "source": [ + "The CDC is defined by the following recursive formulas", + "\n", + "\n$$", + "\n\\text{CDC}_t = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{Nominal}_t + \\text{CDC}_{t+1} \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} ~, & \\text{if Transaction Period is Beginning of Period} \\\\", + "\n\\big( \\text{Nominal}_t + \\text{CDC}_{t+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} ~, & \\text{if Transaction Period is End of Period}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the Transaction Period depends on the given cashflow Amount Type. " + ], + "metadata": {} + }, + { + "id": "d_iKZefoME6wTrnz9UAv5A", + "cell_type": "markdown", + "source": [ + "### Beginning of Period" + ], + "metadata": {} + }, + { + "id": "espKPj1dtUuJz8XXQUAKzg", + "cell_type": "markdown", + "source": [ + "The Amount Type **Premiums** (PR) has Transaction Period **Beginning of Period** (BOP). The corresponding CDC calculated by the application is" + ], + "metadata": {} + }, + { + "id": "T7aVgGRgDEakkG-s3lfN0g", + "cell_type": "code", + "source": [ + "var computedDiscountedPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3FU71v2QJkyxs_bZfP4Uow", + "cell_type": "code", + "source": [ + "computedDiscountedPR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4YMOoutvQU-8pkN7n6TASQ", + "cell_type": "markdown", + "source": [ + "In the following cell we independently evaluate the expected discounted cashflow according to the formula above:" + ], + "metadata": {} + }, + { + "id": "ybObocoOVUKh6wl-2THKMA", + "cell_type": "code", + "source": [ + "var expectedDiscountedPR = new double[nominalPR.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalPR.Values.Length).Reverse()", + "\n .ForEach( i => expectedDiscountedPR[i] = nominalPR.Values[i] + expectedDiscountedPR.GetValidElement(i+1) * expectedDiscount.GetValidElement(i/12) );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "z256hRI3W0-dt-SPwhspvA", + "cell_type": "code", + "source": [ + "expectedDiscountedPR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kS81thpvcUK8_BDbmIGAew", + "cell_type": "code", + "source": [ + "(nominalPR.Values, nominalPR.Values.Length)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BVho0r3vFECpLdRKqXPiJQ", + "cell_type": "markdown", + "source": [ + "The expected cumulated discount is compared with the computed values" + ], + "metadata": {} + }, + { + "id": "rFrYAjOqPU6GlakOLi6Whg", + "cell_type": "code", + "source": [ + "computedDiscountedPR.Values.CheckEquality( expectedDiscountedPR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CNA426Ac4ESI3ob66JKdfg", + "cell_type": "code", + "source": [ + "computedDiscountedPR.Values.CheckEquality( expectedDiscountedPR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qGuikH-yU0uOYPbqe-xgiA", + "cell_type": "markdown", + "source": [ + "### End Of Period" + ], + "metadata": {} + }, + { + "id": "PxdI661DkEOx8fXIEikCeg", + "cell_type": "markdown", + "source": [ + "The Amount Type **Non Investment Component** (NIC) has Transaction Period **End of Period** (EOP). The corresponding CDC calculated by the application is" + ], + "metadata": {} + }, + { + "id": "glGfJSBB_UyhR3a-IkrEyw", + "cell_type": "code", + "source": [ + "var computedDiscountedNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RYBSPN2Cvk-wIGFAo24vXA", + "cell_type": "code", + "source": [ + "computedDiscountedNIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qHM_Iqz93Ee9T-BENSbB6Q", + "cell_type": "markdown", + "source": [ + "In the following cell we independently evaluate the expected discounted cashflow according to the formula above:" + ], + "metadata": {} + }, + { + "id": "MROITxwMj0ujWWt4L-Up3w", + "cell_type": "code", + "source": [ + "var expectedDiscountedNIC = new double[nominalNIC.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalNIC.Values.Length).Reverse()", + "\n .ForEach( i => expectedDiscountedNIC[i] = ( nominalNIC.Values[i] + expectedDiscountedNIC.GetValidElement(i+1) ) * expectedDiscount.GetValidElement(i/12) );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oHNnWbOAC02remoQuB3xeQ", + "cell_type": "code", + "source": [ + "expectedDiscountedNIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pxhcnJV1UUuGT40Y5o79JA", + "cell_type": "markdown", + "source": [ + "The expected cumulated discount is compared with the computed values" + ], + "metadata": {} + }, + { + "id": "fB_CWCbH30qYOnXykKpInQ", + "cell_type": "code", + "source": [ + "computedDiscountedNIC.Values.CheckEquality( expectedDiscountedNIC )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "s2gR76itBESoEBFxheTs2g", + "cell_type": "code", + "source": [ + "computedDiscountedNIC.Values.CheckEquality( expectedDiscountedNIC ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WdMso-NBKku_uV1NVbeBoQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Non Performance Risk Adjustment" + ], + "metadata": {} + }, + { + "id": "x6qIuyV8iUmHNpSrP7kT_Q", + "cell_type": "markdown", + "source": [ + "In this section we treat the determination of the non-performance risk adjustment, an element offsetting partially future", + "\nclaims according to the risk that the reinsurance company cannot fulfil the full extent of its obligations.", + "\n", + "\nFirstly, the discounting recursive relation can be written explicitly as", + "\n", + "\n$$", + "\n\\begin{array}{l}", + "\n\\text{CDC}_t = \\big( \\text{Nominal}_t + \\text{CDC}_{t+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} \\\\", + "\n\\Rightarrow \\text{CDC}_t = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau ", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor nominal Cashflows with Amount Type being *Claims*, the risk-adjusted Cumulated Discounted Cashflow ", + "\nis assigned the Amount Type **Credit Default Risk** (CDR), ", + "\nand is obtained by multiplying the right hand side of the latter formula by the corresponding risk factor", + "\n", + "\n$$", + "\n\\text{CDC}_t^{\\text{Amount Type}=\\text{CDR}} = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau^{\\text{Claim}} \\cdot \\big( e^{-\\gamma(\\tau-t)} -1 \\big)", + "\n$$", + "\n", + "\nwhere $\\gamma$ is the assumed non-performance probability of the reinsurer to be provided as an [input parameter](../DataModel/DataStructure#credit-default-rate).", + "\n", + "\nThis rate is constant for the whole projection period, that is, $\\gamma$ is not a function of $t$. ", + "\nIt effectively amounts to a constant increase in the continuous discount rate by $\\gamma$. " + ], + "metadata": {} + }, + { + "id": "a0Ap0lOGJE21INUHWmjGoQ", + "cell_type": "markdown", + "source": [ + "### Explicit vs recursive formula" + ], + "metadata": {} + }, + { + "id": "pbGuRNJm70SkHeIktIoBDQ", + "cell_type": "markdown", + "source": [ + "The explicit formula is tested versus the expected result obtained with the recursive formula" + ], + "metadata": {} + }, + { + "id": "e6e-jV9vnE6RTUlNhgK1Vw", + "cell_type": "code", + "source": [ + "var expectedDiscountedNICbis = new double[nominalNIC.Values.Length];", + "\n", + "\n//for(int t = 0; t < 12; t++)", + "\n// for(int tau = t; tau < 12; tau++)", + "\n// expectedDiscountedNICbis[t] += nominalNIC.Values[tau] * Math.Pow(expectedDiscount.GetValidElement(t/12), tau-t+1);", + "\n", + "\nEnumerable.Range(0, nominalNIC.Values.Length)", + "\n .ForEach( i => expectedDiscountedNICbis[i] = ", + "\n Enumerable.Range(i, nominalNIC.Values.Length-i).Select( tau => nominalNIC.Values[tau] * Math.Pow(expectedDiscount.GetValidElement(i/12), tau-i+1) ).Sum() );", + "\n ", + "\nexpectedDiscountedNIC.CheckEquality( expectedDiscountedNICbis )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7VKY58rmN0i4hNUObTx5Lg", + "cell_type": "markdown", + "source": [ + "### Risk Adjusted Claims " + ], + "metadata": {} + }, + { + "id": "CDMXGMuNGUWSY2-VFbiSkQ", + "cell_type": "markdown", + "source": [ + "The computed CDC with Amount Type being CDR reads" + ], + "metadata": {} + }, + { + "id": "XnvESgljxkSWyht7EqW7NA", + "cell_type": "code", + "source": [ + "var computedDiscountedCRD = Test.GetScope((id, \"CDR\", calculationType, accidentYear));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "reDXOTbUxEGUchxSzysJog", + "cell_type": "code", + "source": [ + "computedDiscountedCRD" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nv4x6ysZxEmmtipcaDJy9g", + "cell_type": "markdown", + "source": [ + "The starting point for the non performance risk adjustment is the computation of the sum of nominal Cashflows with Amount Type **Claims** listed below" + ], + "metadata": {} + }, + { + "id": "bOQ1CXDjbUOygxJaPI-XYQ", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetClaims()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0pTAfl977UK_SmRREnPF6Q", + "cell_type": "markdown", + "source": [ + "with the corresponding nominal Cashflows being" + ], + "metadata": {} + }, + { + "id": "syJWhInzsEObE2ykdoGLew", + "cell_type": "code", + "source": [ + "var nominalNIC = Test.GetScope((id, \"NIC\", calculationType, accidentYear));", + "\nnominalNIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "C7ko6wgyUkSyCQS2-Q8GuQ", + "cell_type": "code", + "source": [ + "var nominalICO = Test.GetScope((id, \"ICO\", calculationType, accidentYear));", + "\nnominalICO" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GrTtn99Pc0KsTrYaIj7vhg", + "cell_type": "code", + "source": [ + "var nominalALE = Test.GetScope((id, \"ALE\", calculationType, accidentYear));", + "\nnominalNIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gAGXa9ftTUODRVbLikWr2A", + "cell_type": "code", + "source": [ + "var nominalULE = Test.GetScope((id, \"ULE\", calculationType, accidentYear));", + "\nnominalNIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ybob0Y2K00ysBNz_vpid2w", + "cell_type": "code", + "source": [ + "var nominalClaims = nominalICO.Values + nominalNIC.Values + nominalALE.Values + nominalULE.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7UXMUmrFwEKfhXV-EPyNOQ", + "cell_type": "markdown", + "source": [ + "Secondly, the correct credit risk rate (parameter $\\gamma$ in the [formula above](#non-performance-risk-adjustment)) is retrieved from the list of imported [Partner Rating](../DataModel/DataStructure) and [Credit Default Rates](../DataModel/DataStructure) relative to the target [Data Node](#year-and-period)'s Partner" + ], + "metadata": {} + }, + { + "id": "to_RSXazSEKtePbtjP11bA", + "cell_type": "code", + "source": [ + "groupOfContract" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qblrNkgGZkibWZqeduwsJg", + "cell_type": "code", + "source": [ + "var creditDefaultRate = Test.GetStorage().GetNonPerformanceRiskRate( id );", + "\ncreditDefaultRate" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OAZT23-9Uk2Bs3qRbvUOKw", + "cell_type": "markdown", + "source": [ + "Lastly, using the [formula above](#non-performance-risk-adjustment), the expected CDR discounted Cashflow can be computed" + ], + "metadata": {} + }, + { + "id": "rUJBZVBNdU-8u5dSP4bv8w", + "cell_type": "code", + "source": [ + "var expectedDiscountedCDR = new double[nominalNIC.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalClaims.Length).ForEach( t => ", + "\n expectedDiscountedCDR[t] = Enumerable.Range(t, nominalClaims.Length-t).Select( tau => ", + "\n nominalClaims[tau] * Math.Pow(expectedDiscount.GetValidElement(t/12), tau-t+1) * (Math.Exp(-creditDefaultRate*(tau-t)) - 1)", + "\n ).Sum() );", + "\n", + "\nexpectedDiscountedCDR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kKmpjPuP70GAVkBoNBqNrA", + "cell_type": "markdown", + "source": [ + "Finally, the expected cumulated discount is compared with the computed values" + ], + "metadata": {} + }, + { + "id": "m_bSBl61DE26IDp7VpY6dg", + "cell_type": "code", + "source": [ + "computedDiscountedCRD.Values.CheckEquality( expectedDiscountedCDR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DqkJo2YgcE65RX7db90WKQ", + "cell_type": "code", + "source": [ + "computedDiscountedCRD.Values.CheckEquality( expectedDiscountedCDR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mvwCM2Umf0OZHCcpOt9V5Q", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Present Values" + ], + "metadata": {} + }, + { + "id": "jzTF3NdnHkqzQ4KSajU3ig", + "cell_type": "markdown", + "source": [ + "For an implementation of these formulas refer to the [ImportScopeCalculation notebook](../Import/ImportScopeCalculation). " + ], + "metadata": {} + }, + { + "id": "g03stTrBDk-qgVynbAHR8w", + "cell_type": "markdown", + "source": [ + "The company portfolio value in one period is given by the following Analysis of Change AoC steps:", + "\n1. Beginning of Period (BoP): starting value of the portfolio as of December last year (in the Year to Date view), ", + "\n2. Model Corrections (MC): change of the portfolio value based on the model change,", + "\n3. Cash Flow (CF):", + "\n4. Interest Accretion (IA): ", + "\n5. Assumption Update (AU): ", + "\n6. Yield Curve Update (YCU): impact of yield curve update occured during the reporting period,", + "\n7. Credit Risk Update (CRU): impact of credit default rate update occured during the reporting period,", + "\n8. Experience Variance (EV): value adjustments following insurance related events which took place (e.g. mortality),", + "\n9. Combined Liabilities (CL):", + "\n10. End of Period (EOP): portfolio value at the end of the current period.", + "\n", + "\nNote: the AoC steps WO, EA and AM are not included in the Present Value calculation, hence their values if inquired is zero." + ], + "metadata": {} + }, + { + "id": "YcUNq4BqbUuS6xpbevFZDw", + "cell_type": "markdown", + "source": [ + "The Present Value Base (PVB) values are valid for all [Economic Basis](../DataModel/DataStructure#economic-basis) and depends on the corresponding [AoCType](../DataModel/DataStructure#aoc-type):", + "\n", + "\n$$", + "\n\\text{PVB}_t \\big(\\text{AoC}\\big) = ", + "\n\\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{CDC}_t & \\text{if AoC is Beginning of Period (BOP) } \\\\", + "\n-\\text{Nominal}_t(\\text{Parent AoC}) & \\text{if AoC is Expected Cashflow (CF) } \\\\", + "\n\\text{InterestAccretion}_t & \\text{if AoC is Interest Accretion (IA) } \\\\", + "\n\\text{CDC}_t(\\text{Parent AoC}) & \\text{if AoC is End of Period (EOP) } \\\\", + "\n\\text{CDC}_{t}(\\text{current AoC}) - \\text{CDC}_{t}(\\text{parent AoC}) & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nand the Projected Present Value (PPV) reads", + "\n", + "\n$$", + "\n\\text{PPV} \\big(\\text{AoC},\\text{TS},\\text{S}\\big) = \\left\\{", + "\n\\begin{array}{cll}", + "\n\\text{PVB}_{S} & \\text{if AoC Valuation Period is Beginning of Period } & \\text{ (e.g. BOP, MC) } \\\\", + "\n\\text{PVB}_{S+TS/2 -1} & \\text{if AoC Valuation Period is Mid of Period } & \\text{ (no examples in current data model) } \\\\", + "\n\\sum_{i=S}^{S + TS -1}\\text{PVB}_{i} & \\text{if AoC Valuation Period is Delta } & \\text{ (e.g. CF, IA) } \\\\", + "\n\\text{PVB}_{S + TS} & \\text{if AoC Valuation Period is End of Period } & \\text{ (e.g. YCU, CRU, EV, CL, EOP) } \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the Shift (S) and Time Step (TS) are derived from the current [Year and Period](#year-and-period)" + ], + "metadata": {} + }, + { + "id": "96OPjQu30EWs42-nfLhp4A", + "cell_type": "code", + "source": [ + "var projectionPeriod = 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4ZzZwXo6T0-e0QLjP8y4hg", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetShift(projectionPeriod)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "netwTLrv3EmUheR4K9fkww", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetTimeStep(projectionPeriod)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HMUKlLJN6kCSVDgFWS5NUw", + "cell_type": "markdown", + "source": [ + "## Load Cashflow Data" + ], + "metadata": {} + }, + { + "id": "HZbqZPP1wUiVXHajP55O6w", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZWm_0QT1NEy3vrI1pssFEg", + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ERPDxPrxRE2F80hUf91cqQ", + "cell_type": "markdown", + "source": [ + "At this point standard Cashflows are loaded." + ], + "metadata": {} + }, + { + "id": "5qSxlX_u-0a1kyOkKpWkrw", + "cell_type": "markdown", + "source": [ + "Initialization of the Test suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ], + "metadata": {} + }, + { + "id": "yQhC05DCzEGeOGNpEf3mbg", + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "R-gHWFQh4USaSbZeSX4nRA", + "cell_type": "markdown", + "source": [ + "## Select Group of Contract", + "\n", + "\nHere, it is possible to select the Group of Contract used to run the next section of this Notebook." + ], + "metadata": {} + }, + { + "id": "S6Fw2Fa0UUOkuS8wyQfBtg", + "cell_type": "code", + "source": [ + "groupOfContract = \"DTR1.1\" ;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hT5J5i-Tk0evmsGzFslKZA", + "cell_type": "markdown", + "source": [ + "## Beginning of Period" + ], + "metadata": {} + }, + { + "id": "nvqfr4Ux3kWlzwsCW0_USg", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Beginning of Period is:" + ], + "metadata": {} + }, + { + "id": "fC63Uw1ey0OYVorrzegYrA", + "cell_type": "code", + "source": [ + "var idBoP = Test.GetIdentity(groupOfContract, \"BOP\", \"I\");", + "\nidBoP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-_jk2YKNT0u7l9uCTrc18w", + "cell_type": "code", + "source": [ + "var computedPvBaseBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseBoP_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ddqVdgtt20KgvWxmw6d8tQ", + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, the expected BOP AoCType for PVB is defined to be equal to the discounted cashflows with the same Identity, Amount Type, and Calculation Type, whereas the PPV is the S-th element of the PVB." + ], + "metadata": {} + }, + { + "id": "UCd_zlXg7UKAz7Ak8etIKQ", + "cell_type": "code", + "source": [ + "var discountedBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", + "\ndiscountedBoP_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "he2CNq7s20a2kIAEI1Ew5A", + "cell_type": "code", + "source": [ + "var expectedPvBaseBoP_PR = discountedBoP_PR.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "k8y7lMCUU0ahMIV2XNly5w", + "cell_type": "markdown", + "source": [ + "In the following cell we check whether the expected values match the computed values" + ], + "metadata": {} + }, + { + "id": "E_a4AaUiYU-qVqiFMH4Ffg", + "cell_type": "code", + "source": [ + "computedPvBaseBoP_PR.Values.CheckEquality( expectedPvBaseBoP_PR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "USXwqdZpmEOlDJdxqDBZaA", + "cell_type": "code", + "source": [ + "computedPvBaseBoP_PR.Values.CheckEquality( expectedPvBaseBoP_PR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-zbiX1EOvUaXOZIuba9Jbw", + "cell_type": "markdown", + "source": [ + "", + "\n## Model Corrections" + ], + "metadata": {} + }, + { + "id": "8tg7sZov10aMykVfqjUstg", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Model Corrections is:" + ], + "metadata": {} + }, + { + "id": "CxmloqNXXkaE5PpJU1ydAQ", + "cell_type": "code", + "source": [ + "var idMC = Test.GetIdentity(groupOfContract, \"MC\", \"I\");", + "\nidMC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nvbs4pu8Sk-fnfw1MqBJEQ", + "cell_type": "code", + "source": [ + "var computedPvBaseMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseMC_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8I2WEVons0iuf2UA4TyGtQ", + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for MC AoCType, the PVB is equal to the difference between the CDC of the current AoCType and the CDC of its parent. Additionally, the PPV is the S-th element of the PVB." + ], + "metadata": {} + }, + { + "id": "XX3McWqdQECPv33I70zR8w", + "cell_type": "code", + "source": [ + "Test.GetScope((idMC, \"PR\")).Values" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dnlMbprPGEefEvBLpE3SVA", + "cell_type": "code", + "source": [ + "var discountedMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", + "\ndiscountedMC_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "pqOSCzCTJEyNauxM07RTvg", + "cell_type": "code", + "source": [ + "var expectedPvBaseMC_PR = discountedMC_PR.Values - discountedBoP_PR.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gjdYsN-ftE-HlOKgEwvQLg", + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ], + "metadata": {} + }, + { + "id": "WOMu6tnVOEWiRZqaziMRcg", + "cell_type": "code", + "source": [ + "computedPvBaseMC_PR.Values.CheckEquality( expectedPvBaseMC_PR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TvZ78p6vLkCL-xejOqvUcw", + "cell_type": "code", + "source": [ + "computedPvBaseMC_PR.Value == expectedPvBaseMC_PR[0]" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "w9D4tVGk5UmDB-tTCeS5Rw", + "cell_type": "code", + "source": [ + "computedPvBaseMC_PR.Values.CheckEquality( expectedPvBaseMC_PR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nnvwi_zKy0ebrac1nrqanQ", + "cell_type": "code", + "source": [ + "computedPvBaseMC_PR.Value.Should().Be( expectedPvBaseMC_PR[0] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jiKZ8kbywUK4oPhyLtuzFg", + "cell_type": "markdown", + "source": [ + "## Cashflow" + ], + "metadata": {} + }, + { + "id": "LG4pdtcxt0K_GSnJ0CDHLA", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Cashflow is:" + ], + "metadata": {} + }, + { + "id": "CIshbPDh_0OC_HeMFEe2Rw", + "cell_type": "code", + "source": [ + "var idCF = Test.GetIdentity(groupOfContract, \"CF\", \"I\");", + "\nidCF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5sLKCaklikuTAXBf9hAoGQ", + "cell_type": "code", + "source": [ + "var computedPvBaseCF_PR = Test.GetScope((idCF, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseCF_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VNaRi132eUy9m4SnHizakQ", + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for CF AoCType, the PVB is equal to the nominal cashflow of its parent AoC step with opposite sign. The PPV is given by the sum of the first 3 elements." + ], + "metadata": {} + }, + { + "id": "pad5L8Zv40a1HYc508KwvA", + "cell_type": "code", + "source": [ + "var cfReferenceAocStep = Test.GetScope(idCF).Value;", + "\ncfReferenceAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "d_4naEye_0ez9ceQFlUsHg", + "cell_type": "code", + "source": [ + "var cfNominalReference_PR = Test.GetScope((idCF with {AocType = cfReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", + "\ncfNominalReference_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YSGvWpZAgk676PWkouVFvg", + "cell_type": "code", + "source": [ + "var expectedPvBaseCF_PR = -1.0 * cfNominalReference_PR.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "T8i5WyGKH0eb6JTHWt3k3w", + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ], + "metadata": {} + }, + { + "id": "mlrKZMMExkOXb_z-QA-nzQ", + "cell_type": "code", + "source": [ + "computedPvBaseCF_PR.Values.CheckEquality( expectedPvBaseCF_PR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_iXoBI2Ra06t95Lv-UKmdQ", + "cell_type": "code", + "source": [ + "computedPvBaseCF_PR.Values[0] + computedPvBaseCF_PR.Values[1] + computedPvBaseCF_PR.Values[2] == computedPvBaseCF_PR.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QWPx_7NUmEyE5Xu_kEeyjg", + "cell_type": "code", + "source": [ + "computedPvBaseCF_PR.Values.CheckEquality( expectedPvBaseCF_PR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MSbSF0-9w0-iu_c3cNINjA", + "cell_type": "code", + "source": [ + "computedPvBaseCF_PR.Value.Should().Be( computedPvBaseCF_PR.Values[0] + computedPvBaseCF_PR.Values[1] + computedPvBaseCF_PR.Values[2] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iO7keKMcaE2t2gXC_7kqsA", + "cell_type": "markdown", + "source": [ + "", + "\n## Interest Accretion" + ], + "metadata": {} + }, + { + "id": "m6ZEzxBBsUyJ_QAcvMD6dA", + "cell_type": "markdown", + "source": [ + "For IA AoCType, the PVB is given by the following relation ", + "\n", + "\n$$", + "\n\\text{InterestAccretion}_i = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\big(\\text{CDC}_i(\\text{Parent AoC}) - \\text{Nominal}_i(\\text{parent AoC}) \\big) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, ", + "\n & \\text{if AmountType Transaction Period is Beginning of Period} \\\\", + "\n\\text{CDC}_i(\\text{parent AoC}) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, ", + "\n & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhile the PPV is given by the sum of the first S elements.", + "\n", + "\nWhen selecting the Identity, note that the Novelty *C* is not contemplated for Interest Accretion." + ], + "metadata": {} + }, + { + "id": "NMCk4gASMU62Bn6JnDxQmQ", + "cell_type": "code", + "source": [ + "var idIA = Test.GetIdentity(groupOfContract, \"IA\", \"I\");", + "\nidIA" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fGjntj5jp0KxtiO6hKj29A", + "cell_type": "markdown", + "source": [ + "### Amount Type BOP" + ], + "metadata": {} + }, + { + "id": "byoRIpg2MkegjRvCvI9Ung", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Amount Type **Premiums** (PR) with Transaction Period **Beginning of Period** (BOP) is" + ], + "metadata": {} + }, + { + "id": "ZiyHW9AJqEqeFgbYLv9FQA", + "cell_type": "code", + "source": [ + "var computedPvBaseIA_PR = Test.GetScope((idIA, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseIA_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XsDT4dnWfEqsJ28QKuHueg", + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the interest factors, the nominal and discounted Cashflow of the parent Aoc Step" + ], + "metadata": {} + }, + { + "id": "yFVC3VGv4E2tNAJb0CRucw", + "cell_type": "code", + "source": [ + "var iaComputedMonthlyRates = Test.GetScope( idIA );", + "\niaComputedMonthlyRates" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kNS1BMQgXUCkSOuUK_IS7g", + "cell_type": "code", + "source": [ + "var iaReferenceAocStep = Test.GetScope(idIA).Value;", + "\niaReferenceAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "m6gpvEMNwEqFRImTGZBmTQ", + "cell_type": "code", + "source": [ + "var nominalIaReference_PR = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", + "\nnominalIaReference_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kEFdXGJHjkK39Ed9UMwNQA", + "cell_type": "code", + "source": [ + "var discountedIaReference_PR = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", + "\ndiscountedIaReference_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "b-s6yRRvEUeLF_z6-rD7lw", + "cell_type": "code", + "source": [ + "var expectedPvBaseIA_PR = discountedIaReference_PR.Values.Select((val, index) => ( val - nominalIaReference_PR.Values[index]) * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kpN29rNO-Uu2al_yAtJQVg", + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ], + "metadata": {} + }, + { + "id": "2R1QDTLoAkSYgN3VL0pXxg", + "cell_type": "code", + "source": [ + "computedPvBaseIA_PR.Values.CheckEquality( expectedPvBaseIA_PR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ioWKmAEOBk6ly7qdPm8UcQ", + "cell_type": "code", + "source": [ + "computedPvBaseIA_PR.Values[0] + computedPvBaseIA_PR.Values[1] + computedPvBaseIA_PR.Values[2] == computedPvBaseIA_PR.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lLcVd6QU_E-CV-zx6UKKyw", + "cell_type": "code", + "source": [ + "computedPvBaseIA_PR.Values.CheckEquality( expectedPvBaseIA_PR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nksstSVXV0KMKV3s1Qzbjw", + "cell_type": "code", + "source": [ + "computedPvBaseIA_PR.Value.Should().Be( computedPvBaseIA_PR.Values[0] + computedPvBaseIA_PR.Values[1] + computedPvBaseIA_PR.Values[2] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-DoJ5d5hPkGgyuUIARfcpw", + "cell_type": "markdown", + "source": [ + "### Amount Type EOP" + ], + "metadata": {} + }, + { + "id": "AIiYNFEf4EC9W5W55HyRuw", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Amount Type **Non Investment Component** (NIC) with Transaction Period **End of Period** (EOP) is" + ], + "metadata": {} + }, + { + "id": "1sPIRjZ290ekFi_RcQIo0g", + "cell_type": "code", + "source": [ + "var computedPvBaseIA_NIC = Test.GetScope((idIA, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPvBaseIA_NIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8nDAQ54uqUOqhCa5ArK8Ig", + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the interest monthly rates, the discounted Cashflow of the parent Aoc Step" + ], + "metadata": {} + }, + { + "id": "HMwmW4WN50q8XsSBrLA9mw", + "cell_type": "code", + "source": [ + "var iaReferenceAocStep = Test.GetScope(idIA).Value;", + "\niaReferenceAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "harsyLraKU-NCaV-qs_10A", + "cell_type": "code", + "source": [ + "var discountedIaReference_NIC = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"NIC\", \"BE\", (int?)null));", + "\ndiscountedIaReference_NIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CeJcWORR1USjRX0vRrD9uw", + "cell_type": "code", + "source": [ + "var expectedPvBaseIA_NIC = discountedIaReference_NIC.Values.Select((val, index) => val * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Bg1hcEUU9UarAJ7j6K3Cgg", + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ], + "metadata": {} + }, + { + "id": "hiB4BkoAvUWvG3yaH-lUgg", + "cell_type": "code", + "source": [ + "computedPvBaseIA_NIC.Values.CheckEquality( expectedPvBaseIA_NIC )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FAOKIDlrpEiY95BXbRJ9Lg", + "cell_type": "code", + "source": [ + "computedPvBaseIA_NIC.Values[0] + computedPvBaseIA_NIC.Values[1] + computedPvBaseIA_NIC.Values[2] == computedPvBaseIA_NIC.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3XieKhmULE2hpsAGvEz6Jw", + "cell_type": "code", + "source": [ + "computedPvBaseIA_NIC.Values.CheckEquality( expectedPvBaseIA_NIC ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7eg7INUm50qXDWFveCVSJA", + "cell_type": "code", + "source": [ + "computedPvBaseIA_NIC.Value.Should().Be( computedPvBaseIA_NIC.Values[0] + computedPvBaseIA_NIC.Values[1] + computedPvBaseIA_NIC.Values[2] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6PbcOZfV3Ua46NCV9bNvnw", + "cell_type": "markdown", + "source": [ + "## Yield Curve Update" + ], + "metadata": {} + }, + { + "id": "AJCuWf4c_kG-MTka3KHH9A", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Yield Curve Update is:" + ], + "metadata": {} + }, + { + "id": "xECM9ubIAUWuJJQrVhS96Q", + "cell_type": "code", + "source": [ + "var idYcu = Test.GetIdentity(groupOfContract, \"YCU\", \"I\");", + "\nidYcu" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZtcMBnMzIkCuhjXxj25VQA", + "cell_type": "code", + "source": [ + "var computedPvBaseYCU_PR = Test.GetScope((idYcu, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseYCU_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "i_nXQ_NxtkanS4_VPwpXAA", + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the discount factors for beginning of period and for end of period applied to the reference Aoc step, followed by the difference between the CDC obtained with end of period discount factor and the CDC obtained with beginning of period discount factor. " + ], + "metadata": {} + }, + { + "id": "qPgsLajbvEek7uwPNGMznw", + "cell_type": "code", + "source": [ + "var ycReferenceAocStep = Test.GetScope(idYcu).Value;", + "\nycReferenceAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "s8uI23FdzE6M9phEhZvlpg", + "cell_type": "code", + "source": [ + "var ycParentAocStep = Test.GetScope((idYcu, \"PR\")).Values.Single();", + "\nycParentAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "utP-1N2gHk2noyPx1Bz_Xw", + "cell_type": "code", + "source": [ + "var ycParentId = idYcu with {AocType = ycParentAocStep.AocType, Novelty = ycParentAocStep.Novelty};", + "\nycParentId" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mtfbhW8_Fkar_ZID9fIKvw", + "cell_type": "markdown", + "source": [ + "Here is the parent AocStep discounted with the beginning of period discount factor." + ], + "metadata": {} + }, + { + "id": "m-hTC4iApEK8Ex_Oq8nqYQ", + "cell_type": "code", + "source": [ + "var discountedYcParent = Test.GetScope((ycParentId, \"PR\", \"BE\", (int?)null));", + "\ndiscountedYcParent" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "y1gdrxvTuE6sNtropNbIvg", + "cell_type": "markdown", + "source": [ + "Here we independently compute the CDC of the parent AocStep discounted with end of period discount factor." + ], + "metadata": {} + }, + { + "id": "v2NdunV9lUCmDXNy3tWk5g", + "cell_type": "code", + "source": [ + "var nominalYcParent = Test.GetScope((ycParentId, \"PR\", \"BE\", (int?)null));", + "\nnominalYcParent" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Y5RkFcGlxUWUCsWbNDtAbg", + "cell_type": "code", + "source": [ + "var ycComputedMonthlyRates = Test.GetScope( idYcu );", + "\nycComputedMonthlyRates" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Yko2CYybLEGJHMKwCDW3-g", + "cell_type": "code", + "source": [ + "var ycReferenceDiscountedEop = new double[nominalYcParent.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalYcParent.Values.Length).Reverse()", + "\n .ForEach( i => ycReferenceDiscountedEop[i] = nominalYcParent.Values[i] + ycReferenceDiscountedEop.GetValidElement(i+1) * ycComputedMonthlyRates.Discount.GetValidElement(i/12) );", + "\nycReferenceDiscountedEop" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-nB_BwXaFUSg1RGG9OtRWQ", + "cell_type": "code", + "source": [ + "var expectedPvBaseYCU_PR = ycReferenceDiscountedEop - discountedYcParent.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oqAvk5VK906PkRkAT2OaRg", + "cell_type": "code", + "source": [ + "computedPvBaseYCU_PR.Values.CheckEquality( expectedPvBaseYCU_PR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tUv9lq_VLEqCkXFKJJuQig", + "cell_type": "code", + "source": [ + "computedPvBaseYCU_PR.Value == expectedPvBaseYCU_PR[3]" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "m4ee2o2DZ0aKf2FH92STsw", + "cell_type": "code", + "source": [ + "computedPvBaseYCU_PR.Values.CheckEquality( expectedPvBaseYCU_PR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kA0wrkGJaUG-mcZFz8IYPw", + "cell_type": "code", + "source": [ + "computedPvBaseYCU_PR.Value.Should().Be( expectedPvBaseYCU_PR[3] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "USKTbJfkSE607v_NwHKjvA", + "cell_type": "markdown", + "source": [ + "## Credit Risk Update" + ], + "metadata": {} + }, + { + "id": "QxohiF0860mtmiIoW8C26A", + "cell_type": "markdown", + "source": [ + "This Aoc Step is relevant only in the case of a Group of Reinsurance Contract." + ], + "metadata": {} + }, + { + "id": "aN_4K8LWFU-JoAvOSlRyvw", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Credit Risk Update is:" + ], + "metadata": {} + }, + { + "id": "JuGimhzAIEKT0SIZKqog0w", + "cell_type": "code", + "source": [ + "var idCru = Test.GetIdentity(groupOfContract, \"CRU\", \"I\");", + "\nidCru" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "77exgwl5wUefPwQGSvv_nA", + "cell_type": "code", + "source": [ + "var computedPvBaseCRU = Test.GetScope((idCru, \"CDR\", \"BE\", (int?)null));", + "\ncomputedPvBaseCRU" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ltjSbNI1_k-mVdX0EBv-xA", + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently starting as the difference between the CDC obtained with end of period credit default risk rate and the CDC obtained with beginning of period credit default risk rate, both computed using the Nominal cashflow of the reference Aoc Step and the End Of Period discounting factors. " + ], + "metadata": {} + }, + { + "id": "5Mi2lhLj9kivaiTjvv2G1Q", + "cell_type": "code", + "source": [ + "var cruReferenceAocStep = Test.GetScope(idCru).Value;", + "\ncruReferenceAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "px7VkUXT10yK8uLGIu7UEw", + "cell_type": "code", + "source": [ + "var cruReferenceId = idCru with {AocType = cruReferenceAocStep.AocType, Novelty = cruReferenceAocStep.Novelty};", + "\ncruReferenceId" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0EZECyt5MEWdc8mjDVvhuA", + "cell_type": "code", + "source": [ + "var cruParentAocStep = Test.GetScope((idCru, \"CDR\")).Values.Single();", + "\ncruParentAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "osW4gCnv2EKUPFxXxAMqJA", + "cell_type": "code", + "source": [ + "var cruParentId = idCru with {AocType = cruParentAocStep.AocType, Novelty = cruParentAocStep.Novelty};", + "\ncruParentId" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LpyKsQ8EekaZw0sPwhs2Vw", + "cell_type": "markdown", + "source": [ + "Here is the parent AocStep discounted with beginning of period credit default risk rate." + ], + "metadata": {} + }, + { + "id": "72C7qsrN9Ui9B_XYbrIpsQ", + "cell_type": "code", + "source": [ + "var discountedCruParent = Test.GetScope((cruParentId, \"CDR\", \"BE\", (int?)null));", + "\ndiscountedCruParent" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vRLrx8ecq02PiEdHXn3hBg", + "cell_type": "code", + "source": [ + "var nominalCruReference = Test.GetScope((cruReferenceId, \"CDR\", \"BE\", (int?)null)).Values;", + "\nnominalCruReference" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jLV_5_vMx0OrVHD_Yu5mVA", + "cell_type": "code", + "source": [ + "var creditDefaultRate = Test.GetStorage().GetNonPerformanceRiskRate( idCru );", + "\ncreditDefaultRate" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VEgXXlyhrEawDMht-nAV9A", + "cell_type": "code", + "source": [ + "var cruComputedMonthlyRates = Test.GetScope( idCru );", + "\ncruComputedMonthlyRates" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "owmqecMemE-q5q164EhXnw", + "cell_type": "markdown", + "source": [ + "Lastly, using the [formula above](#non-performance-risk-adjustment), the expected CDR discounted Cashflow can be computed" + ], + "metadata": {} + }, + { + "id": "LYbZBgKavEO7IynuEAXGcA", + "cell_type": "code", + "source": [ + "var cruExpectedDiscountedCDR = new double[nominalCruReference.Length];", + "\n", + "\nEnumerable.Range(0, nominalCruReference.Length).ForEach( t => ", + "\n cruExpectedDiscountedCDR[t] = Enumerable.Range(t, nominalCruReference.Length-t).Select( tau => ", + "\n nominalCruReference[tau] * ", + "\n Math.Pow(cruComputedMonthlyRates.Discount.GetValidElement(t/12), tau-t+1) * ", + "\n (Math.Exp(-creditDefaultRate*(tau-t)) - 1)", + "\n ).Sum() );", + "\n", + "\ncruExpectedDiscountedCDR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "f8a9p87_WUCugmBsw0E4sA", + "cell_type": "code", + "source": [ + "var expectedPvBaseCRU = cruExpectedDiscountedCDR - discountedCruParent.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7odSeJ5RTUmTR32M-5tlAA", + "cell_type": "code", + "source": [ + "computedPvBaseCRU.Values.CheckEquality( expectedPvBaseCRU )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ojtYz8I9xkaTA1AcV3U1Cw", + "cell_type": "code", + "source": [ + "computedPvBaseCRU.Value == expectedPvBaseCRU[3]" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WH8Cl5EMp0ewbK4iQ7-W3A", + "cell_type": "code", + "source": [ + "computedPvBaseCRU.Values.CheckEquality( expectedPvBaseCRU ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-4irtBVO70uLS-mVjr-3jQ", + "cell_type": "code", + "source": [ + "computedPvBaseCRU.Value.Should().Be( expectedPvBaseCRU[3] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QLzUGR2eJk-J02bHAg78sg", + "cell_type": "markdown", + "source": [ + "## Combined Liabilities" + ], + "metadata": {} + }, + { + "id": "bxMjiXdzt0a-HXTolLPSig", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Combined Liabilities and Amount Type PR is:" + ], + "metadata": {} + }, + { + "id": "iWOEJ3tfb02n5-nhXKNWPg", + "cell_type": "code", + "source": [ + "var idCL = Test.GetIdentity(groupOfContract, \"CL\", \"C\");", + "\nidCL" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RxytwcSRIEOh4gnpLjM-6A", + "cell_type": "code", + "source": [ + "var computedPvBaseCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseCL_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "L0VyPzCrw02LlbNwi8lo6Q", + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for CL AoCType, the PVB is equal to the difference between the CDC of the current AoCType and the CDC of its parent(s). Additionally, the PPV is the $(\\text{S}+\\text{TS})$-th element of the PVB." + ], + "metadata": {} + }, + { + "id": "eWjL6y9C3k-py-95Mi0SJg", + "cell_type": "code", + "source": [ + "var clParents = Test.GetScope((idCL,\"PR\")).Values;", + "\nclParents" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "o7Xu2o42K0SylUpXrn5bIw", + "cell_type": "code", + "source": [ + "var expectedPvBaseCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values -", + "\n clParents.Select(aocStep => Test.GetScope((idCL with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, \"PR\", \"BE\", (int?)null)).Values).Aggregate();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "2Pzjvmq7BEGnPjDo-Jvo3g", + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ], + "metadata": {} + }, + { + "id": "mJ3zeyh3YUSL7myhsdowKg", + "cell_type": "code", + "source": [ + "computedPvBaseCL_PR.Values.CheckEquality( expectedPvBaseCL_PR )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "t8dZLcMcYEiQaGohNjbhbw", + "cell_type": "code", + "source": [ + "computedPvBaseCL_PR.Value == expectedPvBaseCL_PR[3]" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CG2NuOh-OUWD0O9KjUlTKg", + "cell_type": "code", + "source": [ + "computedPvBaseCL_PR.Values.CheckEquality( expectedPvBaseCL_PR ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FNsLWW7W6UmZwW_agz-FbQ", + "cell_type": "code", + "source": [ + "computedPvBaseCL_PR.Value.Should().Be( expectedPvBaseCL_PR[3] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YAUW6hLjTkSDSB8hvqc-Ow", + "cell_type": "markdown", + "source": [ + "## End of Period" + ], + "metadata": {} + }, + { + "id": "ED73CBkcQkyvPg6_7eDFSg", + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type End of Period is:" + ], + "metadata": {} + }, + { + "id": "k3jsi34sxkSGoxKA1Btb1g", + "cell_type": "code", + "source": [ + "var idEOP = Test.GetIdentity(groupOfContract, \"EOP\", \"C\");", + "\nidEOP" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "s86AHJ-4Pk6Va461mh5gBQ", + "cell_type": "code", + "source": [ + "var computedPvBaseEOP_NIC = Test.GetScope((idEOP, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPvBaseEOP_NIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QVXK0fUvN0-yuvBbKXPPrw", + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for EOP AoCType, the PVB is equal to the CDC of the parent AoC step, while the PPV is the $(\\text{S}+\\text{TS})$-th element of the PVB." + ], + "metadata": {} + }, + { + "id": "22vabLHnN0uty9-9BNNPNg", + "cell_type": "code", + "source": [ + "var eopReferenceAocStep = Test.GetScope(idEOP).Value;", + "\neopReferenceAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ECiuOq0oL0eK5tMnQpoHtg", + "cell_type": "code", + "source": [ + "var discountedCL_NIC = Test.GetScope((idEOP with {AocType = eopReferenceAocStep.AocType, Novelty = eopReferenceAocStep.Novelty}, \"NIC\", \"BE\", (int?)null));", + "\ndiscountedCL_NIC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TgfGcomxyEu_Bi31dr0a8Q", + "cell_type": "code", + "source": [ + "var expectedPvBaseEOP_NIC = discountedCL_NIC.Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "COrZzNoVR0uPcoTvusJl9A", + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ], + "metadata": {} + }, + { + "id": "uHz3FD5pz0KtlPWvehPSTw", + "cell_type": "code", + "source": [ + "computedPvBaseEOP_NIC.Values.CheckEquality( expectedPvBaseEOP_NIC )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "NgccZKROIUGyHphm6Pt3mA", + "cell_type": "code", + "source": [ + "computedPvBaseEOP_NIC.Value == expectedPvBaseEOP_NIC[3]" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9jo2Z3ljfkyeYFEYk8YevQ", + "cell_type": "code", + "source": [ + "computedPvBaseEOP_NIC.Values.CheckEquality( expectedPvBaseEOP_NIC ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wQEKDnBmiEiCcxaQ5z8n_Q", + "cell_type": "code", + "source": [ + "computedPvBaseEOP_NIC.Value.Should().Be( expectedPvBaseEOP_NIC[3] );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TYv8HCkwJ0-eIPL5UgmkSg", + "cell_type": "markdown", + "source": [ + "## Check for zero PVB values" + ], + "metadata": {} + }, + { + "id": "ypVkZQiC50KtLKlrkxwfWA", + "cell_type": "markdown", + "source": [ + "### Amortization" + ], + "metadata": {} + }, + { + "id": "f6LQtXZHZE60NfgYXKiAmg", + "cell_type": "markdown", + "source": [ + "For AM AoCType, the PVB values are zero, i.e. Amortization is not part of the Present Value computation. In this subsection we check whether the corresponding values are zero accordingly. " + ], + "metadata": {} + }, + { + "id": "YmNDcj0tDEObggNuOxfFVg", + "cell_type": "code", + "source": [ + "var idAM = Test.GetIdentity(groupOfContract, \"AM\", \"C\");", + "\nidAM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Hbvbc_-ghkCPuBcY4CaNSw", + "cell_type": "code", + "source": [ + "var computedPvBaseAM_PR = Test.GetScope((idAM, \"PR\", \"BE\", (int?)null));", + "\ncomputedPvBaseAM_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vtA_SwM1FkWUvn7cz_gsEg", + "cell_type": "code", + "source": [ + "var computedPvBaseAM_PR = Test.GetScope((idAM, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPvBaseAM_PR" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Hm9t12cEPEq0qfPXqqQKDA", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Amortization Factors" + ], + "metadata": {} + }, + { + "id": "HIn4-XNBlUC_ryCdXqFJXw", + "cell_type": "markdown", + "source": [ + "The amortization factors (AMF) are calculated from the corresponding Nominal and Discounted Cashflows with Calculation Type being *Coverage Units* (CU). ", + "\nThe monthly AMF is", + "\n", + "\n$$", + "\n\\text{AMF}^{\\text{Monthly}}_t = 1 - \\frac{ \\text{Nominal}^{\\text{Coverage Units}}_t } { \\text{CDC}^{\\text{Coverage Units}}_t } ~,", + "\n$$", + "\n", + "\nwhile the AMF related to the current period is", + "\n", + "\n$$", + "\n\\text{AMF} = \\prod _{t = \\text{S}}^{\\text{S}+\\text{TS}} \\text{AMF}^{\\text{Monthly}}_t ~.", + "\n$$", + "\n", + "\nwhere the shift S and Time Step TS for the [current period](#year-and-period) are" + ], + "metadata": {} + }, + { + "id": "GMNrVzKXH0ymV23dJDvYKQ", + "cell_type": "code", + "source": [ + "var projectionPeriod = 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YPFhl76CQkyB4G8ObloZRg", + "cell_type": "code", + "source": [ + "var shift = Test.GetStorage().GetShift(projectionPeriod);", + "\nshift" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-kXqVC_kq0CICZBKBb1HlQ", + "cell_type": "code", + "source": [ + "var timeStep = Test.GetStorage().GetTimeStep(projectionPeriod);", + "\ntimeStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "t4HaEWnCNk6mQabiDiws1w", + "cell_type": "markdown", + "source": [ + "## Monthly Amortization" + ], + "metadata": {} + }, + { + "id": "xeALkGs7xUeu3Y4WpeNO1Q", + "cell_type": "markdown", + "source": [ + "The computed monthly and current period Amortization Factors derived from a non-zero [imported](#year-and-period) nominal cashflows and its corresponding discounted are shown in the following" + ], + "metadata": {} + }, + { + "id": "L1ZjEB2bYkqJCYEQcSaCLA", + "cell_type": "code", + "source": [ + "var idAM = Test.GetIdentity(groupOfContract, \"CL\", \"C\");", + "\nidAM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "P_fB5G8CbkOe7_gqmr8nQA", + "cell_type": "code", + "source": [ + "var nominalCashflowAmortizationFactorTest = Test.GetScope( (idAM, default(string), \"CU\", (int?)null) );", + "\nnominalCashflowAmortizationFactorTest" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nwNr460Q5kO_3WOTIbp0qQ", + "cell_type": "code", + "source": [ + "var discountedCashflowAmortizationFactorTest = Test.GetScope(idAM);", + "\ndiscountedCashflowAmortizationFactorTest" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "uCI4iAP0DUGsPQOWdrwDuA", + "cell_type": "code", + "source": [ + "var computedMonthlyAmortizationFactor = Test.GetScope(idAM with {AocType = \"AM\"});", + "\ncomputedMonthlyAmortizationFactor" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gHcGaR3jfEWKUAK4D2kCVw", + "cell_type": "markdown", + "source": [ + "In the following cell we independently evaluate the expected monthly amortization factor according to the [formula above](#amortization-factor) and we check whether expected vs computed match" + ], + "metadata": {} + }, + { + "id": "I8F4XooarU6ejB9dIO3ByA", + "cell_type": "code", + "source": [ + "var expectedMonthlyAmortizationFactor = nominalCashflowAmortizationFactorTest.Values.Zip(discountedCashflowAmortizationFactorTest.Values, ", + "\n (nominal, discountedCumulated) => 1 - nominal / discountedCumulated ).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QwB0UIilbkK-CRTF-jWgEA", + "cell_type": "code", + "source": [ + "expectedMonthlyAmortizationFactor.RepeatOnce()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_66rpQUzrU-3wQQMLfLqTw", + "cell_type": "code", + "source": [ + "computedMonthlyAmortizationFactor.MonthlyAmortizationFactors.CheckEquality( expectedMonthlyAmortizationFactor )" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ibllj4WfMkCzKaaYRuhfmA", + "cell_type": "code", + "source": [ + "computedMonthlyAmortizationFactor.MonthlyAmortizationFactors.CheckEquality( expectedMonthlyAmortizationFactor ).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Jk9YlP6QCkqRxZo-o68MsA", + "cell_type": "markdown", + "source": [ + "## Current Period" + ], + "metadata": {} + }, + { + "id": "DTl5o5jz_0erzyZWFTpUHQ", + "cell_type": "markdown", + "source": [ + "The computed current period amortization factor is" + ], + "metadata": {} + }, + { + "id": "PCy8Dakbh0mPaY2sEWzjGg", + "cell_type": "code", + "source": [ + "var computedCurrentPeriodAmortizationFactor = Test.GetScope(idAM with {AocType = \"AM\"});", + "\ncomputedCurrentPeriodAmortizationFactor" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FdbZR9Yuy0-UNKH3vCixGw", + "cell_type": "markdown", + "source": [ + "Conversely, the current period Amortization factor can be independently computed using the [formula above](#amortization-factor) as" + ], + "metadata": {} + }, + { + "id": "w8ypGjX1wUGEjtCySuAp3w", + "cell_type": "code", + "source": [ + "var expectedCurrentPeriodAmortizationFactor = expectedMonthlyAmortizationFactor.Skip(shift).Take(timeStep).Aggregate(1d, (x, y) => x * y);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YwRfJmVI3UmwsjBL1JE48Q", + "cell_type": "code", + "source": [ + "expectedCurrentPeriodAmortizationFactor" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "33_7tRKRmUu9inImy1G2VQ", + "cell_type": "code", + "source": [ + "computedCurrentPeriodAmortizationFactor.Value == expectedCurrentPeriodAmortizationFactor" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rM6pE_9pL0SCB56yFBmlUA", + "cell_type": "code", + "source": [ + "computedCurrentPeriodAmortizationFactor.Value.Should().Be( expectedCurrentPeriodAmortizationFactor );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zJ4a8KsYUEWmMuBSKeJn0g", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Results persisted" + ], + "metadata": {} + }, + { + "id": "c4kFsHdrzEut20I1sKx5wQ", + "cell_type": "markdown", + "source": [ + "The last step during the Cashflow import is to save, namely *persist* the Present Values computed with *locked* (L) and *current* (C) economic basis, and calculation type being *Best Estimate* (BE). ", + "\n", + "\nThese data is the starting point of the [Contractual Service Margin calculation](\"SpecificationsCSM\")." + ], + "metadata": {} + }, + { + "id": "zco2828uiUeNWEkjLJSbmA", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb new file mode 100644 index 00000000..8fdfb7ae --- /dev/null +++ b/Test/SpecificationsSetup.ipynb @@ -0,0 +1,137 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "fE38qOjHW0a08mH8kJrwSg", + "cell_type": "code", + "source": [ + "#!import \"../Import/ImportScopeCalculation\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9xNRIpaJukO9dK_x-P6MAg", + "cell_type": "code", + "source": [ + "public interface Universe : IMutableScopeWithStorage{}", + "\n", + "\npublic async Task StartCalculatorAsync(string reportingNode, int year, int month, string economicBasis, Periodicity period, string format) ", + "\n{", + "\n ", + "\n var importArgs = new ImportArgs(reportingNode, year, month, period, null, format);", + "\n Workspace.Reset();", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n", + "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == importArgs.ReportingNode &&", + "\n p.Year == importArgs.Year &&", + "\n p.Month == importArgs.Month &&", + "\n p.Scenario == importArgs.Scenario", + "\n ).ToArrayAsync()).Single().Id;", + "\n await DataSource.Partition.SetAsync(partition);", + "\n", + "\n //Set Workspace as when the parsing is completed.", + "\n if(importArgs.ImportFormat == ImportFormats.Actual)", + "\n { ", + "\n await Workspace.UpdateAsync(await DataSource.Query()", + "\n .Where(x => x.Partition == partition && ", + "\n new string[]{EstimateTypes.A, EstimateTypes.AA, EstimateTypes.OA}.Contains(x.EstimateType) && ", + "\n new string[]{AocTypes.CF, AocTypes.WO}.Contains(x.AocType))", + "\n .ToArrayAsync());", + "\n }", + "\n else if(importArgs.ImportFormat == ImportFormats.Opening)", + "\n { ", + "\n await Workspace.UpdateAsync(await DataSource.Query()", + "\n .Where(x => x.Partition == partition && ", + "\n new string[]{ EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.DA}.Contains(x.EstimateType) && ", + "\n x.AocType == AocTypes.BOP && x.Novelty == Novelties.I)", + "\n .ToArrayAsync());", + "\n }", + "\n else", + "\n {", + "\n await Workspace.UpdateAsync(await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync());", + "\n }", + "\n var storage = new ImportStorage(importArgs, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n return Scopes.ForStorage(storage).WithContext(economicBasis).ToScope();", + "\n}", + "\n", + "\npublic static ImportIdentity GetIdentity (this Universe universe, string dataNode, string aocType, string novelty) ", + "\n => universe.GetScope(dataNode).Identities.Single( x => x.AocType == aocType && x.Novelty == novelty );", + "\n", + "\nstatic T GetValidElement(this IList array, int index) => GetElementOrDefault(array, index);", + "\n", + "\nstatic T GetValidElement(this IEnumerable array, int index) => GetElementOrDefault(array.ToArray(), index);", + "\n", + "\nstatic void ForEach(this IEnumerable self, Action action) => self.ToList().ForEach(action);", + "\n", + "\npublic static IfrsVariable FromPvToIfrsVariable(this PvBase scope)", + "\n => new IfrsVariable{ EconomicBasis = scope.EconomicBasis, ", + "\n EstimateType = scope.Identity.CalculationType, ", + "\n DataNode = scope.Identity.Id.DataNode, ", + "\n AocType = scope.Identity.Id.AocType, ", + "\n Novelty = scope.Identity.Id.Novelty, ", + "\n AccidentYear = scope.Identity.AccidentYear,", + "\n AmountType = scope.Identity.AmountType,", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };", + "\n", + "\npublic static IfrsVariable FromCsmToIfrsVariable(this Csm scope)", + "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", + "\n DataNode = scope.Identity.DataNode, ", + "\n AocType = scope.Identity.AocType, ", + "\n Novelty = scope.Identity.Novelty, ", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };", + "\n", + "\npublic static IfrsVariable FromLcToIfrsVariable(this Lc scope)", + "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", + "\n DataNode = scope.Identity.DataNode, ", + "\n AocType = scope.Identity.AocType, ", + "\n Novelty = scope.Identity.Novelty, ", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };", + "\n", + "\npublic static IfrsVariable FromLoReCoToIfrsVariable(this LoReCo scope)", + "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", + "\n DataNode = scope.Identity.DataNode, ", + "\n AocType = scope.Identity.AocType, ", + "\n Novelty = scope.Identity.Novelty, ", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nbL-Fjewnk-tw5Vk1IJ2rg", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/SpecificationsTechnicalMargin.ipynb b/Test/SpecificationsTechnicalMargin.ipynb new file mode 100644 index 00000000..7368b76c --- /dev/null +++ b/Test/SpecificationsTechnicalMargin.ipynb @@ -0,0 +1,2576 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "g8tjy1GbI0uoEDhZW9OubA", + "cell_type": "markdown", + "source": [ + "

Technical Margin Specifications

" + ], + "metadata": {} + }, + { + "id": "x6HTq-dyx0CT0axGCN5uCw", + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the Technical Margin (TM) and its allocation to the Contractual Service Margin (CSM), Loss Component (LC), or Loss Recovery Component (LoReCo). The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ], + "metadata": {} + }, + { + "id": "LhxZv_5tLEW3BCU74MttbA", + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ], + "metadata": {} + }, + { + "id": "yPpeVsREbUy--NQi9jbNpw", + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "U3AjnYiM5kuSmp75cguUSA", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "ECkaAKQIMEu5hqUdpeBq8Q", + "cell_type": "markdown", + "source": [ + "# Import Data" + ], + "metadata": {} + }, + { + "id": "SEMqfkxNU0e_-5mrR4lZTw", + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period" + ], + "metadata": {} + }, + { + "id": "IvTb1XGZ1kuJ-VvXkuWNJw", + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" + ], + "metadata": {} + }, + { + "id": "KdFdFW3OhUy3KzhPTiarkg", + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UnwIzmJO6EeRXQWBbmoK1g", + "cell_type": "markdown", + "source": [ + "Import the Dimensions, Parameters, Nominal Cashflows, and Actuals from the corresponding csv files in Initialization/Systemorph/" + ], + "metadata": {} + }, + { + "id": "xPBxX-MYjEirprXfdCjqHw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8lAk_SdyNEmrDVylgM3ueg", + "cell_type": "markdown", + "source": [ + "Initialization of the Test Suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ], + "metadata": {} + }, + { + "id": "LZ2n8pzel0OnpsJ86gHLDw", + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YRjwR8fuJkK9bvH84fq8dA", + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Data Nodes" + ], + "metadata": {} + }, + { + "id": "YEMgdgKuwEe_bIe-xkd09g", + "cell_type": "markdown", + "source": [ + "The imported active Data Nodes from Initialization/Systemorph/DataNodes.csv are " + ], + "metadata": {} + }, + { + "id": "uS9vfK-rBUiZsfCYiJzIpA", + "cell_type": "code", + "source": [ + "Test.GetStorage().DataNodeDataBySystemName" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LvO_qjZPmEOI6YxzgwM4vg", + "cell_type": "markdown", + "source": [ + "whereas the Data Nodes of your imported Cashflows are" + ], + "metadata": {} + }, + { + "id": "jpqlfwEBkU20upkPfktIQA", + "cell_type": "code", + "source": [ + "Test.GetStorage().DataNodesByImportScope[ImportScope.Primary]" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Km-AMREk2ECK0lggstN9yA", + "cell_type": "markdown", + "source": [ + "Please select here below the target Data Node for executing the tests below:" + ], + "metadata": {} + }, + { + "id": "KeB4MbA30U-GTokbWzsbNw", + "cell_type": "code", + "source": [ + "var dataNode = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "yjMtNI_UpEOFhOhlYPIjdg", + "cell_type": "markdown", + "source": [ + "## View list of Identities" + ], + "metadata": {} + }, + { + "id": "2suX-6pDYUu9ZRoKpbzwtg", + "cell_type": "markdown", + "source": [ + "Based on the Cashflows imported, the list of all possible identities, i.e. combinations of valid Data Nodes, Aoc steps, and Novelties, is contructed and reported here below:" + ], + "metadata": {} + }, + { + "id": "uXw2nYCpZ0i16yt57O-hZw", + "cell_type": "code", + "source": [ + "var allIdentities = Test.GetScopes(Test.GetStorage().DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "PpgNb9iz3kaMC2BeZoDKXQ", + "cell_type": "code", + "source": [ + "allIdentities" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "FX3f8E0cn0iRfjDMfGMWMw", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Present Value" + ], + "metadata": {} + }, + { + "id": "bjt2kV7OaU-pgEwV4_f7cw", + "cell_type": "markdown", + "source": [ + "Projected Present Values (PPVs) are calculated for each Amount Type (AT) either with the *locked-in* (L) and with the *current* (C) Yield Curves. While the former is the latest available as per end of the DataNode's inception year, the latter is the latest available as per the current period. ", + "\nPPVs for both Economic Basis L and C have been defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", + "\n", + "\nAccording to the BBA methodology, the CSM calculation uses the PV with locked-in Yield Curve simply defined as", + "\n", + "\n$$", + "\n\\text{PV Locked}(\\text{AoC}, \\text{AT}) = \\text{PPV}(\\text{AoC}, \\text{AT}) \\big|_{\\substack{ \\text{Calculation Type = BE} \\\\ \\text{Economic Base = L} } }", + "\n$$" + ], + "metadata": {} + }, + { + "id": "z3MoqQ9eQUS09tb1mXkFyA", + "cell_type": "code", + "source": [ + "var pvsLocked = allIdentities.SelectMany(id => Test.GetScope(id).PresentValues", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromPvToIfrsVariable())).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "t7tRCeCG10KKMVZzfO_pPg", + "cell_type": "markdown", + "source": [ + "Below a view of the computed locked-in PV " + ], + "metadata": {} + }, + { + "id": "OIen-nXHD0SiauOT9N-_Bg", + "cell_type": "code", + "source": [ + "Report.ForObjects(pvsLocked)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n .GroupColumnsBy(x => x.AmountType)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "muPGuU2J_0C0ajt9hkta5A", + "cell_type": "markdown", + "source": [ + "Aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type):", + "\n", + "\n$$", + "\n\\text{PV Locked Value}(\\text{AoC}) = \\sum_{\\text{AT}} \\text{PV Locked}(\\text{AoC}, \\text{AT})", + "\n$$" + ], + "metadata": {} + }, + { + "id": "kvGGn3Q4rUex05dzYM9qdg", + "cell_type": "markdown", + "source": [ + "Here below an example" + ], + "metadata": {} + }, + { + "id": "9_XxzJoITE-6372AHPhE3g", + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "R9nUtmCCQECPK-w_Mp_yVw", + "cell_type": "code", + "source": [ + "id_BoP_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "du2mo7J8002QJbtRt584Mw", + "cell_type": "code", + "source": [ + "Test.GetScope( id_BoP_I ).Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_OxvDZWrPka_CFvaMAisxg", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Risk Adjustment" + ], + "metadata": {} + }, + { + "id": "376Njyw59EGhWrieNRi8jQ", + "cell_type": "markdown", + "source": [ + "The CSM calculation also uses locked-in Risk Adjustment (RA Locked) which is retrieved from the corresponding Present Value with [Calculation Type](../DataModel/DataStructure#calculation-type) being RA defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", + "\n", + "\nRisk Adjustment values can be written as", + "\n", + "\n$$", + "\n\\text{RA Locked Value}(\\text{AoC}) = \\text{PV}(\\text{AoC})|_{\\substack{ \\text{Calculation Type = RA} \\\\ \\text{Economic Base = L} }}", + "\n$$", + "\n", + "\nwhere the imported Cashflows for the RA Calculation Type are already aggregated over all [Amount Types](../DataModel/DataStructure#amount-type)." + ], + "metadata": {} + }, + { + "id": "3siM-DZsEEiBkk5Y3FRKFg", + "cell_type": "markdown", + "source": [ + "Here below an example" + ], + "metadata": {} + }, + { + "id": "Xl2yuS6a60C9Quny8zQ-5A", + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LSaHrUxyq0i4azSGh961Jg", + "cell_type": "code", + "source": [ + "id_BoP_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RuOYh7rjz0G8Mc61JSv5Yg", + "cell_type": "code", + "source": [ + "Test.GetScope( id_BoP_I ).Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qAzxMRN-SkuuSQuz6UYYYQ", + "cell_type": "markdown", + "source": [ + "The RA Locked per Data Node imported are" + ], + "metadata": {} + }, + { + "id": "I6YzC1vPqUKXP9iGgM9VCw", + "cell_type": "code", + "source": [ + "var rasLocked = allIdentities.SelectMany(id => Test.GetScope(id).PresentValues", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromPvToIfrsVariable())).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iYZeYBNeU0C41iCvscI1CA", + "cell_type": "code", + "source": [ + "Report.ForObjects(rasLocked)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fuyUZe63NEiB09VJA2Na4A", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Technical Margin" + ], + "metadata": {} + }, + { + "id": "2VStZINSF0KMaeav25AQSQ", + "cell_type": "markdown", + "source": [ + "For the computation of the CSM or LC components for each AoC step, it is convenient to introduce the notion of technical margin (TM).", + "\n", + "\nFirstly, it is useful to define the so-called Aggregated Technical Margin (ATM)", + "\n", + "\n$$", + "\n\\text{ATM} (\\text{AoC}) = \\sum_{s\\in\\text{previous AoC steps}} \\text{TM}(s) ~,", + "\n$$", + "\n", + "\nand the Interest Accretion Factor (IAF) ", + "\n", + "\n$$", + "\n\\text{IAF} = \\prod_{i=1}^{\\text{TS}} (1 + \\text{YC}_i) - 1 ~.", + "\n$$", + "\n", + "\nThe TM is defined as", + "\n", + "\n$$", + "\n\\text{TM}(\\text{AoC}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n\\text{TM}(\\rm{EOP}) \\text{ of the previous period} ~ & \\text{if }s = \\text{BOP and Novelty is In-Force}. \\\\", + "\n0 ~ & \\text{if }s = \\text{CF}. \\\\", + "\n\\text{IAF} \\cdot ~ \\text{ATM}(\\text{AoC}) ~ & \\text{if }s = \\text{IA}. \\\\", + "\n\\rm{Premiums} + \\text{Attributable Expense and Commissions} + \\text{Investment Claims} ~ & \\text{if }s = \\text{EA}. \\\\", + "\n-\\text{AMF} \\cdot ~ \\text{ATM}(\\text{AoC}) ~ & \\text{if }s = \\text{AM}. \\\\", + "\n\\text{PV Locked Value}(\\text{AoC}) ", + "\n\\bigg|_{\\substack{\\text{Non Attributable} \\\\ ", + "\n \\text{Amount Types} \\\\ ", + "\n \\text{excluded}}} ", + "\n+ \\text{RA Locked Value}(\\text{AoC}) ~ & \\text{otherwise} ", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere AMF is the Amortization Factor that is defined [here](../Import/ImportScopeCalculation#amortization-factor) and tested [here](SpecificationsImportCashflows#amortization-factor), with YC being the [Yield Curve](#yield-curves) and TS is the Time-Step, ", + "\nand the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", + "\n", + "\n$$", + "\n\\begin{array}{lcl}", + "\n\\rm{Premiums} &=& \\text{Premium Allocation Factor} \\cdot \\sum_{\\text{Amount Type}\\in\\{\\text{PR and its children}\\}}", + "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - ", + "\n \\big(\\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}} + \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~, \\\\", + "\n\\text{Attributable Expense and Commissions} &=& \\sum_{\\text{Amount Type}\\in\\{\\rm{ACA}, \\rm{AEA}\\}}", + "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - \\text{Actual}_{\\text{Novelty=C}} ~, \\\\", + "\n\\text{Investment Claims } &=& \\sum_{\\text{Amount Type}\\in\\{\\text{ICO and its children}\\}}", + "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - ", + "\n \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}} + \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~.", + "\n\\end{array}", + "\n$$", + "\n", + "\nThe AoC Type **CF** is implicit for all formulas, PV is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **OA** and **AA** (see details [here](../Import/ImportScopeCalculation#actual-base))." + ], + "metadata": {} + }, + { + "id": "dHH8INfYdk6Y3NzMtPgJbA", + "cell_type": "markdown", + "source": [ + "## Beginning of Period" + ], + "metadata": {} + }, + { + "id": "X49_KQk8ek2l9u2XuCXQPw", + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-MSegalanEGCyd9Lmbhk2g", + "cell_type": "code", + "source": [ + "id_BoP_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GauKnHaTZk2qPtNwgM0kgQ", + "cell_type": "code", + "source": [ + "var computedTM_BoP_I = Test.GetScope(id_BoP_I);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sDV3uzZnZE-xy3w3XNF0xA", + "cell_type": "code", + "source": [ + "computedTM_BoP_I.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3rv0eEV93Euw7OXSDpqR0w", + "cell_type": "markdown", + "source": [ + "The TM for BOP is equal to the TM for EOP of the previous period, that is, the sum of Csm, Loss Component and LoReCo as of at the end of last period (see the corresponding [formula](#technical-margins)). ", + "\n", + "\nThe corresponding **IFRS Variables** can be loaded directly from the *Storage*" + ], + "metadata": {} + }, + { + "id": "AOE-Piw6OUGsQ3Bl1AuGbw", + "cell_type": "code", + "source": [ + "var valueCsm = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.C, null);", + "\nvalueCsm" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YdYcIzhRG0CLSLEWQblsEA", + "cell_type": "code", + "source": [ + "var valueLc = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.L, null);", + "\nvalueLc" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0Onxmh3pPU6pxWFOSJt6DA", + "cell_type": "code", + "source": [ + "var valueLr = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.LR, null);", + "\nvalueLr" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0x0FA_cjZEWhsLSbrQq40g", + "cell_type": "code", + "source": [ + "var expectedTM_BoP_I = -valueCsm + valueLc + valueLr;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "SJSNzLoPJUiPGHBvEduNeQ", + "cell_type": "code", + "source": [ + "expectedTM_BoP_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8VnVUHSzbE-KpM6n4ONuQg", + "cell_type": "code", + "source": [ + "computedTM_BoP_I.Value.Should().BeApproximately( expectedTM_BoP_I, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xIQdOuzLvESRKcPIgcUsPQ", + "cell_type": "markdown", + "source": [ + "", + "\n## Model Corrections" + ], + "metadata": {} + }, + { + "id": "fNltK5PaA0Kw7wchmSNY_w", + "cell_type": "code", + "source": [ + "var id_MC_I = Test.GetIdentity(dataNode, \"MC\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RRBZvtJHhUikmA_j6oodwg", + "cell_type": "code", + "source": [ + "id_MC_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "AOGe1hxqB0auL-m48n4LEQ", + "cell_type": "code", + "source": [ + "var computedTM_MC_I = Test.GetScope(id_MC_I);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "glwYLenix0mbVAzz2QauDg", + "cell_type": "code", + "source": [ + "computedTM_MC_I.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "NmTxRKBaJUSBln-u_LqjRA", + "cell_type": "markdown", + "source": [ + "The TM for MC is given by the default [formula](#technical-margins), i.e. it is equal to the sum of PV and RA Locked, where the former does not encompass the *NonAttributable* Amount Types" + ], + "metadata": {} + }, + { + "id": "cZmPuuHgGEiu5xbMXe88xQ", + "cell_type": "code", + "source": [ + "var expectedTM_MC_I = Test.GetScope(id_MC_I).Value + Test.GetScope( id_MC_I ).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4L9o1tHqWki3eAAa7xkajA", + "cell_type": "code", + "source": [ + "expectedTM_MC_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "98q4ZQeegkuz71N9nfEHJg", + "cell_type": "code", + "source": [ + "computedTM_MC_I.Value.Should().BeApproximately( expectedTM_MC_I, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "B5PYDN0vMkqQxtE9Hyw25A", + "cell_type": "markdown", + "source": [ + "## Cash Flow" + ], + "metadata": {} + }, + { + "id": "499xH8CoX0GNNMn3D9roXg", + "cell_type": "code", + "source": [ + "var id_CF_I = Test.GetIdentity(dataNode, \"CF\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "D0CbUxy5UUKrMhBCxYOZgg", + "cell_type": "code", + "source": [ + "id_CF_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5Wp3bWCQyUGxZdn4_VfQ6Q", + "cell_type": "code", + "source": [ + "var computedTM_CF_I = Test.GetScope(id_CF_I);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nd6a0CNEH0S7s7gB7otViA", + "cell_type": "code", + "source": [ + "computedTM_CF_I.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3n9f5rJGHUulpGouIZZY-w", + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, the tecnical margin is 0 for the Cash Flow AoC step " + ], + "metadata": {} + }, + { + "id": "rKHBn4AQB0-Xf3R7XoqAaQ", + "cell_type": "code", + "source": [ + "computedTM_CF_I.Value.Should().BeApproximately( 0, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "AVeLuFLOC0C5EG_ODOOKgg", + "cell_type": "markdown", + "source": [ + "", + "\n## Interest Accretion" + ], + "metadata": {} + }, + { + "id": "fb9GTLqZ10S_IGiMHnsjtA", + "cell_type": "code", + "source": [ + "var id_IA_I = Test.GetIdentity(dataNode, \"IA\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qTqnPKarN0W0KXR3GY0C2Q", + "cell_type": "code", + "source": [ + "id_IA_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-A6XSrwceEml_t5TZg447g", + "cell_type": "code", + "source": [ + "var computedTM_IA_I = Test.GetScope(id_IA_I);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "grxq6Y2xxkeWfYaEXojn4w", + "cell_type": "code", + "source": [ + "computedTM_IA_I.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "S4WYAmNv9kOPoeM8Utgblg", + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, for the AoC step IA, the TM is equal to sum of the TMs of its previous AoC step multiplied by the IAF. " + ], + "metadata": {} + }, + { + "id": "4WhIgYaOr0aGNomU8C5-uA", + "cell_type": "markdown", + "source": [ + "The IAF associated to the current period (i.e. shift and time step) can be calculated from the shift, the time Step, and the Interest Rates" + ], + "metadata": {} + }, + { + "id": "4xfyE1DlUEqKdYMjYcygRw", + "cell_type": "code", + "source": [ + "var projectionPeriod = 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "RjAsyz82BECP1W48K-a7rA", + "cell_type": "code", + "source": [ + "var shift = Test.GetStorage().GetShift(projectionPeriod);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wsHHDSkq-0-huGE1nvj3wQ", + "cell_type": "code", + "source": [ + "var timeStep = Test.GetStorage().GetTimeStep(projectionPeriod);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_gEJdoVPuUyxvU1oEF2Clw", + "cell_type": "code", + "source": [ + "(shift, timeStep)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "lNmbEvWOU0KMR_ZMy4DQpQ", + "cell_type": "code", + "source": [ + "var monthlyRates = Test.GetScope(id_IA_I);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "p4EWaRtorkCe5b4KbM6kFA", + "cell_type": "code", + "source": [ + "monthlyRates" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WhnDXZb69ES2SSJKZBdqPA", + "cell_type": "code", + "source": [ + "var IAF = Enumerable.Range(shift,timeStep).Select(i => monthlyRates.Interest.GetValidElement(i/12)).Aggregate(1.0d, (x, y) => x * y ) - 1.0d;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "A4PMm2aaGEejwDCTGWNc2w", + "cell_type": "code", + "source": [ + "IAF" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bJTIxBr6wUSGCYZKPko5RA", + "cell_type": "markdown", + "source": [ + "Since the previous AoC steps are" + ], + "metadata": {} + }, + { + "id": "fJq-TMlCuE-9Xsfek5KWug", + "cell_type": "code", + "source": [ + "var previousAocStep = Test.GetScope((id_IA_I, InputSource.Cashflow)).Values;", + "\npreviousAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "__ftTIzmrUS_DQUcSg34vg", + "cell_type": "markdown", + "source": [ + "the expected TM for the Amortization step reads" + ], + "metadata": {} + }, + { + "id": "FMyRgLCS30mHjSbBaZ6LgA", + "cell_type": "code", + "source": [ + "var expectedTM_IA_I = IAF * previousAocStep.Sum(aoc => Test.GetScope(id_IA_I with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UBacH9pFIkG_rxoWOux8Rg", + "cell_type": "code", + "source": [ + "expectedTM_IA_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1-tr5DyvAEyE3oMQwJnJyA", + "cell_type": "code", + "source": [ + "computedTM_IA_I.Value.Should().BeApproximately( expectedTM_IA_I, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TAmMb4uGQ0CGG-bwB1k0bg", + "cell_type": "markdown", + "source": [ + "## Combined Liabilities" + ], + "metadata": {} + }, + { + "id": "RH193aFtkEq65MfZGDWFgQ", + "cell_type": "code", + "source": [ + "var id_CL_C = Test.GetIdentity(dataNode, \"CL\", \"C\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8Ug4OQB9lEWCTqQm6mWYdA", + "cell_type": "code", + "source": [ + "id_CL_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YDa8Beon7Umu1aUF0ONGJQ", + "cell_type": "code", + "source": [ + "var computedTM_CL_C = Test.GetScope(id_CL_C);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "eyyv-oaJE0KWTDaGRKqDpw", + "cell_type": "code", + "source": [ + "computedTM_CL_C.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VWU-qT5aV0GrakHpIsqPgQ", + "cell_type": "markdown", + "source": [ + "According to the default TM [formula](#technical-margins), for the CL step the TM is equal to the sum of PV and RA Locked, where the former does not encompass the *NonAttributable* Amount Types" + ], + "metadata": {} + }, + { + "id": "6EyiiEVRzkuI6YRXJQ1MTQ", + "cell_type": "code", + "source": [ + "var expectedTM_CL_C = Test.GetScope(id_CL_C).Value + Test.GetScope( id_CL_C ).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0dDkPEAfeE-XhvLA7DH1Wg", + "cell_type": "code", + "source": [ + "expectedTM_CL_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MKmlpGv4-E64crKcv0Zlig", + "cell_type": "code", + "source": [ + "computedTM_CL_C.Value.Should().BeApproximately( expectedTM_CL_C, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WDBCcZKCLUeobaNw-juV1g", + "cell_type": "markdown", + "source": [ + "## Experience Adjustment" + ], + "metadata": {} + }, + { + "id": "2dBJGbhnzk6wE_QuqLi-RQ", + "cell_type": "code", + "source": [ + "var id_EA_C = Test.GetIdentity(dataNode, \"EA\", \"C\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hyawxe-JhUqkLHKOWPTdQw", + "cell_type": "code", + "source": [ + "id_EA_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "goQMZoAJfkSEn4o50YRUew", + "cell_type": "code", + "source": [ + "var computedTM_EA_C = Test.GetScope(id_EA_C);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8dX7PfDfwEWf7hkrubnBxw", + "cell_type": "code", + "source": [ + "computedTM_EA_C.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-WJt_6_ZIkGH0yWrnqftrQ", + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, for the AoC step EA, the TM is equal to sum of the Premiums, Attributable Expense and Commissions, and Investment Claims. Here below we calculate these terms individually." + ], + "metadata": {} + }, + { + "id": "DB62V_OoakmF-fa0ir-6vg", + "cell_type": "markdown", + "source": [ + "The Premiums, Attributable Expense and Commissions and Investment Claims Present Values and Actuals are calculated using the CF AoC step. Therefore, as first step we define the relevant AoC step and Novelties:" + ], + "metadata": {} + }, + { + "id": "tGqV5u76l0-NIz-zJDKesQ", + "cell_type": "code", + "source": [ + "var referenceAoCType = Test.GetScope(id_EA_C).Value.AocType;", + "\nvar referenceAoC = Test.GetStorage().GetNovelties().Select(n => new AocStep(referenceAoCType, n));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tFXCsZ7yPkaUO_sP6Rf4dw", + "cell_type": "code", + "source": [ + "referenceAoC" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Zn9OSvz3M02EYNKavRdHWA", + "cell_type": "markdown", + "source": [ + "**Premiums**" + ], + "metadata": {} + }, + { + "id": "hD28G9xlTki7-KNMU73QQQ", + "cell_type": "markdown", + "source": [ + "The list of Premiums Amount Type defined in the imported dimensions and the Premium Allocation Factor can be retrieved" + ], + "metadata": {} + }, + { + "id": "WPVewiJ-ZUKbnl0snAuRBA", + "cell_type": "code", + "source": [ + "Test.GetStorage().GetPremiums()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "N6sWBi5BvkKF2O4N78nT_Q", + "cell_type": "code", + "source": [ + "var premiumAllocationFactor = Test.GetStorage().GetPremiumAllocationFactor(id_EA_C);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Fmxi3kQshEaXnPNNsbhPNg", + "cell_type": "code", + "source": [ + "premiumAllocationFactor" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GY7vCaRdK0GOmI8q5PX9_Q", + "cell_type": "markdown", + "source": [ + "Lastly, the Premiums term is" + ], + "metadata": {} + }, + { + "id": "5-HIYLo-bk2YFsABuEJCsQ", + "cell_type": "code", + "source": [ + "var premiums = premiumAllocationFactor * Test.GetStorage().GetPremiums()", + "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.A, (int?)null)).Value)", + "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.AA, (int?)null)).Value)", + "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.OA, (int?)null)).Value)", + "\n );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fg0ynhRLfEiTL68jnBFYPg", + "cell_type": "code", + "source": [ + "premiums" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GpYhgIs7bkijYtGnn_rmug", + "cell_type": "markdown", + "source": [ + "**Attributable Expense and Commissions**" + ], + "metadata": {} + }, + { + "id": "HLALKVc8NE233oTSH12a-Q", + "cell_type": "markdown", + "source": [ + "Analogously, the Attributable Expense and Commissions term can be computed" + ], + "metadata": {} + }, + { + "id": "tPhUn5VaikiP2WaFNmIoiA", + "cell_type": "code", + "source": [ + "var attributableExpenseAndCommissions = new string[] {AmountTypes.ACA, AmountTypes.AEA}", + "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, EstimateTypes.A, (int?)null)).Value));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CBelGvY28Uef9-9DjuaJSA", + "cell_type": "code", + "source": [ + "attributableExpenseAndCommissions" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "endWZOKckEWp2c6BLELK1w", + "cell_type": "markdown", + "source": [ + "**Investment Claims**" + ], + "metadata": {} + }, + { + "id": "AHIdM5P7nUyMySdWDQN-kA", + "cell_type": "markdown", + "source": [ + "Finally the Investment Claims term reads" + ], + "metadata": {} + }, + { + "id": "bETNZXjO2EuzRVFBP4Nykw", + "cell_type": "code", + "source": [ + "var investmentClaims = Test.GetStorage().GetInvestmentClaims()", + "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.A, (int?)null)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.AA, (int?)null)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.OA, (int?)null)).Value)", + "\n );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hKxm4Ea8-kCpGkmuQ8-P1g", + "cell_type": "code", + "source": [ + "investmentClaims" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tHqLLnVgKE6pcPnvAv06Tg", + "cell_type": "markdown", + "source": [ + "**Expected TM**" + ], + "metadata": {} + }, + { + "id": "ffxLkcddWUifhMB2Ybvzzw", + "cell_type": "code", + "source": [ + "var expectedTM_EA_C = premiums + attributableExpenseAndCommissions + investmentClaims;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "SUkya34JlUm2dEmvnV6bTQ", + "cell_type": "code", + "source": [ + "expectedTM_EA_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KL-ACiIWbkaCFXsaDZoW-g", + "cell_type": "code", + "source": [ + "computedTM_EA_C.Value.Should().BeApproximately( expectedTM_EA_C, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "aly806PPsk6nb1bq-n7-Sg", + "cell_type": "markdown", + "source": [ + "## Amortization" + ], + "metadata": {} + }, + { + "id": "bsMWbnZzwkiwXgJ8qAvFvw", + "cell_type": "code", + "source": [ + "var id_AM_C = Test.GetIdentity(dataNode, \"AM\", \"C\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "f4APi5_3CUmHUbP4cXLdcg", + "cell_type": "code", + "source": [ + "id_AM_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Rh7epJw7NUaRJ1RMc2rMQg", + "cell_type": "code", + "source": [ + "var computedTM_AM_C = Test.GetScope(id_AM_C);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8zkFkhgH00CXbsv5T8h-Hg", + "cell_type": "code", + "source": [ + "computedTM_AM_C.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "exXE3mAyIEi-kS4auuzrKQ", + "cell_type": "code", + "source": [ + "computedTM_AM_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "EpoM-9UMx0qwL68EXUoiiA", + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, for the AoC step AM, the TM is equal to sum of the TMs of its previous AoC step multiplied by the amortization factor with opposite sign. ", + "\n", + "\nThe AoC step previous to Amortization are" + ], + "metadata": {} + }, + { + "id": "RWUkvmQU9kqvjgKafKtMGg", + "cell_type": "code", + "source": [ + "var previousAocStep = Test.GetScope((id_AM_C, InputSource.Cashflow)).Values;", + "\npreviousAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WvdwUX-cX0SvELfpTOrxHA", + "cell_type": "markdown", + "source": [ + "while the Amortization Factor can be retrieved in the following" + ], + "metadata": {} + }, + { + "id": "HTgPDX8Zw0agihg2o3LoWQ", + "cell_type": "code", + "source": [ + "Test.GetScope(id_AM_C)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "r74wo-n4PEiaFDs1bW_41w", + "cell_type": "markdown", + "source": [ + "Therefore, the expected TM for the Amortization step reads" + ], + "metadata": {} + }, + { + "id": "SznuOL-o1Uy5mmuI-jmWPw", + "cell_type": "code", + "source": [ + "var expectedTM_AM_C = -Test.GetScope(id_AM_C).Value * ", + "\n previousAocStep.Sum(aoc => Test.GetScope(id_AM_C with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rEbKtIir70eeIiyYnSAFiA", + "cell_type": "code", + "source": [ + "expectedTM_AM_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5Boj82BZcUanZERZtQH1mA", + "cell_type": "code", + "source": [ + "computedTM_AM_C.Value.Should().BeApproximately( expectedTM_AM_C, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IoyFPh2DekK36wAQkduuFw", + "cell_type": "markdown", + "source": [ + "## End of Period" + ], + "metadata": {} + }, + { + "id": "e7GBWeapNUCJFEwl3Hdlfw", + "cell_type": "code", + "source": [ + "var id_EoP_C = Test.GetIdentity(dataNode, \"EOP\", \"C\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bFFAsDW4HU21gY0oQl4w-g", + "cell_type": "code", + "source": [ + "id_EoP_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-NF7JtObB0el7f59d8rHzw", + "cell_type": "code", + "source": [ + "var computedTM_EoP_C = Test.GetScope(id_EoP_C);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "J6OQYmtTy0O6Pa4dqCaYEQ", + "cell_type": "code", + "source": [ + "computedTM_EoP_C.Value" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ar4enZGkDkahHzmCKHvxBA", + "cell_type": "code", + "source": [ + "var expectedTM_EoP_C = Test.GetScope( id_EoP_C ).Value + Test.GetScope( id_EoP_C ).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Q-Rv4WF-uEOJenziP5Ko6w", + "cell_type": "code", + "source": [ + "expectedTM_EoP_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "GE0JdvladkOqE6BxVNRMcA", + "cell_type": "code", + "source": [ + "computedTM_EoP_C.Value.Should().BeApproximately( expectedTM_EoP_C, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XDuHL9hx2E6DU5ayGYHutQ", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Switch Logic " + ], + "metadata": {} + }, + { + "id": "NHk1HPZ3y0K-uGfMOBF1gQ", + "cell_type": "markdown", + "source": [ + "The CSM and LC figures are allocated for each AoC step based on the sign of the ATM. Specifically, for positive (negative) ATM, the TM of the current step is allocated to the LC (CSM), unless the TM flips the sign of the ATM. This special circumstance is named **switch**. It can happen at any AoC step with the only exception of Amortization where there is no switch from the previous step.", + "\nWhen a switch occurs the total contribution to the CSM (LC) prior the switching step is brought to 0 and the remaing amount is allocated to LC (CSM).", + "\n", + "\nIn the following the AoC chain is investigated." + ], + "metadata": {} + }, + { + "id": "qkwHpG9GrUmO52LhVW0gMw", + "cell_type": "markdown", + "source": [ + "## Beginning of Period", + "\n", + "\nFor the BOP, the last period is considered, which dictates that the corresponding EOP figures considered have necessarily Novelty of type *In-Force*.", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{BOP}) &=& \\text{CSM}(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force} \\\\", + "\n\\text{LC}(\\text{BOP}) &=& \\text{LC}(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", + "\n\\end{array}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "x2DkfQwGp0q67zTOEqWSDg", + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "U1ZDbeNAYUSlPIqSHFql-A", + "cell_type": "code", + "source": [ + "id_BoP_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OeYWN1P_DEOPTJgMbEYdwg", + "cell_type": "code", + "source": [ + "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", + "\nvar computedLC_BoP_I = Test.GetScope(id_BoP_I).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ihEr80PWCkGZdhvb1ggfKw", + "cell_type": "code", + "source": [ + "(computedCSM_BoP_I, computedLC_BoP_I)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "gGKUWa-n40u9Xu3VNw4n7A", + "cell_type": "markdown", + "source": [ + "To understand where the BOP is allocated, we retrieve the corresponding TM and, based on its sign, we expect the CSM or the LC to be non-zero according to the [formula](#switch-logic) above" + ], + "metadata": {} + }, + { + "id": "GbsT5_IX40yquehB3bXzWg", + "cell_type": "code", + "source": [ + "var TM_BOP_I = Test.GetScope(id_BoP_I).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VzVSQA_NVE2D__qk77LRuQ", + "cell_type": "code", + "source": [ + "TM_BOP_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VyqxO7jhD06tjnlyZWgklA", + "cell_type": "code", + "source": [ + "var expectedCSM_BoP_I = TM_BOP_I < 0 ? -TM_BOP_I : 0;", + "\nvar expectedLC_BoP_I = TM_BOP_I > 0 ? +TM_BOP_I : 0;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "I9Ou_OG9n0-4enuli2WR8w", + "cell_type": "code", + "source": [ + "(expectedCSM_BoP_I, expectedLC_BoP_I)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZGzRu0gOjEuAs_AaPiyaAA", + "cell_type": "code", + "source": [ + "computedCSM_BoP_I.CheckEquality(computedCSM_BoP_I).Should().Be(true);", + "\nexpectedLC_BoP_I.CheckEquality(computedLC_BoP_I).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Dmr2QZObzkCiSqWNVstsqA", + "cell_type": "markdown", + "source": [ + "## Following AoC steps" + ], + "metadata": {} + }, + { + "id": "QhyguKxmFkur5akQ_kuU4w", + "cell_type": "markdown", + "source": [ + "From the BOP up to the CL step, the switch logic is applied separately to the In-Force and New Business novelties." + ], + "metadata": {} + }, + { + "id": "j2v9TGxKBEi9vyAXzjnYRQ", + "cell_type": "code", + "source": [ + "var id_MC_I = Test.GetIdentity(dataNode, \"MC\", \"I\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "oURGBY049UO_6rpp5Yvd8w", + "cell_type": "code", + "source": [ + "id_MC_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Zz6IYfaXW0eEwAt1CFXLqQ", + "cell_type": "code", + "source": [ + "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", + "\nvar computedLC_MC_I = Test.GetScope(id_MC_I).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "anLo2TEZn0a-c-b58-NptA", + "cell_type": "code", + "source": [ + "(computedCSM_MC_I, computedLC_MC_I)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "_3ECx3xw6kaAPhipr_o3IQ", + "cell_type": "markdown", + "source": [ + "According to the [formula](#switch-logic) above this AoC step is allocated either to CSM or to LC based on the sign of ATM + TM. Both these two terms can be retrieved from the **TechnicalMargin** Scope." + ], + "metadata": {} + }, + { + "id": "vDlb6A-66UaV1dj-A7BpwA", + "cell_type": "code", + "source": [ + "var TM_MC_I = Test.GetScope(id_MC_I);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "tWklX6ndd0eQuh10WyJwow", + "cell_type": "code", + "source": [ + "TM_MC_I" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VShlk81fLE6vcS4-zPChpA", + "cell_type": "markdown", + "source": [ + "The correctness of the ATM can be checked by firstly withdrawing the previous AoC steps" + ], + "metadata": {} + }, + { + "id": "ZeVVDyOg8kiQOSI9_cx7Sg", + "cell_type": "code", + "source": [ + "var previousAocStep = Test.GetScope((id_MC_I, InputSource.Cashflow)).Values;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TGc_r6IcEUWsmmbS1dH8gA", + "cell_type": "code", + "source": [ + "previousAocStep" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "4LVnT3VEWkyKk021jdSe1g", + "cell_type": "markdown", + "source": [ + "and then evaluating the sum of the corresponding TMs" + ], + "metadata": {} + }, + { + "id": "C4MRuXZBHEWOoGmxdDMPNQ", + "cell_type": "code", + "source": [ + "var expectedATM = previousAocStep.Sum(aoc => Test.GetScope(id_MC_I with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "AjUcTq64mUiQGuUK9WLhpQ", + "cell_type": "code", + "source": [ + "expectedATM" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qG0nHl69Y0qX9agYsei91g", + "cell_type": "markdown", + "source": [ + "Therefore, the following condition for ATM calculated by the **TechnicalMargin** Scope needs to be fullfilled" + ], + "metadata": {} + }, + { + "id": "-2a6HsG0-U6ss9qGHoExYw", + "cell_type": "code", + "source": [ + "TM_MC_I.AggregatedValue.Should().BeApproximately( expectedATM, Precision );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "z3e8UQynb02Bjtq0B_KbcA", + "cell_type": "markdown", + "source": [ + "The CSM and LC can be allocated according to the [Switch Logic](#switch-logic)." + ], + "metadata": {} + }, + { + "id": "SpZykQISGUS5t5LfteXTqg", + "cell_type": "code", + "source": [ + "double expectedCSM_MC_I; ", + "\ndouble expectedLC_MC_I; " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8I15mZw2KUKeZMDPsOvYfg", + "cell_type": "code", + "source": [ + "var aggregated = TM_MC_I.Value + TM_MC_I.AggregatedValue;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Qw1GlZ5Edkaz3I-5i96u9A", + "cell_type": "markdown", + "source": [ + "If there is no switch from LC, i.e. $\\text{ATM} (\\text{AoC}) > 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\ge 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& 0 ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& \\text{TM}(\\text{AoC}) ~.", + "\n\\end{array}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "7da5XEhrhEu35M4vNuKJ7Q", + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue > 0 && aggregated >= 0) {", + "\n expectedCSM_MC_I = 0 ;", + "\n expectedLC_MC_I = TM_MC_I.Value ;", + "\n} " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "KbFNOw70mEePHWniU_e5Gw", + "cell_type": "markdown", + "source": [ + "If there is no switch from CSM, i.e. $\\text{ATM} (\\text{AoC}) \\le 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\le 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& 0 ~.", + "\n\\end{array}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "fgaGOnieo0qKvh_7zYB2Iw", + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue < 0 && aggregated <= 0) {", + "\n expectedCSM_MC_I = -TM_MC_I.Value ;", + "\n expectedLC_MC_I = 0 ;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "wI01nxemTE6PWDDgvWjtww", + "cell_type": "markdown", + "source": [ + "If $\\text{ATM} (\\text{AoC}) > 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\le 0$, then there is a switch to CSM:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) -\\text{ATM} (\\text{AoC}) ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& -\\text{ATM} (\\text{AoC}) ~.", + "\n\\end{array}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "r_Z-PV3jnEe61s5dxqqeAQ", + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue > 0 && aggregated <= 0) {", + "\n expectedCSM_MC_I = -aggregated;", + "\n expectedLC_MC_I = -TM_MC_I.AggregatedValue ;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UGTIjdFCpUOf3okJiq05Xw", + "cell_type": "markdown", + "source": [ + "On the other hand, if $\\text{ATM} (\\text{AoC}) \\le 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) > 0$, ", + "\nthen the switch is to LC:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& \\text{ATM} (\\text{AoC}) ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& \\text{TM}(\\text{AoC}) + \\text{ATM} (\\text{AoC}) ~.", + "\n\\end{array}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "b4tllqavSUaAPPPQ9-2xNw", + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue <= 0 && aggregated > 0) {", + "\n expectedCSM_MC_I = TM_MC_I.AggregatedValue ;", + "\n expectedLC_MC_I = aggregated ;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "7DcRpZcCLEurfCz1WhmBsA", + "cell_type": "markdown", + "source": [ + "Therefore, the expected CSM and LC for this step are" + ], + "metadata": {} + }, + { + "id": "Cynr0d0AokyhPo5thwHxng", + "cell_type": "code", + "source": [ + "(expectedCSM_MC_I, expectedLC_MC_I)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "jt1m57jeUUOnClnAWUh4GQ", + "cell_type": "code", + "source": [ + "expectedCSM_MC_I.CheckEquality(computedCSM_MC_I).Should().Be(true);", + "\nexpectedLC_MC_I.CheckEquality(computedLC_MC_I).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0CzQml-85UuZbrhJFsKLDw", + "cell_type": "markdown", + "source": [ + "", + "\n## Combined Liabilities" + ], + "metadata": {} + }, + { + "id": "l3-1ZxlOU06br5k6_VWJgw", + "cell_type": "markdown", + "source": [ + "The CL Aoc Step brings both contributions to CSM and LC together as the novelities are summed.", + "\n", + "\nFor the CL step, the logic is similar to the one above, except that a switch from LC to CSM can happen **because of New Business and despite of In-Force**, in which case we have:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) - \\text{ATM}(\\text{Last In-Force AoC step}) - \\text{TM}(\\text{Last In-Force AoC step}) \\\\", + "\n\\text{LC}(\\text{AoC}) &=& -\\text{ATM}(\\text{Last In-Force AoC step}) - \\text{TM}(\\text{Last In-Force AoC step})", + "\n\\end{array}", + "\n$$", + "\n", + "\nIf, on the other hand, the switch from LC to CSM happens **because of In-Force and despite of New Business**, then we have:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& - \\text{TM}(\\text{AoC}) - \\text{ATM}(\\text{Last NB AoC step}) - \\text{TM}(\\text{Last NB AoC step}) \\\\", + "\n\\text{LC}(\\text{AoC}) &=& - \\text{ATM}(\\text{Last NB AoC step}) - \\text{TM}(\\text{Last NB AoC step})", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor the switch in the other direction, i.e. from CSM to LC the formulas are similar except that LC and CSM are swapped." + ], + "metadata": {} + }, + { + "id": "LbA7zjeoTUmzsL20pTogpg", + "cell_type": "code", + "source": [ + "var id_CL_C = Test.GetIdentity(dataNode, \"CL\", \"C\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "BQ0_Jmo4GUCeoSwaNpzSEQ", + "cell_type": "code", + "source": [ + "id_CL_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "b1ZovjyK206ocT3in7tJJg", + "cell_type": "code", + "source": [ + "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", + "\nvar computedLC_CL_C = Test.GetScope(id_CL_C).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "di_k8t-Q8k6S_g2qUV6UKA", + "cell_type": "code", + "source": [ + "(computedCSM_CL_C, computedLC_CL_C)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HNbDZeZA-0q7FhEWN2i1AA", + "cell_type": "markdown", + "source": [ + "The CL step considers the last step of both the New Business and the In Force Novelties to decide what to allocate to CSM or LC. " + ], + "metadata": {} + }, + { + "id": "gFyHo7Xd80Kx9qUhOBfakQ", + "cell_type": "code", + "source": [ + "var lastAocSteps = Test.GetScope((id_CL_C, InputSource.Cashflow)).Values.GroupBy(x => x.Novelty).Select(g => g.Last());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Z0o-1_Kj7kqDfc6VHr5cxQ", + "cell_type": "code", + "source": [ + "lastAocSteps" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "OJYdM2hIAk-hyqf4zANz0A", + "cell_type": "markdown", + "source": [ + "Selecting the corresponding AocTypes:" + ], + "metadata": {} + }, + { + "id": "W0LNije6AESOhExOn3cEIQ", + "cell_type": "code", + "source": [ + "var lastAocTypeNb = lastAocSteps.Single(x => x.Novelty == Novelties.N).AocType;", + "\nvar lastAocTypeI = lastAocSteps.Single(x => x.Novelty == Novelties.I).AocType;", + "\n(lastAocTypeI, lastAocTypeNb)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LQ6g6NwhGkaAn6cNDgnwLw", + "cell_type": "code", + "source": [ + "var lastTM_NewBusiness = Test.GetScope(id_CL_C with {AocType = lastAocTypeNb, Novelty = Novelties.N});" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "h_-vLUO1a0CaiTlvHdl-Qw", + "cell_type": "code", + "source": [ + "lastTM_NewBusiness" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "vx-ERfMXoEmPlM7YjfSpVg", + "cell_type": "code", + "source": [ + "var lastTM_InForce = Test.GetScope(id_CL_C with {AocType = lastAocTypeI, Novelty = Novelties.I});" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nEAfJcJBfU6e8ESe_G-HGQ", + "cell_type": "code", + "source": [ + "lastTM_InForce" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "IsysT0dxB02V9LtXUi4WKw", + "cell_type": "markdown", + "source": [ + "Conversely the TM and ATM for the CL step is" + ], + "metadata": {} + }, + { + "id": "0nCrk056Kki5-Lj4k_DNUA", + "cell_type": "code", + "source": [ + "var TM_Combined = Test.GetScope(id_CL_C);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HYP4Ehlpz06WTCeicsf-TA", + "cell_type": "code", + "source": [ + "TM_Combined" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VizwJ9n3JUWNn8VHtyyZRg", + "cell_type": "markdown", + "source": [ + "where the ATM of CL is given by the sum of the ATMs of the New Business and In Force Novelties" + ], + "metadata": {} + }, + { + "id": "_6wJKgMbikuQcgsNrkRUKA", + "cell_type": "code", + "source": [ + "var aggregatedNewBusiness = lastTM_NewBusiness.Value + lastTM_NewBusiness.AggregatedValue;", + "\nvar aggregatedInForce = lastTM_InForce.Value + lastTM_InForce.AggregatedValue;", + "\nvar sum = aggregatedNewBusiness + aggregatedInForce;", + "\nsum" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VmDd0wzbzEW0oE885Kyqww", + "cell_type": "code", + "source": [ + "( (sum - TM_Combined.AggregatedValue)/sum < 1.0e-12).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "19uVR0w7F02xd9KaJ2yVIQ", + "cell_type": "markdown", + "source": [ + "In order to decide where the TM of the CL step is allocated, one has to check the sign of the ATM + TM for both the New Business and the In Force" + ], + "metadata": {} + }, + { + "id": "QeZXbaKXGk2Vyp4P4dxgJg", + "cell_type": "code", + "source": [ + "var aggregatedCombined = TM_Combined.Value + TM_Combined.AggregatedValue;", + "\naggregatedCombined" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Njb3qejxeU6T_QL3ocb23g", + "cell_type": "markdown", + "source": [ + "According to the [formulas above](#combined-liabilities), for a positive (negative) aggregated CL value, the CL TM has to be allocated to LC (CSM). ", + "\n
In case the one of last Aoc step of the novelties (I, NB) has the sign of the CL ATM opposite to the CL ATM, the CL AocStep is used to introduce a balancing item to bring the ATM of the novelty with opposite sign to 0. ", + "\n
This is equivalent to execute the switch logic with a balancing item = ATM of the last AocStep having opposite sign to CL ATM. ", + "\n
Note that if CL TM is zero this results in allocating the same amount with opposite sign to CSM(note that the sign of the CSM componet is flipped) and LC." + ], + "metadata": {} + }, + { + "id": "PKCnye7OH0qMHL6PW1vWMw", + "cell_type": "code", + "source": [ + "double expectedCSM_CL_C; ", + "\ndouble expectedLC_CL_C; " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mR_PzvyP50CGygsS3pFx9g", + "cell_type": "code", + "source": [ + "var balancingItem = aggregatedCombined < 0 ? aggregatedNewBusiness : aggregatedInForce;", + "\nbalancingItem" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hhE70xjs-EGuXjI4ztfscQ", + "cell_type": "code", + "source": [ + "", + "\nif(aggregatedCombined > 0) {", + "\n expectedCSM_CL_C = balancingItem ;", + "\n expectedLC_CL_C = TM_Combined.Value + balancingItem;", + "\n} else {", + "\n expectedLC_CL_C = - balancingItem ;", + "\n expectedCSM_CL_C = TM_Combined.Value - balancingItem ;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "474WEtEUPEqOIsiRVbHO0g", + "cell_type": "code", + "source": [ + "(expectedCSM_CL_C, expectedLC_CL_C)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-gNe5T_ZLEeVHsBfCLPhWA", + "cell_type": "code", + "source": [ + "expectedCSM_CL_C.CheckEquality(computedCSM_CL_C).Should().Be(true);", + "\nexpectedLC_CL_C.CheckEquality(computedLC_CL_C).Should().Be(true);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DyvDoHzrBEq3_wVcCchkEw", + "cell_type": "markdown", + "source": [ + "## End Of Period", + "\n", + "\nFor the last AoC step, the EOP is the sum of all previous steps", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{EOP}) &=& \\sum_{s~\\in~\\text{previous AoC steps}} \\text{CSM}(s) ~, \\\\", + "\n\\text{LC}(\\text{EOP}) &=& \\sum_{s~\\in~\\text{previous AoC steps}} \\text{LC}(s) ~.", + "\n\\end{array}", + "\n$$" + ], + "metadata": {} + }, + { + "id": "_ESoopqaZU-By3wLhIBkgw", + "cell_type": "code", + "source": [ + "var id_EoP_C = Test.GetIdentity(dataNode, \"EOP\", \"C\");" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZqMiKYtLj0mrhg2Bk0SKbQ", + "cell_type": "code", + "source": [ + "id_EoP_C" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qHO12xBFj0OKhZj66J3uxQ", + "cell_type": "code", + "source": [ + "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", + "\nvar computedLC_EoP_C = Test.GetScope(id_EoP_C).Value;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "C54gDBF8B0iE8erZtf9PDA", + "cell_type": "code", + "source": [ + "(computedCSM_EoP_C, computedLC_EoP_C)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MoN2gU7CgkmSAoAH8E3P4g", + "cell_type": "markdown", + "source": [ + "

", + "\n
", + "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the corresponding gross case TM to allocate the figure either to CSM or to LoReCo. The reinsurance gross TM multiplied by the weights coming from the Reinsurance Coverage Parameter (Data Node Parameters). In case a GRIC has multiple GICs, then these weighted TMs are aggregated.", + "\n
" + ], + "metadata": {} + }, + { + "id": "-17yUzUfYU-46uPh5jCLzQ", + "cell_type": "markdown", + "source": [ + "" + ], + "metadata": {} + }, + { + "id": "LHXDcjueYUy1IKvyMPuZyQ", + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Contractual Service Margin and Loss Component" + ], + "metadata": {} + }, + { + "id": "O7oZvk5RIk-EplmELWCLLw", + "cell_type": "markdown", + "source": [ + "Here below a view of the CSM and Loss Component results are shown. ", + "\n", + "\nNote: the Data Nodes with LiabilityType being *LIC* are excluded." + ], + "metadata": {} + }, + { + "id": "WQsEnHxeUkWa24cVa17ASw", + "cell_type": "code", + "source": [ + "var allIdentitiesWoLic = allIdentities.Where(id => Test.GetStorage().DataNodeDataBySystemName[id.DataNode].LiabilityType != \"LIC\").ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "ZClqTg9_EEKdli2o4Blwqw", + "cell_type": "code", + "source": [ + "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromCsmToIfrsVariable())).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VYCT72rdHE6fE0HDC7ygOQ", + "cell_type": "markdown", + "source": [ + "## Gross case" + ], + "metadata": {} + }, + { + "id": "UsRkibKobkCtFXhm5l__xQ", + "cell_type": "code", + "source": [ + "var allInsuranceIdentitiesWoLic = allIdentitiesWoLic.Where(id => !id.IsReinsurance).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "PirmpNw8w0yTsQZmMWqgKw", + "cell_type": "code", + "source": [ + "var lc = allInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromLcToIfrsVariable())).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rqcC8OgZSEWmclwqnva9LQ", + "cell_type": "markdown", + "source": [ + "## Re-Insurance case (LoReCo)" + ], + "metadata": {} + }, + { + "id": "9FlZC2iKzkimZWgYZNcsRw", + "cell_type": "code", + "source": [ + "var allReInsuranceIdentitiesWoLic = allIdentitiesWoLic.Where(id => id.IsReinsurance).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "NZ39ut9ark6eMKtKoBbyOg", + "cell_type": "code", + "source": [ + "var loreco = allReInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromLoReCoToIfrsVariable())).ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "x-kOOIetOka_mQDABgu3oQ", + "cell_type": "markdown", + "source": [ + "## Summary" + ], + "metadata": {} + }, + { + "id": "mF7UvAY_-EKAlqSsnrQcNQ", + "cell_type": "code", + "source": [ + "Report.ForObjects( csm.Concat(lc).Concat(loreco) )", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupColumnsBy(x => x.EstimateType)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "WMr4L1n4PUOCiZT5gKh9ug", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/TechnicalMarginTest.ipynb b/Test/TechnicalMarginTest.ipynb new file mode 100644 index 00000000..d42316d9 --- /dev/null +++ b/Test/TechnicalMarginTest.ipynb @@ -0,0 +1,305 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "jaNl5tr4gEGSSk1KTK2HpA", + "cell_type": "markdown", + "source": [ + "

Technical Margin Allocation

" + ], + "metadata": {} + }, + { + "id": "E5WE0di2k0aFigu3aInmKw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "YndlmtSQOkuhu3OKAyNj0g", + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ], + "metadata": {} + }, + { + "id": "7vwzSP8vUkSmgw1mvnWC1Q", + "cell_type": "code", + "source": [ + "Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TP-eEY5maEC5c7pVOpolxQ", + "cell_type": "markdown", + "source": [ + "# Test switch logic" + ], + "metadata": {} + }, + { + "id": "nhjoP-0CWUadpg116YgH6Q", + "cell_type": "code", + "source": [ + "//define group of contract", + "\nvar groupOfContract = \"DT1.1\";" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "nvCLj-DBhk211_Y_UDi0uQ", + "cell_type": "code", + "source": [ + "//Define partition", + "\n var args = new ImportArgs(\"CH\", 2020, 12, Periodicity.Quarterly, null, ImportFormats.Actual);", + "\n var partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\n if(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UmXmnz87HUKCgw066Gsx5A", + "cell_type": "code", + "source": [ + "public async Task CheckSwitchLogicAsync(IEnumerable inputDataSet, Dictionary csmLcSwitchBenchmark)", + "\n{", + "\n //Save test input data", + "\n await Workspace.UpdateAsync(inputDataSet);", + "\n ", + "\n //Set up import storage and test universe", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();", + "\n ", + "\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == groupOfContract)).SelectMany(s => s.Identities);", + "\n var csm = testUniverse.GetScopes(identities, o => o.WithContext(\"C\")).Where(x => Math.Abs(x.Value) > Precision);", + "\n var lc = testUniverse.GetScopes(identities, o => o.WithContext(\"L\")).Where(x => Math.Abs(x.Value) > Precision);", + "\n //Clean up Workspace", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", + "\n ", + "\n var csmBenchmark = csmLcSwitchBenchmark.Where(x => Math.Abs(x.Value.valueCsm) > Precision).ToDictionary(x => x.Key, x => x.Value);", + "\n var lcBenchmark = csmLcSwitchBenchmark.Where(x => Math.Abs(x.Value.valueLc) > Precision).ToDictionary(x => x.Key, x => x.Value);", + "\n ", + "\n ", + "\n var errors = new List();", + "\n if(csm.Count() > csmBenchmark.Count()) ", + "\n {", + "\n var extraVariables = csm.Where(x => !csmBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))", + "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}.\");", + "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for CSM has more non zero items than benchmark. Extra computed variables : \\n {string.Join(\"\\n\", extraVariables)}.\" );", + "\n }", + "\n if(lc.Count() > lcBenchmark.Count()) ", + "\n {", + "\n var extraVariables = lc.Where(x => !lcBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))", + "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}, \");", + "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for LC has more non zero items compared to benchmark: \\n {string.Join(\"\\n\", extraVariables)}.\" );", + "\n }", + "\n ", + "\n //Check ValueCsm", + "\n foreach(var kvp in csmBenchmark)", + "\n {", + "\n var scopeSwitch = csm.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", + "\n ", + "\n if(scopeSwitch == null)", + "\n {", + "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );", + "\n continue;", + "\n }", + "\n ", + "\n if(Math.Abs(-1.0 * scopeSwitch.Value - kvp.Value.valueCsm) > Precision) ", + "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Csm {-1 * scopeSwitch.Value}; Benchmark: Csm {kvp.Value.valueCsm}.\" );", + "\n }", + "\n //Check ValueLc", + "\n foreach(var kvp in lcBenchmark)", + "\n {", + "\n var scopeSwitch = lc.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", + "\n ", + "\n if(scopeSwitch == null)", + "\n {", + "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );", + "\n continue;", + "\n }", + "\n ", + "\n if(Math.Abs(scopeSwitch.Value - kvp.Value.valueLc) > Precision) ", + "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Lc {scopeSwitch.Value}; Benchmark: Lc {kvp.Value.valueLc}.\" );", + "\n }", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "qKbQQyYPQU-Iye0tiP7x5A", + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 15.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"N\"),(0d, 100d)},", + "\n {new AocStep(\"IA\",\"N\"), (0d, 15d)},", + "\n {new AocStep(\"EV\",\"N\"), (0d, 100d)},", + "\n {new AocStep(\"CL\",\"C\"), (0d, 100d)},", + "\n {new AocStep(\"EA\",\"C\"), (0d, -8.0)},", + "\n {new AocStep(\"AM\",\"C\"), (0d, -153.5)},", + "\n {new AocStep(\"EOP\",\"C\"),(0d, 153.5)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "TK8_VLRvbkOFHfCgScgBGg", + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 15.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = -500.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"N\"),(0d, 100d)},", + "\n {new AocStep(\"IA\",\"N\"), (0d, 15d)},", + "\n {new AocStep(\"EV\",\"N\"), (0d, 100d)},", + "\n {new AocStep(\"CL\",\"C\"), (285d, -215d)},", + "\n {new AocStep(\"EA\",\"C\"), (8d, 0d)},", + "\n {new AocStep(\"AM\",\"C\"), (-146.5d, 0d)},", + "\n {new AocStep(\"EOP\",\"C\"),(146.5d, 0d)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zFF7F81APUmclfr-m3jMcw", + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = -150.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"N\"), (0d, 100d)},", + "\n {new AocStep(\"IA\",\"N\"), (50d, -100d)},", + "\n {new AocStep(\"EA\",\"C\"), (8d, 0d)},", + "\n {new AocStep(\"AM\",\"C\"), (-29d, 0d)},", + "\n {new AocStep(\"EOP\",\"C\"),(29d, 0d)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HBM6I7rP8UeMjn0PNDOkvg", + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"I\", Value = 5010.0, EstimateType = \"L\", AmountType = null},", + "\n basicIfrsVariable with {AocType = \"MC\", Novelty = \"I\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"I\", Value = -5015.0},", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = -100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = 10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 150.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = -45.0},", + "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = -30.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"),( 0d, 5010.0)},", + "\n {new AocStep(\"MC\",\"I\"), ( 0d, -10d)},", + "\n {new AocStep(\"IA\",\"I\"), ( 0d, 10d)},", + "\n {new AocStep(\"EV\",\"I\"), ( 5d,-5010d)},", + "\n ", + "\n {new AocStep(\"BOP\",\"N\"),(100d, 0d)},", + "\n {new AocStep(\"IA\",\"N\"), (-100d, 50d)},", + "\n {new AocStep(\"EV\",\"N\"), ( 0d, -45d)},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), ( 25d, -5d)},", + "\n {new AocStep(\"EA\",\"C\"), ( -8d, 0d)},", + "\n {new AocStep(\"AM\",\"C\"), ( -11d, 0d)},", + "\n {new AocStep(\"EOP\",\"C\"),( 11d, 0d)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0mf1wwWN00-8_xIdPwv8aA", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Test/Tests.ipynb b/Test/Tests.ipynb new file mode 100644 index 00000000..1cd4f874 --- /dev/null +++ b/Test/Tests.ipynb @@ -0,0 +1,183 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "TZgppEey_UevldeIhLk-Zg", + "cell_type": "markdown", + "source": [ + "

Tests

" + ], + "metadata": {} + }, + { + "id": "SyI_QtXCw0yCEOXRPFFsww", + "cell_type": "code", + "source": [ + "#!eval-notebook \"IfrsVariablesTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-uMg4UaFbECZuIbtwJCvJw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"ImportStorageTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "x_X1-9LqmkCGI9R1UOQo6A", + "cell_type": "code", + "source": [ + "#!eval-notebook \"ReportStorageTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fTEQQtLuT0uQ01JBhmVGzw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"QueriesTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "iRWR94CbKU-eP1eVu7LpbA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"AocStructureTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Omg1EkcRJ0miK9epGdB5Fg", + "cell_type": "code", + "source": [ + "#!eval-notebook \"TechnicalMarginTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "EMHkr07qoEyWT3n-TUrE_A", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "XYHMD6zOzUS3CLOcyaAq_g", + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsImportCashflows\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HfcLmG39kE2VFzt18WLEKA", + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsImportActuals\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XgjC6ZJsvkGNTDeP374MXw", + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsTechnicalMargin\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-zjdp-ODe0qnHVp1-wr02A", + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsFinancialPerformance\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "QtahA_wtJUmc5mWycmnjzA", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "xfKpAnti3UaiKrOBQeD8gw", + "cell_type": "code", + "source": [ + "//#!eval-notebook \"MapTemplateAndImportTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "5jyZtMUGUU6YhrXXY2mMqQ", + "cell_type": "markdown", + "source": [ + "---" + ], + "metadata": {} + }, + { + "id": "hvH198RRBUGXwPc-HsgU0A", + "cell_type": "code", + "source": [ + "#!eval-notebook \"ReportVariablesTest\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Q8h-6uY0TkCHeLq1bFnNhQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Utils/ApplicationMessage.ipynb b/Utils/ApplicationMessage.ipynb new file mode 100644 index 00000000..80df11f5 --- /dev/null +++ b/Utils/ApplicationMessage.ipynb @@ -0,0 +1,149 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "broxX4LAHEyOyWz2MhegDg", + "cell_type": "markdown", + "source": [ + "

Application Message

" + ], + "metadata": {} + }, + { + "id": "h1R2W32vMUu5tJyRO8rd4A", + "cell_type": "code", + "source": [ + "#r \"nuget:Systemorph.Activities,1.2.3\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "84ytRYskFU-7SEmFS1wFiA", + "cell_type": "code", + "source": [ + "#!import \"../Constants/Validations\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zdCOoGGKDUad4bauxbDx8A", + "cell_type": "code", + "source": [ + "using Microsoft.Extensions.Logging;", + "\n", + "\npublic class ApplicationMessage {", + "\n private static ILogger log;", + "\n ", + "\n private static IActivityVariable activity;", + "\n ", + "\n public static void Configure (ILogger log, IActivityVariable activity) ", + "\n {", + "\n ApplicationMessage.log = log;", + "\n ApplicationMessage.activity = activity;", + "\n }", + "\n ", + "\n public static Object Log (Error e, params string[] s) { log.LogError(Get(e,s)); return null; }", + "\n ", + "\n public static Object Log (Warning w, params string[] s) { log.LogWarning(Get(w,s)); return null; }", + "\n ", + "\n public static bool HasErrors () => activity.HasErrors();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "rmXkyteAs0qIkylMj_uzoA", + "cell_type": "code", + "source": [ + "ApplicationMessage.Configure(Log, Activity)" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "C5Sz9dotT0ye5OfZ9kKzZg", + "cell_type": "markdown", + "source": [ + "# Utils" + ], + "metadata": {} + }, + { + "id": "PI-rD5MuDkm1oNDAzAlxdQ", + "cell_type": "code", + "source": [ + "public static bool HasErrors (this ActivityLog[] logs) {", + "\n foreach (var log in logs)", + "\n if(log.Errors.Any())", + "\n return true;", + "\n return false;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zP4DHMB7v0iJBQU0evmyJQ", + "cell_type": "code", + "source": [ + "public static ActivityLog Merge (this ActivityLog a, ActivityLog b) {", + "\n return a with { ", + "\n StartDateTime = a.StartDateTime < b.StartDateTime ? a.StartDateTime : b.StartDateTime,", + "\n FinishDateTime = a.FinishDateTime > b.FinishDateTime ? a.FinishDateTime : b.FinishDateTime,", + "\n Errors = a.Errors.Concat(b.Errors).ToList(),", + "\n Warnings = a.Warnings.Concat(b.Warnings).ToList(),", + "\n Infos = a.Infos.Concat(b.Infos).ToList(),", + "\n Status = a.Status == ActivityLogStatus.Failed || b.Status == ActivityLogStatus.Failed ? ActivityLogStatus.Failed : ActivityLogStatus.Succeeded", + "\n };", + "\n}", + "\n", + "\npublic static ActivityLog Merge (this ActivityLog[] logs) ", + "\n{", + "\n if(logs == null || logs.Length == 0) return null;", + "\n return logs.Aggregate((x, y) => x.Merge(y));", + "\n}", + "\n", + "\npublic static ActivityLog Merge (this ActivityLog[] logs, ActivityLog log) => logs.Merge().Merge(log);", + "\npublic static ActivityLog Merge (this ActivityLog log, ActivityLog[] logs) => log.Merge(logs.Merge());" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CdUfdMGymkqjIXT66mL65g", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/Utils/UtilityMethods.ipynb b/Utils/UtilityMethods.ipynb new file mode 100644 index 00000000..8390e86f --- /dev/null +++ b/Utils/UtilityMethods.ipynb @@ -0,0 +1,1155 @@ +{ + "metadata": { + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "authors": [], + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "id": "72RJn3yBk0-cdIRCo3QO6A", + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"", + "\n#!import \"./ApplicationMessage\"" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "bTXVV8ziO0GApQeS_y9z3Q", + "cell_type": "code", + "source": [ + "using System.Linq.Expressions;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "0rrQ118FOkCCJosdbGYr_Q", + "cell_type": "markdown", + "source": [ + "# Math Functions" + ], + "metadata": {} + }, + { + "id": "JSuwpYPWEE-_BxSyEyzsbQ", + "cell_type": "code", + "source": [ + "static double DivideOrDefault(double numerator, double denominator, double defaultValue = default) => Math.Abs(denominator) > double.Epsilon ? numerator / denominator : defaultValue;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9dxEM2ggXU-zTLNvvCHsOQ", + "cell_type": "code", + "source": [ + "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", + "\nstatic T GetElementOrDefault(this ICollection array, int index)", + "\n{ ", + "\n var count = array.Count;", + "\n if (array == null || count == 0)", + "\n return default(T);", + "\n", + "\n return index < 0", + "\n ? array.ElementAt(0) // should this case be removed?", + "\n : index < count", + "\n ? array.ElementAt(index)", + "\n : array.ElementAt(count -1);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "A-gLq4O2eE6IW3jx-1tDCw", + "cell_type": "markdown", + "source": [ + "# Enumerable Extensions" + ], + "metadata": {} + }, + { + "id": "QhtXvQfGpkOPqpRxznrgcg", + "cell_type": "code", + "source": [ + "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Brh1Yk0MoEO5H52znFTqUQ", + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "3hPGQtfhI0ic1_w5PyiBgw", + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "-Y6HUEHIgEidj23uHIcscQ", + "cell_type": "code", + "source": [ + "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xZnDqW6rXEagl6N5IPFBHg", + "cell_type": "markdown", + "source": [ + "# String Extensions" + ], + "metadata": {} + }, + { + "id": "3TZ5QaWLL0eXsicw9mEhrA", + "cell_type": "code", + "source": [ + "using System.Globalization;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "DLkjFfpXp0ODlwc_imkUwA", + "cell_type": "code", + "source": [ + "public static double CheckStringForExponentialAndConvertToDouble (this string s)", + "\n{ ", + "\n if (s == null) return default;", + "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", + "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "740WQ9Xg6ESwS7mzcd_UDQ", + "cell_type": "markdown", + "source": [ + "# Enum Extentions" + ], + "metadata": {} + }, + { + "id": "WNoxcMPslUm-66pmOH5a8g", + "cell_type": "code", + "source": [ + "public static bool Contains(this T value, T lookingForFlag) ", + "\n where T : struct", + "\n{", + "\n int intValue = (int) (object) value;", + "\n int intLookingForFlag = (int) (object) lookingForFlag;", + "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "NgzAK-3L_kW3JQNLVUSQoQ", + "cell_type": "markdown", + "source": [ + "# Queries" + ], + "metadata": {} + }, + { + "id": "ekflioBoz0ukcAPWv4xRtQ", + "cell_type": "markdown", + "source": [ + "## FX" + ], + "metadata": {} + }, + { + "id": "B24vyYMc9kOlNnSUAfEHGQ", + "cell_type": "code", + "source": [ + "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.Query()", + "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", + "\n x.Year == year && x.Month == month)", + "\n .ToArrayAsync())", + "\n .ToDictionaryGrouped(x => x.Currency,", + "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", + "\n {", + "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", + "\n },", + "\n y => y.FxToGroupCurrency));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hSaegw7GtEWvUosF-y231g", + "cell_type": "code", + "source": [ + "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", + "\n{", + "\n if(currency == groupCurrency)", + "\n return 1;", + "\n", + "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", + "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", + "\n", + "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", + "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", + "\n", + "\n return currencyToGroupFx;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "hcDcg_DFUEOgLrrWw8cE2g", + "cell_type": "markdown", + "source": [ + "## Current and Previous Parameters" + ], + "metadata": {} + }, + { + "id": "qgieIWL7ZUe7mJIVbU_1gQ", + "cell_type": "markdown", + "source": [ + "TODOs:", + "\n
    ", + "\n
  • DataNodes Query: After merging with the new import storage, define IsFirstPeriod property.
  • ", + "\n
  • Once Scenario is defined as a simple property (e.g. in DataNodeState), introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", + "\n
" + ], + "metadata": {} + }, + { + "id": "X01D1mGxS06sfFEPjwyG-A", + "cell_type": "code", + "source": [ + "public static async Task LoadParameterAsync(", + "\n this IQuerySource querySource,", + "\n int year,", + "\n int month,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return await querySource.Query()", + "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", + "\n .Where(filterExpression?? (Expression>)(x => true))", + "\n .ToArrayAsync();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "sKO5N-LgyEGBEZam7l9_Fg", + "cell_type": "code", + "source": [ + "public static async Task> LoadCurrentParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", + "\n .GroupBy(identityExpression)", + "\n .Select(y => y.OrderByDescending(x => x.Year)", + "\n .ThenByDescending(x => x.Month)", + "\n .FirstOrDefault())", + "\n .ToDictionary(identityExpression);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "I0M5hxr91UGl2zNnwXzW-g", + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentAndPreviousParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", + "\n ", + "\n var ret = new Dictionary>();", + "\n foreach(var p in parameters)", + "\n {", + "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", + "\n", + "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n ", + "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", + "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", + "\n }", + "\n return ret;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "UMrZ966740-j48yfqsXM2g", + "cell_type": "markdown", + "source": [ + "", + "\n## Yield Curve" + ], + "metadata": {} + }, + { + "id": "qcQgXJr-l0Gql-aOiCdRrQ", + "cell_type": "code", + "source": [ + "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var lockedInYieldCurveByGoc = new Dictionary();", + "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", + "\n {", + "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", + "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", + "\n ", + "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", + "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", + "\n ", + "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", + "\n }", + "\n ", + "\n return lockedInYieldCurveByGoc;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "mkhcBCMjAku6Fqv8M8fhmg", + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", + "\n x => x.Currency,", + "\n x => contractualCurrenciesInScope.Contains(x.Currency)", + "\n ));", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "11r0X9aBAUKWja2qSlbOWQ", + "cell_type": "markdown", + "source": [ + "## Data Node State" + ], + "metadata": {} + }, + { + "id": "ineEPRxhfkOAuclOvhZ1lw", + "cell_type": "code", + "source": [ + "//TODO : remove this method and clean up in queriesTest. We need a new test for LoadDataNodes.", + "\npublic static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n //This querySource is partitioned", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", + "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", + "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "B1n-fWXBi0GL93ngrSSRbQ", + "cell_type": "markdown", + "source": [ + "## Data Nodes" + ], + "metadata": {} + }, + { + "id": "jdq7blDf4U6-pmv3CMUQTQ", + "cell_type": "code", + "source": [ + "// TODO: the name of this method is strange, one expects DataNodes in return but instead obtains DataNodeData...", + "\npublic static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args) //How do we force the user to provide here a partitioned source? IWorkspace?", + "\n{", + "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", + "\n ", + "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", + "\n .ToDictionary(dn => dn.SystemName, dn => {", + "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", + "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", + "\n return new DataNodeData(){Year = dnPreviousState.Year, ", + "\n Month = dnPreviousState.Month,", + "\n State = dnCurrentState.State,", + "\n PreviousState = dnPreviousState.State,", + "\n //from Group of Contract", + "\n DataNode = dn.SystemName,", + "\n ContractualCurrency = dn.ContractualCurrency,", + "\n FunctionalCurrency = dn.FunctionalCurrency,", + "\n LineOfBusiness = dn.LineOfBusiness,", + "\n ValuationApproach = dn.ValuationApproach,", + "\n OciType = dn.OciType,", + "\n Portfolio = dn.Portfolio,", + "\n AnnualCohort = dn.AnnualCohort,", + "\n LiabilityType = dn.LiabilityType,", + "\n Profitability = dn.Profitability,", + "\n Partner = dn.Partner,", + "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", + "\n };", + "\n }", + "\n );", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "o0-QY0CD_U6QtHo8DUg-XA", + "cell_type": "markdown", + "source": [ + "## Data Node Parameters" + ], + "metadata": {} + }, + { + "id": "u2AAh0Om8k-FVnzV99qeXw", + "cell_type": "markdown", + "source": [ + "### Single data Node" + ], + "metadata": {} + }, + { + "id": "fGw6yDyGdkGSnMtEzlCWNg", + "cell_type": "code", + "source": [ + "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "fqKznL41TkGOYs41YCJkIw", + "cell_type": "markdown", + "source": [ + "### Inter data Node" + ], + "metadata": {} + }, + { + "id": "9TJH-kJoTEmIucE-PjX7sw", + "cell_type": "code", + "source": [ + "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", + "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", + "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", + "\n ", + "\n return parameters.SelectMany(p => p", + "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", + "\n .Select(gg =>", + "\n {", + "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n return (key: p.Key,", + "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", + "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", + "\n })", + "\n )", + "\n .ToDictionaryGrouped(x => x.key,", + "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", + "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "m5W0i-9h_USmOALgfJ5ynw", + "cell_type": "markdown", + "source": [ + "## Aoc Step Configuration" + ], + "metadata": {} + }, + { + "id": "foNau3wankChqmtvuPVxmw", + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.LoadParameterAsync(year, month)).GroupBy(x => (x.AocType, x.Novelty), (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "u2cguHXQ-kyIKbXgTS6P_g", + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) => (await querySource.LoadAocStepConfigurationAsync(year, month)).ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "kujIpDbHiUyTpBosaNnjDg", + "cell_type": "markdown", + "source": [ + "# Export Configurations" + ], + "metadata": {} + }, + { + "id": "cdft6A5YOU-JKits9tdQ0w", + "cell_type": "markdown", + "source": [ + "## Main Tab" + ], + "metadata": {} + }, + { + "id": "qAmPBlXGBkanj2uTVSqlCA", + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Scenario, x => x.Delete()));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xDi9MN7YXE6TzDsUxJKv_g", + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete()));" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "CRZfO8bZy0G9fSLekjFWUg", + "cell_type": "markdown", + "source": [ + "## Dimensions" + ], + "metadata": {} + }, + { + "id": "Ln1Wggqu406eomb1E8Akcw", + "cell_type": "code", + "source": [ + "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", + "\n });" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6qc9dAkjOkSfbiofWgLnXw", + "cell_type": "code", + "source": [ + "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", + "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", + "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", + "\n .WithColumn(x => x.OciType, x => x.Delete())", + "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", + "\n });" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "1dhHyd3JGEOohmsGAjA_gw", + "cell_type": "markdown", + "source": [ + "## Data Node State" + ], + "metadata": {} + }, + { + "id": "Ymq2Wq7sjkeLyNlifepNaQ", + "cell_type": "code", + "source": [ + "using DocumentFormat.OpenXml.Spreadsheet;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "dGKqDg0S5Eq62tKaxG_7yg", + "cell_type": "code", + "source": [ + "public record HelperState { public string State {get; init;} }" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "8HjMW_4oEkSc8gt502-Lkw", + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data.AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", + "\n );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "G2bKdGeyiEeKBz1bG8g86w", + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", + "\n{", + "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", + "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", + "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", + "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", + "\n .WithSource(source => helperState.AsQueryable()) );", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "zb2wO1m1uUaw0RbXeMwHGw", + "cell_type": "markdown", + "source": [ + "## Data Node Parameter" + ], + "metadata": {} + }, + { + "id": "4hvQE9cObUS1h9wW2WA_LA", + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n )", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n );" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "HYdwh4HjBkC--t3kyqy0jg", + "cell_type": "markdown", + "source": [ + "# Report Configurations" + ], + "metadata": {} + }, + { + "id": "qnzf570gh0uWBWG5tHisdw", + "cell_type": "code", + "source": [ + "using Systemorph.Vertex.Pivot.Reporting.Builder;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "L21IHsS-ukOp7q2KpQYwrg", + "cell_type": "code", + "source": [ + "public static ReportBuilder WithGridOptionsForIfrsVariable", + "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", + "\n{", + "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", + "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", + "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", + "\n );", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "xcQnRFiM80yaO6WWqlVJ3w", + "cell_type": "markdown", + "source": [ + "# Utility Methods Class" + ], + "metadata": {} + }, + { + "id": "Yl-kOA4SvkmoX4bFR30uGA", + "cell_type": "markdown", + "source": [ + "This class contains:", + "\n- EqualityComparer" + ], + "metadata": {} + }, + { + "id": "MzSS_gk3YUqeeUoxH5615g", + "cell_type": "code", + "source": [ + "public static class Utils {", + "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", + "\n {", + "\n collection1.Length.Should().Be(collection2.Length);", + "\n var type = typeof(T);", + "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", + "\n if(properties.Count() == 0) {", + "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", + "\n isEqual.Should().Be(true);", + "\n }", + "\n foreach(var item1 in collection1) {", + "\n var item2 = collection2.Where(x => ", + "\n properties.All(prop => {", + "\n var propType = prop.PropertyType;", + "\n var val = prop.GetValue(item1);", + "\n var otherVal = prop.GetValue(x);", + "\n if(val == null && otherVal == null) return true;", + "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", + "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", + "\n })", + "\n );", + "\n item2.Count().Should().NotBe(0);", + "\n }", + "\n }", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Fnb9erxecEyh69YlvuE30Q", + "cell_type": "code", + "source": [ + "// TODO: find a better arrangement to these methods", + "\nstatic var NumericalPrecisionEqualityChecker = 1.0E-10;", + "\n", + "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", + "\n{", + "\n if(arr1.Length != arr2.Length) return false;", + "\n for(int i = 0; i < arr1.Length; i++) {", + "\n double d1 = arr1[i];", + "\n double d2 = arr2[i];", + "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", + "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", + "\n }", + "\n return true;", + "\n}", + "\n", + "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", + "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", + "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", + "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", + "\n", + "\nstatic bool CheckEquality(this double? d1, double? d2) ", + "\n{", + "\n if(d1 == null && d2 == null) return true;", + "\n else return CheckEquality((double)d1, (double)d2);", + "\n}", + "\n" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "etIXAOoMHEGKXFbnzCCRWA", + "cell_type": "markdown", + "source": [ + "## ToIdentityString" + ], + "metadata": {} + }, + { + "id": "-0U7OSuELUeCMTZ487kI_A", + "cell_type": "code", + "source": [ + "using System.Text;", + "\npublic static string ToIdentityString(this T v)", + "\n where T : class", + "\n{", + "\n StringBuilder sb = new StringBuilder();", + "\n var propertyInfos = v.GetType()", + "\n .GetProperties()", + "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", + "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", + "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", + "\n", + "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "cq_4STuakk6krLbs6TZ4yg", + "cell_type": "markdown", + "source": [ + "## GetPreviousIdentities" + ], + "metadata": {} + }, + { + "id": "XYOo4uHfnkeKWMF_MQ5r-Q", + "cell_type": "code", + "source": [ + "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", + "\n{", + "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", + "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", + "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", + "\n return identities.Where(id => id.AocType != AocTypes.BOP)", + "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", + "\n : previousStep[x.Novelty].RepeatOnce();", + "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", + "\n return ret;});", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "XbcZgL57GUy04M44loxF-g", + "cell_type": "markdown", + "source": [ + "## GetReferenceAocStepForCalculated" + ], + "metadata": {} + }, + { + "id": "MLNCUWgSAkyrA-DMWc-JpQ", + "cell_type": "code", + "source": [ + "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", + "\n{", + "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", + "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", + "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", + "\n && aocStep.Novelty == identityAocStep.Novelty) ", + "\n ?? new AocStep(default, default);", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "VxJI9sGp3UyCFxyJM7MGKg", + "cell_type": "markdown", + "source": [ + "# Change Sign Rules" + ], + "metadata": {} + }, + { + "id": "Uv2X9RT3wkKLJvMvooTbSw", + "cell_type": "code", + "source": [ + "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", + "\n return isActual;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "MOV5tqPp2kSr4kp0wet0ag", + "cell_type": "markdown", + "source": [ + "# EstimateType And AmountType" + ], + "metadata": {} + }, + { + "id": "jf_kmDreZUyVr-gBkFuuCg", + "cell_type": "code", + "source": [ + "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n return new Dictionary>(){", + "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", + "\n };", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "j0oOSZn9ZkK6D6BR_YxuJg", + "cell_type": "markdown", + "source": [ + "# Technical Margin EstimateType" + ], + "metadata": {} + }, + { + "id": "86CBe5DnrkOi6irqUzCLNw", + "cell_type": "code", + "source": [ + "public static HashSet GetTechnicalMarginEstimateType()", + "\n{", + "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "9OeFmvwQJECtzHY6Dg8Yzw", + "cell_type": "markdown", + "source": [ + "# Discount and Cumulate" + ], + "metadata": {} + }, + { + "id": "Ajyhr4n0106OnU6fEIdL5g", + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", + "\n{ ", + "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", + "\n ", + "\n var ret = new double[nominalValues.Length];", + "\n ", + "\n if(periodType == PeriodType.BeginningOfPeriod)", + "\n {", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n return ret;", + "\n }", + "\n ", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n ", + "\n return ret;", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "LoqMwHfd8kOJYFyQxw5KNQ", + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", + "\n{ ", + "\n return Enumerable.Range(0, nominalValues.Length)", + "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", + "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", + "\n .Sum() )", + "\n .ToArray();", + "\n}" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "Y9wSV5wvy0mvkCNsCiRmlQ", + "cell_type": "markdown", + "source": [ + "# Import Configuration" + ], + "metadata": {} + }, + { + "id": "11et4IQ_0US7mUdWWNnouw", + "cell_type": "markdown", + "source": [ + "## Data Nodes" + ], + "metadata": {} + }, + { + "id": "fd6J9NnbXkmWF-7Qi2FmWA", + "cell_type": "code", + "source": [ + "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "z4UEzk2bPEOGnwoC6UN3pg", + "cell_type": "code", + "source": [ + "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + }, + { + "id": "6k1Zt47Wtk6cltgFOwSPXQ", + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 1, + "outputs": [] + } + ] +} \ No newline at end of file From 1f545cde35246a8c4f6d147047547dbc150f43b6 Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Wed, 28 Sep 2022 15:41:40 +0200 Subject: [PATCH 02/38] correct broken links --- Import/ImportScopeCalculation.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index 175eb9d1..2823aead 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -511,7 +511,7 @@ "id": "ON4hzALyrkapbo6dsJaCYA", "cell_type": "markdown", "source": [ - "For an example of these calculations see [here](../Test/DocumentationImportCashflowsTest#interest-and-discount-rates)." + "For an example of these calculations see [here](../Test/SpecificationsImportCashflows#interest-and-discount-rates)." ], "metadata": {} }, @@ -1896,7 +1896,7 @@ "\n", "\n### Reinsurance case", "\n", - "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the gross Technical Margins multiplied by the weights coming from the Reinsurance Coverage Parameter (see [Data Node Parameters](..\\DataModel/DataStructure#data-node-parameters)). In case a GRIC has multiple GICs, then these weighted $TM$s are aggregated." + "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the gross Technical Margins multiplied by the weights coming from the Reinsurance Coverage Parameter (see [Data Node Parameters](../DataModel/DataStructure#data-node-parameters)). In case a GRIC has multiple GICs, then these weighted $TM$s are aggregated." ], "metadata": {} }, From fdbe77cf2c91a372e68e4c15852c65e9b32f1bc5 Mon Sep 17 00:00:00 2001 From: Sara Busato Date: Thu, 29 Sep 2022 08:26:10 +0200 Subject: [PATCH 03/38] fixed Opening re-import --- Import/ImportStorage.ipynb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb index c1d8ede4..557210ec 100644 --- a/Import/ImportStorage.ipynb +++ b/Import/ImportStorage.ipynb @@ -250,7 +250,7 @@ "\n //SetPartition to current Period", "\n await querySource.Partition.SetAsync(TargetPartition);", "\n ", - "\n if(primaryScope.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year == args.Year))", + "\n if(primaryScope.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year == args.Year) && ImportFormat != ImportFormats.Opening)", "\n openingIfrsVariables = openingIfrsVariables.Concat(await querySource.Query()", "\n .Where(iv => iv.Partition == TargetPartition && iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I)", "\n .Where(iv => primaryScope.Contains(iv.DataNode) && EstimateTypesByImportFormat[InputSource.Opening.ToString()].Contains(iv.EstimateType) || secondaryScope.Contains(iv.DataNode))", From 6adb68e3b94e649e8e4720098ef9d70414bcb974 Mon Sep 17 00:00:00 2001 From: nnikolopoulos <114566025+nnikolopoulos@users.noreply.github.com> Date: Fri, 30 Sep 2022 11:01:55 +0200 Subject: [PATCH 04/38] Rename "PvBase" to "PresentValue" (#32) --- Import/ImportScopeCalculation.ipynb | 58 +++++----- Test/SpecificationsImportCashflows.ipynb | 130 +++++++++++------------ Test/SpecificationsSetup.ipynb | 2 +- Test/SpecificationsTechnicalMargin.ipynb | 6 +- 4 files changed, 98 insertions(+), 98 deletions(-) diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index 2823aead..9370c157 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -896,15 +896,15 @@ "id": "NX2BdeLNxk2VWROO8E5pBg", "cell_type": "code", "source": [ - "public interface PvBase : IWithGetValueFromValues", + "public interface PresentValue : IWithGetValueFromValues", "\n{ ", "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", "\n || x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode))", - "\n .WithApplicability(x => (x.Identity.Id.AocType == AocTypes.BOP && x.Identity.Id.Novelty != Novelties.C) || x.Identity.Id.AocType == AocTypes.EOP)", + "\n .WithApplicability(x => (x.Identity.Id.AocType == AocTypes.BOP && x.Identity.Id.Novelty != Novelties.C) || x.Identity.Id.AocType == AocTypes.EOP)", "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.CF)", - "\n .WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.IA)", - "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.IA)", + "\n .WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.IA)", + "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.IA)", "\n .WithApplicability(x => new string[]{AocTypes.BOP, AocTypes.EA, AocTypes.AM, AocTypes.RCU}.Contains(x.Identity.Id.AocType) ) //add here combination CRU for At !CDR?", "\n );", "\n ", @@ -917,40 +917,40 @@ "\n public double Value => GetValueFromValues(Values);", "\n}", "\n", - "\npublic interface ComputePvBaseWithIfrsVariable : PvBase", + "\npublic interface ComputePresentValueWithIfrsVariable : PresentValue", "\n{", - "\n double PvBase.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.CalculationType, EconomicBasis, Identity.AccidentYear); //unify CalculationType and EstimateTypeGet", - "\n double[] PvBase.Values => Enumerable.Empty().ToArray();", + "\n double PresentValue.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.CalculationType, EconomicBasis, Identity.AccidentYear); //unify CalculationType and EstimateTypeGet", + "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", "\n}", "\n", - "\npublic interface PvBaseFromDiscountedCashflow : PvBase", + "\npublic interface PresentValueFromDiscountedCashflow : PresentValue", "\n{", "\n [NotVisible]", - "\n double[] PvBase.Values => GetScope(Identity).Values;", + "\n double[] PresentValue.Values => GetScope(Identity).Values;", "\n}", "\n", - "\npublic interface CashflowAocStep : PvBase", + "\npublic interface CashflowAocStep : PresentValue", "\n{", "\n [NotVisible]", - "\n double[] PvBase.Values => -1d * GetScope(Identity).Values;", + "\n double[] PresentValue.Values => -1d * GetScope(Identity).Values;", "\n}", "\n", - "\npublic interface PvBaseWithInterestAccretion : PvBase, IWithInterestAccretion", + "\npublic interface PresentValueWithInterestAccretion : PresentValue, IWithInterestAccretion", "\n{", "\n [NotVisible]", - "\n double[] PvBase.Values => GetInterestAccretion();", + "\n double[] PresentValue.Values => GetInterestAccretion();", "\n}", "\n", - "\npublic interface PvBaseWithInterestAccretionForCreditRisk : PvBase, IWithInterestAccretionForCreditRisk", + "\npublic interface PresentValueWithInterestAccretionForCreditRisk : PresentValue, IWithInterestAccretionForCreditRisk", "\n{", "\n [NotVisible]", - "\n double[] PvBase.Values => GetInterestAccretion();", + "\n double[] PresentValue.Values => GetInterestAccretion();", "\n}", "\n", - "\npublic interface EmptyValuesAocStep : PvBase", + "\npublic interface EmptyValuesAocStep : PresentValue", "\n{", "\n [NotVisible]", - "\n double[] PvBase.Values => Enumerable.Empty().ToArray();", + "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", "\n}" ], "metadata": {}, @@ -1014,9 +1014,9 @@ "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", "\n ", "\n [NotVisible]", - "\n PvBase[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", + "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", "\n .ToArray();", "\n double Value => PresentValues.Aggregate().Value;", "\n}", @@ -1032,9 +1032,9 @@ "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", "\n ", "\n [NotVisible]", - "\n PvBase[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", + "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", "\n .ToArray();", "\n ", "\n double Value => PresentValues.Aggregate().Value;", @@ -1079,7 +1079,7 @@ "\n ", "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", "\n ", - "\n PvBase[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray();", + "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray();", "\n ", "\n double Value => PresentValues.Aggregate().Value;", "\n}", @@ -1093,7 +1093,7 @@ "\n ", "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", "\n ", - "\n PvBase[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", "\n ", "\n double Value => PresentValues.Aggregate().Value;", "\n}" @@ -1580,12 +1580,12 @@ "\n string EstimateType => EstimateTypes.BEPA;", "\n string EconomicBasis => EconomicBases.L;", "\n ", - "\n PvBase[] ByAmountType => GetStorage().GetPremiums().Select(pr => GetStorage().GetPremiumAllocationFactor(Identity) * GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n PresentValue[] ByAmountType => GetStorage().GetPremiums().Select(pr => GetStorage().GetPremiumAllocationFactor(Identity) * GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis))).ToArray(); ", "\n}", "\n", "\npublic interface DefaultValueBeExperienceAdjustmentForPremium : BeExperienceAdjustmentForPremium", "\n{", - "\n PvBase[] BeExperienceAdjustmentForPremium.ByAmountType => Enumerable.Empty().ToArray();", + "\n PresentValue[] BeExperienceAdjustmentForPremium.ByAmountType => Enumerable.Empty().ToArray();", "\n}" ], "metadata": {}, @@ -1702,7 +1702,7 @@ "\n ", "\n double Value => GetScope(Identity.DataNode).BeAmountTypes", "\n .Except(GetStorage().GetNonAttributableAmountType())", - "\n .Sum(at => GetScope((Identity, at, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", + "\n .Sum(at => GetScope((Identity, at, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", "\n GetScope(Identity).Value;", "\n ", "\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values", @@ -1755,12 +1755,12 @@ "\n ", "\n private double attributableExpenseAndCommissions => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(d =>", "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, d, EstimateTypes.A, (int?)null)).Value);", "\n", "\n private double investmentClaims => GetStorage().GetInvestmentClaims().Sum(ic =>", "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.A, (int?)null)).Value - ", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.AA, (int?)null)).Value -", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.OA, (int?)null)).Value);", diff --git a/Test/SpecificationsImportCashflows.ipynb b/Test/SpecificationsImportCashflows.ipynb index ad03bfe5..27b2e084 100644 --- a/Test/SpecificationsImportCashflows.ipynb +++ b/Test/SpecificationsImportCashflows.ipynb @@ -1296,8 +1296,8 @@ "id": "-_jk2YKNT0u7l9uCTrc18w", "cell_type": "code", "source": [ - "var computedPvBaseBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseBoP_PR" + "var computedPresentValueBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueBoP_PR" ], "metadata": {}, "execution_count": 1, @@ -1326,7 +1326,7 @@ "id": "he2CNq7s20a2kIAEI1Ew5A", "cell_type": "code", "source": [ - "var expectedPvBaseBoP_PR = discountedBoP_PR.Values;" + "var expectedPresentValueBoP_PR = discountedBoP_PR.Values;" ], "metadata": {}, "execution_count": 1, @@ -1344,7 +1344,7 @@ "id": "E_a4AaUiYU-qVqiFMH4Ffg", "cell_type": "code", "source": [ - "computedPvBaseBoP_PR.Values.CheckEquality( expectedPvBaseBoP_PR )" + "computedPresentValueBoP_PR.Values.CheckEquality( expectedPresentValueBoP_PR )" ], "metadata": {}, "execution_count": 1, @@ -1354,7 +1354,7 @@ "id": "USXwqdZpmEOlDJdxqDBZaA", "cell_type": "code", "source": [ - "computedPvBaseBoP_PR.Values.CheckEquality( expectedPvBaseBoP_PR ).Should().Be(true);" + "computedPresentValueBoP_PR.Values.CheckEquality( expectedPresentValueBoP_PR ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -1392,8 +1392,8 @@ "id": "nvbs4pu8Sk-fnfw1MqBJEQ", "cell_type": "code", "source": [ - "var computedPvBaseMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseMC_PR" + "var computedPresentValueMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueMC_PR" ], "metadata": {}, "execution_count": 1, @@ -1432,7 +1432,7 @@ "id": "pqOSCzCTJEyNauxM07RTvg", "cell_type": "code", "source": [ - "var expectedPvBaseMC_PR = discountedMC_PR.Values - discountedBoP_PR.Values;" + "var expectedPresentValueMC_PR = discountedMC_PR.Values - discountedBoP_PR.Values;" ], "metadata": {}, "execution_count": 1, @@ -1450,7 +1450,7 @@ "id": "WOMu6tnVOEWiRZqaziMRcg", "cell_type": "code", "source": [ - "computedPvBaseMC_PR.Values.CheckEquality( expectedPvBaseMC_PR )" + "computedPresentValueMC_PR.Values.CheckEquality( expectedPresentValueMC_PR )" ], "metadata": {}, "execution_count": 1, @@ -1460,7 +1460,7 @@ "id": "TvZ78p6vLkCL-xejOqvUcw", "cell_type": "code", "source": [ - "computedPvBaseMC_PR.Value == expectedPvBaseMC_PR[0]" + "computedPresentValueMC_PR.Value == expectedPresentValueMC_PR[0]" ], "metadata": {}, "execution_count": 1, @@ -1470,7 +1470,7 @@ "id": "w9D4tVGk5UmDB-tTCeS5Rw", "cell_type": "code", "source": [ - "computedPvBaseMC_PR.Values.CheckEquality( expectedPvBaseMC_PR ).Should().Be(true);" + "computedPresentValueMC_PR.Values.CheckEquality( expectedPresentValueMC_PR ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -1480,7 +1480,7 @@ "id": "nnvwi_zKy0ebrac1nrqanQ", "cell_type": "code", "source": [ - "computedPvBaseMC_PR.Value.Should().Be( expectedPvBaseMC_PR[0] );" + "computedPresentValueMC_PR.Value.Should().Be( expectedPresentValueMC_PR[0] );" ], "metadata": {}, "execution_count": 1, @@ -1517,8 +1517,8 @@ "id": "5sLKCaklikuTAXBf9hAoGQ", "cell_type": "code", "source": [ - "var computedPvBaseCF_PR = Test.GetScope((idCF, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseCF_PR" + "var computedPresentValueCF_PR = Test.GetScope((idCF, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueCF_PR" ], "metadata": {}, "execution_count": 1, @@ -1558,7 +1558,7 @@ "id": "YSGvWpZAgk676PWkouVFvg", "cell_type": "code", "source": [ - "var expectedPvBaseCF_PR = -1.0 * cfNominalReference_PR.Values;" + "var expectedPresentValueCF_PR = -1.0 * cfNominalReference_PR.Values;" ], "metadata": {}, "execution_count": 1, @@ -1576,7 +1576,7 @@ "id": "mlrKZMMExkOXb_z-QA-nzQ", "cell_type": "code", "source": [ - "computedPvBaseCF_PR.Values.CheckEquality( expectedPvBaseCF_PR )" + "computedPresentValueCF_PR.Values.CheckEquality( expectedPresentValueCF_PR )" ], "metadata": {}, "execution_count": 1, @@ -1586,7 +1586,7 @@ "id": "_iXoBI2Ra06t95Lv-UKmdQ", "cell_type": "code", "source": [ - "computedPvBaseCF_PR.Values[0] + computedPvBaseCF_PR.Values[1] + computedPvBaseCF_PR.Values[2] == computedPvBaseCF_PR.Value" + "computedPresentValueCF_PR.Values[0] + computedPresentValueCF_PR.Values[1] + computedPresentValueCF_PR.Values[2] == computedPresentValueCF_PR.Value" ], "metadata": {}, "execution_count": 1, @@ -1596,7 +1596,7 @@ "id": "QWPx_7NUmEyE5Xu_kEeyjg", "cell_type": "code", "source": [ - "computedPvBaseCF_PR.Values.CheckEquality( expectedPvBaseCF_PR ).Should().Be(true);" + "computedPresentValueCF_PR.Values.CheckEquality( expectedPresentValueCF_PR ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -1606,7 +1606,7 @@ "id": "MSbSF0-9w0-iu_c3cNINjA", "cell_type": "code", "source": [ - "computedPvBaseCF_PR.Value.Should().Be( computedPvBaseCF_PR.Values[0] + computedPvBaseCF_PR.Values[1] + computedPvBaseCF_PR.Values[2] );" + "computedPresentValueCF_PR.Value.Should().Be( computedPresentValueCF_PR.Values[0] + computedPresentValueCF_PR.Values[1] + computedPresentValueCF_PR.Values[2] );" ], "metadata": {}, "execution_count": 1, @@ -1675,8 +1675,8 @@ "id": "ZiyHW9AJqEqeFgbYLv9FQA", "cell_type": "code", "source": [ - "var computedPvBaseIA_PR = Test.GetScope((idIA, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseIA_PR" + "var computedPresentValueIA_PR = Test.GetScope((idIA, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueIA_PR" ], "metadata": {}, "execution_count": 1, @@ -1738,7 +1738,7 @@ "id": "b-s6yRRvEUeLF_z6-rD7lw", "cell_type": "code", "source": [ - "var expectedPvBaseIA_PR = discountedIaReference_PR.Values.Select((val, index) => ( val - nominalIaReference_PR.Values[index]) * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" + "var expectedPresentValueIA_PR = discountedIaReference_PR.Values.Select((val, index) => ( val - nominalIaReference_PR.Values[index]) * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" ], "metadata": {}, "execution_count": 1, @@ -1756,7 +1756,7 @@ "id": "2R1QDTLoAkSYgN3VL0pXxg", "cell_type": "code", "source": [ - "computedPvBaseIA_PR.Values.CheckEquality( expectedPvBaseIA_PR )" + "computedPresentValueIA_PR.Values.CheckEquality( expectedPresentValueIA_PR )" ], "metadata": {}, "execution_count": 1, @@ -1766,7 +1766,7 @@ "id": "ioWKmAEOBk6ly7qdPm8UcQ", "cell_type": "code", "source": [ - "computedPvBaseIA_PR.Values[0] + computedPvBaseIA_PR.Values[1] + computedPvBaseIA_PR.Values[2] == computedPvBaseIA_PR.Value" + "computedPresentValueIA_PR.Values[0] + computedPresentValueIA_PR.Values[1] + computedPresentValueIA_PR.Values[2] == computedPresentValueIA_PR.Value" ], "metadata": {}, "execution_count": 1, @@ -1776,7 +1776,7 @@ "id": "lLcVd6QU_E-CV-zx6UKKyw", "cell_type": "code", "source": [ - "computedPvBaseIA_PR.Values.CheckEquality( expectedPvBaseIA_PR ).Should().Be(true);" + "computedPresentValueIA_PR.Values.CheckEquality( expectedPresentValueIA_PR ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -1786,7 +1786,7 @@ "id": "nksstSVXV0KMKV3s1Qzbjw", "cell_type": "code", "source": [ - "computedPvBaseIA_PR.Value.Should().Be( computedPvBaseIA_PR.Values[0] + computedPvBaseIA_PR.Values[1] + computedPvBaseIA_PR.Values[2] );" + "computedPresentValueIA_PR.Value.Should().Be( computedPresentValueIA_PR.Values[0] + computedPresentValueIA_PR.Values[1] + computedPresentValueIA_PR.Values[2] );" ], "metadata": {}, "execution_count": 1, @@ -1812,8 +1812,8 @@ "id": "1sPIRjZ290ekFi_RcQIo0g", "cell_type": "code", "source": [ - "var computedPvBaseIA_NIC = Test.GetScope((idIA, \"NIC\", \"BE\", (int?)null));", - "\ncomputedPvBaseIA_NIC" + "var computedPresentValueIA_NIC = Test.GetScope((idIA, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPresentValueIA_NIC" ], "metadata": {}, "execution_count": 1, @@ -1853,7 +1853,7 @@ "id": "CeJcWORR1USjRX0vRrD9uw", "cell_type": "code", "source": [ - "var expectedPvBaseIA_NIC = discountedIaReference_NIC.Values.Select((val, index) => val * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" + "var expectedPresentValueIA_NIC = discountedIaReference_NIC.Values.Select((val, index) => val * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" ], "metadata": {}, "execution_count": 1, @@ -1871,7 +1871,7 @@ "id": "hiB4BkoAvUWvG3yaH-lUgg", "cell_type": "code", "source": [ - "computedPvBaseIA_NIC.Values.CheckEquality( expectedPvBaseIA_NIC )" + "computedPresentValueIA_NIC.Values.CheckEquality( expectedPresentValueIA_NIC )" ], "metadata": {}, "execution_count": 1, @@ -1881,7 +1881,7 @@ "id": "FAOKIDlrpEiY95BXbRJ9Lg", "cell_type": "code", "source": [ - "computedPvBaseIA_NIC.Values[0] + computedPvBaseIA_NIC.Values[1] + computedPvBaseIA_NIC.Values[2] == computedPvBaseIA_NIC.Value" + "computedPresentValueIA_NIC.Values[0] + computedPresentValueIA_NIC.Values[1] + computedPresentValueIA_NIC.Values[2] == computedPresentValueIA_NIC.Value" ], "metadata": {}, "execution_count": 1, @@ -1891,7 +1891,7 @@ "id": "3XieKhmULE2hpsAGvEz6Jw", "cell_type": "code", "source": [ - "computedPvBaseIA_NIC.Values.CheckEquality( expectedPvBaseIA_NIC ).Should().Be(true);" + "computedPresentValueIA_NIC.Values.CheckEquality( expectedPresentValueIA_NIC ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -1901,7 +1901,7 @@ "id": "7eg7INUm50qXDWFveCVSJA", "cell_type": "code", "source": [ - "computedPvBaseIA_NIC.Value.Should().Be( computedPvBaseIA_NIC.Values[0] + computedPvBaseIA_NIC.Values[1] + computedPvBaseIA_NIC.Values[2] );" + "computedPresentValueIA_NIC.Value.Should().Be( computedPresentValueIA_NIC.Values[0] + computedPresentValueIA_NIC.Values[1] + computedPresentValueIA_NIC.Values[2] );" ], "metadata": {}, "execution_count": 1, @@ -1938,8 +1938,8 @@ "id": "ZtcMBnMzIkCuhjXxj25VQA", "cell_type": "code", "source": [ - "var computedPvBaseYCU_PR = Test.GetScope((idYcu, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseYCU_PR" + "var computedPresentValueYCU_PR = Test.GetScope((idYcu, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueYCU_PR" ], "metadata": {}, "execution_count": 1, @@ -2053,7 +2053,7 @@ "id": "-nB_BwXaFUSg1RGG9OtRWQ", "cell_type": "code", "source": [ - "var expectedPvBaseYCU_PR = ycReferenceDiscountedEop - discountedYcParent.Values;" + "var expectedPresentValueYCU_PR = ycReferenceDiscountedEop - discountedYcParent.Values;" ], "metadata": {}, "execution_count": 1, @@ -2063,7 +2063,7 @@ "id": "oqAvk5VK906PkRkAT2OaRg", "cell_type": "code", "source": [ - "computedPvBaseYCU_PR.Values.CheckEquality( expectedPvBaseYCU_PR )" + "computedPresentValueYCU_PR.Values.CheckEquality( expectedPresentValueYCU_PR )" ], "metadata": {}, "execution_count": 1, @@ -2073,7 +2073,7 @@ "id": "tUv9lq_VLEqCkXFKJJuQig", "cell_type": "code", "source": [ - "computedPvBaseYCU_PR.Value == expectedPvBaseYCU_PR[3]" + "computedPresentValueYCU_PR.Value == expectedPresentValueYCU_PR[3]" ], "metadata": {}, "execution_count": 1, @@ -2083,7 +2083,7 @@ "id": "m4ee2o2DZ0aKf2FH92STsw", "cell_type": "code", "source": [ - "computedPvBaseYCU_PR.Values.CheckEquality( expectedPvBaseYCU_PR ).Should().Be(true);" + "computedPresentValueYCU_PR.Values.CheckEquality( expectedPresentValueYCU_PR ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -2093,7 +2093,7 @@ "id": "kA0wrkGJaUG-mcZFz8IYPw", "cell_type": "code", "source": [ - "computedPvBaseYCU_PR.Value.Should().Be( expectedPvBaseYCU_PR[3] );" + "computedPresentValueYCU_PR.Value.Should().Be( expectedPresentValueYCU_PR[3] );" ], "metadata": {}, "execution_count": 1, @@ -2138,8 +2138,8 @@ "id": "77exgwl5wUefPwQGSvv_nA", "cell_type": "code", "source": [ - "var computedPvBaseCRU = Test.GetScope((idCru, \"CDR\", \"BE\", (int?)null));", - "\ncomputedPvBaseCRU" + "var computedPresentValueCRU = Test.GetScope((idCru, \"CDR\", \"BE\", (int?)null));", + "\ncomputedPresentValueCRU" ], "metadata": {}, "execution_count": 1, @@ -2280,7 +2280,7 @@ "id": "f8a9p87_WUCugmBsw0E4sA", "cell_type": "code", "source": [ - "var expectedPvBaseCRU = cruExpectedDiscountedCDR - discountedCruParent.Values;" + "var expectedPresentValueCRU = cruExpectedDiscountedCDR - discountedCruParent.Values;" ], "metadata": {}, "execution_count": 1, @@ -2290,7 +2290,7 @@ "id": "7odSeJ5RTUmTR32M-5tlAA", "cell_type": "code", "source": [ - "computedPvBaseCRU.Values.CheckEquality( expectedPvBaseCRU )" + "computedPresentValueCRU.Values.CheckEquality( expectedPresentValueCRU )" ], "metadata": {}, "execution_count": 1, @@ -2300,7 +2300,7 @@ "id": "ojtYz8I9xkaTA1AcV3U1Cw", "cell_type": "code", "source": [ - "computedPvBaseCRU.Value == expectedPvBaseCRU[3]" + "computedPresentValueCRU.Value == expectedPresentValueCRU[3]" ], "metadata": {}, "execution_count": 1, @@ -2310,7 +2310,7 @@ "id": "WH8Cl5EMp0ewbK4iQ7-W3A", "cell_type": "code", "source": [ - "computedPvBaseCRU.Values.CheckEquality( expectedPvBaseCRU ).Should().Be(true);" + "computedPresentValueCRU.Values.CheckEquality( expectedPresentValueCRU ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -2320,7 +2320,7 @@ "id": "-4irtBVO70uLS-mVjr-3jQ", "cell_type": "code", "source": [ - "computedPvBaseCRU.Value.Should().Be( expectedPvBaseCRU[3] );" + "computedPresentValueCRU.Value.Should().Be( expectedPresentValueCRU[3] );" ], "metadata": {}, "execution_count": 1, @@ -2357,8 +2357,8 @@ "id": "RxytwcSRIEOh4gnpLjM-6A", "cell_type": "code", "source": [ - "var computedPvBaseCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseCL_PR" + "var computedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueCL_PR" ], "metadata": {}, "execution_count": 1, @@ -2387,7 +2387,7 @@ "id": "o7Xu2o42K0SylUpXrn5bIw", "cell_type": "code", "source": [ - "var expectedPvBaseCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values -", + "var expectedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values -", "\n clParents.Select(aocStep => Test.GetScope((idCL with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, \"PR\", \"BE\", (int?)null)).Values).Aggregate();" ], "metadata": {}, @@ -2406,7 +2406,7 @@ "id": "mJ3zeyh3YUSL7myhsdowKg", "cell_type": "code", "source": [ - "computedPvBaseCL_PR.Values.CheckEquality( expectedPvBaseCL_PR )" + "computedPresentValueCL_PR.Values.CheckEquality( expectedPresentValueCL_PR )" ], "metadata": {}, "execution_count": 1, @@ -2416,7 +2416,7 @@ "id": "t8dZLcMcYEiQaGohNjbhbw", "cell_type": "code", "source": [ - "computedPvBaseCL_PR.Value == expectedPvBaseCL_PR[3]" + "computedPresentValueCL_PR.Value == expectedPresentValueCL_PR[3]" ], "metadata": {}, "execution_count": 1, @@ -2426,7 +2426,7 @@ "id": "CG2NuOh-OUWD0O9KjUlTKg", "cell_type": "code", "source": [ - "computedPvBaseCL_PR.Values.CheckEquality( expectedPvBaseCL_PR ).Should().Be(true);" + "computedPresentValueCL_PR.Values.CheckEquality( expectedPresentValueCL_PR ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -2436,7 +2436,7 @@ "id": "FNsLWW7W6UmZwW_agz-FbQ", "cell_type": "code", "source": [ - "computedPvBaseCL_PR.Value.Should().Be( expectedPvBaseCL_PR[3] );" + "computedPresentValueCL_PR.Value.Should().Be( expectedPresentValueCL_PR[3] );" ], "metadata": {}, "execution_count": 1, @@ -2473,8 +2473,8 @@ "id": "s86AHJ-4Pk6Va461mh5gBQ", "cell_type": "code", "source": [ - "var computedPvBaseEOP_NIC = Test.GetScope((idEOP, \"NIC\", \"BE\", (int?)null));", - "\ncomputedPvBaseEOP_NIC" + "var computedPresentValueEOP_NIC = Test.GetScope((idEOP, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPresentValueEOP_NIC" ], "metadata": {}, "execution_count": 1, @@ -2514,7 +2514,7 @@ "id": "TgfGcomxyEu_Bi31dr0a8Q", "cell_type": "code", "source": [ - "var expectedPvBaseEOP_NIC = discountedCL_NIC.Values;" + "var expectedPresentValueEOP_NIC = discountedCL_NIC.Values;" ], "metadata": {}, "execution_count": 1, @@ -2532,7 +2532,7 @@ "id": "uHz3FD5pz0KtlPWvehPSTw", "cell_type": "code", "source": [ - "computedPvBaseEOP_NIC.Values.CheckEquality( expectedPvBaseEOP_NIC )" + "computedPresentValueEOP_NIC.Values.CheckEquality( expectedPresentValueEOP_NIC )" ], "metadata": {}, "execution_count": 1, @@ -2542,7 +2542,7 @@ "id": "NgccZKROIUGyHphm6Pt3mA", "cell_type": "code", "source": [ - "computedPvBaseEOP_NIC.Value == expectedPvBaseEOP_NIC[3]" + "computedPresentValueEOP_NIC.Value == expectedPresentValueEOP_NIC[3]" ], "metadata": {}, "execution_count": 1, @@ -2552,7 +2552,7 @@ "id": "9jo2Z3ljfkyeYFEYk8YevQ", "cell_type": "code", "source": [ - "computedPvBaseEOP_NIC.Values.CheckEquality( expectedPvBaseEOP_NIC ).Should().Be(true);" + "computedPresentValueEOP_NIC.Values.CheckEquality( expectedPresentValueEOP_NIC ).Should().Be(true);" ], "metadata": {}, "execution_count": 1, @@ -2562,7 +2562,7 @@ "id": "wQEKDnBmiEiCcxaQ5z8n_Q", "cell_type": "code", "source": [ - "computedPvBaseEOP_NIC.Value.Should().Be( expectedPvBaseEOP_NIC[3] );" + "computedPresentValueEOP_NIC.Value.Should().Be( expectedPresentValueEOP_NIC[3] );" ], "metadata": {}, "execution_count": 1, @@ -2607,8 +2607,8 @@ "id": "Hbvbc_-ghkCPuBcY4CaNSw", "cell_type": "code", "source": [ - "var computedPvBaseAM_PR = Test.GetScope((idAM, \"PR\", \"BE\", (int?)null));", - "\ncomputedPvBaseAM_PR" + "var computedPresentValueAM_PR = Test.GetScope((idAM, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueAM_PR" ], "metadata": {}, "execution_count": 1, @@ -2618,8 +2618,8 @@ "id": "vtA_SwM1FkWUvn7cz_gsEg", "cell_type": "code", "source": [ - "var computedPvBaseAM_PR = Test.GetScope((idAM, \"NIC\", \"BE\", (int?)null));", - "\ncomputedPvBaseAM_PR" + "var computedPresentValueAM_PR = Test.GetScope((idAM, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPresentValueAM_PR" ], "metadata": {}, "execution_count": 1, diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb index 8fdfb7ae..96e7025a 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/Test/SpecificationsSetup.ipynb @@ -84,7 +84,7 @@ "\n", "\nstatic void ForEach(this IEnumerable self, Action action) => self.ToList().ForEach(action);", "\n", - "\npublic static IfrsVariable FromPvToIfrsVariable(this PvBase scope)", + "\npublic static IfrsVariable FromPvToIfrsVariable(this PresentValue scope)", "\n => new IfrsVariable{ EconomicBasis = scope.EconomicBasis, ", "\n EstimateType = scope.Identity.CalculationType, ", "\n DataNode = scope.Identity.Id.DataNode, ", diff --git a/Test/SpecificationsTechnicalMargin.ipynb b/Test/SpecificationsTechnicalMargin.ipynb index 7368b76c..5e35ce33 100644 --- a/Test/SpecificationsTechnicalMargin.ipynb +++ b/Test/SpecificationsTechnicalMargin.ipynb @@ -1223,7 +1223,7 @@ "cell_type": "code", "source": [ "var premiums = premiumAllocationFactor * Test.GetStorage().GetPremiums()", - "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.A, (int?)null)).Value)", "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.AA, (int?)null)).Value)", "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.OA, (int?)null)).Value)", @@ -1264,7 +1264,7 @@ "cell_type": "code", "source": [ "var attributableExpenseAndCommissions = new string[] {AmountTypes.ACA, AmountTypes.AEA}", - "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, EstimateTypes.A, (int?)null)).Value));" ], "metadata": {}, @@ -1302,7 +1302,7 @@ "cell_type": "code", "source": [ "var investmentClaims = Test.GetStorage().GetInvestmentClaims()", - "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.A, (int?)null)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.AA, (int?)null)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.OA, (int?)null)).Value)", From 2c0cc65cc062f69f6a23ab11118dfe5acaa2300f Mon Sep 17 00:00:00 2001 From: Sara Busato Date: Wed, 5 Oct 2022 17:01:21 +0200 Subject: [PATCH 05/38] include new default spaces --- Constants/Consts.ipynb | 660 +-- Constants/Enums.ipynb | 458 +- Constants/Validations.ipynb | 364 +- DataModel/DataStructure.ipynb | 3890 ++++++------- Database/Configure.ipynb | 218 +- Database/Schema Delete.ipynb | 144 +- Export/MapTemplate.ipynb | 578 +- Import/ImportResultPreview.ipynb | 590 +- Import/ImportScopeCalculation.ipynb | 4348 +++++++-------- Import/ImportStorage.ipynb | 752 ++- Import/Importers.ipynb | 2254 ++++---- .../InitSystemorphBaseToMemory.ipynb | 454 +- Initialization/InitSystemorphToDatabase.ipynb | 526 +- Initialization/InitSystemorphToMemory.ipynb | 242 +- InputFormatDescription.ipynb | 208 +- OverviewCalculationEngine.ipynb | 480 +- Report/ReportConfigurationAndUtils.ipynb | 268 +- Report/ReportScopes.ipynb | 1888 +++---- Report/ReportStorage.ipynb | 454 +- Report/Reports.ipynb | 900 ++- Test/AocStructureTest.ipynb | 1268 ++--- Test/ExportIfrsVariable.ipynb | 214 +- Test/ExportReportVariables.ipynb | 318 +- Test/IfrsVariablesTest.ipynb | 592 +- Test/ImportStorageTest.ipynb | 1298 ++--- Test/MapTemplateAndImportTest.ipynb | 1000 ++-- Test/QueriesTest.ipynb | 952 ++-- Test/ReportStorageTest.ipynb | 218 +- Test/ReportVariablesTest.ipynb | 434 +- Test/ReportVariablesTestBase.ipynb | 284 +- Test/SpecificationsFinancialPerformance.ipynb | 2872 ++++------ Test/SpecificationsImportActuals.ipynb | 1202 ++-- Test/SpecificationsImportCashflows.ipynb | 4892 +++++++---------- Test/SpecificationsSetup.ipynb | 256 +- Test/SpecificationsTechnicalMargin.ipynb | 4334 ++++++--------- Test/TechnicalMarginTest.ipynb | 558 +- Test/Tests.ipynb | 302 +- Utils/ApplicationMessage.ipynb | 260 +- Utils/UtilityMethods.ipynb | 2050 +++---- 39 files changed, 18759 insertions(+), 24221 deletions(-) diff --git a/Constants/Consts.ipynb b/Constants/Consts.ipynb index 21850a86..12992f46 100644 --- a/Constants/Consts.ipynb +++ b/Constants/Consts.ipynb @@ -1,386 +1,280 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "2kYu9e9ygUipdOuqA9Hk6A", - "cell_type": "markdown", - "source": [ - "

Consts

" - ], - "metadata": {} - }, - { - "id": "DmUpa-myfk6s7tnBoktcyw", - "cell_type": "markdown", - "source": [ - "# Numerical Precision" - ], - "metadata": {} - }, - { - "id": "KG3zmL2K_kGTNzWA2eQJvg", - "cell_type": "code", - "source": [ - "public const double Precision = 1E-5;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gMPLPUb7kUiJnLQWtEkkFA", - "cell_type": "code", - "source": [ - "public const double ProjectionPrecision = 1E-3;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gv0HnKTwuU--7Xo8e6UU2w", - "cell_type": "code", - "source": [ - "public const double BenchmarkPrecision = 1E-4;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gbuDd5t2Ike1Jq-lnVVIqg", - "cell_type": "markdown", - "source": [ - "# Time Period" - ], - "metadata": {} - }, - { - "id": "oX6yOw75DE-NwrYkdYTmzg", - "cell_type": "code", - "source": [ - "public const int CurrentPeriod = 0; " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2XFjLebnDEWBoNCyq6lKgg", - "cell_type": "code", - "source": [ - "public const int PreviousPeriod = -1; " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5ydvfd1abEm-CSTH-csz-g", - "cell_type": "code", - "source": [ - "public const int MonthInAYear = 12;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yhpv5BPDJUGKucF6Y_AVeQ", - "cell_type": "markdown", - "source": [ - "# Defaults" - ], - "metadata": {} - }, - { - "id": "uOfb6nvi8USI3mPOH8YvwQ", - "cell_type": "code", - "source": [ - "public const int DefaultDataNodeActivationMonth = 1;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZU5IN71RqEmHfRQSSCUvnw", - "cell_type": "code", - "source": [ - "public const double DefaultPremiumExperienceAdjustmentFactor = 1.0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KNUzhe58B0GBnCuZD1ATOg", - "cell_type": "markdown", - "source": [ - "# Names" - ], - "metadata": {} - }, - { - "id": "hZGPPDopiECnoXlB48cB2Q", - "cell_type": "code", - "source": [ - "public const string Main = nameof(Main);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "w5Zs2AGjxkWgRQfAGs8BIA", - "cell_type": "code", - "source": [ - "public const string Default = nameof(Default);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jAyhudwOJkmsPwMaZM1P4g", - "cell_type": "code", - "source": [ - "public const string ValueType = nameof(ValueType);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Aj_qnZxiqUeFHk088tNruA", - "cell_type": "markdown", - "source": [ - "GroupCurrency defines the SystemName (from Currency Dimension) to be used as the Group Currency." - ], - "metadata": {} - }, - { - "id": "pvlhKSXdW0Wt3dns45SWfQ", - "cell_type": "code", - "source": [ - "public const string GroupCurrency = \"CHF\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9SCJFj6zcUK_5Uczpicjjw", - "cell_type": "markdown", - "source": [ - "# Import Formats" - ], - "metadata": {} - }, - { - "id": "xEDrrk_AxUicpKHTSr6acA", - "cell_type": "code", - "source": [ - "public static class ImportFormats{", - "\n public const string Cashflow = nameof(Cashflow);", - "\n public const string Actual = nameof(Actual);", - "\n public const string DataNodeParameter = nameof(DataNodeParameter);", - "\n public const string SimpleValue = nameof(SimpleValue);", - "\n public const string Opening = nameof(Opening);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DQHpY4V8xUOGR8L84B7DTg", - "cell_type": "markdown", - "source": [ - "# IFRS specific" - ], - "metadata": {} - }, - { - "id": "YjgOf6OCyUuxcwR9IhoZvA", - "cell_type": "code", - "source": [ - "public static class ValuationApproaches{", - "\n public const string BBA = nameof(BBA); //Building Block Approach", - "\n public const string VFA = nameof(VFA); //Variable Fee Approach", - "\n public const string PAA = nameof(PAA); //Premium Allocation Approach", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pMhVfzvrjkyXcNpx0Tn4wA", - "cell_type": "code", - "source": [ - "public static class LiabilityTypes{", - "\n public const string LRC = nameof(LRC); //Liability for Remaining Coverage", - "\n public const string LIC = nameof(LIC); //Liability Incurred Claims", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1eDEjgoZmEOfPbRzZthlTQ", - "cell_type": "code", - "source": [ - "public static class CalculationTypes{", - "\n public const string BE = nameof(BE); //Best Estimate", - "\n public const string CU = nameof(CU); //Coverage Units", - "\n public const string RA = nameof(RA); //Risk Adjustment", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "b6cmqzNyQ0q0McHf-Rf5lw", - "cell_type": "code", - "source": [ - "public static class EstimateTypes{", - "\n public const string BE = nameof(BE); //Best Estimate", - "\n public const string RA = nameof(RA); //Risk Adjustment", - "\n public const string A = nameof(A); //Actuals", - "\n public const string AA = nameof(AA); //Advance Actuals", - "\n public const string OA = nameof(OA); //Overdue Actuals", - "\n public const string DA = nameof(DA); //Deferrable Actuals", - "\n public const string C = nameof(C); //Contractual Service Margin", - "\n public const string L = nameof(L); //Loss Component", - "\n public const string LR = nameof(LR); //Loss Recovery", - "\n public const string F = nameof(F); //factors", - "\n public const string FCF = nameof(FCF); //Fulfilment Cash flows", - "\n public const string BEPA = nameof(BEPA); //Experience Adjusted BE Premium to Csm", - "\n public const string APA = nameof(APA); //Experience Adjusted Written Actual Premium to Csm", - "\n public const string AAPA = nameof(AAPA); //Experience Adjusted Advance Actual Premium to Csm", - "\n public const string OAPA = nameof(OAPA); //Experience Adjusted Overdue Actual Premium to Csm", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vCJNvDF6D02HPepD8ay2pA", - "cell_type": "code", - "source": [ - "public static class AocTypes{", - "\n public const string BOP = nameof(BOP);", - "\n public const string MC = nameof(MC);", - "\n public const string RCU = nameof(RCU);", - "\n public const string CF = nameof(CF);", - "\n public const string IA = nameof(IA);", - "\n public const string YCU = nameof(YCU);", - "\n public const string CRU = nameof(CRU);", - "\n public const string WO = nameof(WO);", - "\n public const string EV = nameof(EV);", - "\n public const string CL = nameof(CL);", - "\n public const string EA = nameof(EA);", - "\n public const string AM = nameof(AM);", - "\n public const string FX = nameof(FX);", - "\n public const string EOP = nameof(EOP);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OE45Je2KUk6WlHo9upd5fA", - "cell_type": "code", - "source": [ - "public static class Novelties{", - "\n public const string I = nameof(I); //In-Force", - "\n public const string N = nameof(N); //New Business", - "\n public const string C = nameof(C); //All Novelties Combined", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BUPmJSTjdkuP8nR7MJyQiw", - "cell_type": "code", - "source": [ - "public static class EconomicBases{", - "\n public const string L = nameof(L); //Locked Interest Rates", - "\n public const string C = nameof(C); //Current Interest Rates", - "\n public const string N = nameof(N); //Nominal Interest Rates", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-cRhXT5tKE-834Umpyaudw", - "cell_type": "code", - "source": [ - "public static class AmountTypes{", - "\n public const string ACA = nameof(ACA); //Attributable Commissions Acquisition", - "\n public const string AEA = nameof(AEA); //Attributable Expenses Acquisition", - "\n public const string CDR = nameof(CDR); //Credit Default Risk", - "\n public const string CL = nameof(CL); //Claims", - "\n public const string PR = nameof(PR); //Premiums", - "\n public const string NIC = nameof(NIC); //Claims Non-Investment component", - "\n public const string ICO = nameof(ICO); //Claims Investment component", - "\n public const string NE = nameof(NE); //Non Attributable Expenses", - "\n public const string ACM = nameof(ACM); //Attributable Commissions Maintenance", - "\n public const string AEM = nameof(AEM); //Attributable Expenses Maintenance", - "\n public const string AC = nameof(AC); //Attributable Commissions", - "\n public const string AE = nameof(AE); //Attributable Expenses", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "e33hFwGm9kmVNOsShmvn4w", - "cell_type": "markdown", - "source": [ - "# Insurance specific" - ], - "metadata": {} - }, - { - "id": "9n2de6iCUEKECrkoUtSuiw", - "cell_type": "code", - "source": [ - "public static class LineOfBusinesses{", - "\n public const string LI = nameof(LI); //Life", - "\n public const string NL = nameof(NL); //Non-Life", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Consts

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Numerical Precision" + ] + }, + { + "cell_type": "code", + "source": [ + "public const double Precision = 1E-5;" + ] + }, + { + "cell_type": "code", + "source": [ + "public const double ProjectionPrecision = 1E-3;" + ] + }, + { + "cell_type": "code", + "source": [ + "public const double BenchmarkPrecision = 1E-4;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Time Period" + ] + }, + { + "cell_type": "code", + "source": [ + "public const int CurrentPeriod = 0; " + ] + }, + { + "cell_type": "code", + "source": [ + "public const int PreviousPeriod = -1; " + ] + }, + { + "cell_type": "code", + "source": [ + "public const int MonthInAYear = 12;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Defaults" + ] + }, + { + "cell_type": "code", + "source": [ + "public const int DefaultDataNodeActivationMonth = 1;" + ] + }, + { + "cell_type": "code", + "source": [ + "public const double DefaultPremiumExperienceAdjustmentFactor = 1.0;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Names" + ] + }, + { + "cell_type": "code", + "source": [ + "public const string Main = nameof(Main);" + ] + }, + { + "cell_type": "code", + "source": [ + "public const string Default = nameof(Default);" + ] + }, + { + "cell_type": "code", + "source": [ + "public const string ValueType = nameof(ValueType);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "GroupCurrency defines the SystemName (from Currency Dimension) to be used as the Group Currency." + ] + }, + { + "cell_type": "code", + "source": [ + "public const string GroupCurrency = \"CHF\";" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Formats" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class ImportFormats{", + "\n public const string Cashflow = nameof(Cashflow);", + "\n public const string Actual = nameof(Actual);", + "\n public const string DataNodeParameter = nameof(DataNodeParameter);", + "\n public const string SimpleValue = nameof(SimpleValue);", + "\n public const string Opening = nameof(Opening);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# IFRS specific" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class ValuationApproaches{", + "\n public const string BBA = nameof(BBA); //Building Block Approach", + "\n public const string VFA = nameof(VFA); //Variable Fee Approach", + "\n public const string PAA = nameof(PAA); //Premium Allocation Approach", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class LiabilityTypes{", + "\n public const string LRC = nameof(LRC); //Liability for Remaining Coverage", + "\n public const string LIC = nameof(LIC); //Liability Incurred Claims", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class CalculationTypes{", + "\n public const string BE = nameof(BE); //Best Estimate", + "\n public const string CU = nameof(CU); //Coverage Units", + "\n public const string RA = nameof(RA); //Risk Adjustment", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class EstimateTypes{", + "\n public const string BE = nameof(BE); //Best Estimate", + "\n public const string RA = nameof(RA); //Risk Adjustment", + "\n public const string A = nameof(A); //Actuals", + "\n public const string AA = nameof(AA); //Advance Actuals", + "\n public const string OA = nameof(OA); //Overdue Actuals", + "\n public const string DA = nameof(DA); //Deferrable Actuals", + "\n public const string C = nameof(C); //Contractual Service Margin", + "\n public const string L = nameof(L); //Loss Component", + "\n public const string LR = nameof(LR); //Loss Recovery", + "\n public const string F = nameof(F); //factors", + "\n public const string FCF = nameof(FCF); //Fulfilment Cash flows", + "\n public const string BEPA = nameof(BEPA); //Experience Adjusted BE Premium to Csm", + "\n public const string APA = nameof(APA); //Experience Adjusted Written Actual Premium to Csm", + "\n public const string AAPA = nameof(AAPA); //Experience Adjusted Advance Actual Premium to Csm", + "\n public const string OAPA = nameof(OAPA); //Experience Adjusted Overdue Actual Premium to Csm", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class AocTypes{", + "\n public const string BOP = nameof(BOP);", + "\n public const string MC = nameof(MC);", + "\n public const string RCU = nameof(RCU);", + "\n public const string CF = nameof(CF);", + "\n public const string IA = nameof(IA);", + "\n public const string YCU = nameof(YCU);", + "\n public const string CRU = nameof(CRU);", + "\n public const string WO = nameof(WO);", + "\n public const string EV = nameof(EV);", + "\n public const string CL = nameof(CL);", + "\n public const string EA = nameof(EA);", + "\n public const string AM = nameof(AM);", + "\n public const string FX = nameof(FX);", + "\n public const string EOP = nameof(EOP);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class Novelties{", + "\n public const string I = nameof(I); //In-Force", + "\n public const string N = nameof(N); //New Business", + "\n public const string C = nameof(C); //All Novelties Combined", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class EconomicBases{", + "\n public const string L = nameof(L); //Locked Interest Rates", + "\n public const string C = nameof(C); //Current Interest Rates", + "\n public const string N = nameof(N); //Nominal Interest Rates", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class AmountTypes{", + "\n public const string ACA = nameof(ACA); //Attributable Commissions Acquisition", + "\n public const string AEA = nameof(AEA); //Attributable Expenses Acquisition", + "\n public const string CDR = nameof(CDR); //Credit Default Risk", + "\n public const string CL = nameof(CL); //Claims", + "\n public const string PR = nameof(PR); //Premiums", + "\n public const string NIC = nameof(NIC); //Claims Non-Investment component", + "\n public const string ICO = nameof(ICO); //Claims Investment component", + "\n public const string NE = nameof(NE); //Non Attributable Expenses", + "\n public const string ACM = nameof(ACM); //Attributable Commissions Maintenance", + "\n public const string AEM = nameof(AEM); //Attributable Expenses Maintenance", + "\n public const string AC = nameof(AC); //Attributable Commissions", + "\n public const string AE = nameof(AE); //Attributable Expenses", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Insurance specific" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class LineOfBusinesses{", + "\n public const string LI = nameof(LI); //Life", + "\n public const string NL = nameof(NL); //Non-Life", + "\n}" + ] + } + ] } \ No newline at end of file diff --git a/Constants/Enums.ipynb b/Constants/Enums.ipynb index 5700a892..63b1b56f 100644 --- a/Constants/Enums.ipynb +++ b/Constants/Enums.ipynb @@ -1,269 +1,193 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "HUFgBXkmYU6rV0daYBo-nQ", - "cell_type": "markdown", - "source": [ - "# Enumerables", - "\n", - "\nIn the case of data which is not expected to change over time, it is convenient to introduce such data as variables of type \"enumerable\"." - ], - "metadata": {} - }, - { - "id": "ALWeaAkPh0uiwQ9SYb9Y-w", - "cell_type": "markdown", - "source": [ - "## Exchange Rates", - "\n", - "\nFor exchange rates, we set the type for which the rates apply:" - ], - "metadata": {} - }, - { - "id": "W6x_0Pa3_kOAd3N9CBgcgQ", - "cell_type": "code", - "source": [ - "public enum FxType { Spot, Average }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "r50zPe2AP0KrCOR-fgpccg", - "cell_type": "code", - "source": [ - "public enum FxPeriod { NotApplicable, BeginningOfPeriod, Average, EndOfPeriod }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YCF3tVHQB0eUa0yWpiRD0g", - "cell_type": "markdown", - "source": [ - "## Currency Types" - ], - "metadata": {} - }, - { - "id": "cF0fRptcGE64Vr1b058rqg", - "cell_type": "markdown", - "source": [ - "Currency Types define which currency is used as standard at different aggregation levels (in the Data Level hierarchy).", - "\n- Functional: this is the standard Currency Type at Reporting Node level", - "\n- Group: this is the standard Currency Type at Group level", - "\n- Contractual: this is the standard Currency Type at Data Node level", - "\n- Transactional: this is the standard Currency Type at Transactional level (used typically for Actuals)" - ], - "metadata": {} - }, - { - "id": "zj07LR0PT0CesH4nRl1Sig", - "cell_type": "code", - "source": [ - "public enum CurrencyType { Functional, Group, Contractual, Transactional }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wL17I9jyQ0eaeXrSdlvJyA", - "cell_type": "markdown", - "source": [ - "## Period Type" - ], - "metadata": {} - }, - { - "id": "3e3wVNw-rECnTHBTkVOfCQ", - "cell_type": "code", - "source": [ - "public enum PeriodType { NotApplicable, BeginningOfPeriod, EndOfPeriod }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Expd7Urm102om6-y2Skz4w", - "cell_type": "markdown", - "source": [ - "## Valuation Period" - ], - "metadata": {} - }, - { - "id": "dsJwHWIQPkOB29dEUCLHGg", - "cell_type": "code", - "source": [ - "public enum ValuationPeriod { NotApplicable, BeginningOfPeriod, MidOfPeriod, Delta, EndOfPeriod }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iejG0G0VJ0q_tAg2HGHuOw", - "cell_type": "markdown", - "source": [ - "## Portfolio View" - ], - "metadata": {} - }, - { - "id": "0Pdzxbnsx0SOaIiUb_X1YQ", - "cell_type": "code", - "source": [ - "[Flags] public enum PortfolioView { Gross = 1, Reinsurance = 2, Net = Gross | Reinsurance }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "v7NVqB0p1Ei4vilTCiErFg", - "cell_type": "markdown", - "source": [ - "## Structure Type" - ], - "metadata": {} - }, - { - "id": "Kge1fD31n0S7BW0EiClT0g", - "cell_type": "code", - "source": [ - "public enum StructureType { None, AoC }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "S49a3Gcz_0S7apcSmQy3JA", - "cell_type": "markdown", - "source": [ - "## State" - ], - "metadata": {} - }, - { - "id": "mJADknA9Q0KQjmTmf03Blw", - "cell_type": "markdown", - "source": [ - "State describes the state in which a Data Node can be - There are two types of states:", - "\n- Active: visible in reports and queries", - "\n- Inactive: not visible in reports and queries" - ], - "metadata": {} - }, - { - "id": "lsRYxseYzUaLMcAn7JB2Qw", - "cell_type": "code", - "source": [ - "public enum State { Active, Inactive }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kgMLZfJ4PkCFRU4kLKSGcw", - "cell_type": "markdown", - "source": [ - "## Periodicity" - ], - "metadata": {} - }, - { - "id": "iV_fcqBE2E6B12CgJq2ybg", - "cell_type": "code", - "source": [ - "public enum Periodicity { Monthly, Quarterly, Yearly }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ndV2D2lQL0icIY9VirJweQ", - "cell_type": "markdown", - "source": [ - "## Input Source" - ], - "metadata": {} - }, - { - "id": "z6t0m-civUGAcBEAW0C3Nw", - "cell_type": "code", - "source": [ - "[Flags]", - "\npublic enum InputSource {NotApplicable = 0, Opening = 1, Actual = 2, Cashflow = 4} ", - "\n//Opening + Actual = 3,", - "\n//Opening + Cashflow = 5", - "\n//Actual + Cashflow = 6", - "\n//Opening + Actual + Cashflow = 7" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "aEqUAtvxPESgt-FHx2e7yA", - "cell_type": "markdown", - "source": [ - "## Data Type" - ], - "metadata": {} - }, - { - "id": "LR7R7DUA0k6Ywl5WjSrEvg", - "cell_type": "code", - "source": [ - "public enum DataType { Optional, Mandatory, Calculated, CalculatedTelescopic }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "euBhm6zy1Uib521-G3w3eQ", - "cell_type": "markdown", - "source": [ - "## Import Scope" - ], - "metadata": {} - }, - { - "id": "4PP7M-Sv9k6_6MsJWS1bUg", - "cell_type": "code", - "source": [ - "public enum ImportScope { Primary, Secondary }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Enumerables", + "\n", + "\nIn the case of data which is not expected to change over time, it is convenient to introduce such data as variables of type \"enumerable\"." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Exchange Rates", + "\n", + "\nFor exchange rates, we set the type for which the rates apply:" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum FxType { Spot, Average }" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum FxPeriod { NotApplicable, BeginningOfPeriod, Average, EndOfPeriod }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Currency Types" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Currency Types define which currency is used as standard at different aggregation levels (in the Data Level hierarchy).", + "\n- Functional: this is the standard Currency Type at Reporting Node level", + "\n- Group: this is the standard Currency Type at Group level", + "\n- Contractual: this is the standard Currency Type at Data Node level", + "\n- Transactional: this is the standard Currency Type at Transactional level (used typically for Actuals)" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum CurrencyType { Functional, Group, Contractual, Transactional }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Period Type" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum PeriodType { NotApplicable, BeginningOfPeriod, EndOfPeriod }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Valuation Period" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum ValuationPeriod { NotApplicable, BeginningOfPeriod, MidOfPeriod, Delta, EndOfPeriod }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Portfolio View" + ] + }, + { + "cell_type": "code", + "source": [ + "[Flags] public enum PortfolioView { Gross = 1, Reinsurance = 2, Net = Gross | Reinsurance }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Structure Type" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum StructureType { None, AoC }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## State" + ] + }, + { + "cell_type": "markdown", + "source": [ + "State describes the state in which a Data Node can be - There are two types of states:", + "\n- Active: visible in reports and queries", + "\n- Inactive: not visible in reports and queries" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum State { Active, Inactive }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Periodicity" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum Periodicity { Monthly, Quarterly, Yearly }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Input Source" + ] + }, + { + "cell_type": "code", + "source": [ + "[Flags]", + "\npublic enum InputSource {NotApplicable = 0, Opening = 1, Actual = 2, Cashflow = 4} ", + "\n//Opening + Actual = 3,", + "\n//Opening + Cashflow = 5", + "\n//Actual + Cashflow = 6", + "\n//Opening + Actual + Cashflow = 7" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Type" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum DataType { Optional, Mandatory, Calculated, CalculatedTelescopic }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Import Scope" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum ImportScope { Primary, Secondary }" + ] + } + ] } \ No newline at end of file diff --git a/Constants/Validations.ipynb b/Constants/Validations.ipynb index f58110a8..18f30a6f 100644 --- a/Constants/Validations.ipynb +++ b/Constants/Validations.ipynb @@ -1,200 +1,170 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "LgEd-jVnbEGK9QI-QWcVQw", - "cell_type": "markdown", - "source": [ - "

Errors and Warnings

" - ], - "metadata": {} - }, - { - "id": "-scbNYag2kmx_38hEmkBgA", - "cell_type": "code", - "source": [ - "#!import \"Enums\"", - "\n#!import \"Consts\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8xjDwqEVm0WjJuTlC2QERA", - "cell_type": "markdown", - "source": [ - "# Codes" - ], - "metadata": {} - }, - { - "id": "9CPbuC0YV0aSt5wA3uOxnw", - "cell_type": "code", - "source": [ - "public enum Warning {", - "\n // Import", - "\n ActiveDataNodeWithCashflowBOPI,", - "\n // Default", - "\n Generic", - "\n}; " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QWAQV2xUcEigl3eydHTJaA", - "cell_type": "code", - "source": [ - "public enum Error { ", - "\n // Import", - "\n NoMainTab, IncompleteMainTab, ParsingScientificNotation, ValueTypeNotFound, ValueTypeNotValid, AocTypeNotValid,", - "\n // Partition", - "\n PartitionNotFound, ParsedPartitionNotFound, PartititionNameNotFound, PartitionTypeNotFound,", - "\n // Dimensions", - "\n AmountTypeNotFound, EstimateTypeNotFound,CalculationTypeNotFound, ReportingNodeNotFound, AocTypeMapNotFound, AocTypeNotFound, PortfolioGicNotFound, PortfolioGricNotFound, ", - "\n InvalidAmountTypeEstimateType, MultipleTechnicalMarginOpening,", - "\n // Exchange Rate", - "\n ExchangeRateNotFound, ExchangeRateCurrency,", - "\n // Data Note State", - "\n ChangeDataNodeState, InactiveDataNodeState,", - "\n // Parameters", - "\n ReinsuranceCoverageDataNode, DuplicateInterDataNode, DuplicateSingleDataNode, InvalidDataNode, ", - "\n // Storage", - "\n DataNodeNotFound, PartnerNotFound, RatingNotFound, CreditDefaultRateNotFound, MissingPremiumAllocation, ReinsuranceCoverage, ", - "\n YieldCurveNotFound, YieldCurvePeriodNotApplicable, EconomicBasisNotFound, AccountingVariableTypeNotFound,", - "\n // Scopes", - "\n NotSupportedAocStepReference, MultipleEoP,", - "\n // Data completeness", - "\n MissingDataAtPosting, MissingCombinedLiability, MissingCoverageUnit, ", - "\n // Default", - "\n Generic", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ThPESGETMUm31fuq-qS4_w", - "cell_type": "markdown", - "source": [ - "# Messages" - ], - "metadata": {} - }, - { - "id": "x3UlljewwEut3M0NRlUDDg", - "cell_type": "code", - "source": [ - "public static string Get (Error e, params string[] s) => (e, s.Length) switch ", - "\n{", - "\n // Import", - "\n (Error.NoMainTab , _) => $\"No Main tab in the parsed file.\",", - "\n (Error.IncompleteMainTab , _) => $\"Incomplete Main tab in the parsed file.\",", - "\n (Error.ParsingScientificNotation , 1) => $\"While parsing found real number in scientific notation: {s[0]}.\",", - "\n (Error.ValueTypeNotFound , _) => $\"Value Type not found.\",", - "\n (Error.ValueTypeNotValid , 1) => $\"The Value Type {s[0]} is invalid.\",", - "\n (Error.AocTypeNotValid , 1) => $\"The parsed AocType {s[0]} is invalid.\",", - "\n // Partition", - "\n (Error.PartitionNotFound , _) => $\"Partition do not found.\",", - "\n (Error.ParsedPartitionNotFound , 1) => $\"Parsed partition not available: ReportingNode {s[0]}.\",", - "\n (Error.ParsedPartitionNotFound , 4) => $\"Parsed partition not available: ReportingNode {s[0]}, Year {s[1]}, Month {s[2]}, Scenario {s[3]}.\",", - "\n (Error.PartitionTypeNotFound , 1) => $\"Partition type not found: {s[0]}.\",", - "\n // Dimensions", - "\n (Error.AmountTypeNotFound , 1) => $\"AmountType {s[0]} not found.\",", - "\n (Error.EstimateTypeNotFound , 1) => $\"EstimateType {s[0]} not found.\",", - "\n (Error.CalculationTypeNotFound , 1) => $\"CalculationType {s[0]} not found.\",", - "\n (Error.ReportingNodeNotFound , 1) => $\"Reporting Node {s[0]} not found.\",", - "\n (Error.AocTypeNotFound , 1) => $\"AocType {s[0]} not found.\",", - "\n (Error.AocTypeMapNotFound , 2) => $\"AocType {s[0]} and Novelty {s[1]} combination not defined in the mapping.\",", - "\n (Error.PortfolioGicNotFound , 2) => $\"Portfolio {s[0]} assigned to Group of Insurance Contract {s[1]} does not exist.\",", - "\n (Error.PortfolioGricNotFound , 2) => $\"Portfolio {s[0]} assigned to Group of Reinsurance Contract {s[1]} does not exist.\",", - "\n (Error.InvalidAmountTypeEstimateType , 2) => $\"Invalid combination of EstimateType {s[0]} and AmountType {s[1]}.\",", - "\n (Error.MultipleTechnicalMarginOpening , 1) => $\"Multiple opening for techincal margin are not allowed for DataNode {s[0]}.\",", - "\n // Exchange Rate", - "\n (Error.ExchangeRateNotFound , 2) => $\"Exchange Rate for {s[0]} {s[1]} is not present.\",", - "\n (Error.ExchangeRateCurrency , 1) => $\"{s[0]} does not have any Exchange Rate defined.\", ", - "\n // Data Node State", - "\n (Error.ChangeDataNodeState , 0) => $\"Data Node State can not change from Inactive state into Active state.\",", - "\n (Error.ChangeDataNodeState , 1) => $\"Data Node State for {s[0]} can not change from Inactive state into Active state.\",", - "\n (Error.ChangeDataNodeState , 3) => $\"Data Node State for {s[0]} can not change from {s[1]} state into {s[2]} state.\",", - "\n (Error.InactiveDataNodeState , 1) => $\"Data imported for inactive Data Node {s[0]}.\",", - "\n //Parameters", - "\n (Error.ReinsuranceCoverageDataNode , 2) => $\"Invalid Reinsurance Coverage parameter does not link a GroupOfReinsuranceContract to a GroupOfInsuranceContract. Provided GroupOfContracts are: {s[0]}, {s[1]}.\",", - "\n (Error.DuplicateInterDataNode , 2) => $\"Duplicated Inter-DataNode parameter for {s[0]}-{s[1]} is found.\",", - "\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 // Storage", - "\n (Error.DataNodeNotFound , 1) => $\"DataNode {s[0]} not found.\",", - "\n (Error.PartnerNotFound , 1) => $\"Partner not found for DataNode {s[0]}.\",", - "\n (Error.RatingNotFound , 1) => $\"Rating not found for Partner {s[0]}.\",", - "\n (Error.CreditDefaultRateNotFound , 1) => $\"Credit Default Rate not found for rating {s[0]}.\",", - "\n (Error.MissingPremiumAllocation , 1) => $\"Premium Allocation Rate not found for Group of Contract {s[0]}.\", // TODO: this is now a warning to be produced by a validation in the importers (default is 1)", - "\n (Error.ReinsuranceCoverage , 1) => $\"Reinsurance Allocation Rate not found for Group of Insurance Contract {s[0]}.\",", - "\n (Error.YieldCurveNotFound , 3) => $\"Yield Curve not found for currency {s[0]}, year {s[1]}, and month {s[2]}.\",", - "\n (Error.YieldCurvePeriodNotApplicable , 2) => $\"YieldCurve period NotApplicable not valid for AocStep with AocType {s[0]} and Novelty {s[1]}.\",", - "\n (Error.EconomicBasisNotFound , 1) => $\"EconomicBasis not valid for DataNode {s[0]}.\",", - "\n (Error.AccountingVariableTypeNotFound , 1) => $\"AccountingVariableType {s[0]} not found.\",", - "\n // Scopes", - "\n (Error.NotSupportedAocStepReference , 1) => $\"Unsupported reference Aoc Step for Aoc Type {s[0]}.\",", - "\n (Error.MultipleEoP , 0) => $\"Closing Balance for both Csm and Lc are computed.\",", - "\n // Data Completeness", - "\n (Error.MissingDataAtPosting , 1) => $\"Missing imported data for {s[0]} DataNode.\",", - "\n (Error.MissingCombinedLiability , 2) => $\"Missing Combined Liability Aoc Type for DataNode {s[0]} and AmountType {s[1]}.\",", - "\n (Error.MissingCoverageUnit , 1) => $\"Missing Coverage Unit cash flow for {s[0]} DataNode.\",", - "\n // Default", - "\n (Error.Generic , _) => $\"{s[0]}\",", - "\n (_ , _) => $\"Error not found.\"", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "PnguuqruSkaTERChlORdKw", - "cell_type": "code", - "source": [ - "public static string Get (Warning w, params string[] s) => (w, s.Length) switch {", - "\n // Import", - "\n (Warning.ActiveDataNodeWithCashflowBOPI , _) => $\"Cashflows for active DataNode has been parsed with AocType {AocTypes.BOP} and Novelty {Novelties.I} \",", - "\n // Default", - "\n (Warning.Generic , _) => $\"{s[0]}\",", - "\n (_ , _) => $\"Warning not found.\"", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "COxOqdqYwUqx0ozqRQof0w", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Errors and Warnings

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"Enums\"", + "\n#!import \"Consts\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Codes" + ] + }, + { + "cell_type": "code", + "source": [ + "public enum Warning {", + "\n // Import", + "\n ActiveDataNodeWithCashflowBOPI,", + "\n // Default", + "\n Generic", + "\n}; " + ] + }, + { + "cell_type": "code", + "source": [ + "public enum Error { ", + "\n // Import", + "\n NoMainTab, IncompleteMainTab, ParsingScientificNotation, ValueTypeNotFound, ValueTypeNotValid, AocTypeNotValid,", + "\n // Partition", + "\n PartitionNotFound, ParsedPartitionNotFound, PartititionNameNotFound, PartitionTypeNotFound,", + "\n // Dimensions", + "\n AmountTypeNotFound, EstimateTypeNotFound,CalculationTypeNotFound, ReportingNodeNotFound, AocTypeMapNotFound, AocTypeNotFound, PortfolioGicNotFound, PortfolioGricNotFound, ", + "\n InvalidAmountTypeEstimateType, MultipleTechnicalMarginOpening,", + "\n // Exchange Rate", + "\n ExchangeRateNotFound, ExchangeRateCurrency,", + "\n // Data Note State", + "\n ChangeDataNodeState, InactiveDataNodeState,", + "\n // Parameters", + "\n ReinsuranceCoverageDataNode, DuplicateInterDataNode, DuplicateSingleDataNode, InvalidDataNode, ", + "\n // Storage", + "\n DataNodeNotFound, PartnerNotFound, RatingNotFound, CreditDefaultRateNotFound, MissingPremiumAllocation, ReinsuranceCoverage, ", + "\n YieldCurveNotFound, YieldCurvePeriodNotApplicable, EconomicBasisNotFound, AccountingVariableTypeNotFound,", + "\n // Scopes", + "\n NotSupportedAocStepReference, MultipleEoP,", + "\n // Data completeness", + "\n MissingDataAtPosting, MissingCombinedLiability, MissingCoverageUnit, ", + "\n // Default", + "\n Generic", + "\n};" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Messages" + ] + }, + { + "cell_type": "code", + "source": [ + "public static string Get (Error e, params string[] s) => (e, s.Length) switch ", + "\n{", + "\n // Import", + "\n (Error.NoMainTab , _) => $\"No Main tab in the parsed file.\",", + "\n (Error.IncompleteMainTab , _) => $\"Incomplete Main tab in the parsed file.\",", + "\n (Error.ParsingScientificNotation , 1) => $\"While parsing found real number in scientific notation: {s[0]}.\",", + "\n (Error.ValueTypeNotFound , _) => $\"Value Type not found.\",", + "\n (Error.ValueTypeNotValid , 1) => $\"The Value Type {s[0]} is invalid.\",", + "\n (Error.AocTypeNotValid , 1) => $\"The parsed AocType {s[0]} is invalid.\",", + "\n // Partition", + "\n (Error.PartitionNotFound , _) => $\"Partition do not found.\",", + "\n (Error.ParsedPartitionNotFound , 1) => $\"Parsed partition not available: ReportingNode {s[0]}.\",", + "\n (Error.ParsedPartitionNotFound , 4) => $\"Parsed partition not available: ReportingNode {s[0]}, Year {s[1]}, Month {s[2]}, Scenario {s[3]}.\",", + "\n (Error.PartitionTypeNotFound , 1) => $\"Partition type not found: {s[0]}.\",", + "\n // Dimensions", + "\n (Error.AmountTypeNotFound , 1) => $\"AmountType {s[0]} not found.\",", + "\n (Error.EstimateTypeNotFound , 1) => $\"EstimateType {s[0]} not found.\",", + "\n (Error.CalculationTypeNotFound , 1) => $\"CalculationType {s[0]} not found.\",", + "\n (Error.ReportingNodeNotFound , 1) => $\"Reporting Node {s[0]} not found.\",", + "\n (Error.AocTypeNotFound , 1) => $\"AocType {s[0]} not found.\",", + "\n (Error.AocTypeMapNotFound , 2) => $\"AocType {s[0]} and Novelty {s[1]} combination not defined in the mapping.\",", + "\n (Error.PortfolioGicNotFound , 2) => $\"Portfolio {s[0]} assigned to Group of Insurance Contract {s[1]} does not exist.\",", + "\n (Error.PortfolioGricNotFound , 2) => $\"Portfolio {s[0]} assigned to Group of Reinsurance Contract {s[1]} does not exist.\",", + "\n (Error.InvalidAmountTypeEstimateType , 2) => $\"Invalid combination of EstimateType {s[0]} and AmountType {s[1]}.\",", + "\n (Error.MultipleTechnicalMarginOpening , 1) => $\"Multiple opening for techincal margin are not allowed for DataNode {s[0]}.\",", + "\n // Exchange Rate", + "\n (Error.ExchangeRateNotFound , 2) => $\"Exchange Rate for {s[0]} {s[1]} is not present.\",", + "\n (Error.ExchangeRateCurrency , 1) => $\"{s[0]} does not have any Exchange Rate defined.\", ", + "\n // Data Node State", + "\n (Error.ChangeDataNodeState , 0) => $\"Data Node State can not change from Inactive state into Active state.\",", + "\n (Error.ChangeDataNodeState , 1) => $\"Data Node State for {s[0]} can not change from Inactive state into Active state.\",", + "\n (Error.ChangeDataNodeState , 3) => $\"Data Node State for {s[0]} can not change from {s[1]} state into {s[2]} state.\",", + "\n (Error.InactiveDataNodeState , 1) => $\"Data imported for inactive Data Node {s[0]}.\",", + "\n //Parameters", + "\n (Error.ReinsuranceCoverageDataNode , 2) => $\"Invalid Reinsurance Coverage parameter does not link a GroupOfReinsuranceContract to a GroupOfInsuranceContract. Provided GroupOfContracts are: {s[0]}, {s[1]}.\",", + "\n (Error.DuplicateInterDataNode , 2) => $\"Duplicated Inter-DataNode parameter for {s[0]}-{s[1]} is found.\",", + "\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 // Storage", + "\n (Error.DataNodeNotFound , 1) => $\"DataNode {s[0]} not found.\",", + "\n (Error.PartnerNotFound , 1) => $\"Partner not found for DataNode {s[0]}.\",", + "\n (Error.RatingNotFound , 1) => $\"Rating not found for Partner {s[0]}.\",", + "\n (Error.CreditDefaultRateNotFound , 1) => $\"Credit Default Rate not found for rating {s[0]}.\",", + "\n (Error.MissingPremiumAllocation , 1) => $\"Premium Allocation Rate not found for Group of Contract {s[0]}.\", // TODO: this is now a warning to be produced by a validation in the importers (default is 1)", + "\n (Error.ReinsuranceCoverage , 1) => $\"Reinsurance Allocation Rate not found for Group of Insurance Contract {s[0]}.\",", + "\n (Error.YieldCurveNotFound , 3) => $\"Yield Curve not found for currency {s[0]}, year {s[1]}, and month {s[2]}.\",", + "\n (Error.YieldCurvePeriodNotApplicable , 2) => $\"YieldCurve period NotApplicable not valid for AocStep with AocType {s[0]} and Novelty {s[1]}.\",", + "\n (Error.EconomicBasisNotFound , 1) => $\"EconomicBasis not valid for DataNode {s[0]}.\",", + "\n (Error.AccountingVariableTypeNotFound , 1) => $\"AccountingVariableType {s[0]} not found.\",", + "\n // Scopes", + "\n (Error.NotSupportedAocStepReference , 1) => $\"Unsupported reference Aoc Step for Aoc Type {s[0]}.\",", + "\n (Error.MultipleEoP , 0) => $\"Closing Balance for both Csm and Lc are computed.\",", + "\n // Data Completeness", + "\n (Error.MissingDataAtPosting , 1) => $\"Missing imported data for {s[0]} DataNode.\",", + "\n (Error.MissingCombinedLiability , 2) => $\"Missing Combined Liability Aoc Type for DataNode {s[0]} and AmountType {s[1]}.\",", + "\n (Error.MissingCoverageUnit , 1) => $\"Missing Coverage Unit cash flow for {s[0]} DataNode.\",", + "\n // Default", + "\n (Error.Generic , _) => $\"{s[0]}\",", + "\n (_ , _) => $\"Error not found.\"", + "\n};" + ] + }, + { + "cell_type": "code", + "source": [ + "public static string Get (Warning w, params string[] s) => (w, s.Length) switch {", + "\n // Import", + "\n (Warning.ActiveDataNodeWithCashflowBOPI , _) => $\"Cashflows for active DataNode has been parsed with AocType {AocTypes.BOP} and Novelty {Novelties.I} \",", + "\n // Default", + "\n (Warning.Generic , _) => $\"{s[0]}\",", + "\n (_ , _) => $\"Warning not found.\"", + "\n};" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/DataModel/DataStructure.ipynb b/DataModel/DataStructure.ipynb index 1e65f8b1..871ff938 100644 --- a/DataModel/DataStructure.ipynb +++ b/DataModel/DataStructure.ipynb @@ -1,2139 +1,1755 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "E3XGdKdQXkSFZwQ0OR8f9Q", - "cell_type": "markdown", - "source": [ - "", - "\n

Data Model

", - "\n", - "\nThis notebook has the main structures used to hold data - This is usually called the **data model**." - ], - "metadata": {} - }, - { - "id": "wIRyXTP_f0aojedzQ_2yaw", - "cell_type": "markdown", - "source": [ - "# References", - "\nThis section initializes libraries and code from other notebooks, which will be used here, as well as information needed for querying data from the database." - ], - "metadata": {} - }, - { - "id": "_ldA06bDKEyrEr1rDJpRng", - "cell_type": "markdown", - "source": [ - "## Libraries" - ], - "metadata": {} - }, - { - "id": "iVjxSwqCvkCRk9OnawoClw", - "cell_type": "code", - "source": [ - "#r \"nuget:Systemorph.Workspace,1.2.0\"", - "\n#r \"nuget:Systemorph.Scopes,1.2.4\"", - "\n#r \"nuget:Systemorph.Import,1.3.0\"", - "\n#r \"nuget:Systemorph.Test,1.2.4\"", - "\n#r \"nuget:Systemorph.Export,1.3.0\"", - "\n#r \"nuget:Systemorph.DataSetReader,1.3.0\"", - "\n#r \"nuget:Systemorph.DataSource,1.2.0\"", - "\n#r \"nuget:Systemorph.DataSource.Conversions,1.2.0\"", - "\n#r \"nuget:Systemorph.Reporting,1.2.4\"", - "\n#r \"nuget:Systemorph.DomainDesigner,1.3.0\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tVqfp6kjPEWcWTsE7nmIJQ", - "cell_type": "markdown", - "source": [ - "## Usings" - ], - "metadata": {} - }, - { - "id": "H4cEfQ5jnE-pcrbgue7FNA", - "cell_type": "code", - "source": [ - "using System.ComponentModel.DataAnnotations;", - "\nusing System.ComponentModel.DataAnnotations.Schema;", - "\nusing Systemorph.Vertex.Grid.Model;", - "\nusing static Systemorph.Vertex.Arithmetics.ArithmeticOperations;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "r7mAcZwhpEOp8xf82HvdyQ", - "cell_type": "markdown", - "source": [ - "## Notebooks" - ], - "metadata": {} - }, - { - "id": "wkcyVZzJ5kqKCJm_siKkNQ", - "cell_type": "code", - "source": [ - "#!import \"../Constants/Enums\"", - "\n#!import \"../Constants/Consts\"", - "\n#!import \"../Constants/Validations\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HTeT_yYbpUCPrWtjwe9fdQ", - "cell_type": "markdown", - "source": [ - "# Data Infrastructure" - ], - "metadata": {} - }, - { - "id": "HrfAYsLiM0SFRqKe6IIlxA", - "cell_type": "markdown", - "source": [ - "", - "\n## Base Interfaces", - "\nThe following interfaces are used to define the granularity at which data is stored.", - "\n", - "\nFor instance, the IKeyed interface corresponds to the lowest granularity which is simply a unique identifier for a certain generic piece of data:" - ], - "metadata": {} - }, - { - "id": "-JHURlI5Z0mY6_UxQ7gfGA", - "cell_type": "code", - "source": [ - "public interface IKeyed", - "\n{ ", - "\n public Guid Id { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TLXXKZET0E-dDwCIcdZXBg", - "cell_type": "markdown", - "source": [ - "The interface IPartition identifies the partitions in the system." - ], - "metadata": {} - }, - { - "id": "A-Onlfa3vkqOVvHu6-JMQg", - "cell_type": "code", - "source": [ - "public interface IPartition : IKeyed {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iF7QiEQqBE2pxD1M85J2Sw", - "cell_type": "markdown", - "source": [ - "The interface IPartitioned simply assigns a unique identifier for elements of a data partition - The exact definition of such elements can be found in the [partition](#partition) section below." - ], - "metadata": {} - }, - { - "id": "UI71Ps6BF0K27AoG-9UkDw", - "cell_type": "code", - "source": [ - "public interface IPartitioned", - "\n{", - "\n public Guid Partition { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mwvvs9R7IE6s7-QzaQ44Iw", - "cell_type": "markdown", - "source": [ - "The interface IHierarchy is used for modelling dimensions which have an hierarchical structure, such as [Amount Type](#amount-type)." - ], - "metadata": {} - }, - { - "id": "udn_BFvLkE-kpOBDTNrOzg", - "cell_type": "code", - "source": [ - "public interface IHierarchy", - "\n{", - "\n [Display(Order = 10)]", - "\n public string Name { get; init; }", - "\n ", - "\n [Display(Order = 20)]", - "\n public string Parent { get; init; }", - "\n ", - "\n [Display(Order = 30)]", - "\n public string Child { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qlvXHTn5VUmrP2f97WrtTw", - "cell_type": "markdown", - "source": [ - "The interface IWithYearAndMonth allows to speficy to which year and month a certain piece of data applies to:" - ], - "metadata": {} - }, - { - "id": "jD1t0fnTnUGMALFqTwsLHA", - "cell_type": "code", - "source": [ - "public interface IWithYearAndMonth", - "\n{", - "\n public int Year { get; init; }", - "\n ", - "\n public int Month { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WbhV6bUsy0ukIAm920fzwg", - "cell_type": "markdown", - "source": [ - "", - "\n## Abstract Classes", - "\nThese classes are not reflected in the database, i.e. are not persisted." - ], - "metadata": {} - }, - { - "id": "EVd9ytkY40OTYvjWp5aziA", - "cell_type": "code", - "source": [ - "public abstract record KeyedRecord : IKeyed {", - "\n [Key]", - "\n [NotVisible] ", - "\n public Guid Id { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "h-P8iuN2zUqCz2F1HgnXjQ", - "cell_type": "code", - "source": [ - "public abstract record KeyedDimension : INamed {", - "\n [Key]", - "\n [IdentityProperty]", - "\n [StringLength(16)]", - "\n [Display(Order = 1)]", - "\n public string SystemName { get; init; }", - "\n ", - "\n [Display(Order = 2)]", - "\n [NotVisible]", - "\n public string DisplayName { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q1r9nxY4cEudsXAFS_0LOA", - "cell_type": "code", - "source": [ - "public abstract record KeyedOrderedDimension : KeyedDimension, IOrdered {", - "\n [NotVisible]", - "\n public int Order { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "V0ZEujrm8EeHPz95bLGLOA", - "cell_type": "code", - "source": [ - "public abstract record KeyedOrderedDimensionWithExternalId : KeyedOrderedDimension {", - "\n [Display(Order = 100)]", - "\n [Conversion(typeof(JsonConverter))]", - "\n public string[] ExternalId { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1ZMlcc50Q0yVI7dZBvBCyQ", - "cell_type": "markdown", - "source": [ - "", - "\n# Dimensions", - "\n", - "\nDimensions are data which tipically can be given a short name, here called 'System Name'. They also change slowly with time. A typical example is currencies, and examples of System Names are EUR, CHF, etc.", - "\n", - "\nThe advantages of using Dimensions are:", - "\n- The data is easier to maintain (the data is said to be 'normalized');", - "\n- The business logic is easier to read;", - "\n- Easier scructuring of the data, e.g. in a data-cube." - ], - "metadata": {} - }, - { - "id": "Nh9SUewfGEisAbZfcpYfPA", - "cell_type": "markdown", - "source": [ - "", - "\n## Hierarchical Dimension With Level", - "\nHierarchical dimensions are useful to define for example the legal structure of a company (reporting nodes and their parents).", - "\n", - "\nBelow we introduce the concept of a hierarchical dimension with level, which is a simple way to keep track of the \"level\" in a hierarchical dimension." - ], - "metadata": {} - }, - { - "id": "4JGV542yw0KkgF5wA8Xc-A", - "cell_type": "code", - "source": [ - "//TODO: Should this be abstract or have a reference to the type?", - "\npublic record HierarchicalDimensionWithLevel(string SystemName, string DisplayName, string Parent, int Level) : IHierarchicalDimension;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3mdUv9EKwUaRHVRzBFxSNw", - "cell_type": "markdown", - "source": [ - "", - "\n## Amount Type" - ], - "metadata": {} - }, - { - "id": "oD4Rl6GEpEqnLIn_CUdivg", - "cell_type": "markdown", - "source": [ - "Amount Type is a dimension used to describe the nature of numbers. For example: Numbers associated to the payment of premiums have Amount Type 'Premiums'; Numbers associated to the payment of claims have Amount Type 'Claims'; Numbers associated to expenses have Amount Type 'Expenses'. ", - "\n", - "\nIt is defined as a hierarchical dimension so that higher-granularity types can be introduced. For example: 'Claim Expenses' have parent 'Claims'.", - "\n", - "\nAmount Types are a central piece in the IFRS 17 application and are used for instance to name the different types of cashflows. For example: There might be cashflows for 'Premiums'; Cashflows for 'Claims', etc. In case the mapping between cash flow and amount type is non-trivial, then specific mappings are introduced through the use of ExternalId." - ], - "metadata": {} - }, - { - "id": "ffEXk8fDRUSuFc1EOOWVXA", - "cell_type": "code", - "source": [ - "public record AmountType : KeyedOrderedDimensionWithExternalId, IHierarchicalDimension", - "\n{", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(AmountType))]", - "\n public string Parent { get; init; }", - "\n ", - "\n [Display(Order = 20)]", - "\n [Dimension(typeof(PeriodType))]", - "\n public PeriodType PeriodType { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xY7Lv0cnPk2ZqR7zMUKVAQ", - "cell_type": "markdown", - "source": [ - "We distinguish between amount types used for cashflows and actuals (**Present Value Amount Types**), and amount types used for deferrable values (**Deferrable Amount Types**). In particular, deferrable amount types are for costs and expenses that can be deferred to the future. These amounts are treated separately from the Present Value Amount Types because they are not considered for the calculation of Contractual Service Margin and Loss Component." - ], - "metadata": {} - }, - { - "id": "u1zwrsAl_06VNVKVjqY52g", - "cell_type": "code", - "source": [ - "public record PvAmountType : AmountType {} //TODO Rename ", - "\n", - "\npublic record DeferrableAmountType : AmountType {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uCEMSSPR00Oh87NXjPpxaQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Calculation Type", - "\nThis dimension is used to distinguish between e.g. **Best Estimate** values and **Risk Adjustment** values:" - ], - "metadata": {} - }, - { - "id": "ZNlHEPmkHky4j1HvhgN88A", - "cell_type": "code", - "source": [ - "public record CalculationType : KeyedOrderedDimension {", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(PeriodType))]", - "\n public PeriodType PeriodType { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vKJfcG-udU2bWMy_nL8WSQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Risk Driver", - "\n", - "\nRisk drivers are used to distinguish between the different Risk Adjustment numbers. For instance: Mortality, Disability, Longevity, etc.", - "\n", - "\nWhen only total risk adjustment values are used, then there is no need to use risk drivers." - ], - "metadata": {} - }, - { - "id": "fa88nNjOdk6ESB_dqpM35w", - "cell_type": "code", - "source": [ - "public record RiskDriver : KeyedOrderedDimension, IHierarchicalDimension", - "\n{", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(RiskDriver))]", - "\n public string Parent { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VkCT-HB9TkyWJJyAcX42QQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Estimate Type", - "\n", - "\nEstimate Type is a dimension used to distinguish the context to which numbers belong to. For instance: Numbers for present values have Estimate Type 'Present Value'; Numbers for Risk Adjustments have Estimate Type 'Risk Adjustment'." - ], - "metadata": {} - }, - { - "id": "PGODf3XfjEOJ2CfpWJNxvw", - "cell_type": "code", - "source": [ - "public record EstimateType : KeyedOrderedDimensionWithExternalId", - "\n{", - "\n [Display(Order = 110)]", - "\n public InputSource InputSource { get; init; }", - "\n ", - "\n [Display(Order = 120)]", - "\n public StructureType StructureType { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bo_ARw7-YEWDtJJsK8ODmA", - "cell_type": "markdown", - "source": [ - "", - "\n## Novelty", - "\n", - "\nNovelty is a [dimension](#dimensions) used to identity the novelty of the business. Typical examples of Novelty are New Busines, In-Force, and Combined." - ], - "metadata": {} - }, - { - "id": "mV4OXu-r_0e7k1vZthQ1IQ", - "cell_type": "code", - "source": [ - "public record Novelty : KeyedOrderedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "O-7_tXaPPEOL_eRj1Ev76g", - "cell_type": "markdown", - "source": [ - "", - "\n## Variable Type" - ], - "metadata": {} - }, - { - "id": "jFh4gN-zTEyK_KZ55DhlEw", - "cell_type": "code", - "source": [ - "public record VariableType : KeyedOrderedDimension, IHierarchicalDimension", - "\n{ ", - "\n [Display(Order = 10)]", - "\n public string Parent { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RJcV2vGuokmqX1cLgr8tcw", - "cell_type": "markdown", - "source": [ - "", - "\n### AoC Variable Type", - "\n", - "\nThe AocType describes the type of the Analysis of Change step - For example: Amortization, Cashflow, Combined Liabilities etc.", - "\n", - "\nThe **Combined Liability** AocType aims in capturing the difference between the sum of all relevant previous Aoc steps and the end of period Aoc step. Unexplained changes (not captured by any other defined AoC step), are then visible in this Aoc step. Note that the nominal cash flows input in the cashflow input file corresponds to cash flow projection for the end of period step.", - "\nIn addition, this step distinguishes itself from the others for:", - "\n- It is a mandatory AocType as it is used to trigger the Run off of the cashflow. This is achieved by providing a cash flow of 0s. ", - "\n- It is the first AocType for the Combined Novelty and therefore it carries the contribution of combining In force and New business.", - "\n- Its present value is computed as telescoping difference with the last AoC Step for the In-Force novelty and the New Business novelty.", - "\n- In the technical margin calculation it is used to merge the profitability of the In-Force and New business components, which may result in a forced switch." - ], - "metadata": {} - }, - { - "id": "uXawxEZ9akakX3cBhzIvkw", - "cell_type": "code", - "source": [ - "public record AocType : VariableType", - "\n{ ", - "\n [Display(Order = 30)]", - "\n [Dimension(typeof(AocType))]", - "\n public string Parent { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wURsJ4y22UClSsa-dgRVKg", - "cell_type": "code", - "source": [ - "public record AocStep(string AocType, string Novelty){}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9FQQEf3waUyPGTjoJ3kPvA", - "cell_type": "markdown", - "source": [ - "", - "\n### PnL Variable Type", - "\n", - "\nThe PnlVariableType is used to describe the various profit and loss sections and the corresponding hierarchy." - ], - "metadata": {} - }, - { - "id": "yXjDtNxmtUKCm7l4rInNRw", - "cell_type": "code", - "source": [ - "public record PnlVariableType : VariableType {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6TMaVeubb0yfDj0zHl3dNQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Balance Sheet Variable Type", - "\n", - "\nThe BsVariableType is used to descibe the Anlysis of change of the Balance Sheet reports." - ], - "metadata": {} - }, - { - "id": "kmnM353ouUSOXqQD4IcV7Q", - "cell_type": "code", - "source": [ - "public record BsVariableType : VariableType {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WglnqvLArU6Ahc29yVDgSQ", - "cell_type": "markdown", - "source": [ - "## Accounting Variable Type", - "\nThe AccountingVariableType is used to describe the accounting events that are posted in the accounting output file." - ], - "metadata": {} - }, - { - "id": "tqFR7uu7BkOnFUvISdLF1A", - "cell_type": "code", - "source": [ - "public record AccountingVariableType : VariableType {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gQILcufhBU6Gh3ZoHDRIYA", - "cell_type": "markdown", - "source": [ - "", - "\n## Scenario", - "\nThe Scenario record holds the various scenarios for which calculations should also be performed." - ], - "metadata": {} - }, - { - "id": "WKR88bI5G0qwjmpDyGZTsw", - "cell_type": "code", - "source": [ - "public record Scenario : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "c-cppckU8UeROzwpBdL44A", - "cell_type": "markdown", - "source": [ - " The 'neutral' Scenario (i.e. the default one, with no-stress situations applied) is designated as 'Best Estimate'." - ], - "metadata": {} - }, - { - "id": "ysCBY_ONbUmbRFL_KEXoXg", - "cell_type": "markdown", - "source": [ - "", - "\n## Line Of Business" - ], - "metadata": {} - }, - { - "id": "XPrjV3N-LE-TKVM80pV5yQ", - "cell_type": "markdown", - "source": [ - "Line Of Business is a dimension used to identity insurance business according to usual business classifications (usually a market or company-specific business classification representing a convolution of risk covered, 1st party / 3rd party cover type, product type, etc...)", - "\nTypical examples of Line of Business are Motor, Property, Endowment, etc... This is a hierarchical dimension." - ], - "metadata": {} - }, - { - "id": "VxLXh8klyEi6UhXPn1ZKKw", - "cell_type": "code", - "source": [ - "public record LineOfBusiness : KeyedOrderedDimension, IHierarchicalDimension", - "\n{", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(LineOfBusiness))]", - "\n public string Parent { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pnCYzQI05UWCUkXGHAB9QA", - "cell_type": "markdown", - "source": [ - "", - "\n## Currency" - ], - "metadata": {} - }, - { - "id": "PZEeN2QhsEGXT0BQ4Rjlag", - "cell_type": "markdown", - "source": [ - "Currency is a dimension used to identity the currency.", - "\nTypical examples of Currency are EUR, CHF, USD, etc..." - ], - "metadata": {} - }, - { - "id": "TUEcu5Y_ZE6Nv_pUG-_COQ", - "cell_type": "code", - "source": [ - "public record Currency : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TUfMA1ybakuqVJ73ERA3ZQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Economic Basis", - "\n", - "\nThe Economic Basis defines the discount type which is used in calculations. Examples are: Nominal, Current and Locked." - ], - "metadata": {} - }, - { - "id": "rt_ieWyHpU29K0fpiBXLcQ", - "cell_type": "code", - "source": [ - "public record EconomicBasis : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CJjymwgpJEiBZhPYBoZV-w", - "cell_type": "markdown", - "source": [ - "", - "\n## Valuation Approach", - "\nThis dimension holds the various methodologies used in the calculations: BBA, VFA and PAA." - ], - "metadata": {} - }, - { - "id": "oPjqx6DSTkyk2Pi5v9Bgww", - "cell_type": "code", - "source": [ - "public record ValuationApproach : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "v5-cD3t8RkaWxWs7t5oTxg", - "cell_type": "markdown", - "source": [ - "", - "\n## Liability Type", - "\nThe Liability Type distinguishes betweeen e.g. liabilities for incurred claims and liabilities for remaining coverage." - ], - "metadata": {} - }, - { - "id": "zZBD3LVJqUSlsfat1_eEDw", - "cell_type": "code", - "source": [ - "public record LiabilityType : KeyedDimension, IHierarchicalDimension", - "\n{", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(LiabilityType))]", - "\n public string Parent { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "JkEN-M0lnUaJ5FsC0QM6JQ", - "cell_type": "markdown", - "source": [ - "", - "\n## OCI Type", - "\nOther Comprehensive Income (OCI) Type describes how the financial contributions to the IFRS17 Financial Performance is apportioned between the P&L and the OCI sections." - ], - "metadata": {} - }, - { - "id": "pAjz1mAaPUGhHNTdyP54gw", - "cell_type": "code", - "source": [ - "public record OciType : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZvvcNAbtHki9DK9rkMj5PQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Profitability" - ], - "metadata": {} - }, - { - "id": "SpHNgrkn70WBckuZf-9rtA", - "cell_type": "markdown", - "source": [ - "Profitability is a dimension used in IFRS 17 to describe the profitability of a Group of Contracts (GIC/GRIC).", - "\nTypical examples of Profitability are Profitable, Non-Profitable, etc.." - ], - "metadata": {} - }, - { - "id": "rJS1Lqw9gUyBmW8LzFRIAw", - "cell_type": "code", - "source": [ - "public record Profitability : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5nzILMYUw06HnJmXUyLYgg", - "cell_type": "markdown", - "source": [ - "", - "\n## Partner", - "\nPartner is the counterparty of a reinsurance contract." - ], - "metadata": {} - }, - { - "id": "_vf2ckZDHkiTBUqDESRY7A", - "cell_type": "code", - "source": [ - "public record Partner : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "K48oHe7Yw0GIy27KBHbDtQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Credit Risk Rating", - "\nThis holds the credit risk rating of each Partner." - ], - "metadata": {} - }, - { - "id": "faZdNRqxWkqUXYnGZQNNLQ", - "cell_type": "code", - "source": [ - "public record CreditRiskRating : KeyedDimension {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LrcDCmrTYkiEFks8X5d5qQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Reporting Node", - "\nA Reporting Node is an element in the reporting structure of the company. It has a hierarchical structure and the end nodes is the level at which data is imported." - ], - "metadata": {} - }, - { - "id": "yfIk7Ocnc0SkfFXciN5yfQ", - "cell_type": "code", - "source": [ - "public record ReportingNode : KeyedDimension, IHierarchicalDimension ", - "\n{", - "\n [Display(Order = 20)]", - "\n [Dimension(typeof(ReportingNode))]", - "\n public string Parent { get; init; }", - "\n ", - "\n [Required]", - "\n [Display(Order = 40)]", - "\n [Dimension(typeof(Currency))]", - "\n public virtual string Currency { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dgSDvMwORkWAHKNhcKsOsQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Projection Configuration" - ], - "metadata": {} - }, - { - "id": "SXiQr9uXpEOar1SWj1NbHQ", - "cell_type": "markdown", - "source": [ - "Projections are configured by defining the following 2 parameters:", - "\n", - "\n- Shift defines how many months are in the cashflow file before the first value of the period in interest.
", - "\n- TimeStep defines how many months are in the period of interest.
", - "\n", - "\nBoth Shift and TimeStep are measured in terms of number of months.", - "\nFor instance, for the current year and year-to-date view we have $\\rm{Shift}=0$ and $TimeStep=3$ for the first quarter, $TimeStep=6$ for the 2nd quarter and so on." - ], - "metadata": {} - }, - { - "id": "5roF1i3RCkuAb120D2hlCw", - "cell_type": "code", - "source": [ - "public record ProjectionConfiguration : KeyedDimension", - "\n{", - "\n [IdentityProperty]", - "\n public int Shift { get; init; }", - "\n [IdentityProperty]", - "\n public int TimeStep { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0BJMDgWcZ0-7DaVBFvhhrg", - "cell_type": "markdown", - "source": [ - "", - "\n# Parameters" - ], - "metadata": {} - }, - { - "id": "lZdeQUGmGUmVPRibX3A4mQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Aoc Step Configuration" - ], - "metadata": {} - }, - { - "id": "NRbkQdbBAkSeX6wwNvqeLg", - "cell_type": "markdown", - "source": [ - "The record below holds parameters over time for each combination of AocType and Novelty. In particular:", - "\n- DataType identifies between Calculated aoc steps and Optional inputs or Mandatory inputs.", - "\n- InputSource identifies whether an aoc step is relevant for Actuals, Cashflow or both calculations.", - "\n- FxPeriod identifies which fx rate should be used.", - "\n- YcPeriod identifies which Yield Curve should be used (from current or previous period).", - "\n- CdrPeriod identifies which Credit Default Rate should be used (from current or previous period).", - "\n- ValuationPeriod identifies which value from the Cashflow corresponds to the Present Value.", - "\n- RcPeriod identifies which Reinsurance Coverage should be used (from current or previous period).", - "\n", - "\n
The values for each parameter can be found in [Enums Notebook](./Constants/Enums)." - ], - "metadata": {} - }, - { - "id": "fSKSGQxYvEWCjRwEU8Zp8A", - "cell_type": "code", - "source": [ - "public record AocConfiguration : KeyedRecord, IWithYearAndMonth, IOrdered", - "\n{", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 10)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 20)]", - "\n public int Month { get; init; }", - "\n ", - "\n [IdentityProperty]", - "\n [Display(Order = 30)]", - "\n [Dimension(typeof(AocType))]", - "\n public string AocType { get; init; }", - "\n ", - "\n [IdentityProperty]", - "\n [Display(Order = 40)]", - "\n [Dimension(typeof(Novelty))]", - "\n public string Novelty { get; init; }", - "\n ", - "\n [Display(Order = 50)]", - "\n [Dimension(typeof(DataType))]", - "\n public DataType DataType { get; init; }", - "\n ", - "\n [Display(Order = 55)]", - "\n [Dimension(typeof(InputSource))]", - "\n public InputSource InputSource { get; init; }", - "\n ", - "\n [Display(Order = 60)]", - "\n [Dimension(typeof(FxPeriod))]", - "\n public FxPeriod FxPeriod { get; init; }", - "\n ", - "\n [Display(Order = 70)]", - "\n [Dimension(typeof(PeriodType), nameof(YcPeriod))]", - "\n public PeriodType YcPeriod { get; init; }", - "\n ", - "\n [Display(Order = 80)]", - "\n [Dimension(typeof(PeriodType), nameof(CdrPeriod))]", - "\n public PeriodType CdrPeriod { get; init; }", - "\n ", - "\n [Display(Order = 90)]", - "\n [Dimension(typeof(ValuationPeriod))]", - "\n public ValuationPeriod ValuationPeriod { get; init; }", - "\n ", - "\n [Display(Order = 100)]", - "\n [Dimension(typeof(PeriodType), nameof(RcPeriod))]", - "\n public PeriodType RcPeriod { get; init; }", - "\n ", - "\n [NotVisible]", - "\n public int Order { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9EDmAQK2o0CtkSqxrxadaw", - "cell_type": "markdown", - "source": [ - "", - "\n## Exchange Rate", - "\nThe record below holds the Exchange Rates over time and for each exchange type ([FxType](./Constants/Enums)). Exchange Rate must be updated every reporting period as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", - "\n", - "\nIn case the Exchange Rate for the current period is missing, an error is returned. " - ], - "metadata": {} - }, - { - "id": "0UriZBf9PkWxz4YC-Zj6jQ", - "cell_type": "code", - "source": [ - "public record ExchangeRate : KeyedRecord", - "\n{ ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(Currency))]", - "\n public string Currency { get; init; }", - "\n", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 20)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 30)]", - "\n public int Month { get; init; }", - "\n", - "\n [IdentityProperty]", - "\n [Required]", - "\n [Display(Order = 40)]", - "\n public FxType FxType { get; init; }", - "\n", - "\n [Display(Order = 50)]", - "\n public double FxToGroupCurrency { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DqeuCXH1bkmJd_iD726ypg", - "cell_type": "markdown", - "source": [ - "", - "\n## Credit Default Rate", - "\nThe record below holds the Credit Default Rates over time for each [Credit Risk Rating](#credit-risk-rating). Credit Default Rate can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", - "\n", - "\nThe Credit Default Rate values must be entered with monthly granularity, i.e. every value corresponds to the default rate for a certain month. The first month entered in column Values0 always corresponds to January of the year entered in column Year. The last value is considered valid also for the following years (for which no value has been provided). ", - "\n", - "\nThe latest Credit Default Rate 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." - ], - "metadata": {} - }, - { - "id": "dGtfTrO3iUaqdptZ0yybYw", - "cell_type": "code", - "source": [ - "public record CreditDefaultRate : KeyedRecord, IWithYearAndMonth", - "\n{ ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(CreditRiskRating))]", - "\n public string CreditRiskRating { get; init; }", - "\n", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 20)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 30)]", - "\n public int Month { get; init; }", - "\n ", - "\n [Conversion(typeof(PrimitiveArrayConverter))]", - "\n [Display(Order = 40)]", - "\n public double[] Values { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9_ycC9yzPkG8EqR3gTj3PA", - "cell_type": "markdown", - "source": [ - "", - "\n## Yield Curve", - "\nThe record below holds the Yield Curves across time for each [Currency](#currency) and [Scenario](#scenario).", - "\nYield curves can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", - "\n", - "\nThe Yield Curve values must be entered with **yearly** granularity, i.e. every value corresponds to the rate of the whole year starting from the year entered in column Year. The last value is considered valid also for the following years (for which no value has been provided). ", - "\n", - "\nWhen the current Yield Curve must be used in the calculation, the latest Yield Curve available in the system with Year and Month earlier or equal to Year and Month of the closing period will be used." - ], - "metadata": {} - }, - { - "id": "3TbdMYHKKk2Wan-Egtuetg", - "cell_type": "code", - "source": [ - "public record YieldCurve : KeyedRecord, IWithYearAndMonth", - "\n{ ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(Currency))]", - "\n public string Currency { get; init; }", - "\n", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 20)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 30)]", - "\n public int Month { get; init; }", - "\n", - "\n [IdentityProperty]", - "\n [Display(Order = 35)]", - "\n public string Scenario { get; init; }", - "\n", - "\n [Conversion(typeof(PrimitiveArrayConverter))]", - "\n [Display(Order = 40)]", - "\n public double[] Values { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kR4nqN3MwkqRBS8Yeb4bOA", - "cell_type": "markdown", - "source": [ - "", - "\n## Partner Rating", - "\nThe record below holds the [Credit Risk Rating](#credit-risk-partner) for each [Partner](#partner) across time. Partner Rating can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. " - ], - "metadata": {} - }, - { - "id": "-yzxBGiz7U62zp3niNtqEA", - "cell_type": "code", - "source": [ - "public record PartnerRating : KeyedRecord, IWithYearAndMonth", - "\n{ ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(Partner))]", - "\n public string Partner { get; init; }", - "\n", - "\n [Required]", - "\n [Display(Order = 20)]", - "\n [Dimension(typeof(CreditRiskRating))]", - "\n public string CreditRiskRating { get; init; }", - "\n", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 30)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 40)]", - "\n public int Month { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4bFzr4BUxECkAZN1KK83Kg", - "cell_type": "markdown", - "source": [ - "", - "\n# Partitions", - "\nThe notion of Partition is used to define small but meaningful sets of data, called partitions. Partitions are then used to optimize the extraction of data from the database, i.e. only the data for a certain partition is retrieved." - ], - "metadata": {} - }, - { - "id": "lfo6j69S00S5MmeGEgWhWA", - "cell_type": "code", - "source": [ - "public abstract record IfrsPartition : IPartition {", - "\n [Key]", - "\n [PartitionId]", - "\n public Guid Id { get; init; }", - "\n", - "\n [Required]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(ReportingNode))]", - "\n [IdentityProperty]", - "\n public string ReportingNode { get; init; }", - "\n", - "\n [Display(Order = 50)]", - "\n [Dimension(typeof(Scenario))]", - "\n [IdentityProperty]", - "\n public string Scenario { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Oy6PSvNeAkOrHXzbWi144g", - "cell_type": "markdown", - "source": [ - "For instance, the data pertaining to a certain [Reporting Node](#reporting-node) for a certain [Scenario](#scenario) is called an IfrsPartition and assigned a unique identifier:" - ], - "metadata": {} - }, - { - "id": "YQl5TqjBQUui3Ao3FsgiUw", - "cell_type": "code", - "source": [ - "public record PartitionByReportingNode : IfrsPartition {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "M8p4dGJQHkC7dFwqXU4RXQ", - "cell_type": "markdown", - "source": [ - "The partition PartitionByReportingNodeAndPeriod is a further partition of the IfrsPartition sets - In particular, it defines sets for the data pertaining to a certain [Reporting Node](#reporting-node), [Scenario](#scenario), year and month. The value of the Month is the last month of the reporting period to which the data belongs to. " - ], - "metadata": {} - }, - { - "id": "a7nDH2imYUeP23B6WT5yZw", - "cell_type": "code", - "source": [ - "public record PartitionByReportingNodeAndPeriod : IfrsPartition {", - "\n [Display(Order = 30)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [IdentityProperty]", - "\n public int Year { get; init; }", - "\n", - "\n [Display(Order = 40)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [IdentityProperty]", - "\n public int Month { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TZvDAkF0M02LQtQKCZLJRA", - "cell_type": "markdown", - "source": [ - "", - "\n# Policy-related Data Structures", - "\n", - "\nThe data structures below are the pieces of the data model where policy-related data is held." - ], - "metadata": {} - }, - { - "id": "kjn-7dhJgEa7EDS2jG2CbA", - "cell_type": "markdown", - "source": [ - "", - "\n## Data Node", - "\n", - "\nA data node is basically a set of labels which identify data according to its:", - "\n- Reporting Node", - "\n- Scenario", - "\n- Contractual Currency", - "\n- FunctionalCurrency", - "\n- LineOfBusiness", - "\n- ValuationApproach", - "\n- OCI Type" - ], - "metadata": {} - }, - { - "id": "7I3_uOSDzkuHhcVJMukGlA", - "cell_type": "markdown", - "source": [ - "TODOs:", - "\n
    ", - "\n
  • Remove Scenario from Partition and include it as simple property (see Year, Month). Introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", - "\n
" - ], - "metadata": {} - }, - { - "id": "XlZfZAGgi0GjV_7P_tJtiQ", - "cell_type": "code", - "source": [ - "public record DataNode : KeyedDimension, IPartitioned {", - "\n [NotVisible]", - "\n [PartitionKey(typeof(PartitionByReportingNode))]", - "\n public Guid Partition { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(Currency))]", - "\n //[Required] // TODO: check", - "\n //[Immutable] // TODO: Not available yet", - "\n public string ContractualCurrency { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(Currency))]", - "\n //[Required] // TODO: check", - "\n //[Immutable]", - "\n public string FunctionalCurrency { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(LineOfBusiness))]", - "\n //[Immutable]", - "\n public string LineOfBusiness { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(ValuationApproach))]", - "\n [Required]", - "\n //[Immutable]", - "\n public string ValuationApproach { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(OciType))]", - "\n //[Immutable]", - "\n public string OciType { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0Zg-7p1UNU6Wdzok3kr-AA", - "cell_type": "markdown", - "source": [ - "", - "\n## Portfolios", - "\n", - "\nA Portfolio is a set of Group of Contracts. The relationship is set on the Group of Contracts (see below).", - "\n", - "\nPortfolios are of type DataNode and there are two types: Insurance Portfolio and Reinsurance Portfolios." - ], - "metadata": {} - }, - { - "id": "0P3rhAjUNUyBonuP1k9uHg", - "cell_type": "code", - "source": [ - "public record Portfolio : DataNode {}", - "\n", - "\npublic record InsurancePortfolio : Portfolio {}", - "\npublic record ReinsurancePortfolio : Portfolio {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xbAt9JzjCE614P7B97aiVA", - "cell_type": "markdown", - "source": [ - "", - "\n## Group of Contracts", - "\n", - "\nA Group of Contract is a set of contracts with the same Annual Cohort, Liability Type, Profitability and Partner (in case the contracts are done with a re-insurer).", - "\n", - "\nVarious Group of Contracts are put together into portfolios." - ], - "metadata": {} - }, - { - "id": "la_B6Lgw10-Y8UNDpmZ3gA", - "cell_type": "code", - "source": [ - "public record GroupOfContract : DataNode {", - "\n [NotVisible] ", - "\n [Dimension(typeof(int), nameof(AnnualCohort))]", - "\n //[Immutable]", - "\n public int AnnualCohort { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(LiabilityType))]", - "\n //[Immutable]", - "\n public string LiabilityType { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(Profitability))]", - "\n //[Immutable]", - "\n public string Profitability { get; init; }", - "\n ", - "\n [Required]", - "\n [NotVisible] ", - "\n [Dimension(typeof(Portfolio))]", - "\n //[Immutable]", - "\n public string Portfolio { get; init; }", - "\n ", - "\n public virtual string Partner { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qgBtX4_gZEeQFJWmImnXKg", - "cell_type": "markdown", - "source": [ - "A group of insurance contracts is called a **GIC** and has no information on Partner.", - "\n", - "\nOnly Groups of Reinsurance Contracts, defined below and usually called **GRIC**s, have Partner information.", - "\nAgain, there are Insurance GRICs and Reinsurance GRICs:" - ], - "metadata": {} - }, - { - "id": "IGY1DT71jECwSzukcliQKg", - "cell_type": "code", - "source": [ - "public record GroupOfInsuranceContract : GroupOfContract {", - "\n [Required]", - "\n [NotVisible] ", - "\n [Display(Name = \"InsurancePortfolio\")]", - "\n [Dimension(typeof(InsurancePortfolio))]", - "\n //[Immutable]", - "\n public string Portfolio { get => base.Portfolio; init => base.Portfolio = value; }", - "\n ", - "\n // TODO: for the case of internal reinsurance the Partner would be the reporting node, hence not null.", - "\n // If this is true we need the [Required] attribute here, add some validation at dataNode import ", - "\n // and to add logic in the GetNonPerformanceRiskRate method in ImportStorage.", - "\n [NotVisible] ", - "\n [NotMapped]", - "\n //[Immutable]", - "\n public override string Partner => null;", - "\n}", - "\n", - "\npublic record GroupOfReinsuranceContract : GroupOfContract {", - "\n [Required]", - "\n [NotVisible] ", - "\n [Display(Name = \"ReinsurancePortfolio\")]", - "\n [Dimension(typeof(ReinsurancePortfolio))]", - "\n //[Immutable]", - "\n public string Portfolio { get => base.Portfolio; init => base.Portfolio = value; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "STd2Dg5TnU-jBYDxq-VbnA", - "cell_type": "markdown", - "source": [ - "", - "\n## Data Node State", - "\n", - "\nThe Data State is used to track whether a GOC is Active or Inactive across time (year and month). ", - "\nIt is only possible to update the state of a Group of Contract from Active to Inactive." - ], - "metadata": {} - }, - { - "id": "l1RwYYRGQUuYklornedCUA", - "cell_type": "code", - "source": [ - "public record DataNodeState : KeyedRecord, IPartitioned, IWithYearAndMonth", - "\n{", - "\n [NotVisible]", - "\n [PartitionKey(typeof(PartitionByReportingNode))]", - "\n public Guid Partition { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(GroupOfContract))]", - "\n public string DataNode { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 20)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 30)]", - "\n [DefaultValue(DefaultDataNodeActivationMonth)]", - "\n public int Month { get; init; } = DefaultDataNodeActivationMonth;", - "\n ", - "\n [Required]", - "\n [Display(Order = 40)]", - "\n [DefaultValue(State.Active)]", - "\n public State State { get; init; } = State.Active;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "siMZOfujgkCvYRhglSafRw", - "cell_type": "markdown", - "source": [ - "", - "\n## Data Node Parameters", - "\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 AocType of the Technical Margin and is valid only for Group of Insurance Contract with LiabilityType : Liability for Remaining Coverage.", - "\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.", - "\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." - ], - "metadata": {} - }, - { - "id": "Y9V4hdUwV0WlDgxhiVJ0lg", - "cell_type": "code", - "source": [ - "public record DataNodeParameter : KeyedRecord, IPartitioned, IWithYearAndMonth", - "\n{", - "\n [NotVisible]", - "\n [PartitionKey(typeof(PartitionByReportingNode))]", - "\n public Guid Partition { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 20)]", - "\n public int Year { get; init; }", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n [Display(Order = 30)]", - "\n [DefaultValue(DefaultDataNodeActivationMonth)]", - "\n public int Month { get; init; } = DefaultDataNodeActivationMonth;", - "\n ", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(GroupOfContract))]", - "\n public string DataNode { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Cnr2el8xg0OjF0x79bM9lQ", - "cell_type": "code", - "source": [ - "public record SingleDataNodeParameter : DataNodeParameter {", - "\n [DefaultValue(DefaultPremiumExperienceAdjustmentFactor)]", - "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n public double PremiumAllocation { get; init; } = DefaultPremiumExperienceAdjustmentFactor;", - "\n}", - "\n", - "\npublic record InterDataNodeParameter : DataNodeParameter {", - "\n [Required]", - "\n [IdentityProperty]", - "\n [Display(Order = 20)]", - "\n [Dimension(typeof(GroupOfContract))]", - "\n public string LinkedDataNode { get; init; }", - "\n ", - "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", - "\n public double ReinsuranceCoverage { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WCZyCC4Qlkm0FjxSRHM0xw", - "cell_type": "markdown", - "source": [ - "## DataNodeData PocoType", - "\nThe DataNodeData type is not persisted (i.e. not stored in the database) and is used in order to hold Data Node data during data manipulations." - ], - "metadata": {} - }, - { - "id": "koNxFi27ZkuU4_2cCG2GMA", - "cell_type": "code", - "source": [ - "public record DataNodeData {", - "\n public string DataNode { get; init; }", - "\n ", - "\n //Portfolio", - "\n public string ContractualCurrency { get; init; }", - "\n public string FunctionalCurrency { get; init; }", - "\n public string LineOfBusiness { get; init; }", - "\n public string ValuationApproach { get; init; }", - "\n public string OciType { get; init; }", - "\n ", - "\n //GroupOfContract", - "\n public string Portfolio { get; init; }", - "\n public int AnnualCohort { get; init; }", - "\n public string LiabilityType { get; init; }", - "\n public string Profitability { get; init; }", - "\n public string Partner { get; init; }", - "\n ", - "\n //DataNodeState", - "\n public int Year { get; init; }", - "\n public int Month { get; init; }", - "\n public State State { get; init; }", - "\n public State PreviousState { get; init; }", - "\n ", - "\n public bool IsReinsurance { get; init; }", - "\n ", - "\n public DataNodeData(){}", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9zeoLgvZ8EKhCCDbihId8w", - "cell_type": "markdown", - "source": [ - "", - "\n## Raw Variables (Cashflows)", - "\n", - "\nRaw Variables are used to store **cashflows** on the database during import, i.e. *after* mappings are applied and *before* calculations are applied.", - "\n", - "\nThey are stored on the database for both audit and re-calculation purposes." - ], - "metadata": {} - }, - { - "id": "vy4oWvNmmUGJTicrwsX63Q", - "cell_type": "code", - "source": [ - "public abstract record BaseVariableIdentity {", - "\n [NotVisible]", - "\n [Dimension(typeof(GroupOfContract))]", - "\n [IdentityProperty]", - "\n public string DataNode { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(AocType))]", - "\n [IdentityProperty]", - "\n public string AocType { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(Novelty))]", - "\n [IdentityProperty]", - "\n public string Novelty { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_bTxTL4-o0efG6zNvhuDjg", - "cell_type": "code", - "source": [ - "public abstract record BaseDataRecord : BaseVariableIdentity, IKeyed, IPartitioned {", - "\n [Key]", - "\n [NotVisible] ", - "\n public Guid Id { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [PartitionKey(typeof(PartitionByReportingNodeAndPeriod))]", - "\n public Guid Partition { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(AmountType))]", - "\n [IdentityProperty]", - "\n public string AmountType { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(int),nameof(AccidentYear))]", - "\n [IdentityProperty]", - "\n public int? AccidentYear { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "X688yB4HTEm3riHh8lTrug", - "cell_type": "markdown", - "source": [ - "Basically, RawVariable is defined for a certain Reporting Node, Scenario, Year, Month, Amount Type and Calculation Type:" - ], - "metadata": {} - }, - { - "id": "kfbf0LwJSEGaxyUuPFnsKg", - "cell_type": "code", - "source": [ - "public record RawVariable : BaseDataRecord", - "\n{", - "\n [Conversion(typeof(PrimitiveArrayConverter))]", - "\n public double[] Values { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(CalculationType))]", - "\n [IdentityProperty]", - "\n public string CalculationType { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IeCO6PmNPEioYptDRrzHTA", - "cell_type": "markdown", - "source": [ - "", - "\n## Ifrs Variable", - "\n", - "\nIfrs Variables are used to store:", - "\n", - "\n- **Actual Values**", - "\n- **Present Values**", - "\n", - "\nPresent Values are calculated from the [raw variables](#raw-variables) during the import of cashflows.", - "\n", - "\nIfrs Variables are stored on the database, i.e. they are 'persisted', for performance purposes." - ], - "metadata": {} - }, - { - "id": "H9N-c0drk0GPoWh-VfRXzA", - "cell_type": "code", - "source": [ - "public record IfrsVariable : BaseDataRecord", - "\n{", - "\n public double Value { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(EstimateType))]", - "\n [IdentityProperty]", - "\n public string EstimateType { get; init; }", - "\n ", - "\n [NotVisible] ", - "\n [Dimension(typeof(EconomicBasis))]", - "\n [IdentityProperty]", - "\n public string EconomicBasis { get; init; }", - "\n ", - "\n public IfrsVariable (){}", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MCh8EtPVKUyEIcixf6Q_1Q", - "cell_type": "markdown", - "source": [ - "", - "\n## Import Identity", - "\nThe Import Identity contains the data elements used to determine the data sets which are used when performing data manipulations, e.g. during a [data import](./Import/ImportScopeCalculation) - In particular, an Import Identity is defined by: DataNode, AocType, Novelty, and whether it's reinsurance data or not:" - ], - "metadata": {} - }, - { - "id": "w5SSaFTyYE-3Xj0yy0eobw", - "cell_type": "code", - "source": [ - "public record ImportIdentity : BaseVariableIdentity {", - "\n ", - "\n [NotVisible]", - "\n public bool IsReinsurance { get; init; }", - "\n ", - "\n [NotVisible]", - "\n public string ValuationApproach { get; init; }", - "\n ", - "\n [NotVisible]", - "\n public int ProjectionPeriod { get; init; }", - "\n ", - "\n public (string, string) AocStep => (AocType, Novelty);", - "\n ", - "\n public ImportScope ImportScope { get; init; }", - "\n ", - "\n public ImportIdentity(RawVariable rv){", - "\n DataNode = rv.DataNode;", - "\n AocType = rv.AocType;", - "\n Novelty = rv.Novelty;", - "\n }", - "\n ", - "\n public ImportIdentity(IfrsVariable iv){", - "\n DataNode = iv.DataNode;", - "\n AocType = iv.AocType;", - "\n Novelty = iv.Novelty;", - "\n }", - "\n", - "\n public ImportIdentity(){}", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "31-e-C4gwESKBN8E0Rr6gQ", - "cell_type": "markdown", - "source": [ - "", - "\n# Report Variable", - "\n", - "\nReport Variables are used to hold data after data manipulations and before being outputed in the form of a report. They are not persisted, i.e. they are not saved on the database." - ], - "metadata": {} - }, - { - "id": "2yvEMKViYE6wZPnuy7AClg", - "cell_type": "code", - "source": [ - "public record ReportVariable {", - "\n", - "\n [NotVisible]", - "\n [Dimension(typeof(ReportingNode))]", - "\n [IdentityProperty]", - "\n public string ReportingNode { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Scenario))]", - "\n [IdentityProperty]", - "\n public string Scenario { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Currency), nameof(FunctionalCurrency))]", - "\n [IdentityProperty]", - "\n //[AggregateBy]", - "\n public string FunctionalCurrency { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Currency), nameof(ContractualCurrency))]", - "\n [IdentityProperty]", - "\n //[AggregateBy]", - "\n public string ContractualCurrency { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(GroupOfContract))]", - "\n [IdentityProperty]", - "\n public string GroupOfContract { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Portfolio))]", - "\n [IdentityProperty]", - "\n public string Portfolio { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(LineOfBusiness))]", - "\n [IdentityProperty]", - "\n public string LineOfBusiness { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(LiabilityType))]", - "\n [IdentityProperty]", - "\n public string LiabilityType { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Profitability), nameof(InitialProfitability))]", - "\n [IdentityProperty]", - "\n public string InitialProfitability { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(ValuationApproach))]", - "\n [IdentityProperty]", - "\n public string ValuationApproach { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(AnnualCohort))]", - "\n [IdentityProperty]", - "\n public int AnnualCohort { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(OciType))]", - "\n [IdentityProperty]", - "\n public string OciType { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Partner))]", - "\n [IdentityProperty]", - "\n public string Partner { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [IdentityProperty]", - "\n public bool IsReinsurance { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(AccidentYear))]", - "\n [IdentityProperty]", - "\n public int AccidentYear { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [NoArithmetics(ArithmeticOperation.Scale)]", - "\n [Dimension(typeof(int), nameof(Projection))]", - "\n [IdentityProperty]", - "\n //[AggregateBy]", - "\n public int Projection { get; init;}", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(VariableType))]", - "\n [IdentityProperty]", - "\n public string VariableType { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(Novelty))]", - "\n [IdentityProperty]", - "\n public string Novelty { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(AmountType))]", - "\n [IdentityProperty]", - "\n public string AmountType { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(EstimateType))]", - "\n [IdentityProperty]", - "\n public string EstimateType { get; init; }", - "\n ", - "\n [NotVisible]", - "\n [Dimension(typeof(EconomicBasis))]", - "\n [IdentityProperty]", - "\n //[AggregateBy]", - "\n public string EconomicBasis { get; init; }", - "\n ", - "\n public double Value { get; init; }", - "\n ", - "\n public ReportVariable(){}", - "\n public ReportVariable(ReportVariable rv){", - "\n ReportingNode = rv.ReportingNode;", - "\n Scenario = rv.Scenario;", - "\n FunctionalCurrency = rv.FunctionalCurrency;", - "\n ContractualCurrency = rv.ContractualCurrency;", - "\n GroupOfContract = rv.GroupOfContract;", - "\n Portfolio = rv.Portfolio;", - "\n LineOfBusiness = rv.LineOfBusiness;", - "\n LiabilityType = rv.LiabilityType;", - "\n InitialProfitability = rv.InitialProfitability;", - "\n ValuationApproach = rv.ValuationApproach;", - "\n AnnualCohort = rv.AnnualCohort;", - "\n OciType = rv.OciType;", - "\n Partner = rv.Partner;", - "\n IsReinsurance = rv.IsReinsurance;", - "\n AccidentYear = rv.AccidentYear;", - "\n Projection = rv.Projection;", - "\n VariableType = rv.VariableType;", - "\n Novelty = rv.Novelty;", - "\n AmountType = rv.AmountType;", - "\n EstimateType = rv.EstimateType;", - "\n EconomicBasis = rv.EconomicBasis;", - "\n Value = rv.Value;", - "\n }", - "\n public ReportVariable(DataNodeData dn, IfrsVariable iv){", - "\n FunctionalCurrency = dn.FunctionalCurrency;", - "\n ContractualCurrency = dn.ContractualCurrency;", - "\n GroupOfContract = dn.DataNode;", - "\n Portfolio = dn.Portfolio;", - "\n LineOfBusiness = dn.LineOfBusiness;", - "\n LiabilityType = dn.LiabilityType;", - "\n InitialProfitability = dn.Profitability;", - "\n ValuationApproach = dn.ValuationApproach;", - "\n AnnualCohort = dn.AnnualCohort;", - "\n OciType = dn.OciType;", - "\n Partner = dn.Partner;", - "\n IsReinsurance = dn.IsReinsurance;", - "\n AccidentYear = iv.AccidentYear ?? default;", - "\n VariableType = iv.AocType;", - "\n Novelty = iv.Novelty;", - "\n AmountType = iv.AmountType;", - "\n EstimateType = iv.EstimateType;", - "\n EconomicBasis = iv.EconomicBasis;", - "\n Value = iv.Value;", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WtIFU8efQE2aUaVim03Iog", - "cell_type": "markdown", - "source": [ - "# Args" - ], - "metadata": {} - }, - { - "id": "i8WBwS3IuUqLxaV5XGKWsg", - "cell_type": "code", - "source": [ - "public record Args(string ReportingNode, int Year, int Month, Periodicity Periodicity, string Scenario){}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6FcgQqQpzE2yPeqwZNRfiQ", - "cell_type": "code", - "source": [ - "public record ImportArgs : Args", - "\n{", - "\n public string ImportFormat { get; init; }", - "\n ", - "\n public ImportArgs(string reportingNode, int year, int month, Periodicity periodicity, string scenario, string importFormat)", - "\n : base(reportingNode, year, month, periodicity, scenario)", - "\n {", - "\n ImportFormat = importFormat;", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mJUZ9khq1k-jUZcG-qZniQ", - "cell_type": "code", - "source": [ - "public record ReportArgs : Args", - "\n{", - "\n public string HierarchyName { get; init; }", - "\n ", - "\n public CurrencyType CurrencyType { get; init; }", - "\n ", - "\n public string ReportName { get; init; } // this is the key to which data to load (like loading behavior). If null, loads everything", - "\n ", - "\n public ReportArgs(string reportingNode, int year, int month, Periodicity periodicity, string scenario, string hierarchyName, CurrencyType currencyType)", - "\n : base(reportingNode, year, month, periodicity, scenario)", - "\n {", - "\n CurrencyType = currencyType;", - "\n HierarchyName = hierarchyName;", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Data Model

", + "\n", + "\nThis notebook has the main structures used to hold data - This is usually called the **data model**." + ] + }, + { + "cell_type": "markdown", + "source": [ + "# References", + "\nThis section initializes libraries and code from other notebooks, which will be used here, as well as information needed for querying data from the database." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Libraries" + ] + }, + { + "cell_type": "code", + "source": [ + "#r \"nuget:Systemorph.Workspace,1.2.0\"", + "\n#r \"nuget:Systemorph.Scopes,1.2.4\"", + "\n#r \"nuget:Systemorph.Import,1.3.0\"", + "\n#r \"nuget:Systemorph.Test,1.2.4\"", + "\n#r \"nuget:Systemorph.Export,1.3.0\"", + "\n#r \"nuget:Systemorph.DataSetReader,1.3.0\"", + "\n#r \"nuget:Systemorph.DataSource,1.2.0\"", + "\n#r \"nuget:Systemorph.DataSource.Conversions,1.2.0\"", + "\n#r \"nuget:Systemorph.Reporting,1.2.4\"", + "\n#r \"nuget:Systemorph.DomainDesigner,1.3.0\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Usings" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.ComponentModel.DataAnnotations;", + "\nusing System.ComponentModel.DataAnnotations.Schema;", + "\nusing Systemorph.Vertex.Grid.Model;", + "\nusing static Systemorph.Vertex.Arithmetics.ArithmeticOperations;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Notebooks" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Constants/Enums\"", + "\n#!import \"../Constants/Consts\"", + "\n#!import \"../Constants/Validations\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Infrastructure" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Base Interfaces", + "\nThe following interfaces are used to define the granularity at which data is stored.", + "\n", + "\nFor instance, the IKeyed interface corresponds to the lowest granularity which is simply a unique identifier for a certain generic piece of data:" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IKeyed", + "\n{ ", + "\n public Guid Id { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The interface IPartition identifies the partitions in the system." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IPartition : IKeyed {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The interface IPartitioned simply assigns a unique identifier for elements of a data partition - The exact definition of such elements can be found in the [partition](#partition) section below." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IPartitioned", + "\n{", + "\n public Guid Partition { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The interface IHierarchy is used for modelling dimensions which have an hierarchical structure, such as [Amount Type](#amount-type)." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IHierarchy", + "\n{", + "\n [Display(Order = 10)]", + "\n public string Name { get; init; }", + "\n ", + "\n [Display(Order = 20)]", + "\n public string Parent { get; init; }", + "\n ", + "\n [Display(Order = 30)]", + "\n public string Child { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The interface IWithYearAndMonth allows to speficy to which year and month a certain piece of data applies to:" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IWithYearAndMonth", + "\n{", + "\n public int Year { get; init; }", + "\n ", + "\n public int Month { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Abstract Classes", + "\nThese classes are not reflected in the database, i.e. are not persisted." + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record KeyedRecord : IKeyed {", + "\n [Key]", + "\n [NotVisible] ", + "\n public Guid Id { get; init; }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record KeyedDimension : INamed {", + "\n [Key]", + "\n [IdentityProperty]", + "\n [StringLength(16)]", + "\n [Display(Order = 1)]", + "\n public string SystemName { get; init; }", + "\n ", + "\n [Display(Order = 2)]", + "\n [NotVisible]", + "\n public string DisplayName { get; init; }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record KeyedOrderedDimension : KeyedDimension, IOrdered {", + "\n [NotVisible]", + "\n public int Order { get; init; }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record KeyedOrderedDimensionWithExternalId : KeyedOrderedDimension {", + "\n [Display(Order = 100)]", + "\n [Conversion(typeof(JsonConverter))]", + "\n public string[] ExternalId { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Dimensions", + "\n", + "\nDimensions are data which tipically can be given a short name, here called 'System Name'. They also change slowly with time. A typical example is currencies, and examples of System Names are EUR, CHF, etc.", + "\n", + "\nThe advantages of using Dimensions are:", + "\n- The data is easier to maintain (the data is said to be 'normalized');", + "\n- The business logic is easier to read;", + "\n- Easier scructuring of the data, e.g. in a data-cube." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Hierarchical Dimension With Level", + "\nHierarchical dimensions are useful to define for example the legal structure of a company (reporting nodes and their parents).", + "\n", + "\nBelow we introduce the concept of a hierarchical dimension with level, which is a simple way to keep track of the \"level\" in a hierarchical dimension." + ] + }, + { + "cell_type": "code", + "source": [ + "//TODO: Should this be abstract or have a reference to the type?", + "\npublic record HierarchicalDimensionWithLevel(string SystemName, string DisplayName, string Parent, int Level) : IHierarchicalDimension;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Amount Type" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Amount Type is a dimension used to describe the nature of numbers. For example: Numbers associated to the payment of premiums have Amount Type 'Premiums'; Numbers associated to the payment of claims have Amount Type 'Claims'; Numbers associated to expenses have Amount Type 'Expenses'. ", + "\n", + "\nIt is defined as a hierarchical dimension so that higher-granularity types can be introduced. For example: 'Claim Expenses' have parent 'Claims'.", + "\n", + "\nAmount Types are a central piece in the IFRS 17 application and are used for instance to name the different types of cashflows. For example: There might be cashflows for 'Premiums'; Cashflows for 'Claims', etc. In case the mapping between cash flow and amount type is non-trivial, then specific mappings are introduced through the use of ExternalId." + ] + }, + { + "cell_type": "code", + "source": [ + "public record AmountType : KeyedOrderedDimensionWithExternalId, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(AmountType))]", + "\n public string Parent { get; init; }", + "\n ", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(PeriodType))]", + "\n public PeriodType PeriodType { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "We distinguish between amount types used for cashflows and actuals (**Present Value Amount Types**), and amount types used for deferrable values (**Deferrable Amount Types**). In particular, deferrable amount types are for costs and expenses that can be deferred to the future. These amounts are treated separately from the Present Value Amount Types because they are not considered for the calculation of Contractual Service Margin and Loss Component." + ] + }, + { + "cell_type": "code", + "source": [ + "public record PvAmountType : AmountType {} //TODO Rename ", + "\n", + "\npublic record DeferrableAmountType : AmountType {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Calculation Type", + "\nThis dimension is used to distinguish between e.g. **Best Estimate** values and **Risk Adjustment** values:" + ] + }, + { + "cell_type": "code", + "source": [ + "public record CalculationType : KeyedOrderedDimension {", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(PeriodType))]", + "\n public PeriodType PeriodType { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Risk Driver", + "\n", + "\nRisk drivers are used to distinguish between the different Risk Adjustment numbers. For instance: Mortality, Disability, Longevity, etc.", + "\n", + "\nWhen only total risk adjustment values are used, then there is no need to use risk drivers." + ] + }, + { + "cell_type": "code", + "source": [ + "public record RiskDriver : KeyedOrderedDimension, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(RiskDriver))]", + "\n public string Parent { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Estimate Type", + "\n", + "\nEstimate Type is a dimension used to distinguish the context to which numbers belong to. For instance: Numbers for present values have Estimate Type 'Present Value'; Numbers for Risk Adjustments have Estimate Type 'Risk Adjustment'." + ] + }, + { + "cell_type": "code", + "source": [ + "public record EstimateType : KeyedOrderedDimensionWithExternalId", + "\n{", + "\n [Display(Order = 110)]", + "\n public InputSource InputSource { get; init; }", + "\n ", + "\n [Display(Order = 120)]", + "\n public StructureType StructureType { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Novelty", + "\n", + "\nNovelty is a [dimension](#dimensions) used to identity the novelty of the business. Typical examples of Novelty are New Busines, In-Force, and Combined." + ] + }, + { + "cell_type": "code", + "source": [ + "public record Novelty : KeyedOrderedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Variable Type" + ] + }, + { + "cell_type": "code", + "source": [ + "public record VariableType : KeyedOrderedDimension, IHierarchicalDimension", + "\n{ ", + "\n [Display(Order = 10)]", + "\n public string Parent { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### AoC Variable Type", + "\n", + "\nThe AocType describes the type of the Analysis of Change step - For example: Amortization, Cashflow, Combined Liabilities etc.", + "\n", + "\nThe **Combined Liability** AocType aims in capturing the difference between the sum of all relevant previous Aoc steps and the end of period Aoc step. Unexplained changes (not captured by any other defined AoC step), are then visible in this Aoc step. Note that the nominal cash flows input in the cashflow input file corresponds to cash flow projection for the end of period step.", + "\nIn addition, this step distinguishes itself from the others for:", + "\n- It is a mandatory AocType as it is used to trigger the Run off of the cashflow. This is achieved by providing a cash flow of 0s. ", + "\n- It is the first AocType for the Combined Novelty and therefore it carries the contribution of combining In force and New business.", + "\n- Its present value is computed as telescoping difference with the last AoC Step for the In-Force novelty and the New Business novelty.", + "\n- In the technical margin calculation it is used to merge the profitability of the In-Force and New business components, which may result in a forced switch." + ] + }, + { + "cell_type": "code", + "source": [ + "public record AocType : VariableType", + "\n{ ", + "\n [Display(Order = 30)]", + "\n [Dimension(typeof(AocType))]", + "\n public string Parent { get; init; }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public record AocStep(string AocType, string Novelty){}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### PnL Variable Type", + "\n", + "\nThe PnlVariableType is used to describe the various profit and loss sections and the corresponding hierarchy." + ] + }, + { + "cell_type": "code", + "source": [ + "public record PnlVariableType : VariableType {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Balance Sheet Variable Type", + "\n", + "\nThe BsVariableType is used to descibe the Anlysis of change of the Balance Sheet reports." + ] + }, + { + "cell_type": "code", + "source": [ + "public record BsVariableType : VariableType {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Accounting Variable Type", + "\nThe AccountingVariableType is used to describe the accounting events that are posted in the accounting output file." + ] + }, + { + "cell_type": "code", + "source": [ + "public record AccountingVariableType : VariableType {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Scenario", + "\nThe Scenario record holds the various scenarios for which calculations should also be performed." + ] + }, + { + "cell_type": "code", + "source": [ + "public record Scenario : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + " The 'neutral' Scenario (i.e. the default one, with no-stress situations applied) is designated as 'Best Estimate'." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Line Of Business" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Line Of Business is a dimension used to identity insurance business according to usual business classifications (usually a market or company-specific business classification representing a convolution of risk covered, 1st party / 3rd party cover type, product type, etc...)", + "\nTypical examples of Line of Business are Motor, Property, Endowment, etc... This is a hierarchical dimension." + ] + }, + { + "cell_type": "code", + "source": [ + "public record LineOfBusiness : KeyedOrderedDimension, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(LineOfBusiness))]", + "\n public string Parent { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Currency" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Currency is a dimension used to identity the currency.", + "\nTypical examples of Currency are EUR, CHF, USD, etc..." + ] + }, + { + "cell_type": "code", + "source": [ + "public record Currency : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Economic Basis", + "\n", + "\nThe Economic Basis defines the discount type which is used in calculations. Examples are: Nominal, Current and Locked." + ] + }, + { + "cell_type": "code", + "source": [ + "public record EconomicBasis : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Valuation Approach", + "\nThis dimension holds the various methodologies used in the calculations: BBA, VFA and PAA." + ] + }, + { + "cell_type": "code", + "source": [ + "public record ValuationApproach : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Liability Type", + "\nThe Liability Type distinguishes betweeen e.g. liabilities for incurred claims and liabilities for remaining coverage." + ] + }, + { + "cell_type": "code", + "source": [ + "public record LiabilityType : KeyedDimension, IHierarchicalDimension", + "\n{", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(LiabilityType))]", + "\n public string Parent { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## OCI Type", + "\nOther Comprehensive Income (OCI) Type describes how the financial contributions to the IFRS17 Financial Performance is apportioned between the P&L and the OCI sections." + ] + }, + { + "cell_type": "code", + "source": [ + "public record OciType : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Profitability" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Profitability is a dimension used in IFRS 17 to describe the profitability of a Group of Contracts (GIC/GRIC).", + "\nTypical examples of Profitability are Profitable, Non-Profitable, etc.." + ] + }, + { + "cell_type": "code", + "source": [ + "public record Profitability : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Partner", + "\nPartner is the counterparty of a reinsurance contract." + ] + }, + { + "cell_type": "code", + "source": [ + "public record Partner : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Credit Risk Rating", + "\nThis holds the credit risk rating of each Partner." + ] + }, + { + "cell_type": "code", + "source": [ + "public record CreditRiskRating : KeyedDimension {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Reporting Node", + "\nA Reporting Node is an element in the reporting structure of the company. It has a hierarchical structure and the end nodes is the level at which data is imported." + ] + }, + { + "cell_type": "code", + "source": [ + "public record ReportingNode : KeyedDimension, IHierarchicalDimension ", + "\n{", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(ReportingNode))]", + "\n public string Parent { get; init; }", + "\n ", + "\n [Required]", + "\n [Display(Order = 40)]", + "\n [Dimension(typeof(Currency))]", + "\n public virtual string Currency { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Projection Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Projections are configured by defining the following 2 parameters:", + "\n", + "\n- Shift defines how many months are in the cashflow file before the first value of the period in interest.
", + "\n- TimeStep defines how many months are in the period of interest.
", + "\n", + "\nBoth Shift and TimeStep are measured in terms of number of months.", + "\nFor instance, for the current year and year-to-date view we have $\\rm{Shift}=0$ and $TimeStep=3$ for the first quarter, $TimeStep=6$ for the 2nd quarter and so on." + ] + }, + { + "cell_type": "code", + "source": [ + "public record ProjectionConfiguration : KeyedDimension", + "\n{", + "\n [IdentityProperty]", + "\n public int Shift { get; init; }", + "\n [IdentityProperty]", + "\n public int TimeStep { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Parameters" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Aoc Step Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The record below holds parameters over time for each combination of AocType and Novelty. In particular:", + "\n- DataType identifies between Calculated aoc steps and Optional inputs or Mandatory inputs.", + "\n- InputSource identifies whether an aoc step is relevant for Actuals, Cashflow or both calculations.", + "\n- FxPeriod identifies which fx rate should be used.", + "\n- YcPeriod identifies which Yield Curve should be used (from current or previous period).", + "\n- CdrPeriod identifies which Credit Default Rate should be used (from current or previous period).", + "\n- ValuationPeriod identifies which value from the Cashflow corresponds to the Present Value.", + "\n- RcPeriod identifies which Reinsurance Coverage should be used (from current or previous period).", + "\n", + "\n
The values for each parameter can be found in [Enums Notebook](./Constants/Enums)." + ] + }, + { + "cell_type": "code", + "source": [ + "public record AocConfiguration : KeyedRecord, IWithYearAndMonth, IOrdered", + "\n{", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 10)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Month { get; init; }", + "\n ", + "\n [IdentityProperty]", + "\n [Display(Order = 30)]", + "\n [Dimension(typeof(AocType))]", + "\n public string AocType { get; init; }", + "\n ", + "\n [IdentityProperty]", + "\n [Display(Order = 40)]", + "\n [Dimension(typeof(Novelty))]", + "\n public string Novelty { get; init; }", + "\n ", + "\n [Display(Order = 50)]", + "\n [Dimension(typeof(DataType))]", + "\n public DataType DataType { get; init; }", + "\n ", + "\n [Display(Order = 55)]", + "\n [Dimension(typeof(InputSource))]", + "\n public InputSource InputSource { get; init; }", + "\n ", + "\n [Display(Order = 60)]", + "\n [Dimension(typeof(FxPeriod))]", + "\n public FxPeriod FxPeriod { get; init; }", + "\n ", + "\n [Display(Order = 70)]", + "\n [Dimension(typeof(PeriodType), nameof(YcPeriod))]", + "\n public PeriodType YcPeriod { get; init; }", + "\n ", + "\n [Display(Order = 80)]", + "\n [Dimension(typeof(PeriodType), nameof(CdrPeriod))]", + "\n public PeriodType CdrPeriod { get; init; }", + "\n ", + "\n [Display(Order = 90)]", + "\n [Dimension(typeof(ValuationPeriod))]", + "\n public ValuationPeriod ValuationPeriod { get; init; }", + "\n ", + "\n [Display(Order = 100)]", + "\n [Dimension(typeof(PeriodType), nameof(RcPeriod))]", + "\n public PeriodType RcPeriod { get; init; }", + "\n ", + "\n [NotVisible]", + "\n public int Order { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Exchange Rate", + "\nThe record below holds the Exchange Rates over time and for each exchange type ([FxType](./Constants/Enums)). Exchange Rate must be updated every reporting period as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", + "\n", + "\nIn case the Exchange Rate for the current period is missing, an error is returned. " + ] + }, + { + "cell_type": "code", + "source": [ + "public record ExchangeRate : KeyedRecord", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(Currency))]", + "\n public string Currency { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Month { get; init; }", + "\n", + "\n [IdentityProperty]", + "\n [Required]", + "\n [Display(Order = 40)]", + "\n public FxType FxType { get; init; }", + "\n", + "\n [Display(Order = 50)]", + "\n public double FxToGroupCurrency { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Credit Default Rate", + "\nThe record below holds the Credit Default Rates over time for each [Credit Risk Rating](#credit-risk-rating). Credit Default Rate can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", + "\n", + "\nThe Credit Default Rate values must be entered with monthly granularity, i.e. every value corresponds to the default rate for a certain month. The first month entered in column Values0 always corresponds to January of the year entered in column Year. The last value is considered valid also for the following years (for which no value has been provided). ", + "\n", + "\nThe latest Credit Default Rate 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." + ] + }, + { + "cell_type": "code", + "source": [ + "public record CreditDefaultRate : KeyedRecord, IWithYearAndMonth", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(CreditRiskRating))]", + "\n public string CreditRiskRating { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Month { get; init; }", + "\n ", + "\n [Conversion(typeof(PrimitiveArrayConverter))]", + "\n [Display(Order = 40)]", + "\n public double[] Values { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Yield Curve", + "\nThe record below holds the Yield Curves across time for each [Currency](#currency) and [Scenario](#scenario).", + "\nYield curves can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. ", + "\n", + "\nThe Yield Curve values must be entered with **yearly** granularity, i.e. every value corresponds to the rate of the whole year starting from the year entered in column Year. The last value is considered valid also for the following years (for which no value has been provided). ", + "\n", + "\nWhen the current Yield Curve must be used in the calculation, the latest Yield Curve available in the system with Year and Month earlier or equal to Year and Month of the closing period will be used." + ] + }, + { + "cell_type": "code", + "source": [ + "public record YieldCurve : KeyedRecord, IWithYearAndMonth", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(Currency))]", + "\n public string Currency { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Month { get; init; }", + "\n", + "\n [IdentityProperty]", + "\n [Display(Order = 35)]", + "\n public string Scenario { get; init; }", + "\n", + "\n [Conversion(typeof(PrimitiveArrayConverter))]", + "\n [Display(Order = 40)]", + "\n public double[] Values { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Partner Rating", + "\nThe record below holds the [Credit Risk Rating](#credit-risk-partner) for each [Partner](#partner) across time. Partner Rating can be updated every month as part of the close preparation. In general, the last month of the reporting period should be use to import the new data for the period. " + ] + }, + { + "cell_type": "code", + "source": [ + "public record PartnerRating : KeyedRecord, IWithYearAndMonth", + "\n{ ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(Partner))]", + "\n public string Partner { get; init; }", + "\n", + "\n [Required]", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(CreditRiskRating))]", + "\n public string CreditRiskRating { get; init; }", + "\n", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 40)]", + "\n public int Month { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Partitions", + "\nThe notion of Partition is used to define small but meaningful sets of data, called partitions. Partitions are then used to optimize the extraction of data from the database, i.e. only the data for a certain partition is retrieved." + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record IfrsPartition : IPartition {", + "\n [Key]", + "\n [PartitionId]", + "\n public Guid Id { get; init; }", + "\n", + "\n [Required]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(ReportingNode))]", + "\n [IdentityProperty]", + "\n public string ReportingNode { get; init; }", + "\n", + "\n [Display(Order = 50)]", + "\n [Dimension(typeof(Scenario))]", + "\n [IdentityProperty]", + "\n public string Scenario { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For instance, the data pertaining to a certain [Reporting Node](#reporting-node) for a certain [Scenario](#scenario) is called an IfrsPartition and assigned a unique identifier:" + ] + }, + { + "cell_type": "code", + "source": [ + "public record PartitionByReportingNode : IfrsPartition {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The partition PartitionByReportingNodeAndPeriod is a further partition of the IfrsPartition sets - In particular, it defines sets for the data pertaining to a certain [Reporting Node](#reporting-node), [Scenario](#scenario), year and month. The value of the Month is the last month of the reporting period to which the data belongs to. " + ] + }, + { + "cell_type": "code", + "source": [ + "public record PartitionByReportingNodeAndPeriod : IfrsPartition {", + "\n [Display(Order = 30)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [IdentityProperty]", + "\n public int Year { get; init; }", + "\n", + "\n [Display(Order = 40)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [IdentityProperty]", + "\n public int Month { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Policy-related Data Structures", + "\n", + "\nThe data structures below are the pieces of the data model where policy-related data is held." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data Node", + "\n", + "\nA data node is basically a set of labels which identify data according to its:", + "\n- Reporting Node", + "\n- Scenario", + "\n- Contractual Currency", + "\n- FunctionalCurrency", + "\n- LineOfBusiness", + "\n- ValuationApproach", + "\n- OCI Type" + ] + }, + { + "cell_type": "markdown", + "source": [ + "TODOs:", + "\n
    ", + "\n
  • Remove Scenario from Partition and include it as simple property (see Year, Month). Introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", + "\n
" + ] + }, + { + "cell_type": "code", + "source": [ + "public record DataNode : KeyedDimension, IPartitioned {", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNode))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Currency))]", + "\n //[Required] // TODO: check", + "\n //[Immutable] // TODO: Not available yet", + "\n public string ContractualCurrency { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Currency))]", + "\n //[Required] // TODO: check", + "\n //[Immutable]", + "\n public string FunctionalCurrency { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(LineOfBusiness))]", + "\n //[Immutable]", + "\n public string LineOfBusiness { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(ValuationApproach))]", + "\n [Required]", + "\n //[Immutable]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(OciType))]", + "\n //[Immutable]", + "\n public string OciType { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Portfolios", + "\n", + "\nA Portfolio is a set of Group of Contracts. The relationship is set on the Group of Contracts (see below).", + "\n", + "\nPortfolios are of type DataNode and there are two types: Insurance Portfolio and Reinsurance Portfolios." + ] + }, + { + "cell_type": "code", + "source": [ + "public record Portfolio : DataNode {}", + "\n", + "\npublic record InsurancePortfolio : Portfolio {}", + "\npublic record ReinsurancePortfolio : Portfolio {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Group of Contracts", + "\n", + "\nA Group of Contract is a set of contracts with the same Annual Cohort, Liability Type, Profitability and Partner (in case the contracts are done with a re-insurer).", + "\n", + "\nVarious Group of Contracts are put together into portfolios." + ] + }, + { + "cell_type": "code", + "source": [ + "public record GroupOfContract : DataNode {", + "\n [NotVisible] ", + "\n [Dimension(typeof(int), nameof(AnnualCohort))]", + "\n //[Immutable]", + "\n public int AnnualCohort { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(LiabilityType))]", + "\n //[Immutable]", + "\n public string LiabilityType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Profitability))]", + "\n //[Immutable]", + "\n public string Profitability { get; init; }", + "\n ", + "\n [Required]", + "\n [NotVisible] ", + "\n [Dimension(typeof(Portfolio))]", + "\n //[Immutable]", + "\n public string Portfolio { get; init; }", + "\n ", + "\n public virtual string Partner { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "A group of insurance contracts is called a **GIC** and has no information on Partner.", + "\n", + "\nOnly Groups of Reinsurance Contracts, defined below and usually called **GRIC**s, have Partner information.", + "\nAgain, there are Insurance GRICs and Reinsurance GRICs:" + ] + }, + { + "cell_type": "code", + "source": [ + "public record GroupOfInsuranceContract : GroupOfContract {", + "\n [Required]", + "\n [NotVisible] ", + "\n [Display(Name = \"InsurancePortfolio\")]", + "\n [Dimension(typeof(InsurancePortfolio))]", + "\n //[Immutable]", + "\n public string Portfolio { get => base.Portfolio; init => base.Portfolio = value; }", + "\n ", + "\n // TODO: for the case of internal reinsurance the Partner would be the reporting node, hence not null.", + "\n // If this is true we need the [Required] attribute here, add some validation at dataNode import ", + "\n // and to add logic in the GetNonPerformanceRiskRate method in ImportStorage.", + "\n [NotVisible] ", + "\n [NotMapped]", + "\n //[Immutable]", + "\n public override string Partner => null;", + "\n}", + "\n", + "\npublic record GroupOfReinsuranceContract : GroupOfContract {", + "\n [Required]", + "\n [NotVisible] ", + "\n [Display(Name = \"ReinsurancePortfolio\")]", + "\n [Dimension(typeof(ReinsurancePortfolio))]", + "\n //[Immutable]", + "\n public string Portfolio { get => base.Portfolio; init => base.Portfolio = value; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data Node State", + "\n", + "\nThe Data State is used to track whether a GOC is Active or Inactive across time (year and month). ", + "\nIt is only possible to update the state of a Group of Contract from Active to Inactive." + ] + }, + { + "cell_type": "code", + "source": [ + "public record DataNodeState : KeyedRecord, IPartitioned, IWithYearAndMonth", + "\n{", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNode))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n public string DataNode { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n [DefaultValue(DefaultDataNodeActivationMonth)]", + "\n public int Month { get; init; } = DefaultDataNodeActivationMonth;", + "\n ", + "\n [Required]", + "\n [Display(Order = 40)]", + "\n [DefaultValue(State.Active)]", + "\n public State State { get; init; } = State.Active;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data Node Parameters", + "\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 AocType of the Technical Margin and is valid only for Group of Insurance Contract with LiabilityType : Liability for Remaining Coverage.", + "\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.", + "\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." + ] + }, + { + "cell_type": "code", + "source": [ + "public record DataNodeParameter : KeyedRecord, IPartitioned, IWithYearAndMonth", + "\n{", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNode))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n [Range(1900, 2100, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 20)]", + "\n public int Year { get; init; }", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n [Range(1, 12, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n [Display(Order = 30)]", + "\n [DefaultValue(DefaultDataNodeActivationMonth)]", + "\n public int Month { get; init; } = DefaultDataNodeActivationMonth;", + "\n ", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 10)]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n public string DataNode { get; init; }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public record SingleDataNodeParameter : DataNodeParameter {", + "\n [DefaultValue(DefaultPremiumExperienceAdjustmentFactor)]", + "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n public double PremiumAllocation { get; init; } = DefaultPremiumExperienceAdjustmentFactor;", + "\n}", + "\n", + "\npublic record InterDataNodeParameter : DataNodeParameter {", + "\n [Required]", + "\n [IdentityProperty]", + "\n [Display(Order = 20)]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n public string LinkedDataNode { get; init; }", + "\n ", + "\n [Range(0, 1, ErrorMessage = \"Value for {0} must be between {1} and {2}.\")]", + "\n public double ReinsuranceCoverage { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## DataNodeData PocoType", + "\nThe DataNodeData type is not persisted (i.e. not stored in the database) and is used in order to hold Data Node data during data manipulations." + ] + }, + { + "cell_type": "code", + "source": [ + "public record DataNodeData {", + "\n public string DataNode { get; init; }", + "\n ", + "\n //Portfolio", + "\n public string ContractualCurrency { get; init; }", + "\n public string FunctionalCurrency { get; init; }", + "\n public string LineOfBusiness { get; init; }", + "\n public string ValuationApproach { get; init; }", + "\n public string OciType { get; init; }", + "\n ", + "\n //GroupOfContract", + "\n public string Portfolio { get; init; }", + "\n public int AnnualCohort { get; init; }", + "\n public string LiabilityType { get; init; }", + "\n public string Profitability { get; init; }", + "\n public string Partner { get; init; }", + "\n ", + "\n //DataNodeState", + "\n public int Year { get; init; }", + "\n public int Month { get; init; }", + "\n public State State { get; init; }", + "\n public State PreviousState { get; init; }", + "\n ", + "\n public bool IsReinsurance { get; init; }", + "\n ", + "\n public DataNodeData(){}", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Raw Variables (Cashflows)", + "\n", + "\nRaw Variables are used to store **cashflows** on the database during import, i.e. *after* mappings are applied and *before* calculations are applied.", + "\n", + "\nThey are stored on the database for both audit and re-calculation purposes." + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record BaseVariableIdentity {", + "\n [NotVisible]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n [IdentityProperty]", + "\n public string DataNode { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(AocType))]", + "\n [IdentityProperty]", + "\n public string AocType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(Novelty))]", + "\n [IdentityProperty]", + "\n public string Novelty { get; init; }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public abstract record BaseDataRecord : BaseVariableIdentity, IKeyed, IPartitioned {", + "\n [Key]", + "\n [NotVisible] ", + "\n public Guid Id { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [PartitionKey(typeof(PartitionByReportingNodeAndPeriod))]", + "\n public Guid Partition { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(AmountType))]", + "\n [IdentityProperty]", + "\n public string AmountType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(int),nameof(AccidentYear))]", + "\n [IdentityProperty]", + "\n public int? AccidentYear { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Basically, RawVariable is defined for a certain Reporting Node, Scenario, Year, Month, Amount Type and Calculation Type:" + ] + }, + { + "cell_type": "code", + "source": [ + "public record RawVariable : BaseDataRecord", + "\n{", + "\n [Conversion(typeof(PrimitiveArrayConverter))]", + "\n public double[] Values { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(CalculationType))]", + "\n [IdentityProperty]", + "\n public string CalculationType { get; init; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Ifrs Variable", + "\n", + "\nIfrs Variables are used to store:", + "\n", + "\n- **Actual Values**", + "\n- **Present Values**", + "\n", + "\nPresent Values are calculated from the [raw variables](#raw-variables) during the import of cashflows.", + "\n", + "\nIfrs Variables are stored on the database, i.e. they are 'persisted', for performance purposes." + ] + }, + { + "cell_type": "code", + "source": [ + "public record IfrsVariable : BaseDataRecord", + "\n{", + "\n public double Value { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(EstimateType))]", + "\n [IdentityProperty]", + "\n public string EstimateType { get; init; }", + "\n ", + "\n [NotVisible] ", + "\n [Dimension(typeof(EconomicBasis))]", + "\n [IdentityProperty]", + "\n public string EconomicBasis { get; init; }", + "\n ", + "\n public IfrsVariable (){}", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Import Identity", + "\nThe Import Identity contains the data elements used to determine the data sets which are used when performing data manipulations, e.g. during a [data import](./Import/ImportScopeCalculation) - In particular, an Import Identity is defined by: DataNode, AocType, Novelty, and whether it's reinsurance data or not:" + ] + }, + { + "cell_type": "code", + "source": [ + "public record ImportIdentity : BaseVariableIdentity {", + "\n ", + "\n [NotVisible]", + "\n public bool IsReinsurance { get; init; }", + "\n ", + "\n [NotVisible]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n [NotVisible]", + "\n public int ProjectionPeriod { get; init; }", + "\n ", + "\n public (string, string) AocStep => (AocType, Novelty);", + "\n ", + "\n public ImportScope ImportScope { get; init; }", + "\n ", + "\n public ImportIdentity(RawVariable rv){", + "\n DataNode = rv.DataNode;", + "\n AocType = rv.AocType;", + "\n Novelty = rv.Novelty;", + "\n }", + "\n ", + "\n public ImportIdentity(IfrsVariable iv){", + "\n DataNode = iv.DataNode;", + "\n AocType = iv.AocType;", + "\n Novelty = iv.Novelty;", + "\n }", + "\n", + "\n public ImportIdentity(){}", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Report Variable", + "\n", + "\nReport Variables are used to hold data after data manipulations and before being outputed in the form of a report. They are not persisted, i.e. they are not saved on the database." + ] + }, + { + "cell_type": "code", + "source": [ + "public record ReportVariable {", + "\n", + "\n [NotVisible]", + "\n [Dimension(typeof(ReportingNode))]", + "\n [IdentityProperty]", + "\n public string ReportingNode { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Scenario))]", + "\n [IdentityProperty]", + "\n public string Scenario { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Currency), nameof(FunctionalCurrency))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public string FunctionalCurrency { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Currency), nameof(ContractualCurrency))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public string ContractualCurrency { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(GroupOfContract))]", + "\n [IdentityProperty]", + "\n public string GroupOfContract { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Portfolio))]", + "\n [IdentityProperty]", + "\n public string Portfolio { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(LineOfBusiness))]", + "\n [IdentityProperty]", + "\n public string LineOfBusiness { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(LiabilityType))]", + "\n [IdentityProperty]", + "\n public string LiabilityType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Profitability), nameof(InitialProfitability))]", + "\n [IdentityProperty]", + "\n public string InitialProfitability { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(ValuationApproach))]", + "\n [IdentityProperty]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(AnnualCohort))]", + "\n [IdentityProperty]", + "\n public int AnnualCohort { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(OciType))]", + "\n [IdentityProperty]", + "\n public string OciType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Partner))]", + "\n [IdentityProperty]", + "\n public string Partner { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [IdentityProperty]", + "\n public bool IsReinsurance { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(AccidentYear))]", + "\n [IdentityProperty]", + "\n public int AccidentYear { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [NoArithmetics(ArithmeticOperation.Scale)]", + "\n [Dimension(typeof(int), nameof(Projection))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public int Projection { get; init;}", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(VariableType))]", + "\n [IdentityProperty]", + "\n public string VariableType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(Novelty))]", + "\n [IdentityProperty]", + "\n public string Novelty { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(AmountType))]", + "\n [IdentityProperty]", + "\n public string AmountType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(EstimateType))]", + "\n [IdentityProperty]", + "\n public string EstimateType { get; init; }", + "\n ", + "\n [NotVisible]", + "\n [Dimension(typeof(EconomicBasis))]", + "\n [IdentityProperty]", + "\n //[AggregateBy]", + "\n public string EconomicBasis { get; init; }", + "\n ", + "\n public double Value { get; init; }", + "\n ", + "\n public ReportVariable(){}", + "\n public ReportVariable(ReportVariable rv){", + "\n ReportingNode = rv.ReportingNode;", + "\n Scenario = rv.Scenario;", + "\n FunctionalCurrency = rv.FunctionalCurrency;", + "\n ContractualCurrency = rv.ContractualCurrency;", + "\n GroupOfContract = rv.GroupOfContract;", + "\n Portfolio = rv.Portfolio;", + "\n LineOfBusiness = rv.LineOfBusiness;", + "\n LiabilityType = rv.LiabilityType;", + "\n InitialProfitability = rv.InitialProfitability;", + "\n ValuationApproach = rv.ValuationApproach;", + "\n AnnualCohort = rv.AnnualCohort;", + "\n OciType = rv.OciType;", + "\n Partner = rv.Partner;", + "\n IsReinsurance = rv.IsReinsurance;", + "\n AccidentYear = rv.AccidentYear;", + "\n Projection = rv.Projection;", + "\n VariableType = rv.VariableType;", + "\n Novelty = rv.Novelty;", + "\n AmountType = rv.AmountType;", + "\n EstimateType = rv.EstimateType;", + "\n EconomicBasis = rv.EconomicBasis;", + "\n Value = rv.Value;", + "\n }", + "\n public ReportVariable(DataNodeData dn, IfrsVariable iv){", + "\n FunctionalCurrency = dn.FunctionalCurrency;", + "\n ContractualCurrency = dn.ContractualCurrency;", + "\n GroupOfContract = dn.DataNode;", + "\n Portfolio = dn.Portfolio;", + "\n LineOfBusiness = dn.LineOfBusiness;", + "\n LiabilityType = dn.LiabilityType;", + "\n InitialProfitability = dn.Profitability;", + "\n ValuationApproach = dn.ValuationApproach;", + "\n AnnualCohort = dn.AnnualCohort;", + "\n OciType = dn.OciType;", + "\n Partner = dn.Partner;", + "\n IsReinsurance = dn.IsReinsurance;", + "\n AccidentYear = iv.AccidentYear ?? default;", + "\n VariableType = iv.AocType;", + "\n Novelty = iv.Novelty;", + "\n AmountType = iv.AmountType;", + "\n EstimateType = iv.EstimateType;", + "\n EconomicBasis = iv.EconomicBasis;", + "\n Value = iv.Value;", + "\n }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Args" + ] + }, + { + "cell_type": "code", + "source": [ + "public record Args(string ReportingNode, int Year, int Month, Periodicity Periodicity, string Scenario){}" + ] + }, + { + "cell_type": "code", + "source": [ + "public record ImportArgs : Args", + "\n{", + "\n public string ImportFormat { get; init; }", + "\n ", + "\n public ImportArgs(string reportingNode, int year, int month, Periodicity periodicity, string scenario, string importFormat)", + "\n : base(reportingNode, year, month, periodicity, scenario)", + "\n {", + "\n ImportFormat = importFormat;", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public record ReportArgs : Args", + "\n{", + "\n public string HierarchyName { get; init; }", + "\n ", + "\n public CurrencyType CurrencyType { get; init; }", + "\n ", + "\n public string ReportName { get; init; } // this is the key to which data to load (like loading behavior). If null, loads everything", + "\n ", + "\n public ReportArgs(string reportingNode, int year, int month, Periodicity periodicity, string scenario, string hierarchyName, CurrencyType currencyType)", + "\n : base(reportingNode, year, month, periodicity, scenario)", + "\n {", + "\n CurrencyType = currencyType;", + "\n HierarchyName = hierarchyName;", + "\n }", + "\n}" + ] + } + ] } \ No newline at end of file diff --git a/Database/Configure.ipynb b/Database/Configure.ipynb index 2819a9af..edca53dd 100644 --- a/Database/Configure.ipynb +++ b/Database/Configure.ipynb @@ -1,131 +1,93 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "vWKQtrDv20CeZFovAj82Vw", - "cell_type": "markdown", - "source": [ - "

DataSource Configuration

" - ], - "metadata": {} - }, - { - "id": "ekOMREP2YkKF0vgtOn6cyQ", - "cell_type": "code", - "source": [ - "#!import \"../DataModel/DataStructure\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "eEI7AS2fc0-CFjAR_WzdHg", - "cell_type": "code", - "source": [ - "#!import \"PersonalConnection\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZoHg5nndvEWdxnUy6nU0aQ", - "cell_type": "code", - "source": [ - "using System.Reflection;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "V3sPPe7bkEOIAjZHtM5oTw", - "cell_type": "markdown", - "source": [ - "# Database Configure" - ], - "metadata": {} - }, - { - "id": "ZxIo5q84i02LBlbq4AQnNA", - "cell_type": "code", - "source": [ - "var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())", - "\n .Where(t => (t.IsAssignableTo(typeof(IKeyed)) || t.IsAssignableTo(typeof(KeyedDimension)))", - "\n && !t.IsInterface", - "\n && !t.IsAbstract", - "\n ).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Wi93Z_KSukSEMiLoOfsKXA", - "cell_type": "code", - "source": [ - "await DataSource.Configure().UseMsSql(opt => opt.WithConnectionString(connectionStringMsSql)", - "\n .WithTypes(allTypes)) .ConnectAsync();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4jSr3apQzEm6bXs7ot9uJQ", - "cell_type": "code", - "source": [ - "await DataSource.CommitAsync();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "SUiuO25f-0S6Uv5at0MehA", - "cell_type": "markdown", - "source": [ - "# Reset Workspace" - ], - "metadata": {} - }, - { - "id": "T0pNd11nrkuDwN6S0YgItg", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sAYMeiwmiUWC-T3QYXi7aw", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

DataSource Configuration

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"PersonalConnection\"" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Reflection;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Database Configure" + ] + }, + { + "cell_type": "code", + "source": [ + "var allTypes = AppDomain.CurrentDomain.GetAssemblies().SelectMany(a => a.GetTypes())", + "\n .Where(t => (t.IsAssignableTo(typeof(IKeyed)) || t.IsAssignableTo(typeof(KeyedDimension)))", + "\n && !t.IsInterface", + "\n && !t.IsAbstract", + "\n ).ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "await DataSource.Configure().UseMsSql(opt => opt.WithConnectionString(connectionStringMsSql)", + "\n .WithTypes(allTypes)) .ConnectAsync();" + ] + }, + { + "cell_type": "code", + "source": [ + "await DataSource.CommitAsync();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules());" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Database/Schema Delete.ipynb b/Database/Schema Delete.ipynb index 49792b90..e3e1eb69 100644 --- a/Database/Schema Delete.ipynb +++ b/Database/Schema Delete.ipynb @@ -1,87 +1,63 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "documentInfo": "{\r\n \"authors\": [\r\n \"Peter Kunszt\"\r\n ],\r\n \"contributors\": [],\r\n \"tags\": [\r\n \"storage\",\r\n \"database\",\r\n \"persistence\",\r\n \"dependency\"\r\n ],\r\n \"title\": \"Multiple Storages with Persistence\",\r\n \"description\": \"Demo the usage of database backend to resolve a data dependency.\",\r\n \"createdDate\": \"Jan. 2022\",\r\n \"publishedDate\": \"Jan. 2022\",\r\n \"changelog\": [\r\n {\r\n \"version\": \"1.0\",\r\n \"description\": \"Initial Notebook\"\r\n }\r\n ]\r\n }", + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + } }, - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, - "documentInfo": "{\r\n \"authors\": [\r\n \"Peter Kunszt\"\r\n ],\r\n \"contributors\": [],\r\n \"tags\": [\r\n \"storage\",\r\n \"database\",\r\n \"persistence\",\r\n \"dependency\"\r\n ],\r\n \"title\": \"Multiple Storages with Persistence\",\r\n \"description\": \"Demo the usage of database backend to resolve a data dependency.\",\r\n \"createdDate\": \"Jan. 2022\",\r\n \"publishedDate\": \"Jan. 2022\",\r\n \"changelog\": [\r\n {\r\n \"version\": \"1.0\",\r\n \"description\": \"Initial Notebook\"\r\n }\r\n ]\r\n }" - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "XekEwxVoCk6YtMSTaBi_6A", - "cell_type": "code", - "source": [ - "#!import \"PersonalConnection\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "aMGWTiny-EO8ZtyaiC0M2A", - "cell_type": "code", - "source": [ - "#r \"nuget:SqlConnection,1.0.4\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dKBE6yQHq0CZbS4Oq7ZXag", - "cell_type": "code", - "source": [ - "string[] split = connectionStringMsSql.Split(new char[] { '=', ':', ',', ';' });", - "\n", - "\nstring serverName = split[2];", - "\nstring database = split[5];", - "\nstring userID = split[9];", - "\nstring password = split[11];" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BBbDUGWgHUywoxk289vQ2A", - "cell_type": "code", - "source": [ - "using SQLConnection;", - "\nusing System;", - "\nusing System.Data.SqlClient;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "S-_OArgE70qFUpEbX12H3Q", - "cell_type": "code", - "source": [ - "string query = \"DECLARE @sql NVARCHAR(max)='' SELECT @sql += ' Drop table ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) + '; 'FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' Exec Sp_executesql @sql\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oeQryPr0l0uflGqNrUvmLw", - "cell_type": "code", - "source": [ - "int rowAffect = SqlServer.AzureSqlConnection(serverName, database, userID, password, query);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"PersonalConnection\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#r \"nuget:SqlConnection,1.0.4\"" + ] + }, + { + "cell_type": "code", + "source": [ + "string[] split = connectionStringMsSql.Split(new char[] { '=', ':', ',', ';' });", + "\n", + "\nstring serverName = split[2];", + "\nstring database = split[5];", + "\nstring userID = split[9];", + "\nstring password = split[11];" + ] + }, + { + "cell_type": "code", + "source": [ + "using SQLConnection;", + "\nusing System;", + "\nusing System.Data.SqlClient;" + ] + }, + { + "cell_type": "code", + "source": [ + "string query = \"DECLARE @sql NVARCHAR(max)='' SELECT @sql += ' Drop table ' + QUOTENAME(TABLE_SCHEMA) + '.'+ QUOTENAME(TABLE_NAME) + '; 'FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_TYPE = 'BASE TABLE' Exec Sp_executesql @sql\";" + ] + }, + { + "cell_type": "code", + "source": [ + "int rowAffect = SqlServer.AzureSqlConnection(serverName, database, userID, password, query);" + ] + } + ] } \ No newline at end of file diff --git a/Export/MapTemplate.ipynb b/Export/MapTemplate.ipynb index c1fb9d01..1f91daa0 100644 --- a/Export/MapTemplate.ipynb +++ b/Export/MapTemplate.ipynb @@ -1,338 +1,244 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "J7Lk0NfjhkC9DBXVAnd4ag", - "cell_type": "markdown", - "source": [ - "

Map Template

" - ], - "metadata": {} - }, - { - "id": "nJozo1XeSkeGCLiQXUPlzA", - "cell_type": "markdown", - "source": [ - "This Notebook exports the Data nodes, states, and parameters for the target partition to a spreadsheet file which can be read, modified, and is ready to be re-imported." - ], - "metadata": {} - }, - { - "id": "T4LYGKNFjke1IDEPU8E44Q", - "cell_type": "markdown", - "source": [ - "After setting the desired target Partition, the Data present in the workspace is ready to be exported. " - ], - "metadata": {} - }, - { - "id": "J3Om4qznT0qnFdizsJg6gA", - "cell_type": "markdown", - "source": [ - "# Import dependencies" - ], - "metadata": {} - }, - { - "id": "jz0ZzjaNNkyPlNjH7p_9CQ", - "cell_type": "code", - "source": [ - "#!import \"../Utils/UtilityMethods\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4kGmVeM2F0y1LR3iEJJAaA", - "cell_type": "markdown", - "source": [ - "# Select Initialization" - ], - "metadata": {} - }, - { - "id": "nVFGNWhtb0iw49kOFNKpUQ", - "cell_type": "markdown", - "source": [ - "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." - ], - "metadata": {} - }, - { - "id": "MbQiJg5acUurtMhQFZOPtw", - "cell_type": "code", - "source": [ - "/* The DataSource is configured and connected to real database */", - "\n//#!eval-notebook \"Database/Configure\"", - "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", - "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Ma-JBoxkmUqAb81Pb2v8EA", - "cell_type": "markdown", - "source": [ - "# Workspace Initialization " - ], - "metadata": {} - }, - { - "id": "zaO0K3_d3UOftmtrwhqrFg", - "cell_type": "markdown", - "source": [ - "Firstly, the Workspace is initialized with basic dimensions and with Data Nodes. For a list of the dimensions please refer to the DataModel/DataStructure notebook." - ], - "metadata": {} - }, - { - "id": "BP4HG8krfkul6dXSvdGHnw", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CirOR3dQA0iqxXipYfNcFQ", - "cell_type": "markdown", - "source": [ - "# Map Template: Data Node" - ], - "metadata": {} - }, - { - "id": "z1pGwBuU20ywRLjN6Gj5eg", - "cell_type": "markdown", - "source": [ - "## Set Partition" - ], - "metadata": {} - }, - { - "id": "8y9ezk2H7EetGACPthoNUw", - "cell_type": "code", - "source": [ - "static var partition = new PartitionByReportingNode() { ReportingNode = \"CH\" };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XFPlV7vwiUCUY7llRpEeEQ", - "cell_type": "code", - "source": [ - "await Workspace.Partition.SetAsync( partition );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7MTJTAXvjUCDuc6-sHSUQQ", - "cell_type": "markdown", - "source": [ - "## Export" - ], - "metadata": {} - }, - { - "id": "yBbsPeQ5XkO5M_mXJtkiTw", - "cell_type": "code", - "source": [ - "await Export.ToExcel(\"DataNodes\")", - "\n .WithSource(Workspace)", - "\n .PortfolioConfiguration()", - "\n .PortfolioConfiguration()", - "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", - "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", - "\n .MainTabConfigurationWoScenario(partition)", - "\n.ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "SG9iYPdfGkOJqrcbjN-cIQ", - "cell_type": "markdown", - "source": [ - "# Map Template: Data Node State" - ], - "metadata": {} - }, - { - "id": "go7LKWKxBECDgXOhv9Se8g", - "cell_type": "markdown", - "source": [ - "## Set Partition" - ], - "metadata": {} - }, - { - "id": "b7xD5r6TuE2QTO-J6L8q-Q", - "cell_type": "code", - "source": [ - "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q1MIgSZcNE60Sx6cCGC9YA", - "cell_type": "code", - "source": [ - "await Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "reWr-I2FeUijpPeiXGdOCA", - "cell_type": "markdown", - "source": [ - "## Export" - ], - "metadata": {} - }, - { - "id": "iW-JFPjuS0q_aGWGSn4Ujg", - "cell_type": "code", - "source": [ - "var dataNodeStates = (await Workspace.Query()", - "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", - "\n .GroupBy(x => x.DataNode)", - "\n .Select(x => x.OrderByDescending(y => y.Year).ThenByDescending(y => y.Month))", - "\n .Select(x => x.Last())", - "\n .ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "64_Gk6W_qkuh47zAJ1xcZw", - "cell_type": "code", - "source": [ - "await Export.ToExcel(\"DataNodeState\")", - "\n .WithSource(Workspace)", - "\n .StateEnumConfiguration() ", - "\n .DataNodeStateConfiguration(dataNodeStates)", - "\n .MainTabConfigurationWoScenario(partition)", - "\n.ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Aolg5llKGkWX3-v94jBP8A", - "cell_type": "markdown", - "source": [ - "# Map Template: Data Node Parameter" - ], - "metadata": {} - }, - { - "id": "amCy5h6BA0K6wxCh7NvZrg", - "cell_type": "markdown", - "source": [ - "## Set Partition" - ], - "metadata": {} - }, - { - "id": "kMTcDi7DFEC6FuMagh5uDg", - "cell_type": "code", - "source": [ - "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-tmD3uOmwUmFUX_q78nD7A", - "cell_type": "code", - "source": [ - "await Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "z6pkleZXd0mZN82EQprS3w", - "cell_type": "markdown", - "source": [ - "## Export" - ], - "metadata": {} - }, - { - "id": "0zdLZPrPw0Sm4w1TjesGMQ", - "cell_type": "code", - "source": [ - "var dataNodeParameters = (await Workspace.Query()", - "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", - "\n .GroupBy(x => x.GetType().Name)", - "\n .ToDictionary(x => x.Key, ", - "\n x => x.GroupBy(y => y.DataNode)", - "\n .Select(y => y.OrderByDescending(z => z.Year).ThenByDescending(z => z.Month))", - "\n .Select(y => y.Last())", - "\n .ToArray() );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xp0dlpVqC0mQfbqqrpn8Aw", - "cell_type": "code", - "source": [ - "await Export.ToExcel(\"DataNodeParameter\")", - "\n .WithSource(Workspace)", - "\n .DataNodeParameterConfiguration(dataNodeParameters)", - "\n .MainTabConfiguration(partition)", - "\n.ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3tf3mjl0gUqui_fD_X7OmQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Map Template

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This Notebook exports the Data nodes, states, and parameters for the target partition to a spreadsheet file which can be read, modified, and is ready to be re-imported." + ] + }, + { + "cell_type": "markdown", + "source": [ + "After setting the desired target Partition, the Data present in the workspace is ready to be exported. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import dependencies" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Utils/UtilityMethods\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Select Initialization" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." + ] + }, + { + "cell_type": "code", + "source": [ + "/* The DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"Database/Configure\"", + "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", + "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ] + }, + { + "cell_type": "markdown", + "source": [ + "Firstly, the Workspace is initialized with basic dimensions and with Data Nodes. For a list of the dimensions please refer to the DataModel/DataStructure notebook." + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Map Template: Data Node" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Set Partition" + ] + }, + { + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNode() { ReportingNode = \"CH\" };" + ] + }, + { + "cell_type": "code", + "source": [ + "await Workspace.Partition.SetAsync( partition );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Export" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(\"DataNodes\")", + "\n .WithSource(Workspace)", + "\n .PortfolioConfiguration()", + "\n .PortfolioConfiguration()", + "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", + "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Map Template: Data Node State" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Set Partition" + ] + }, + { + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };" + ] + }, + { + "cell_type": "code", + "source": [ + "await Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Export" + ] + }, + { + "cell_type": "code", + "source": [ + "var dataNodeStates = (await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", + "\n .GroupBy(x => x.DataNode)", + "\n .Select(x => x.OrderByDescending(y => y.Year).ThenByDescending(y => y.Month))", + "\n .Select(x => x.Last())", + "\n .ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(\"DataNodeState\")", + "\n .WithSource(Workspace)", + "\n .StateEnumConfiguration() ", + "\n .DataNodeStateConfiguration(dataNodeStates)", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Map Template: Data Node Parameter" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Set Partition" + ] + }, + { + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };" + ] + }, + { + "cell_type": "code", + "source": [ + "await Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Export" + ] + }, + { + "cell_type": "code", + "source": [ + "var dataNodeParameters = (await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", + "\n .GroupBy(x => x.GetType().Name)", + "\n .ToDictionary(x => x.Key, ", + "\n x => x.GroupBy(y => y.DataNode)", + "\n .Select(y => y.OrderByDescending(z => z.Year).ThenByDescending(z => z.Month))", + "\n .Select(y => y.Last())", + "\n .ToArray() );" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(\"DataNodeParameter\")", + "\n .WithSource(Workspace)", + "\n .DataNodeParameterConfiguration(dataNodeParameters)", + "\n .MainTabConfiguration(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Import/ImportResultPreview.ipynb b/Import/ImportResultPreview.ipynb index 4b61bb94..22cd4398 100644 --- a/Import/ImportResultPreview.ipynb +++ b/Import/ImportResultPreview.ipynb @@ -1,344 +1,250 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "9Q5yj6YN-EKdGXz1kK8Q6A", - "cell_type": "markdown", - "source": [ - "# Temporary for debugging (initialize data and construct/initialize storage)" - ], - "metadata": {} - }, - { - "id": "maDeKWCseEWbze58VbJlyw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "S2vYnVC3LUuldJH71p8jfA", - "cell_type": "code", - "source": [ - "#!import \"../Test/SpecificationsSetup\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BmCoR4B2rEuIBBIgZnqI1w", - "cell_type": "markdown", - "source": [ - "", - "\nGiven the current status of the implementation, in order to display Actual reports it is necessary to set Actual format in the Args while to display Cashflow it is necessary to set Cashflow format." - ], - "metadata": {} - }, - { - "id": "trcP0qut1kWbOQTgIF35cg", - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"L\" ;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2m1t-aisOEiw325jWesNXQ", - "cell_type": "code", - "source": [ - "var UniversePreview = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "AbkLGXiDFk6sdSdWtinXjA", - "cell_type": "code", - "source": [ - "var importStorage = UniversePreview.GetStorage();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "k9qNkaSwjUqp_Y_vGf9RwA", - "cell_type": "markdown", - "source": [ - "# Import Preview" - ], - "metadata": {} - }, - { - "id": "5EP-6YDPFkeMJcxDTaO7qw", - "cell_type": "markdown", - "source": [ - "## Present Value" - ], - "metadata": {} - }, - { - "id": "XTFLl2lau0SjbCIEtOTHpA", - "cell_type": "code", - "source": [ - "var identities = UniversePreview.GetScopes(importStorage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yEjsrBVzEk26kz9jgLkJ-Q", - "cell_type": "code", - "source": [ - "var pvs = UniversePreview.GetScopes(identities, o => o.WithStorage(importStorage)).SelectMany(x => x.PvCurrent.Concat(x.PvLocked));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ck9xZbpeDUyh_Tw6FOoxKg", - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(pvs", - "\n //.Where(x => x.DataNode == \"DTR1.1\")", - "\n )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n //.GroupColumnsBy(x => x.AmountType)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n //VariableType", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n //.GroupColumnsBy(x => x.Novelty)", - "\n .WithGridOptionsForIfrsVariable(720)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XIPJIPxfyEy6P4JYfRAXTA", - "cell_type": "markdown", - "source": [ - "## Risk Adjustment" - ], - "metadata": {} - }, - { - "id": "4bBaRnP3pE-ZbxPKKnxOCA", - "cell_type": "code", - "source": [ - "var ras = UniversePreview.GetScopes(identities).SelectMany(x => x.RaCurrent.Concat(x.RaLocked));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "AiOWaeI_Hku1SDbNB-xlXA", - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(ras)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n //.GroupRowsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n //VariableType", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n //.GroupColumnsBy(x => x.Novelty)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rqCr51d6kUGgBzGRAqrtXw", - "cell_type": "markdown", - "source": [ - "## Actuals" - ], - "metadata": {} - }, - { - "id": "vl8E9tTAT06fpVUcTfflbg", - "cell_type": "code", - "source": [ - "var actuals = UniversePreview.GetScopes(identities).SelectMany(x => x.Actual);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hQUJ7t1AB0O-L0PVYPqsVw", - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(actuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupRowsBy(x => x.AmountType)", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n .WithGridOptionsForIfrsVariable(550)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nwWJHZ5vTUuJsHqFTGwLQw", - "cell_type": "markdown", - "source": [ - "## Advance, Overdue Actuals" - ], - "metadata": {} - }, - { - "id": "UYvTQnP0NUe4pLm0fnYEAA", - "cell_type": "code", - "source": [ - "var aoActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.AdvanceActual.Concat(x.OverdueActual));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1v6tcALrVEGG-vdRDV7HIQ", - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(aoActuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupColumnsBy(x => x.AmountType)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable(300)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ab2P4J7DO0mkVrlsP09fhQ", - "cell_type": "markdown", - "source": [ - "## Deferrable Actuals" - ], - "metadata": {} - }, - { - "id": "KCZlxRFa10CYDduJ65KMHg", - "cell_type": "code", - "source": [ - "var deferrableActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.DeferrableActual);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zln4EOOdqUiUTFbwoqTirw", - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(deferrableActuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable(350)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "l5uZz5MhKUOYLsKpzNZwvQ", - "cell_type": "markdown", - "source": [ - "## Csm Lc LoReCo" - ], - "metadata": {} - }, - { - "id": "WZ_xvxUBtEKO2jingfCpRQ", - "cell_type": "code", - "source": [ - "var csm = UniversePreview.GetScopes(identities).SelectMany(x => x.Csms);", - "\nvar loss = UniversePreview.GetScopes(identities).SelectMany(x => x.Loss);", - "\nvar csmLcLoReCo = Enumerable.Empty().Concat(csm).Concat(loss);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RAN7qdbDLECNmb-kxUNx1A", - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(csmLcLoReCo", - "\n //.Where(x => x.DataNode == \"DT1.1\")", - "\n )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GszVX-_KiEa9h0m0P0rlhQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "# Temporary for debugging (initialize data and construct/initialize storage)" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Test/SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\nGiven the current status of the implementation, in order to display Actual reports it is necessary to set Actual format in the Args while to display Cashflow it is necessary to set Cashflow format." + ] + }, + { + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;" + ] + }, + { + "cell_type": "code", + "source": [ + "var UniversePreview = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ] + }, + { + "cell_type": "code", + "source": [ + "var importStorage = UniversePreview.GetStorage();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Preview" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Present Value" + ] + }, + { + "cell_type": "code", + "source": [ + "var identities = UniversePreview.GetScopes(importStorage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);" + ] + }, + { + "cell_type": "code", + "source": [ + "var pvs = UniversePreview.GetScopes(identities, o => o.WithStorage(importStorage)).SelectMany(x => x.PvCurrent.Concat(x.PvLocked));" + ] + }, + { + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(pvs", + "\n //.Where(x => x.DataNode == \"DTR1.1\")", + "\n )", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n //.GroupColumnsBy(x => x.AmountType)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n //VariableType", + "\n //.GroupColumnsBy(x => x.DataNode)", + "\n //.GroupColumnsBy(x => x.Novelty)", + "\n .WithGridOptionsForIfrsVariable(720)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Risk Adjustment" + ] + }, + { + "cell_type": "code", + "source": [ + "var ras = UniversePreview.GetScopes(identities).SelectMany(x => x.RaCurrent.Concat(x.RaLocked));" + ] + }, + { + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(ras)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n //.GroupRowsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n //VariableType", + "\n //.GroupColumnsBy(x => x.DataNode)", + "\n //.GroupColumnsBy(x => x.Novelty)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "var actuals = UniversePreview.GetScopes(identities).SelectMany(x => x.Actual);" + ] + }, + { + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(actuals)", + "\n .WithQuerySource(Workspace)", + "\n .GroupRowsBy(x => x.AmountType)", + "\n //.GroupColumnsBy(x => x.DataNode)", + "\n .WithGridOptionsForIfrsVariable(550)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Advance, Overdue Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "var aoActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.AdvanceActual.Concat(x.OverdueActual));" + ] + }, + { + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(aoActuals)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupColumnsBy(x => x.EstimateType)", + "\n .GroupColumnsBy(x => x.AmountType)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable(300)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Deferrable Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "var deferrableActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.DeferrableActual);" + ] + }, + { + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(deferrableActuals)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable(350)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Csm Lc LoReCo" + ] + }, + { + "cell_type": "code", + "source": [ + "var csm = UniversePreview.GetScopes(identities).SelectMany(x => x.Csms);", + "\nvar loss = UniversePreview.GetScopes(identities).SelectMany(x => x.Loss);", + "\nvar csmLcLoReCo = Enumerable.Empty().Concat(csm).Concat(loss);" + ] + }, + { + "cell_type": "code", + "source": [ + "Report", + "\n .ForObjects(csmLcLoReCo", + "\n //.Where(x => x.DataNode == \"DT1.1\")", + "\n )", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupColumnsBy(x => x.EstimateType)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index 9370c157..b932e924 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -1,2296 +1,2056 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "a6wbTgZMQ0q5Of99FfYD-A", - "cell_type": "markdown", - "source": [ - "", - "\n

Import Scopes (IFRS17 Methodology Business Logic)

", - "\n", - "\nThis notebook contains the logic used to perform calculations upon import of data (actuals and cashflows). This is also called 'Data Loading' and the concept of Scope is used here to define the logic and provide the means of executing the logic." - ], - "metadata": {} - }, - { - "id": "6qZO0vcpd0GtSc7GvLlgBQ", - "cell_type": "markdown", - "source": [ - "# References", - "\nLibraries and other notebooks which are needed for this notebook are imported below." - ], - "metadata": {} - }, - { - "id": "G75a3tlrBkqn_MN5as22Jw", - "cell_type": "markdown", - "source": [ - "## Notebooks" - ], - "metadata": {} - }, - { - "id": "HQwfAINEvUqJK5l5FV_SOg", - "cell_type": "code", - "source": [ - "#!import \"ImportStorage\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kd06OH9YcE2hGUtgERwXhA", - "cell_type": "markdown", - "source": [ - "", - "\n# Scopes", - "\nScopes are used to define and perform data handling in a structured and easy-to-read-through fashion.", - "\n", - "\nThe IModel interface below will be used to execute calculations (i.e. evaluate the scopes) based on imported data." - ], - "metadata": {} - }, - { - "id": "3ye2s5-hWEWsy3YLTe5R-w", - "cell_type": "code", - "source": [ - "public interface IModel : IMutableScopeWithStorage{}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LjnVkU0bq0yP61Cb1_EMxA", - "cell_type": "markdown", - "source": [ - "## Getting Existing Identities", - "\n", - "\nAn [Identity](../DataModel/DataStructure#import-identity) is a set of identifiers for a certain set of data. In particular, an identity consists of a certain [AoC Type](../DataModel/DataStructure#aoc-type), [Novelty](../DataModel/DataStructure#novelty), [Data Node](../DataModel/DataStructure#data-node), Accident Year, and information on whether the data is for reinsurance or not. ", - "\n", - "\nGiven a certain Data Node and Accident Year, the interface GetIdentities returns all the existing identities (e.g. for Actuals and Cashflows) which have that Data Node and Accident Year." - ], - "metadata": {} - }, - { - "id": "SyhE8EzOsECEpMzUSS6kGQ", - "cell_type": "code", - "source": [ - "public interface AllCfIdentities : IScope // string represents a DataNode", - "\n{", - "\n public IEnumerable ids => GetStorage().GetAllAocSteps(InputSource.Cashflow)", - "\n .Select(aocStep => new ImportIdentity {", - "\n AocType = aocStep.AocType,", - "\n Novelty = aocStep.Novelty,", - "\n DataNode = Identity", - "\n });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_LsQEeHMYE6G4pGS8dK4RQ", - "cell_type": "code", - "source": [ - "public interface GetIdentities : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity))", - "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Actual)", - "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Cashflow)", - "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Opening)", - "\n );", - "\n ", - "\n private IEnumerable computedIdentities => new string[]{AocTypes.EA, AocTypes.AM, AocTypes.EOP}", - "\n .Select(aocType => new ImportIdentity {", - "\n AocType = aocType,", - "\n Novelty = Novelties.C,", - "\n DataNode = Identity", - "\n });", - "\n private IEnumerable allIdentities => ParsedIdentities.Concat(computedIdentities).Concat(SpecialIdentities).ToHashSet(); ", - "\n ", - "\n IEnumerable ParsedIdentities => Enumerable.Empty(); ", - "\n IEnumerable SpecialIdentities => Enumerable.Empty();", - "\n ", - "\n //Set DataNode properties and ProjectionPeriod", - "\n IEnumerable Identities => allIdentities.Select(id => id with { IsReinsurance = GetStorage().DataNodeDataBySystemName[id.DataNode].IsReinsurance,", - "\n ValuationApproach = GetStorage().DataNodeDataBySystemName[id.DataNode].ValuationApproach", - "\n });", - "\n /* .SelectMany(id => Enumerable.Range(0,GetStorage().GetProjectionCount() + 1)", - "\n .Select(pp => id with {ProjectionPeriod = pp })", - "\n );*/", - "\n}", - "\n", - "\npublic interface AllCashflowIdentities : GetIdentities", - "\n{", - "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids;", - "\n}", - "\n", - "\n", - "\npublic interface GetActualIdentities : GetIdentities", - "\n{", - "\n private IEnumerable actualEstimateTypes => GetStorage().EstimateTypesByImportFormat[ImportFormats.Actual];", - "\n ", - "\n IEnumerable GetIdentities.ParsedIdentities => GetStorage().GetIfrsVariables(Identity).Where(iv => actualEstimateTypes.Contains(iv.EstimateType)).Select(v => new ImportIdentity(v));", - "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids", - "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Opening)", - "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", - "\n Novelty = aocStep.Novelty,", - "\n DataNode = Identity", - "\n }));", - "\n}", - "\n", - "\npublic interface GetCashflowIdentities : GetIdentities", - "\n{", - "\n private bool isReinsurance => GetStorage().DataNodeDataBySystemName[Identity].IsReinsurance; //clean up in the next PR", - "\n ", - "\n IEnumerable GetIdentities.ParsedIdentities => GetStorage().GetRawVariables(Identity).Select(v => new ImportIdentity(v));", - "\n ", - "\n IEnumerable GetIdentities.SpecialIdentities => ParsedIdentities.Where(id => id.Novelty != Novelties.C)", - "\n .Select(id => id.Novelty).ToHashSet()", - "\n .SelectMany(n => (n == Novelties.N ", - "\n ? new string[]{AocTypes.IA, AocTypes.CF} //Add IA, CF, for New Business", - "\n : isReinsurance ", - "\n ? new string[]{AocTypes.IA, AocTypes.CF, AocTypes.YCU, AocTypes.CRU, AocTypes.RCU} //Add IA, CF, YCU, CRU, RCU for in force", - "\n : new string[]{AocTypes.IA, AocTypes.CF, AocTypes.YCU}) //Add IA, CF, YCU,", - "\n .Select(aocType => new ImportIdentity {", - "\n AocType = aocType,", - "\n Novelty = n,", - "\n DataNode = Identity }))", - "\n .Concat(new ImportIdentity {", - "\n AocType = AocTypes.CF, //Add CF for Deferral", - "\n Novelty = Novelties.C,", - "\n DataNode = Identity", - "\n }.RepeatOnce()) ", - "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Opening)", - "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", - "\n Novelty = aocStep.Novelty,", - "\n DataNode = Identity", - "\n })); ", - "\n}", - "\n", - "\npublic interface GetAllIdentities : GetIdentities", - "\n{", - "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids", - "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Actual)", - "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", - "\n Novelty = aocStep.Novelty,", - "\n DataNode = Identity,", - "\n }));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZVtzxigEF0yEaftuPtLQlw", - "cell_type": "markdown", - "source": [ - "## Getting Amount Types", - "\n", - "\nSimilarly, given a certain Data Node and Accident Year, the interface ValidAmountType returns all the amount types which are used in imported data with that Data Node and Accident Year." - ], - "metadata": {} - }, - { - "id": "kE72GkEJNE2GPEnIe78RDA", - "cell_type": "code", - "source": [ - "public interface ValidAmountType : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow ||", - "\n x.GetStorage().IsSecondaryScope(x.Identity)));", - "\n ", - "\n IEnumerable BeAmountTypes => GetStorage().GetRawVariables(Identity)", - "\n .Where(rv => rv.AmountType != null)", - "\n .Select(x => x.AmountType)", - "\n .Concat(GetStorage().DataNodeDataBySystemName[Identity].IsReinsurance ? (AmountTypes.CDR).RepeatOnce() : Enumerable.Empty())", - "\n .ToHashSet();", - "\n ", - "\n ", - "\n IEnumerable ActualAmountTypes => GetStorage().GetIfrsVariables(Identity)", - "\n .Where(iv => GetStorage().EstimateTypesByImportFormat[ImportFormats.Actual].Contains(iv.EstimateType))", - "\n .Select(x => x.AmountType)", - "\n .ToHashSet();", - "\n}", - "\npublic interface BeAmountTypesFromIfrsVariables : ValidAmountType", - "\n{", - "\n IEnumerable ValidAmountType.BeAmountTypes => GetStorage().GetIfrsVariables(Identity)", - "\n .Where(iv => GetStorage().EstimateTypesByImportFormat[ImportFormats.Cashflow].Contains(iv.EstimateType) && iv.AmountType != null)", - "\n .Select(x => x.AmountType)", - "\n .ToHashSet();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OppPBfh8o0-NsCYyUGOVLg", - "cell_type": "markdown", - "source": [ - "", - "\n## AoC Step Structure", - "\n", - "\nThe Aoc step structure is constructed from the data which is delivered as input. It is assumed that it depends only on the Group of Contrat (i.e. it is invariant across Amount types or Accident Year). " - ], - "metadata": {} - }, - { - "id": "54mTUE9VgUG3fW8ov6K3Uw", - "cell_type": "markdown", - "source": [ - "### ParentAocStep ", - "\nThe **ParentAocStep** scope computes and provides an important piece of information for each [Identity](../DataModel/DataStructure#import-identity), i.e. for a certain [AocType](../DataModel/DataStructure#aoc-type) and [Novelty](../DataModel/DataStructure#novelty).", - "\n", - "\nIt provides the list of the adjacent AocSteps prior to Identity one. It can be more than one only for the step **CL** where a parent for each novelty is considered.", - "\nParentAocStep is critical when computing the *telescoping* differences. ", - "\n", - "\nThey are defined as follows:", - "\n", - "\n$$", - "\n\\text{ParentAocStep}(\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{AoC step with AoC Type YCU and Novelty I} & \\text{if AocType CRU} \\\\", - "\n\\text{The last AoC step with Data Type != Calculated and same Novelty as the AocStep} & \\text{if AocType YCU} \\\\", - "\n\\text{The AoC step which comes before in terms of order (as defined by AocType)} & \\text{otherwise} \\\\", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n" - ], - "metadata": {} - }, - { - "id": "l9dack27s0Kc15M14T2vxg", - "cell_type": "code", - "source": [ - "public interface ParentAocStep : IScope<(ImportIdentity Id, string AmountType), ImportStorage>", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType != AmountTypes.CDR));", - "\n ", - "\n private HashSet ParsedAocSteps => GetScope(Identity.Id.DataNode).ParsedIdentities.Select(id => new AocStep(id.AocType, id.Novelty)).ToHashSet();", - "\n private IEnumerable OrderedParsedAocSteps => ParsedAocSteps.Concat(CalculatedTelescopicAocStep).OrderBy(x => GetStorage().AocConfigurationByAocStep[x].Order);", - "\n ", - "\n private Dictionary> ParentParsedIdentities => GetPreviousIdentities(OrderedParsedAocSteps);", - "\n private AocStep identityAocStep => new AocStep(Identity.Id.AocType, Identity.Id.Novelty);", - "\n ", - "\n IEnumerable CalculatedTelescopicAocStep => GetStorage().GetCalculatedTelescopicAocSteps();", - "\n ", - "\n IEnumerable Values => ", - "\n Identity.Id.AocType switch {", - "\n AocTypes.CRU => new AocStep(AocTypes.YCU, Novelties.I).RepeatOnce(),", - "\n AocTypes.YCU => OrderedParsedAocSteps.GetReferenceAocStepForCalculated(GetStorage().AocConfigurationByAocStep, identityAocStep).RepeatOnce(),", - "\n _ => ParentParsedIdentities.TryGetValue(identityAocStep, out var parents) ? parents : Enumerable.Empty(),", - "\n };", - "\n}", - "\n", - "\npublic interface ParentAocStepForCreditRisk : ParentAocStep", - "\n{", - "\n IEnumerable ParentAocStep.CalculatedTelescopicAocStep => ", - "\n GetStorage().GetCalculatedTelescopicAocSteps().Where(aoc => aoc.AocType != AocTypes.CRU);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5L-2OpNhxki8UNE8od5BLQ", - "cell_type": "markdown", - "source": [ - "### ReferenceAocStep", - "\n", - "\nThe **ReferenceAocStep** scope provides the AocStep from which to retrieve the data in order to compute its value (e.g. AoC step EA retrieves Present Values, while AoC step YCU retrieves Nominal).", - "\n", - "\nThey are defined as follows:", - "\n", - "\n$$", - "\n\\text{ReferenceAocStep}(\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{self} & \\text{if AocStep InputSource is not Calculated} \\\\", - "\n\\text{The last AoC step with Data Type != Calculated and same Novelty as the input AocStep} ~, & \\text{if AocType } \\in \\text{\\{RCU, CF, IA, YCU, CRU\\}} \\\\", - "\n\\text{AoC step with AoC Type CF and Novelty as the AocStep} & \\text{if AocType EA} \\\\", - "\n\\text{AoC step with AoC Type CL and Novelty C} & \\text{if AocType $\\in$ \\{AM, EOP\\}} \\\\", - "\n\\text{empty} & \\text{if AocType is BOP} \\\\", - "\n\\text{log NotSupportedAocStepReference error} & \\text{otherwise} \\\\", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere the last AocStep is obtained by ordering the AocSteps according to their order (as defined by its AocType) and taking the last one." - ], - "metadata": {} - }, - { - "id": "ItSTOo7qmE68A7gENSMguQ", - "cell_type": "code", - "source": [ - "public interface ReferenceAocStep : IScope ", - "\n{", - "\n private IEnumerable OrderedParsedAocSteps => GetScope(Identity.DataNode).ParsedIdentities", - "\n .Select(id => new AocStep(id.AocType, id.Novelty))", - "\n .Distinct()", - "\n .OrderBy(aocStep => GetStorage().AocConfigurationByAocStep[aocStep].Order);", - "\n private AocStep identityAocStep => new AocStep(Identity.AocType, Identity.Novelty);", - "\n private AocStep GetReferenceAocStep(string aocType) {", - "\n return aocType switch {", - "\n AocTypes.RCU or AocTypes.CF or AocTypes.IA or AocTypes.YCU or AocTypes.CRU => OrderedParsedAocSteps.GetReferenceAocStepForCalculated(GetStorage().AocConfigurationByAocStep, identityAocStep),", - "\n AocTypes.EA => new AocStep(AocTypes.CF, Identity.Novelty),", - "\n AocTypes.AM or AocTypes.EOP => new AocStep(AocTypes.CL, Novelties.C),", - "\n AocTypes.BOP => new AocStep(default, default), //BOP, C has DataType == Calculated. See ReferenceAocStep condition.", - "\n _ => (AocStep)ApplicationMessage.Log(Error.NotSupportedAocStepReference, Identity.AocType),", - "\n };", - "\n }", - "\n", - "\n // The Reference AocStep from which get data (Nominal or PV) to compute", - "\n AocStep Value => GetStorage().AocConfigurationByAocStep[identityAocStep].DataType == DataType.Calculated ", - "\n || GetStorage().AocConfigurationByAocStep[identityAocStep].DataType == DataType.CalculatedTelescopic ", - "\n ? GetReferenceAocStep(Identity.AocType)", - "\n : identityAocStep;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tzXoa0VDqUSEqPJLe4LCdA", - "cell_type": "markdown", - "source": [ - "### PreviousAocSteps", - "\nThe **PreviousAocSteps** scope computes and provides an other important piece of information for each [Identity](../DataModel/DataStructure#import-identity), i.e. for a certain [AocType](../DataModel/DataStructure#aoc-type) and [Novelty](../DataModel/DataStructure#novelty).", - "\n", - "\nIt provides the list of all previous AocSteps up to the **BOP** step, whereby a Combined novelty will branch into the InForce and New Business AocTypes.", - "\n", - "\nPreviousAocSteps is critical when computing aggregated values along the various dimensions (such as for example Line of Business) and ", - "\nis formed by the ParentAocStep and its parent and so on until there is no parent.", - "\n", - "\n$$", - "\n\\text{PreviousAocSteps}(\\rm{AocStep}) = \\{PAS_1, PAS_2, \\ldots\\}", - "\n$$", - "\nwhere", - "\n$$", - "\n\\rm{PAS}_1 = \\rm{ParentAocStep}(\\rm{AocStep})", - "\n$$", - "\n$$", - "\n\\rm{PAS}_2 = \\rm{ParentAocStep}(\\rm{PAS}_1).", - "\n$$", - "\n", - "\nThis scope depends on the InputSource (Actual or Cashflow) for which the PreviousSteps are requested due to the AocChain differences between Actual reports and the rest." - ], - "metadata": {} - }, - { - "id": "4AJrFGaLqEm52QmmXGl6pg", - "cell_type": "code", - "source": [ - "public interface PreviousAocSteps : IScope<(ImportIdentity Id, InputSource ScopeInputSource), ImportStorage> ", - "\n{ ", - "\n private AocStep identityAocStep => new AocStep(Identity.Id.AocType, Identity.Id.Novelty);", - "\n private int aocStepOrder => GetStorage().AocConfigurationByAocStep[identityAocStep].Order;", - "\n private HashSet allAocSteps => GetStorage().GetAllAocSteps(Identity.ScopeInputSource).ToHashSet();", - "\n IEnumerable Values => allAocSteps.Contains(identityAocStep)", - "\n ? GetScope(Identity.Id.DataNode).Identities", - "\n .Select(id => new AocStep(id.AocType, id.Novelty))", - "\n .Distinct()", - "\n .Where(aoc => allAocSteps.Contains(aoc) && ", - "\n GetStorage().AocConfigurationByAocStep[aoc].Order < aocStepOrder && ", - "\n (Identity.Id.Novelty != Novelties.C ? aoc.Novelty == Identity.Id.Novelty : true) )", - "\n .OrderBy(aoc => GetStorage().AocConfigurationByAocStep[aoc].Order)", - "\n : Enumerable.Empty();", - "\n} " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "JJ7sk4vUDUSWJJvVDpbZNw", - "cell_type": "markdown", - "source": [ - "The exact structure being return depends on the **order** of the AoC Steps (which is set by the [AoC Type](../DataModel/DataStructure#aoc-type)), and on which AoC steps exist.", - "\n", - "\nFor an example of the usage of the AocStep scope see [here](../Test/AocStructureTest)." - ], - "metadata": {} - }, - { - "id": "1qVdizG_x0OI3MI-IEVZKA", - "cell_type": "markdown", - "source": [ - "", - "\n## Discounting", - "\n", - "\nThe calculation of IFRS17 figures is based on cumulated discounted cashflows." - ], - "metadata": {} - }, - { - "id": "bKrNP0O7ZEOtm23hLJyEyg", - "cell_type": "markdown", - "source": [ - "", - "\n### Yield Curves", - "\n", - "\nThe Yield Curves used for the discounting calculations are functions of the [Currency](../DataModel/DataStructure#currency), the [Data Node](../DataModel/DataStructure#data-node) and the [Economic Basis](../DataModel/DataStructure#economic-basis).", - "\n", - "\nIn particular:", - "\n- For the **Locked-in** economic basis, the yield curve used is the latest available as per end of the DataNode's inception year;", - "\n- Whereas for the **Current** economic base, the yield curve used is the latest available as per the current period.", - "\n", - "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/UtilityMethods#yield-curve)." - ], - "metadata": {} - }, - { - "id": "DcHXuat1WUaOAFa_MsVSdQ", - "cell_type": "markdown", - "source": [ - "", - "\n### Interest and Discount Rates and Factors", - "\n", - "\nThe factors used for discounting have the same granularity as the cashflow, i.e. monthly. The yield curves have yearly granularity, so the annual Interest factor is 1 + interest rate. The monthly Interest Interest and Discount factors are obtained from the annual factors such that the product of 12 months results in the annual factors, as follows:", - "\n", - "\n$$", - "\n\\text{Discount}_i = ( 1 + \\text{YC}_i ) ^{-\\frac{1}{12}} ~,", - "\n$$", - "\nand ", - "\n$$", - "\n\\text{Interest}_i = ( 1 + \\text{YC}_i) ^{\\frac{1}{12}} ~,", - "\n$$", - "\n", - "\nwhere the index $i$ denotes years." - ], - "metadata": {} - }, - { - "id": "yCCcQcUwzEO1lzy3iwRM8Q", - "cell_type": "code", - "source": [ - "public interface MonthlyRate : IScope", - "\n{", - "\n private string EconomicBasis => GetContext();", - "\n ", - "\n private double[] YearlyYieldCurve => GetStorage().GetYearlyYieldCurve(Identity, EconomicBasis);", - "\n ", - "\n private double Perturbation => 0; //GetStorage().GetYieldCurvePerturbation(); => switch Args.Scenario { 10ptsU => 0.1, 10ptsD => -0.1, _ => default)", - "\n ", - "\n double[] Interest => YearlyYieldCurve.Select(rate => Math.Pow(1d + rate, 1d / 12d) + Perturbation).ToArray(); ", - "\n ", - "\n double[] Discount => Interest^(-1);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ON4hzALyrkapbo6dsJaCYA", - "cell_type": "markdown", - "source": [ - "For an example of these calculations see [here](../Test/SpecificationsImportCashflows#interest-and-discount-rates)." - ], - "metadata": {} - }, - { - "id": "wCY9O1rFG0OcsUmqNLVm4Q", - "cell_type": "markdown", - "source": [ - "", - "\n## Nominal Values", - "\n", - "\nThe nominal cashflow values correspond to the cashflows provided in the Cashflow input file. ", - "\n
These values are stored in the database as [RawVariable](../DataModel/DataStructure#raw-variables).", - "\n
Refer to the ReferenceAocStep of the AocStructure calculation to identify the correct AocType and Novelty to retrieve.", - "\n
Due to the Credit Default Risk of a reinsurance partner, the logic to compute the Nominal Cashflows for this Amount Type must be defined separately. " - ], - "metadata": {} - }, - { - "id": "YZrg-gGldUGe6pZF0Kh3Qw", - "cell_type": "code", - "source": [ - "public interface NominalCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.CF)", - "\n .WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR));", - "\n", - "\n AocStep referenceAocStep => GetScope(Identity.Id).Value;", - "\n double[] Values => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.AccidentYear);", - "\n}", - "\n", - "\npublic interface CreditDefaultRiskNominalCashflow : NominalCashflow", - "\n{", - "\n private double[] NominalClaimsCashflow => GetStorage().GetClaims()", - "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", - "\n .Aggregate();", - "\n ", - "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", - "\n ", - "\n private double[] PvCdrDecumulated { get {", - "\n var ret = new double[NominalClaimsCashflow.Length];", - "\n for (var i = NominalClaimsCashflow.Length - 1; i >= 0; i--)", - "\n ret[i] = Math.Exp(-nonPerformanceRiskRate) * ret.ElementAtOrDefault(i + 1) + NominalClaimsCashflow[i] - NominalClaimsCashflow.ElementAtOrDefault(i + 1);", - "\n return ret; } } ", - "\n ", - "\n double[] NominalCashflow.Values => PvCdrDecumulated - NominalClaimsCashflow;", - "\n}", - "\n", - "\npublic interface AllClaimsCashflow : NominalCashflow", - "\n{", - "\n double[] NominalCashflow.Values => GetStorage().GetClaims()", - "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", - "\n .Aggregate();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OPI-l8iwREuVVszAP89Hqw", - "cell_type": "markdown", - "source": [ - "For a given month $i$ they are denoted as $\\rm{Nominal}_i$." - ], - "metadata": {} - }, - { - "id": "7RRmYOmkFEuqu8yfOR-0rw", - "cell_type": "markdown", - "source": [ - "For an example of nominal cashflow values see [here](../Test/SpecificationsImportCashflows#nominal-cashflow)." - ], - "metadata": {} - }, - { - "id": "q0ZU9L_OMUqLUKUOUcLuAw", - "cell_type": "markdown", - "source": [ - "", - "\n## Present Values", - "\n", - "\nPresent Values are calculated during the import of the cashflows and stored on the database. They are computed for the relevant Economic Basis, depending on the Valuation Basis.", - "\n", - "\nTheir calculation is described in the following sections and is summarized in the $\\rm{PV}$ formula [below](#present-value)." - ], - "metadata": {} - }, - { - "id": "4SsmFu7Uo0aIEmes8Z4LoQ", - "cell_type": "markdown", - "source": [ - "", - "\n### Cumulated Discounted Cashflows", - "\n", - "\nCumulated and Discounted cashflows $\\rm{CDC}$ are computed using the monthly discount rates and in a recursive manner, as follows:", - "\n", - "\n$$", - "\n\\text{CDC}_i(\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{Nominal}_i + \\text{CDC}_{i+1} \\cdot {\\text{Valid Discount}_{\\frac{i}{12}}} ~, & \\text{if Aoc Type's Period Type is Beginning Of Period} \\\\", - "\n\\big( \\text{Nominal}_i + \\text{CDC}_{i+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{i}{12}}} ~, & \\text{if Aoc Type's Period Type is End Of Period}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere Transaction Period depends on which Best Estimate value is being computed, in particular on what its [Amount Type](../DataModel/DataStructure#amount-type) is (each Amount Type has its own [Period Type](../Constants/Enums)); and $\\text{Valid Discount}$ stands for the fact that in case the Discount Curves are shorter than the required index, then their last element is returned.", - "\n", - "\n
Also here, the Credit Default Risk contribution is calculated separately. Since it is based on Claims, the Period Type is implicitly defined." - ], - "metadata": {} - }, - { - "id": "n0bMVVX8JUGCvXh-hcQi9g", - "cell_type": "code", - "source": [ - "public interface DiscountedCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", - "\n{", - "\n private PeriodType periodType => GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType); ", - "\n ", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR));", - "\n", - "\n [NotVisible]", - "\n string EconomicBasis => GetContext();", - "\n", - "\n [NotVisible]", - "\n double[] MonthlyDiscounting => GetScope(Identity.Id).Discount;", - "\n ", - "\n [NotVisible]", - "\n double[] NominalValues => GetScope(Identity).Values;", - "\n", - "\n double[] Values => NominalValues.ComputeDiscountAndCumulate(MonthlyDiscounting, periodType);", - "\n}", - "\n", - "\npublic interface DiscountedCreditRiskCashflow : DiscountedCashflow", - "\n{ ", - "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", - "\n ", - "\n double[] DiscountedCashflow.Values => NominalValues.ComputeDiscountAndCumulateWithCreditDefaultRisk(MonthlyDiscounting, nonPerformanceRiskRate);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "V8aa9nD9bUqsX54-bD1Hiw", - "cell_type": "markdown", - "source": [ - "For example calculations for Cumulated Discounted Cashflows see [here](../Test/SpecificationsImportCashflows#cumulated-discounted-cashflow)." - ], - "metadata": {} - }, - { - "id": "bYq1f5UE80q1fxb-AON3pA", - "cell_type": "markdown", - "source": [ - "", - "\n### Telescoping Difference", - "\n", - "\n", - "\nPresent Value figures for a specific period are typically reported through an analysis of change, where for each [AocStep](#aoc-steps-structure) the variation with respect to the preceding AocStep is shown.", - "\n", - "\nThe Telescoping Difference is basically the delta between two adjacent AoC steps, whereby the [ParentAocStep](#aoc-steps-structure) is used to determine the AoC step. ", - "\n", - "\nIt is defined as follows:", - "\n", - "\n$$", - "\n\\text{TelescopingDifference}_i = ", - "\n\\text{CDC}_{i}\\big(\\text{current AoC step}\\big) - \\text{CDC}_{i}\\big(\\text{parent AoC step}\\big)", - "\n$$", - "\n", - "\nwhere AocType is the AoC Type of the AoC Step for which the calculations are being performed." - ], - "metadata": {} - }, - { - "id": "cNNeXkyxjkiDODg6ARR5Zw", - "cell_type": "code", - "source": [ - "public interface TelescopicDifference : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", - "\n{", - "\n [NotVisible]", - "\n string EconomicBasis => GetContext();", - "\n private double[] CurrentValues => GetScope(Identity).Values;", - "\n ", - "\n private double[] PreviousValues => (GetScope((Identity.Id, Identity.AmountType)))", - "\n .Values", - "\n .Select(aoc => GetScope((Identity.Id with {AocType = aoc.AocType, Novelty = aoc.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.Accidentyear)).Values)", - "\n .Where(cf => cf.Count() > 0)", - "\n .Aggregate();", - "\n ", - "\n double[] Values => CurrentValues - PreviousValues;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cYmNPbah5UaC9Iu3db7pqA", - "cell_type": "markdown", - "source": [ - "Examples of Telescoping Difference calculations for different AoC steps start [here](../Test/SpecificationsImportCashflows#modelcorrections)." - ], - "metadata": {} - }, - { - "id": "Z42Ysovu4UmepvVo0U429w", - "cell_type": "markdown", - "source": [ - "", - "\n### Present Value", - "\n", - "\nThe present value ($\\rm{PV}$) can be determined by taking the appropriate elements of the cumulated discounted cashflows. This is done as function of the two [projection parameters](../DataModel/DataStructure#projection-configuration) $\\rm{Shift}$ ($S$) and $\\rm{TimeStep}$ ($TS$):", - "\n", - "\n$$", - "\n\\text{PV}(S, TS) = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{PV Base}_{S} ~, & \\text{if Valuation Period is Beginning of Period} \\\\", - "\n\\text{PV Base}_{S+TS/2 -1} ~, & \\text{if Valuation Period is Mid of Period} \\\\", - "\n\\sum_{i=S}^{S + TS - 1}\\text{PV Base}_{i} ~, & \\text{if Valuation Period is Delta} \\\\", - "\n\\text{PV Base}_{S + TS} ~, & \\text{if Valuation Period is End of Period} \\\\", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere [PV Base](#present-value-base) is defined below, and the term $TS/2$ uses MidpointRounding.AwayFromZero (as defined by *https:[]()//docs.microsoft.com/en-us/dotnet/api/system.midpointrounding?view=net-6.0)*: rounding to the nearest number, away from zero in the exact halfway case. Furthermore, if the array is smaller than the index, then the last element is returned.", - "\n", - "\nFor instance, for the current year and year-to-date view we have $S=0$ and $TS=3$ for the first quarter, $TS=6$ for the 2nd quarter and so on.", - "\nFor the projection values of next year first quarter we would have $S=12$ and $TS=3$, etc." - ], - "metadata": {} - }, - { - "id": "a_j0Wz_NsEeWjap6zY-mDA", - "cell_type": "code", - "source": [ - "public interface IWithGetValueFromValues : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", - "\n{", - "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", - "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", - "\n ", - "\n public double GetValueFromValues(double[] Values)", - "\n {", - "\n return GetStorage().GetValuationPeriod(Identity.Id) switch {", - "\n ValuationPeriod.BeginningOfPeriod => Values.ElementAtOrDefault(shift),", - "\n ValuationPeriod.MidOfPeriod => Values.ElementAtOrDefault(shift + Convert.ToInt32(Math.Round(timeStep / 2d, MidpointRounding.AwayFromZero)) - 1),", - "\n ValuationPeriod.Delta => Values.Skip(shift).Take(timeStep).Sum(),", - "\n ValuationPeriod.EndOfPeriod => Values.ElementAtOrDefault(shift + timeStep),", - "\n ValuationPeriod.NotApplicable => default", - "\n };", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LX0IfHO1HkG3juJfHtyRsQ", - "cell_type": "markdown", - "source": [ - "An example of Projected Present Value calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." - ], - "metadata": {} - }, - { - "id": "JablJ7mjvkSSqXmjUWZ-mg", - "cell_type": "markdown", - "source": [ - "", - "\n### Interest Accretion", - "\n", - "\nSince the Interest Accretion cashflows are typically not provided as input (as they can be computed from its parent AocStep), its present values can be computed as follows:", - "\n", - "\n$$", - "\n\\text{InterestAccretion}_i(\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\big(\\text{CDC}_i(\\text{Parent AoC step}) - \\text{Nominal}_i(\\text{parent AoC step}) \\big) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, & \\text{if Amount Type's Transaction Period is Beginning of Period} \\\\", - "\n\\text{CDC}_i(\\text{parent AoC step}) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, & \\text{otherwise}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\n
Due to the Credit Default Risk of a reinsurance partner, the logic to compute the Interest Accretion for this Amount Type must be defined separately. Since it is based on Claims, the Period Type is implicitly defined." - ], - "metadata": {} - }, - { - "id": "vGVQDaWg2UeXvSxdJ18zpA", - "cell_type": "code", - "source": [ - "public interface IWithInterestAccretion : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", - "\n{", - "\n private double[] parentDiscountedValues => GetScope(Identity).Values; ", - "\n private double[] parentNominalValues => GetScope(Identity).Values;", - "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", - "\n ", - "\n double[] GetInterestAccretion() ", - "\n {", - "\n var periodType = GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType);", - "\n var ret = new double[parentDiscountedValues.Length];", - "\n ", - "\n switch (periodType) {", - "\n case PeriodType.BeginningOfPeriod :", - "\n for (var i = 0; i < parentDiscountedValues.Length; i++)", - "\n ret[i] = (parentDiscountedValues[i] - parentNominalValues[i]) * (GetElementOrDefault(monthlyInterestFactor, i/12) - 1d );", - "\n break;", - "\n default :", - "\n for (var i = 0; i < parentDiscountedValues.Length; i++)", - "\n ret[i] = parentDiscountedValues[i] * (GetElementOrDefault(monthlyInterestFactor, i/12) - 1d );", - "\n break;", - "\n }", - "\n ", - "\n return ret;", - "\n }", - "\n}", - "\n", - "\npublic interface IWithInterestAccretionForCreditRisk : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", - "\n{", - "\n private double[] nominalClaimsCashflow => GetScope(Identity).Values;", - "\n private double[] nominalValuesCreditRisk => -1 * GetScope(Identity with {Id = Identity.Id with {AocType = AocTypes.CF}}).Values;", - "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", - "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", - "\n ", - "\n double[] GetInterestAccretion() ", - "\n {", - "\n var interestOnClaimsCashflow = new double[nominalClaimsCashflow.Length];", - "\n var interestOnClaimsCashflowCreditRisk = new double[nominalClaimsCashflow.Length];", - "\n var effectCreditRisk = new double[nominalClaimsCashflow.Length];", - "\n for (var i = nominalClaimsCashflow.Length - 1; i >= 0; i--) {", - "\n interestOnClaimsCashflow[i] = 1 / GetElementOrDefault(monthlyInterestFactor, i/12) * (interestOnClaimsCashflow.ElementAtOrDefault(i + 1) + nominalClaimsCashflow[i] - nominalClaimsCashflow.ElementAtOrDefault(i + 1));", - "\n interestOnClaimsCashflowCreditRisk[i] = 1 / GetElementOrDefault(monthlyInterestFactor, i/12) * (Math.Exp(-nonPerformanceRiskRate) * interestOnClaimsCashflowCreditRisk.ElementAtOrDefault(i + 1) + nominalClaimsCashflow[i] - nominalClaimsCashflow.ElementAtOrDefault(i + 1));", - "\n effectCreditRisk[i] = interestOnClaimsCashflow[i] - interestOnClaimsCashflowCreditRisk[i];", - "\n }", - "\n ", - "\n return effectCreditRisk - nominalValuesCreditRisk;", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "f_Nqjp76YUWFtL08hw0iTg", - "cell_type": "markdown", - "source": [ - "An example of the Interest Accretion calculations can be found [here](../Test/SpecificationsImportCashflows#interest-accretion)." - ], - "metadata": {} - }, - { - "id": "lWN9DuSvtkWi8KPDtnLcZA", - "cell_type": "markdown", - "source": [ - "", - "\n### Present Value Base", - "\n", - "\nThe PV Base values are valid for all choices of the [Economic Basis](../DataModel/DataStructure#economic-basis):", - "\n", - "\n$$", - "\n\\text{PV Base}_i (\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{rl}", - "\n\\text{CDC}_i ~, & \\text{if AoCType = BOP} \\\\", - "\n-\\text{Nominal}_i(\\text{Parent AoC step}) ~, & \\text{if AoCType = CF } \\\\", - "\n\\text{InterestAccretion}_i ~, & \\text{if AoCType = IA } \\\\", - "\n0 ~, & \\text{if AoCType = AM } \\\\\\", - "\n\\text{CDC}_i(\\text{Parent AoC step}) ~, & \\text{if AoCType = EOP } \\\\", - "\n\\text{TelescopingDifference}_i ~, & \\text{otherwise}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere $i$ denotes the months, and the [$\\rm{TelescopingDifference}_i$](#telescopic-difference) and the [$\\rm{InterestAccretion}_i$](#interest-accretion) quantities are defined above." - ], - "metadata": {} - }, - { - "id": "NX2BdeLNxk2VWROO8E5pBg", - "cell_type": "code", - "source": [ - "public interface PresentValue : IWithGetValueFromValues", - "\n{ ", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", - "\n || x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode))", - "\n .WithApplicability(x => (x.Identity.Id.AocType == AocTypes.BOP && x.Identity.Id.Novelty != Novelties.C) || x.Identity.Id.AocType == AocTypes.EOP)", - "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.CF)", - "\n .WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.IA)", - "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.IA)", - "\n .WithApplicability(x => new string[]{AocTypes.BOP, AocTypes.EA, AocTypes.AM, AocTypes.RCU}.Contains(x.Identity.Id.AocType) ) //add here combination CRU for At !CDR?", - "\n );", - "\n ", - "\n [NotVisible][IdentityProperty][Dimension(typeof(EconomicBasis))]", - "\n string EconomicBasis => GetContext();", - "\n ", - "\n [NotVisible]", - "\n double[] Values => GetScope(Identity).Values;", - "\n ", - "\n public double Value => GetValueFromValues(Values);", - "\n}", - "\n", - "\npublic interface ComputePresentValueWithIfrsVariable : PresentValue", - "\n{", - "\n double PresentValue.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.CalculationType, EconomicBasis, Identity.AccidentYear); //unify CalculationType and EstimateTypeGet", - "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", - "\n}", - "\n", - "\npublic interface PresentValueFromDiscountedCashflow : PresentValue", - "\n{", - "\n [NotVisible]", - "\n double[] PresentValue.Values => GetScope(Identity).Values;", - "\n}", - "\n", - "\npublic interface CashflowAocStep : PresentValue", - "\n{", - "\n [NotVisible]", - "\n double[] PresentValue.Values => -1d * GetScope(Identity).Values;", - "\n}", - "\n", - "\npublic interface PresentValueWithInterestAccretion : PresentValue, IWithInterestAccretion", - "\n{", - "\n [NotVisible]", - "\n double[] PresentValue.Values => GetInterestAccretion();", - "\n}", - "\n", - "\npublic interface PresentValueWithInterestAccretionForCreditRisk : PresentValue, IWithInterestAccretionForCreditRisk", - "\n{", - "\n [NotVisible]", - "\n double[] PresentValue.Values => GetInterestAccretion();", - "\n}", - "\n", - "\npublic interface EmptyValuesAocStep : PresentValue", - "\n{", - "\n [NotVisible]", - "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yZbP0Jm3ckC1XQBFERPm_g", - "cell_type": "markdown", - "source": [ - "An example of the Present Value Base calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." - ], - "metadata": {} - }, - { - "id": "lWMlf8gT5kGtPaXz4CcdLg", - "cell_type": "markdown", - "source": [ - "", - "\n### Current and Locked", - "\n", - "\nPV Current and PV Locked below basically hold the Present Values [PV](#present-value) computed using the **Current** yield curves and the **Locked** yield curves, respectively.", - "\n", - "\nValues are available for each AmountType (by calling PvLocked.ByAmountType):", - "\n", - "\n$$", - "\n\\text{PV Locked}(\\text{AoC step}, \\text{Amount Type}) = \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = L}}", - "\n$$", - "\n", - "\n$$", - "\n\\text{PV Current}(\\text{AoC step}, \\text{Amount Type}) = \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = C}}", - "\n$$", - "\n", - "\n", - "\nAnd aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type) (by calling PvLocked.Value):", - "\n", - "\n$$", - "\n\\text{PV Locked}(\\text{AoC step}) = \\sum_{\\text{Amount Types}} \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = L}}", - "\n$$", - "\n", - "\n$$", - "\n\\text{PV Current}(\\text{AoC step}) = \\sum_{\\text{Amount Types}} \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = C}}", - "\n$$", - "\n", - "\nThese are used in the BBA methodology, whereby in the CSM calculations only PV Locked is used, and both of them are stored in the database under the [IfrsVariable](../DataModel/DataStructure#ifrs-variable) data structure." - ], - "metadata": {} - }, - { - "id": "1wOqzclAjkaUcoGzwf1ldQ", - "cell_type": "code", - "source": [ - "public interface PvLocked : IScope", - "\n{ ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", - "\n string EconomicBasis => EconomicBases.L;", - "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.BE;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", - "\n ", - "\n [NotVisible]", - "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", - "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", - "\n .ToArray();", - "\n double Value => PresentValues.Aggregate().Value;", - "\n}", - "\n", - "\npublic interface PvCurrent : IScope", - "\n{", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", - "\n string EconomicBasis => EconomicBases.C;", - "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.BE;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", - "\n ", - "\n [NotVisible]", - "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", - "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", - "\n .ToArray();", - "\n ", - "\n double Value => PresentValues.Aggregate().Value;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6pCT1yWm30S4fz2w2Km62w", - "cell_type": "markdown", - "source": [ - "", - "\n## Risk Adjustment", - "\n", - "\nRisk Adjustment values ($\\rm{RA}$) are accessible from the [PV Base](#present-value-base) data and have [Calculation Type](../DataModel/DataStructure#calculation-type) $RA$. In particular, the Locked-In and Current values are given by:", - "\n", - "\n$$", - "\n\\text{RA Locked}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = L}}", - "\n$$", - "\n", - "\n$$", - "\n\\text{RA Current}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = C}}", - "\n$$", - "\n", - "\nwhere PV is defined [above](#present-value) and uses the input cashflows with Calculation Type = RA." - ], - "metadata": {} - }, - { - "id": "TrbvThWf6EergPrBDCULNQ", - "cell_type": "code", - "source": [ - "public interface RaLocked : IScope", - "\n{ ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", - "\n string EconomicBasis => EconomicBases.L;", - "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.RA;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", - "\n ", - "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray();", - "\n ", - "\n double Value => PresentValues.Aggregate().Value;", - "\n}", - "\npublic interface RaCurrent : IScope", - "\n{", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", - "\n string EconomicBasis => EconomicBases.C;", - "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.RA;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", - "\n ", - "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", - "\n ", - "\n double Value => PresentValues.Aggregate().Value;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lCTjmXtNM0anxWCIugOk1g", - "cell_type": "markdown", - "source": [ - "", - "\n## Amortization", - "\n", - "\nFor the Amortization AoC Step (AoC Type **AM**), the amortization factors to be used are defined below." - ], - "metadata": {} - }, - { - "id": "1EJRTEzTH02xfXBuVK6aQQ", - "cell_type": "markdown", - "source": [ - "", - "\n### Coverage Units", - "\n", - "\nThe coverage unit (CU) of a GIC is introduced in the standard as the quantity of the service provided in that GIC. The service is", - "\nmeasured by considering the quantity of benefits provided as well as the expected coverage period of the GIC.", - "\n", - "\nThe cashflows of coverage units are retrieved from the discounted cashflows with [Calculation Type](../DataModel/DataStructure#calculation-type) CU." - ], - "metadata": {} - }, - { - "id": "8s4nf1G3h0O5cmlvAC3QLw", - "cell_type": "code", - "source": [ - "public interface CoverageUnitCashflow : IScope", - "\n{ ", - "\n [NotVisible] string EconomicBasis => GetContext();", - "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.CU;", - "\n ", - "\n double[] Values => GetScope((Identity, (string)null, CalculationType, (int?)null)).Values;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BTET6Z8yrkOpMBOGK5Bu3g", - "cell_type": "markdown", - "source": [ - "", - "\n### Amortization Factor" - ], - "metadata": {} - }, - { - "id": "m1VQAxKwaEuv9KI6qEVFxA", - "cell_type": "markdown", - "source": [ - "For a certain GIC, the monthly Amortization Factors $\\text{Monthly }AF_i$ are computed from the cashflows of the underlying coverage unit for that GIC:", - "\n", - "\n$$", - "\n\\text{Monthly }AF_i = 1 - \\frac{ \\text{Nominal}_i(CL)} {\\text{CDC}_i(CL) } ~.", - "\n$$", - "\n", - "\nwhere:", - "\n- $i$ denotes a monthly period;", - "\n- the nominal cash flows $\\text{Nominal}_i(CL)$ are the nominal cashflows of the coverage unit for the AoC Step **Combined Liability** (CL) (input data);", - "\n- and the corresponding cumulated discounted cashflows $\\text{CDC}_i$ are defined [above](#cumulated-discounted-cashflows)." - ], - "metadata": {} - }, - { - "id": "ilj2SgcU7kOjz53Sf946cw", - "cell_type": "code", - "source": [ - "public interface MonthlyAmortizationFactorCashflow : IScope", - "\n{", - "\n private double[] NominalCuCashflow => GetScope((Identity with {AocType = AocTypes.CL}, (string)null, CalculationTypes.CU, (int?)null)).Values;", - "\n private double[] DiscountedCuCashflow => GetScope(Identity with {AocType = AocTypes.CL}, o => o.WithContext(EconomicBasis)).Values;", - "\n ", - "\n [NotVisible] string EconomicBasis => GetContext();", - "\n ", - "\n double[] MonthlyAmortizationFactors => Identity.AocType switch {", - "\n AocTypes.AM => NominalCuCashflow.Zip(DiscountedCuCashflow, //Extract to an other scope with month in the identity to avoid Zip?", - "\n (nominal, discountedCumulated) => discountedCumulated >= Precision ", - "\n ? 1 - nominal / discountedCumulated ", - "\n : 0).ToArray(),", - "\n _ => Enumerable.Empty().ToArray(),", - "\n };", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bqUlBh41xUCZmzV497BLug", - "cell_type": "markdown", - "source": [ - "For a certain projection period - defined by the Shift, $S$, and the Time-Step, $TS$, parameters - the Amortization Factor is then given by the product of the corresponding monthly amortization factors:", - "\n", - "\n$$", - "\nAF = \\prod _{i = S}^{TS} \\text{Monthly }AF_i ~.", - "\n$$", - "\n", - "\nEach GIC will have his own AF." - ], - "metadata": {} - }, - { - "id": "6OE1dyBDq0-W4sMSuAQoeQ", - "cell_type": "code", - "source": [ - "public interface CurrentPeriodAmortizationFactor : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => ", - "\n s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", - "\n || x.GetStorage().IsSecondaryScope(x.Identity.DataNode)));", - "\n ", - "\n private int shift => GetStorage().GetShift(0);//Identity.ProjectionPeriod", - "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.ProjectionPeriod", - "\n ", - "\n [NotVisible] string EconomicBasis => GetContext();", - "\n ", - "\n string EstimateType => EstimateTypes.F;", - "\n double Value => GetScope(Identity)", - "\n .MonthlyAmortizationFactors", - "\n .Skip(shift)", - "\n .Take(timeStep)", - "\n .Aggregate(1d, (x, y) => x * y);", - "\n}", - "\n", - "\npublic interface AmfFromIfrsVariable : CurrentPeriodAmortizationFactor", - "\n{", - "\n double CurrentPeriodAmortizationFactor.Value => GetStorage().GetValue(Identity, (string)null, EstimateType, EconomicBasis, (int?)null); //unify CalculationType and EstimateTypeGet", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jpW8fnmKpEi5m8fmZckqfA", - "cell_type": "markdown", - "source": [ - "", - "\n## Actual Values", - "\n", - "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", - "\n- Actuals (A)", - "\n- Advance Actuals (AA)", - "\n- Overdue Actuals (OA)", - "\n- Deferrable Actuals (DA)", - "\n", - "\nwith the Estimate Type's system name shown between parenthesis above.", - "\n", - "\nThe following simplified AoC Chain applies for Advance and Overdue Actuals:", - "\n
 BOP", - "\n
 Release", - "\n
 Write-off", - "\n
 EOP" - ], - "metadata": {} - }, - { - "id": "EBK-msISl0WxxcRgAvBDWQ", - "cell_type": "markdown", - "source": [ - "", - "\n### Actual Base", - "\n", - "\nThe Actual Base sets values for actual, advance, and overdue as follows:", - "\n", - "\n$$", - "\n\\text{Actual Base} (\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{rl}", - "\n0 ~, & \\text{if AoC Step's AoC Type = AM} \\\\", - "\n\\text{Actual Base}(\\rm{BOP}) + \\text{Actual Base}(\\rm{CF}) + \\text{Actual Base}(\\rm{WO}) ~, & \\text{if AoC Step's AoC Type = EOP and EstimateType is not A} \\\\", - "\n\\text{Imported Actual} ~, & \\text{otherwise}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere the value is also function of the [Estimate Type](../DataModel/DataStructure#EstimateType) and [Amount Type](../DataModel/DataStructure#AmountType), and the $\\text{Imported Actual}$ value is described [here]()." - ], - "metadata": {} - }, - { - "id": "_w7DsklRxEy1-gr0L3xnxQ", - "cell_type": "code", - "source": [ - "public interface ActualBase : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Actual ", - "\n && !x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode)", - "\n && x.Identity.Id.AocType == AocTypes.AM)", - "\n .WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow ", - "\n && !x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode)", - "\n && x.Identity.Id.AocType == AocTypes.EOP ", - "\n && x.Identity.EstimateType != EstimateTypes.A)", - "\n );", - "\n public double Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear); ", - "\n}", - "\n", - "\npublic interface EndOfPeriodActual : ActualBase", - "\n{", - "\n double ActualBase.Value => GetScope((Identity.Id, InputSource.Actual)).Values", - "\n .Sum(aocStep => GetScope((Identity.Id with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear)).Value);", - "\n}", - "\n", - "\npublic interface EmptyValuesActual : ActualBase", - "\n{", - "\n double ActualBase.Value => 0;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hZgnWCXsbEm7b3a_M5X91Q", - "cell_type": "markdown", - "source": [ - "An example of Actual Base figures can be found [here](../Test/SpecificationsImportActuals#base-actual)." - ], - "metadata": {} - }, - { - "id": "seP-q4-pNEKPbBJB6XWgGQ", - "cell_type": "markdown", - "source": [ - "", - "\n### Actuals", - "\nThe Actuals correspond to ActualBase values with estimate type $A$.", - "\nThe only valid Aoc step is Release:", - "\n", - "\n$$", - "\n\\text{Actual} (\\text{Release}) = \\text{Actual Base} (\\text{Release})|_{\\text{Estimate Type} = A}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "rA5FAU7rP0mVtOb_OMRAQQ", - "cell_type": "code", - "source": [ - "public interface Actual : IScope", - "\n{", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", - "\n string EstimateType => EstimateTypes.A;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", - "\n ", - "\n [NotVisible]", - "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", - "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tQS8QPziAEWrDh1ztulzDw", - "cell_type": "markdown", - "source": [ - "", - "\n### Advance Actuals", - "\n", - "\n**Advance Actuals** are those cashflows with due date inside the reporting period but which occured *before* the reporting period - They include:", - "\n- Receivable Claims", - "\n- Receivable Expenses", - "\n- Payable Premiums", - "\n", - "\nAdvance Actuals are given by", - "\n", - "\n$$", - "\n\\text{Advance Actual} (\\text{AoC step}) = \\text{Actual Base} (\\text{AoC step})|_{\\text{Estimate Type} = AA}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "BGCY3AvaxkWvnU8Py4UK5w", - "cell_type": "code", - "source": [ - "public interface AdvanceActual : IScope", - "\n{", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", - "\n string EstimateType => EstimateTypes.AA;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", - "\n ", - "\n [NotVisible]", - "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", - "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "EDA0vEXMd0602tAx8vQ8Eg", - "cell_type": "markdown", - "source": [ - "", - "\n### Overdue Actuals", - "\n", - "\n**Overdue Actuals** are those cashflows with due date inside the reporting period but which occur *after* the reporting period - They contain:", - "\n- Payable Claims", - "\n- Payable Expenses", - "\n- Receivable Premiums", - "\n", - "\nThe sign convention is the inverse of the default behavior - In particular: Premiums have positive value, whereas Claims and Expenses have negative value.", - "\n", - "\nThe Overdue Actuals are given by", - "\n", - "\n$$", - "\n\\text{Overdue Actual} (\\text{AoC step}) = \\text{Actual Base} (\\text{AoC step})|_{\\text{Estimate Type} = OA}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "JhdC-O-53k-OPdsSNtyTqQ", - "cell_type": "code", - "source": [ - "public interface OverdueActual : IScope", - "\n{", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", - "\n string EstimateType => EstimateTypes.OA;", - "\n ", - "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", - "\n ", - "\n [NotVisible]", - "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", - "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BU02PReB0UyuCXL3rgF7kw", - "cell_type": "markdown", - "source": [ - "", - "\n### Deferrable Actuals", - "\n", - "\nFinally, Deferrable Actuals are given by", - "\n", - "\n$$", - "\n\\text{Deferrable Actual} (\\text{AoC step}) = \\left\\{", - "\n\\begin{array}{rl}", - "\n\\sum_{\\text{Amount Type}~\\in~\\text{\\{ACA, AEA}\\}}\\text{Actual Base}(\\rm{CF})|_{\\text{Estimate Type = A}} ~, & \\text{if AoC Step's AoC Type = CF } \\\\", - "\n- \\text{Amortization Factor} \\cdot \\big( \\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) \\big) ~, & \\text{if AoC Step's AoC Type = AM } \\\\", - "\n\\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) + \\text{Deferrable Actual}(\\rm{AM}) ~, & \\text{if AoC Step's AoC Type = EOP } \\\\", - "\n\\text{Input Actual}|_{\\text{Estimate Type = DA}} ~, & \\text{ otherwise } \\\\", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere $ACA$ and $AEA$ are *Aquisition* Amount Types from **Attributable Commission** and **Attributable Expenses**, respectively." - ], - "metadata": {} - }, - { - "id": "ydbJzjQG6kGLXvpaU9QqxQ", - "cell_type": "code", - "source": [ - "public interface DeferrableActual : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.VFA, ", - "\n p => p.ForMember(s => s.EconomicBasis))", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CF)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.AM)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)", - "\n );", - "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", - "\n string EstimateType => EstimateTypes.DA;", - "\n ", - "\n [NotVisible] string EconomicBasis => EconomicBases.L;", - "\n ", - "\n public double Value => GetStorage().GetValue(Identity, (string)null, EstimateType, (int?)null);", - "\n}", - "\n", - "\npublic interface DeferrableActualForCurrentBasis : DeferrableActual", - "\n{", - "\n [NotVisible] string DeferrableActual.EconomicBasis => EconomicBases.C;", - "\n}", - "\n", - "\npublic interface ReleaseDeferrable : DeferrableActual", - "\n{", - "\n double DeferrableActual.Value => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(at => GetScope((Identity, at, EstimateTypes.A, (int?)null)).Value);", - "\n}", - "\n", - "\npublic interface AmortizationDeferrable : DeferrableActual", - "\n{", - "\n private double AmortizationFactor => GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;", - "\n private double AggregatedDeferrable => GetScope((Identity, InputSource.Actual)).Values", - "\n .Sum(aocStep => GetScope(Identity with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}).Value);", - "\n double DeferrableActual.Value => -1d * AggregatedDeferrable * AmortizationFactor;", - "\n}", - "\n", - "\npublic interface EndOfPeriodDeferrable : DeferrableActual", - "\n{", - "\n double DeferrableActual.Value => GetScope((Identity, InputSource.Actual)).Values", - "\n .Sum(aocStep => GetScope(Identity with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}).Value);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "p-VbKXd52UuaKecFYnE8iQ", - "cell_type": "markdown", - "source": [ - "An example of Deferrable Actual figures can be found [here](../Test/SpecificationsImportActuals#deferrable-actual)." - ], - "metadata": {} - }, - { - "id": "Mtf0XXuvUkS76O6DBZUr4A", - "cell_type": "markdown", - "source": [ - "", - "\n## Contractual Service Margin, Loss Component and Loss Recovery Component", - "\n", - "\nThe Contractual Service Margin ($CSM$) denotes the unearned profit from an insurance contract or group of insurance contracts and plays a critical role in the calculation of profit & loss values. Similarly, the unearned loss is denoted by Loss Component ($LC$), Loss Recovery Component in the case of reinsurance contracts." - ], - "metadata": {} - }, - { - "id": "Wq-e5YleykGCYEopzDLT4A", - "cell_type": "markdown", - "source": [ - "## Experience Adjustment on Premium" - ], - "metadata": {} - }, - { - "id": "JwOnE_oxnE6u4nU3ZQku3Q", - "cell_type": "markdown", - "source": [ - "The Experience Adjustment (EA) on Premiums weights the cash-flow (CF aocSteps) for premium amount types by the PremiumAllocationFactor input for each group of insurance contract. ", - "\nThe contributions of present values and actuals are computed separately.", - "\n", - "\n$$", - "\nEA (\\rm{PV}) = \\text{Premium Allocation Factor} \\cdot \\big( PV (\\text{AocType = CF}) \\big)~, \\\\", - "\n$$", - "\n$$", - "\nEA (\\text{Actual}) = \\text{Premium Allocation Factor} \\cdot \\big( \\text{Actual}(\\text{AocType = CF}) + \\text{Advance Actual}(\\text{AocType = CF})+ \\text{Overdue Actual}(\\text{AocType = CF}) \\big) ~,", - "\n$$", - "\nwhere amount type premium and its children are considered, novelties in-force and new business are considered for $PV$ whereas novelty combined is considered for Actual. The allocation is always done in the finest granularity (novelty, line of business, ..) possible." - ], - "metadata": {} - }, - { - "id": "pEi0POgs0UejZ_BJaXi_LQ", - "cell_type": "code", - "source": [ - "public interface BeExperienceAdjustmentForPremium : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s", - "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", - "\n", - "\n string EstimateType => EstimateTypes.BEPA;", - "\n string EconomicBasis => EconomicBases.L;", - "\n ", - "\n PresentValue[] ByAmountType => GetStorage().GetPremiums().Select(pr => GetStorage().GetPremiumAllocationFactor(Identity) * GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis))).ToArray(); ", - "\n}", - "\n", - "\npublic interface DefaultValueBeExperienceAdjustmentForPremium : BeExperienceAdjustmentForPremium", - "\n{", - "\n PresentValue[] BeExperienceAdjustmentForPremium.ByAmountType => Enumerable.Empty().ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CA2eQXhYYUevjiAr92nN6Q", - "cell_type": "code", - "source": [ - "public interface ActualExperienceAdjustmentForPremium : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s", - "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", - "\n ", - "\n public ActualBase[] ByAmountTypeAndEstimateType => GetStorage().GetPremiums().SelectMany(pr => ", - "\n GetStorage().ExperienceAdjustEstimateTypeMapping.Keys", - "\n .Select(et => GetStorage().GetPremiumAllocationFactor(Identity) * ", - "\n GetScope((Identity, pr, et, (int?)null)))).ToArray(); ", - "\n}", - "\n", - "\npublic interface DefaultValueActualExperienceAdjustmentForPremium : ActualExperienceAdjustmentForPremium", - "\n{", - "\n ActualBase[] ActualExperienceAdjustmentForPremium.ByAmountTypeAndEstimateType => Enumerable.Empty().ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "czmwLF-VTkKtolr0jqiX8w", - "cell_type": "markdown", - "source": [ - "", - "\n## Technical Margin", - "\n", - "\nFor the computation of the $CSM$ or $LC$ component values for each step of the [AoC Step Structure](#aoc-step-structure), it is convenient to introduce the ", - "\nnotion of technical margin $TM$. In the case of BBA methodology, the Locked-in interest rates discounting is applied to obtain the PV and RA values.", - "\n", - "\nThis can be summarized as follows:", - "\n", - "\n$$", - "\nTM(s) = \\left\\{", - "\n\\begin{array}{rl}", - "\nTM(\\rm{EOP}) \\text{ of the previous period} ~ & \\text{if }s = \\text{BOP and Novelty is In-Force}.", - "\n\\\\", - "\n0 ~ & \\text{if }s = \\text{CF}.", - "\n\\\\", - "\nIAF \\cdot~\\text{Aggregated}~TM(\\text{IA}) ~ & \\text{if }s = \\text{IA and Novelty is In-Force}.", - "\n\\\\", - "\n\\rm{Premiums} + \\text{Attributable Expense and Commissions} + \\text{Investment Claims} ~ & \\text{if }s = \\text{EA}.", - "\n\\\\", - "\n-AF \\cdot~\\text{Aggregated}~TM(\\text{AM})~ & \\text{if }s = \\text{AM}.", - "\n\\\\", - "\n\\text{PV}(\\text{s})\\bigg|_{\\substack{\\text{Non Attributable} \\\\ \\text{Amount Types} \\\\ \\text{excluded}}} ", - "\n+ \\text{RA}(\\text{s})~ & \\text{otherwise} ", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere", - "\n", - "\n$$", - "\n\\text{Aggregated}~TM (\\text{AoC step}) = \\sum_{s\\in\\text{ previous AoC steps}} TM(s)~.", - "\n$$", - "\n", - "\nand the Interest Accretion Factor ($IAF$) is given by", - "\n", - "\n$$", - "\nIAF = \\prod_{i=1}^{TS} \\text{Interest}_i - 1", - "\n$$", - "\n", - "\nwhere $\\text{Interest}_i$ is the monthly interest factor obtained from the [Yield Curve](#yield-curves) and $TS$ is the Time-Step.", - "\n", - "\nFinally, the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", - "\n", - "\n$$", - "\n\\rm{Premiums} = \\sum_{\\text{Amount Type}\\in\\{\\text{PR and its children}\\}}", - "\nEA(\\rm{PV}) - EA(\\text{Actual}) ~,", - "\n$$", - "\n", - "\n$$", - "\n\\text{Attributable Expense and Commissions} = \\sum_{\\text{Amount Type}\\in\\{\\rm{ACA}, \\rm{AEA}\\}}", - "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\text{Actual}_{\\text{Novelty=C}} ~,", - "\n$$", - "\n", - "\n$$", - "\n\\text{Investment Claims } = \\sum_{\\text{Amount Type}\\in\\{\\text{ICO and its children}\\}}", - "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}}+ \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~,", - "\n$$", - "\n", - "\nwhere the AoC Step **CF** is implicit for all formulas, $PV$ is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **AA**, and **OA** (see details [here](#actual-values))." - ], - "metadata": {} - }, - { - "id": "uWXzMWj2I0mfBjJ6P43ZFg", - "cell_type": "code", - "source": [ - "public interface TechnicalMargin : IScope", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ", - "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.VFA, p => p.ForMember(s => s.EconomicBasis))", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP && x.Identity.Novelty == Novelties.I)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CF)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.IA && x.Identity.Novelty == Novelties.I)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EA && !x.Identity.IsReinsurance)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.AM)", - "\n );", - "\n ", - "\n [NotVisible] string EconomicBasis => EconomicBases.L;", - "\n ", - "\n double Value => GetScope(Identity.DataNode).BeAmountTypes", - "\n .Except(GetStorage().GetNonAttributableAmountType())", - "\n .Sum(at => GetScope((Identity, at, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", - "\n GetScope(Identity).Value;", - "\n ", - "\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values", - "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);", - "\n}", - "\n", - "\npublic interface TechnicalMarginForCurrentBasis : TechnicalMargin", - "\n{", - "\n [NotVisible] string TechnicalMargin.EconomicBasis => EconomicBases.C;", - "\n}", - "\n", - "\npublic interface TechnicalMarginForBOP : TechnicalMargin", - "\n{", - "\n private double ValueCsm => GetStorage().GetValue(Identity, null, EstimateTypes.C, null);", - "\n private double ValueLc => GetStorage().GetValue(Identity, null, EstimateTypes.L, null);", - "\n private double ValueLr => GetStorage().GetValue(Identity, null, EstimateTypes.LR, null);", - "\n ", - "\n double TechnicalMargin.Value => -1d * ValueCsm + ValueLc + ValueLr;", - "\n}", - "\n", - "\npublic interface TechnicalMarginDefaultValue : TechnicalMargin", - "\n{", - "\n double TechnicalMargin.Value => default;", - "\n}", - "\n", - "\npublic interface TechnicalMarginForIA : TechnicalMargin", - "\n{", - "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", - "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", - "\n ", - "\n private double[] monthlyInterestFactor => GetScope(Identity, o => o.WithContext(EconomicBasis)).Interest;", - "\n ", - "\n private double interestAccretionFactor => Enumerable.Range(shift,timeStep)", - "\n .Select(i => GetElementOrDefault(monthlyInterestFactor, i/12))", - "\n .Aggregate(1d, (x, y) => x * y ) - 1d;", - "\n ", - "\n double TechnicalMargin.Value => AggregatedValue * interestAccretionFactor;", - "\n}", - "\n", - "\npublic interface TechnicalMarginForEA : TechnicalMargin", - "\n{", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilderInner(ApplicabilityBuilder builder) => ", - "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.IsReinsurance));", - "\n ", - "\n private string referenceAocType => GetScope(Identity).Value.AocType;", - "\n ", - "\n private double premiums => GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope(Identity with {AocType = referenceAocType, Novelty = n}).ByAmountType.Sum(sc => sc.Value)) -", - "\n GetScope(Identity with {AocType = referenceAocType, Novelty = Novelties.C}).ByAmountTypeAndEstimateType.Sum(sc => sc.Value);", - "\n ", - "\n private double attributableExpenseAndCommissions => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(d =>", - "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", - "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, d, EstimateTypes.A, (int?)null)).Value);", - "\n", - "\n private double investmentClaims => GetStorage().GetInvestmentClaims().Sum(ic =>", - "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", - "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.A, (int?)null)).Value - ", - "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.AA, (int?)null)).Value -", - "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.OA, (int?)null)).Value);", - "\n ", - "\n double TechnicalMargin.Value => premiums + attributableExpenseAndCommissions + investmentClaims;", - "\n}", - "\n", - "\npublic interface TechnicalMarginForAM : TechnicalMargin", - "\n{", - "\n double TechnicalMargin.Value => -1d * AggregatedValue * GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "eV_qYONYOU-QbM_aQVg7vg", - "cell_type": "markdown", - "source": [ - "", - "\n## Switch Logic", - "\n ", - "\nThe $CSM$ and $LC$ components are computed from the [technical margin](#technical-margin). In particular, for a given AoC step $s$, TM is allocated to the $LC$ when $\\text{Aggregated } TM$ is positive whereas it is allocated to the $CSM$ when $\\text{Aggregated } TM$ is negative:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\nCSM({\\text{Aoc step}}) = 0,~~ LC({\\text{AoC step}}) = TM({\\text{AoC step}}) ~ & \\text{if }\\text{Aggregated }TM({\\text{AoC step}}) > 0.", - "\n\\\\", - "\nCSM({\\text{Aoc step}}) = - TM({\\text{AoC step}}),~~ LC({\\text{AoC step}}) = 0 ~ & \\text{otherwise} ", - "\n\\end{array}", - "\n$$", - "\n", - "\n", - "\nThe figures reported under CSM are the opposite of the TM value in order to satisfy our sign convention.", - "\n", - "\nIt is possible to switch from $CSM$ to $LC$ and from $LC$ to $CSM$ at any AoC step $s$ with the only exception of **Amortization** where there is no switch from the previous step.", - "\nWhen a switch occurs the total contribution to the $CSM$ ($LC$) prior the switching step is brought to 0 and the remaing amount is allocated to $LC$ ($CSM$).", - "\n", - "\n", - "\n### Gross case (i.e. no reinsurance)", - "\n", - "\nThe switch logic is applied ***separately*** to the In-Force and New Business novelties. The Combined Liability Aoc Step **CL** will bring both contributions to CSM and LC together as the novelities are summed up.", - "\n", - "\nIn detail, and as we go through the AoC steps in the AoC chain, we have", - "\n", - "\n**A)** For the **BOP**:", - "\n$$", - "\n\\begin{array}{rl}", - "\nCSM(\\text{BOP}) &= CSM(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", - "\n\\\\", - "\nLC(\\text{BOP}) &= LC(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", - "\n\\end{array}", - "\n$$", - "\n", - "\n", - "\n**B)** For the **following AoC steps**, the switch logic is preferably formulated using the delta variations between steps, $\\Delta CSM$ and $\\Delta LC$ for the CSM and the LC respectively.", - "\n", - "\nThe switch logic for these AoC steps with the *exception* of Combined Liability is:", - "\n", - "\nIf $\\text{Aggregated }TM(\\text{AoC Step}) > 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\le 0$, then there is a switch from $LC$ to $CSM$:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\text{Aggregated } TM(\\text{AoC Step})", - "\n\\\\", - "\n\\Delta LC(\\text{AoC step}) &= -\\text{Aggregated } TM(\\text{AoC Step}) ", - "\n\\end{array}", - "\n$$", - "\n", - "\nOn the other hand, if $\\text{Aggregated }TM(\\text{AoC Step}) \\le 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) > 0$, then the switch is from $CSM$ to $LC$:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\n\\Delta CSM(\\text{AoC step}) &= \\text{Aggregated } TM(\\text{AoC Step}) ", - "\n\\\\", - "\n\\Delta LC(\\text{AoC step}) &= TM(\\text{AoC Step}) + \\text{Aggregated } TM(\\text{AoC Step}) ", - "\n\\end{array}", - "\n$$", - "\n", - "\nIf there is no switch from $CSM$, i.e. $\\text{Aggregated }TM(\\text{AoC Step}) \\le 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\le 0 $, then:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step})", - "\n\\\\", - "\n\\Delta LC(\\text{AoC step}) &= 0", - "\n\\end{array}", - "\n$$", - "\n", - "\nAnd finally, if there is no switch from $LC$, i.e. $\\text{Aggregated }TM(\\text{AoC Step}) > 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\ge 0 $, then:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\n\\Delta CSM(\\text{AoC step}) &= 0", - "\n\\\\", - "\n\\Delta LC(\\text{AoC step}) &= TM(\\text{AoC Step})", - "\n\\end{array}", - "\n$$", - "\n", - "\n**C)** For the AoC step Combined Liability **CL**, the switch logic is similar to the one above, except that a switch from $LC$ to $CSM$ can happen **because of New Business and despite of In-Force**, in which case we have:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\big(\\text{Aggregated } TM(\\text{Last In-Force AoC step})+TM(\\text{Last In-Force AoC step}) \\big)", - "\n\\\\", - "\n\\Delta LC(\\text{AoC step}) &= -\\big(\\text{Aggregated } TM(\\text{Last In-Force AoC step}) + TM(\\text{Last In-Force AoC step}) \\big)", - "\n\\end{array}", - "\n$$", - "\n", - "\nIf, on the other hand, the switch from $LC$ to $CSM$ happens **because of In-Force and despite of New Business**, then we have:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\big(\\text{Aggregated } TM(\\text{Last NB AoC step})+TM(\\text{Last NB AoC step}) \\big)", - "\n\\\\", - "\n\\Delta LC(\\text{AoC step}) &= -\\big(\\text{Aggregated } TM(\\text{Last NB AoC step}) + TM(\\text{Last NB AoC step}) \\big)", - "\n\\end{array}", - "\n$$", - "\n", - "\nFor the switch in the other direction, i.e. from $CSM$ to $LC$ the formulas are similar except that LC and CSM are swapped.", - "\n", - "\n**D)** Finally, for the last AoC step, the **EOP**, we have:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\nCSM(\\text{EOP}) &= \\sum_{s~\\in~\\text{previous AoC steps}}\\Delta CSM(s)", - "\n\\\\", - "\nLC(\\text{EOP}) &= \\sum_{s~\\in~\\text{previous AoC steps}}\\Delta LC(s)", - "\n\\end{array}", - "\n$$", - "\n", - "\n", - "\n### Reinsurance case", - "\n", - "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the gross Technical Margins multiplied by the weights coming from the Reinsurance Coverage Parameter (see [Data Node Parameters](../DataModel/DataStructure#data-node-parameters)). In case a GRIC has multiple GICs, then these weighted $TM$s are aggregated." - ], - "metadata": {} - }, - { - "id": "UnZAtItpLkaBp5iMJesSzw", - "cell_type": "code", - "source": [ - "public interface AllocateTechnicalMargin: IScope", - "\n{", - "\n //Switch", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ", - "\n builder.ForScope(s => s", - "\n .WithApplicability(x => x.Identity.IsReinsurance && x.Identity.AocType == AocTypes.CL) ", - "\n .WithApplicability(x => x.Identity.IsReinsurance, ", - "\n p => p.ForMember(s => s.ComputedEstimateType)", - "\n .ForMember(s => s.HasSwitch))", - "\n .WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity.DataNode)) ", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CL)", - "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)", - "\n );", - "\n ", - "\n [NotVisible] double AggregatedTechnicalMargin => GetScope(Identity).AggregatedValue; ", - "\n [NotVisible] double TechnicalMargin => GetScope(Identity).Value;", - "\n ", - "\n [NotVisible] string ComputedEstimateType => ComputeEstimateType(GetScope(Identity).AggregatedValue + TechnicalMargin);", - "\n [NotVisible] bool HasSwitch => ComputedEstimateType != ComputeEstimateType(GetScope(Identity).AggregatedValue);", - "\n ", - "\n //Allocate ", - "\n [NotVisible] string EstimateType => GetContext();", - "\n ", - "\n double Value => (HasSwitch, EstimateType == ComputedEstimateType) switch {", - "\n (true, true) => TechnicalMargin + AggregatedTechnicalMargin,", - "\n (true, false) => -1d * AggregatedTechnicalMargin,", - "\n (false, true) => TechnicalMargin,", - "\n _ => default", - "\n };", - "\n ", - "\n string ComputeEstimateType(double aggregatedTechnicalMargin) => aggregatedTechnicalMargin > Precision ? EstimateTypes.L : EstimateTypes.C;", - "\n}", - "\n", - "\npublic interface ComputeAllocateTechnicalMarginWithIfrsVariable : AllocateTechnicalMargin", - "\n{ ", - "\n double AllocateTechnicalMargin.TechnicalMargin => ComputeTechnicalMarginFromIfrsVariables(Identity);", - "\n double AllocateTechnicalMargin.AggregatedTechnicalMargin => GetScope((Identity, InputSource.Cashflow)).Values", - "\n .Sum(aoc => ComputeTechnicalMarginFromIfrsVariables(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}));", - "\n ", - "\n private double ComputeTechnicalMarginFromIfrsVariables(ImportIdentity id)", - "\n {", - "\n return GetStorage().GetValue(Identity, null, EstimateTypes.LR, null) +", - "\n GetStorage().GetValue(Identity, null, EstimateTypes.L, null) - ", - "\n GetStorage().GetValue(Identity, null, EstimateTypes.C, null);", - "\n }", - "\n}", - "\n", - "\npublic interface AllocateTechnicalMarginForReinsurance : AllocateTechnicalMargin", - "\n{ ", - "\n //TODO add Reinsurance Coverage Update (RCU, Novelty=I) AocStep", - "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);", - "\n ", - "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", - "\n GetScope(Identity with {DataNode = gic}).TechnicalMargin);", - "\n ", - "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", - "\n GetScope(Identity with {DataNode = gic}).AggregatedTechnicalMargin);", - "\n ", - "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;", - "\n ", - "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);", - "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => ComputedEstimateType != ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM); ", - "\n}", - "\n", - "\npublic interface AllocateTechnicalMarginForReinsuranceCL : AllocateTechnicalMargin", - "\n{ ", - "\n //In common1", - "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);", - "\n ", - "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", - "\n GetScope(Identity with {DataNode = gic}).TechnicalMargin);", - "\n ", - "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", - "\n GetScope(Identity with {DataNode = gic}).AggregatedTechnicalMargin);", - "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;", - "\n ", - "\n string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);", - "\n //In common2", - "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))", - "\n .Values", - "\n .GroupBy(x => x.Novelty)", - "\n .Select(g => g.Last())", - "\n .Sum(aoc => { ", - "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};", - "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ", - "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin", - "\n : (double)default; });", - "\n ", - "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;", - "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue; ", - "\n}", - "\n", - "\npublic interface AllocateTechnicalMarginForCl : AllocateTechnicalMargin", - "\n{", - "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))", - "\n .Values", - "\n .GroupBy(x => x.Novelty)", - "\n .Select(g => g.Last())", - "\n .Sum(aoc => { ", - "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};", - "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ", - "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin", - "\n : (double)default; });", - "\n", - "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;", - "\n ", - "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue;", - "\n}", - "\n", - "\npublic interface AllocateTechnicalMarginForBop : AllocateTechnicalMargin", - "\n{ ", - "\n bool AllocateTechnicalMargin.HasSwitch => false;", - "\n}", - "\n", - "\npublic interface AllocateTechnicalMarginForEop : AllocateTechnicalMargin", - "\n{", - "\n double AllocateTechnicalMargin.Value => GetScope((Identity, InputSource.Cashflow)).Values", - "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);", - "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeEstimateType(AggregatedTechnicalMargin);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vY4oXJJJ8ke97-m8ASMsAw", - "cell_type": "markdown", - "source": [ - "For the **Group of Reinsurance Contracts** (GRICs), the switch is computed within the underlying GIC context and $CSM$ and $LR$ are then computed in the same manner as for the underlying GICs CSM and LC." - ], - "metadata": {} - }, - { - "id": "DqGSuXbt6USNumZ69sErWg", - "cell_type": "markdown", - "source": [ - "The scopes below are simply used to set the appropriate Estimate Type (C for $CSM$, L for $LC$ and LR for $LCR$), as well as to set $CSM$ values to be positive:" - ], - "metadata": {} - }, - { - "id": "n2dT4_znvk2eUSMMef6OIg", - "cell_type": "code", - "source": [ - "public interface Csm : IScope", - "\n{", - "\n [NotVisible]string EstimateType => EstimateTypes.C;", - "\n ", - "\n double Value => -1d * GetScope(Identity, o => o.WithContext(EstimateType)).Value;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1fUoYZjlOki4f5GCvCmpoA", - "cell_type": "code", - "source": [ - "public interface Lc : IScope", - "\n{", - "\n [NotVisible]string EstimateType => EstimateTypes.L;", - "\n ", - "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TmqOsKRObkaw3PKUdp_lDw", - "cell_type": "code", - "source": [ - "public interface LoReCo : IScope", - "\n{ ", - "\n [NotVisible]string EstimateType => EstimateTypes.LR;", - "\n ", - "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_ejvWQaq-kSPyTqB4Y2n9Q", - "cell_type": "markdown", - "source": [ - "## Computing All Scopes", - "\n", - "\nSince all the calculations defined in the various scopes are to be performed together, it is useful to introduce the scope ComputeAllScopes below, which given a certain Import Identity and Import Storage, performs all the calculations (defined above) based on the corresponding data:" - ], - "metadata": {} - }, - { - "id": "68_d30x6ZUGoP_UjvJ9SBg", - "cell_type": "code", - "source": [ - "public interface ComputeAllScopes: IScope //ComputeIfrsVariable", - "\n{", - "\n IEnumerable PvLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", - "\n DataNode = x.Identity.Id.DataNode, ", - "\n AocType = x.Identity.Id.AocType, ", - "\n Novelty = x.Identity.Id.Novelty, ", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = x.Identity.AmountType,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n IEnumerable PvCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", - "\n DataNode = x.Identity.Id.DataNode, ", - "\n AocType = x.Identity.Id.AocType, ", - "\n Novelty = x.Identity.Id.Novelty, ", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = x.Identity.AmountType,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n IEnumerable RaCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", - "\n DataNode = x.Identity.Id.DataNode, ", - "\n AocType = x.Identity.Id.AocType, ", - "\n Novelty = x.Identity.Id.Novelty, ", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = null,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n IEnumerable RaLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", - "\n DataNode = x.Identity.Id.DataNode, ", - "\n AocType = x.Identity.Id.AocType, ", - "\n Novelty = x.Identity.Id.Novelty, ", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = null,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n private string EconomicBasis => Identity.ValuationApproach == ValuationApproaches.VFA ? EconomicBases.C : EconomicBases.L;", - "\n private IEnumerable amortizationFactor => Identity.AocType == AocTypes.AM", - "\n ? GetScope(Identity, o => o.WithContext(EconomicBasis))", - "\n .RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", - "\n DataNode = x.Identity.DataNode,", - "\n AocType = x.Identity.AocType,", - "\n Novelty = x.Identity.Novelty,", - "\n EconomicBasis = x.EconomicBasis,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n })", - "\n : Enumerable.Empty();", - "\n IEnumerable Actual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", - "\n DataNode = x.Identity.Id.DataNode,", - "\n AocType = x.Identity.Id.AocType,", - "\n Novelty = x.Identity.Id.Novelty,", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = x.Identity.AmountType,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n IEnumerable AdvanceActual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", - "\n DataNode = x.Identity.Id.DataNode,", - "\n AocType = x.Identity.Id.AocType,", - "\n Novelty = x.Identity.Id.Novelty,", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = x.Identity.AmountType,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n IEnumerable OverdueActual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", - "\n DataNode = x.Identity.Id.DataNode,", - "\n AocType = x.Identity.Id.AocType,", - "\n Novelty = x.Identity.Id.Novelty,", - "\n AccidentYear = x.Identity.AccidentYear,", - "\n AmountType = x.Identity.AmountType,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n IEnumerable DeferrableActual => GetScope(Identity).RepeatOnce().Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", - "\n DataNode = x.Identity.DataNode,", - "\n AocType = x.Identity.AocType,", - "\n Novelty = x.Identity.Novelty,", - "\n AccidentYear = null,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n ", - "\n IEnumerable BeEAForPremium => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", - "\n || Identity.IsReinsurance", - "\n ? Enumerable.Empty()", - "\n : GetScope(Identity)", - "\n .ByAmountType", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(sc => new IfrsVariable{ EstimateType = GetScope(Identity).EstimateType, ", - "\n DataNode = sc.Identity.Id.DataNode, ", - "\n AocType = sc.Identity.Id.AocType, ", - "\n Novelty = sc.Identity.Id.Novelty, ", - "\n AccidentYear = sc.Identity.AccidentYear,", - "\n EconomicBasis = sc.EconomicBasis,", - "\n AmountType = sc.Identity.AmountType,", - "\n Value = sc.Value,", - "\n Partition = sc.GetStorage().TargetPartition });", - "\n ", - "\n IEnumerable ActEAForPremium => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", - "\n || Identity.IsReinsurance", - "\n ? Enumerable.Empty()", - "\n : GetScope(Identity)", - "\n .ByAmountTypeAndEstimateType", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(sc => new IfrsVariable{ EstimateType = GetStorage().ExperienceAdjustEstimateTypeMapping[sc.Identity.EstimateType], ", - "\n DataNode = sc.Identity.Id.DataNode, ", - "\n AocType = sc.Identity.Id.AocType, ", - "\n Novelty = sc.Identity.Id.Novelty, ", - "\n AccidentYear = sc.Identity.AccidentYear,", - "\n //EconomicBasis = scope.EconomicBasis,", - "\n AmountType = sc.Identity.AmountType,", - "\n Value = sc.Value,", - "\n Partition = GetStorage().TargetPartition });", - "\n ", - "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", - "\n ? Enumerable.Empty()", - "\n : GetScope(Identity).RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", - "\n DataNode = x.Identity.DataNode,", - "\n AocType = x.Identity.AocType,", - "\n Novelty = x.Identity.Novelty,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n", - "\n IEnumerable Loss => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", - "\n ? Enumerable.Empty()", - "\n : Identity.IsReinsurance ", - "\n ? GetScope(Identity).RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", - "\n DataNode = x.Identity.DataNode,", - "\n AocType = x.Identity.AocType,", - "\n Novelty = x.Identity.Novelty,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n })", - "\n : GetScope(Identity).RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", - "\n DataNode = x.Identity.DataNode,", - "\n AocType = x.Identity.AocType,", - "\n Novelty = x.Identity.Novelty,", - "\n Value = x.Value,", - "\n Partition = GetStorage().TargetPartition", - "\n });", - "\n", - "\n /*private double validateSingleEoP => Math.Abs(ValueCsm) > Precision && Math.Abs(ValueLc) > Precision ", - "\n ? (double)ApplicationMessage.Log(Error.MultipleEoP)", - "\n : default;", - "\n */", - "\n IEnumerable CalculatedIfrsVariables => GetStorage().ImportFormat switch {", - "\n ImportFormats.Actual => Actual.Concat(AdvanceActual).Concat(OverdueActual).Concat(ActEAForPremium)", - "\n .Concat(DeferrableActual).Concat(Csms).Concat(Loss),", - "\n ImportFormats.Cashflow => PvLocked.Concat(PvCurrent).Concat(RaCurrent).Concat(RaLocked)", - "\n .Concat(amortizationFactor).Concat(BeEAForPremium)", - "\n .Concat(DeferrableActual).Concat(Csms).Concat(Loss),", - "\n ImportFormats.Opening => AdvanceActual.Concat(OverdueActual).Concat(DeferrableActual)", - "\n .Concat(Csms).Concat(Loss),", - "\n };", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "I56SQek6SkukwZ49PojX-g", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Import Scopes (IFRS17 Methodology Business Logic)

", + "\n", + "\nThis notebook contains the logic used to perform calculations upon import of data (actuals and cashflows). This is also called 'Data Loading' and the concept of Scope is used here to define the logic and provide the means of executing the logic." + ] + }, + { + "cell_type": "markdown", + "source": [ + "# References", + "\nLibraries and other notebooks which are needed for this notebook are imported below." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Notebooks" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ImportStorage\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Scopes", + "\nScopes are used to define and perform data handling in a structured and easy-to-read-through fashion.", + "\n", + "\nThe IModel interface below will be used to execute calculations (i.e. evaluate the scopes) based on imported data." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IModel : IMutableScopeWithStorage{}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Getting Existing Identities", + "\n", + "\nAn [Identity](../DataModel/DataStructure#import-identity) is a set of identifiers for a certain set of data. In particular, an identity consists of a certain [AoC Type](../DataModel/DataStructure#aoc-type), [Novelty](../DataModel/DataStructure#novelty), [Data Node](../DataModel/DataStructure#data-node), Accident Year, and information on whether the data is for reinsurance or not. ", + "\n", + "\nGiven a certain Data Node and Accident Year, the interface GetIdentities returns all the existing identities (e.g. for Actuals and Cashflows) which have that Data Node and Accident Year." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface AllCfIdentities : IScope // string represents a DataNode", + "\n{", + "\n public IEnumerable ids => GetStorage().GetAllAocSteps(InputSource.Cashflow)", + "\n .Select(aocStep => new ImportIdentity {", + "\n AocType = aocStep.AocType,", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity", + "\n });", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface GetIdentities : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity))", + "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Actual)", + "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Cashflow)", + "\n .WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Opening)", + "\n );", + "\n ", + "\n private IEnumerable computedIdentities => new string[]{AocTypes.EA, AocTypes.AM, AocTypes.EOP}", + "\n .Select(aocType => new ImportIdentity {", + "\n AocType = aocType,", + "\n Novelty = Novelties.C,", + "\n DataNode = Identity", + "\n });", + "\n private IEnumerable allIdentities => ParsedIdentities.Concat(computedIdentities).Concat(SpecialIdentities).ToHashSet(); ", + "\n ", + "\n IEnumerable ParsedIdentities => Enumerable.Empty(); ", + "\n IEnumerable SpecialIdentities => Enumerable.Empty();", + "\n ", + "\n //Set DataNode properties and ProjectionPeriod", + "\n IEnumerable Identities => allIdentities.Select(id => id with { IsReinsurance = GetStorage().DataNodeDataBySystemName[id.DataNode].IsReinsurance,", + "\n ValuationApproach = GetStorage().DataNodeDataBySystemName[id.DataNode].ValuationApproach", + "\n });", + "\n /* .SelectMany(id => Enumerable.Range(0,GetStorage().GetProjectionCount() + 1)", + "\n .Select(pp => id with {ProjectionPeriod = pp })", + "\n );*/", + "\n}", + "\n", + "\npublic interface AllCashflowIdentities : GetIdentities", + "\n{", + "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids;", + "\n}", + "\n", + "\n", + "\npublic interface GetActualIdentities : GetIdentities", + "\n{", + "\n private IEnumerable actualEstimateTypes => GetStorage().EstimateTypesByImportFormat[ImportFormats.Actual];", + "\n ", + "\n IEnumerable GetIdentities.ParsedIdentities => GetStorage().GetIfrsVariables(Identity).Where(iv => actualEstimateTypes.Contains(iv.EstimateType)).Select(v => new ImportIdentity(v));", + "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids", + "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Opening)", + "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity", + "\n }));", + "\n}", + "\n", + "\npublic interface GetCashflowIdentities : GetIdentities", + "\n{", + "\n private bool isReinsurance => GetStorage().DataNodeDataBySystemName[Identity].IsReinsurance; //clean up in the next PR", + "\n ", + "\n IEnumerable GetIdentities.ParsedIdentities => GetStorage().GetRawVariables(Identity).Select(v => new ImportIdentity(v));", + "\n ", + "\n IEnumerable GetIdentities.SpecialIdentities => ParsedIdentities.Where(id => id.Novelty != Novelties.C)", + "\n .Select(id => id.Novelty).ToHashSet()", + "\n .SelectMany(n => (n == Novelties.N ", + "\n ? new string[]{AocTypes.IA, AocTypes.CF} //Add IA, CF, for New Business", + "\n : isReinsurance ", + "\n ? new string[]{AocTypes.IA, AocTypes.CF, AocTypes.YCU, AocTypes.CRU, AocTypes.RCU} //Add IA, CF, YCU, CRU, RCU for in force", + "\n : new string[]{AocTypes.IA, AocTypes.CF, AocTypes.YCU}) //Add IA, CF, YCU,", + "\n .Select(aocType => new ImportIdentity {", + "\n AocType = aocType,", + "\n Novelty = n,", + "\n DataNode = Identity }))", + "\n .Concat(new ImportIdentity {", + "\n AocType = AocTypes.CF, //Add CF for Deferral", + "\n Novelty = Novelties.C,", + "\n DataNode = Identity", + "\n }.RepeatOnce()) ", + "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Opening)", + "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity", + "\n })); ", + "\n}", + "\n", + "\npublic interface GetAllIdentities : GetIdentities", + "\n{", + "\n IEnumerable GetIdentities.SpecialIdentities => GetScope(Identity).ids", + "\n .Concat(GetStorage().GetAllAocSteps(InputSource.Actual)", + "\n .Select(aocStep => new ImportIdentity {AocType = aocStep.AocType, ", + "\n Novelty = aocStep.Novelty,", + "\n DataNode = Identity,", + "\n }));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Getting Amount Types", + "\n", + "\nSimilarly, given a certain Data Node and Accident Year, the interface ValidAmountType returns all the amount types which are used in imported data with that Data Node and Accident Year." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ValidAmountType : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow ||", + "\n x.GetStorage().IsSecondaryScope(x.Identity)));", + "\n ", + "\n IEnumerable BeAmountTypes => GetStorage().GetRawVariables(Identity)", + "\n .Where(rv => rv.AmountType != null)", + "\n .Select(x => x.AmountType)", + "\n .Concat(GetStorage().DataNodeDataBySystemName[Identity].IsReinsurance ? (AmountTypes.CDR).RepeatOnce() : Enumerable.Empty())", + "\n .ToHashSet();", + "\n ", + "\n ", + "\n IEnumerable ActualAmountTypes => GetStorage().GetIfrsVariables(Identity)", + "\n .Where(iv => GetStorage().EstimateTypesByImportFormat[ImportFormats.Actual].Contains(iv.EstimateType))", + "\n .Select(x => x.AmountType)", + "\n .ToHashSet();", + "\n}", + "\npublic interface BeAmountTypesFromIfrsVariables : ValidAmountType", + "\n{", + "\n IEnumerable ValidAmountType.BeAmountTypes => GetStorage().GetIfrsVariables(Identity)", + "\n .Where(iv => GetStorage().EstimateTypesByImportFormat[ImportFormats.Cashflow].Contains(iv.EstimateType) && iv.AmountType != null)", + "\n .Select(x => x.AmountType)", + "\n .ToHashSet();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## AoC Step Structure", + "\n", + "\nThe Aoc step structure is constructed from the data which is delivered as input. It is assumed that it depends only on the Group of Contrat (i.e. it is invariant across Amount types or Accident Year). " + ] + }, + { + "cell_type": "markdown", + "source": [ + "### ParentAocStep ", + "\nThe **ParentAocStep** scope computes and provides an important piece of information for each [Identity](../DataModel/DataStructure#import-identity), i.e. for a certain [AocType](../DataModel/DataStructure#aoc-type) and [Novelty](../DataModel/DataStructure#novelty).", + "\n", + "\nIt provides the list of the adjacent AocSteps prior to Identity one. It can be more than one only for the step **CL** where a parent for each novelty is considered.", + "\nParentAocStep is critical when computing the *telescoping* differences. ", + "\n", + "\nThey are defined as follows:", + "\n", + "\n$$", + "\n\\text{ParentAocStep}(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{AoC step with AoC Type YCU and Novelty I} & \\text{if AocType CRU} \\\\", + "\n\\text{The last AoC step with Data Type != Calculated and same Novelty as the AocStep} & \\text{if AocType YCU} \\\\", + "\n\\text{The AoC step which comes before in terms of order (as defined by AocType)} & \\text{otherwise} \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ParentAocStep : IScope<(ImportIdentity Id, string AmountType), ImportStorage>", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType != AmountTypes.CDR));", + "\n ", + "\n private HashSet ParsedAocSteps => GetScope(Identity.Id.DataNode).ParsedIdentities.Select(id => new AocStep(id.AocType, id.Novelty)).ToHashSet();", + "\n private IEnumerable OrderedParsedAocSteps => ParsedAocSteps.Concat(CalculatedTelescopicAocStep).OrderBy(x => GetStorage().AocConfigurationByAocStep[x].Order);", + "\n ", + "\n private Dictionary> ParentParsedIdentities => GetPreviousIdentities(OrderedParsedAocSteps);", + "\n private AocStep identityAocStep => new AocStep(Identity.Id.AocType, Identity.Id.Novelty);", + "\n ", + "\n IEnumerable CalculatedTelescopicAocStep => GetStorage().GetCalculatedTelescopicAocSteps();", + "\n ", + "\n IEnumerable Values => ", + "\n Identity.Id.AocType switch {", + "\n AocTypes.CRU => new AocStep(AocTypes.YCU, Novelties.I).RepeatOnce(),", + "\n AocTypes.YCU => OrderedParsedAocSteps.GetReferenceAocStepForCalculated(GetStorage().AocConfigurationByAocStep, identityAocStep).RepeatOnce(),", + "\n _ => ParentParsedIdentities.TryGetValue(identityAocStep, out var parents) ? parents : Enumerable.Empty(),", + "\n };", + "\n}", + "\n", + "\npublic interface ParentAocStepForCreditRisk : ParentAocStep", + "\n{", + "\n IEnumerable ParentAocStep.CalculatedTelescopicAocStep => ", + "\n GetStorage().GetCalculatedTelescopicAocSteps().Where(aoc => aoc.AocType != AocTypes.CRU);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### ReferenceAocStep", + "\n", + "\nThe **ReferenceAocStep** scope provides the AocStep from which to retrieve the data in order to compute its value (e.g. AoC step EA retrieves Present Values, while AoC step YCU retrieves Nominal).", + "\n", + "\nThey are defined as follows:", + "\n", + "\n$$", + "\n\\text{ReferenceAocStep}(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{self} & \\text{if AocStep InputSource is not Calculated} \\\\", + "\n\\text{The last AoC step with Data Type != Calculated and same Novelty as the input AocStep} ~, & \\text{if AocType } \\in \\text{\\{RCU, CF, IA, YCU, CRU\\}} \\\\", + "\n\\text{AoC step with AoC Type CF and Novelty as the AocStep} & \\text{if AocType EA} \\\\", + "\n\\text{AoC step with AoC Type CL and Novelty C} & \\text{if AocType $\\in$ \\{AM, EOP\\}} \\\\", + "\n\\text{empty} & \\text{if AocType is BOP} \\\\", + "\n\\text{log NotSupportedAocStepReference error} & \\text{otherwise} \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the last AocStep is obtained by ordering the AocSteps according to their order (as defined by its AocType) and taking the last one." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ReferenceAocStep : IScope ", + "\n{", + "\n private IEnumerable OrderedParsedAocSteps => GetScope(Identity.DataNode).ParsedIdentities", + "\n .Select(id => new AocStep(id.AocType, id.Novelty))", + "\n .Distinct()", + "\n .OrderBy(aocStep => GetStorage().AocConfigurationByAocStep[aocStep].Order);", + "\n private AocStep identityAocStep => new AocStep(Identity.AocType, Identity.Novelty);", + "\n private AocStep GetReferenceAocStep(string aocType) {", + "\n return aocType switch {", + "\n AocTypes.RCU or AocTypes.CF or AocTypes.IA or AocTypes.YCU or AocTypes.CRU => OrderedParsedAocSteps.GetReferenceAocStepForCalculated(GetStorage().AocConfigurationByAocStep, identityAocStep),", + "\n AocTypes.EA => new AocStep(AocTypes.CF, Identity.Novelty),", + "\n AocTypes.AM or AocTypes.EOP => new AocStep(AocTypes.CL, Novelties.C),", + "\n AocTypes.BOP => new AocStep(default, default), //BOP, C has DataType == Calculated. See ReferenceAocStep condition.", + "\n _ => (AocStep)ApplicationMessage.Log(Error.NotSupportedAocStepReference, Identity.AocType),", + "\n };", + "\n }", + "\n", + "\n // The Reference AocStep from which get data (Nominal or PV) to compute", + "\n AocStep Value => GetStorage().AocConfigurationByAocStep[identityAocStep].DataType == DataType.Calculated ", + "\n || GetStorage().AocConfigurationByAocStep[identityAocStep].DataType == DataType.CalculatedTelescopic ", + "\n ? GetReferenceAocStep(Identity.AocType)", + "\n : identityAocStep;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### PreviousAocSteps", + "\nThe **PreviousAocSteps** scope computes and provides an other important piece of information for each [Identity](../DataModel/DataStructure#import-identity), i.e. for a certain [AocType](../DataModel/DataStructure#aoc-type) and [Novelty](../DataModel/DataStructure#novelty).", + "\n", + "\nIt provides the list of all previous AocSteps up to the **BOP** step, whereby a Combined novelty will branch into the InForce and New Business AocTypes.", + "\n", + "\nPreviousAocSteps is critical when computing aggregated values along the various dimensions (such as for example Line of Business) and ", + "\nis formed by the ParentAocStep and its parent and so on until there is no parent.", + "\n", + "\n$$", + "\n\\text{PreviousAocSteps}(\\rm{AocStep}) = \\{PAS_1, PAS_2, \\ldots\\}", + "\n$$", + "\nwhere", + "\n$$", + "\n\\rm{PAS}_1 = \\rm{ParentAocStep}(\\rm{AocStep})", + "\n$$", + "\n$$", + "\n\\rm{PAS}_2 = \\rm{ParentAocStep}(\\rm{PAS}_1).", + "\n$$", + "\n", + "\nThis scope depends on the InputSource (Actual or Cashflow) for which the PreviousSteps are requested due to the AocChain differences between Actual reports and the rest." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface PreviousAocSteps : IScope<(ImportIdentity Id, InputSource ScopeInputSource), ImportStorage> ", + "\n{ ", + "\n private AocStep identityAocStep => new AocStep(Identity.Id.AocType, Identity.Id.Novelty);", + "\n private int aocStepOrder => GetStorage().AocConfigurationByAocStep[identityAocStep].Order;", + "\n private HashSet allAocSteps => GetStorage().GetAllAocSteps(Identity.ScopeInputSource).ToHashSet();", + "\n IEnumerable Values => allAocSteps.Contains(identityAocStep)", + "\n ? GetScope(Identity.Id.DataNode).Identities", + "\n .Select(id => new AocStep(id.AocType, id.Novelty))", + "\n .Distinct()", + "\n .Where(aoc => allAocSteps.Contains(aoc) && ", + "\n GetStorage().AocConfigurationByAocStep[aoc].Order < aocStepOrder && ", + "\n (Identity.Id.Novelty != Novelties.C ? aoc.Novelty == Identity.Id.Novelty : true) )", + "\n .OrderBy(aoc => GetStorage().AocConfigurationByAocStep[aoc].Order)", + "\n : Enumerable.Empty();", + "\n} " + ] + }, + { + "cell_type": "markdown", + "source": [ + "The exact structure being return depends on the **order** of the AoC Steps (which is set by the [AoC Type](../DataModel/DataStructure#aoc-type)), and on which AoC steps exist.", + "\n", + "\nFor an example of the usage of the AocStep scope see [here](../Test/AocStructureTest)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Discounting", + "\n", + "\nThe calculation of IFRS17 figures is based on cumulated discounted cashflows." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Yield Curves", + "\n", + "\nThe Yield Curves used for the discounting calculations are functions of the [Currency](../DataModel/DataStructure#currency), the [Data Node](../DataModel/DataStructure#data-node) and the [Economic Basis](../DataModel/DataStructure#economic-basis).", + "\n", + "\nIn particular:", + "\n- For the **Locked-in** economic basis, the yield curve used is the latest available as per end of the DataNode's inception year;", + "\n- Whereas for the **Current** economic base, the yield curve used is the latest available as per the current period.", + "\n", + "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/UtilityMethods#yield-curve)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Interest and Discount Rates and Factors", + "\n", + "\nThe factors used for discounting have the same granularity as the cashflow, i.e. monthly. The yield curves have yearly granularity, so the annual Interest factor is 1 + interest rate. The monthly Interest Interest and Discount factors are obtained from the annual factors such that the product of 12 months results in the annual factors, as follows:", + "\n", + "\n$$", + "\n\\text{Discount}_i = ( 1 + \\text{YC}_i ) ^{-\\frac{1}{12}} ~,", + "\n$$", + "\nand ", + "\n$$", + "\n\\text{Interest}_i = ( 1 + \\text{YC}_i) ^{\\frac{1}{12}} ~,", + "\n$$", + "\n", + "\nwhere the index $i$ denotes years." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface MonthlyRate : IScope", + "\n{", + "\n private string EconomicBasis => GetContext();", + "\n ", + "\n private double[] YearlyYieldCurve => GetStorage().GetYearlyYieldCurve(Identity, EconomicBasis);", + "\n ", + "\n private double Perturbation => 0; //GetStorage().GetYieldCurvePerturbation(); => switch Args.Scenario { 10ptsU => 0.1, 10ptsD => -0.1, _ => default)", + "\n ", + "\n double[] Interest => YearlyYieldCurve.Select(rate => Math.Pow(1d + rate, 1d / 12d) + Perturbation).ToArray(); ", + "\n ", + "\n double[] Discount => Interest^(-1);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For an example of these calculations see [here](../Test/SpecificationsImportCashflows#interest-and-discount-rates)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Nominal Values", + "\n", + "\nThe nominal cashflow values correspond to the cashflows provided in the Cashflow input file. ", + "\n
These values are stored in the database as [RawVariable](../DataModel/DataStructure#raw-variables).", + "\n
Refer to the ReferenceAocStep of the AocStructure calculation to identify the correct AocType and Novelty to retrieve.", + "\n
Due to the Credit Default Risk of a reinsurance partner, the logic to compute the Nominal Cashflows for this Amount Type must be defined separately. " + ] + }, + { + "cell_type": "code", + "source": [ + "public interface NominalCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR));", + "\n", + "\n AocStep referenceAocStep => GetScope(Identity.Id).Value;", + "\n double[] Values => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.AccidentYear);", + "\n}", + "\n", + "\npublic interface CreditDefaultRiskNominalCashflow : NominalCashflow", + "\n{", + "\n private double[] NominalClaimsCashflow => GetStorage().GetClaims()", + "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", + "\n .Aggregate();", + "\n ", + "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", + "\n ", + "\n private double[] PvCdrDecumulated { get {", + "\n var ret = new double[NominalClaimsCashflow.Length];", + "\n for (var i = NominalClaimsCashflow.Length - 1; i >= 0; i--)", + "\n ret[i] = Math.Exp(-nonPerformanceRiskRate) * ret.ElementAtOrDefault(i + 1) + NominalClaimsCashflow[i] - NominalClaimsCashflow.ElementAtOrDefault(i + 1);", + "\n return ret; } } ", + "\n ", + "\n double[] NominalCashflow.Values => PvCdrDecumulated - NominalClaimsCashflow;", + "\n}", + "\n", + "\npublic interface AllClaimsCashflow : NominalCashflow", + "\n{", + "\n double[] NominalCashflow.Values => GetStorage().GetClaims()", + "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", + "\n .Aggregate();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For a given month $i$ they are denoted as $\\rm{Nominal}_i$." + ] + }, + { + "cell_type": "markdown", + "source": [ + "For an example of nominal cashflow values see [here](../Test/SpecificationsImportCashflows#nominal-cashflow)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Present Values", + "\n", + "\nPresent Values are calculated during the import of the cashflows and stored on the database. They are computed for the relevant Economic Basis, depending on the Valuation Basis.", + "\n", + "\nTheir calculation is described in the following sections and is summarized in the $\\rm{PV}$ formula [below](#present-value)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Cumulated Discounted Cashflows", + "\n", + "\nCumulated and Discounted cashflows $\\rm{CDC}$ are computed using the monthly discount rates and in a recursive manner, as follows:", + "\n", + "\n$$", + "\n\\text{CDC}_i(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{Nominal}_i + \\text{CDC}_{i+1} \\cdot {\\text{Valid Discount}_{\\frac{i}{12}}} ~, & \\text{if Aoc Type's Period Type is Beginning Of Period} \\\\", + "\n\\big( \\text{Nominal}_i + \\text{CDC}_{i+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{i}{12}}} ~, & \\text{if Aoc Type's Period Type is End Of Period}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere Transaction Period depends on which Best Estimate value is being computed, in particular on what its [Amount Type](../DataModel/DataStructure#amount-type) is (each Amount Type has its own [Period Type](../Constants/Enums)); and $\\text{Valid Discount}$ stands for the fact that in case the Discount Curves are shorter than the required index, then their last element is returned.", + "\n", + "\n
Also here, the Credit Default Risk contribution is calculated separately. Since it is based on Claims, the Period Type is implicitly defined." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface DiscountedCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", + "\n{", + "\n private PeriodType periodType => GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType); ", + "\n ", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR));", + "\n", + "\n [NotVisible]", + "\n string EconomicBasis => GetContext();", + "\n", + "\n [NotVisible]", + "\n double[] MonthlyDiscounting => GetScope(Identity.Id).Discount;", + "\n ", + "\n [NotVisible]", + "\n double[] NominalValues => GetScope(Identity).Values;", + "\n", + "\n double[] Values => NominalValues.ComputeDiscountAndCumulate(MonthlyDiscounting, periodType);", + "\n}", + "\n", + "\npublic interface DiscountedCreditRiskCashflow : DiscountedCashflow", + "\n{ ", + "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", + "\n ", + "\n double[] DiscountedCashflow.Values => NominalValues.ComputeDiscountAndCumulateWithCreditDefaultRisk(MonthlyDiscounting, nonPerformanceRiskRate);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For example calculations for Cumulated Discounted Cashflows see [here](../Test/SpecificationsImportCashflows#cumulated-discounted-cashflow)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Telescoping Difference", + "\n", + "\n", + "\nPresent Value figures for a specific period are typically reported through an analysis of change, where for each [AocStep](#aoc-steps-structure) the variation with respect to the preceding AocStep is shown.", + "\n", + "\nThe Telescoping Difference is basically the delta between two adjacent AoC steps, whereby the [ParentAocStep](#aoc-steps-structure) is used to determine the AoC step. ", + "\n", + "\nIt is defined as follows:", + "\n", + "\n$$", + "\n\\text{TelescopingDifference}_i = ", + "\n\\text{CDC}_{i}\\big(\\text{current AoC step}\\big) - \\text{CDC}_{i}\\big(\\text{parent AoC step}\\big)", + "\n$$", + "\n", + "\nwhere AocType is the AoC Type of the AoC Step for which the calculations are being performed." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface TelescopicDifference : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", + "\n{", + "\n [NotVisible]", + "\n string EconomicBasis => GetContext();", + "\n private double[] CurrentValues => GetScope(Identity).Values;", + "\n ", + "\n private double[] PreviousValues => (GetScope((Identity.Id, Identity.AmountType)))", + "\n .Values", + "\n .Select(aoc => GetScope((Identity.Id with {AocType = aoc.AocType, Novelty = aoc.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.Accidentyear)).Values)", + "\n .Where(cf => cf.Count() > 0)", + "\n .Aggregate();", + "\n ", + "\n double[] Values => CurrentValues - PreviousValues;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Examples of Telescoping Difference calculations for different AoC steps start [here](../Test/SpecificationsImportCashflows#modelcorrections)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Present Value", + "\n", + "\nThe present value ($\\rm{PV}$) can be determined by taking the appropriate elements of the cumulated discounted cashflows. This is done as function of the two [projection parameters](../DataModel/DataStructure#projection-configuration) $\\rm{Shift}$ ($S$) and $\\rm{TimeStep}$ ($TS$):", + "\n", + "\n$$", + "\n\\text{PV}(S, TS) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{PV Base}_{S} ~, & \\text{if Valuation Period is Beginning of Period} \\\\", + "\n\\text{PV Base}_{S+TS/2 -1} ~, & \\text{if Valuation Period is Mid of Period} \\\\", + "\n\\sum_{i=S}^{S + TS - 1}\\text{PV Base}_{i} ~, & \\text{if Valuation Period is Delta} \\\\", + "\n\\text{PV Base}_{S + TS} ~, & \\text{if Valuation Period is End of Period} \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere [PV Base](#present-value-base) is defined below, and the term $TS/2$ uses MidpointRounding.AwayFromZero (as defined by *https:[]()//docs.microsoft.com/en-us/dotnet/api/system.midpointrounding?view=net-6.0)*: rounding to the nearest number, away from zero in the exact halfway case. Furthermore, if the array is smaller than the index, then the last element is returned.", + "\n", + "\nFor instance, for the current year and year-to-date view we have $S=0$ and $TS=3$ for the first quarter, $TS=6$ for the 2nd quarter and so on.", + "\nFor the projection values of next year first quarter we would have $S=12$ and $TS=3$, etc." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IWithGetValueFromValues : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", + "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", + "\n ", + "\n public double GetValueFromValues(double[] Values)", + "\n {", + "\n return GetStorage().GetValuationPeriod(Identity.Id) switch {", + "\n ValuationPeriod.BeginningOfPeriod => Values.ElementAtOrDefault(shift),", + "\n ValuationPeriod.MidOfPeriod => Values.ElementAtOrDefault(shift + Convert.ToInt32(Math.Round(timeStep / 2d, MidpointRounding.AwayFromZero)) - 1),", + "\n ValuationPeriod.Delta => Values.Skip(shift).Take(timeStep).Sum(),", + "\n ValuationPeriod.EndOfPeriod => Values.ElementAtOrDefault(shift + timeStep),", + "\n ValuationPeriod.NotApplicable => default", + "\n };", + "\n }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An example of Projected Present Value calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Interest Accretion", + "\n", + "\nSince the Interest Accretion cashflows are typically not provided as input (as they can be computed from its parent AocStep), its present values can be computed as follows:", + "\n", + "\n$$", + "\n\\text{InterestAccretion}_i(\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\big(\\text{CDC}_i(\\text{Parent AoC step}) - \\text{Nominal}_i(\\text{parent AoC step}) \\big) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, & \\text{if Amount Type's Transaction Period is Beginning of Period} \\\\", + "\n\\text{CDC}_i(\\text{parent AoC step}) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\n
Due to the Credit Default Risk of a reinsurance partner, the logic to compute the Interest Accretion for this Amount Type must be defined separately. Since it is based on Claims, the Period Type is implicitly defined." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IWithInterestAccretion : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n private double[] parentDiscountedValues => GetScope(Identity).Values; ", + "\n private double[] parentNominalValues => GetScope(Identity).Values;", + "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", + "\n ", + "\n double[] GetInterestAccretion() ", + "\n {", + "\n var periodType = GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType);", + "\n var ret = new double[parentDiscountedValues.Length];", + "\n ", + "\n switch (periodType) {", + "\n case PeriodType.BeginningOfPeriod :", + "\n for (var i = 0; i < parentDiscountedValues.Length; i++)", + "\n ret[i] = (parentDiscountedValues[i] - parentNominalValues[i]) * (GetElementOrDefault(monthlyInterestFactor, i/12) - 1d );", + "\n break;", + "\n default :", + "\n for (var i = 0; i < parentDiscountedValues.Length; i++)", + "\n ret[i] = parentDiscountedValues[i] * (GetElementOrDefault(monthlyInterestFactor, i/12) - 1d );", + "\n break;", + "\n }", + "\n ", + "\n return ret;", + "\n }", + "\n}", + "\n", + "\npublic interface IWithInterestAccretionForCreditRisk : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\n{", + "\n private double[] nominalClaimsCashflow => GetScope(Identity).Values;", + "\n private double[] nominalValuesCreditRisk => -1 * GetScope(Identity with {Id = Identity.Id with {AocType = AocTypes.CF}}).Values;", + "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", + "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", + "\n ", + "\n double[] GetInterestAccretion() ", + "\n {", + "\n var interestOnClaimsCashflow = new double[nominalClaimsCashflow.Length];", + "\n var interestOnClaimsCashflowCreditRisk = new double[nominalClaimsCashflow.Length];", + "\n var effectCreditRisk = new double[nominalClaimsCashflow.Length];", + "\n for (var i = nominalClaimsCashflow.Length - 1; i >= 0; i--) {", + "\n interestOnClaimsCashflow[i] = 1 / GetElementOrDefault(monthlyInterestFactor, i/12) * (interestOnClaimsCashflow.ElementAtOrDefault(i + 1) + nominalClaimsCashflow[i] - nominalClaimsCashflow.ElementAtOrDefault(i + 1));", + "\n interestOnClaimsCashflowCreditRisk[i] = 1 / GetElementOrDefault(monthlyInterestFactor, i/12) * (Math.Exp(-nonPerformanceRiskRate) * interestOnClaimsCashflowCreditRisk.ElementAtOrDefault(i + 1) + nominalClaimsCashflow[i] - nominalClaimsCashflow.ElementAtOrDefault(i + 1));", + "\n effectCreditRisk[i] = interestOnClaimsCashflow[i] - interestOnClaimsCashflowCreditRisk[i];", + "\n }", + "\n ", + "\n return effectCreditRisk - nominalValuesCreditRisk;", + "\n }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An example of the Interest Accretion calculations can be found [here](../Test/SpecificationsImportCashflows#interest-accretion)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Present Value Base", + "\n", + "\nThe PV Base values are valid for all choices of the [Economic Basis](../DataModel/DataStructure#economic-basis):", + "\n", + "\n$$", + "\n\\text{PV Base}_i (\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n\\text{CDC}_i ~, & \\text{if AoCType = BOP} \\\\", + "\n-\\text{Nominal}_i(\\text{Parent AoC step}) ~, & \\text{if AoCType = CF } \\\\", + "\n\\text{InterestAccretion}_i ~, & \\text{if AoCType = IA } \\\\", + "\n0 ~, & \\text{if AoCType = AM } \\\\\\", + "\n\\text{CDC}_i(\\text{Parent AoC step}) ~, & \\text{if AoCType = EOP } \\\\", + "\n\\text{TelescopingDifference}_i ~, & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere $i$ denotes the months, and the [$\\rm{TelescopingDifference}_i$](#telescopic-difference) and the [$\\rm{InterestAccretion}_i$](#interest-accretion) quantities are defined above." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface PresentValue : IWithGetValueFromValues", + "\n{ ", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", + "\n || x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode))", + "\n .WithApplicability(x => (x.Identity.Id.AocType == AocTypes.BOP && x.Identity.Id.Novelty != Novelties.C) || x.Identity.Id.AocType == AocTypes.EOP)", + "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.IA)", + "\n .WithApplicability(x => x.Identity.Id.AocType == AocTypes.IA)", + "\n .WithApplicability(x => new string[]{AocTypes.BOP, AocTypes.EA, AocTypes.AM, AocTypes.RCU}.Contains(x.Identity.Id.AocType) ) //add here combination CRU for At !CDR?", + "\n );", + "\n ", + "\n [NotVisible][IdentityProperty][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => GetContext();", + "\n ", + "\n [NotVisible]", + "\n double[] Values => GetScope(Identity).Values;", + "\n ", + "\n public double Value => GetValueFromValues(Values);", + "\n}", + "\n", + "\npublic interface ComputePresentValueWithIfrsVariable : PresentValue", + "\n{", + "\n double PresentValue.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.CalculationType, EconomicBasis, Identity.AccidentYear); //unify CalculationType and EstimateTypeGet", + "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", + "\n}", + "\n", + "\npublic interface PresentValueFromDiscountedCashflow : PresentValue", + "\n{", + "\n [NotVisible]", + "\n double[] PresentValue.Values => GetScope(Identity).Values;", + "\n}", + "\n", + "\npublic interface CashflowAocStep : PresentValue", + "\n{", + "\n [NotVisible]", + "\n double[] PresentValue.Values => -1d * GetScope(Identity).Values;", + "\n}", + "\n", + "\npublic interface PresentValueWithInterestAccretion : PresentValue, IWithInterestAccretion", + "\n{", + "\n [NotVisible]", + "\n double[] PresentValue.Values => GetInterestAccretion();", + "\n}", + "\n", + "\npublic interface PresentValueWithInterestAccretionForCreditRisk : PresentValue, IWithInterestAccretionForCreditRisk", + "\n{", + "\n [NotVisible]", + "\n double[] PresentValue.Values => GetInterestAccretion();", + "\n}", + "\n", + "\npublic interface EmptyValuesAocStep : PresentValue", + "\n{", + "\n [NotVisible]", + "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An example of the Present Value Base calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Current and Locked", + "\n", + "\nPV Current and PV Locked below basically hold the Present Values [PV](#present-value) computed using the **Current** yield curves and the **Locked** yield curves, respectively.", + "\n", + "\nValues are available for each AmountType (by calling PvLocked.ByAmountType):", + "\n", + "\n$$", + "\n\\text{PV Locked}(\\text{AoC step}, \\text{Amount Type}) = \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = L}}", + "\n$$", + "\n", + "\n$$", + "\n\\text{PV Current}(\\text{AoC step}, \\text{Amount Type}) = \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = C}}", + "\n$$", + "\n", + "\n", + "\nAnd aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type) (by calling PvLocked.Value):", + "\n", + "\n$$", + "\n\\text{PV Locked}(\\text{AoC step}) = \\sum_{\\text{Amount Types}} \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = L}}", + "\n$$", + "\n", + "\n$$", + "\n\\text{PV Current}(\\text{AoC step}) = \\sum_{\\text{Amount Types}} \\text{PV}(\\text{AoC step}, \\text{Amount Type})|_{\\text{Economic Base = C}}", + "\n$$", + "\n", + "\nThese are used in the BBA methodology, whereby in the CSM calculations only PV Locked is used, and both of them are stored in the database under the [IfrsVariable](../DataModel/DataStructure#ifrs-variable) data structure." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface PvLocked : IScope", + "\n{ ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.L;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.BE;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", + "\n ", + "\n [NotVisible]", + "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .ToArray();", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}", + "\n", + "\npublic interface PvCurrent : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.C;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.BE;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .ToArray();", + "\n ", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Risk Adjustment", + "\n", + "\nRisk Adjustment values ($\\rm{RA}$) are accessible from the [PV Base](#present-value-base) data and have [Calculation Type](../DataModel/DataStructure#calculation-type) $RA$. In particular, the Locked-In and Current values are given by:", + "\n", + "\n$$", + "\n\\text{RA Locked}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = L}}", + "\n$$", + "\n", + "\n$$", + "\n\\text{RA Current}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = C}}", + "\n$$", + "\n", + "\nwhere PV is defined [above](#present-value) and uses the input cashflows with Calculation Type = RA." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface RaLocked : IScope", + "\n{ ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.L;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.RA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", + "\n ", + "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray();", + "\n ", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}", + "\npublic interface RaCurrent : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", + "\n string EconomicBasis => EconomicBases.C;", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.RA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", + "\n ", + "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n ", + "\n double Value => PresentValues.Aggregate().Value;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Amortization", + "\n", + "\nFor the Amortization AoC Step (AoC Type **AM**), the amortization factors to be used are defined below." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Coverage Units", + "\n", + "\nThe coverage unit (CU) of a GIC is introduced in the standard as the quantity of the service provided in that GIC. The service is", + "\nmeasured by considering the quantity of benefits provided as well as the expected coverage period of the GIC.", + "\n", + "\nThe cashflows of coverage units are retrieved from the discounted cashflows with [Calculation Type](../DataModel/DataStructure#calculation-type) CU." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface CoverageUnitCashflow : IScope", + "\n{ ", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", + "\n string CalculationType => CalculationTypes.CU;", + "\n ", + "\n double[] Values => GetScope((Identity, (string)null, CalculationType, (int?)null)).Values;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Amortization Factor" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For a certain GIC, the monthly Amortization Factors $\\text{Monthly }AF_i$ are computed from the cashflows of the underlying coverage unit for that GIC:", + "\n", + "\n$$", + "\n\\text{Monthly }AF_i = 1 - \\frac{ \\text{Nominal}_i(CL)} {\\text{CDC}_i(CL) } ~.", + "\n$$", + "\n", + "\nwhere:", + "\n- $i$ denotes a monthly period;", + "\n- the nominal cash flows $\\text{Nominal}_i(CL)$ are the nominal cashflows of the coverage unit for the AoC Step **Combined Liability** (CL) (input data);", + "\n- and the corresponding cumulated discounted cashflows $\\text{CDC}_i$ are defined [above](#cumulated-discounted-cashflows)." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface MonthlyAmortizationFactorCashflow : IScope", + "\n{", + "\n private double[] NominalCuCashflow => GetScope((Identity with {AocType = AocTypes.CL}, (string)null, CalculationTypes.CU, (int?)null)).Values;", + "\n private double[] DiscountedCuCashflow => GetScope(Identity with {AocType = AocTypes.CL}, o => o.WithContext(EconomicBasis)).Values;", + "\n ", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n double[] MonthlyAmortizationFactors => Identity.AocType switch {", + "\n AocTypes.AM => NominalCuCashflow.Zip(DiscountedCuCashflow, //Extract to an other scope with month in the identity to avoid Zip?", + "\n (nominal, discountedCumulated) => discountedCumulated >= Precision ", + "\n ? 1 - nominal / discountedCumulated ", + "\n : 0).ToArray(),", + "\n _ => Enumerable.Empty().ToArray(),", + "\n };", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For a certain projection period - defined by the Shift, $S$, and the Time-Step, $TS$, parameters - the Amortization Factor is then given by the product of the corresponding monthly amortization factors:", + "\n", + "\n$$", + "\nAF = \\prod _{i = S}^{TS} \\text{Monthly }AF_i ~.", + "\n$$", + "\n", + "\nEach GIC will have his own AF." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface CurrentPeriodAmortizationFactor : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => ", + "\n s.WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow", + "\n || x.GetStorage().IsSecondaryScope(x.Identity.DataNode)));", + "\n ", + "\n private int shift => GetStorage().GetShift(0);//Identity.ProjectionPeriod", + "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.ProjectionPeriod", + "\n ", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n string EstimateType => EstimateTypes.F;", + "\n double Value => GetScope(Identity)", + "\n .MonthlyAmortizationFactors", + "\n .Skip(shift)", + "\n .Take(timeStep)", + "\n .Aggregate(1d, (x, y) => x * y);", + "\n}", + "\n", + "\npublic interface AmfFromIfrsVariable : CurrentPeriodAmortizationFactor", + "\n{", + "\n double CurrentPeriodAmortizationFactor.Value => GetStorage().GetValue(Identity, (string)null, EstimateType, EconomicBasis, (int?)null); //unify CalculationType and EstimateTypeGet", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Actual Values", + "\n", + "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", + "\n- Actuals (A)", + "\n- Advance Actuals (AA)", + "\n- Overdue Actuals (OA)", + "\n- Deferrable Actuals (DA)", + "\n", + "\nwith the Estimate Type's system name shown between parenthesis above.", + "\n", + "\nThe following simplified AoC Chain applies for Advance and Overdue Actuals:", + "\n
 BOP", + "\n
 Release", + "\n
 Write-off", + "\n
 EOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Actual Base", + "\n", + "\nThe Actual Base sets values for actual, advance, and overdue as follows:", + "\n", + "\n$$", + "\n\\text{Actual Base} (\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n0 ~, & \\text{if AoC Step's AoC Type = AM} \\\\", + "\n\\text{Actual Base}(\\rm{BOP}) + \\text{Actual Base}(\\rm{CF}) + \\text{Actual Base}(\\rm{WO}) ~, & \\text{if AoC Step's AoC Type = EOP and EstimateType is not A} \\\\", + "\n\\text{Imported Actual} ~, & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the value is also function of the [Estimate Type](../DataModel/DataStructure#EstimateType) and [Amount Type](../DataModel/DataStructure#AmountType), and the $\\text{Imported Actual}$ value is described [here]()." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ActualBase : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().ImportFormat == ImportFormats.Actual ", + "\n && !x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode)", + "\n && x.Identity.Id.AocType == AocTypes.AM)", + "\n .WithApplicability(x => x.GetStorage().ImportFormat != ImportFormats.Cashflow ", + "\n && !x.GetStorage().IsSecondaryScope(x.Identity.Id.DataNode)", + "\n && x.Identity.Id.AocType == AocTypes.EOP ", + "\n && x.Identity.EstimateType != EstimateTypes.A)", + "\n );", + "\n public double Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear); ", + "\n}", + "\n", + "\npublic interface EndOfPeriodActual : ActualBase", + "\n{", + "\n double ActualBase.Value => GetScope((Identity.Id, InputSource.Actual)).Values", + "\n .Sum(aocStep => GetScope((Identity.Id with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear)).Value);", + "\n}", + "\n", + "\npublic interface EmptyValuesActual : ActualBase", + "\n{", + "\n double ActualBase.Value => 0;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An example of Actual Base figures can be found [here](../Test/SpecificationsImportActuals#base-actual)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Actuals", + "\nThe Actuals correspond to ActualBase values with estimate type $A$.", + "\nThe only valid Aoc step is Release:", + "\n", + "\n$$", + "\n\\text{Actual} (\\text{Release}) = \\text{Actual Base} (\\text{Release})|_{\\text{Estimate Type} = A}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Actual : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.A;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Advance Actuals", + "\n", + "\n**Advance Actuals** are those cashflows with due date inside the reporting period but which occured *before* the reporting period - They include:", + "\n- Receivable Claims", + "\n- Receivable Expenses", + "\n- Payable Premiums", + "\n", + "\nAdvance Actuals are given by", + "\n", + "\n$$", + "\n\\text{Advance Actual} (\\text{AoC step}) = \\text{Actual Base} (\\text{AoC step})|_{\\text{Estimate Type} = AA}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface AdvanceActual : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.AA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Overdue Actuals", + "\n", + "\n**Overdue Actuals** are those cashflows with due date inside the reporting period but which occur *after* the reporting period - They contain:", + "\n- Payable Claims", + "\n- Payable Expenses", + "\n- Receivable Premiums", + "\n", + "\nThe sign convention is the inverse of the default behavior - In particular: Premiums have positive value, whereas Claims and Expenses have negative value.", + "\n", + "\nThe Overdue Actuals are given by", + "\n", + "\n$$", + "\n\\text{Overdue Actual} (\\text{AoC step}) = \\text{Actual Base} (\\text{AoC step})|_{\\text{Estimate Type} = OA}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface OverdueActual : IScope", + "\n{", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.OA;", + "\n ", + "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", + "\n ", + "\n [NotVisible]", + "\n ActualBase[] Actuals => GetScope(Identity.DataNode).ActualAmountTypes", + "\n .SelectMany(at => accidentYears", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay)))).ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Deferrable Actuals", + "\n", + "\nFinally, Deferrable Actuals are given by", + "\n", + "\n$$", + "\n\\text{Deferrable Actual} (\\text{AoC step}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n\\sum_{\\text{Amount Type}~\\in~\\text{\\{ACA, AEA}\\}}\\text{Actual Base}(\\rm{CF})|_{\\text{Estimate Type = A}} ~, & \\text{if AoC Step's AoC Type = CF } \\\\", + "\n- \\text{Amortization Factor} \\cdot \\big( \\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) \\big) ~, & \\text{if AoC Step's AoC Type = AM } \\\\", + "\n\\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) + \\text{Deferrable Actual}(\\rm{AM}) ~, & \\text{if AoC Step's AoC Type = EOP } \\\\", + "\n\\text{Input Actual}|_{\\text{Estimate Type = DA}} ~, & \\text{ otherwise } \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere $ACA$ and $AEA$ are *Aquisition* Amount Types from **Attributable Commission** and **Attributable Expenses**, respectively." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface DeferrableActual : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.VFA, ", + "\n p => p.ForMember(s => s.EconomicBasis))", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.AM)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)", + "\n );", + "\n ", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.DA;", + "\n ", + "\n [NotVisible] string EconomicBasis => EconomicBases.L;", + "\n ", + "\n public double Value => GetStorage().GetValue(Identity, (string)null, EstimateType, (int?)null);", + "\n}", + "\n", + "\npublic interface DeferrableActualForCurrentBasis : DeferrableActual", + "\n{", + "\n [NotVisible] string DeferrableActual.EconomicBasis => EconomicBases.C;", + "\n}", + "\n", + "\npublic interface ReleaseDeferrable : DeferrableActual", + "\n{", + "\n double DeferrableActual.Value => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(at => GetScope((Identity, at, EstimateTypes.A, (int?)null)).Value);", + "\n}", + "\n", + "\npublic interface AmortizationDeferrable : DeferrableActual", + "\n{", + "\n private double AmortizationFactor => GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;", + "\n private double AggregatedDeferrable => GetScope((Identity, InputSource.Actual)).Values", + "\n .Sum(aocStep => GetScope(Identity with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}).Value);", + "\n double DeferrableActual.Value => -1d * AggregatedDeferrable * AmortizationFactor;", + "\n}", + "\n", + "\npublic interface EndOfPeriodDeferrable : DeferrableActual", + "\n{", + "\n double DeferrableActual.Value => GetScope((Identity, InputSource.Actual)).Values", + "\n .Sum(aocStep => GetScope(Identity with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}).Value);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An example of Deferrable Actual figures can be found [here](../Test/SpecificationsImportActuals#deferrable-actual)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Contractual Service Margin, Loss Component and Loss Recovery Component", + "\n", + "\nThe Contractual Service Margin ($CSM$) denotes the unearned profit from an insurance contract or group of insurance contracts and plays a critical role in the calculation of profit & loss values. Similarly, the unearned loss is denoted by Loss Component ($LC$), Loss Recovery Component in the case of reinsurance contracts." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Experience Adjustment on Premium" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Experience Adjustment (EA) on Premiums weights the cash-flow (CF aocSteps) for premium amount types by the PremiumAllocationFactor input for each group of insurance contract. ", + "\nThe contributions of present values and actuals are computed separately.", + "\n", + "\n$$", + "\nEA (\\rm{PV}) = \\text{Premium Allocation Factor} \\cdot \\big( PV (\\text{AocType = CF}) \\big)~, \\\\", + "\n$$", + "\n$$", + "\nEA (\\text{Actual}) = \\text{Premium Allocation Factor} \\cdot \\big( \\text{Actual}(\\text{AocType = CF}) + \\text{Advance Actual}(\\text{AocType = CF})+ \\text{Overdue Actual}(\\text{AocType = CF}) \\big) ~,", + "\n$$", + "\nwhere amount type premium and its children are considered, novelties in-force and new business are considered for $PV$ whereas novelty combined is considered for Actual. The allocation is always done in the finest granularity (novelty, line of business, ..) possible." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface BeExperienceAdjustmentForPremium : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s", + "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", + "\n", + "\n string EstimateType => EstimateTypes.BEPA;", + "\n string EconomicBasis => EconomicBases.L;", + "\n ", + "\n PresentValue[] ByAmountType => GetStorage().GetPremiums().Select(pr => GetStorage().GetPremiumAllocationFactor(Identity) * GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n}", + "\n", + "\npublic interface DefaultValueBeExperienceAdjustmentForPremium : BeExperienceAdjustmentForPremium", + "\n{", + "\n PresentValue[] BeExperienceAdjustmentForPremium.ByAmountType => Enumerable.Empty().ToArray();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ActualExperienceAdjustmentForPremium : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s", + "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", + "\n ", + "\n public ActualBase[] ByAmountTypeAndEstimateType => GetStorage().GetPremiums().SelectMany(pr => ", + "\n GetStorage().ExperienceAdjustEstimateTypeMapping.Keys", + "\n .Select(et => GetStorage().GetPremiumAllocationFactor(Identity) * ", + "\n GetScope((Identity, pr, et, (int?)null)))).ToArray(); ", + "\n}", + "\n", + "\npublic interface DefaultValueActualExperienceAdjustmentForPremium : ActualExperienceAdjustmentForPremium", + "\n{", + "\n ActualBase[] ActualExperienceAdjustmentForPremium.ByAmountTypeAndEstimateType => Enumerable.Empty().ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Technical Margin", + "\n", + "\nFor the computation of the $CSM$ or $LC$ component values for each step of the [AoC Step Structure](#aoc-step-structure), it is convenient to introduce the ", + "\nnotion of technical margin $TM$. In the case of BBA methodology, the Locked-in interest rates discounting is applied to obtain the PV and RA values.", + "\n", + "\nThis can be summarized as follows:", + "\n", + "\n$$", + "\nTM(s) = \\left\\{", + "\n\\begin{array}{rl}", + "\nTM(\\rm{EOP}) \\text{ of the previous period} ~ & \\text{if }s = \\text{BOP and Novelty is In-Force}.", + "\n\\\\", + "\n0 ~ & \\text{if }s = \\text{CF}.", + "\n\\\\", + "\nIAF \\cdot~\\text{Aggregated}~TM(\\text{IA}) ~ & \\text{if }s = \\text{IA and Novelty is In-Force}.", + "\n\\\\", + "\n\\rm{Premiums} + \\text{Attributable Expense and Commissions} + \\text{Investment Claims} ~ & \\text{if }s = \\text{EA}.", + "\n\\\\", + "\n-AF \\cdot~\\text{Aggregated}~TM(\\text{AM})~ & \\text{if }s = \\text{AM}.", + "\n\\\\", + "\n\\text{PV}(\\text{s})\\bigg|_{\\substack{\\text{Non Attributable} \\\\ \\text{Amount Types} \\\\ \\text{excluded}}} ", + "\n+ \\text{RA}(\\text{s})~ & \\text{otherwise} ", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere", + "\n", + "\n$$", + "\n\\text{Aggregated}~TM (\\text{AoC step}) = \\sum_{s\\in\\text{ previous AoC steps}} TM(s)~.", + "\n$$", + "\n", + "\nand the Interest Accretion Factor ($IAF$) is given by", + "\n", + "\n$$", + "\nIAF = \\prod_{i=1}^{TS} \\text{Interest}_i - 1", + "\n$$", + "\n", + "\nwhere $\\text{Interest}_i$ is the monthly interest factor obtained from the [Yield Curve](#yield-curves) and $TS$ is the Time-Step.", + "\n", + "\nFinally, the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", + "\n", + "\n$$", + "\n\\rm{Premiums} = \\sum_{\\text{Amount Type}\\in\\{\\text{PR and its children}\\}}", + "\nEA(\\rm{PV}) - EA(\\text{Actual}) ~,", + "\n$$", + "\n", + "\n$$", + "\n\\text{Attributable Expense and Commissions} = \\sum_{\\text{Amount Type}\\in\\{\\rm{ACA}, \\rm{AEA}\\}}", + "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\text{Actual}_{\\text{Novelty=C}} ~,", + "\n$$", + "\n", + "\n$$", + "\n\\text{Investment Claims } = \\sum_{\\text{Amount Type}\\in\\{\\text{ICO and its children}\\}}", + "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}}+ \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~,", + "\n$$", + "\n", + "\nwhere the AoC Step **CF** is implicit for all formulas, $PV$ is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **AA**, and **OA** (see details [here](#actual-values))." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface TechnicalMargin : IScope", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.ValuationApproach == ValuationApproaches.VFA, p => p.ForMember(s => s.EconomicBasis))", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP && x.Identity.Novelty == Novelties.I)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CF)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.IA && x.Identity.Novelty == Novelties.I)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EA && !x.Identity.IsReinsurance)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.AM)", + "\n );", + "\n ", + "\n [NotVisible] string EconomicBasis => EconomicBases.L;", + "\n ", + "\n double Value => GetScope(Identity.DataNode).BeAmountTypes", + "\n .Except(GetStorage().GetNonAttributableAmountType())", + "\n .Sum(at => GetScope((Identity, at, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", + "\n GetScope(Identity).Value;", + "\n ", + "\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values", + "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);", + "\n}", + "\n", + "\npublic interface TechnicalMarginForCurrentBasis : TechnicalMargin", + "\n{", + "\n [NotVisible] string TechnicalMargin.EconomicBasis => EconomicBases.C;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForBOP : TechnicalMargin", + "\n{", + "\n private double ValueCsm => GetStorage().GetValue(Identity, null, EstimateTypes.C, null);", + "\n private double ValueLc => GetStorage().GetValue(Identity, null, EstimateTypes.L, null);", + "\n private double ValueLr => GetStorage().GetValue(Identity, null, EstimateTypes.LR, null);", + "\n ", + "\n double TechnicalMargin.Value => -1d * ValueCsm + ValueLc + ValueLr;", + "\n}", + "\n", + "\npublic interface TechnicalMarginDefaultValue : TechnicalMargin", + "\n{", + "\n double TechnicalMargin.Value => default;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForIA : TechnicalMargin", + "\n{", + "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", + "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", + "\n ", + "\n private double[] monthlyInterestFactor => GetScope(Identity, o => o.WithContext(EconomicBasis)).Interest;", + "\n ", + "\n private double interestAccretionFactor => Enumerable.Range(shift,timeStep)", + "\n .Select(i => GetElementOrDefault(monthlyInterestFactor, i/12))", + "\n .Aggregate(1d, (x, y) => x * y ) - 1d;", + "\n ", + "\n double TechnicalMargin.Value => AggregatedValue * interestAccretionFactor;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForEA : TechnicalMargin", + "\n{", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilderInner(ApplicabilityBuilder builder) => ", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.IsReinsurance));", + "\n ", + "\n private string referenceAocType => GetScope(Identity).Value.AocType;", + "\n ", + "\n private double premiums => GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", + "\n .Sum(n => GetScope(Identity with {AocType = referenceAocType, Novelty = n}).ByAmountType.Sum(sc => sc.Value)) -", + "\n GetScope(Identity with {AocType = referenceAocType, Novelty = Novelties.C}).ByAmountTypeAndEstimateType.Sum(sc => sc.Value);", + "\n ", + "\n private double attributableExpenseAndCommissions => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(d =>", + "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, d, EstimateTypes.A, (int?)null)).Value);", + "\n", + "\n private double investmentClaims => GetStorage().GetInvestmentClaims().Sum(ic =>", + "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.A, (int?)null)).Value - ", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.AA, (int?)null)).Value -", + "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.OA, (int?)null)).Value);", + "\n ", + "\n double TechnicalMargin.Value => premiums + attributableExpenseAndCommissions + investmentClaims;", + "\n}", + "\n", + "\npublic interface TechnicalMarginForAM : TechnicalMargin", + "\n{", + "\n double TechnicalMargin.Value => -1d * AggregatedValue * GetScope(Identity, o => o.WithContext(EconomicBasis)).Value;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Switch Logic", + "\n ", + "\nThe $CSM$ and $LC$ components are computed from the [technical margin](#technical-margin). In particular, for a given AoC step $s$, TM is allocated to the $LC$ when $\\text{Aggregated } TM$ is positive whereas it is allocated to the $CSM$ when $\\text{Aggregated } TM$ is negative:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\nCSM({\\text{Aoc step}}) = 0,~~ LC({\\text{AoC step}}) = TM({\\text{AoC step}}) ~ & \\text{if }\\text{Aggregated }TM({\\text{AoC step}}) > 0.", + "\n\\\\", + "\nCSM({\\text{Aoc step}}) = - TM({\\text{AoC step}}),~~ LC({\\text{AoC step}}) = 0 ~ & \\text{otherwise} ", + "\n\\end{array}", + "\n$$", + "\n", + "\n", + "\nThe figures reported under CSM are the opposite of the TM value in order to satisfy our sign convention.", + "\n", + "\nIt is possible to switch from $CSM$ to $LC$ and from $LC$ to $CSM$ at any AoC step $s$ with the only exception of **Amortization** where there is no switch from the previous step.", + "\nWhen a switch occurs the total contribution to the $CSM$ ($LC$) prior the switching step is brought to 0 and the remaing amount is allocated to $LC$ ($CSM$).", + "\n", + "\n", + "\n### Gross case (i.e. no reinsurance)", + "\n", + "\nThe switch logic is applied ***separately*** to the In-Force and New Business novelties. The Combined Liability Aoc Step **CL** will bring both contributions to CSM and LC together as the novelities are summed up.", + "\n", + "\nIn detail, and as we go through the AoC steps in the AoC chain, we have", + "\n", + "\n**A)** For the **BOP**:", + "\n$$", + "\n\\begin{array}{rl}", + "\nCSM(\\text{BOP}) &= CSM(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", + "\n\\\\", + "\nLC(\\text{BOP}) &= LC(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", + "\n\\end{array}", + "\n$$", + "\n", + "\n", + "\n**B)** For the **following AoC steps**, the switch logic is preferably formulated using the delta variations between steps, $\\Delta CSM$ and $\\Delta LC$ for the CSM and the LC respectively.", + "\n", + "\nThe switch logic for these AoC steps with the *exception* of Combined Liability is:", + "\n", + "\nIf $\\text{Aggregated }TM(\\text{AoC Step}) > 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\le 0$, then there is a switch from $LC$ to $CSM$:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\text{Aggregated } TM(\\text{AoC Step})", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= -\\text{Aggregated } TM(\\text{AoC Step}) ", + "\n\\end{array}", + "\n$$", + "\n", + "\nOn the other hand, if $\\text{Aggregated }TM(\\text{AoC Step}) \\le 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) > 0$, then the switch is from $CSM$ to $LC$:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= \\text{Aggregated } TM(\\text{AoC Step}) ", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= TM(\\text{AoC Step}) + \\text{Aggregated } TM(\\text{AoC Step}) ", + "\n\\end{array}", + "\n$$", + "\n", + "\nIf there is no switch from $CSM$, i.e. $\\text{Aggregated }TM(\\text{AoC Step}) \\le 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\le 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step})", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= 0", + "\n\\end{array}", + "\n$$", + "\n", + "\nAnd finally, if there is no switch from $LC$, i.e. $\\text{Aggregated }TM(\\text{AoC Step}) > 0$ and $\\text{Aggregated }TM(\\text{AoC Step}) + TM(\\text{AoC Step}) \\ge 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= 0", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= TM(\\text{AoC Step})", + "\n\\end{array}", + "\n$$", + "\n", + "\n**C)** For the AoC step Combined Liability **CL**, the switch logic is similar to the one above, except that a switch from $LC$ to $CSM$ can happen **because of New Business and despite of In-Force**, in which case we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\big(\\text{Aggregated } TM(\\text{Last In-Force AoC step})+TM(\\text{Last In-Force AoC step}) \\big)", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= -\\big(\\text{Aggregated } TM(\\text{Last In-Force AoC step}) + TM(\\text{Last In-Force AoC step}) \\big)", + "\n\\end{array}", + "\n$$", + "\n", + "\nIf, on the other hand, the switch from $LC$ to $CSM$ happens **because of In-Force and despite of New Business**, then we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\n\\Delta CSM(\\text{AoC step}) &= -TM(\\text{AoC Step}) -\\big(\\text{Aggregated } TM(\\text{Last NB AoC step})+TM(\\text{Last NB AoC step}) \\big)", + "\n\\\\", + "\n\\Delta LC(\\text{AoC step}) &= -\\big(\\text{Aggregated } TM(\\text{Last NB AoC step}) + TM(\\text{Last NB AoC step}) \\big)", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor the switch in the other direction, i.e. from $CSM$ to $LC$ the formulas are similar except that LC and CSM are swapped.", + "\n", + "\n**D)** Finally, for the last AoC step, the **EOP**, we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\nCSM(\\text{EOP}) &= \\sum_{s~\\in~\\text{previous AoC steps}}\\Delta CSM(s)", + "\n\\\\", + "\nLC(\\text{EOP}) &= \\sum_{s~\\in~\\text{previous AoC steps}}\\Delta LC(s)", + "\n\\end{array}", + "\n$$", + "\n", + "\n", + "\n### Reinsurance case", + "\n", + "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the gross Technical Margins multiplied by the weights coming from the Reinsurance Coverage Parameter (see [Data Node Parameters](../DataModel/DataStructure#data-node-parameters)). In case a GRIC has multiple GICs, then these weighted $TM$s are aggregated." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface AllocateTechnicalMargin: IScope", + "\n{", + "\n //Switch", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) => ", + "\n builder.ForScope(s => s", + "\n .WithApplicability(x => x.Identity.IsReinsurance && x.Identity.AocType == AocTypes.CL) ", + "\n .WithApplicability(x => x.Identity.IsReinsurance, ", + "\n p => p.ForMember(s => s.ComputedEstimateType)", + "\n .ForMember(s => s.HasSwitch))", + "\n .WithApplicability(x => x.GetStorage().IsSecondaryScope(x.Identity.DataNode)) ", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.BOP)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.CL)", + "\n .WithApplicability(x => x.Identity.AocType == AocTypes.EOP)", + "\n );", + "\n ", + "\n [NotVisible] double AggregatedTechnicalMargin => GetScope(Identity).AggregatedValue; ", + "\n [NotVisible] double TechnicalMargin => GetScope(Identity).Value;", + "\n ", + "\n [NotVisible] string ComputedEstimateType => ComputeEstimateType(GetScope(Identity).AggregatedValue + TechnicalMargin);", + "\n [NotVisible] bool HasSwitch => ComputedEstimateType != ComputeEstimateType(GetScope(Identity).AggregatedValue);", + "\n ", + "\n //Allocate ", + "\n [NotVisible] string EstimateType => GetContext();", + "\n ", + "\n double Value => (HasSwitch, EstimateType == ComputedEstimateType) switch {", + "\n (true, true) => TechnicalMargin + AggregatedTechnicalMargin,", + "\n (true, false) => -1d * AggregatedTechnicalMargin,", + "\n (false, true) => TechnicalMargin,", + "\n _ => default", + "\n };", + "\n ", + "\n string ComputeEstimateType(double aggregatedTechnicalMargin) => aggregatedTechnicalMargin > Precision ? EstimateTypes.L : EstimateTypes.C;", + "\n}", + "\n", + "\npublic interface ComputeAllocateTechnicalMarginWithIfrsVariable : AllocateTechnicalMargin", + "\n{ ", + "\n double AllocateTechnicalMargin.TechnicalMargin => ComputeTechnicalMarginFromIfrsVariables(Identity);", + "\n double AllocateTechnicalMargin.AggregatedTechnicalMargin => GetScope((Identity, InputSource.Cashflow)).Values", + "\n .Sum(aoc => ComputeTechnicalMarginFromIfrsVariables(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}));", + "\n ", + "\n private double ComputeTechnicalMarginFromIfrsVariables(ImportIdentity id)", + "\n {", + "\n return GetStorage().GetValue(Identity, null, EstimateTypes.LR, null) +", + "\n GetStorage().GetValue(Identity, null, EstimateTypes.L, null) - ", + "\n GetStorage().GetValue(Identity, null, EstimateTypes.C, null);", + "\n }", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForReinsurance : AllocateTechnicalMargin", + "\n{ ", + "\n //TODO add Reinsurance Coverage Update (RCU, Novelty=I) AocStep", + "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);", + "\n ", + "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).TechnicalMargin);", + "\n ", + "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).AggregatedTechnicalMargin);", + "\n ", + "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;", + "\n ", + "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);", + "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => ComputedEstimateType != ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM); ", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForReinsuranceCL : AllocateTechnicalMargin", + "\n{ ", + "\n //In common1", + "\n private IEnumerable underlyingGic => GetStorage().GetUnderlyingGic(Identity);", + "\n ", + "\n private double weightedUnderlyingTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).TechnicalMargin);", + "\n ", + "\n private double weightedUnderlyingAggregatedTM => underlyingGic.Sum(gic => GetStorage().GetReinsuranceCoverage(Identity, gic) * ", + "\n GetScope(Identity with {DataNode = gic}).AggregatedTechnicalMargin);", + "\n private string ComputeReinsuranceEstimateType(double aggregatedFcf) => aggregatedFcf > Precision ? EstimateTypes.LR : EstimateTypes.C;", + "\n ", + "\n string AllocateTechnicalMargin.ComputedEstimateType => ComputeReinsuranceEstimateType(weightedUnderlyingAggregatedTM + weightedUnderlyingTM);", + "\n //In common2", + "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))", + "\n .Values", + "\n .GroupBy(x => x.Novelty)", + "\n .Select(g => g.Last())", + "\n .Sum(aoc => { ", + "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};", + "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ", + "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin", + "\n : (double)default; });", + "\n ", + "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;", + "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue; ", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForCl : AllocateTechnicalMargin", + "\n{", + "\n private double balancingValue => GetScope((Identity, InputSource.Cashflow))", + "\n .Values", + "\n .GroupBy(x => x.Novelty)", + "\n .Select(g => g.Last())", + "\n .Sum(aoc => { ", + "\n var id = Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty};", + "\n return GetScope(id).ComputedEstimateType != ComputedEstimateType ? ", + "\n GetScope(id).TechnicalMargin + GetScope(id).AggregatedTechnicalMargin", + "\n : (double)default; });", + "\n", + "\n [NotVisible] bool AllocateTechnicalMargin.HasSwitch => Math.Abs(balancingValue) > Precision;", + "\n ", + "\n [NotVisible] double AllocateTechnicalMargin.AggregatedTechnicalMargin => balancingValue;", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForBop : AllocateTechnicalMargin", + "\n{ ", + "\n bool AllocateTechnicalMargin.HasSwitch => false;", + "\n}", + "\n", + "\npublic interface AllocateTechnicalMarginForEop : AllocateTechnicalMargin", + "\n{", + "\n double AllocateTechnicalMargin.Value => GetScope((Identity, InputSource.Cashflow)).Values", + "\n .Sum(aoc => GetScope(Identity with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);", + "\n [NotVisible] string AllocateTechnicalMargin.ComputedEstimateType => ComputeEstimateType(AggregatedTechnicalMargin);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For the **Group of Reinsurance Contracts** (GRICs), the switch is computed within the underlying GIC context and $CSM$ and $LR$ are then computed in the same manner as for the underlying GICs CSM and LC." + ] + }, + { + "cell_type": "markdown", + "source": [ + "The scopes below are simply used to set the appropriate Estimate Type (C for $CSM$, L for $LC$ and LR for $LCR$), as well as to set $CSM$ values to be positive:" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Csm : IScope", + "\n{", + "\n [NotVisible]string EstimateType => EstimateTypes.C;", + "\n ", + "\n double Value => -1d * GetScope(Identity, o => o.WithContext(EstimateType)).Value;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Lc : IScope", + "\n{", + "\n [NotVisible]string EstimateType => EstimateTypes.L;", + "\n ", + "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface LoReCo : IScope", + "\n{ ", + "\n [NotVisible]string EstimateType => EstimateTypes.LR;", + "\n ", + "\n double Value => GetScope(Identity, o => o.WithContext(EstimateType)).Value;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Computing All Scopes", + "\n", + "\nSince all the calculations defined in the various scopes are to be performed together, it is useful to introduce the scope ComputeAllScopes below, which given a certain Import Identity and Import Storage, performs all the calculations (defined above) based on the corresponding data:" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ComputeAllScopes: IScope //ComputeIfrsVariable", + "\n{", + "\n IEnumerable PvLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable PvCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable RaCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = null,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable RaLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", + "\n EstimateType = x.Identity.CalculationType, ", + "\n DataNode = x.Identity.Id.DataNode, ", + "\n AocType = x.Identity.Id.AocType, ", + "\n Novelty = x.Identity.Id.Novelty, ", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = null,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n private string EconomicBasis => Identity.ValuationApproach == ValuationApproaches.VFA ? EconomicBases.C : EconomicBases.L;", + "\n private IEnumerable amortizationFactor => Identity.AocType == AocTypes.AM", + "\n ? GetScope(Identity, o => o.WithContext(EconomicBasis))", + "\n .RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n EconomicBasis = x.EconomicBasis,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n })", + "\n : Enumerable.Empty();", + "\n IEnumerable Actual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", + "\n DataNode = x.Identity.Id.DataNode,", + "\n AocType = x.Identity.Id.AocType,", + "\n Novelty = x.Identity.Id.Novelty,", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable AdvanceActual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", + "\n DataNode = x.Identity.Id.DataNode,", + "\n AocType = x.Identity.Id.AocType,", + "\n Novelty = x.Identity.Id.Novelty,", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable OverdueActual => GetScope(Identity).Actuals.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.Identity.EstimateType,", + "\n DataNode = x.Identity.Id.DataNode,", + "\n AocType = x.Identity.Id.AocType,", + "\n Novelty = x.Identity.Id.Novelty,", + "\n AccidentYear = x.Identity.AccidentYear,", + "\n AmountType = x.Identity.AmountType,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n IEnumerable DeferrableActual => GetScope(Identity).RepeatOnce().Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n AccidentYear = null,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n ", + "\n IEnumerable BeEAForPremium => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n || Identity.IsReinsurance", + "\n ? Enumerable.Empty()", + "\n : GetScope(Identity)", + "\n .ByAmountType", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(sc => new IfrsVariable{ EstimateType = GetScope(Identity).EstimateType, ", + "\n DataNode = sc.Identity.Id.DataNode, ", + "\n AocType = sc.Identity.Id.AocType, ", + "\n Novelty = sc.Identity.Id.Novelty, ", + "\n AccidentYear = sc.Identity.AccidentYear,", + "\n EconomicBasis = sc.EconomicBasis,", + "\n AmountType = sc.Identity.AmountType,", + "\n Value = sc.Value,", + "\n Partition = sc.GetStorage().TargetPartition });", + "\n ", + "\n IEnumerable ActEAForPremium => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n || Identity.IsReinsurance", + "\n ? Enumerable.Empty()", + "\n : GetScope(Identity)", + "\n .ByAmountTypeAndEstimateType", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(sc => new IfrsVariable{ EstimateType = GetStorage().ExperienceAdjustEstimateTypeMapping[sc.Identity.EstimateType], ", + "\n DataNode = sc.Identity.Id.DataNode, ", + "\n AocType = sc.Identity.Id.AocType, ", + "\n Novelty = sc.Identity.Id.Novelty, ", + "\n AccidentYear = sc.Identity.AccidentYear,", + "\n //EconomicBasis = scope.EconomicBasis,", + "\n AmountType = sc.Identity.AmountType,", + "\n Value = sc.Value,", + "\n Partition = GetStorage().TargetPartition });", + "\n ", + "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n ? Enumerable.Empty()", + "\n : GetScope(Identity).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n", + "\n IEnumerable Loss => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", + "\n ? Enumerable.Empty()", + "\n : Identity.IsReinsurance ", + "\n ? GetScope(Identity).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n })", + "\n : GetScope(Identity).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", + "\n DataNode = x.Identity.DataNode,", + "\n AocType = x.Identity.AocType,", + "\n Novelty = x.Identity.Novelty,", + "\n Value = x.Value,", + "\n Partition = GetStorage().TargetPartition", + "\n });", + "\n", + "\n /*private double validateSingleEoP => Math.Abs(ValueCsm) > Precision && Math.Abs(ValueLc) > Precision ", + "\n ? (double)ApplicationMessage.Log(Error.MultipleEoP)", + "\n : default;", + "\n */", + "\n IEnumerable CalculatedIfrsVariables => GetStorage().ImportFormat switch {", + "\n ImportFormats.Actual => Actual.Concat(AdvanceActual).Concat(OverdueActual).Concat(ActEAForPremium)", + "\n .Concat(DeferrableActual).Concat(Csms).Concat(Loss),", + "\n ImportFormats.Cashflow => PvLocked.Concat(PvCurrent).Concat(RaCurrent).Concat(RaLocked)", + "\n .Concat(amortizationFactor).Concat(BeEAForPremium)", + "\n .Concat(DeferrableActual).Concat(Csms).Concat(Loss),", + "\n ImportFormats.Opening => AdvanceActual.Concat(OverdueActual).Concat(DeferrableActual)", + "\n .Concat(Csms).Concat(Loss),", + "\n };", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb index 557210ec..ea1af2cc 100644 --- a/Import/ImportStorage.ipynb +++ b/Import/ImportStorage.ipynb @@ -1,387 +1,371 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "zXp-Bu79BE-93BUbDiTYAg", - "cell_type": "markdown", - "source": [ - "", - "\n

Import Storage

", - "\n", - "\nThe Import Storage collects the following data upon import of a file:", - "\n", - "\n- Current Period (year, month)", - "\n- Previous Period", - "\n- [Partitions](../DataModel/DataStructure)", - "\n- [RawVariables](../DataModel/DataStructure)", - "\n- [IfrsVariables](../DataModel/DataStructure)", - "\n- [Projection Configuration](../DataModel/DataStructure)", - "\n- [YieldCurve](../DataModel/DataStructure)", - "\n- [AocType](../DataModel/DataStructure)", - "\n- [AmountType](../DataModel/DataStructure)", - "\n- [CalculationType](../DataModel/DataStructure)", - "\n- [DataNodes](../DataModel/DataStructure)", - "\n", - "\nSuch storage is then passed to calculations defined in the corresponding [Import Scopes](./ImportScopeCalculation)." - ], - "metadata": {} - }, - { - "id": "BBcl8VllBE2yH3necdNVxQ", - "cell_type": "code", - "source": [ - "#!import \"../Utils/UtilityMethods\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "aIs6_wKUtEKp2vLJAPpVpQ", - "cell_type": "markdown", - "source": [ - "# Import Storage" - ], - "metadata": {} - }, - { - "id": "kigCPC7MoEy40WWR1LAtFA", - "cell_type": "code", - "source": [ - "public class ImportStorage", - "\n{ ", - "\n private readonly IDataSource querySource; ", - "\n private readonly IWorkspace workspace;", - "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache;", - "\n private readonly ImportArgs args;", - "\n ", - "\n // Constants", - "\n private static int periodicityInMonths => 3; // Revisit", - "\n ", - "\n //Format", - "\n public string ImportFormat => args.ImportFormat; ", - "\n ", - "\n //Time Periods ", - "\n public (int Year, int Month) CurrentReportingPeriod => (args.Year, args.Month);", - "\n public (int Year, int Month) PreviousReportingPeriod => (args.Year - 1, MonthInAYear); // YTD Logic", - "\n", - "\n //Partitions", - "\n public Guid PartitionByRn;", - "\n public Guid TargetPartition;", - "\n public Guid DefaultPartition;", - "\n public Guid PreviousPeriodPartition; ", - "\n", - "\n //Projections", - "\n private ProjectionConfiguration[] ProjectionConfiguration;", - "\n ", - "\n //DataNodes", - "\n public IDictionary DataNodeDataBySystemName { get; private set; }", - "\n public IDictionary> DataNodesByImportScope { get; private set; }", - "\n public IDictionary> AccidentYearsByDataNode { get; private set; }", - "\n //Variables", - "\n public IDictionary> RawVariablesByImportIdentity { get; private set; }", - "\n public IDictionary> IfrsVariablesByImportIdentity { get; private set; }", - "\n ", - "\n //Parameters", - "\n public Dictionary LockedInYieldCurve { get; private set; }", - "\n public Dictionary> CurrentYieldCurve { get; private set; }", - "\n public Dictionary> PartnerRating { get; private set; }", - "\n public Dictionary> CreditDefaultRates { get; private set; }", - "\n public Dictionary> SingleDataNodeParametersByGoc { get; private set; }", - "\n public Dictionary>> InterDataNodeParametersByGoc { get; private set; }", - "\n public Dictionary AocConfigurationByAocStep { get; private set; }", - "\n ", - "\n private Dictionary> aocStepByInputSource;", - "\n ", - "\n //Dimensions", - "\n public Dictionary AmountTypeDimension { get; private set; }", - "\n public Dictionary NoveltyDimension { get; private set; }", - "\n public Dictionary CalculationTypeDimension { get; private set; }", - "\n public Dictionary EstimateTypeDimension { get; private set; }", - "\n public Dictionary> EstimateTypesByImportFormat { get; private set; }", - "\n public Dictionary ExperienceAdjustEstimateTypeMapping { get; private set; } ", - "\n ", - "\n //Constructor", - "\n public ImportStorage(ImportArgs args, IDataSource querySource, IWorkspace workspace)", - "\n {", - "\n this.querySource = querySource;", - "\n this.workspace = workspace;", - "\n hierarchyCache = workspace.ToHierarchicalDimensionCache();", - "\n this.args = args;", - "\n }", - "\n ", - "\n //Initialize", - "\n public async Task InitializeAsync()", - "\n { ", - "\n //Dimensions", - "\n var estimateTypes = (await workspace.Query().ToArrayAsync());", - "\n ", - "\n EstimateTypeDimension = estimateTypes.ToDictionary(x => x.SystemName);", - "\n AmountTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", - "\n NoveltyDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", - "\n CalculationTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", - "\n ", - "\n ExperienceAdjustEstimateTypeMapping = new Dictionary{{EstimateTypes.A, EstimateTypes.APA}, {EstimateTypes.AA, EstimateTypes.AAPA}, {EstimateTypes.OA, EstimateTypes.OAPA}}; //TODO move this logic", - "\n ", - "\n //Hierarchy Cache", - "\n hierarchyCache.Initialize();", - "\n ", - "\n //EstimateType to load and to update", - "\n EstimateTypesByImportFormat = new InputSource[] { InputSource.Opening, InputSource.Actual, InputSource.Cashflow,}", - "\n .ToDictionary(x => x.ToString(), ", - "\n x => estimateTypes", - "\n .Where(et => et.InputSource.Contains(x))", - "\n .Select(et => et.SystemName)", - "\n .ToHashSet());", - "\n ", - "\n //ProjectionConfiguration : Current Period + projection for every Quarter End for current Year and next Years as in projectionConfiguration.csv", - "\n ProjectionConfiguration = (await workspace.Query()", - "\n .Where(x => x.Shift > 0 || x.TimeStep == args.Month || (x.TimeStep > args.Month && x.TimeStep % periodicityInMonths == 0))", - "\n .OrderBy(x => x.Shift).ThenBy(x => x.TimeStep).ToArrayAsync());", - "\n ", - "\n //Get Partitions", - "\n PartitionByRn = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).Single().Id;", - "\n TargetPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", - "\n p.Year == CurrentReportingPeriod.Year &&", - "\n p.Month == CurrentReportingPeriod.Month &&", - "\n p.Scenario == args.Scenario).ToArrayAsync()).Single().Id;", - "\n DefaultPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", - "\n p.Year == CurrentReportingPeriod.Year &&", - "\n p.Month == CurrentReportingPeriod.Month &&", - "\n p.Scenario == null).ToArrayAsync()).Single().Id;", - "\n //Set Partitions", - "\n await querySource.Partition.SetAsync(PartitionByRn);", - "\n await workspace.Partition.SetAsync(PartitionByRn);", - "\n ", - "\n await querySource.Partition.SetAsync(TargetPartition);", - "\n await workspace.Partition.SetAsync(TargetPartition);", - "\n ", - "\n //Get data from Workspace (result of parsing)", - "\n var parsedRawVariables = await workspace.Query().ToArrayAsync();", - "\n var parsedIfrsVariables = await workspace.Query().ToArrayAsync();", - "\n ", - "\n //DataNodes", - "\n DataNodeDataBySystemName = await workspace.LoadDataNodesAsync(args);", - "\n ", - "\n //Accident Years", - "\n AccidentYearsByDataNode = (IDictionary>)", - "\n (ImportFormat == ImportFormats.Cashflow ? parsedRawVariables.Select(x => new {x.DataNode, x.AccidentYear}) : parsedIfrsVariables.Select(x => new {x.DataNode, x.AccidentYear}))", - "\n .ToDictionaryGrouped(x => x.DataNode, x => (ICollection)x.Select(y => y.AccidentYear).ToHashSet());", - "\n ", - "\n // Import Scopes and Data Node relationship parameters", - "\n InterDataNodeParametersByGoc = await workspace.LoadInterDataNodeParametersAsync(args);", - "\n ", - "\n var primaryScopeFromParsedVariables = (ImportFormat == ImportFormats.Cashflow ? parsedRawVariables.Select(x => x.DataNode) : parsedIfrsVariables.Select(x => x.DataNode)).ToHashSet();", - "\n var primaryScopeFromLinkedReinsurance = primaryScopeFromParsedVariables", - "\n .Where(goc => !DataNodeDataBySystemName[goc].IsReinsurance && DataNodeDataBySystemName[goc].LiabilityType == LiabilityTypes.LRC)", - "\n .SelectMany(goc => InterDataNodeParametersByGoc.TryGetValue(goc, out var interDataNodeParamByPeriod)", - "\n ? interDataNodeParamByPeriod[CurrentPeriod].Select(param => param.DataNode == goc ? param.LinkedDataNode : param.DataNode).Where(goc => !primaryScopeFromParsedVariables.Contains(goc))", - "\n : Enumerable.Empty())", - "\n .ToHashSet();", - "\n ", - "\n var primaryScope = primaryScopeFromParsedVariables.Concat(primaryScopeFromLinkedReinsurance).ToHashSet();", - "\n var secondaryScope = InterDataNodeParametersByGoc", - "\n .Where(kvp => primaryScope.Contains(kvp.Key))", - "\n .SelectMany(kvp => { var linkedGocs = kvp.Value[CurrentPeriod].Select(param => param.DataNode == kvp.Key ? param.LinkedDataNode : param.DataNode);", - "\n return linkedGocs.Where(goc => !primaryScope.Contains(goc));}).ToHashSet();", - "\n var allImportScopes = new HashSet(primaryScope.Concat(secondaryScope));", - "\n ", - "\n DataNodesByImportScope = new Dictionary> { { ImportScope.Primary, primaryScope }, { ImportScope.Secondary, secondaryScope } };", - "\n ", - "\n // Parameters", - "\n PartnerRating = await workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.Partner);", - "\n CreditDefaultRates = await workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.CreditRiskRating);", - "\n SingleDataNodeParametersByGoc = await workspace.LoadSingleDataNodeParametersAsync(args);", - "\n LockedInYieldCurve = await workspace.LoadLockedInYieldCurveAsync(args, allImportScopes.Select(dn => DataNodeDataBySystemName[dn]));", - "\n CurrentYieldCurve = await workspace.LoadCurrentYieldCurveAsync(args, allImportScopes.Select(dn => DataNodeDataBySystemName[dn])); //TODO Rename this variable", - "\n ", - "\n AocConfigurationByAocStep = await querySource.LoadAocStepConfigurationAsDictionaryAsync(args.Year, args.Month); ", - "\n aocStepByInputSource = ((InputSource[])Enum.GetValues(typeof(InputSource))).ToDictionary(x => x,", - "\n x => AocConfigurationByAocStep", - "\n .Where(kvp => kvp.Value.InputSource.Contains(x))", - "\n .Select(kvp => kvp.Key)", - "\n .ToHashSet());", - "\n ", - "\n //Previous Period", - "\n var openingRawVariables = Enumerable.Empty();", - "\n var openingIfrsVariables = Enumerable.Empty();", - "\n", - "\n if(allImportScopes.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year < args.Year)) {", - "\n PreviousPeriodPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", - "\n p.Year == PreviousReportingPeriod.Year &&", - "\n p.Month == PreviousReportingPeriod.Month &&", - "\n p.Scenario == null).ToArrayAsync()).Single().Id;", - "\n ", - "\n await querySource.Partition.SetAsync(PreviousPeriodPartition);", - "\n ", - "\n //Perform queries to previous Period", - "\n openingRawVariables = (await querySource.Query()", - "\n .Where(rv => rv.Partition == PreviousPeriodPartition && rv.AocType == AocTypes.CL)", - "\n .Where(v => primaryScope.Contains(v.DataNode))", - "\n .ToArrayAsync())", - "\n .Select(rv => rv with {AocType = AocTypes.BOP, Novelty = Novelties.I, Values = rv.Values.Skip(MonthInAYear).ToArray(), Partition = TargetPartition});", - "\n ", - "\n openingIfrsVariables = (await querySource.Query()", - "\n .Where(iv => iv.Partition == PreviousPeriodPartition && iv.AocType == AocTypes.EOP)", - "\n .Where(v => allImportScopes.Contains(v.DataNode))", - "\n .ToArrayAsync())", - "\n .Select(iv => iv with {AocType = AocTypes.BOP, Novelty = Novelties.I, Partition = TargetPartition});", - "\n ", - "\n // TODO: print error if ", - "\n //openingRawVariables.Select(x => x.DataNode).ToHashSet() != dataNodesWithPreviousPeriod", - "\n }", - "\n ", - "\n //SetPartition to current Period", - "\n await querySource.Partition.SetAsync(TargetPartition);", - "\n ", - "\n if(primaryScope.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year == args.Year) && ImportFormat != ImportFormats.Opening)", - "\n openingIfrsVariables = openingIfrsVariables.Concat(await querySource.Query()", - "\n .Where(iv => iv.Partition == TargetPartition && iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I)", - "\n .Where(iv => primaryScope.Contains(iv.DataNode) && EstimateTypesByImportFormat[InputSource.Opening.ToString()].Contains(iv.EstimateType) || secondaryScope.Contains(iv.DataNode))", - "\n .ToArrayAsync());", - "\n ", - "\n //Variables", - "\n var rawVariables = parsedRawVariables.Concat(openingRawVariables)", - "\n .Concat(await querySource.Query()", - "\n .Where(rv => rv.Partition == TargetPartition)", - "\n .Where(rv => primaryScopeFromLinkedReinsurance.Contains(rv.DataNode))", - "\n .ToArrayAsync());", - "\n RawVariablesByImportIdentity = (IDictionary>)rawVariables.ToDictionaryGrouped(v => v.DataNode, v => (ICollection)v.ToArray());", - "\n ", - "\n var ifrsVariables = parsedIfrsVariables.Concat(openingIfrsVariables)", - "\n .Concat(await querySource.Query()", - "\n .Where(iv => iv.Partition == TargetPartition && !(iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I))", - "\n .Where(iv => primaryScopeFromParsedVariables.Contains(iv.DataNode) && !EstimateTypesByImportFormat[ImportFormat].Contains(iv.EstimateType) ", - "\n || primaryScopeFromLinkedReinsurance.Contains(iv.DataNode) ", - "\n || secondaryScope.Contains(iv.DataNode))", - "\n .ToArrayAsync());", - "\n IfrsVariablesByImportIdentity = (IDictionary>)ifrsVariables.ToDictionaryGrouped(v => v.DataNode, v => (ICollection)v.ToArray());", - "\n }", - "\n ", - "\n //Getters", - "\n ", - "\n //Periods", - "\n public ValuationPeriod GetValuationPeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].ValuationPeriod;", - "\n public PeriodType GetYieldCurvePeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].YcPeriod;", - "\n public PeriodType GetCreditDefaultRiskPeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].CdrPeriod;", - "\n ", - "\n public IEnumerable GetAllAocSteps(InputSource source) => aocStepByInputSource[source];", - "\n public IEnumerable GetCalculatedTelescopicAocSteps() => AocConfigurationByAocStep.Where(kvp => kvp.Value.DataType == DataType.CalculatedTelescopic).Select(kvp => kvp.Key);", - "\n ", - "\n //YieldCurve", - "\n public double[] GetYearlyYieldCurve(ImportIdentity id, string economicBasis) {", - "\n var yc = GetYieldCurve(id, economicBasis);", - "\n return yc.Values.Skip(args.Year - yc.Year).ToArray(); //Check if the returned array is empty? Log Warning?", - "\n }", - "\n ", - "\n public YieldCurve GetYieldCurve(ImportIdentity id, string economicBasis) => (economicBasis, GetYieldCurvePeriod(id)) switch {", - "\n (EconomicBases.C, PeriodType.BeginningOfPeriod) => CurrentYieldCurve[DataNodeDataBySystemName[id.DataNode].ContractualCurrency][PreviousPeriod],", - "\n (EconomicBases.C, PeriodType.EndOfPeriod) => CurrentYieldCurve[DataNodeDataBySystemName[id.DataNode].ContractualCurrency][CurrentPeriod],", - "\n (EconomicBases.L, _ ) => LockedInYieldCurve[id.DataNode],", - "\n (_, PeriodType.NotApplicable) => (YieldCurve)ApplicationMessage.Log(Error.YieldCurvePeriodNotApplicable, id.AocType, id.Novelty),", - "\n (_, _) => (YieldCurve)ApplicationMessage.Log(Error.EconomicBasisNotFound, id.DataNode)", - "\n };", - "\n ", - "\n //int Identity.ProjectionPeriod ", - "\n public int GetProjectionCount() => ProjectionConfiguration.Count();", - "\n public int GetShift(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].Shift;", - "\n public int GetTimeStep(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].TimeStep;", - "\n ", - "\n public PeriodType GetPeriodType(string amountType, string calculationType) => ", - "\n amountType != null && AmountTypeDimension.TryGetValue(amountType, out var at) ", - "\n ? at.PeriodType", - "\n : calculationType != null && CalculationTypeDimension.TryGetValue(calculationType, out var ct) ", - "\n ? ct.PeriodType : PeriodType.EndOfPeriod;", - "\n", - "\n //Variables and Cashflows", - "\n public IEnumerable GetRawVariables(string dataNode) => RawVariablesByImportIdentity.TryGetValue(dataNode, out var variableCollection) ? variableCollection : Enumerable.Empty();", - "\n public IEnumerable GetIfrsVariables(string dataNode) => IfrsVariablesByImportIdentity.TryGetValue(dataNode, out var variableCollection) ? variableCollection : Enumerable.Empty();", - "\n ", - "\n public double[] GetValues(ImportIdentity id, Func whereClause) => GetRawVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Values ?? Enumerable.Empty().ToArray();", - "\n public double GetValue(ImportIdentity id, Func whereClause) => GetIfrsVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Value ?? 0;", - "\n ", - "\n public double[] GetValues(ImportIdentity id, string amountType, string calculationType, int? accidentYear) => GetValues(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.CalculationType == calculationType);", - "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType);", - "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, string economicBasis, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType && v.EconomicBasis == economicBasis);", - "\n ", - "\n //Novelty", - "\n private IEnumerable GetNoveltiesForAocType(string aocType, IEnumerable aocConfiguration) => aocConfiguration.Where(aocStep => aocStep.AocType == aocType).Select(aocStep => aocStep.Novelty);", - "\n public IEnumerable GetNovelties() => NoveltyDimension.Keys;", - "\n public IEnumerable GetNovelties(string aocType) => GetNoveltiesForAocType(aocType, AocConfigurationByAocStep.Keys);", - "\n public IEnumerable GetNovelties(string aocType, InputSource inputSource) => GetNoveltiesForAocType(aocType, aocStepByInputSource[inputSource]);", - "\n ", - "\n //Accident years", - "\n public IEnumerable GetAccidentYears(string dataNode) => AccidentYearsByDataNode.TryGetValue(dataNode, out var accidentYear) ? accidentYear : new int?[] { null };", - "\n ", - "\n // Parameters", - "\n public double GetNonPerformanceRiskRate (ImportIdentity identity) {", - "\n var period = GetCreditDefaultRiskPeriod(identity) == PeriodType.BeginningOfPeriod ? PreviousPeriod : CurrentPeriod;", - "\n ", - "\n if(!DataNodeDataBySystemName.TryGetValue(identity.DataNode, out var dataNodeData)) ApplicationMessage.Log(Error.DataNodeNotFound, identity.DataNode);", - "\n if(dataNodeData.Partner == null) ApplicationMessage.Log(Error.PartnerNotFound, identity.DataNode);", - "\n // if Partner == Internal then return 0;", - "\n if(!PartnerRating.TryGetValue(dataNodeData.Partner, out var rating)) ApplicationMessage.Log(Error.RatingNotFound, dataNodeData.Partner);", - "\n if(!CreditDefaultRates.TryGetValue(rating[period].CreditRiskRating, out var rate)) ApplicationMessage.Log(Error.CreditDefaultRateNotFound, rating[period].CreditRiskRating);", - "\n return rate[period].Values[0];", - "\n }", - "\n ", - "\n public double GetPremiumAllocationFactor(ImportIdentity id) => SingleDataNodeParametersByGoc.TryGetValue(id.DataNode, out var singleDataNodeParameter) ", - "\n ? singleDataNodeParameter[CurrentPeriod].PremiumAllocation : DefaultPremiumExperienceAdjustmentFactor;", - "\n ", - "\n // Data Node relationships", - "\n public IEnumerable GetUnderlyingGic(ImportIdentity id) => !InterDataNodeParametersByGoc.TryGetValue(id.DataNode, out var interDataNodeParameters)", - "\n ? Enumerable.Empty()", - "\n : interDataNodeParameters[CurrentPeriod].Select(x => x.DataNode != id.DataNode ? x.DataNode : x.LinkedDataNode).Where(goc => !DataNodeDataBySystemName[goc].IsReinsurance);", - "\n ", - "\n public double GetReinsuranceCoverage (ImportIdentity id, string gic) ", - "\n {", - "\n var targetPeriod = AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].RcPeriod == PeriodType.EndOfPeriod ? CurrentPeriod : PreviousPeriod;", - "\n return InterDataNodeParametersByGoc.TryGetValue(id.DataNode, out var interDataNodeParameters)", - "\n ? interDataNodeParameters[targetPeriod].FirstOrDefault(x => x.DataNode == gic || x.LinkedDataNode == gic).ReinsuranceCoverage", - "\n : (double)ApplicationMessage.Log(Error.ReinsuranceCoverage, id.DataNode);", - "\n }", - "\n ", - "\n // Import Scope", - "\n public bool IsPrimaryScope (string dataNode) => DataNodesByImportScope[ImportScope.Primary].Contains(dataNode);", - "\n public bool IsSecondaryScope (string dataNode) => DataNodesByImportScope[ImportScope.Secondary].Contains(dataNode);", - "\n ", - "\n // Other", - "\n public IEnumerable GetNonAttributableAmountType() => new string[]{AmountTypes.NE};", - "\n public IEnumerable GetAttributableExpenseAndCommissionAmountType() => new string[] {AmountTypes.ACA, AmountTypes.AEA}; //U+ specific", - "\n public IEnumerable GetInvestmentClaims() => hierarchyCache.Get(AmountTypes.ICO).Descendants(includeSelf : true).Select(x => x.SystemName);", - "\n public IEnumerable GetPremiums() => hierarchyCache.Get(AmountTypes.PR).Descendants(includeSelf : true).Select(x => x.SystemName);", - "\n public IEnumerable GetClaims() => hierarchyCache.Get(AmountTypes.CL).Descendants().Select(x => x.SystemName);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "AZV9Uq344ESUtVbb13Y6UA", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Import Storage

", + "\n", + "\nThe Import Storage collects the following data upon import of a file:", + "\n", + "\n- Current Period (year, month)", + "\n- Previous Period", + "\n- [Partitions](../DataModel/DataStructure)", + "\n- [RawVariables](../DataModel/DataStructure)", + "\n- [IfrsVariables](../DataModel/DataStructure)", + "\n- [Projection Configuration](../DataModel/DataStructure)", + "\n- [YieldCurve](../DataModel/DataStructure)", + "\n- [AocType](../DataModel/DataStructure)", + "\n- [AmountType](../DataModel/DataStructure)", + "\n- [CalculationType](../DataModel/DataStructure)", + "\n- [DataNodes](../DataModel/DataStructure)", + "\n", + "\nSuch storage is then passed to calculations defined in the corresponding [Import Scopes](./ImportScopeCalculation)." + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Utils/UtilityMethods\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Storage" + ] + }, + { + "cell_type": "code", + "source": [ + "public class ImportStorage", + "\n{ ", + "\n private readonly IDataSource querySource; ", + "\n private readonly IWorkspace workspace;", + "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache;", + "\n private readonly ImportArgs args;", + "\n ", + "\n // Constants", + "\n private static int periodicityInMonths => 3; // Revisit", + "\n ", + "\n //Format", + "\n public string ImportFormat => args.ImportFormat; ", + "\n ", + "\n //Time Periods ", + "\n public (int Year, int Month) CurrentReportingPeriod => (args.Year, args.Month);", + "\n public (int Year, int Month) PreviousReportingPeriod => (args.Year - 1, MonthInAYear); // YTD Logic", + "\n", + "\n //Partitions", + "\n public Guid PartitionByRn;", + "\n public Guid TargetPartition;", + "\n public Guid DefaultPartition;", + "\n public Guid PreviousPeriodPartition; ", + "\n", + "\n //Projections", + "\n private ProjectionConfiguration[] ProjectionConfiguration;", + "\n ", + "\n //DataNodes", + "\n public IDictionary DataNodeDataBySystemName { get; private set; }", + "\n public IDictionary> DataNodesByImportScope { get; private set; }", + "\n public IDictionary> AccidentYearsByDataNode { get; private set; }", + "\n //Variables", + "\n public IDictionary> RawVariablesByImportIdentity { get; private set; }", + "\n public IDictionary> IfrsVariablesByImportIdentity { get; private set; }", + "\n ", + "\n //Parameters", + "\n public Dictionary LockedInYieldCurve { get; private set; }", + "\n public Dictionary> CurrentYieldCurve { get; private set; }", + "\n public Dictionary> PartnerRating { get; private set; }", + "\n public Dictionary> CreditDefaultRates { get; private set; }", + "\n public Dictionary> SingleDataNodeParametersByGoc { get; private set; }", + "\n public Dictionary>> InterDataNodeParametersByGoc { get; private set; }", + "\n public Dictionary AocConfigurationByAocStep { get; private set; }", + "\n ", + "\n private Dictionary> aocStepByInputSource;", + "\n ", + "\n //Dimensions", + "\n public Dictionary AmountTypeDimension { get; private set; }", + "\n public Dictionary NoveltyDimension { get; private set; }", + "\n public Dictionary CalculationTypeDimension { get; private set; }", + "\n public Dictionary EstimateTypeDimension { get; private set; }", + "\n public Dictionary> EstimateTypesByImportFormat { get; private set; }", + "\n public Dictionary ExperienceAdjustEstimateTypeMapping { get; private set; } ", + "\n ", + "\n //Constructor", + "\n public ImportStorage(ImportArgs args, IDataSource querySource, IWorkspace workspace)", + "\n {", + "\n this.querySource = querySource;", + "\n this.workspace = workspace;", + "\n hierarchyCache = workspace.ToHierarchicalDimensionCache();", + "\n this.args = args;", + "\n }", + "\n ", + "\n //Initialize", + "\n public async Task InitializeAsync()", + "\n { ", + "\n //Dimensions", + "\n var estimateTypes = (await workspace.Query().ToArrayAsync());", + "\n ", + "\n EstimateTypeDimension = estimateTypes.ToDictionary(x => x.SystemName);", + "\n AmountTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n NoveltyDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n CalculationTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n ", + "\n ExperienceAdjustEstimateTypeMapping = new Dictionary{{EstimateTypes.A, EstimateTypes.APA}, {EstimateTypes.AA, EstimateTypes.AAPA}, {EstimateTypes.OA, EstimateTypes.OAPA}}; //TODO move this logic", + "\n ", + "\n //Hierarchy Cache", + "\n hierarchyCache.Initialize();", + "\n ", + "\n //EstimateType to load and to update", + "\n EstimateTypesByImportFormat = new InputSource[] { InputSource.Opening, InputSource.Actual, InputSource.Cashflow,}", + "\n .ToDictionary(x => x.ToString(), ", + "\n x => estimateTypes", + "\n .Where(et => et.InputSource.Contains(x))", + "\n .Select(et => et.SystemName)", + "\n .ToHashSet());", + "\n ", + "\n //ProjectionConfiguration : Current Period + projection for every Quarter End for current Year and next Years as in projectionConfiguration.csv", + "\n ProjectionConfiguration = (await workspace.Query()", + "\n .Where(x => x.Shift > 0 || x.TimeStep == args.Month || (x.TimeStep > args.Month && x.TimeStep % periodicityInMonths == 0))", + "\n .OrderBy(x => x.Shift).ThenBy(x => x.TimeStep).ToArrayAsync());", + "\n ", + "\n //Get Partitions", + "\n PartitionByRn = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).Single().Id;", + "\n TargetPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == CurrentReportingPeriod.Year &&", + "\n p.Month == CurrentReportingPeriod.Month &&", + "\n p.Scenario == args.Scenario).ToArrayAsync()).Single().Id;", + "\n DefaultPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == CurrentReportingPeriod.Year &&", + "\n p.Month == CurrentReportingPeriod.Month &&", + "\n p.Scenario == null).ToArrayAsync()).Single().Id;", + "\n //Set Partitions", + "\n await querySource.Partition.SetAsync(PartitionByRn);", + "\n await workspace.Partition.SetAsync(PartitionByRn);", + "\n ", + "\n await querySource.Partition.SetAsync(TargetPartition);", + "\n await workspace.Partition.SetAsync(TargetPartition);", + "\n ", + "\n //Get data from Workspace (result of parsing)", + "\n var parsedRawVariables = await workspace.Query().ToArrayAsync();", + "\n var parsedIfrsVariables = await workspace.Query().ToArrayAsync();", + "\n ", + "\n //DataNodes", + "\n DataNodeDataBySystemName = await workspace.LoadDataNodesAsync(args);", + "\n ", + "\n //Accident Years", + "\n AccidentYearsByDataNode = (IDictionary>)", + "\n (ImportFormat == ImportFormats.Cashflow ? parsedRawVariables.Select(x => new {x.DataNode, x.AccidentYear}) : parsedIfrsVariables.Select(x => new {x.DataNode, x.AccidentYear}))", + "\n .ToDictionaryGrouped(x => x.DataNode, x => (ICollection)x.Select(y => y.AccidentYear).ToHashSet());", + "\n ", + "\n // Import Scopes and Data Node relationship parameters", + "\n InterDataNodeParametersByGoc = await workspace.LoadInterDataNodeParametersAsync(args);", + "\n ", + "\n var primaryScopeFromParsedVariables = (ImportFormat == ImportFormats.Cashflow ? parsedRawVariables.Select(x => x.DataNode) : parsedIfrsVariables.Select(x => x.DataNode)).ToHashSet();", + "\n var primaryScopeFromLinkedReinsurance = primaryScopeFromParsedVariables", + "\n .Where(goc => !DataNodeDataBySystemName[goc].IsReinsurance && DataNodeDataBySystemName[goc].LiabilityType == LiabilityTypes.LRC)", + "\n .SelectMany(goc => InterDataNodeParametersByGoc.TryGetValue(goc, out var interDataNodeParamByPeriod)", + "\n ? interDataNodeParamByPeriod[CurrentPeriod].Select(param => param.DataNode == goc ? param.LinkedDataNode : param.DataNode).Where(goc => !primaryScopeFromParsedVariables.Contains(goc))", + "\n : Enumerable.Empty())", + "\n .ToHashSet();", + "\n ", + "\n var primaryScope = primaryScopeFromParsedVariables.Concat(primaryScopeFromLinkedReinsurance).ToHashSet();", + "\n var secondaryScope = InterDataNodeParametersByGoc", + "\n .Where(kvp => primaryScope.Contains(kvp.Key))", + "\n .SelectMany(kvp => { var linkedGocs = kvp.Value[CurrentPeriod].Select(param => param.DataNode == kvp.Key ? param.LinkedDataNode : param.DataNode);", + "\n return linkedGocs.Where(goc => !primaryScope.Contains(goc));}).ToHashSet();", + "\n var allImportScopes = new HashSet(primaryScope.Concat(secondaryScope));", + "\n ", + "\n DataNodesByImportScope = new Dictionary> { { ImportScope.Primary, primaryScope }, { ImportScope.Secondary, secondaryScope } };", + "\n ", + "\n // Parameters", + "\n PartnerRating = await workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.Partner);", + "\n CreditDefaultRates = await workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.CreditRiskRating);", + "\n SingleDataNodeParametersByGoc = await workspace.LoadSingleDataNodeParametersAsync(args);", + "\n LockedInYieldCurve = await workspace.LoadLockedInYieldCurveAsync(args, allImportScopes.Select(dn => DataNodeDataBySystemName[dn]));", + "\n CurrentYieldCurve = await workspace.LoadCurrentYieldCurveAsync(args, allImportScopes.Select(dn => DataNodeDataBySystemName[dn])); //TODO Rename this variable", + "\n ", + "\n AocConfigurationByAocStep = await querySource.LoadAocStepConfigurationAsDictionaryAsync(args.Year, args.Month); ", + "\n aocStepByInputSource = ((InputSource[])Enum.GetValues(typeof(InputSource))).ToDictionary(x => x,", + "\n x => AocConfigurationByAocStep", + "\n .Where(kvp => kvp.Value.InputSource.Contains(x))", + "\n .Select(kvp => kvp.Key)", + "\n .ToHashSet());", + "\n ", + "\n //Previous Period", + "\n var openingRawVariables = Enumerable.Empty();", + "\n var openingIfrsVariables = Enumerable.Empty();", + "\n", + "\n if(allImportScopes.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year < args.Year)) {", + "\n PreviousPeriodPartition = (await querySource.Query().Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == PreviousReportingPeriod.Year &&", + "\n p.Month == PreviousReportingPeriod.Month &&", + "\n p.Scenario == null).ToArrayAsync()).Single().Id;", + "\n ", + "\n await querySource.Partition.SetAsync(PreviousPeriodPartition);", + "\n ", + "\n //Perform queries to previous Period", + "\n openingRawVariables = (await querySource.Query()", + "\n .Where(rv => rv.Partition == PreviousPeriodPartition && rv.AocType == AocTypes.CL)", + "\n .Where(v => primaryScope.Contains(v.DataNode))", + "\n .ToArrayAsync())", + "\n .Select(rv => rv with {AocType = AocTypes.BOP, Novelty = Novelties.I, Values = rv.Values.Skip(MonthInAYear).ToArray(), Partition = TargetPartition});", + "\n ", + "\n openingIfrsVariables = (await querySource.Query()", + "\n .Where(iv => iv.Partition == PreviousPeriodPartition && iv.AocType == AocTypes.EOP)", + "\n .Where(v => allImportScopes.Contains(v.DataNode))", + "\n .ToArrayAsync())", + "\n .Select(iv => iv with {AocType = AocTypes.BOP, Novelty = Novelties.I, Partition = TargetPartition});", + "\n ", + "\n // TODO: print error if ", + "\n //openingRawVariables.Select(x => x.DataNode).ToHashSet() != dataNodesWithPreviousPeriod", + "\n }", + "\n ", + "\n //SetPartition to current Period", + "\n await querySource.Partition.SetAsync(TargetPartition);", + "\n ", + "\n if(primaryScope.Select(dn => DataNodeDataBySystemName[dn]).Any(dnd => dnd.Year == args.Year) && ImportFormat != ImportFormats.Opening)", + "\n openingIfrsVariables = openingIfrsVariables.Concat(await querySource.Query()", + "\n .Where(iv => iv.Partition == TargetPartition && iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I)", + "\n .Where(iv => primaryScope.Contains(iv.DataNode) && EstimateTypesByImportFormat[InputSource.Opening.ToString()].Contains(iv.EstimateType) || secondaryScope.Contains(iv.DataNode))", + "\n .ToArrayAsync());", + "\n ", + "\n //Variables", + "\n var rawVariables = parsedRawVariables.Concat(openingRawVariables)", + "\n .Concat(await querySource.Query()", + "\n .Where(rv => rv.Partition == TargetPartition)", + "\n .Where(rv => primaryScopeFromLinkedReinsurance.Contains(rv.DataNode))", + "\n .ToArrayAsync());", + "\n RawVariablesByImportIdentity = (IDictionary>)rawVariables.ToDictionaryGrouped(v => v.DataNode, v => (ICollection)v.ToArray());", + "\n ", + "\n var ifrsVariables = parsedIfrsVariables.Concat(openingIfrsVariables)", + "\n .Concat(await querySource.Query()", + "\n .Where(iv => iv.Partition == TargetPartition && !(iv.AocType == AocTypes.BOP && iv.Novelty == Novelties.I))", + "\n .Where(iv => primaryScopeFromParsedVariables.Contains(iv.DataNode) && !EstimateTypesByImportFormat[ImportFormat].Contains(iv.EstimateType) ", + "\n || primaryScopeFromLinkedReinsurance.Contains(iv.DataNode) ", + "\n || secondaryScope.Contains(iv.DataNode))", + "\n .ToArrayAsync());", + "\n IfrsVariablesByImportIdentity = (IDictionary>)ifrsVariables.ToDictionaryGrouped(v => v.DataNode, v => (ICollection)v.ToArray());", + "\n }", + "\n ", + "\n //Getters", + "\n ", + "\n //Periods", + "\n public ValuationPeriod GetValuationPeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].ValuationPeriod;", + "\n public PeriodType GetYieldCurvePeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].YcPeriod;", + "\n public PeriodType GetCreditDefaultRiskPeriod(ImportIdentity id) => AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].CdrPeriod;", + "\n ", + "\n public IEnumerable GetAllAocSteps(InputSource source) => aocStepByInputSource[source];", + "\n public IEnumerable GetCalculatedTelescopicAocSteps() => AocConfigurationByAocStep.Where(kvp => kvp.Value.DataType == DataType.CalculatedTelescopic).Select(kvp => kvp.Key);", + "\n ", + "\n //YieldCurve", + "\n public double[] GetYearlyYieldCurve(ImportIdentity id, string economicBasis) {", + "\n var yc = GetYieldCurve(id, economicBasis);", + "\n return yc.Values.Skip(args.Year - yc.Year).ToArray(); //Check if the returned array is empty? Log Warning?", + "\n }", + "\n ", + "\n public YieldCurve GetYieldCurve(ImportIdentity id, string economicBasis) => (economicBasis, GetYieldCurvePeriod(id)) switch {", + "\n (EconomicBases.C, PeriodType.BeginningOfPeriod) => CurrentYieldCurve[DataNodeDataBySystemName[id.DataNode].ContractualCurrency][PreviousPeriod],", + "\n (EconomicBases.C, PeriodType.EndOfPeriod) => CurrentYieldCurve[DataNodeDataBySystemName[id.DataNode].ContractualCurrency][CurrentPeriod],", + "\n (EconomicBases.L, _ ) => LockedInYieldCurve[id.DataNode],", + "\n (_, PeriodType.NotApplicable) => (YieldCurve)ApplicationMessage.Log(Error.YieldCurvePeriodNotApplicable, id.AocType, id.Novelty),", + "\n (_, _) => (YieldCurve)ApplicationMessage.Log(Error.EconomicBasisNotFound, id.DataNode)", + "\n };", + "\n ", + "\n //int Identity.ProjectionPeriod ", + "\n public int GetProjectionCount() => ProjectionConfiguration.Count();", + "\n public int GetShift(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].Shift;", + "\n public int GetTimeStep(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].TimeStep;", + "\n ", + "\n public PeriodType GetPeriodType(string amountType, string calculationType) => ", + "\n amountType != null && AmountTypeDimension.TryGetValue(amountType, out var at) ", + "\n ? at.PeriodType", + "\n : calculationType != null && CalculationTypeDimension.TryGetValue(calculationType, out var ct) ", + "\n ? ct.PeriodType : PeriodType.EndOfPeriod;", + "\n", + "\n //Variables and Cashflows", + "\n public IEnumerable GetRawVariables(string dataNode) => RawVariablesByImportIdentity.TryGetValue(dataNode, out var variableCollection) ? variableCollection : Enumerable.Empty();", + "\n public IEnumerable GetIfrsVariables(string dataNode) => IfrsVariablesByImportIdentity.TryGetValue(dataNode, out var variableCollection) ? variableCollection : Enumerable.Empty();", + "\n ", + "\n public double[] GetValues(ImportIdentity id, Func whereClause) => GetRawVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Values ?? Enumerable.Empty().ToArray();", + "\n public double GetValue(ImportIdentity id, Func whereClause) => GetIfrsVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Value ?? 0;", + "\n ", + "\n public double[] GetValues(ImportIdentity id, string amountType, string calculationType, int? accidentYear) => GetValues(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.CalculationType == calculationType);", + "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType);", + "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, string economicBasis, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType && v.EconomicBasis == economicBasis);", + "\n ", + "\n //Novelty", + "\n private IEnumerable GetNoveltiesForAocType(string aocType, IEnumerable aocConfiguration) => aocConfiguration.Where(aocStep => aocStep.AocType == aocType).Select(aocStep => aocStep.Novelty);", + "\n public IEnumerable GetNovelties() => NoveltyDimension.Keys;", + "\n public IEnumerable GetNovelties(string aocType) => GetNoveltiesForAocType(aocType, AocConfigurationByAocStep.Keys);", + "\n public IEnumerable GetNovelties(string aocType, InputSource inputSource) => GetNoveltiesForAocType(aocType, aocStepByInputSource[inputSource]);", + "\n ", + "\n //Accident years", + "\n public IEnumerable GetAccidentYears(string dataNode) => AccidentYearsByDataNode.TryGetValue(dataNode, out var accidentYear) ? accidentYear : new int?[] { null };", + "\n ", + "\n // Parameters", + "\n public double GetNonPerformanceRiskRate (ImportIdentity identity) {", + "\n var period = GetCreditDefaultRiskPeriod(identity) == PeriodType.BeginningOfPeriod ? PreviousPeriod : CurrentPeriod;", + "\n ", + "\n if(!DataNodeDataBySystemName.TryGetValue(identity.DataNode, out var dataNodeData)) ApplicationMessage.Log(Error.DataNodeNotFound, identity.DataNode);", + "\n if(dataNodeData.Partner == null) ApplicationMessage.Log(Error.PartnerNotFound, identity.DataNode);", + "\n // if Partner == Internal then return 0;", + "\n if(!PartnerRating.TryGetValue(dataNodeData.Partner, out var rating)) ApplicationMessage.Log(Error.RatingNotFound, dataNodeData.Partner);", + "\n if(!CreditDefaultRates.TryGetValue(rating[period].CreditRiskRating, out var rate)) ApplicationMessage.Log(Error.CreditDefaultRateNotFound, rating[period].CreditRiskRating);", + "\n return rate[period].Values[0];", + "\n }", + "\n ", + "\n public double GetPremiumAllocationFactor(ImportIdentity id) => SingleDataNodeParametersByGoc.TryGetValue(id.DataNode, out var singleDataNodeParameter) ", + "\n ? singleDataNodeParameter[CurrentPeriod].PremiumAllocation : DefaultPremiumExperienceAdjustmentFactor;", + "\n ", + "\n // Data Node relationships", + "\n public IEnumerable GetUnderlyingGic(ImportIdentity id) => !InterDataNodeParametersByGoc.TryGetValue(id.DataNode, out var interDataNodeParameters)", + "\n ? Enumerable.Empty()", + "\n : interDataNodeParameters[CurrentPeriod].Select(x => x.DataNode != id.DataNode ? x.DataNode : x.LinkedDataNode).Where(goc => !DataNodeDataBySystemName[goc].IsReinsurance);", + "\n ", + "\n public double GetReinsuranceCoverage (ImportIdentity id, string gic) ", + "\n {", + "\n var targetPeriod = AocConfigurationByAocStep[new AocStep(id.AocType, id.Novelty)].RcPeriod == PeriodType.EndOfPeriod ? CurrentPeriod : PreviousPeriod;", + "\n return InterDataNodeParametersByGoc.TryGetValue(id.DataNode, out var interDataNodeParameters)", + "\n ? interDataNodeParameters[targetPeriod].FirstOrDefault(x => x.DataNode == gic || x.LinkedDataNode == gic).ReinsuranceCoverage", + "\n : (double)ApplicationMessage.Log(Error.ReinsuranceCoverage, id.DataNode);", + "\n }", + "\n ", + "\n // Import Scope", + "\n public bool IsPrimaryScope (string dataNode) => DataNodesByImportScope[ImportScope.Primary].Contains(dataNode);", + "\n public bool IsSecondaryScope (string dataNode) => DataNodesByImportScope[ImportScope.Secondary].Contains(dataNode);", + "\n ", + "\n // Other", + "\n public IEnumerable GetNonAttributableAmountType() => new string[]{AmountTypes.NE};", + "\n public IEnumerable GetAttributableExpenseAndCommissionAmountType() => new string[] {AmountTypes.ACA, AmountTypes.AEA}; //U+ specific", + "\n public IEnumerable GetInvestmentClaims() => hierarchyCache.Get(AmountTypes.ICO).Descendants(includeSelf : true).Select(x => x.SystemName);", + "\n public IEnumerable GetPremiums() => hierarchyCache.Get(AmountTypes.PR).Descendants(includeSelf : true).Select(x => x.SystemName);", + "\n public IEnumerable GetClaims() => hierarchyCache.Get(AmountTypes.CL).Descendants().Select(x => x.SystemName);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index 843a7409..eb140724 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -1,1199 +1,1061 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "atie2kRp5EK_Lok_1cKKnA", - "cell_type": "markdown", - "source": [ - "", - "\n

Importer Methods

", - "\n" - ], - "metadata": {} - }, - { - "id": "YHW5Ovles0y2T26fE8ZOLw", - "cell_type": "code", - "source": [ - "#!import \"ImportScopeCalculation\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Wraw7o21Pk2HmWk4UAqqsA", - "cell_type": "markdown", - "source": [ - "# Parsing Storage" - ], - "metadata": {} - }, - { - "id": "R427JwfBrEqXKnAMHrgizg", - "cell_type": "code", - "source": [ - "public class ParsingStorage", - "\n{", - "\n private readonly IDataSource dataSource;", - "\n private readonly IWorkspace workspace;", - "\n private readonly ImportArgs args;", - "\n ", - "\n //Hierarchy Cache", - "\n public Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache HierarchyCache;", - "\n ", - "\n public ReportingNode ReportingNode { get; protected set; }", - "\n ", - "\n public Dictionary DataNodeDataBySystemName;", - "\n ", - "\n // Dimensions", - "\n public Dictionary CalculationType;", - "\n public Dictionary PvAmountType; ", - "\n public HashSet AocTypeMap;", - "\n private HashSet estimateTypes;", - "\n private HashSet amountTypes;", - "\n private Dictionary> amountTypesByEstimateType => GetAmountTypesByEstimateType(HierarchyCache);", - "\n public HashSet TechnicalMarginEstimateTypes => GetTechnicalMarginEstimateType(); ", - "\n public Dictionary> DimensionsWithExternalId;", - "\n ", - "\n // Partitions", - "\n public PartitionByReportingNode TargetPartitionByReportingNode;", - "\n public PartitionByReportingNodeAndPeriod TargetPartitionByReportingNodeAndPeriod;", - "\n ", - "\n //Constructor", - "\n public ParsingStorage(ImportArgs args, IDataSource dataSource, IWorkspace workspace)", - "\n {", - "\n this.args = args;", - "\n this.dataSource = dataSource;", - "\n this.workspace = workspace;", - "\n }", - "\n ", - "\n // Initialize", - "\n public async Task InitializeAsync()", - "\n {", - "\n //Partition Workspace and DataSource", - "\n TargetPartitionByReportingNode = (await workspace.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).SingleOrDefault(); ", - "\n ", - "\n if(TargetPartitionByReportingNode == null) ", - "\n { ApplicationMessage.Log(Error.ParsedPartitionNotFound, args.ReportingNode); return; } ", - "\n ", - "\n await workspace.Partition.SetAsync(TargetPartitionByReportingNode.Id);", - "\n await dataSource.Partition.SetAsync(TargetPartitionByReportingNode.Id);", - "\n ", - "\n if(args.Year != default(int) && args.Month != default(int))", - "\n {", - "\n TargetPartitionByReportingNodeAndPeriod = (await workspace.Query()", - "\n .Where(p => p.ReportingNode == args.ReportingNode &&", - "\n p.Year == args.Year &&", - "\n p.Month == args.Month &&", - "\n p.Scenario == args.Scenario).ToArrayAsync()).SingleOrDefault();", - "\n ", - "\n if(TargetPartitionByReportingNodeAndPeriod == null) ", - "\n { ApplicationMessage.Log(Error.ParsedPartitionNotFound, args.ReportingNode, args.Year.ToString(), args.Month.ToString(), args.Scenario); return; } ", - "\n ", - "\n await workspace.Partition.SetAsync(TargetPartitionByReportingNodeAndPeriod.Id);", - "\n await dataSource.Partition.SetAsync(TargetPartitionByReportingNodeAndPeriod.Id);", - "\n ", - "\n //Clean up the workspace", - "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", - "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", - "\n }", - "\n ", - "\n ReportingNode = (await dataSource.Query().Where(x => x.SystemName == args.ReportingNode).ToArrayAsync()).First();", - "\n var aocConfigurationByAocStep = await dataSource.LoadAocStepConfigurationAsync(args.Year, args.Month);", - "\n AocTypeMap = args.ImportFormat switch {", - "\n ImportFormats.Cashflow => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Cashflow) &&", - "\n !new DataType[]{DataType.Calculated, DataType.CalculatedTelescopic}.Contains(x.DataType) )", - "\n .GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", - "\n ImportFormats.Actual => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Actual) &&", - "\n !new DataType[]{DataType.Calculated, DataType.CalculatedTelescopic}.Contains(x.DataType) && ", - "\n new AocStep(x.AocType, x.Novelty) != new AocStep(AocTypes.BOP, Novelties.I))", - "\n .GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", - "\n ImportFormats.Opening => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Opening) && x.DataType == DataType.Optional).GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", - "\n ImportFormats.SimpleValue => aocConfigurationByAocStep.GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).Concat((await dataSource.Query().ToArrayAsync())", - "\n .Select(vt => new AocStep(vt.SystemName,null))).ToHashSet(),", - "\n _ => Enumerable.Empty().ToHashSet(),", - "\n };", - "\n ", - "\n //DataNodes", - "\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 // Dimensions", - "\n CalculationType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", - "\n PvAmountType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", - "\n amountTypes = (await dataSource.Query().ToArrayAsync()).Select(at => at.SystemName).ToHashSet();", - "\n estimateTypes = args.ImportFormat switch {", - "\n ImportFormats.SimpleValue => (await dataSource.Query().ToArrayAsync()).Select(et => et.SystemName).ToHashSet(),", - "\n ImportFormats.Opening => (await dataSource.Query().Where(et => et.StructureType == StructureType.AoC).ToArrayAsync())", - "\n .Where(et => et.InputSource.Contains(InputSource.Opening)) //This Contains overload cannot be used in DB", - "\n .Select(et => et.SystemName).ToHashSet(),", - "\n _ => Enumerable.Empty().ToHashSet(),", - "\n };", - "\n ", - "\n ", - "\n // DimensionsWithExternalId", - "\n DimensionsWithExternalId = new Dictionary>()", - "\n {", - "\n { typeof(PvAmountType), await GetDimensionWithExternalIdDictionaryAsync() },", - "\n { typeof(EstimateType), await GetDimensionWithExternalIdDictionaryAsync() }", - "\n };", - "\n ", - "\n //Hierarchy Cache", - "\n HierarchyCache = workspace.ToHierarchicalDimensionCache();", - "\n HierarchyCache.Initialize();", - "\n }", - "\n ", - "\n public async Task> GetDimensionWithExternalIdDictionaryAsync () where T : KeyedOrderedDimension", - "\n {", - "\n var dict = new Dictionary();", - "\n var items = await dataSource.Query().ToArrayAsync();", - "\n foreach (var item in items) {", - "\n dict.TryAdd(item.SystemName, item.SystemName);", - "\n if(typeof(T).IsAssignableTo(typeof(KeyedOrderedDimensionWithExternalId))) {", - "\n var externalIds = (string[])(typeof(T).GetProperty(nameof(KeyedOrderedDimensionWithExternalId.ExternalId)).GetValue(item));", - "\n if(externalIds == null) continue;", - "\n foreach (var extId in externalIds) ", - "\n dict.TryAdd(extId, item.SystemName);", - "\n }", - "\n }", - "\n return dict;", - "\n }", - "\n ", - "\n // Getters", - "\n public bool IsDataNodeReinsurance(string goc) => DataNodeDataBySystemName[goc].IsReinsurance;", - "\n public bool IsValidDataNode(string goc) => DataNodeDataBySystemName.ContainsKey(goc);", - "\n ", - "\n // Validations", - "\n public string ValidateEstimateType(string et, string goc) {", - "\n var allowedEstimateTypes = estimateTypes;", - "\n if (DataNodeDataBySystemName.TryGetValue(goc, out var dataNodeData) && dataNodeData.LiabilityType == LiabilityTypes.LIC)", - "\n estimateTypes.ExceptWith(TechnicalMarginEstimateTypes);", - "\n if(!allowedEstimateTypes.Contains(et))", - "\n ApplicationMessage.Log(Error.EstimateTypeNotFound, et);", - "\n return et;", - "\n }", - "\n ", - "\n public string ValidateAmountType(string at) {", - "\n if (at != null && !amountTypes.Contains(at))", - "\n ApplicationMessage.Log(Error.AmountTypeNotFound, at);", - "\n return at;", - "\n }", - "\n ", - "\n public AocStep ValidateAocStep(AocStep aoc) {", - "\n if (!AocTypeMap.Contains(aoc))", - "\n ApplicationMessage.Log(Error.AocTypeMapNotFound, aoc.AocType, aoc.Novelty);", - "\n return aoc;", - "\n }", - "\n ", - "\n public string ValidateDataNode(string goc) {", - "\n if (!DataNodeDataBySystemName.ContainsKey(goc))", - "\n ApplicationMessage.Log(Error.InvalidDataNode, goc);", - "\n return goc;", - "\n }", - "\n ", - "\n public void ValidateEstimateTypeAndAmountType(string estimateType, string amountType){", - "\n if (amountTypesByEstimateType.TryGetValue(estimateType, out var ats) && ats.Any() && !ats.Contains(amountType))", - "\n ApplicationMessage.Log(Error.InvalidAmountTypeEstimateType, estimateType, amountType);", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jLFF7eOl8EKi-EoKn60NkA", - "cell_type": "markdown", - "source": [ - "# Basics" - ], - "metadata": {} - }, - { - "id": "LAqrzcPzfU-9EsHmiVfxOg", - "cell_type": "markdown", - "source": [ - "## Clean the Database" - ], - "metadata": {} - }, - { - "id": "USkMObKefk2vtLjT3OjqKQ", - "cell_type": "code", - "source": [ - "async public Task CleanDatabaseAsync (Expression> filter = null) where T : class", - "\n{", - "\n var loadData = await DataSource.Query().Where(filter?? (Expression>)(x => true)).ToListAsync();", - "\n await DataSource.DeleteAsync(loadData);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mUaUxMr_ekW_ZKMYlwu6WQ", - "cell_type": "code", - "source": [ - "async public Task CleanDatabaseFromPartitionAsync (Guid partitionId, Func filter = null) where T : class, IPartitioned", - "\n{", - "\n var loadData = (await DataSource.Query().Where(x => x.Partition == partitionId).ToArrayAsync())", - "\n .Where(filter?? (Func)(x => true)).ToList();", - "\n await DataSource.DeleteAsync(loadData);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3CLQow7bjE67Fq14luFOrw", - "cell_type": "markdown", - "source": [ - "## Update the Database" - ], - "metadata": {} - }, - { - "id": "EQ--NVPYYEqya9DtvVVluw", - "cell_type": "code", - "source": [ - "async public Task CommitToDatabase (Guid partitionId, bool snapshot = true, Func filter = null) where T : class, IPartitioned", - "\n{", - "\n if(snapshot) await CleanDatabaseFromPartitionAsync(partitionId, filter);", - "\n await DataSource.UpdateAsync( await Workspace.Query().ToArrayAsync() );", - "\n await DataSource.CommitAsync();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "alZOFNV3nECY6mw1jPOg9g", - "cell_type": "markdown", - "source": [ - "## Data Node Factory" - ], - "metadata": {} - }, - { - "id": "x30peNSotU-F4HtmYwmRFg", - "cell_type": "code", - "source": [ - "// TODO: think of a better Factory to instantiate DataNode/State/Parameter simultaneously while avoiding public contructors (see Factory Patterns)", - "\n// ATTENTION: this Factory method provides default states and parameters so that it is not mandatory to import them (=> simpler calculation engine). ", - "\n// This method weakness is that these defaults aren't always replaced with the imported values, e,g, when Month > DefaultDataNodeActivationMonth.", - "\n// Therefore they will remain in the DataSource (hopefully without producing any harm).", - "\npublic async Task DataNodeFactoryAsync ()", - "\n{", - "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", - "\n var existingGroupOfContracts = await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync();", - "\n var importedGroupOfContracts = await Workspace.Query().ToArrayAsync();", - "\n var listOfPartitionsWithPeriod = new List();", - "\n ", - "\n foreach (var groupOfContract in importedGroupOfContracts)", - "\n {", - "\n var name = groupOfContract.SystemName;", - "\n if(!existingGroupOfContracts.Any(x => x.SystemName == name))", - "\n {", - "\n var state = new DataNodeState { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", - "\n var parameter = new SingleDataNodeParameter { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", - "\n await Workspace.UpdateAsync(state);", - "\n if(groupOfContract is GroupOfInsuranceContract) await Workspace.UpdateAsync(parameter);", - "\n }", - "\n }", - "\n ", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n //Hot fix: Disabling default as using Annual Cohort breakes Opening importer logic. ", - "\n //await CommitToDatabase(partition, snapshot: false);", - "\n //await CommitToDatabase(partition, snapshot: false);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "plZbdAKxhE2ZjyY7T43g-Q", - "cell_type": "markdown", - "source": [ - "# Importers" - ], - "metadata": {} - }, - { - "id": "6w4ObiZRmUaMLel1WMHQNA", - "cell_type": "markdown", - "source": [ - "## Parse and Upload: Dimensions" - ], - "metadata": {} - }, - { - "id": "hC50TsmYNkKo6cyJ1A0uRQ", - "cell_type": "code", - "source": [ - "public async Task UploadDimensionsAsync (string fileName) where T: class ", - "\n{", - "\n await CleanDatabaseAsync();", - "\n var importLog = await Import.FromFile(fileName).WithType().WithTarget(DataSource).ExecuteAsync();", - "\n return importLog;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zPGrABD22kCbEaJxlm9CYw", - "cell_type": "markdown", - "source": [ - "## Parse Main Tab and return Args" - ], - "metadata": {} - }, - { - "id": "l1JQnGEPfEylauUl-Y-Kqw", - "cell_type": "code", - "source": [ - "public async Task GetArgsFromMainAsync(string file)", - "\n{", - "\n var extension = System.IO.Path.GetExtension(file);", - "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[Main];", - "\n ", - "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", - "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", - "\n if(ApplicationMessage.HasErrors()) return null;", - "\n ", - "\n var main = mainTab.Rows.First();", - "\n var scenario = mainTab.Columns.Where(x => x.ColumnName == nameof(PartitionByReportingNode.Scenario)).Count() > 0? ", - "\n (string)main[nameof(PartitionByReportingNode.Scenario)] : default(string);", - "\n ", - "\n var partitionName = typeof(IPartition).Name switch ", - "\n {", - "\n nameof(PartitionByReportingNode) => new ImportArgs( (string)main[nameof(PartitionByReportingNode.ReportingNode)],", - "\n default(int),", - "\n default(int),", - "\n default(Periodicity),", - "\n scenario,", - "\n default(string)),", - "\n ", - "\n nameof(PartitionByReportingNodeAndPeriod) => new ImportArgs( (string)main[nameof(PartitionByReportingNodeAndPeriod.ReportingNode)], ", - "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Year)], typeof(int)),", - "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Month)], typeof(int)),", - "\n default(Periodicity),", - "\n scenario,", - "\n default(string)),", - "\n ", - "\n _ => null", - "\n };", - "\n ", - "\n if (partitionName == null) ApplicationMessage.Log(Error.PartitionTypeNotFound, typeof(IPartition).Name); ", - "\n return partitionName;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Nc8XqguDwEywNGHzIg3C4A", - "cell_type": "markdown", - "source": [ - "### Parse and Upload: Data Nodes" - ], - "metadata": {} - }, - { - "id": "TryM-sop6USTlvmWqP14CQ", - "cell_type": "markdown", - "source": [ - "### Portfolio and Group of contract" - ], - "metadata": {} - }, - { - "id": "XxwGlJ5PS02O5OtQsb1v8g", - "cell_type": "code", - "source": [ - "public async Task UploadDataNodesToWorkspaceAsync(string fileName)", - "\n{", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization()", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n ", - "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(fileName);", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n var storage = new ParsingStorage(args, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n var errors = new List();", - "\n var importLogPortfolios = await Import.FromFile(fileName)", - "\n .WithType((dataset, datarow) => new InsurancePortfolio {", - "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", - "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", - "\n Partition = storage.TargetPartitionByReportingNode.Id,", - "\n ContractualCurrency = datarow.Field(nameof(DataNode.ContractualCurrency)),", - "\n FunctionalCurrency = storage.ReportingNode.Currency,", - "\n LineOfBusiness = datarow.Field(nameof(DataNode.LineOfBusiness)),", - "\n ValuationApproach = datarow.Field(nameof(DataNode.ValuationApproach)),", - "\n OciType = datarow.Field(nameof(DataNode.OciType))", - "\n })", - "\n .WithType((dataset, datarow) =>new ReinsurancePortfolio {", - "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", - "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", - "\n Partition = storage.TargetPartitionByReportingNode.Id,", - "\n ContractualCurrency = datarow.Field(nameof(DataNode.ContractualCurrency)),", - "\n FunctionalCurrency = storage.ReportingNode.Currency,", - "\n LineOfBusiness = datarow.Field(nameof(DataNode.LineOfBusiness)),", - "\n ValuationApproach = datarow.Field(nameof(DataNode.ValuationApproach)),", - "\n OciType = datarow.Field(nameof(DataNode.OciType))", - "\n })", - "\n .WithTarget(Workspace)", - "\n .ExecuteAsync();", - "\n ", - "\n var portfolios = await Workspace.Query().ToDictionaryAsync(x => x.SystemName);", - "\n var importLogGroupOfContracts = await Import.FromFile(fileName)", - "\n .WithType((dataset, datarow) => {", - "\n var gicSystemName = datarow.Field(nameof(DataNode.SystemName));", - "\n var pf = datarow.Field(nameof(InsurancePortfolio));", - "\n if(!portfolios.TryGetValue(pf, out var portfolioData))", - "\n {", - "\n ApplicationMessage.Log(Error.PortfolioGicNotFound, pf, gicSystemName);", - "\n return null;", - "\n }", - "\n var gic = new GroupOfInsuranceContract {", - "\n SystemName = gicSystemName,", - "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", - "\n Partition = storage.TargetPartitionByReportingNode.Id,", - "\n ContractualCurrency = portfolioData.ContractualCurrency,", - "\n FunctionalCurrency = portfolioData.FunctionalCurrency,", - "\n LineOfBusiness = portfolioData.LineOfBusiness,", - "\n ValuationApproach = portfolioData.ValuationApproach,", - "\n OciType = portfolioData.OciType,", - "\n AnnualCohort = Convert.ToInt32(datarow.Field(nameof(GroupOfContract.AnnualCohort))),", - "\n LiabilityType = datarow.Field(nameof(GroupOfContract.LiabilityType)),", - "\n Profitability = datarow.Field(nameof(GroupOfContract.Profitability)),", - "\n Portfolio = pf", - "\n };", - "\n return ExtendGroupOfContract(gic, datarow);", - "\n })", - "\n .WithType((dataset, datarow) => {", - "\n var gricSystemName = datarow.Field(nameof(DataNode.SystemName));", - "\n var pf = datarow.Field(nameof(ReinsurancePortfolio));", - "\n if(!portfolios.TryGetValue(pf, out var portfolioData))", - "\n {", - "\n ApplicationMessage.Log(Error.PortfolioGicNotFound, pf, gricSystemName);", - "\n return null;", - "\n }", - "\n var gric = new GroupOfReinsuranceContract {", - "\n SystemName = gricSystemName,", - "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", - "\n Partition = storage.TargetPartitionByReportingNode.Id,", - "\n ContractualCurrency = portfolioData.ContractualCurrency,", - "\n FunctionalCurrency = portfolioData.FunctionalCurrency,", - "\n LineOfBusiness = portfolioData.LineOfBusiness,", - "\n ValuationApproach = portfolioData.ValuationApproach,", - "\n OciType = portfolioData.OciType,", - "\n AnnualCohort = Convert.ToInt32(datarow.Field(nameof(GroupOfContract.AnnualCohort))),", - "\n LiabilityType = datarow.Field(nameof(GroupOfContract.LiabilityType)),", - "\n Profitability = datarow.Field(nameof(GroupOfContract.Profitability)),", - "\n Portfolio = pf,", - "\n Partner = datarow.Field(nameof(GroupOfContract.Partner))", - "\n };", - "\n return ExtendGroupOfContract(gric, datarow);", - "\n })", - "\n .WithTarget(Workspace)", - "\n .ExecuteAsync();", - "\n ", - "\n return Activity.Finish().Merge(importLogPortfolios).Merge(importLogGroupOfContracts);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ek8lfAoNYUuv38Cg7Ld7UA", - "cell_type": "code", - "source": [ - "public async Task UploadDataNodesAsync(string fileName)", - "\n{", - "\n var log = await UploadDataNodesToWorkspaceAsync(fileName);", - "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", - "\n ", - "\n await DataNodeFactoryAsync(); ", - "\n return log;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "EWnSq0n9wkmoyganTsWoYw", - "cell_type": "markdown", - "source": [ - "### Data Node State" - ], - "metadata": {} - }, - { - "id": "GPjdrCFjTEiPfTQ_5EzELg", - "cell_type": "code", - "source": [ - "public async Task ValidateDataNodeStatesAsync(Dictionary persistentDataNodeByDataNode)", - "\n{", - "\n foreach(var importedDataNodeState in await Workspace.Query().ToArrayAsync())", - "\n {", - "\n if(persistentDataNodeByDataNode.TryGetValue(importedDataNodeState.DataNode, out var currentPersistentDataNode))", - "\n {", - "\n if(importedDataNodeState.State < currentPersistentDataNode.State)", - "\n ApplicationMessage.Log(Error.ChangeDataNodeState, importedDataNodeState.DataNode, ", - "\n currentPersistentDataNode.State.ToString(), ", - "\n importedDataNodeState.State.ToString());", - "\n", - "\n if(importedDataNodeState.State == currentPersistentDataNode.State)", - "\n await Workspace.DeleteAsync(importedDataNodeState);", - "\n }", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Onp_ZdRWQ0-oaDr1QwZdYg", - "cell_type": "code", - "source": [ - "public async Task UploadDataNodeStateToWorkspaceAsync(string fileName)", - "\n{", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n ", - "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", - "\n ", - "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(fileName);", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n var storage = new ParsingStorage(args, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n", - "\n var importLog = await Import.FromFile(fileName).WithType(", - "\n (dataset, datarow) => new DataNodeState {", - "\n DataNode = datarow.Field(nameof(DataNodeState.DataNode)),", - "\n State = (State)Enum.Parse(typeof(State), datarow.Field(nameof(DataNodeState.State))),", - "\n Year = args.Year,", - "\n Month = args.Month,", - "\n Partition = storage.TargetPartitionByReportingNode.Id", - "\n }", - "\n ).WithTarget(Workspace).ExecuteAsync();", - "\n", - "\n await ValidateDataNodeStatesAsync(storage.DataNodeDataBySystemName);", - "\n return Activity.Finish().Merge(importLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LvFi94RVy0C36bUPNXZIuQ", - "cell_type": "code", - "source": [ - "public async Task UploadDataNodeStateAsync(string fileName)", - "\n{", - "\n var log = await UploadDataNodeStateToWorkspaceAsync(fileName);", - "\n await CommitToDatabase((Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode)), snapshot: false); ", - "\n return log;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "l1yjjsQ6P0OSf1PWW_AL8w", - "cell_type": "markdown", - "source": [ - "### DataNode Parameters" - ], - "metadata": {} - }, - { - "id": "Q5PAOqsi5kOktzneex2EZA", - "cell_type": "code", - "source": [ - "public async Task UploadDataNodeParameterToWorkspaceAsync(string fileName, Guid targetPartitionByReportingNodeId)", - "\n{", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n ", - "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", - "\n ", - "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(fileName) with {ImportFormat = ImportFormats.DataNodeParameter};", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n", - "\n var storage = new ParsingStorage(args, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n", - "\n var singleDataNode = new List();", - "\n var interDataNode = new List<(string,string)>();", - "\n ", - "\n var importLog = await Import.FromFile(fileName)", - "\n .WithType( (dataset, datarow) => {", - "\n", - "\n //read and validate DataNodes", - "\n var dataNode = datarow.Field(nameof(DataNode));", - "\n if(!storage.IsValidDataNode(dataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, dataNode); return null; }", - "\n", - "\n //check for duplicates", - "\n if(singleDataNode.Contains(dataNode)) { ApplicationMessage.Log(Error.DuplicateSingleDataNode, dataNode); return null; }", - "\n singleDataNode.Add(dataNode);", - "\n ", - "\n //Instantiate SingleDataNodeParameter", - "\n return new SingleDataNodeParameter {", - "\n Year = args.Year,", - "\n Month = args.Month,", - "\n Partition = storage.TargetPartitionByReportingNode.Id,", - "\n", - "\n DataNode = dataNode,", - "\n PremiumAllocation = (datarow.Field(nameof(SingleDataNodeParameter.PremiumAllocation)))", - "\n .ToString().CheckStringForExponentialAndConvertToDouble(),", - "\n };", - "\n })", - "\n .WithType( (dataset, datarow) => {", - "\n", - "\n //read and validate DataNodes", - "\n var dataNode = datarow.Field(nameof(InterDataNodeParameter.DataNode));", - "\n if(!storage.IsValidDataNode(dataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, dataNode); return null; }", - "\n", - "\n var linkedDataNode = datarow.Field(nameof(InterDataNodeParameter.LinkedDataNode));", - "\n if(!storage.IsValidDataNode(linkedDataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, linkedDataNode); return null; }", - "\n var dataNodes = new string[]{dataNode, linkedDataNode}.OrderBy(x => x).ToArray();", - "\n", - "\n //validate ReinsuranceGross Link", - "\n var isDn1Reinsurance = storage.IsDataNodeReinsurance(dataNodes[0]);", - "\n var isDn2Reinsurance = storage.IsDataNodeReinsurance(dataNodes[1]);", - "\n var isGrossReinsuranceLink = (isDn1Reinsurance && !isDn2Reinsurance) != (!isDn1Reinsurance && isDn2Reinsurance);", - "\n var reinsCov = (datarow.Field(nameof(InterDataNodeParameter.ReinsuranceCoverage)))", - "\n .ToString().CheckStringForExponentialAndConvertToDouble();", - "\n if(!isGrossReinsuranceLink && Math.Abs(reinsCov) > Precision )", - "\n ApplicationMessage.Log(Error.ReinsuranceCoverageDataNode, dataNodes[0], dataNodes[1]); // TODO: is this error or warning?", - "\n", - "\n //check for duplicates", - "\n if(interDataNode.Contains((dataNodes[0], dataNodes[1])) || interDataNode.Contains((dataNodes[1], dataNodes[0])))", - "\n ApplicationMessage.Log(Error.DuplicateInterDataNode, dataNodes[0], dataNodes[1]); // TODO: is this error or warning?", - "\n", - "\n interDataNode.Add((dataNodes[0], dataNodes[1])); ", - "\n //Instantiate InterDataNodeParameter", - "\n return new InterDataNodeParameter {", - "\n Year = args.Year,", - "\n Month = args.Month,", - "\n Partition = storage.TargetPartitionByReportingNode.Id,", - "\n DataNode = dataNodes[0],", - "\n LinkedDataNode = dataNodes[1],", - "\n ReinsuranceCoverage = reinsCov,", - "\n };", - "\n })", - "\n .WithTarget(Workspace)", - "\n .ExecuteAsync();", - "\n ", - "\n targetPartitionByReportingNodeId = storage.TargetPartitionByReportingNode.Id;", - "\n return Activity.Finish().Merge(importLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FpMgj56nhUWiJDn-bke8XQ", - "cell_type": "code", - "source": [ - "public async Task UploadDataNodeParameterAsync(string fileName)", - "\n{", - "\n Guid partitionId = new Guid();", - "\n var log = await UploadDataNodeParameterToWorkspaceAsync(fileName, partitionId);", - "\n ", - "\n await CommitToDatabase(partitionId, snapshot: false);", - "\n await CommitToDatabase(partitionId, snapshot: false); ", - "\n ", - "\n return log;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "NayXrFB1fUCjVZsyuv3HCA", - "cell_type": "markdown", - "source": [ - "## Parse and Upload: Variables" - ], - "metadata": {} - }, - { - "id": "6nCpBsFe4kylRPgDYwMg9A", - "cell_type": "markdown", - "source": [ - "### Validation for Active Data Node States" - ], - "metadata": {} - }, - { - "id": "aVUxILOVD0WCQ3Kd9uMtaA", - "cell_type": "code", - "source": [ - "public async Task ValidateForDataNodeStateActiveAsync(Dictionary dataNodes) where T : BaseDataRecord", - "\n{ ", - "\n foreach(var item in (await Workspace.Query().ToArrayAsync()).GroupBy(x => x.DataNode))", - "\n if(!dataNodes.ContainsKey(item.First().DataNode))", - "\n ApplicationMessage.Log(Error.InactiveDataNodeState, item.First().DataNode);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WFAodnYhh0S4UQHkB4pFcQ", - "cell_type": "markdown", - "source": [ - "### Cashflow as Raw Variable and Ifrs Variable" - ], - "metadata": {} - }, - { - "id": "a2sXTTFuxk6by0RB9IyY5g", - "cell_type": "code", - "source": [ - "public async Task ParseCashflowsToWorkspaceAsync(string fileName, ImportArgs args)", - "\n{", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n ", - "\n Activity.Start();", - "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", - "\n await parsingStorage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n var importLog = await Import.FromFile(fileName)", - "\n .WithType ( (dataset, datarow) => {", - "\n var aocType = datarow.Field(nameof(RawVariable.AocType));", - "\n var novelty = datarow.Field(nameof(RawVariable.Novelty));", - "\n var dataNode = datarow.Field(nameof(DataNode));", - "\n ", - "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", - "\n ApplicationMessage.Log(Error.InvalidDataNode, dataNode);", - "\n return null;", - "\n }", - "\n ", - "\n // Error if AocType is not present in the mapping", - "\n if(!parsingStorage.AocTypeMap.Contains(new AocStep(aocType, novelty))) {", - "\n ApplicationMessage.Log(Error.AocTypeMapNotFound, aocType, novelty);", - "\n return null;", - "\n }", - "\n ", - "\n // Filter out cashflows for DataNode that were created in the past and are still active and come with AocType = BOPI", - "\n if(dataNodeData.Year < args.Year && aocType == AocTypes.BOP && novelty == Novelties.I) {", - "\n ApplicationMessage.Log(Warning.ActiveDataNodeWithCashflowBOPI);", - "\n return null;", - "\n }", - "\n ", - "\n var amountTypeFromFile = datarow.Field(nameof(RawVariable.AmountType));", - "\n var isCalculationType = parsingStorage.CalculationType.ContainsKey(amountTypeFromFile);", - "\n var amountType = isCalculationType ? null : amountTypeFromFile;", - "\n var calculationType = isCalculationType ? amountTypeFromFile : CalculationTypes.BE;", - "\n ", - "\n var values = datarow.Table.Columns.Where(c => c.ColumnName.StartsWith(nameof(RawVariable.Values))).OrderBy(c => c.ColumnName.Length).ThenBy(c => c.ColumnName)", - "\n .Select(x => datarow.Field(x.ColumnName).CheckStringForExponentialAndConvertToDouble()).Prune();", - "\n ", - "\n // Filter out empty raw variables for AocType != CL", - "\n if(values.Length == 0 && aocType != AocTypes.CL) return null; //TODO: extend this check for all mandatory step and not just for CL", - "\n ", - "\n var item = new RawVariable {", - "\n DataNode = dataNode,", - "\n AocType = aocType,", - "\n Novelty = novelty,", - "\n AmountType = amountType,", - "\n CalculationType = calculationType,", - "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(RawVariable.AccidentYear))), out var tempVal)? tempVal : (int?)null,", - "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Values = Multiply(GetSign((aocType, amountType, calculationType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), values)", - "\n };", - "\n return item;", - "\n }, ImportFormats.Cashflow", - "\n ).WithTarget(Workspace).ExecuteAsync();", - "\n ", - "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", - "\n return Activity.Finish().Merge(importLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3iGcaiP12U-Jc2zU_pPCQw", - "cell_type": "code", - "source": [ - "public async Task UploadCashflowsAsync(string fileName)", - "\n{", - "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Cashflow};", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(fileName, args);", - "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", - "\n ", - "\n var storage = new ImportStorage(args, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", - "\n ", - "\n var universe = Scopes.ForStorage(storage).ToScope();", - "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", - "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", - "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", - "\n ", - "\n await Workspace.UpdateAsync(ivs);", - "\n await CommitToDatabase(storage.TargetPartition, ", - "\n snapshot : true, ", - "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Cashflow].Contains(x.EstimateType) && ", - "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode)); ", - "\n await CommitToDatabase(storage.TargetPartition, ", - "\n snapshot : true,", - "\n filter : x => storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", - "\n", - "\n return Activity.Finish().Merge(parsingLog); ", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BzW1jMILIk-dXDuU0pbd3w", - "cell_type": "markdown", - "source": [ - "### Actuals as Ifrs Variable" - ], - "metadata": {} - }, - { - "id": "4CYHZInVJUOfrmoLQKbolQ", - "cell_type": "code", - "source": [ - "public async Task ParseActualsToWorkspaceAsync(string fileName, ImportArgs args)", - "\n{", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n ", - "\n Activity.Start();", - "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", - "\n await parsingStorage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n", - "\n var importLog = await Import.FromFile(fileName)", - "\n .WithType ( (dataset, datarow) => {", - "\n var dataNode = datarow.Field(nameof(DataNode));", - "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", - "\n ApplicationMessage.Log(Error.InvalidDataNode, dataNode);", - "\n return null;", - "\n }", - "\n ", - "\n var valueType = datarow.Field(ValueType);", - "\n if(valueType == null) { ", - "\n ApplicationMessage.Log(Error.ValueTypeNotFound); ", - "\n return null; ", - "\n }", - "\n ", - "\n var amountType = parsingStorage.DimensionsWithExternalId[typeof(PvAmountType)].TryGetValue(valueType, out var at)? at : null;", - "\n var isStdActual = parsingStorage.PvAmountType.ContainsKey(valueType);", - "\n var estimateType = isStdActual? EstimateTypes.A : parsingStorage.DimensionsWithExternalId[typeof(EstimateType)].TryGetValue(valueType, out var et)? et : null;", - "\n if(estimateType == null || amountType == null) { ", - "\n ApplicationMessage.Log(Error.ValueTypeNotValid, valueType);", - "\n return null;", - "\n }", - "\n ", - "\n var aocType = datarow.Field(nameof(IfrsVariable.AocType));", - "\n if((!isStdActual && aocType != AocTypes.CF && aocType != AocTypes.WO) || (isStdActual && aocType != AocTypes.CF) ) {", - "\n ApplicationMessage.Log(Error.AocTypeNotValid, aocType);", - "\n return null;", - "\n }", - "\n ", - "\n var item = new IfrsVariable {", - "\n DataNode = dataNode,", - "\n AocType = aocType,", - "\n Novelty = Novelties.C,", - "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(IfrsVariable.AccidentYear))), out var tempAccYear)? tempAccYear : (int?)null,", - "\n AmountType = amountType,", - "\n EstimateType = estimateType,", - "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Value = Multiply(GetSign((aocType, amountType, estimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()),", - "\n };", - "\n return item;", - "\n }, ImportFormats.Actual", - "\n ).WithTarget(Workspace).ExecuteAsync();", - "\n ", - "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", - "\n return Activity.Finish().Merge(importLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xeJTsq8-HEqh4t1fxKDzcg", - "cell_type": "code", - "source": [ - "public async Task UploadActualAsync(string fileName)", - "\n{", - "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Actual};", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n", - "\n var parsingLog = await ParseActualsToWorkspaceAsync(fileName, args);", - "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", - "\n", - "\n var storage = new ImportStorage(args, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", - "\n", - "\n var universe = Scopes.ForStorage(storage).ToScope();", - "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", - "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", - "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", - "\n", - "\n await Workspace.UpdateAsync(ivs);", - "\n await CommitToDatabase(storage.TargetPartition, ", - "\n snapshot : true, ", - "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Actual].Contains(x.EstimateType) && ", - "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", - "\n", - "\n return Activity.Finish().Merge(parsingLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GBB66l28v06C1ovuu7oKAA", - "cell_type": "markdown", - "source": [ - "# Simple Value Import" - ], - "metadata": {} - }, - { - "id": "0eUHQv8O1kSXjjquLKakNQ", - "cell_type": "markdown", - "source": [ - "## Simple Value to Workspace" - ], - "metadata": {} - }, - { - "id": "BdMAjdPmX0y00AXxMyx40w", - "cell_type": "code", - "source": [ - "public async Task ParseSimpleValueToWorkspaceAsync(string fileName, ImportArgs args, Guid targetPartitionByReportingNodeAndPeriodId)", - "\n{", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n ", - "\n Activity.Start();", - "\n var importFormat = args.ImportFormat;", - "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", - "\n await parsingStorage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish(); ", - "\n", - "\n var importLog = await Import.FromFile(fileName)", - "\n .WithType ( (dataset, datarow) => {", - "\n var dataNode = parsingStorage.ValidateDataNode(datarow.Field(nameof(DataNode)));", - "\n var amountType = parsingStorage.ValidateAmountType(datarow.Field(nameof(IfrsVariable.AmountType)));", - "\n var estimateType = parsingStorage.ValidateEstimateType(datarow.Field(nameof(IfrsVariable.EstimateType)), dataNode); //TODO LIC/LRC dependence", - "\n var aocStep = importFormat == ImportFormats.SimpleValue ", - "\n ? parsingStorage.ValidateAocStep(new AocStep (datarow.Field(nameof(IfrsVariable.AocType)), ", - "\n datarow.Field(nameof(IfrsVariable.Novelty))))", - "\n : new AocStep(AocTypes.BOP, Novelties.I);", - "\n var economicBasis = importFormat == ImportFormats.SimpleValue ", - "\n ? datarow.Field(nameof(IfrsVariable.EconomicBasis)) ", - "\n : null;", - "\n ", - "\n parsingStorage.ValidateEstimateTypeAndAmountType(estimateType, amountType);", - "\n ", - "\n var iv = new IfrsVariable {", - "\n DataNode = dataNode,", - "\n AocType = aocStep.AocType,", - "\n Novelty = aocStep.Novelty,", - "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(IfrsVariable.AccidentYear))), out var accidentYear) ? accidentYear : (int?)null,", - "\n AmountType = amountType,", - "\n EstimateType = estimateType,", - "\n EconomicBasis = economicBasis,", - "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Value = GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", - "\n * datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()", - "\n };", - "\n return iv;", - "\n }, importFormat", - "\n ).WithTarget(Workspace).ExecuteAsync();", - "\n ", - "\n HashSet availableEstimateTypes = parsingStorage.TechnicalMarginEstimateTypes;", - "\n var multipleOp = await Workspace.Query().Where(iv => availableEstimateTypes.Contains(iv.EstimateType))", - "\n .GroupBy(iv => iv.DataNode)", - "\n .Where(g => g.Count() > 1).ToArrayAsync();", - "\n //.Select(g => ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, g.Key));", - "\n ", - "\n foreach (var op in multipleOp)", - "\n ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, op.Key);", - "\n ", - "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", - "\n targetPartitionByReportingNodeAndPeriodId = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id;", - "\n return Activity.Finish().Merge(importLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9OUXaxBq9UWnDfTVkzZWxQ", - "cell_type": "markdown", - "source": [ - "## Simple Value as IfrsVariable" - ], - "metadata": {} - }, - { - "id": "LQsJefixt0iCd-c5YpFk0A", - "cell_type": "code", - "source": [ - "public async Task UploadSimpleValueAsync(string fileName)", - "\n{", - "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.SimpleValue};", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n Guid partitionId = new Guid();", - "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", - "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", - "\n ", - "\n Workspace.Query().Select(v => new {v.DataNode, v.AccidentYear}).Distinct();", - "\n ", - "\n await CommitToDatabase(partitionId, ", - "\n snapshot : true,", - "\n filter : x => Workspace.Query().Select(v => v.DataNode).Distinct().Contains(x.DataNode));", - "\n ", - "\n return Activity.Finish().Merge(parsingLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tyyiqAeFX0Gc5OKA_lmSEw", - "cell_type": "markdown", - "source": [ - "## Openings as IfrsVariable" - ], - "metadata": {} - }, - { - "id": "bkCo7-z9F0-_18aRV7Upqw", - "cell_type": "code", - "source": [ - "public async Task UploadOpeningAsync(string fileName)", - "\n{", - "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Opening};", - "\n if(Activity.HasErrors()) return Activity.Finish();", - "\n ", - "\n Guid partitionId = new Guid();", - "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", - "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", - "\n ", - "\n var storage = new ImportStorage(args, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", - "\n ", - "\n var universe = Scopes.ForStorage(storage).ToScope();", - "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", - "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", - "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", - "\n", - "\n await Workspace.UpdateAsync(ivs);", - "\n await CommitToDatabase(storage.TargetPartition, ", - "\n snapshot : true,", - "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Opening].Contains(x.EstimateType) && ", - "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode ));", - "\n", - "\n return Activity.Finish().Merge(parsingLog);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YqhevtPH3EiTicAIQesk-g", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Importer Methods

", + "\n" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ImportScopeCalculation\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Parsing Storage" + ] + }, + { + "cell_type": "code", + "source": [ + "public class ParsingStorage", + "\n{", + "\n private readonly IDataSource dataSource;", + "\n private readonly IWorkspace workspace;", + "\n private readonly ImportArgs args;", + "\n ", + "\n //Hierarchy Cache", + "\n public Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache HierarchyCache;", + "\n ", + "\n public ReportingNode ReportingNode { get; protected set; }", + "\n ", + "\n public Dictionary DataNodeDataBySystemName;", + "\n ", + "\n // Dimensions", + "\n public Dictionary CalculationType;", + "\n public Dictionary PvAmountType; ", + "\n public HashSet AocTypeMap;", + "\n private HashSet estimateTypes;", + "\n private HashSet amountTypes;", + "\n private Dictionary> amountTypesByEstimateType => GetAmountTypesByEstimateType(HierarchyCache);", + "\n public HashSet TechnicalMarginEstimateTypes => GetTechnicalMarginEstimateType(); ", + "\n public Dictionary> DimensionsWithExternalId;", + "\n ", + "\n // Partitions", + "\n public PartitionByReportingNode TargetPartitionByReportingNode;", + "\n public PartitionByReportingNodeAndPeriod TargetPartitionByReportingNodeAndPeriod;", + "\n ", + "\n //Constructor", + "\n public ParsingStorage(ImportArgs args, IDataSource dataSource, IWorkspace workspace)", + "\n {", + "\n this.args = args;", + "\n this.dataSource = dataSource;", + "\n this.workspace = workspace;", + "\n }", + "\n ", + "\n // Initialize", + "\n public async Task InitializeAsync()", + "\n {", + "\n //Partition Workspace and DataSource", + "\n TargetPartitionByReportingNode = (await workspace.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).SingleOrDefault(); ", + "\n ", + "\n if(TargetPartitionByReportingNode == null) ", + "\n { ApplicationMessage.Log(Error.ParsedPartitionNotFound, args.ReportingNode); return; } ", + "\n ", + "\n await workspace.Partition.SetAsync(TargetPartitionByReportingNode.Id);", + "\n await dataSource.Partition.SetAsync(TargetPartitionByReportingNode.Id);", + "\n ", + "\n if(args.Year != default(int) && args.Month != default(int))", + "\n {", + "\n TargetPartitionByReportingNodeAndPeriod = (await workspace.Query()", + "\n .Where(p => p.ReportingNode == args.ReportingNode &&", + "\n p.Year == args.Year &&", + "\n p.Month == args.Month &&", + "\n p.Scenario == args.Scenario).ToArrayAsync()).SingleOrDefault();", + "\n ", + "\n if(TargetPartitionByReportingNodeAndPeriod == null) ", + "\n { ApplicationMessage.Log(Error.ParsedPartitionNotFound, args.ReportingNode, args.Year.ToString(), args.Month.ToString(), args.Scenario); return; } ", + "\n ", + "\n await workspace.Partition.SetAsync(TargetPartitionByReportingNodeAndPeriod.Id);", + "\n await dataSource.Partition.SetAsync(TargetPartitionByReportingNodeAndPeriod.Id);", + "\n ", + "\n //Clean up the workspace", + "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", + "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", + "\n }", + "\n ", + "\n ReportingNode = (await dataSource.Query().Where(x => x.SystemName == args.ReportingNode).ToArrayAsync()).First();", + "\n var aocConfigurationByAocStep = await dataSource.LoadAocStepConfigurationAsync(args.Year, args.Month);", + "\n AocTypeMap = args.ImportFormat switch {", + "\n ImportFormats.Cashflow => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Cashflow) &&", + "\n !new DataType[]{DataType.Calculated, DataType.CalculatedTelescopic}.Contains(x.DataType) )", + "\n .GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", + "\n ImportFormats.Actual => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Actual) &&", + "\n !new DataType[]{DataType.Calculated, DataType.CalculatedTelescopic}.Contains(x.DataType) && ", + "\n new AocStep(x.AocType, x.Novelty) != new AocStep(AocTypes.BOP, Novelties.I))", + "\n .GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", + "\n ImportFormats.Opening => aocConfigurationByAocStep.Where(x => x.InputSource.Contains(InputSource.Opening) && x.DataType == DataType.Optional).GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).ToHashSet(),", + "\n ImportFormats.SimpleValue => aocConfigurationByAocStep.GroupBy(x => new AocStep(x.AocType, x.Novelty), (k,v) => k).Concat((await dataSource.Query().ToArrayAsync())", + "\n .Select(vt => new AocStep(vt.SystemName,null))).ToHashSet(),", + "\n _ => Enumerable.Empty().ToHashSet(),", + "\n };", + "\n ", + "\n //DataNodes", + "\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 // Dimensions", + "\n CalculationType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n PvAmountType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n amountTypes = (await dataSource.Query().ToArrayAsync()).Select(at => at.SystemName).ToHashSet();", + "\n estimateTypes = args.ImportFormat switch {", + "\n ImportFormats.SimpleValue => (await dataSource.Query().ToArrayAsync()).Select(et => et.SystemName).ToHashSet(),", + "\n ImportFormats.Opening => (await dataSource.Query().Where(et => et.StructureType == StructureType.AoC).ToArrayAsync())", + "\n .Where(et => et.InputSource.Contains(InputSource.Opening)) //This Contains overload cannot be used in DB", + "\n .Select(et => et.SystemName).ToHashSet(),", + "\n _ => Enumerable.Empty().ToHashSet(),", + "\n };", + "\n ", + "\n ", + "\n // DimensionsWithExternalId", + "\n DimensionsWithExternalId = new Dictionary>()", + "\n {", + "\n { typeof(PvAmountType), await GetDimensionWithExternalIdDictionaryAsync() },", + "\n { typeof(EstimateType), await GetDimensionWithExternalIdDictionaryAsync() }", + "\n };", + "\n ", + "\n //Hierarchy Cache", + "\n HierarchyCache = workspace.ToHierarchicalDimensionCache();", + "\n HierarchyCache.Initialize();", + "\n }", + "\n ", + "\n public async Task> GetDimensionWithExternalIdDictionaryAsync () where T : KeyedOrderedDimension", + "\n {", + "\n var dict = new Dictionary();", + "\n var items = await dataSource.Query().ToArrayAsync();", + "\n foreach (var item in items) {", + "\n dict.TryAdd(item.SystemName, item.SystemName);", + "\n if(typeof(T).IsAssignableTo(typeof(KeyedOrderedDimensionWithExternalId))) {", + "\n var externalIds = (string[])(typeof(T).GetProperty(nameof(KeyedOrderedDimensionWithExternalId.ExternalId)).GetValue(item));", + "\n if(externalIds == null) continue;", + "\n foreach (var extId in externalIds) ", + "\n dict.TryAdd(extId, item.SystemName);", + "\n }", + "\n }", + "\n return dict;", + "\n }", + "\n ", + "\n // Getters", + "\n public bool IsDataNodeReinsurance(string goc) => DataNodeDataBySystemName[goc].IsReinsurance;", + "\n public bool IsValidDataNode(string goc) => DataNodeDataBySystemName.ContainsKey(goc);", + "\n ", + "\n // Validations", + "\n public string ValidateEstimateType(string et, string goc) {", + "\n var allowedEstimateTypes = estimateTypes;", + "\n if (DataNodeDataBySystemName.TryGetValue(goc, out var dataNodeData) && dataNodeData.LiabilityType == LiabilityTypes.LIC)", + "\n estimateTypes.ExceptWith(TechnicalMarginEstimateTypes);", + "\n if(!allowedEstimateTypes.Contains(et))", + "\n ApplicationMessage.Log(Error.EstimateTypeNotFound, et);", + "\n return et;", + "\n }", + "\n ", + "\n public string ValidateAmountType(string at) {", + "\n if (at != null && !amountTypes.Contains(at))", + "\n ApplicationMessage.Log(Error.AmountTypeNotFound, at);", + "\n return at;", + "\n }", + "\n ", + "\n public AocStep ValidateAocStep(AocStep aoc) {", + "\n if (!AocTypeMap.Contains(aoc))", + "\n ApplicationMessage.Log(Error.AocTypeMapNotFound, aoc.AocType, aoc.Novelty);", + "\n return aoc;", + "\n }", + "\n ", + "\n public string ValidateDataNode(string goc) {", + "\n if (!DataNodeDataBySystemName.ContainsKey(goc))", + "\n ApplicationMessage.Log(Error.InvalidDataNode, goc);", + "\n return goc;", + "\n }", + "\n ", + "\n public void ValidateEstimateTypeAndAmountType(string estimateType, string amountType){", + "\n if (amountTypesByEstimateType.TryGetValue(estimateType, out var ats) && ats.Any() && !ats.Contains(amountType))", + "\n ApplicationMessage.Log(Error.InvalidAmountTypeEstimateType, estimateType, amountType);", + "\n }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Basics" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Clean the Database" + ] + }, + { + "cell_type": "code", + "source": [ + "async public Task CleanDatabaseAsync (Expression> filter = null) where T : class", + "\n{", + "\n var loadData = await DataSource.Query().Where(filter?? (Expression>)(x => true)).ToListAsync();", + "\n await DataSource.DeleteAsync(loadData);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "async public Task CleanDatabaseFromPartitionAsync (Guid partitionId, Func filter = null) where T : class, IPartitioned", + "\n{", + "\n var loadData = (await DataSource.Query().Where(x => x.Partition == partitionId).ToArrayAsync())", + "\n .Where(filter?? (Func)(x => true)).ToList();", + "\n await DataSource.DeleteAsync(loadData);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Update the Database" + ] + }, + { + "cell_type": "code", + "source": [ + "async public Task CommitToDatabase (Guid partitionId, bool snapshot = true, Func filter = null) where T : class, IPartitioned", + "\n{", + "\n if(snapshot) await CleanDatabaseFromPartitionAsync(partitionId, filter);", + "\n await DataSource.UpdateAsync( await Workspace.Query().ToArrayAsync() );", + "\n await DataSource.CommitAsync();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node Factory" + ] + }, + { + "cell_type": "code", + "source": [ + "// TODO: think of a better Factory to instantiate DataNode/State/Parameter simultaneously while avoiding public contructors (see Factory Patterns)", + "\n// ATTENTION: this Factory method provides default states and parameters so that it is not mandatory to import them (=> simpler calculation engine). ", + "\n// This method weakness is that these defaults aren't always replaced with the imported values, e,g, when Month > DefaultDataNodeActivationMonth.", + "\n// Therefore they will remain in the DataSource (hopefully without producing any harm).", + "\npublic async Task DataNodeFactoryAsync ()", + "\n{", + "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", + "\n var existingGroupOfContracts = await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync();", + "\n var importedGroupOfContracts = await Workspace.Query().ToArrayAsync();", + "\n var listOfPartitionsWithPeriod = new List();", + "\n ", + "\n foreach (var groupOfContract in importedGroupOfContracts)", + "\n {", + "\n var name = groupOfContract.SystemName;", + "\n if(!existingGroupOfContracts.Any(x => x.SystemName == name))", + "\n {", + "\n var state = new DataNodeState { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", + "\n var parameter = new SingleDataNodeParameter { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", + "\n await Workspace.UpdateAsync(state);", + "\n if(groupOfContract is GroupOfInsuranceContract) await Workspace.UpdateAsync(parameter);", + "\n }", + "\n }", + "\n ", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n //Hot fix: Disabling default as using Annual Cohort breakes Opening importer logic. ", + "\n //await CommitToDatabase(partition, snapshot: false);", + "\n //await CommitToDatabase(partition, snapshot: false);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Importers" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Parse and Upload: Dimensions" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDimensionsAsync (string fileName) where T: class ", + "\n{", + "\n await CleanDatabaseAsync();", + "\n var importLog = await Import.FromFile(fileName).WithType().WithTarget(DataSource).ExecuteAsync();", + "\n return importLog;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Parse Main Tab and return Args" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task GetArgsFromMainAsync(string file)", + "\n{", + "\n var extension = System.IO.Path.GetExtension(file);", + "\n var stream = await Project.FileStorage.ReadAsync(file);", + "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[Main];", + "\n ", + "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", + "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", + "\n if(ApplicationMessage.HasErrors()) return null;", + "\n ", + "\n var main = mainTab.Rows.First();", + "\n var scenario = mainTab.Columns.Where(x => x.ColumnName == nameof(PartitionByReportingNode.Scenario)).Count() > 0? ", + "\n (string)main[nameof(PartitionByReportingNode.Scenario)] : default(string);", + "\n ", + "\n var partitionName = typeof(IPartition).Name switch ", + "\n {", + "\n nameof(PartitionByReportingNode) => new ImportArgs( (string)main[nameof(PartitionByReportingNode.ReportingNode)],", + "\n default(int),", + "\n default(int),", + "\n default(Periodicity),", + "\n scenario,", + "\n default(string)),", + "\n ", + "\n nameof(PartitionByReportingNodeAndPeriod) => new ImportArgs( (string)main[nameof(PartitionByReportingNodeAndPeriod.ReportingNode)], ", + "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Year)], typeof(int)),", + "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Month)], typeof(int)),", + "\n default(Periodicity),", + "\n scenario,", + "\n default(string)),", + "\n ", + "\n _ => null", + "\n };", + "\n ", + "\n if (partitionName == null) ApplicationMessage.Log(Error.PartitionTypeNotFound, typeof(IPartition).Name); ", + "\n return partitionName;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Parse and Upload: Data Nodes" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Portfolio and Group of contract" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDataNodesToWorkspaceAsync(string fileName)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var args = await GetArgsFromMainAsync(fileName);", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var storage = new ParsingStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var errors = new List();", + "\n var importLogPortfolios = await Import.FromFile(fileName)", + "\n .WithType((dataset, datarow) => new InsurancePortfolio {", + "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = datarow.Field(nameof(DataNode.ContractualCurrency)),", + "\n FunctionalCurrency = storage.ReportingNode.Currency,", + "\n LineOfBusiness = datarow.Field(nameof(DataNode.LineOfBusiness)),", + "\n ValuationApproach = datarow.Field(nameof(DataNode.ValuationApproach)),", + "\n OciType = datarow.Field(nameof(DataNode.OciType))", + "\n })", + "\n .WithType((dataset, datarow) =>new ReinsurancePortfolio {", + "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = datarow.Field(nameof(DataNode.ContractualCurrency)),", + "\n FunctionalCurrency = storage.ReportingNode.Currency,", + "\n LineOfBusiness = datarow.Field(nameof(DataNode.LineOfBusiness)),", + "\n ValuationApproach = datarow.Field(nameof(DataNode.ValuationApproach)),", + "\n OciType = datarow.Field(nameof(DataNode.OciType))", + "\n })", + "\n .WithTarget(Workspace)", + "\n .ExecuteAsync();", + "\n ", + "\n var portfolios = await Workspace.Query().ToDictionaryAsync(x => x.SystemName);", + "\n var importLogGroupOfContracts = await Import.FromFile(fileName)", + "\n .WithType((dataset, datarow) => {", + "\n var gicSystemName = datarow.Field(nameof(DataNode.SystemName));", + "\n var pf = datarow.Field(nameof(InsurancePortfolio));", + "\n if(!portfolios.TryGetValue(pf, out var portfolioData))", + "\n {", + "\n ApplicationMessage.Log(Error.PortfolioGicNotFound, pf, gicSystemName);", + "\n return null;", + "\n }", + "\n var gic = new GroupOfInsuranceContract {", + "\n SystemName = gicSystemName,", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = portfolioData.ContractualCurrency,", + "\n FunctionalCurrency = portfolioData.FunctionalCurrency,", + "\n LineOfBusiness = portfolioData.LineOfBusiness,", + "\n ValuationApproach = portfolioData.ValuationApproach,", + "\n OciType = portfolioData.OciType,", + "\n AnnualCohort = Convert.ToInt32(datarow.Field(nameof(GroupOfContract.AnnualCohort))),", + "\n LiabilityType = datarow.Field(nameof(GroupOfContract.LiabilityType)),", + "\n Profitability = datarow.Field(nameof(GroupOfContract.Profitability)),", + "\n Portfolio = pf", + "\n };", + "\n return ExtendGroupOfContract(gic, datarow);", + "\n })", + "\n .WithType((dataset, datarow) => {", + "\n var gricSystemName = datarow.Field(nameof(DataNode.SystemName));", + "\n var pf = datarow.Field(nameof(ReinsurancePortfolio));", + "\n if(!portfolios.TryGetValue(pf, out var portfolioData))", + "\n {", + "\n ApplicationMessage.Log(Error.PortfolioGicNotFound, pf, gricSystemName);", + "\n return null;", + "\n }", + "\n var gric = new GroupOfReinsuranceContract {", + "\n SystemName = gricSystemName,", + "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n ContractualCurrency = portfolioData.ContractualCurrency,", + "\n FunctionalCurrency = portfolioData.FunctionalCurrency,", + "\n LineOfBusiness = portfolioData.LineOfBusiness,", + "\n ValuationApproach = portfolioData.ValuationApproach,", + "\n OciType = portfolioData.OciType,", + "\n AnnualCohort = Convert.ToInt32(datarow.Field(nameof(GroupOfContract.AnnualCohort))),", + "\n LiabilityType = datarow.Field(nameof(GroupOfContract.LiabilityType)),", + "\n Profitability = datarow.Field(nameof(GroupOfContract.Profitability)),", + "\n Portfolio = pf,", + "\n Partner = datarow.Field(nameof(GroupOfContract.Partner))", + "\n };", + "\n return ExtendGroupOfContract(gric, datarow);", + "\n })", + "\n .WithTarget(Workspace)", + "\n .ExecuteAsync();", + "\n ", + "\n return Activity.Finish().Merge(importLogPortfolios).Merge(importLogGroupOfContracts);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDataNodesAsync(string fileName)", + "\n{", + "\n var log = await UploadDataNodesToWorkspaceAsync(fileName);", + "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", + "\n ", + "\n await DataNodeFactoryAsync(); ", + "\n return log;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task ValidateDataNodeStatesAsync(Dictionary persistentDataNodeByDataNode)", + "\n{", + "\n foreach(var importedDataNodeState in await Workspace.Query().ToArrayAsync())", + "\n {", + "\n if(persistentDataNodeByDataNode.TryGetValue(importedDataNodeState.DataNode, out var currentPersistentDataNode))", + "\n {", + "\n if(importedDataNodeState.State < currentPersistentDataNode.State)", + "\n ApplicationMessage.Log(Error.ChangeDataNodeState, importedDataNodeState.DataNode, ", + "\n currentPersistentDataNode.State.ToString(), ", + "\n importedDataNodeState.State.ToString());", + "\n", + "\n if(importedDataNodeState.State == currentPersistentDataNode.State)", + "\n await Workspace.DeleteAsync(importedDataNodeState);", + "\n }", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeStateToWorkspaceAsync(string fileName)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", + "\n ", + "\n Activity.Start();", + "\n var args = await GetArgsFromMainAsync(fileName);", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var storage = new ParsingStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var importLog = await Import.FromFile(fileName).WithType(", + "\n (dataset, datarow) => new DataNodeState {", + "\n DataNode = datarow.Field(nameof(DataNodeState.DataNode)),", + "\n State = (State)Enum.Parse(typeof(State), datarow.Field(nameof(DataNodeState.State))),", + "\n Year = args.Year,", + "\n Month = args.Month,", + "\n Partition = storage.TargetPartitionByReportingNode.Id", + "\n }", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n", + "\n await ValidateDataNodeStatesAsync(storage.DataNodeDataBySystemName);", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeStateAsync(string fileName)", + "\n{", + "\n var log = await UploadDataNodeStateToWorkspaceAsync(fileName);", + "\n await CommitToDatabase((Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode)), snapshot: false); ", + "\n return log;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### DataNode Parameters" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeParameterToWorkspaceAsync(string fileName, Guid targetPartitionByReportingNodeId)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", + "\n ", + "\n Activity.Start();", + "\n var args = await GetArgsFromMainAsync(fileName) with {ImportFormat = ImportFormats.DataNodeParameter};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var storage = new ParsingStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var singleDataNode = new List();", + "\n var interDataNode = new List<(string,string)>();", + "\n ", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType( (dataset, datarow) => {", + "\n", + "\n //read and validate DataNodes", + "\n var dataNode = datarow.Field(nameof(DataNode));", + "\n if(!storage.IsValidDataNode(dataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, dataNode); return null; }", + "\n", + "\n //check for duplicates", + "\n if(singleDataNode.Contains(dataNode)) { ApplicationMessage.Log(Error.DuplicateSingleDataNode, dataNode); return null; }", + "\n singleDataNode.Add(dataNode);", + "\n ", + "\n //Instantiate SingleDataNodeParameter", + "\n return new SingleDataNodeParameter {", + "\n Year = args.Year,", + "\n Month = args.Month,", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n", + "\n DataNode = dataNode,", + "\n PremiumAllocation = (datarow.Field(nameof(SingleDataNodeParameter.PremiumAllocation)))", + "\n .ToString().CheckStringForExponentialAndConvertToDouble(),", + "\n };", + "\n })", + "\n .WithType( (dataset, datarow) => {", + "\n", + "\n //read and validate DataNodes", + "\n var dataNode = datarow.Field(nameof(InterDataNodeParameter.DataNode));", + "\n if(!storage.IsValidDataNode(dataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, dataNode); return null; }", + "\n", + "\n var linkedDataNode = datarow.Field(nameof(InterDataNodeParameter.LinkedDataNode));", + "\n if(!storage.IsValidDataNode(linkedDataNode)) { ApplicationMessage.Log(Error.InvalidDataNode, linkedDataNode); return null; }", + "\n var dataNodes = new string[]{dataNode, linkedDataNode}.OrderBy(x => x).ToArray();", + "\n", + "\n //validate ReinsuranceGross Link", + "\n var isDn1Reinsurance = storage.IsDataNodeReinsurance(dataNodes[0]);", + "\n var isDn2Reinsurance = storage.IsDataNodeReinsurance(dataNodes[1]);", + "\n var isGrossReinsuranceLink = (isDn1Reinsurance && !isDn2Reinsurance) != (!isDn1Reinsurance && isDn2Reinsurance);", + "\n var reinsCov = (datarow.Field(nameof(InterDataNodeParameter.ReinsuranceCoverage)))", + "\n .ToString().CheckStringForExponentialAndConvertToDouble();", + "\n if(!isGrossReinsuranceLink && Math.Abs(reinsCov) > Precision )", + "\n ApplicationMessage.Log(Error.ReinsuranceCoverageDataNode, dataNodes[0], dataNodes[1]); // TODO: is this error or warning?", + "\n", + "\n //check for duplicates", + "\n if(interDataNode.Contains((dataNodes[0], dataNodes[1])) || interDataNode.Contains((dataNodes[1], dataNodes[0])))", + "\n ApplicationMessage.Log(Error.DuplicateInterDataNode, dataNodes[0], dataNodes[1]); // TODO: is this error or warning?", + "\n", + "\n interDataNode.Add((dataNodes[0], dataNodes[1])); ", + "\n //Instantiate InterDataNodeParameter", + "\n return new InterDataNodeParameter {", + "\n Year = args.Year,", + "\n Month = args.Month,", + "\n Partition = storage.TargetPartitionByReportingNode.Id,", + "\n DataNode = dataNodes[0],", + "\n LinkedDataNode = dataNodes[1],", + "\n ReinsuranceCoverage = reinsCov,", + "\n };", + "\n })", + "\n .WithTarget(Workspace)", + "\n .ExecuteAsync();", + "\n ", + "\n targetPartitionByReportingNodeId = storage.TargetPartitionByReportingNode.Id;", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadDataNodeParameterAsync(string fileName)", + "\n{", + "\n Guid partitionId = new Guid();", + "\n var log = await UploadDataNodeParameterToWorkspaceAsync(fileName, partitionId);", + "\n ", + "\n await CommitToDatabase(partitionId, snapshot: false);", + "\n await CommitToDatabase(partitionId, snapshot: false); ", + "\n ", + "\n return log;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Parse and Upload: Variables" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Validation for Active Data Node States" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task ValidateForDataNodeStateActiveAsync(Dictionary dataNodes) where T : BaseDataRecord", + "\n{ ", + "\n foreach(var item in (await Workspace.Query().ToArrayAsync()).GroupBy(x => x.DataNode))", + "\n if(!dataNodes.ContainsKey(item.First().DataNode))", + "\n ApplicationMessage.Log(Error.InactiveDataNodeState, item.First().DataNode);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Cashflow as Raw Variable and Ifrs Variable" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task ParseCashflowsToWorkspaceAsync(string fileName, ImportArgs args)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", + "\n await parsingStorage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType ( (dataset, datarow) => {", + "\n var aocType = datarow.Field(nameof(RawVariable.AocType));", + "\n var novelty = datarow.Field(nameof(RawVariable.Novelty));", + "\n var dataNode = datarow.Field(nameof(DataNode));", + "\n ", + "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", + "\n ApplicationMessage.Log(Error.InvalidDataNode, dataNode);", + "\n return null;", + "\n }", + "\n ", + "\n // Error if AocType is not present in the mapping", + "\n if(!parsingStorage.AocTypeMap.Contains(new AocStep(aocType, novelty))) {", + "\n ApplicationMessage.Log(Error.AocTypeMapNotFound, aocType, novelty);", + "\n return null;", + "\n }", + "\n ", + "\n // Filter out cashflows for DataNode that were created in the past and are still active and come with AocType = BOPI", + "\n if(dataNodeData.Year < args.Year && aocType == AocTypes.BOP && novelty == Novelties.I) {", + "\n ApplicationMessage.Log(Warning.ActiveDataNodeWithCashflowBOPI);", + "\n return null;", + "\n }", + "\n ", + "\n var amountTypeFromFile = datarow.Field(nameof(RawVariable.AmountType));", + "\n var isCalculationType = parsingStorage.CalculationType.ContainsKey(amountTypeFromFile);", + "\n var amountType = isCalculationType ? null : amountTypeFromFile;", + "\n var calculationType = isCalculationType ? amountTypeFromFile : CalculationTypes.BE;", + "\n ", + "\n var values = datarow.Table.Columns.Where(c => c.ColumnName.StartsWith(nameof(RawVariable.Values))).OrderBy(c => c.ColumnName.Length).ThenBy(c => c.ColumnName)", + "\n .Select(x => datarow.Field(x.ColumnName).CheckStringForExponentialAndConvertToDouble()).Prune();", + "\n ", + "\n // Filter out empty raw variables for AocType != CL", + "\n if(values.Length == 0 && aocType != AocTypes.CL) return null; //TODO: extend this check for all mandatory step and not just for CL", + "\n ", + "\n var item = new RawVariable {", + "\n DataNode = dataNode,", + "\n AocType = aocType,", + "\n Novelty = novelty,", + "\n AmountType = amountType,", + "\n CalculationType = calculationType,", + "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(RawVariable.AccidentYear))), out var tempVal)? tempVal : (int?)null,", + "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", + "\n Values = Multiply(GetSign((aocType, amountType, calculationType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), values)", + "\n };", + "\n return item;", + "\n }, ImportFormats.Cashflow", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n ", + "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadCashflowsAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Cashflow};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(fileName, args);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var storage = new ImportStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var universe = Scopes.ForStorage(storage).ToScope();", + "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", + "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n await Workspace.UpdateAsync(ivs);", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true, ", + "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Cashflow].Contains(x.EstimateType) && ", + "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode)); ", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true,", + "\n filter : x => storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", + "\n", + "\n return Activity.Finish().Merge(parsingLog); ", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Actuals as Ifrs Variable" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task ParseActualsToWorkspaceAsync(string fileName, ImportArgs args)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", + "\n await parsingStorage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType ( (dataset, datarow) => {", + "\n var dataNode = datarow.Field(nameof(DataNode));", + "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", + "\n ApplicationMessage.Log(Error.InvalidDataNode, dataNode);", + "\n return null;", + "\n }", + "\n ", + "\n var valueType = datarow.Field(ValueType);", + "\n if(valueType == null) { ", + "\n ApplicationMessage.Log(Error.ValueTypeNotFound); ", + "\n return null; ", + "\n }", + "\n ", + "\n var amountType = parsingStorage.DimensionsWithExternalId[typeof(PvAmountType)].TryGetValue(valueType, out var at)? at : null;", + "\n var isStdActual = parsingStorage.PvAmountType.ContainsKey(valueType);", + "\n var estimateType = isStdActual? EstimateTypes.A : parsingStorage.DimensionsWithExternalId[typeof(EstimateType)].TryGetValue(valueType, out var et)? et : null;", + "\n if(estimateType == null || amountType == null) { ", + "\n ApplicationMessage.Log(Error.ValueTypeNotValid, valueType);", + "\n return null;", + "\n }", + "\n ", + "\n var aocType = datarow.Field(nameof(IfrsVariable.AocType));", + "\n if((!isStdActual && aocType != AocTypes.CF && aocType != AocTypes.WO) || (isStdActual && aocType != AocTypes.CF) ) {", + "\n ApplicationMessage.Log(Error.AocTypeNotValid, aocType);", + "\n return null;", + "\n }", + "\n ", + "\n var item = new IfrsVariable {", + "\n DataNode = dataNode,", + "\n AocType = aocType,", + "\n Novelty = Novelties.C,", + "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(IfrsVariable.AccidentYear))), out var tempAccYear)? tempAccYear : (int?)null,", + "\n AmountType = amountType,", + "\n EstimateType = estimateType,", + "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", + "\n Value = Multiply(GetSign((aocType, amountType, estimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()),", + "\n };", + "\n return item;", + "\n }, ImportFormats.Actual", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n ", + "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadActualAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Actual};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n", + "\n var parsingLog = await ParseActualsToWorkspaceAsync(fileName, args);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n var storage = new ImportStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n var universe = Scopes.ForStorage(storage).ToScope();", + "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", + "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n await Workspace.UpdateAsync(ivs);", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true, ", + "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Actual].Contains(x.EstimateType) && ", + "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", + "\n", + "\n return Activity.Finish().Merge(parsingLog);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Simple Value Import" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Simple Value to Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task ParseSimpleValueToWorkspaceAsync(string fileName, ImportArgs args, Guid targetPartitionByReportingNodeAndPeriodId)", + "\n{", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n ", + "\n Activity.Start();", + "\n var importFormat = args.ImportFormat;", + "\n var parsingStorage = new ParsingStorage(args, DataSource, Workspace);", + "\n await parsingStorage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish(); ", + "\n", + "\n var importLog = await Import.FromFile(fileName)", + "\n .WithType ( (dataset, datarow) => {", + "\n var dataNode = parsingStorage.ValidateDataNode(datarow.Field(nameof(DataNode)));", + "\n var amountType = parsingStorage.ValidateAmountType(datarow.Field(nameof(IfrsVariable.AmountType)));", + "\n var estimateType = parsingStorage.ValidateEstimateType(datarow.Field(nameof(IfrsVariable.EstimateType)), dataNode); //TODO LIC/LRC dependence", + "\n var aocStep = importFormat == ImportFormats.SimpleValue ", + "\n ? parsingStorage.ValidateAocStep(new AocStep (datarow.Field(nameof(IfrsVariable.AocType)), ", + "\n datarow.Field(nameof(IfrsVariable.Novelty))))", + "\n : new AocStep(AocTypes.BOP, Novelties.I);", + "\n var economicBasis = importFormat == ImportFormats.SimpleValue ", + "\n ? datarow.Field(nameof(IfrsVariable.EconomicBasis)) ", + "\n : null;", + "\n ", + "\n parsingStorage.ValidateEstimateTypeAndAmountType(estimateType, amountType);", + "\n ", + "\n var iv = new IfrsVariable {", + "\n DataNode = dataNode,", + "\n AocType = aocStep.AocType,", + "\n Novelty = aocStep.Novelty,", + "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(IfrsVariable.AccidentYear))), out var accidentYear) ? accidentYear : (int?)null,", + "\n AmountType = amountType,", + "\n EstimateType = estimateType,", + "\n EconomicBasis = economicBasis,", + "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", + "\n Value = GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", + "\n * datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()", + "\n };", + "\n return iv;", + "\n }, importFormat", + "\n ).WithTarget(Workspace).ExecuteAsync();", + "\n ", + "\n HashSet availableEstimateTypes = parsingStorage.TechnicalMarginEstimateTypes;", + "\n var multipleOp = await Workspace.Query().Where(iv => availableEstimateTypes.Contains(iv.EstimateType))", + "\n .GroupBy(iv => iv.DataNode)", + "\n .Where(g => g.Count() > 1).ToArrayAsync();", + "\n //.Select(g => ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, g.Key));", + "\n ", + "\n foreach (var op in multipleOp)", + "\n ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, op.Key);", + "\n ", + "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", + "\n targetPartitionByReportingNodeAndPeriodId = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id;", + "\n return Activity.Finish().Merge(importLog);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Simple Value as IfrsVariable" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadSimpleValueAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.SimpleValue};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n Guid partitionId = new Guid();", + "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n Workspace.Query().Select(v => new {v.DataNode, v.AccidentYear}).Distinct();", + "\n ", + "\n await CommitToDatabase(partitionId, ", + "\n snapshot : true,", + "\n filter : x => Workspace.Query().Select(v => v.DataNode).Distinct().Contains(x.DataNode));", + "\n ", + "\n return Activity.Finish().Merge(parsingLog);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Openings as IfrsVariable" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task UploadOpeningAsync(string fileName)", + "\n{", + "\n Activity.Start();", + "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Opening};", + "\n if(Activity.HasErrors()) return Activity.Finish();", + "\n ", + "\n Guid partitionId = new Guid();", + "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", + "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var storage = new ImportStorage(args, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n ", + "\n var universe = Scopes.ForStorage(storage).ToScope();", + "\n var identities = universe.GetScopes(storage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);", + "\n var ivs = universe.GetScopes(identities).SelectMany(x => x.CalculatedIfrsVariables);", + "\n if(Activity.HasErrors()) return Activity.Finish().Merge(parsingLog);", + "\n", + "\n await Workspace.UpdateAsync(ivs);", + "\n await CommitToDatabase(storage.TargetPartition, ", + "\n snapshot : true,", + "\n filter : x => storage.EstimateTypesByImportFormat[ImportFormats.Opening].Contains(x.EstimateType) && ", + "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode ));", + "\n", + "\n return Activity.Finish().Merge(parsingLog);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Initialization/InitSystemorphBaseToMemory.ipynb b/Initialization/InitSystemorphBaseToMemory.ipynb index 25f07ab0..097ddb40 100644 --- a/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/Initialization/InitSystemorphBaseToMemory.ipynb @@ -1,268 +1,190 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "IsXau2AxIU6GrqDFBctd_g", - "cell_type": "markdown", - "source": [ - "

In Memory Initialization of unconfigured DataSource

", - "\n

Reference Data and DataNode

", - "\n", - "\n" - ], - "metadata": {} - }, - { - "id": "7UYbILtPnkuX3ekPtoWAWA", - "cell_type": "code", - "source": [ - "#!import \"../Import/Importers\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "X1GMcf7BW0mzdwq86kKuRQ", - "cell_type": "markdown", - "source": [ - "# Set default DataSource" - ], - "metadata": {} - }, - { - "id": "fVAqI420SkWAgNT6ijl6Fg", - "cell_type": "code", - "source": [ - "await DataSource.SetAsync();", - "\nDataSource.Reset(x => x.ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "82iGxa0-z0StnHV9TIuQDQ", - "cell_type": "markdown", - "source": [ - "# Initialize Workspace" - ], - "metadata": {} - }, - { - "id": "t74nFVf0AkOncugJ2F8jUQ", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "K898FO9wPUmvy-obSQrJ3Q", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QppbRvo4lUWN-7dYzi7zqw", - "cell_type": "markdown", - "source": [ - "# Import Dimensions, Partitions" - ], - "metadata": {} - }, - { - "id": "4T9Mtqgv8kuSz7Ro7CfcOw", - "cell_type": "code", - "source": [ - "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithTarget(DataSource)", - "\n .ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DCmPy2JDPEqrwPZceL6ncA", - "cell_type": "code", - "source": [ - "await Import.FromFile(\"../Files/300.ReportingNodes/ReportingNodes.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pg7FYVPT8E-V8CHNAvl1Wg", - "cell_type": "code", - "source": [ - "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", - "\n .WithType()", - "\n .WithType()", - "\n .WithTarget(DataSource)", - "\n .ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RxTzyhca0kSB8pMpuzIcug", - "cell_type": "markdown", - "source": [ - "# Import Parameters" - ], - "metadata": {} - }, - { - "id": "zVvAMvAHzEWwm2mzvadTng", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KdJRkfTVH0KUAXsSPQetHg", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oxIQKMoo5UqjKAtjcdn32Q", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4CDsZoshXE6BZbDJYoXD_w", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uu3vipnW30CDEQcLQ1ezyA", - "cell_type": "markdown", - "source": [ - "# Import DataNodes and DataNodeParameters" - ], - "metadata": {} - }, - { - "id": "DzfZozeHJk-8yJ_uH5jKUA", - "cell_type": "code", - "source": [ - "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "A8AUrboHqESmsdhkjXLh_Q", - "cell_type": "code", - "source": [ - "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "p1m4aehU1kSmNpWDzIpE0A", - "cell_type": "code", - "source": [ - "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pEqNN1RpCkSiVxiqryS-vQ", - "cell_type": "markdown", - "source": [ - "# Reset Workspace" - ], - "metadata": {} - }, - { - "id": "pqpb7AWAy06nubi3ydQCPA", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Uc9njlRC-kiAccvmjSF5xw", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

In Memory Initialization of unconfigured DataSource

", + "\n

Reference Data and DataNode

", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Import/Importers\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Set default DataSource" + ] + }, + { + "cell_type": "code", + "source": [ + "await DataSource.SetAsync();", + "\nDataSource.Reset(x => x.ResetCurrentPartitions());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Initialize Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Dimensions, Partitions" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/300.ReportingNodes/ReportingNodes.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Parameters" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import DataNodes and DataNodeParameters" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Initialization/InitSystemorphToDatabase.ipynb b/Initialization/InitSystemorphToDatabase.ipynb index 862b85ef..8dba5617 100644 --- a/Initialization/InitSystemorphToDatabase.ipynb +++ b/Initialization/InitSystemorphToDatabase.ipynb @@ -1,314 +1,216 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "Cy8T4hrL4kO_Gfnm6Z5XTg", - "cell_type": "markdown", - "source": [ - "

Physical Database Initialization

" - ], - "metadata": {} - }, - { - "id": "TW3qAJFbN0GzvfZswIQD9g", - "cell_type": "code", - "source": [ - "#!import \"../Database/Configure\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WW6qYyWLN0CDzizR6oTSFw", - "cell_type": "code", - "source": [ - "#!import \"../Import/Importers\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MKwi685La0Shl61un7unGg", - "cell_type": "markdown", - "source": [ - "# Initialize Workspace" - ], - "metadata": {} - }, - { - "id": "19uyY1p_DEafziYCP4_ajg", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VaUXNeTpnkqp4qvlkZT1tA", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ujiYx54U70a1Lk7al17aNQ", - "cell_type": "markdown", - "source": [ - "# Import Dimensions, Partitions" - ], - "metadata": {} - }, - { - "id": "iHL9ANV_7EqKGUtvOzgh9A", - "cell_type": "code", - "source": [ - "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithType()", - "\n .WithTarget(DataSource)", - "\n .ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WITsBPPMmkapIKK3ocjeCA", - "cell_type": "code", - "source": [ - "await Import.FromFile(\"../Files/300.ReportingNodes/ReportingNodes.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UBG4zPFBzEGM9I8BwyLHBg", - "cell_type": "code", - "source": [ - "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", - "\n .WithType()", - "\n .WithType()", - "\n .WithTarget(DataSource)", - "\n .ExecuteAsync()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "x_FX7ZmdQkqPWJ_8inZXIg", - "cell_type": "markdown", - "source": [ - "# Import Parameters" - ], - "metadata": {} - }, - { - "id": "OecjLAV7AkiT3KhjiiJnog", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Ii5PJHvCl0Cx2m89VaFSQg", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XRyJuiNql0mkE-hZETImsg", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bGA-LWJqmUmMqydPlYBymQ", - "cell_type": "code", - "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UzoF3kC3bkSV0tPlgFIH4Q", - "cell_type": "markdown", - "source": [ - "# Import DataNodes and DataNodeParameters" - ], - "metadata": {} - }, - { - "id": "7D_GmV2jsUa_BlNeRX202w", - "cell_type": "code", - "source": [ - "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BNrbXnwP-USpPbMvCQJkQw", - "cell_type": "code", - "source": [ - "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Gbq1iNgL5ku27G-9ZCDgyw", - "cell_type": "code", - "source": [ - "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mIAgGfevFkSw8FcNW7S_Dw", - "cell_type": "markdown", - "source": [ - "# Import Cashflow and Actuals" - ], - "metadata": {} - }, - { - "id": "Dx3T6KwOi0-h1_MxtEvu0Q", - "cell_type": "code", - "source": [ - "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7rQXgufixki5Mr5wvIqvmg", - "cell_type": "code", - "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9teVf5xzQ0Gkra1zUNiPVw", - "cell_type": "code", - "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "teSj9-cIHEKxQBYlxrSUaw", - "cell_type": "code", - "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "eopo9jQQJECpkYPGIcToIg", - "cell_type": "code", - "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "I9rluX4YaE2AXRNtnwzghw", - "cell_type": "markdown", - "source": [ - "# Reset Workspace" - ], - "metadata": {} - }, - { - "id": "vjYLEV52S0yEzRX-hbQu5g", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CQDkkzwLSUi-ZedmBK9uVg", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Physical Database Initialization

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Database/Configure\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Import/Importers\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Initialize Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules());" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Dimensions, Partitions" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/300.ReportingNodes/ReportingNodes.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\")", + "\n .WithType()", + "\n .WithType()", + "\n .WithTarget(DataSource)", + "\n .ExecuteAsync()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Parameters" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import DataNodes and DataNodeParameters" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Cashflow and Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Initialization/InitSystemorphToMemory.ipynb b/Initialization/InitSystemorphToMemory.ipynb index 211f88c1..80f655a5 100644 --- a/Initialization/InitSystemorphToMemory.ipynb +++ b/Initialization/InitSystemorphToMemory.ipynb @@ -1,147 +1,101 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "p3DIOKsMYUawUuOBORa9iQ", - "cell_type": "markdown", - "source": [ - "

In Memory Initialization of unconfigured DataSource

", - "\n", - "\n" - ], - "metadata": {} - }, - { - "id": "M0C3GJVwOkKVrGYTzCLVXw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ekrl841-jk6Qu-cUbOdg9g", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "55NcBpz1JU2BhAj8tZAtbg", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oSjApvqd006sATOwdgj9fA", - "cell_type": "markdown", - "source": [ - "# Import of Transactional Data" - ], - "metadata": {} - }, - { - "id": "_44_VnWkr0KGvFIltkjYlw", - "cell_type": "code", - "source": [ - "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-lteFKun20qSXUvjgV0Rtw", - "cell_type": "code", - "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "eZ5TTE-VyEqMqe4FJhoSxw", - "cell_type": "code", - "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wvXE8jKoiE6GQKf0u2Ja5g", - "cell_type": "code", - "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "y-vXTvD7pEuT7CEINzNlxg", - "cell_type": "code", - "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CFPyThMEyUSs9Z01gQRMXg", - "cell_type": "markdown", - "source": [ - "# Reset Workspace" - ], - "metadata": {} - }, - { - "id": "6BRncOutP0KF8VwCVa1jYw", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qQmhez-Ep0G2G01ULLKy-g", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

In Memory Initialization of unconfigured DataSource

", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import of Transactional Data" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" + ] + }, + { + "cell_type": "code", + "source": [ + "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Reset Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/InputFormatDescription.ipynb b/InputFormatDescription.ipynb index edb44e59..02152194 100644 --- a/InputFormatDescription.ipynb +++ b/InputFormatDescription.ipynb @@ -1,113 +1,101 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "l1JMz4NpDU2Lk2MWRSzYLA", - "cell_type": "markdown", - "source": [ - "

Structure of the Cashflows, Actuals and Openings Files

", - "\n", - "\nThis Notebook documents the structure of Cashflows, Actuals and Opening input files.", - "\n", - "\n", - "\n# The Cashflows File Structure ", - "\n", - "\n", - "\n
" - ], - "metadata": {} - }, - { - "id": "EHUOzfMOXkWnTeS5CUKVRg", - "cell_type": "markdown", - "source": [ - "A cashflow file is named **NominalCashflows** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Cashflow**.", - "\n", - "\nThe **Main** section contains information such as: Reporting Node, Year, Month and Scenario for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partitions) to which the data belongs.", - "\n", - "\nThe **Cashflow** section contains the cash flow data. Several pieces of information are required to characterize a cash flow correctly:", - "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", - "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", - "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", - "\n- [Novelty](./DataModel/DataStructure#novelty) : entered with its SystemName,", - "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims.", - "\n", - "\nAll valid combinations of AocType and Novelty can be found in [AocConfiguration](./DataModel/DataStructure#aoc-configuration) with DataType Optional or Mandatory.", - "\n
The cash flow is entered in the columns named ValuesN where N goes from 0 to the lenght of cash flow. The Value0 corresponds to January of the Year entered in the **Main** section for every combination of AocType and Novelty. " - ], - "metadata": {} - }, - { - "id": "--aqUDIEv0Cij8PWGTssJg", - "cell_type": "markdown", - "source": [ - "", - "\n# The Actuals File Structure ", - "\n", - "\n", - "\n
" - ], - "metadata": {} - }, - { - "id": "auImDZLVDEy-rTLf8gfd_w", - "cell_type": "markdown", - "source": [ - "An Actuals file is named **Actuals** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Actual**.", - "\n", - "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", - "\n", - "\nThe **Actual** section contains the actuals data. Several pieces of information are required to to characterize an Actuals amount correctly:", - "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", - "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", - "\n- [ValueType](./DataModel/DataStructure#amount-type) : corresponds to AmountType SystemName extended with the ExternalId,", - "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." - ], - "metadata": {} - }, - { - "id": "7spVD7c5bkejHCPT5UwVTQ", - "cell_type": "markdown", - "source": [ - "", - "\n# The Openings File Structure ", - "\n", - "\n", - "\n
" - ], - "metadata": {} - }, - { - "id": "xvO-5fBVq0CNPmlNpqDGsw", - "cell_type": "markdown", - "source": [ - "An Openings file is named **Openings** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Opening**. In an AoC for one period, we only need one file with the year/month combination of the beginning of the period. Some GICs do not need any entries in Openings.", - "\n", - "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", - "\n", - "\nThe **Opening** section contains values at opening of an analysis. Several pieces of information are required to to characterize an Opening amount correctly:", - "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", - "\n- [EstimateType](./DataModel/DataStructure#estimate-type) : entered with its SystemName,", - "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", - "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." - ], - "metadata": {} - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Structure of the Cashflows, Actuals and Openings Files

", + "\n", + "\nThis Notebook documents the structure of Cashflows, Actuals and Opening input files.", + "\n", + "\n", + "\n# The Cashflows File Structure ", + "\n", + "\n", + "\n
" + ] + }, + { + "cell_type": "markdown", + "source": [ + "A cashflow file is named **NominalCashflows** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Cashflow**.", + "\n", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month and Scenario for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partitions) to which the data belongs.", + "\n", + "\nThe **Cashflow** section contains the cash flow data. Several pieces of information are required to characterize a cash flow correctly:", + "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", + "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", + "\n- [Novelty](./DataModel/DataStructure#novelty) : entered with its SystemName,", + "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims.", + "\n", + "\nAll valid combinations of AocType and Novelty can be found in [AocConfiguration](./DataModel/DataStructure#aoc-configuration) with DataType Optional or Mandatory.", + "\n
The cash flow is entered in the columns named ValuesN where N goes from 0 to the lenght of cash flow. The Value0 corresponds to January of the Year entered in the **Main** section for every combination of AocType and Novelty. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# The Actuals File Structure ", + "\n", + "\n", + "\n
" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An Actuals file is named **Actuals** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Actual**.", + "\n", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", + "\n", + "\nThe **Actual** section contains the actuals data. Several pieces of information are required to to characterize an Actuals amount correctly:", + "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", + "\n- [ValueType](./DataModel/DataStructure#amount-type) : corresponds to AmountType SystemName extended with the ExternalId,", + "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# The Openings File Structure ", + "\n", + "\n", + "\n
" + ] + }, + { + "cell_type": "markdown", + "source": [ + "An Openings file is named **Openings** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Opening**. In an AoC for one period, we only need one file with the year/month combination of the beginning of the period. Some GICs do not need any entries in Openings.", + "\n", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", + "\n", + "\nThe **Opening** section contains values at opening of an analysis. Several pieces of information are required to to characterize an Opening amount correctly:", + "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [EstimateType](./DataModel/DataStructure#estimate-type) : entered with its SystemName,", + "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", + "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." + ] + } + ] } \ No newline at end of file diff --git a/OverviewCalculationEngine.ipynb b/OverviewCalculationEngine.ipynb index 8fe93bea..db79df0c 100644 --- a/OverviewCalculationEngine.ipynb +++ b/OverviewCalculationEngine.ipynb @@ -1,258 +1,228 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "n-YC5c-J-Uq-NYiRZe6gCg", - "cell_type": "markdown", - "source": [ - "

IFRS17 Calculation Engine - an Overview

" - ], - "metadata": {} - }, - { - "id": "Z0Z4HkpVQUWm6q2GfAjRhg", - "cell_type": "markdown", - "source": [ - "Version of 01 Sep 2022" - ], - "metadata": {} - }, - { - "id": "YvapB2YH1029s0tnPiMdjg", - "cell_type": "markdown", - "source": [ - "# Introduction", - "\n", - "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key inpute: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", - "\n", - "\nThis notebook provides an **overview** of Systemorph's IFRS 17 Calculation Engine with brief introductions to all the main steps.", - "\n", - "\nThere are numerous **links** to several notebooks of the Calculation Engine. These notebooks contain specifications, code and also some detailed explanations with formulas in markdown blocks. The most important ones in this respect are [DataModel/DataStructure](./DataModel/DataStructure#data-structure), [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) and [ReportScopes](./Report/ReportScopes#report-scopes)." - ], - "metadata": {} - }, - { - "id": "3xZL2IO6zkqknoPSVOK6AA", - "cell_type": "markdown", - "source": [ - "", - "\n# IFRS 17", - "\n", - "\nIFRS 17 is a new accounting standard for insurance contracts. The previous standard IFRS 4, which is based on nominal accounting, is replaced by the economic accounting standard IFRS 17.", - "\n", - "\nExplanatory **videos** on **IFRS 17** and a **demo application** can be found on Systemorph's website. Some key points are repeated here briefly.", - "\n", - "\nIFRS 17 deals with insurance contracts which are on the liability side of the balance sheet. Other accounting standards deal with other parts of the business, primarily IFRS 9 for invested assets.", - "\n", - "\nInsurance policies need to be allocated to homogeneous groups of insurance contracts (GICs) according to high-level principles established by the IFRS 17 standard, such as contract type, line of business, annual cohort etc. Insurers have some degree of freedom to optmize those GICs, as long as they respect the high-level principles.", - "\n", - "\nInsurance contracts generate different types of cashflows. For example, **Amount Type** is a dimension refering to premiums, claims, expenses of different kinds, etc. for these cashflows. The Calculation Engine presented here expects input files of all the projected cashflows for each GIC, for different regular time points (quarterly or monthly, ...) and corresponding actual amounts observed for a given period. ", - "\n", - "\nEach cashflow is characterized by all the necessary attributes: business unit, start time, amount type, novelty of business etc. and projected cashflow amounts in a regular time grid until the final run-off of all contracts.", - "\n", - "\nIf the entered cashflows are nominal (the usual case), the the present value (PV) of each cashflow is computed using proper yield curves for discounting.", - "\n", - "\nA central element of IFRS 17 is the Analysis of Change (AoC). The present value of the business (future cashflows) changes from the beginning to the end of the accounting period due to different effects, each of them constituting a modeled AoC step.", - "\n", - "\nIn IFRS 17, the value of future profitable business has a component called the Contractual Service Margin (CSM), defined at GIC level. The profit measured as CSM is recognized slowly over time rather than immediately in financial performance statements. On the other hand, a GIC can be onerous and produce a Loss Component (LC) instead, which needs to be recognized immediately.", - "\n", - "\nSeveral reports on the valuation of cashflows, balance sheet and financial performance can be produced, each dealing with different aspects, such as", - "\n - Present Value of Future Cash Flows (PVFCF)", - "\n - Contractual Service Margin (CSM) and Loss Component (LC)", - "\n - Liability for Remaining Coverage (LRC)", - "\n - Liability for Incurred Claims (LIC)", - "\n - Financial Performance", - "\n - Accounting Events" - ], - "metadata": {} - }, - { - "id": "LcfKBqhuPEe9gyQfTle0Qg", - "cell_type": "markdown", - "source": [ - "", - "\n# Data Model, Data Input, Data Import", - "\n", - "\nThe IFRS 17 calculations are based on a well-defined **data model**. The data input files are set up according to the data model, and the data import and all the ensuing calculations up to the final report generation respect the data model.", - "\n", - "\nInput files as listed below are used to provide the necessary information on the business to be modeled. These files are part of the IFRS 17 Calculation Engine and can be used as templates for users intending to model their own business and adapt some files accordingly. ", - "\n", - "\nThe IFRS 17 calculations start by importing the data input files, and the more complex logic of the IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." - ], - "metadata": {} - }, - { - "id": "E1xdnYPKM0u0NqVxOjLBJw", - "cell_type": "markdown", - "source": [ - "", - "\n## Data Model", - "\n", - "\nThe data model includes the definition of reporting nodes and dimensions to be used, including identities, amount types, group of insurance contracts and many more.", - "\n", - "\nThe notebook [DataModel/DataStructure](./DataModel/DataStructure#data-structure) defines the data records, dimensions and interfaces of the data model. There is a long section on the many [dimensions](./DataModel/DataStructure#dimensions) used to characterize the business and its IFRS 17 model.", - "\n", - "\nThe [input files](#data-input-dim-nodes) ReportingNodes and especially DimensionsAndPartitions provide an overview of data structures actually used. Some dimensions are hierarchical, so some entries have parent entries.", - "\n", - "\nMany abbreviations and acronyms used later in the documentation and the code are the **system names**, where the corresponding display names can be found together with the attributes." - ], - "metadata": {} - }, - { - "id": "GGqaecTDuE6XUrAnYdsG-g", - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Reporting nodes, dimensions and partitions", - "\n", - "\nSee folders *Files* (DimensionsAndPartitions) and *Files/300.ReportingNodes* (ReportingNodes).", - "\n- **ReportingNodes**: List of business units, often per country, with system name and display name, currency and \"G\" for the whole group", - "\n- **DimensionsAndPartitions**: The many dimensions (21) required to characterize all of the data and results, with system names and display names. This information is quite stable, but some information related to partitions refers to the reporting nodes " - ], - "metadata": {} - }, - { - "id": "LhUX4L3Xc0C0rq4_Y9J6qQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Groups of insurance and reinsurance contracts", - "\n", - "\nSee folder Files/700.DataNodes. The information is about data nodes, that is Groups of Insurance Contracts (GICs) and Groups of Reinsurance Contracts (GRICs) and portfolios of these.", - "\n- **DataNodes**: List of all GICs and GRICs, each with several attributes and the portfolios to which they belong; an additional attribute of GRICs being the reinsurance partner", - "\n- **DataNodeParameters** *\\_* *\\_* *\\_*: List of those GICs and GRICs that are actually used for the given reporting node/year/month combination with few attributes; if needed, more such files may be added for other reporting node/year/month combinations", - "\n- **DataNodeStates** *\\_* *\\_* *\\_*: Switching data nodes on and off, the normal state is (\"Active\") for all the GICs and GRICs of the reporting node/year/month combination; if needed, more such files may be added for other reporting node/year/month combinations" - ], - "metadata": {} - }, - { - "id": "QMmg_-Sg9UOvWDKPIfPCqw", - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Parameters from financial markets", - "\n", - "\nSee folder Files/800.Parameters.", - "\n- **YieldCurve**: List of all yield curves to be used, for different currencies and as-of dates (year/month), using a yearly grid of interest rate maturities extending as far as needed", - "\n- **ExchangeRate**: List of exchange rates to be used, for different currencies and as-of dates (year/month), with a type (Spot/Average); defined as the value of 1 foreign unit expressed in the group currency of the insurance company ", - "\n- **CreditDefaultRate**: For relevant year/month combinations, each with a full list of all credit ratings in S&P notation with their default rate (= probabilty of default within 1 year)", - "\n- **PartnerRating**: For each reinsurance partner of a relevant GRIC, the rating in S&P notation with the as-of date (year/month)" - ], - "metadata": {} - }, - { - "id": "rVg0MlnQdkC77prbiq421A", - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Groups of insurance and reinsurance contracts", - "\n", - "\nSee folder Files/900.TransactionalData.", - "\n- **Actuals** *\\_* *\\_* *\\_*: List of all actual amounts for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types and other attributes; we need at least two such files for the two dates of the Analysis of Change", - "\n- **Openings** *\\_* *\\_* *\\_*: List of the opening amounts for some GICs that are used by the given reporting node. The year/month combination corresponds to the beginning of the planned Analysis of Change period, so only one such file is required. The entries are by EstimateType and AmountType.", - "\n- **NominalCashflows** *\\_* *\\_* *\\_*: List of all projected cash flows for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types, novelty types and other attributes, where the cash flow amounts are given in a regular sequence extending as far as needed; we need at least two such files for the two dates of the Analysis of Change", - "\n", - "\nThe structure of the [Actuals](./InputFormatDescription#actual), [Openings](./InputFormatDescription#opening) and [NominalCashflows](./InputFormatDescription#cashflow) files is explained in a special [notebook](./InputFormatDescription).", - "\n", - "\nThe less usual option of having discounted instead of nominal cash flows in the input is also supported." - ], - "metadata": {} - }, - { - "id": "JVl9TW0NJkS6zsxTFpcDXg", - "cell_type": "markdown", - "source": [ - "", - "\n## Data import and related calculations", - "\n", - "\nSeveral notebooks organize the data import. Methods for importing and accessing data are in the class [ImportStorage](./Import/ImportStorage#import-storage). Methods for further calculations to be done upon import are in [ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation).", - "\n", - "\nHowever, the import as such is conducted by other notebooks which use the methods of ImportStorage and ImportScopeCalculation in a chain of notebook imports:", - "\n", - "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) --> [InitSystemorphBaseToMemory](./Initialization/InitSystemorphBaseToMemory#init-base-to-memory) --> [InitSystemorphToMemory](./Initialization/InitSystemorphToMemory#init-base-to-memory).", - "\n", - "\nThe latter two notebooks initialize and store the imported and derived data in memory for further usage. To store the data in a physical database, [InitSystemorphToDatabase](./Initialization/InitSystemorphToDatabase#init-to-database) can be employed.", - "\n", - "\nThe calculations of ImportScopeCalculation cover a large part of the IFRS 17 methodology and are explained in the section below." - ], - "metadata": {} - }, - { - "id": "oey1-V5ihE2fKiURTRNp1A", - "cell_type": "markdown", - "source": [ - "", - "\n# IFRS 17 Model Calculations", - "\n", - "\nThe notebook **[ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation)** has all the calculations to be executed upon data import. The methods used are explained there with formulas. The centerpiece is the Analysis of Change (AoC) of the insurance business over one period (here: quarter). The formulas often use acronyms (system names) as explained in the [section](#data-input-dim-nodes) on *DimensionsAndPartitions*.", - "\n", - "\nThe main concepts and parts of ImportScopeCalculation are listed here, with links.", - "\n- Structure and sequence of the **[Analysis of Change (AoC)](./Import/ImportScopeCalculation#aoc-step-structure)** steps for the given period", - "\n- **[Discounting](./Import/ImportScopeCalculation#discounting-calculation)** projected cash flows using [yield curves](#data-input-parameters) (current or locked in)", - "\n- **[Nominal](./Import/ImportScopeCalculation#nominal-values)** cash flow amounts per AoC step", - "\n- **[Present Values (PV)](./Import/ImportScopeCalculation#present-values)** of cash flow amounts for all AoC steps:", - "\n - [Cumulated discounted](./Import/ImportScopeCalculation#cumulated-discounted-cashflows) cash flow amounts for all AoC steps", - "\n - [Telescoping difference](./Import/ImportScopeCalculation#telescopic-difference) calculation of cumulated discounted cashflows per AoC step, where the total PV change over the period is the telescoping sum of all these differences", - "\n - [Present Value calculation](./Import/ImportScopeCalculation#present-value) at the beginning and end of the period, with its underlying [PV base](./Import/ImportScopeCalculation#present-value-base) calculations for different AoC types and for [current and locked-in](./Import/ImportScopeCalculation#current-and-locked) yield curves", - "\n - [Interest accretion](./Import/ImportScopeCalculation#interest-accretion) cash flow calculation (one of the AoC steps)", - "\n- **[Risk Adjustment (RA)](./Import/ImportScopeCalculation#risk-adjustment)** calculation, a requirement of the IFRS 17 standard", - "\n- **[Amortization](./Import/ImportScopeCalculation#amortization)**, the AoC step dealing with the reduction of the remaining exposure over the period:", - "\n - [Coverage Unit (CU)](./Import/ImportScopeCalculation#coverage-units), the quantity of services provided by a given GIC, considering one period (reflecting the run-off pattern of the GIC)", - "\n - [Amortization factor](./Import/ImportScopeCalculation#amortization-factor), the relative size of the amortization of a GIC, monthly and for a longer time interval", - "\n- **[Actuals](./Import/ImportScopeCalculation#actual-values)**, treatment of actual values per GIC or GRIC, distinguished according to by their Estimate Type: Ordinary Actuals, Advance Actuals, Overdue Actuals and Deferrable Actuals", - "\n - Calculation of [Actuals Base](./Import/ImportScopeCalculation#actual-base) values for a given GIC and per Estimate Type and Amount Type", - "\n - Different Estimate Types of Actuals and their calculations: Ordinary [Actuals](./Import/ImportScopeCalculation#actuals), [Advance Actuals](./Import/ImportScopeCalculation#advance-actuals) paid before the due date which is inside the AoC period, [Overdue Actuals](./Import/ImportScopeCalculation#overdue-actuals) paid after the AoC period, [Deferrable Actuals](./Import/ImportScopeCalculation#overdue-actuals) whose recognition is deferred (typically used for expenses of different kinds)", - "\n- **[Contractual Service Margin (CSM), Loss Component LC) and Loss Recovery Component (LRC)](./Import/ImportScopeCalculation#csm)**, modeling the treatment of unearned profits (CSM) and losses (LC, LRC) as required by the IFRS 17 standard, per GIC or GRIC:", - "\n - [Fulfillment Cashflow (FCF)](./Import/ImportScopeCalculation#fulfillment-cashflow), same as the aforementioned cumulated discounted cashflow, now adding the risk adjustment component as a basis for CSM and LC calculations", - "\n - [Technical Margin](./Import/ImportScopeCalculation#technical-margin), which is the FCF with special rules for different AoC steps including the Amortization step, also using and calculating the Interest Accretion Factor, Premiums, Deferrals and Investment Claims", - "\n - [Switch Logic for CSM and LC](./Import/ImportScopeCalculation#technical-margin), switching between CSM and LC for a given AoC step in the AoC period; one of the two is always zero depending on the sign of the Technical Margin; distinguishing the [gross case](./Import/ImportScopeCalculation#gross-case) (no reinsurance) from the [reinsurance case](./Import/ImportScopeCalculation#reinsurance-case) which applies reinsurance coverage weights" - ], - "metadata": {} - }, - { - "id": "BnM9Jki8OEedq18buCnW9A", - "cell_type": "markdown", - "source": [ - "", - "\n# Reports", - "\n", - "\nSeveral types of reports can be generated from the same model basis. The notebook **[ReportScopes](./Report/ReportScopes#report-scopes)** has many methods to produce different reports to be executed after the end of all data imports.", - "\n", - "\nThe reports are generated with the help of **DataCube**, a Systemorph tool that allows for the targeted retrieval of information from a large multi-dimensional (in-memory) database, selecting the desired categories, items and degrees of granularity and aggregation across different dimensions.", - "\n", - "\nSome reports of ReportScopes just present existing data from the database, namely the imported data and the results already calculated using the methods of [ImportScopes](#model-calc).", - "\n", - "\nSome other reports related to **[Financial Performance](./Report/ReportScopes#financial-performance)** (profit & loss) require further calculations provided by ReportScopes. An IFRS 17 financial performance report has at least four sections: Insurance Revenue, Insurance Service Expense, Insurance Finance Income/Expense and Other Comprehensive Income. Formulas are provided [here](./Report/ReportScopes#financial-performance).", - "\n", - "\nWhile the ReportScopes notebook provides the calculation formulas for different reports, the production of reports is done by a notebook such as **[Reports](./Report/Reports#report-production)** which imports ReportScopes." - ], - "metadata": {} - }, - { - "id": "au5gK98z6EWDe-C7Wm3Img", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

IFRS17 Calculation Engine - an Overview

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Version of 01 Sep 2022" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Introduction", + "\n", + "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key inpute: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\n", + "\nThis notebook provides an **overview** of Systemorph's IFRS 17 Calculation Engine with brief introductions to all the main steps.", + "\n", + "\nThere are numerous **links** to several notebooks of the Calculation Engine. These notebooks contain specifications, code and also some detailed explanations with formulas in markdown blocks. The most important ones in this respect are [DataModel/DataStructure](./DataModel/DataStructure#data-structure), [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) and [ReportScopes](./Report/ReportScopes#report-scopes)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17", + "\n", + "\nIFRS 17 is a new accounting standard for insurance contracts. The previous standard IFRS 4, which is based on nominal accounting, is replaced by the economic accounting standard IFRS 17.", + "\n", + "\nExplanatory **videos** on **IFRS 17** and a **demo application** can be found on Systemorph's website. Some key points are repeated here briefly.", + "\n", + "\nIFRS 17 deals with insurance contracts which are on the liability side of the balance sheet. Other accounting standards deal with other parts of the business, primarily IFRS 9 for invested assets.", + "\n", + "\nInsurance policies need to be allocated to homogeneous groups of insurance contracts (GICs) according to high-level principles established by the IFRS 17 standard, such as contract type, line of business, annual cohort etc. Insurers have some degree of freedom to optmize those GICs, as long as they respect the high-level principles.", + "\n", + "\nInsurance contracts generate different types of cashflows. For example, **Amount Type** is a dimension refering to premiums, claims, expenses of different kinds, etc. for these cashflows. The Calculation Engine presented here expects input files of all the projected cashflows for each GIC, for different regular time points (quarterly or monthly, ...) and corresponding actual amounts observed for a given period. ", + "\n", + "\nEach cashflow is characterized by all the necessary attributes: business unit, start time, amount type, novelty of business etc. and projected cashflow amounts in a regular time grid until the final run-off of all contracts.", + "\n", + "\nIf the entered cashflows are nominal (the usual case), the the present value (PV) of each cashflow is computed using proper yield curves for discounting.", + "\n", + "\nA central element of IFRS 17 is the Analysis of Change (AoC). The present value of the business (future cashflows) changes from the beginning to the end of the accounting period due to different effects, each of them constituting a modeled AoC step.", + "\n", + "\nIn IFRS 17, the value of future profitable business has a component called the Contractual Service Margin (CSM), defined at GIC level. The profit measured as CSM is recognized slowly over time rather than immediately in financial performance statements. On the other hand, a GIC can be onerous and produce a Loss Component (LC) instead, which needs to be recognized immediately.", + "\n", + "\nSeveral reports on the valuation of cashflows, balance sheet and financial performance can be produced, each dealing with different aspects, such as", + "\n - Present Value of Future Cash Flows (PVFCF)", + "\n - Contractual Service Margin (CSM) and Loss Component (LC)", + "\n - Liability for Remaining Coverage (LRC)", + "\n - Liability for Incurred Claims (LIC)", + "\n - Financial Performance", + "\n - Accounting Events" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Data Model, Data Input, Data Import", + "\n", + "\nThe IFRS 17 calculations are based on a well-defined **data model**. The data input files are set up according to the data model, and the data import and all the ensuing calculations up to the final report generation respect the data model.", + "\n", + "\nInput files as listed below are used to provide the necessary information on the business to be modeled. These files are part of the IFRS 17 Calculation Engine and can be used as templates for users intending to model their own business and adapt some files accordingly. ", + "\n", + "\nThe IFRS 17 calculations start by importing the data input files, and the more complex logic of the IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data Model", + "\n", + "\nThe data model includes the definition of reporting nodes and dimensions to be used, including identities, amount types, group of insurance contracts and many more.", + "\n", + "\nThe notebook [DataModel/DataStructure](./DataModel/DataStructure#data-structure) defines the data records, dimensions and interfaces of the data model. There is a long section on the many [dimensions](./DataModel/DataStructure#dimensions) used to characterize the business and its IFRS 17 model.", + "\n", + "\nThe [input files](#data-input-dim-nodes) ReportingNodes and especially DimensionsAndPartitions provide an overview of data structures actually used. Some dimensions are hierarchical, so some entries have parent entries.", + "\n", + "\nMany abbreviations and acronyms used later in the documentation and the code are the **system names**, where the corresponding display names can be found together with the attributes." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Reporting nodes, dimensions and partitions", + "\n", + "\nSee folders *Files* (DimensionsAndPartitions) and *Files/300.ReportingNodes* (ReportingNodes).", + "\n- **ReportingNodes**: List of business units, often per country, with system name and display name, currency and \"G\" for the whole group", + "\n- **DimensionsAndPartitions**: The many dimensions (21) required to characterize all of the data and results, with system names and display names. This information is quite stable, but some information related to partitions refers to the reporting nodes " + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Groups of insurance and reinsurance contracts", + "\n", + "\nSee folder Files/700.DataNodes. The information is about data nodes, that is Groups of Insurance Contracts (GICs) and Groups of Reinsurance Contracts (GRICs) and portfolios of these.", + "\n- **DataNodes**: List of all GICs and GRICs, each with several attributes and the portfolios to which they belong; an additional attribute of GRICs being the reinsurance partner", + "\n- **DataNodeParameters** *\\_* *\\_* *\\_*: List of those GICs and GRICs that are actually used for the given reporting node/year/month combination with few attributes; if needed, more such files may be added for other reporting node/year/month combinations", + "\n- **DataNodeStates** *\\_* *\\_* *\\_*: Switching data nodes on and off, the normal state is (\"Active\") for all the GICs and GRICs of the reporting node/year/month combination; if needed, more such files may be added for other reporting node/year/month combinations" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Parameters from financial markets", + "\n", + "\nSee folder Files/800.Parameters.", + "\n- **YieldCurve**: List of all yield curves to be used, for different currencies and as-of dates (year/month), using a yearly grid of interest rate maturities extending as far as needed", + "\n- **ExchangeRate**: List of exchange rates to be used, for different currencies and as-of dates (year/month), with a type (Spot/Average); defined as the value of 1 foreign unit expressed in the group currency of the insurance company ", + "\n- **CreditDefaultRate**: For relevant year/month combinations, each with a full list of all credit ratings in S&P notation with their default rate (= probabilty of default within 1 year)", + "\n- **PartnerRating**: For each reinsurance partner of a relevant GRIC, the rating in S&P notation with the as-of date (year/month)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Groups of insurance and reinsurance contracts", + "\n", + "\nSee folder Files/900.TransactionalData.", + "\n- **Actuals** *\\_* *\\_* *\\_*: List of all actual amounts for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types and other attributes; we need at least two such files for the two dates of the Analysis of Change", + "\n- **Openings** *\\_* *\\_* *\\_*: List of the opening amounts for some GICs that are used by the given reporting node. The year/month combination corresponds to the beginning of the planned Analysis of Change period, so only one such file is required. The entries are by EstimateType and AmountType.", + "\n- **NominalCashflows** *\\_* *\\_* *\\_*: List of all projected cash flows for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types, novelty types and other attributes, where the cash flow amounts are given in a regular sequence extending as far as needed; we need at least two such files for the two dates of the Analysis of Change", + "\n", + "\nThe structure of the [Actuals](./InputFormatDescription#actual), [Openings](./InputFormatDescription#opening) and [NominalCashflows](./InputFormatDescription#cashflow) files is explained in a special [notebook](./InputFormatDescription).", + "\n", + "\nThe less usual option of having discounted instead of nominal cash flows in the input is also supported." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data import and related calculations", + "\n", + "\nSeveral notebooks organize the data import. Methods for importing and accessing data are in the class [ImportStorage](./Import/ImportStorage#import-storage). Methods for further calculations to be done upon import are in [ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation).", + "\n", + "\nHowever, the import as such is conducted by other notebooks which use the methods of ImportStorage and ImportScopeCalculation in a chain of notebook imports:", + "\n", + "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) --> [InitSystemorphBaseToMemory](./Initialization/InitSystemorphBaseToMemory#init-base-to-memory) --> [InitSystemorphToMemory](./Initialization/InitSystemorphToMemory#init-base-to-memory).", + "\n", + "\nThe latter two notebooks initialize and store the imported and derived data in memory for further usage. To store the data in a physical database, [InitSystemorphToDatabase](./Initialization/InitSystemorphToDatabase#init-to-database) can be employed.", + "\n", + "\nThe calculations of ImportScopeCalculation cover a large part of the IFRS 17 methodology and are explained in the section below." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17 Model Calculations", + "\n", + "\nThe notebook **[ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation)** has all the calculations to be executed upon data import. The methods used are explained there with formulas. The centerpiece is the Analysis of Change (AoC) of the insurance business over one period (here: quarter). The formulas often use acronyms (system names) as explained in the [section](#data-input-dim-nodes) on *DimensionsAndPartitions*.", + "\n", + "\nThe main concepts and parts of ImportScopeCalculation are listed here, with links.", + "\n- Structure and sequence of the **[Analysis of Change (AoC)](./Import/ImportScopeCalculation#aoc-step-structure)** steps for the given period", + "\n- **[Discounting](./Import/ImportScopeCalculation#discounting-calculation)** projected cash flows using [yield curves](#data-input-parameters) (current or locked in)", + "\n- **[Nominal](./Import/ImportScopeCalculation#nominal-values)** cash flow amounts per AoC step", + "\n- **[Present Values (PV)](./Import/ImportScopeCalculation#present-values)** of cash flow amounts for all AoC steps:", + "\n - [Cumulated discounted](./Import/ImportScopeCalculation#cumulated-discounted-cashflows) cash flow amounts for all AoC steps", + "\n - [Telescoping difference](./Import/ImportScopeCalculation#telescopic-difference) calculation of cumulated discounted cashflows per AoC step, where the total PV change over the period is the telescoping sum of all these differences", + "\n - [Present Value calculation](./Import/ImportScopeCalculation#present-value) at the beginning and end of the period, with its underlying [PV base](./Import/ImportScopeCalculation#present-value-base) calculations for different AoC types and for [current and locked-in](./Import/ImportScopeCalculation#current-and-locked) yield curves", + "\n - [Interest accretion](./Import/ImportScopeCalculation#interest-accretion) cash flow calculation (one of the AoC steps)", + "\n- **[Risk Adjustment (RA)](./Import/ImportScopeCalculation#risk-adjustment)** calculation, a requirement of the IFRS 17 standard", + "\n- **[Amortization](./Import/ImportScopeCalculation#amortization)**, the AoC step dealing with the reduction of the remaining exposure over the period:", + "\n - [Coverage Unit (CU)](./Import/ImportScopeCalculation#coverage-units), the quantity of services provided by a given GIC, considering one period (reflecting the run-off pattern of the GIC)", + "\n - [Amortization factor](./Import/ImportScopeCalculation#amortization-factor), the relative size of the amortization of a GIC, monthly and for a longer time interval", + "\n- **[Actuals](./Import/ImportScopeCalculation#actual-values)**, treatment of actual values per GIC or GRIC, distinguished according to by their Estimate Type: Ordinary Actuals, Advance Actuals, Overdue Actuals and Deferrable Actuals", + "\n - Calculation of [Actuals Base](./Import/ImportScopeCalculation#actual-base) values for a given GIC and per Estimate Type and Amount Type", + "\n - Different Estimate Types of Actuals and their calculations: Ordinary [Actuals](./Import/ImportScopeCalculation#actuals), [Advance Actuals](./Import/ImportScopeCalculation#advance-actuals) paid before the due date which is inside the AoC period, [Overdue Actuals](./Import/ImportScopeCalculation#overdue-actuals) paid after the AoC period, [Deferrable Actuals](./Import/ImportScopeCalculation#overdue-actuals) whose recognition is deferred (typically used for expenses of different kinds)", + "\n- **[Contractual Service Margin (CSM), Loss Component LC) and Loss Recovery Component (LRC)](./Import/ImportScopeCalculation#csm)**, modeling the treatment of unearned profits (CSM) and losses (LC, LRC) as required by the IFRS 17 standard, per GIC or GRIC:", + "\n - [Fulfillment Cashflow (FCF)](./Import/ImportScopeCalculation#fulfillment-cashflow), same as the aforementioned cumulated discounted cashflow, now adding the risk adjustment component as a basis for CSM and LC calculations", + "\n - [Technical Margin](./Import/ImportScopeCalculation#technical-margin), which is the FCF with special rules for different AoC steps including the Amortization step, also using and calculating the Interest Accretion Factor, Premiums, Deferrals and Investment Claims", + "\n - [Switch Logic for CSM and LC](./Import/ImportScopeCalculation#technical-margin), switching between CSM and LC for a given AoC step in the AoC period; one of the two is always zero depending on the sign of the Technical Margin; distinguishing the [gross case](./Import/ImportScopeCalculation#gross-case) (no reinsurance) from the [reinsurance case](./Import/ImportScopeCalculation#reinsurance-case) which applies reinsurance coverage weights" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Reports", + "\n", + "\nSeveral types of reports can be generated from the same model basis. The notebook **[ReportScopes](./Report/ReportScopes#report-scopes)** has many methods to produce different reports to be executed after the end of all data imports.", + "\n", + "\nThe reports are generated with the help of **DataCube**, a Systemorph tool that allows for the targeted retrieval of information from a large multi-dimensional (in-memory) database, selecting the desired categories, items and degrees of granularity and aggregation across different dimensions.", + "\n", + "\nSome reports of ReportScopes just present existing data from the database, namely the imported data and the results already calculated using the methods of [ImportScopes](#model-calc).", + "\n", + "\nSome other reports related to **[Financial Performance](./Report/ReportScopes#financial-performance)** (profit & loss) require further calculations provided by ReportScopes. An IFRS 17 financial performance report has at least four sections: Insurance Revenue, Insurance Service Expense, Insurance Finance Income/Expense and Other Comprehensive Income. Formulas are provided [here](./Report/ReportScopes#financial-performance).", + "\n", + "\nWhile the ReportScopes notebook provides the calculation formulas for different reports, the production of reports is done by a notebook such as **[Reports](./Report/Reports#report-production)** which imports ReportScopes." + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Report/ReportConfigurationAndUtils.ipynb b/Report/ReportConfigurationAndUtils.ipynb index 628b0f04..61e8193f 100644 --- a/Report/ReportConfigurationAndUtils.ipynb +++ b/Report/ReportConfigurationAndUtils.ipynb @@ -1,148 +1,126 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "RcqlbIqLC0GUIOHkkIM0fA", - "cell_type": "markdown", - "source": [ - "

Report Configuration And Utils

" - ], - "metadata": {} - }, - { - "id": "JWFelad9jEy9FfjxYAaBwA", - "cell_type": "code", - "source": [ - "#!import \"../Utils/UtilityMethods\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YyjCBXNsHk2Q8c-G2NlyIA", - "cell_type": "code", - "source": [ - "using Systemorph.Vertex.Pivot.Reporting.Builder;", - "\nusing System.Collections.Immutable;", - "\n", - "\npublic static DataCubeReportBuilder, TVariable, TVariable ,TVariable> ReportGridOptions(", - "\n this DataCubeReportBuilder, TVariable, TVariable, TVariable> reportBuilder,", - "\n int reportHeight = 700,", - "\n int valueColumnWidth = 250,", - "\n int headerColumnWidth = 250,", - "\n int groupDefaultExpanded = 2)", - "\n => reportBuilder.WithGridOptions(go => go", - "\n .WithColumns(cols => cols.Modify(\"Value\",c => c.WithWidth(valueColumnWidth).WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", - "\n .WithRows(rows => rows", - "\n .Where(r => !(r.RowGroup.Coordinates.Last() == \"NullGroup\"))", - "\n .Select(r => r with { RowGroup = r.RowGroup with { Coordinates = r.RowGroup.Coordinates.Where(c => c != \"NullGroup\").ToImmutableList() } })", - "\n .ToArray())", - "\n .WithAutoGroupColumn(c => c.WithWidth(headerColumnWidth) with { Pinned = \"left\" })", - "\n with { Height = reportHeight, GroupDefaultExpanded = groupDefaultExpanded, OnGridReady = null } );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iBIqwkn9SUCQTW4I5tiVIg", - "cell_type": "code", - "source": [ - "public static string CurrencyGrouper(CurrencyType currencyType) => currencyType switch {", - "\n CurrencyType.Contractual => \"ContractualCurrency\",", - "\n CurrencyType.Functional => \"FunctionalCurrency\",", - "\n _ => string.Empty };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "M1TrAAwxbEaxJ2r5B3SSkw", - "cell_type": "markdown", - "source": [ - "# Queries" - ], - "metadata": {} - }, - { - "id": "K7EO5RzzdUq_sjJvMccxoA", - "cell_type": "markdown", - "source": [ - "## Query Report Variables" - ], - "metadata": {} - }, - { - "id": "bRSyLeKBd0KijXxUwm4o-w", - "cell_type": "code", - "source": [ - "public static async Task> QueryReportVariablesAsync(this IWorkspace workspace, (int Year, int Month, string ReportingNode, string Scenario) args ) {", - "\n ", - "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", - "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Year, Month = args.Month });", - "\n ", - "\n return await workspace.Query()", - "\n .Join(workspace.Query(),", - "\n dn => dn.SystemName,", - "\n iv => iv.DataNode,", - "\n (dn, iv) => new ReportVariable {", - "\n // From Args/Inputs", - "\n ReportingNode = args.ReportingNode,", - "\n Scenario = args.Scenario,", - "\n ", - "\n // From Data Node", - "\n Portfolio = dn.Portfolio,", - "\n GroupOfContract = dn.SystemName,", - "\n ", - "\n FunctionalCurrency = dn.FunctionalCurrency,", - "\n ContractualCurrency = dn.ContractualCurrency,", - "\n ", - "\n ValuationApproach = dn.ValuationApproach,", - "\n OciType = dn.OciType,", - "\n InitialProfitability = dn.Profitability,", - "\n LiabilityType = dn.LiabilityType,", - "\n AnnualCohort = dn.AnnualCohort,", - "\n LineOfBusiness = dn.LineOfBusiness,", - "\n ", - "\n // Reinsurance", - "\n IsReinsurance = dn is GroupOfReinsuranceContract, ", - "\n Partner = dn.Partner,", - "\n ", - "\n // From Variable", - "\n EstimateType = iv.EstimateType,", - "\n VariableType = iv.AocType,", - "\n Novelty = iv.Novelty,", - "\n AmountType = iv.AmountType,", - "\n EconomicBasis = iv.EconomicBasis,", - "\n ", - "\n //LIC", - "\n AccidentYear = iv.AccidentYear == null ? default : (int)iv.AccidentYear,", - "\n ", - "\n Value = iv.Value })", - "\n .ToArrayAsync();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Report Configuration And Utils

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Utils/UtilityMethods\"" + ] + }, + { + "cell_type": "code", + "source": [ + "using Systemorph.Vertex.Pivot.Reporting.Builder;", + "\nusing System.Collections.Immutable;", + "\n", + "\npublic static DataCubeReportBuilder, TVariable, TVariable ,TVariable> ReportGridOptions(", + "\n this DataCubeReportBuilder, TVariable, TVariable, TVariable> reportBuilder,", + "\n int reportHeight = 700,", + "\n int valueColumnWidth = 250,", + "\n int headerColumnWidth = 250,", + "\n int groupDefaultExpanded = 2)", + "\n => reportBuilder.WithGridOptions(go => go", + "\n .WithColumns(cols => cols.Modify(\"Value\",c => c.WithWidth(valueColumnWidth).WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows", + "\n .Where(r => !(r.RowGroup.Coordinates.Last() == \"NullGroup\"))", + "\n .Select(r => r with { RowGroup = r.RowGroup with { Coordinates = r.RowGroup.Coordinates.Where(c => c != \"NullGroup\").ToImmutableList() } })", + "\n .ToArray())", + "\n .WithAutoGroupColumn(c => c.WithWidth(headerColumnWidth) with { Pinned = \"left\" })", + "\n with { Height = reportHeight, GroupDefaultExpanded = groupDefaultExpanded, OnGridReady = null } );" + ] + }, + { + "cell_type": "code", + "source": [ + "public static string CurrencyGrouper(CurrencyType currencyType) => currencyType switch {", + "\n CurrencyType.Contractual => \"ContractualCurrency\",", + "\n CurrencyType.Functional => \"FunctionalCurrency\",", + "\n _ => string.Empty };" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Queries" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Query Report Variables" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> QueryReportVariablesAsync(this IWorkspace workspace, (int Year, int Month, string ReportingNode, string Scenario) args ) {", + "\n ", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Year, Month = args.Month });", + "\n ", + "\n return await workspace.Query()", + "\n .Join(workspace.Query(),", + "\n dn => dn.SystemName,", + "\n iv => iv.DataNode,", + "\n (dn, iv) => new ReportVariable {", + "\n // From Args/Inputs", + "\n ReportingNode = args.ReportingNode,", + "\n Scenario = args.Scenario,", + "\n ", + "\n // From Data Node", + "\n Portfolio = dn.Portfolio,", + "\n GroupOfContract = dn.SystemName,", + "\n ", + "\n FunctionalCurrency = dn.FunctionalCurrency,", + "\n ContractualCurrency = dn.ContractualCurrency,", + "\n ", + "\n ValuationApproach = dn.ValuationApproach,", + "\n OciType = dn.OciType,", + "\n InitialProfitability = dn.Profitability,", + "\n LiabilityType = dn.LiabilityType,", + "\n AnnualCohort = dn.AnnualCohort,", + "\n LineOfBusiness = dn.LineOfBusiness,", + "\n ", + "\n // Reinsurance", + "\n IsReinsurance = dn is GroupOfReinsuranceContract, ", + "\n Partner = dn.Partner,", + "\n ", + "\n // From Variable", + "\n EstimateType = iv.EstimateType,", + "\n VariableType = iv.AocType,", + "\n Novelty = iv.Novelty,", + "\n AmountType = iv.AmountType,", + "\n EconomicBasis = iv.EconomicBasis,", + "\n ", + "\n //LIC", + "\n AccidentYear = iv.AccidentYear == null ? default : (int)iv.AccidentYear,", + "\n ", + "\n Value = iv.Value })", + "\n .ToArrayAsync();", + "\n}" + ] + } + ] } \ No newline at end of file diff --git a/Report/ReportScopes.ipynb b/Report/ReportScopes.ipynb index 534b3bc3..719b2f66 100644 --- a/Report/ReportScopes.ipynb +++ b/Report/ReportScopes.ipynb @@ -1,1038 +1,854 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "RC8Ga5S2p0C8yAmyjz_N-g", - "cell_type": "markdown", - "source": [ - "", - "\n

Report Scopes (IFRS17 Methodology Business Logic)

", - "\n", - "\nThis notebook contains the logic used to perform calculations upon reporting of data." - ], - "metadata": {} - }, - { - "id": "LVx2yOMaFE6N2gnro5w9Qg", - "cell_type": "markdown", - "source": [ - "# References", - "\nLibraries and other notebooks which are needed for this notebook are imported below." - ], - "metadata": {} - }, - { - "id": "9AZzZxEXwkCvLIoKhmBQlQ", - "cell_type": "markdown", - "source": [ - "## Notebooks" - ], - "metadata": {} - }, - { - "id": "MTpy2cXeG0GmCbe_aOWmBw", - "cell_type": "code", - "source": [ - "#!import \"ReportStorage\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "upikmN8zjU-hYfL_NTHY1A", - "cell_type": "markdown", - "source": [ - "# Scopes" - ], - "metadata": {} - }, - { - "id": "Zs3wCzFnZ0mgnoovzVtI4g", - "cell_type": "markdown", - "source": [ - "## Helper Scopes" - ], - "metadata": {} - }, - { - "id": "kMmCRDkymECPHAt_8qMONw", - "cell_type": "markdown", - "source": [ - "### Universe" - ], - "metadata": {} - }, - { - "id": "09cKY7l-c0WdVsk5Eqhscw", - "cell_type": "code", - "source": [ - "public interface IUniverse: IScopeWithStorage {}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KadX2iXWl02PhqX5WatT_A", - "cell_type": "markdown", - "source": [ - "## Data Transformation" - ], - "metadata": {} - }, - { - "id": "syVjSAh1tEazuQzXYkPajw", - "cell_type": "markdown", - "source": [ - "### Retrieve Raw Data" - ], - "metadata": {} - }, - { - "id": "MRPDIFQlykKNky6h_5dzzg", - "cell_type": "code", - "source": [ - "public interface Data: IScope<(ReportIdentity ReportIdentity, string EstimateType), ReportStorage>, IDataCube {", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", - "\n ", - "\n protected IDataCube RawData => GetStorage().GetVariables(Identity.ReportIdentity, Identity.EstimateType);", - "\n", - "\n private IDataCube RawEops => RawData.Filter((\"VariableType\", AocTypes.EOP));", - "\n private IDataCube NotEopsNotCls => RawData.Filter((\"VariableType\", \"!EOP\"),(\"VariableType\", \"!CL\")); // TODO negation must be hardcoded (also to avoid string concatenation)", - "\n ", - "\n private IDataCube CalculatedCl => (RawEops - NotEopsNotCls)", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = AocTypes.CL });", - "\n ", - "\n private IDataCube CalculatedEops => (NotEopsNotCls + CalculatedCl)", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(x => x with { VariableType = AocTypes.EOP, Novelty = Novelties.C });", - "\n ", - "\n IDataCube Data => NotEopsNotCls + CalculatedCl + CalculatedEops;", - "\n}", - "\npublic interface DataWrittenActual: Data {", - "\n IDataCube Data.Data => RawData;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yus8OX8BukyLFOjUwOQLLA", - "cell_type": "markdown", - "source": [ - "### Foreign Exchange (FX) Rates" - ], - "metadata": {} - }, - { - "id": "cJq9jrxRrEitDC2cNGnQLg", - "cell_type": "code", - "source": [ - "public interface Fx: IScope<(string ContractualCurrency, string FunctionalCurrency, FxPeriod FxPeriod, (int, int) Period, CurrencyType CurrencyType), ReportStorage> { ", - "\n private double groupFxRate => Identity.CurrencyType switch {", - "\n CurrencyType.Group => GetStorage().GetFx(Identity.Period, Identity.FunctionalCurrency, GroupCurrency, FxPeriod.Average),", - "\n _ => 1", - "\n };", - "\n ", - "\n private double GetFunctionalFxRate(FxPeriod fxPeriod) => Identity.CurrencyType switch {", - "\n CurrencyType.Contractual => 1,", - "\n _ => GetStorage().GetFx(Identity.Period, Identity.ContractualCurrency, Identity.FunctionalCurrency, fxPeriod)", - "\n };", - "\n ", - "\n double Fx => GetFunctionalFxRate(Identity.FxPeriod) * groupFxRate;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sFdrnO2l-kaXQVOwaTfu4Q", - "cell_type": "code", - "source": [ - "public interface FxData: IScope<(ReportIdentity ReportIdentity, CurrencyType CurrencyType, string EstimateType), ReportStorage>, IDataCube {", - "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", - "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", - "\n ", - "\n protected IDataCube Data => GetScope((Identity.ReportIdentity, Identity.EstimateType)).Data", - "\n .SelectToDataCube(x => GetScope((Identity.ReportIdentity.ContractualCurrency, ", - "\n Identity.ReportIdentity.FunctionalCurrency, ", - "\n GetStorage().GetFxPeriod(GetStorage().Args.Period, x.VariableType, x.Novelty),", - "\n (Identity.ReportIdentity.Year, Identity.ReportIdentity.Month),", - "\n Identity.CurrencyType", - "\n )).Fx * x);", - "\n ", - "\n private IDataCube Eops => Data.Filter((\"VariableType\", AocTypes.EOP));", - "\n private IDataCube NotEops => Data.Filter((\"VariableType\", \"!EOP\")); // TODO negation must be hardcoded (also to avoid string concatenation)", - "\n ", - "\n private IDataCube Fx => (Eops - NotEops)", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = AocTypes.FX });", - "\n ", - "\n IDataCube FxData => Data + Fx;", - "\n}", - "\n", - "\npublic interface FxDataWrittenActual: FxData {", - "\n IDataCube FxData.FxData => Data;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "c-y9Rq20yU-c1k-zkJbtZA", - "cell_type": "markdown", - "source": [ - "## Present Value" - ], - "metadata": {} - }, - { - "id": "uD97mWuNn0i7IDWGmZcNvQ", - "cell_type": "markdown", - "source": [ - "", - "\n### Best Estimate", - "\n", - "\nBest Estimate of Present Value (PV) report includes contributions from the [Present Value](../Import/ImportScopeCalculation#current-and-locked) calculation. The result of the Locked-in calculation is used when the Valuation Approach is BBA and the flag for Oci is active." - ], - "metadata": {} - }, - { - "id": "JgpSiRtFuEmUmFnBtZdTRA", - "cell_type": "code", - "source": [ - "public interface BestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube BestEstimate => Identity.Id switch {", - "\n { ValuationApproach: ValuationApproaches.BBA, IsOci: true } => GetScope(Identity).LockedBestEstimate,", - "\n _ => GetScope(Identity).CurrentBestEstimate };", - "\n}", - "\n", - "\npublic interface LockedBestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube LockedBestEstimate => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BE)).FxData", - "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.L));", - "\n}", - "\n", - "\npublic interface CurrentBestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube CurrentBestEstimate => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BE)).FxData", - "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.C));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "o4YOxEue9U2IsUWtpQRwNg", - "cell_type": "markdown", - "source": [ - "", - "\n### Risk Adjustment", - "\n", - "\nRisk Adjustment (RA) report includes contributions from the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) calculation. The result of the Locked-in calculation is used when the Valuation Approach is BBA and the flag for Oci is active." - ], - "metadata": {} - }, - { - "id": "j6tStuZslUWvsTYy34vFCQ", - "cell_type": "code", - "source": [ - "public interface RiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube RiskAdjustment => Identity.Id switch {", - "\n { ValuationApproach: ValuationApproaches.BBA, IsOci: true } => GetScope(Identity).LockedRiskAdjustment,", - "\n _ => GetScope(Identity).CurrentRiskAdjustment };", - "\n}", - "\n", - "\npublic interface LockedRiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube LockedRiskAdjustment => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.RA)).FxData", - "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.L));", - "\n}", - "\n", - "\npublic interface CurrentRiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube CurrentRiskAdjustment => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.RA)).FxData", - "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.C));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "P-vfX_L3rkW_9Lmf31RxpA", - "cell_type": "markdown", - "source": [ - "", - "\n## Fulfillment Cashflows", - "\nFulfillment Cashflows (FCF) report includes contributions from the [Best Estimate](#best-estimate) of Present Value and [Risk Adjustment](#risk-adjustment) Present Value." - ], - "metadata": {} - }, - { - "id": "KK0mF25Mf0aFBgqRlpZL9g", - "cell_type": "code", - "source": [ - "public interface Fcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube BestEstimate => GetScope(Identity).BestEstimate;", - "\n private IDataCube RiskAdjustment => GetScope(Identity).RiskAdjustment;", - "\n ", - "\n IDataCube Fcf => BestEstimate + RiskAdjustment;", - "\n}", - "\n", - "\npublic interface CurrentFcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube { ", - "\n private IDataCube BestEstimate => GetScope(Identity).CurrentBestEstimate;", - "\n private IDataCube RiskAdjustment => GetScope(Identity).CurrentRiskAdjustment;", - "\n ", - "\n IDataCube CurrentFcf => BestEstimate + RiskAdjustment;", - "\n}", - "\n", - "\npublic interface LockedFcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube { ", - "\n private IDataCube BestEstimate => GetScope(Identity).LockedBestEstimate;", - "\n private IDataCube RiskAdjustment => GetScope(Identity).LockedRiskAdjustment;", - "\n ", - "\n IDataCube LockedFcf => BestEstimate + RiskAdjustment;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BnSosIcbCUqw1lbDI0LxPw", - "cell_type": "markdown", - "source": [ - "", - "\n## LRC Technical Margin: CSM, LC, LoReCo", - "\n", - "\nContractual Service Margin (CSM), Loss Component (LC), Loss Recovery Component (LoReCo) reports of the Liability for Remaining Coverage (LRC) include contributions from the calculation of [CSM](../Import/ImportScopeCalculation#csm), [LC](../Import/ImportScopeCalculation#csm), and [LoReCo](../Import/ImportScopeCalculation#csm), respectively." - ], - "metadata": {} - }, - { - "id": "ZPTctq2WjkinG6niMamqoA", - "cell_type": "code", - "source": [ - "public interface Csm: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube Csm => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.C)).FxData;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cG4TSd1LZ0iIWMjgLaB7iA", - "cell_type": "code", - "source": [ - "public interface Lc: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube Lc => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.L)).FxData;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2pNl3ECznUOsfhcu-OWIPQ", - "cell_type": "code", - "source": [ - "public interface Loreco: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube Loreco => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.LR)).FxData;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "t2D8_dXH90uK90VYE8I_Fg", - "cell_type": "code", - "source": [ - "public interface LrcTechnicalMargin: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube Csm => GetScope(Identity).Csm;", - "\n private IDataCube Lc => GetScope(Identity).Lc;", - "\n private IDataCube Loreco => GetScope(Identity).Loreco;", - "\n ", - "\n IDataCube LrcTechnicalMargin => Lc + Loreco - 1 * Csm;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QXA-wNeyfkStz-eabLqYkw", - "cell_type": "markdown", - "source": [ - "", - "\n## Written, Accruals and Deferrals ", - "\n", - "\nWritten Actual (Actual) report includes contributions from the [Actual](../Import/ImportScopeCalculation#actuals) import. ", - "\n
Accrual Actuals (Advance, Overdue Actual) report includes contributions from the [Advance](../Import/ImportScopeCalculation#advance-actuals) and [Overdue](../Import/ImportScopeCalculation#overdue-actuals) Actual calculation.", - "\n
Deferral (Deferral Actual) report includes contributions from the calculation of [Deferral](../Import/ImportScopeCalculation#deferrable-actuals) Actual." - ], - "metadata": {} - }, - { - "id": "6oQzlalJiEKtr4FVgbf30g", - "cell_type": "code", - "source": [ - "public interface WrittenAndAccruals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube Written => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.A)).FxData;", - "\n IDataCube Advance => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.AA)).FxData;", - "\n IDataCube Overdue => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.OA)).FxData;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ezZf5dedgUuHkuUp-bBDDg", - "cell_type": "code", - "source": [ - "public interface Deferrals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube Deferrals => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.DA)).FxData;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FSsDY7cH70S2Lu3yXeXw3w", - "cell_type": "markdown", - "source": [ - "## Experience Adjustment", - "\n", - "\nExperience Adjustment (EA) report includes contributions from the [Written](#written-accrual-deferral) Actual report and the [Best Estimate](#best-estimate) of Present Value report (only the *Cash flow* AocStep). " - ], - "metadata": {} - }, - { - "id": "JRn9_o5AL06364MC1z7Fkg", - "cell_type": "code", - "source": [ - "public interface ExperienceAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube WrittenCashflow => GetScope(Identity).Written", - "\n .Filter((\"VariableType\", AocTypes.CF));", - "\n ", - "\n private IDataCube BestEstimateCashflow => GetScope(Identity).BestEstimate", - "\n .Filter((\"VariableType\", AocTypes.CF))", - "\n .SelectToDataCube(rv => rv with { EconomicBasis = null, Novelty = Novelties.C });", - "\n", - "\n IDataCube ActuarialExperienceAdjustment => WrittenCashflow - BestEstimateCashflow;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9YDqvT60sUuBmJmZL-tF7w", - "cell_type": "markdown", - "source": [ - "", - "\n## LIC Actuarial (Actuarial Liability for Incurred Claims)", - "\n", - "\nLiability of Incurred Claims (LIC Actuarial) report includes the contributions from [Fulfillment cashflow](#fulfillment-cashflows)." - ], - "metadata": {} - }, - { - "id": "N9PQzPef10meQscdc39AtQ", - "cell_type": "code", - "source": [ - "public interface LicActuarial: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n IDataCube LicActuarial => GetScope(Identity).CurrentFcf.Filter((\"LiabilityType\", LiabilityTypes.LIC));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BWNVgJ7kVUuivi0spCqfcw", - "cell_type": "markdown", - "source": [ - "## LIC (Liability for Incurred Claims)", - "\n", - "\nLiability of Incurred Claims (LIC) report includes the contributions from [Lic Actuarial](#lic-actuarial) (Fullfilment Cashflow), [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." - ], - "metadata": {} - }, - { - "id": "TDQUKQ-ZLEuPyI1q0ZU9yg", - "cell_type": "code", - "source": [ - "public interface Lic: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube licActuarial => GetScope(Identity).LicActuarial;", - "\n private IDataCube accrual => GetScope(Identity).Advance.Filter((\"LiabilityType\", LiabilityTypes.LIC)) + ", - "\n GetScope(Identity).Overdue.Filter((\"LiabilityType\", LiabilityTypes.LIC));", - "\n private IDataCube licData => licActuarial + accrual;", - "\n ", - "\n private IDataCube bop => licData.Filter((\"VariableType\", AocTypes.BOP));", - "\n private IDataCube delta => licData.Filter((\"VariableType\",\"!BOP\"),(\"VariableType\",\"!EOP\"))", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = \"D\" });", - "\n private IDataCube eop => licData.Filter((\"VariableType\",AocTypes.EOP));", - "\n ", - "\n IDataCube Lic => bop + delta + eop;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jFBlyVq-A0G7tmw5YdUm2Q", - "cell_type": "markdown", - "source": [ - "", - "\n## LRC Actuarial (Actuarial Liability for Remaining Coverage)", - "\n", - "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [Fulfillment cashflow](#fulfillment-cashflows), [Contructual Sevice Margin](#technical-margin), [Loss Component](#technical-margin), and [Loss Recovery Component](#technical-margin)." - ], - "metadata": {} - }, - { - "id": "Nh6Na96xYkGFXBLGuTXAWQ", - "cell_type": "code", - "source": [ - "public interface LrcActuarial: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube Fcf => GetScope(Identity).CurrentFcf.Filter((\"LiabilityType\", LiabilityTypes.LRC));", - "\n private IDataCube Csm => GetScope(Identity).Csm;", - "\n private IDataCube Loreco => GetScope(Identity).Loreco;", - "\n ", - "\n IDataCube LrcActuarial => Fcf + Csm + Loreco;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ivAB2SOatESuXm7mpgcW5w", - "cell_type": "markdown", - "source": [ - "## LRC (Liability for Remaining Coverage)", - "\n", - "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [LRC Actuarial](#lrc-actuarial) (Fulfillment Cashflow, Contructual Sevice Margin, Loss Component, Loss Recovery Component) and, [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." - ], - "metadata": {} - }, - { - "id": "G1fG1yC8kEyGuJfovw39HA", - "cell_type": "code", - "source": [ - "public interface Lrc: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube lrcActuarial => GetScope(Identity).LrcActuarial;", - "\n private IDataCube accrual => GetScope(Identity).Advance.Filter((\"LiabilityType\", LiabilityTypes.LRC)) + ", - "\n GetScope(Identity).Overdue.Filter((\"LiabilityType\", LiabilityTypes.LRC));", - "\n private IDataCube lrcData => lrcActuarial + accrual;", - "\n ", - "\n private IDataCube bop => lrcData.Filter((\"VariableType\",AocTypes.BOP));", - "\n private IDataCube delta => lrcData.Filter((\"VariableType\",\"!BOP\"),(\"VariableType\",\"!EOP\"))", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = \"D\" });", - "\n private IDataCube eop => lrcData.Filter((\"VariableType\",AocTypes.EOP));", - "\n ", - "\n IDataCube Lrc => bop + delta + eop;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q-X5STJu20-7PdTNWxysqg", - "cell_type": "markdown", - "source": [ - "", - "\n# IFRS 17 Financial Performance" - ], - "metadata": {} - }, - { - "id": "_F85lUYI8USa7GLuh0CFYA", - "cell_type": "markdown", - "source": [ - "The IFRS 17 Financial Performance aims at disclosing the deltas (i.e. difference between EoP and BoP, or the Change in Estimate) of the IFRS 17 Balance Sheet items (LRC, LIC) and the relevant incurred cashflows (Premiums, Claims, Expenses, etc...) for the given period.", - "\n", - "\nIn addition, the IFRS 17 Financial Performance must split the results into at least 4 distinct sections:", - "\n - Insurance Revenue ($IR$)", - "\n - Insurance Service Expense ($ISE$)", - "\n - Insurance Finance Income/Expense ($IFIE$)", - "\n - Other Comprehensive Income ($OCI$)", - "\n", - "\nThese can be structured in a hierarchy, such that aggregation and intermediate results can be shown separately.", - "\nAlso the granularity for some relevant items (e.g. Gross LRC vs Reinsurance LRC) must be split into the different sections, as the notion of Insurance Revenue and Insurance Service Expense must be consistent.", - "\n", - "\nThe overall formulas for each of the sections above are as follows:", - "\n$$", - "\n\\begin{array}{rl}", - "\nIR =& -\\Delta \\text{ Gross Non-Financial LRC } - \\text{ Incurred Incoming Cashflows } - \\text{ Claims Investment Component } + \\text{ Amortization of the Insurance Acquisition Cashflows} - \\text{ Experience Adjustment On Premium }", - "\n\\\\", - "\nISE =& -\\Delta \\text{ Reinsurance Non-Financial LRC } - \\Delta \\text{ Non-Financial LIC } - \\Delta \\text{ Loss Component } - \\text{ Incurred Outgoing Cashflows } - \\text{ Amortization of the Insurance Acquisition Cashflows}", - "\n\\\\", - "\nIFIE =& -\\Delta \\text{ Financial LRC } - \\Delta \\text{ Financial LIC }", - "\n\\\\", - "\nOCI =& \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Valuation Rates } + \\Delta \\text{ LIC at Valuation Rates } - \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Current Rates } - \\Delta \\text{ LIC at Current Rates }", - "\n\\end{array}", - "\n$$", - "\n", - "\nFor CSM, LC and LoReCo (and implicit Amortization Factors / Coverage Units), the yield curve used is according to the methodology choice (e.g. BBA uses Locked-In rates). ", - "\n", - "\nThe Fulfillment Cashflows components for LIC and LRC are discounted using the appropriate yield curve (Locked-In or Current) according to the choice of the OCI option and methodology. We can distinguish 2 cases for the Building Block approach (BBA):", - "\n - BBA, OCI option ***disabled***: FCF computed using Current rates", - "\n - BBA, OCI option ***enabled***: FCF computed using Locked-In rates", - "\n", - "\nIn the case when the OCI option is disabled, the OCI contribution is zero. Otherwise, we have:", - "\n", - "\n$$", - "\n\\begin{array}{rl}", - "\nOCI =& \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Locked-In Rates } + \\Delta \\text{ LIC at Locked-In Rates } - \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Current Rates } - \\Delta \\text{ LIC at Current Rates }", - "\n\\end{array}", - "\n$$", - "\n", - "\nUsually, some more details on the items above are desired (e.g. separating the LRC into its components FCF, RA, CSM/LC or explicitly showing the CSM Amortization vs. other financial/non-financial adjustments to the CSM estimation). These are specific to each implementation and depend on the data granularity (e.g. how the Amount Types, AoC steps are detailed and structured). This level of detail is omitted from the generic documentation presented here, but are implicit to the way each item above is calculated. Nevertheless, this extra granularity is available when the reports are generated and sliced by the corresponding dimensions. " - ], - "metadata": {} - }, - { - "id": "yUjR-vS6yUm5Enx3ZvkzIA", - "cell_type": "markdown", - "source": [ - "## Fulfillment Cashflows (excluding the Loss Component)" - ], - "metadata": {} - }, - { - "id": "y-_vkbeDdk-drcNsqFxKgw", - "cell_type": "markdown", - "source": [ - "Let us first describe the Balance Sheet items, where we need to disclose the Changes in Estimate in the Financial Performance.", - "\nAs mentioned, often the LRC and LIC contributions are broken down into smaller parts for disclosure and reconciliation purposes.", - "\n", - "\nThe Fulfillment Cashflows (which may include onerous contributions in some interpretations when a Loss Component is defined) contributions to the Financial Performance (Insurance Result and OCI) are detailed below.", - "\nThe main requisite is to ensure the right mapping of its non-financial and financial components into the appropriate sections of the Financial Performance.", - "\n", - "\nFurthermore, we also need to distinguish the Reinsurance contributions to the LRC, as they are considered to be expenses and not revenue.", - "\nThe OCI contribution is also performed here, as the only contributions to the OCI come from the FCF under the current methodology assumptions.", - "\nTo all contributions a sign flip is applied. ", - "\n", - "\nIn particular: ", - "\n- Financial component includes the AocType Interest Accreation, Yield Curve Update, and Credit Risk Update,", - "\n- Non-Financial component includes all the remaining AocTypes.", - "\n- Oci component includes the difference between the movement occured in the period computed applying the discounting with the current yield curve and the discounting with the locked-in yield curve.", - "\n", - "\nThe Financial contributions are reported in 'Financial LIC Changes' for a Group of Contract with Liability Type LIC and to 'Financial LRC Changes' for a Group of Contract with Liability Type LRC.", - "\n
The Non Financial contributions are reported in 'Non Financial LIC Changes' for a Group of Contract with Liability Type LIC. For a Group of Contract with Liability Type LRC, they are reported in 'Non-Financial LRC Changes (Exc. CSM Amortization)' for a Group of Insurance Contract and in 'Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo)' for a Group of Reinsurance Contract.", - "\n
The Oci contributions are reported in the 'Other Comprehensive Income' section under 'Financial LIC Changes' or a Group of Contract with Liability Type LIC and to 'Financial LRC Changes' for a Group of Contract with Liability Type LRC." - ], - "metadata": {} - }, - { - "id": "WkhNSKUFjkaCCaIOupDs4w", - "cell_type": "code", - "source": [ - "public interface FcfChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube FcfDeltas => GetScope(Identity).Fcf.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n GetScope(Identity).Fcf.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", - "\n ", - "\n private IDataCube CurrentFcfDeltas => GetScope(Identity).CurrentFcf.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n GetScope(Identity).CurrentFcf.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", - "\n", - "\n // Non-Financial Fp", - "\n private string variableTypeNonFinancial => Identity.Id switch {", - "\n { LiabilityType: LiabilityTypes.LRC, IsReinsurance: false } => \"IR5\",", - "\n { LiabilityType: LiabilityTypes.LRC, IsReinsurance: true } => \"ISE10\",", - "\n { LiabilityType: LiabilityTypes.LIC } => \"ISE12\"", - "\n };", - "\n ", - "\n private IDataCube NonFinancialFcfDeltas => FcfDeltas", - "\n .Filter((\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")); ", - "\n ", - "\n IDataCube FpNonFinancial => -1 * NonFinancialFcfDeltas", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeNonFinancial }); ", - "\n ", - "\n // Financial Fp", - "\n private string variableTypeFpFinancial => Identity.Id switch {", - "\n { LiabilityType: LiabilityTypes.LRC } => \"IFIE1\",", - "\n { LiabilityType: LiabilityTypes.LIC } => \"IFIE2\",", - "\n };", - "\n ", - "\n // OCI ", - "\n private string variableTypeOciFinancial => Identity.Id switch {", - "\n { LiabilityType: LiabilityTypes.LRC } => \"OCI1\",", - "\n { LiabilityType: LiabilityTypes.LIC } => \"OCI2\",", - "\n };", - "\n ", - "\n private IDataCube FinancialFcfDeltas => FcfDeltas.Filter((\"VariableType\", AocTypes.IA)) + ", - "\n FcfDeltas.Filter((\"VariableType\", AocTypes.YCU)) +", - "\n FcfDeltas.Filter((\"VariableType\", AocTypes.CRU));", - "\n ", - "\n IDataCube FpFinancial => -1 * FinancialFcfDeltas", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeFpFinancial});", - "\n", - "\n IDataCube OciFinancial => (FcfDeltas - CurrentFcfDeltas)", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeOciFinancial});", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MlJhmth_qkiiKsC8XSxAdw", - "cell_type": "markdown", - "source": [ - "Subsequently, the Contractual Service Margin (CSM), Loss Component (LC) and Loss Recovery Component (LoReCo) are also divided into non-financial and financial components. In addition the corresponding amortization/releases (CSM Amortization, LC Release and LoReCo Release) are also explicitly shown." - ], - "metadata": {} - }, - { - "id": "yqLNUINQEk2fACiFnKzGhg", - "cell_type": "markdown", - "source": [ - "## Contractual Service Margin (CSM)", - "\n", - "\nCsm contributes to the 'Insurance Revenue' in the case of a Group of Insurance Contract and to the 'Insurance Service Expense' in the case of a Group of Reinsurance Contract and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", - "\nIn particular, the CSM figures are separated in three cathegories: ", - "\n- Amortization (including to AocType Amortization),", - "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", - "\n- Non Financial contributions (including all the remaining AocTypes).", - "\n", - "\n
The Amortization contribution is reported in 'Insurance Revenue' under 'CSM Amortization' or in 'Insurance Service Expense' under 'Reinsurance CSM Amortization' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively. ", - "\n
The Financial contributions are reported in 'Financial LRC Changes'.", - "\n
The Non Financial contributions are reported in 'Non-Financial LRC Changes (Exc. CSM Amortization)' and 'Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo)' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively. " - ], - "metadata": {} - }, - { - "id": "JZhM9-mDEUKaqcD8QoIvCg", - "cell_type": "code", - "source": [ - "public interface CsmChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n ", - "\n private (string amortization, string nonFinancial) variableType => Identity.Id switch {", - "\n { IsReinsurance: false} => (\"IR3\", \"IR5\"),", - "\n { IsReinsurance: true } => (\"ISE7\", \"ISE10\")", - "\n };", - "\n ", - "\n private IDataCube Csm => GetScope(Identity).Csm.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n GetScope(Identity).Csm.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", - "\n ", - "\n IDataCube Amortization => -1 * Csm.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = variableType.amortization });", - "\n ", - "\n IDataCube NonFinancialChanges => -1 * Csm", - "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = variableType.nonFinancial });", - "\n ", - "\n IDataCube FinancialChanges => -1 * (Csm.Filter((\"VariableType\", AocTypes.IA)) +", - "\n Csm.Filter((\"VariableType\", AocTypes.YCU)) +", - "\n Csm.Filter((\"VariableType\", AocTypes.CRU)) )", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yylNI472I0u4OuR1Bllheg", - "cell_type": "markdown", - "source": [ - "## Loss Component (LC)", - "\n", - "\nLC contributes to the 'Insurance Service Expense' and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", - "\nIn particular, the LC figures are separated in three cathegories: ", - "\n- Amortization (including to AocType Amortization),", - "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", - "\n- Non Financial contributions (including all the remaining AocTypes).", - "\n", - "\n
The Amortization contribution is reported in 'Loss Component Release'.", - "\n
The Financial contributions are reported in 'Financial LRC Changes'.", - "\n
The Non Financial contributions are reported in 'Loss Component / LoReCo Changes (Exc. Releases)'." - ], - "metadata": {} - }, - { - "id": "52YpETmY1kmKN_CcZj4cpw", - "cell_type": "code", - "source": [ - "public interface LcChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n ", - "\n private IDataCube Lc => GetScope(Identity).Lc.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n GetScope(Identity).Lc.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", - "\n ", - "\n IDataCube Amortization => -1 * Lc.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE9\" });", - "\n ", - "\n IDataCube NonFinancialChanges => -1 * Lc", - "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", - "\n ", - "\n IDataCube FinancialChanges => -1 * (Lc.Filter((\"VariableType\", AocTypes.IA)) +", - "\n Lc.Filter((\"VariableType\", AocTypes.YCU)) +", - "\n Lc.Filter((\"VariableType\", AocTypes.CRU)) )", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1-0UxQCxX0-LKLJ0MCCYUw", - "cell_type": "markdown", - "source": [ - "## Loss Recovery Component (LoReCo)", - "\n", - "\nLoReCo contributes to the 'Insurance Service Expense' and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", - "\nIn particular, the LoReCo figures are separated in three cathegories: ", - "\n- Amortization (including to AocType Amortization),", - "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", - "\n- Non Financial contributions (including all the remaining AocTypes).", - "\n", - "\n
The Amortization contribution is reported in 'LoReCo Release'.", - "\n
The Financial contributions are reported in 'Financial LRC Changes'.", - "\n
The Non Financial contributions are reported in 'Loss Component / LoReCo Changes (Exc. Releases)'." - ], - "metadata": {} - }, - { - "id": "d6UE4RWht0uRmVVVLSV2VA", - "cell_type": "code", - "source": [ - "public interface LorecoChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n ", - "\n private IDataCube Loreco => GetScope(Identity).Loreco.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n GetScope(Identity).Loreco.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", - "\n ", - "\n IDataCube Amortization => -1 * Loreco.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE8\" });", - "\n ", - "\n IDataCube NonFinancialChanges => -1 * Loreco", - "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", - "\n ", - "\n IDataCube FinancialChanges => -1 * (Loreco.Filter((\"VariableType\", AocTypes.IA)) +", - "\n Loreco.Filter((\"VariableType\", AocTypes.YCU)) +", - "\n Loreco.Filter((\"VariableType\", AocTypes.CRU)) )", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Ugt3GrQOf0Or0r17sFKx6Q", - "cell_type": "markdown", - "source": [ - "## Incurred Actuals" - ], - "metadata": {} - }, - { - "id": "zhrluPCsVUSl09Ib5324jA", - "cell_type": "markdown", - "source": [ - "After the main Balance Sheet items, we need to disclose the Incurred Cashflows (i.e. Actuals) for the period in the Financial Performance (which includes the effect of Advance and Overdue Accruals, but Write-Off amounts are not taken into account).", - "\nAs another requirement, we exclude any investment components explicitly.", - "\n", - "\nThese contributions are splitted by Amount Type to the following sections:", - "\n- Premiums contributions are reported under 'Insurance Revenue' in 'Premiums' section or in 'Insurance Service Expense' under 'Reinsurance Premiums' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively,", - "\n- Claims Non-Investment Component contributions are reported under 'Insurance Revenue' in 'Claims' section,", - "\n- Claims Investment Component contributions are reported under 'Insurance Service Expense' in 'Acquisition Expenses' section and under 'Insurance Revenue' in 'Exc. Investment Components' section with a sign change,", - "\n- Expenses contributions are reported under 'Insurance Service Expense' in 'Expenses' section,", - "\n- Commissions contributions are reported under 'Insurance Service Expense' in 'Commissions' section." - ], - "metadata": {} - }, - { - "id": "UfES8juT2kSi22gODGLDCw", - "cell_type": "code", - "source": [ - "public interface IncurredActuals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube WrittenAndAccruals => GetScope(Identity).Filter((\"VariableType\", \"CF\"));", - "\n ", - "\n private string premiumsVariableType => Identity.Id switch {", - "\n { IsReinsurance: false} => \"IR1\",", - "\n { IsReinsurance: true } => \"ISE1\"", - "\n }; ", - "\n ", - "\n IDataCube Premiums => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.PR))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = premiumsVariableType });", - "\n ", - "\n IDataCube ClaimsNic => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.NIC))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE2\" });", - "\n ", - "\n private IEnumerable ClaimsIco => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO));", - "\n ", - "\n IDataCube ClaimsIcoToIr => ClaimsIco.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR2\" });", - "\n IDataCube ClaimsIcoToIse => (-1 * ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", - "\n ", - "\n IDataCube Expenses => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AE))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE3\" });", - "\n", - "\n IDataCube Commissions => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AC))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE4\" });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LwsvN0yOSkCOVRXLN381JQ", - "cell_type": "markdown", - "source": [ - "## Incurred Deferrals and Acquisition Expenses" - ], - "metadata": {} - }, - { - "id": "wiPCBpKmKUq9k5vGf5XfNg", - "cell_type": "markdown", - "source": [ - "The next item are the Deferrals, where the Amortization is the only contribution explicitly shown, but these do not have any direct impact on the Financial Performance under the current methodology assumptions. The Amortization contribution is here considered with its sign changed. This contribution is allocated under 'Insurance Service Expense' in 'Acquisition Expenses' section and under 'Insurance Revenue' in 'Acquistion Expenses Amortization' section with a sign change. " - ], - "metadata": {} - }, - { - "id": "aSfW_K2sMkiui5Kyu0MiDA", - "cell_type": "code", - "source": [ - "public interface IncurredDeferrals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube Deferrals => GetScope(Identity).Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\"));", - "\n ", - "\n private IDataCube Amortization => -1 * Deferrals", - "\n .Filter((\"VariableType\", AocTypes.AM));", - "\n ", - "\n IDataCube AmortizationToIr => (-1 * Amortization).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR4\" });", - "\n IDataCube AmortizationToIse => Amortization.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE6\" });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "SOtkVo0ffEKckF0hH2Q6YQ", - "cell_type": "markdown", - "source": [ - "## Experience Adjustment on Premium (allocation to CSM vs P&L recognition)" - ], - "metadata": {} - }, - { - "id": "Pgc61JA6rU6RdoGTvHFhIQ", - "cell_type": "markdown", - "source": [ - "The figures disclosed in the Financial Performance as described above consider full Premiums for past, current and future services (for Best Estimate and Actuals).", - "\nHowever, we applied the Premium Allocation factor in the CSM computations to adjust for the experience. To correct this, we need to exclude the Experience Adjustment on Premium part in the Financial Performance to avoid double counting and it is allocated under 'Insurance Revenue' in the 'Exc. Experience Adjustment on Premiums' section." - ], - "metadata": {} - }, - { - "id": "3rmklNkYPkSHioMl14xxiw", - "cell_type": "code", - "source": [ - "public interface ExperienceAdjustmentOnPremium: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n private IDataCube WrittenPremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.APA)).FxData;", - "\n private IDataCube AdvancePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.AAPA)).FxData;", - "\n private IDataCube OverduePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.OAPA)).FxData;", - "\n private IDataCube BestEstimatePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BEPA)).FxData;", - "\n ", - "\n IDataCube ExperienceAdjustmentOnPremium => (WrittenPremiumToCsm + AdvancePremiumToCsm + OverduePremiumToCsm - BestEstimatePremiumToCsm)", - "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", - "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR6\" });", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zr-GVPs8uUWdzPGwaINBrQ", - "cell_type": "markdown", - "source": [ - "## Financial Performance" - ], - "metadata": {} - }, - { - "id": "-aWqJjLyD0qw69pCfTydUg", - "cell_type": "markdown", - "source": [ - "As the last step, all the contributions above are calculated and combined into the Financial Performance, which will be used to generate the final report." - ], - "metadata": {} - }, - { - "id": "3eqY3uzwA0aCp5NOV-TpWw", - "cell_type": "code", - "source": [ - "public interface FinancialPerformance: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", - "\n ", - "\n private IDataCube FcfChangeInEstimate => GetScope(Identity);", - "\n private IDataCube CsmChangeInEstimate => GetScope(Identity);", - "\n private IDataCube LcChangeInEstimate => GetScope(Identity);", - "\n private IDataCube LorecoChangeInEstimate => GetScope(Identity);", - "\n private IDataCube IncurredActuals => GetScope(Identity);", - "\n private IDataCube IncurredDeferrals => GetScope(Identity);", - "\n private IDataCube ExperienceAdjustmentOnPremium => GetScope(Identity);", - "\n ", - "\n IDataCube FinancialPerformance => FcfChangeInEstimate + CsmChangeInEstimate + LcChangeInEstimate + LorecoChangeInEstimate + IncurredActuals + IncurredDeferrals + ExperienceAdjustmentOnPremium;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xgem_L0voUyElSD53tj9BQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Report Scopes (IFRS17 Methodology Business Logic)

", + "\n", + "\nThis notebook contains the logic used to perform calculations upon reporting of data." + ] + }, + { + "cell_type": "markdown", + "source": [ + "# References", + "\nLibraries and other notebooks which are needed for this notebook are imported below." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Notebooks" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportStorage\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Scopes" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Helper Scopes" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Universe" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IUniverse: IScopeWithStorage {}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Transformation" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Retrieve Raw Data" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Data: IScope<(ReportIdentity ReportIdentity, string EstimateType), ReportStorage>, IDataCube {", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", + "\n ", + "\n protected IDataCube RawData => GetStorage().GetVariables(Identity.ReportIdentity, Identity.EstimateType);", + "\n", + "\n private IDataCube RawEops => RawData.Filter((\"VariableType\", AocTypes.EOP));", + "\n private IDataCube NotEopsNotCls => RawData.Filter((\"VariableType\", \"!EOP\"),(\"VariableType\", \"!CL\")); // TODO negation must be hardcoded (also to avoid string concatenation)", + "\n ", + "\n private IDataCube CalculatedCl => (RawEops - NotEopsNotCls)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = AocTypes.CL });", + "\n ", + "\n private IDataCube CalculatedEops => (NotEopsNotCls + CalculatedCl)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => x with { VariableType = AocTypes.EOP, Novelty = Novelties.C });", + "\n ", + "\n IDataCube Data => NotEopsNotCls + CalculatedCl + CalculatedEops;", + "\n}", + "\npublic interface DataWrittenActual: Data {", + "\n IDataCube Data.Data => RawData;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Foreign Exchange (FX) Rates" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Fx: IScope<(string ContractualCurrency, string FunctionalCurrency, FxPeriod FxPeriod, (int, int) Period, CurrencyType CurrencyType), ReportStorage> { ", + "\n private double groupFxRate => Identity.CurrencyType switch {", + "\n CurrencyType.Group => GetStorage().GetFx(Identity.Period, Identity.FunctionalCurrency, GroupCurrency, FxPeriod.Average),", + "\n _ => 1", + "\n };", + "\n ", + "\n private double GetFunctionalFxRate(FxPeriod fxPeriod) => Identity.CurrencyType switch {", + "\n CurrencyType.Contractual => 1,", + "\n _ => GetStorage().GetFx(Identity.Period, Identity.ContractualCurrency, Identity.FunctionalCurrency, fxPeriod)", + "\n };", + "\n ", + "\n double Fx => GetFunctionalFxRate(Identity.FxPeriod) * groupFxRate;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface FxData: IScope<(ReportIdentity ReportIdentity, CurrencyType CurrencyType, string EstimateType), ReportStorage>, IDataCube {", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", + "\n ", + "\n protected IDataCube Data => GetScope((Identity.ReportIdentity, Identity.EstimateType)).Data", + "\n .SelectToDataCube(x => GetScope((Identity.ReportIdentity.ContractualCurrency, ", + "\n Identity.ReportIdentity.FunctionalCurrency, ", + "\n GetStorage().GetFxPeriod(GetStorage().Args.Period, x.VariableType, x.Novelty),", + "\n (Identity.ReportIdentity.Year, Identity.ReportIdentity.Month),", + "\n Identity.CurrencyType", + "\n )).Fx * x);", + "\n ", + "\n private IDataCube Eops => Data.Filter((\"VariableType\", AocTypes.EOP));", + "\n private IDataCube NotEops => Data.Filter((\"VariableType\", \"!EOP\")); // TODO negation must be hardcoded (also to avoid string concatenation)", + "\n ", + "\n private IDataCube Fx => (Eops - NotEops)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = AocTypes.FX });", + "\n ", + "\n IDataCube FxData => Data + Fx;", + "\n}", + "\n", + "\npublic interface FxDataWrittenActual: FxData {", + "\n IDataCube FxData.FxData => Data;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Present Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Best Estimate", + "\n", + "\nBest Estimate of Present Value (PV) report includes contributions from the [Present Value](../Import/ImportScopeCalculation#current-and-locked) calculation. The result of the Locked-in calculation is used when the Valuation Approach is BBA and the flag for Oci is active." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface BestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube BestEstimate => Identity.Id switch {", + "\n { ValuationApproach: ValuationApproaches.BBA, IsOci: true } => GetScope(Identity).LockedBestEstimate,", + "\n _ => GetScope(Identity).CurrentBestEstimate };", + "\n}", + "\n", + "\npublic interface LockedBestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube LockedBestEstimate => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BE)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.L));", + "\n}", + "\n", + "\npublic interface CurrentBestEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube CurrentBestEstimate => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BE)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.C));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Risk Adjustment", + "\n", + "\nRisk Adjustment (RA) report includes contributions from the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) calculation. The result of the Locked-in calculation is used when the Valuation Approach is BBA and the flag for Oci is active." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface RiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube RiskAdjustment => Identity.Id switch {", + "\n { ValuationApproach: ValuationApproaches.BBA, IsOci: true } => GetScope(Identity).LockedRiskAdjustment,", + "\n _ => GetScope(Identity).CurrentRiskAdjustment };", + "\n}", + "\n", + "\npublic interface LockedRiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube LockedRiskAdjustment => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.RA)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.L));", + "\n}", + "\n", + "\npublic interface CurrentRiskAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube CurrentRiskAdjustment => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.RA)).FxData", + "\n .Filter((\"LiabilityType\", Identity.Id.LiabilityType), (\"EconomicBasis\", EconomicBases.C));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Fulfillment Cashflows", + "\nFulfillment Cashflows (FCF) report includes contributions from the [Best Estimate](#best-estimate) of Present Value and [Risk Adjustment](#risk-adjustment) Present Value." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Fcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube BestEstimate => GetScope(Identity).BestEstimate;", + "\n private IDataCube RiskAdjustment => GetScope(Identity).RiskAdjustment;", + "\n ", + "\n IDataCube Fcf => BestEstimate + RiskAdjustment;", + "\n}", + "\n", + "\npublic interface CurrentFcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube { ", + "\n private IDataCube BestEstimate => GetScope(Identity).CurrentBestEstimate;", + "\n private IDataCube RiskAdjustment => GetScope(Identity).CurrentRiskAdjustment;", + "\n ", + "\n IDataCube CurrentFcf => BestEstimate + RiskAdjustment;", + "\n}", + "\n", + "\npublic interface LockedFcf: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube { ", + "\n private IDataCube BestEstimate => GetScope(Identity).LockedBestEstimate;", + "\n private IDataCube RiskAdjustment => GetScope(Identity).LockedRiskAdjustment;", + "\n ", + "\n IDataCube LockedFcf => BestEstimate + RiskAdjustment;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## LRC Technical Margin: CSM, LC, LoReCo", + "\n", + "\nContractual Service Margin (CSM), Loss Component (LC), Loss Recovery Component (LoReCo) reports of the Liability for Remaining Coverage (LRC) include contributions from the calculation of [CSM](../Import/ImportScopeCalculation#csm), [LC](../Import/ImportScopeCalculation#csm), and [LoReCo](../Import/ImportScopeCalculation#csm), respectively." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Csm: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Csm => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.C)).FxData;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Lc: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Lc => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.L)).FxData;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Loreco: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Loreco => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.LR)).FxData;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface LrcTechnicalMargin: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube Csm => GetScope(Identity).Csm;", + "\n private IDataCube Lc => GetScope(Identity).Lc;", + "\n private IDataCube Loreco => GetScope(Identity).Loreco;", + "\n ", + "\n IDataCube LrcTechnicalMargin => Lc + Loreco - 1 * Csm;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Written, Accruals and Deferrals ", + "\n", + "\nWritten Actual (Actual) report includes contributions from the [Actual](../Import/ImportScopeCalculation#actuals) import. ", + "\n
Accrual Actuals (Advance, Overdue Actual) report includes contributions from the [Advance](../Import/ImportScopeCalculation#advance-actuals) and [Overdue](../Import/ImportScopeCalculation#overdue-actuals) Actual calculation.", + "\n
Deferral (Deferral Actual) report includes contributions from the calculation of [Deferral](../Import/ImportScopeCalculation#deferrable-actuals) Actual." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface WrittenAndAccruals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Written => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.A)).FxData;", + "\n IDataCube Advance => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.AA)).FxData;", + "\n IDataCube Overdue => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.OA)).FxData;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Deferrals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube Deferrals => GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.DA)).FxData;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Experience Adjustment", + "\n", + "\nExperience Adjustment (EA) report includes contributions from the [Written](#written-accrual-deferral) Actual report and the [Best Estimate](#best-estimate) of Present Value report (only the *Cash flow* AocStep). " + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ExperienceAdjustment: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube WrittenCashflow => GetScope(Identity).Written", + "\n .Filter((\"VariableType\", AocTypes.CF));", + "\n ", + "\n private IDataCube BestEstimateCashflow => GetScope(Identity).BestEstimate", + "\n .Filter((\"VariableType\", AocTypes.CF))", + "\n .SelectToDataCube(rv => rv with { EconomicBasis = null, Novelty = Novelties.C });", + "\n", + "\n IDataCube ActuarialExperienceAdjustment => WrittenCashflow - BestEstimateCashflow;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## LIC Actuarial (Actuarial Liability for Incurred Claims)", + "\n", + "\nLiability of Incurred Claims (LIC Actuarial) report includes the contributions from [Fulfillment cashflow](#fulfillment-cashflows)." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface LicActuarial: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n IDataCube LicActuarial => GetScope(Identity).CurrentFcf.Filter((\"LiabilityType\", LiabilityTypes.LIC));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## LIC (Liability for Incurred Claims)", + "\n", + "\nLiability of Incurred Claims (LIC) report includes the contributions from [Lic Actuarial](#lic-actuarial) (Fullfilment Cashflow), [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Lic: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube licActuarial => GetScope(Identity).LicActuarial;", + "\n private IDataCube accrual => GetScope(Identity).Advance.Filter((\"LiabilityType\", LiabilityTypes.LIC)) + ", + "\n GetScope(Identity).Overdue.Filter((\"LiabilityType\", LiabilityTypes.LIC));", + "\n private IDataCube licData => licActuarial + accrual;", + "\n ", + "\n private IDataCube bop => licData.Filter((\"VariableType\", AocTypes.BOP));", + "\n private IDataCube delta => licData.Filter((\"VariableType\",\"!BOP\"),(\"VariableType\",\"!EOP\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = \"D\" });", + "\n private IDataCube eop => licData.Filter((\"VariableType\",AocTypes.EOP));", + "\n ", + "\n IDataCube Lic => bop + delta + eop;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## LRC Actuarial (Actuarial Liability for Remaining Coverage)", + "\n", + "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [Fulfillment cashflow](#fulfillment-cashflows), [Contructual Sevice Margin](#technical-margin), [Loss Component](#technical-margin), and [Loss Recovery Component](#technical-margin)." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface LrcActuarial: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube Fcf => GetScope(Identity).CurrentFcf.Filter((\"LiabilityType\", LiabilityTypes.LRC));", + "\n private IDataCube Csm => GetScope(Identity).Csm;", + "\n private IDataCube Loreco => GetScope(Identity).Loreco;", + "\n ", + "\n IDataCube LrcActuarial => Fcf + Csm + Loreco;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## LRC (Liability for Remaining Coverage)", + "\n", + "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [LRC Actuarial](#lrc-actuarial) (Fulfillment Cashflow, Contructual Sevice Margin, Loss Component, Loss Recovery Component) and, [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Lrc: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube lrcActuarial => GetScope(Identity).LrcActuarial;", + "\n private IDataCube accrual => GetScope(Identity).Advance.Filter((\"LiabilityType\", LiabilityTypes.LRC)) + ", + "\n GetScope(Identity).Overdue.Filter((\"LiabilityType\", LiabilityTypes.LRC));", + "\n private IDataCube lrcData => lrcActuarial + accrual;", + "\n ", + "\n private IDataCube bop => lrcData.Filter((\"VariableType\",AocTypes.BOP));", + "\n private IDataCube delta => lrcData.Filter((\"VariableType\",\"!BOP\"),(\"VariableType\",\"!EOP\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(x => Math.Abs(x.Value) >= Precision, x => x with { Novelty = Novelties.C, VariableType = \"D\" });", + "\n private IDataCube eop => lrcData.Filter((\"VariableType\",AocTypes.EOP));", + "\n ", + "\n IDataCube Lrc => bop + delta + eop;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17 Financial Performance" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The IFRS 17 Financial Performance aims at disclosing the deltas (i.e. difference between EoP and BoP, or the Change in Estimate) of the IFRS 17 Balance Sheet items (LRC, LIC) and the relevant incurred cashflows (Premiums, Claims, Expenses, etc...) for the given period.", + "\n", + "\nIn addition, the IFRS 17 Financial Performance must split the results into at least 4 distinct sections:", + "\n - Insurance Revenue ($IR$)", + "\n - Insurance Service Expense ($ISE$)", + "\n - Insurance Finance Income/Expense ($IFIE$)", + "\n - Other Comprehensive Income ($OCI$)", + "\n", + "\nThese can be structured in a hierarchy, such that aggregation and intermediate results can be shown separately.", + "\nAlso the granularity for some relevant items (e.g. Gross LRC vs Reinsurance LRC) must be split into the different sections, as the notion of Insurance Revenue and Insurance Service Expense must be consistent.", + "\n", + "\nThe overall formulas for each of the sections above are as follows:", + "\n$$", + "\n\\begin{array}{rl}", + "\nIR =& -\\Delta \\text{ Gross Non-Financial LRC } - \\text{ Incurred Incoming Cashflows } - \\text{ Claims Investment Component } + \\text{ Amortization of the Insurance Acquisition Cashflows} - \\text{ Experience Adjustment On Premium }", + "\n\\\\", + "\nISE =& -\\Delta \\text{ Reinsurance Non-Financial LRC } - \\Delta \\text{ Non-Financial LIC } - \\Delta \\text{ Loss Component } - \\text{ Incurred Outgoing Cashflows } - \\text{ Amortization of the Insurance Acquisition Cashflows}", + "\n\\\\", + "\nIFIE =& -\\Delta \\text{ Financial LRC } - \\Delta \\text{ Financial LIC }", + "\n\\\\", + "\nOCI =& \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Valuation Rates } + \\Delta \\text{ LIC at Valuation Rates } - \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Current Rates } - \\Delta \\text{ LIC at Current Rates }", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor CSM, LC and LoReCo (and implicit Amortization Factors / Coverage Units), the yield curve used is according to the methodology choice (e.g. BBA uses Locked-In rates). ", + "\n", + "\nThe Fulfillment Cashflows components for LIC and LRC are discounted using the appropriate yield curve (Locked-In or Current) according to the choice of the OCI option and methodology. We can distinguish 2 cases for the Building Block approach (BBA):", + "\n - BBA, OCI option ***disabled***: FCF computed using Current rates", + "\n - BBA, OCI option ***enabled***: FCF computed using Locked-In rates", + "\n", + "\nIn the case when the OCI option is disabled, the OCI contribution is zero. Otherwise, we have:", + "\n", + "\n$$", + "\n\\begin{array}{rl}", + "\nOCI =& \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Locked-In Rates } + \\Delta \\text{ LIC at Locked-In Rates } - \\Delta \\text{ LRC excl. CSM/LC/LoReCo at Current Rates } - \\Delta \\text{ LIC at Current Rates }", + "\n\\end{array}", + "\n$$", + "\n", + "\nUsually, some more details on the items above are desired (e.g. separating the LRC into its components FCF, RA, CSM/LC or explicitly showing the CSM Amortization vs. other financial/non-financial adjustments to the CSM estimation). These are specific to each implementation and depend on the data granularity (e.g. how the Amount Types, AoC steps are detailed and structured). This level of detail is omitted from the generic documentation presented here, but are implicit to the way each item above is calculated. Nevertheless, this extra granularity is available when the reports are generated and sliced by the corresponding dimensions. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Fulfillment Cashflows (excluding the Loss Component)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Let us first describe the Balance Sheet items, where we need to disclose the Changes in Estimate in the Financial Performance.", + "\nAs mentioned, often the LRC and LIC contributions are broken down into smaller parts for disclosure and reconciliation purposes.", + "\n", + "\nThe Fulfillment Cashflows (which may include onerous contributions in some interpretations when a Loss Component is defined) contributions to the Financial Performance (Insurance Result and OCI) are detailed below.", + "\nThe main requisite is to ensure the right mapping of its non-financial and financial components into the appropriate sections of the Financial Performance.", + "\n", + "\nFurthermore, we also need to distinguish the Reinsurance contributions to the LRC, as they are considered to be expenses and not revenue.", + "\nThe OCI contribution is also performed here, as the only contributions to the OCI come from the FCF under the current methodology assumptions.", + "\nTo all contributions a sign flip is applied. ", + "\n", + "\nIn particular: ", + "\n- Financial component includes the AocType Interest Accreation, Yield Curve Update, and Credit Risk Update,", + "\n- Non-Financial component includes all the remaining AocTypes.", + "\n- Oci component includes the difference between the movement occured in the period computed applying the discounting with the current yield curve and the discounting with the locked-in yield curve.", + "\n", + "\nThe Financial contributions are reported in 'Financial LIC Changes' for a Group of Contract with Liability Type LIC and to 'Financial LRC Changes' for a Group of Contract with Liability Type LRC.", + "\n
The Non Financial contributions are reported in 'Non Financial LIC Changes' for a Group of Contract with Liability Type LIC. For a Group of Contract with Liability Type LRC, they are reported in 'Non-Financial LRC Changes (Exc. CSM Amortization)' for a Group of Insurance Contract and in 'Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo)' for a Group of Reinsurance Contract.", + "\n
The Oci contributions are reported in the 'Other Comprehensive Income' section under 'Financial LIC Changes' or a Group of Contract with Liability Type LIC and to 'Financial LRC Changes' for a Group of Contract with Liability Type LRC." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface FcfChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube FcfDeltas => GetScope(Identity).Fcf.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Fcf.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n private IDataCube CurrentFcfDeltas => GetScope(Identity).CurrentFcf.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).CurrentFcf.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n", + "\n // Non-Financial Fp", + "\n private string variableTypeNonFinancial => Identity.Id switch {", + "\n { LiabilityType: LiabilityTypes.LRC, IsReinsurance: false } => \"IR5\",", + "\n { LiabilityType: LiabilityTypes.LRC, IsReinsurance: true } => \"ISE10\",", + "\n { LiabilityType: LiabilityTypes.LIC } => \"ISE12\"", + "\n };", + "\n ", + "\n private IDataCube NonFinancialFcfDeltas => FcfDeltas", + "\n .Filter((\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")); ", + "\n ", + "\n IDataCube FpNonFinancial => -1 * NonFinancialFcfDeltas", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeNonFinancial }); ", + "\n ", + "\n // Financial Fp", + "\n private string variableTypeFpFinancial => Identity.Id switch {", + "\n { LiabilityType: LiabilityTypes.LRC } => \"IFIE1\",", + "\n { LiabilityType: LiabilityTypes.LIC } => \"IFIE2\",", + "\n };", + "\n ", + "\n // OCI ", + "\n private string variableTypeOciFinancial => Identity.Id switch {", + "\n { LiabilityType: LiabilityTypes.LRC } => \"OCI1\",", + "\n { LiabilityType: LiabilityTypes.LIC } => \"OCI2\",", + "\n };", + "\n ", + "\n private IDataCube FinancialFcfDeltas => FcfDeltas.Filter((\"VariableType\", AocTypes.IA)) + ", + "\n FcfDeltas.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n FcfDeltas.Filter((\"VariableType\", AocTypes.CRU));", + "\n ", + "\n IDataCube FpFinancial => -1 * FinancialFcfDeltas", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeFpFinancial});", + "\n", + "\n IDataCube OciFinancial => (FcfDeltas - CurrentFcfDeltas)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeOciFinancial});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Subsequently, the Contractual Service Margin (CSM), Loss Component (LC) and Loss Recovery Component (LoReCo) are also divided into non-financial and financial components. In addition the corresponding amortization/releases (CSM Amortization, LC Release and LoReCo Release) are also explicitly shown." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Contractual Service Margin (CSM)", + "\n", + "\nCsm contributes to the 'Insurance Revenue' in the case of a Group of Insurance Contract and to the 'Insurance Service Expense' in the case of a Group of Reinsurance Contract and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", + "\nIn particular, the CSM figures are separated in three cathegories: ", + "\n- Amortization (including to AocType Amortization),", + "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", + "\n- Non Financial contributions (including all the remaining AocTypes).", + "\n", + "\n
The Amortization contribution is reported in 'Insurance Revenue' under 'CSM Amortization' or in 'Insurance Service Expense' under 'Reinsurance CSM Amortization' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively. ", + "\n
The Financial contributions are reported in 'Financial LRC Changes'.", + "\n
The Non Financial contributions are reported in 'Non-Financial LRC Changes (Exc. CSM Amortization)' and 'Non-Financial Reinsurance LRC Changes (Exc. LC/LoReCo)' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively. " + ] + }, + { + "cell_type": "code", + "source": [ + "public interface CsmChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private (string amortization, string nonFinancial) variableType => Identity.Id switch {", + "\n { IsReinsurance: false} => (\"IR3\", \"IR5\"),", + "\n { IsReinsurance: true } => (\"ISE7\", \"ISE10\")", + "\n };", + "\n ", + "\n private IDataCube Csm => GetScope(Identity).Csm.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Csm.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n IDataCube Amortization => -1 * Csm.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = variableType.amortization });", + "\n ", + "\n IDataCube NonFinancialChanges => -1 * Csm", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = variableType.nonFinancial });", + "\n ", + "\n IDataCube FinancialChanges => -1 * (Csm.Filter((\"VariableType\", AocTypes.IA)) +", + "\n Csm.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n Csm.Filter((\"VariableType\", AocTypes.CRU)) )", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Loss Component (LC)", + "\n", + "\nLC contributes to the 'Insurance Service Expense' and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", + "\nIn particular, the LC figures are separated in three cathegories: ", + "\n- Amortization (including to AocType Amortization),", + "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", + "\n- Non Financial contributions (including all the remaining AocTypes).", + "\n", + "\n
The Amortization contribution is reported in 'Loss Component Release'.", + "\n
The Financial contributions are reported in 'Financial LRC Changes'.", + "\n
The Non Financial contributions are reported in 'Loss Component / LoReCo Changes (Exc. Releases)'." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface LcChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private IDataCube Lc => GetScope(Identity).Lc.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Lc.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n IDataCube Amortization => -1 * Lc.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE9\" });", + "\n ", + "\n IDataCube NonFinancialChanges => -1 * Lc", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", + "\n ", + "\n IDataCube FinancialChanges => -1 * (Lc.Filter((\"VariableType\", AocTypes.IA)) +", + "\n Lc.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n Lc.Filter((\"VariableType\", AocTypes.CRU)) )", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Loss Recovery Component (LoReCo)", + "\n", + "\nLoReCo contributes to the 'Insurance Service Expense' and to the 'Insurance Finance Income/Expense'. To all contributions a sign flip is applied. ", + "\nIn particular, the LoReCo figures are separated in three cathegories: ", + "\n- Amortization (including to AocType Amortization),", + "\n- Financial contributions (including the AocTypes Interest Accreation, Yield Curve Update, and Credit Risk Update),", + "\n- Non Financial contributions (including all the remaining AocTypes).", + "\n", + "\n
The Amortization contribution is reported in 'LoReCo Release'.", + "\n
The Financial contributions are reported in 'Financial LRC Changes'.", + "\n
The Non Financial contributions are reported in 'Loss Component / LoReCo Changes (Exc. Releases)'." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface LorecoChangeInEstimate: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private IDataCube Loreco => GetScope(Identity).Loreco.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n GetScope(Identity).Loreco.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));", + "\n ", + "\n IDataCube Amortization => -1 * Loreco.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE8\" });", + "\n ", + "\n IDataCube NonFinancialChanges => -1 * Loreco", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", + "\n ", + "\n IDataCube FinancialChanges => -1 * (Loreco.Filter((\"VariableType\", AocTypes.IA)) +", + "\n Loreco.Filter((\"VariableType\", AocTypes.YCU)) +", + "\n Loreco.Filter((\"VariableType\", AocTypes.CRU)) )", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE1\" });", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Incurred Actuals" + ] + }, + { + "cell_type": "markdown", + "source": [ + "After the main Balance Sheet items, we need to disclose the Incurred Cashflows (i.e. Actuals) for the period in the Financial Performance (which includes the effect of Advance and Overdue Accruals, but Write-Off amounts are not taken into account).", + "\nAs another requirement, we exclude any investment components explicitly.", + "\n", + "\nThese contributions are splitted by Amount Type to the following sections:", + "\n- Premiums contributions are reported under 'Insurance Revenue' in 'Premiums' section or in 'Insurance Service Expense' under 'Reinsurance Premiums' for a Group of Insurance Contract and a Group of Reinsurance Contract, respectively,", + "\n- Claims Non-Investment Component contributions are reported under 'Insurance Revenue' in 'Claims' section,", + "\n- Claims Investment Component contributions are reported under 'Insurance Service Expense' in 'Acquisition Expenses' section and under 'Insurance Revenue' in 'Exc. Investment Components' section with a sign change,", + "\n- Expenses contributions are reported under 'Insurance Service Expense' in 'Expenses' section,", + "\n- Commissions contributions are reported under 'Insurance Service Expense' in 'Commissions' section." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IncurredActuals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube WrittenAndAccruals => GetScope(Identity).Filter((\"VariableType\", \"CF\"));", + "\n ", + "\n private string premiumsVariableType => Identity.Id switch {", + "\n { IsReinsurance: false} => \"IR1\",", + "\n { IsReinsurance: true } => \"ISE1\"", + "\n }; ", + "\n ", + "\n IDataCube Premiums => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.PR))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = premiumsVariableType });", + "\n ", + "\n IDataCube ClaimsNic => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.NIC))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE2\" });", + "\n ", + "\n private IEnumerable ClaimsIco => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO));", + "\n ", + "\n IDataCube ClaimsIcoToIr => ClaimsIco.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR2\" });", + "\n IDataCube ClaimsIcoToIse => (-1 * ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", + "\n ", + "\n IDataCube Expenses => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AE))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE3\" });", + "\n", + "\n IDataCube Commissions => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AC))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE4\" });", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Incurred Deferrals and Acquisition Expenses" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The next item are the Deferrals, where the Amortization is the only contribution explicitly shown, but these do not have any direct impact on the Financial Performance under the current methodology assumptions. The Amortization contribution is here considered with its sign changed. This contribution is allocated under 'Insurance Service Expense' in 'Acquisition Expenses' section and under 'Insurance Revenue' in 'Acquistion Expenses Amortization' section with a sign change. " + ] + }, + { + "cell_type": "code", + "source": [ + "public interface IncurredDeferrals: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube Deferrals => GetScope(Identity).Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\"));", + "\n ", + "\n private IDataCube Amortization => -1 * Deferrals", + "\n .Filter((\"VariableType\", AocTypes.AM));", + "\n ", + "\n IDataCube AmortizationToIr => (-1 * Amortization).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR4\" });", + "\n IDataCube AmortizationToIse => Amortization.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE6\" });", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Experience Adjustment on Premium (allocation to CSM vs P&L recognition)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The figures disclosed in the Financial Performance as described above consider full Premiums for past, current and future services (for Best Estimate and Actuals).", + "\nHowever, we applied the Premium Allocation factor in the CSM computations to adjust for the experience. To correct this, we need to exclude the Experience Adjustment on Premium part in the Financial Performance to avoid double counting and it is allocated under 'Insurance Revenue' in the 'Exc. Experience Adjustment on Premiums' section." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ExperienceAdjustmentOnPremium: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n private IDataCube WrittenPremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.APA)).FxData;", + "\n private IDataCube AdvancePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.AAPA)).FxData;", + "\n private IDataCube OverduePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.OAPA)).FxData;", + "\n private IDataCube BestEstimatePremiumToCsm => -1 * GetScope((Identity.Id, Identity.CurrencyType, EstimateTypes.BEPA)).FxData;", + "\n ", + "\n IDataCube ExperienceAdjustmentOnPremium => (WrittenPremiumToCsm + AdvancePremiumToCsm + OverduePremiumToCsm - BestEstimatePremiumToCsm)", + "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR6\" });", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Financial Performance" + ] + }, + { + "cell_type": "markdown", + "source": [ + "As the last step, all the contributions above are calculated and combined into the Financial Performance, which will be used to generate the final report." + ] + }, + { + "cell_type": "code", + "source": [ + "public interface FinancialPerformance: IScope<(ReportIdentity Id, CurrencyType CurrencyType), ReportStorage>, IDataCube {", + "\n ", + "\n private IDataCube FcfChangeInEstimate => GetScope(Identity);", + "\n private IDataCube CsmChangeInEstimate => GetScope(Identity);", + "\n private IDataCube LcChangeInEstimate => GetScope(Identity);", + "\n private IDataCube LorecoChangeInEstimate => GetScope(Identity);", + "\n private IDataCube IncurredActuals => GetScope(Identity);", + "\n private IDataCube IncurredDeferrals => GetScope(Identity);", + "\n private IDataCube ExperienceAdjustmentOnPremium => GetScope(Identity);", + "\n ", + "\n IDataCube FinancialPerformance => FcfChangeInEstimate + CsmChangeInEstimate + LcChangeInEstimate + LorecoChangeInEstimate + IncurredActuals + IncurredDeferrals + ExperienceAdjustmentOnPremium;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Report/ReportStorage.ipynb b/Report/ReportStorage.ipynb index 7eea19f9..477fc0bb 100644 --- a/Report/ReportStorage.ipynb +++ b/Report/ReportStorage.ipynb @@ -1,241 +1,219 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "HEuASoWo4UGVdx8dGf6u_A", - "cell_type": "markdown", - "source": [ - "", - "\n

Report Storage and Identity

", - "\n", - "\nThe Report Identity is a record collecting all information needed to define the granularity in which the calculation are performed.", - "\n", - "\nThe Report Storage collects the required data and parameters used in the calculations.", - "\n", - "\nBoth Storage and Identity are defined to support the calculations defined in the corresponding [Report Scopes](./ReportScopes)." - ], - "metadata": {} - }, - { - "id": "lH7xWMjez0q8ciCz4Qykww", - "cell_type": "code", - "source": [ - "#!import \"ReportConfigurationAndUtils\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2dj3bWBcRkGx9h4euZjMZA", - "cell_type": "markdown", - "source": [ - "# Report Identity" - ], - "metadata": {} - }, - { - "id": "XYiuv9tTxk218jeGK45wwg", - "cell_type": "code", - "source": [ - "[IdentityAggregationBehaviour(IdentityAggregationBehaviour.Aggregate)]", - "\npublic record ReportIdentity {", - "\n ", - "\n [Dimension(typeof(int), nameof(Year))]", - "\n public int Year { get; init; }", - "\n", - "\n [Dimension(typeof(int), nameof(Month))]", - "\n public int Month { get; init; }", - "\n", - "\n [Dimension(typeof(ReportingNode))]", - "\n public string ReportingNode { get; init; }", - "\n ", - "\n [Dimension(typeof(Scenario))]", - "\n public string Scenario { get; init; }", - "\n", - "\n [Dimension(typeof(Currency), nameof(ContractualCurrency))]", - "\n public string ContractualCurrency { get; init; }", - "\n ", - "\n [Dimension(typeof(Currency), nameof(FunctionalCurrency))]", - "\n public string FunctionalCurrency { get; init; }", - "\n", - "\n [NotAggregated]", - "\n [Dimension(typeof(int), nameof(Projection))]", - "\n public int Projection { get; init; }", - "\n", - "\n [Dimension(typeof(LiabilityType))]", - "\n public string LiabilityType { get; init; }", - "\n ", - "\n [Dimension(typeof(ValuationApproach))]", - "\n public string ValuationApproach { get; init; }", - "\n ", - "\n public bool IsReinsurance { get; init; } //TODO use ReinsuranceType", - "\n ", - "\n public bool IsOci { get; init; } ", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Xp1yqkllkEeactK1U1Wfbw", - "cell_type": "markdown", - "source": [ - "# Report Storage" - ], - "metadata": {} - }, - { - "id": "vXC3nuN1jUaN-35vvZ9pWA", - "cell_type": "code", - "source": [ - "public class ReportStorage {", - "\n protected readonly IWorkspace workspace;", - "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchicalDimensionCache;", - "\n private readonly Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory;", - "\n ", - "\n // Current Storage Settings", - "\n public ((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args {get; private set;}", - "\n ", - "\n // Cache for Aux Data ", - "\n private Dictionary<(int year, int month), Dictionary>> exchangeRatesByCurrencyByFxTypeAndPeriod = new(); // Fx Rates", - "\n private Dictionary<(int year, int month), Dictionary> fxPeriodsByAocStepAndPeriod = new(); // FxParameter", - "\n ", - "\n public HashSet EstimateTypesWithoutAoc {get; private set;}", - "\n ", - "\n // Cache for Variables and Parameters", - "\n private Dictionary<((int year, int month) period, string reportingNode, string scenario), Dictionary>>> variablesDictionary = new();", - "\n ", - "\n // Constructor", - "\n public ReportStorage(IWorkspace workspace, Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory) {", - "\n this.workspace = workspace;", - "\n this.hierarchicalDimensionCache = workspace.ToHierarchicalDimensionCache();", - "\n this.reportFactory = reportFactory;", - "\n }", - "\n ", - "\n // Initializers", - "\n public async Task InitializeReportIndependentCacheAsync() {", - "\n // Hierarchical Dimensions", - "\n hierarchicalDimensionCache.Initialize();", - "\n hierarchicalDimensionCache.Initialize(); ", - "\n hierarchicalDimensionCache.Initialize();", - "\n hierarchicalDimensionCache.Initialize();", - "\n }", - "\n ", - "\n public async Task InitializeAsync((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType) {", - "\n // Report Dependent Cache", - "\n", - "\n // Setting the Args --> Temp for the moment", - "\n Args = (period, reportingNode, scenario, currencyType);", - "\n ", - "\n EstimateTypesWithoutAoc = (await workspace.Query().Where(x => x.StructureType != StructureType.AoC).Select(x => x.SystemName).ToArrayAsync()).ToHashSet();", - "\n ", - "\n // FX && Fx Parameters", - "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType) || !fxPeriodsByAocStepAndPeriod.TryGetValue(period, out var fxPeriodsByAocStep)) {", - "\n exchangeRatesByCurrencyByFxType = await workspace.GetExchangeRatesDictionaryAsync(period.year, period.month);", - "\n exchangeRatesByCurrencyByFxTypeAndPeriod.Add(period, exchangeRatesByCurrencyByFxType);", - "\n fxPeriodsByAocStep = (await workspace.LoadAocStepConfigurationAsync(period.year, period.month)).Where(x => x.FxPeriod != FxPeriod.NotApplicable).ToDictionary(x => new AocStep(x.AocType, x.Novelty), x => (FxPeriod)x.FxPeriod);", - "\n fxPeriodsByAocStepAndPeriod.Add(period, fxPeriodsByAocStep);", - "\n }", - "\n ", - "\n // Variables", - "\n foreach(var rn in GetLeaves(reportingNode)) { ", - "\n if(!variablesDictionary.TryGetValue((period, rn, scenario), out var variablesByIdentity)) {", - "\n variablesByIdentity = (await workspace.QueryReportVariablesAsync((period.year, period.month, rn, scenario)))", - "\n .ToDictionaryGrouped(x => new ReportIdentity {", - "\n Year = period.year,", - "\n Month = period.month,", - "\n ReportingNode = x.ReportingNode,", - "\n Scenario = x.Scenario,", - "\n Projection = x.Projection,", - "\n ContractualCurrency = x.ContractualCurrency,", - "\n FunctionalCurrency = x.FunctionalCurrency,", - "\n ValuationApproach = x.ValuationApproach,", - "\n LiabilityType = x.LiabilityType,", - "\n IsReinsurance = x.IsReinsurance,", - "\n IsOci = !string.IsNullOrWhiteSpace(x.OciType) },", - "\n x => x.ToDictionaryGrouped(y => y.EstimateType,", - "\n y => y.ToArray().ToDataCube()));", - "\n ", - "\n variablesDictionary.Add((period, rn, scenario), variablesByIdentity);", - "\n }", - "\n }", - "\n }", - "\n ", - "\n // Getters for Data", - "\n public IDataCube GetVariables(ReportIdentity reportIdentity, params string[] estimateTypes)", - "\n => (!variablesDictionary.TryGetValue(((reportIdentity.Year, reportIdentity.Month), reportIdentity.ReportingNode, reportIdentity.Scenario), out var variablesByIdentity) || !variablesByIdentity.TryGetValue(reportIdentity, out var variablesByEstimateType))", - "\n ? Enumerable.Empty().ToDataCube()", - "\n : estimateTypes.Length switch {", - "\n 0 => variablesByEstimateType.SelectMany(x => x.Value).ToDataCube(),", - "\n 1 => variablesByEstimateType.TryGetValue(estimateTypes.First(), out var variables)", - "\n ? variables.ToDataCube()", - "\n : Enumerable.Empty().ToDataCube(),", - "\n _ => estimateTypes.Select(et => variablesByEstimateType.TryGetValue(et, out var variables)", - "\n ? variables.ToDataCube()", - "\n : Enumerable.Empty())", - "\n .Aggregate((x, y) => x.Concat(y))", - "\n .ToDataCube()", - "\n };", - "\n ", - "\n // Other getters", - "\n public IWorkspace Workspace => workspace;", - "\n public Systemorph.Vertex.Pivot.Reporting.IReportFactory Report => reportFactory;", - "\n", - "\n public Systemorph.Vertex.Hierarchies.IHierarchy GetHierarchy() where T : class, IHierarchicalDimension => hierarchicalDimensionCache.Get();", - "\n ", - "\n public HashSet<(ReportIdentity, CurrencyType)> GetIdentities((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType)", - "\n => GetLeaves(reportingNode)", - "\n .SelectMany(rn => variablesDictionary.TryGetValue((period, rn, scenario), out var inner) ? inner.Keys.Select(x => (x, currencyType)) : Enumerable.Empty<(ReportIdentity, CurrencyType)>())", - "\n .ToHashSet();", - "\n ", - "\n public double GetFx((int year, int month) period, string currentCurrency, string targetCurrency, FxPeriod fxPeriod) {", - "\n if (currentCurrency == targetCurrency) return 1;", - "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType))", - "\n throw new Exception ($\"No exchange rates for Period {period} were found.\");", - "\n return GetCurrencyToGroupFx(exchangeRatesByCurrencyByFxType, currentCurrency, fxPeriod, GroupCurrency)", - "\n / GetCurrencyToGroupFx(exchangeRatesByCurrencyByFxType, targetCurrency, fxPeriod, GroupCurrency);", - "\n }", - "\n ", - "\n public FxPeriod GetFxPeriod((int year, int month) period, string aocType, string novelty) => fxPeriodsByAocStepAndPeriod[period][new AocStep(aocType, novelty)];", - "\n ", - "\n // Helpers", - "\n public HashSet GetLeaves(string systemName) where T : class, IHierarchicalDimension {", - "\n var descendants = hierarchicalDimensionCache.Get(systemName).Descendants(includeSelf: true);", - "\n return descendants.Where(x => !descendants.Select(y => y.Parent).Contains(x.SystemName)).Select(x => x.SystemName).ToHashSet();", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Gl9OQV-72kGG19Hx1igOHw", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Report Storage and Identity

", + "\n", + "\nThe Report Identity is a record collecting all information needed to define the granularity in which the calculation are performed.", + "\n", + "\nThe Report Storage collects the required data and parameters used in the calculations.", + "\n", + "\nBoth Storage and Identity are defined to support the calculations defined in the corresponding [Report Scopes](./ReportScopes)." + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportConfigurationAndUtils\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Report Identity" + ] + }, + { + "cell_type": "code", + "source": [ + "[IdentityAggregationBehaviour(IdentityAggregationBehaviour.Aggregate)]", + "\npublic record ReportIdentity {", + "\n ", + "\n [Dimension(typeof(int), nameof(Year))]", + "\n public int Year { get; init; }", + "\n", + "\n [Dimension(typeof(int), nameof(Month))]", + "\n public int Month { get; init; }", + "\n", + "\n [Dimension(typeof(ReportingNode))]", + "\n public string ReportingNode { get; init; }", + "\n ", + "\n [Dimension(typeof(Scenario))]", + "\n public string Scenario { get; init; }", + "\n", + "\n [Dimension(typeof(Currency), nameof(ContractualCurrency))]", + "\n public string ContractualCurrency { get; init; }", + "\n ", + "\n [Dimension(typeof(Currency), nameof(FunctionalCurrency))]", + "\n public string FunctionalCurrency { get; init; }", + "\n", + "\n [NotAggregated]", + "\n [Dimension(typeof(int), nameof(Projection))]", + "\n public int Projection { get; init; }", + "\n", + "\n [Dimension(typeof(LiabilityType))]", + "\n public string LiabilityType { get; init; }", + "\n ", + "\n [Dimension(typeof(ValuationApproach))]", + "\n public string ValuationApproach { get; init; }", + "\n ", + "\n public bool IsReinsurance { get; init; } //TODO use ReinsuranceType", + "\n ", + "\n public bool IsOci { get; init; } ", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Report Storage" + ] + }, + { + "cell_type": "code", + "source": [ + "public class ReportStorage {", + "\n protected readonly IWorkspace workspace;", + "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchicalDimensionCache;", + "\n private readonly Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory;", + "\n ", + "\n // Current Storage Settings", + "\n public ((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args {get; private set;}", + "\n ", + "\n // Cache for Aux Data ", + "\n private Dictionary<(int year, int month), Dictionary>> exchangeRatesByCurrencyByFxTypeAndPeriod = new(); // Fx Rates", + "\n private Dictionary<(int year, int month), Dictionary> fxPeriodsByAocStepAndPeriod = new(); // FxParameter", + "\n ", + "\n public HashSet EstimateTypesWithoutAoc {get; private set;}", + "\n ", + "\n // Cache for Variables and Parameters", + "\n private Dictionary<((int year, int month) period, string reportingNode, string scenario), Dictionary>>> variablesDictionary = new();", + "\n ", + "\n // Constructor", + "\n public ReportStorage(IWorkspace workspace, Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory) {", + "\n this.workspace = workspace;", + "\n this.hierarchicalDimensionCache = workspace.ToHierarchicalDimensionCache();", + "\n this.reportFactory = reportFactory;", + "\n }", + "\n ", + "\n // Initializers", + "\n public async Task InitializeReportIndependentCacheAsync() {", + "\n // Hierarchical Dimensions", + "\n hierarchicalDimensionCache.Initialize();", + "\n hierarchicalDimensionCache.Initialize(); ", + "\n hierarchicalDimensionCache.Initialize();", + "\n hierarchicalDimensionCache.Initialize();", + "\n }", + "\n ", + "\n public async Task InitializeAsync((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType) {", + "\n // Report Dependent Cache", + "\n", + "\n // Setting the Args --> Temp for the moment", + "\n Args = (period, reportingNode, scenario, currencyType);", + "\n ", + "\n EstimateTypesWithoutAoc = (await workspace.Query().Where(x => x.StructureType != StructureType.AoC).Select(x => x.SystemName).ToArrayAsync()).ToHashSet();", + "\n ", + "\n // FX && Fx Parameters", + "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType) || !fxPeriodsByAocStepAndPeriod.TryGetValue(period, out var fxPeriodsByAocStep)) {", + "\n exchangeRatesByCurrencyByFxType = await workspace.GetExchangeRatesDictionaryAsync(period.year, period.month);", + "\n exchangeRatesByCurrencyByFxTypeAndPeriod.Add(period, exchangeRatesByCurrencyByFxType);", + "\n fxPeriodsByAocStep = (await workspace.LoadAocStepConfigurationAsync(period.year, period.month)).Where(x => x.FxPeriod != FxPeriod.NotApplicable).ToDictionary(x => new AocStep(x.AocType, x.Novelty), x => (FxPeriod)x.FxPeriod);", + "\n fxPeriodsByAocStepAndPeriod.Add(period, fxPeriodsByAocStep);", + "\n }", + "\n ", + "\n // Variables", + "\n foreach(var rn in GetLeaves(reportingNode)) { ", + "\n if(!variablesDictionary.TryGetValue((period, rn, scenario), out var variablesByIdentity)) {", + "\n variablesByIdentity = (await workspace.QueryReportVariablesAsync((period.year, period.month, rn, scenario)))", + "\n .ToDictionaryGrouped(x => new ReportIdentity {", + "\n Year = period.year,", + "\n Month = period.month,", + "\n ReportingNode = x.ReportingNode,", + "\n Scenario = x.Scenario,", + "\n Projection = x.Projection,", + "\n ContractualCurrency = x.ContractualCurrency,", + "\n FunctionalCurrency = x.FunctionalCurrency,", + "\n ValuationApproach = x.ValuationApproach,", + "\n LiabilityType = x.LiabilityType,", + "\n IsReinsurance = x.IsReinsurance,", + "\n IsOci = !string.IsNullOrWhiteSpace(x.OciType) },", + "\n x => x.ToDictionaryGrouped(y => y.EstimateType,", + "\n y => y.ToArray().ToDataCube()));", + "\n ", + "\n variablesDictionary.Add((period, rn, scenario), variablesByIdentity);", + "\n }", + "\n }", + "\n }", + "\n ", + "\n // Getters for Data", + "\n public IDataCube GetVariables(ReportIdentity reportIdentity, params string[] estimateTypes)", + "\n => (!variablesDictionary.TryGetValue(((reportIdentity.Year, reportIdentity.Month), reportIdentity.ReportingNode, reportIdentity.Scenario), out var variablesByIdentity) || !variablesByIdentity.TryGetValue(reportIdentity, out var variablesByEstimateType))", + "\n ? Enumerable.Empty().ToDataCube()", + "\n : estimateTypes.Length switch {", + "\n 0 => variablesByEstimateType.SelectMany(x => x.Value).ToDataCube(),", + "\n 1 => variablesByEstimateType.TryGetValue(estimateTypes.First(), out var variables)", + "\n ? variables.ToDataCube()", + "\n : Enumerable.Empty().ToDataCube(),", + "\n _ => estimateTypes.Select(et => variablesByEstimateType.TryGetValue(et, out var variables)", + "\n ? variables.ToDataCube()", + "\n : Enumerable.Empty())", + "\n .Aggregate((x, y) => x.Concat(y))", + "\n .ToDataCube()", + "\n };", + "\n ", + "\n // Other getters", + "\n public IWorkspace Workspace => workspace;", + "\n public Systemorph.Vertex.Pivot.Reporting.IReportFactory Report => reportFactory;", + "\n", + "\n public Systemorph.Vertex.Hierarchies.IHierarchy GetHierarchy() where T : class, IHierarchicalDimension => hierarchicalDimensionCache.Get();", + "\n ", + "\n public HashSet<(ReportIdentity, CurrencyType)> GetIdentities((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType)", + "\n => GetLeaves(reportingNode)", + "\n .SelectMany(rn => variablesDictionary.TryGetValue((period, rn, scenario), out var inner) ? inner.Keys.Select(x => (x, currencyType)) : Enumerable.Empty<(ReportIdentity, CurrencyType)>())", + "\n .ToHashSet();", + "\n ", + "\n public double GetFx((int year, int month) period, string currentCurrency, string targetCurrency, FxPeriod fxPeriod) {", + "\n if (currentCurrency == targetCurrency) return 1;", + "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType))", + "\n throw new Exception ($\"No exchange rates for Period {period} were found.\");", + "\n return GetCurrencyToGroupFx(exchangeRatesByCurrencyByFxType, currentCurrency, fxPeriod, GroupCurrency)", + "\n / GetCurrencyToGroupFx(exchangeRatesByCurrencyByFxType, targetCurrency, fxPeriod, GroupCurrency);", + "\n }", + "\n ", + "\n public FxPeriod GetFxPeriod((int year, int month) period, string aocType, string novelty) => fxPeriodsByAocStepAndPeriod[period][new AocStep(aocType, novelty)];", + "\n ", + "\n // Helpers", + "\n public HashSet GetLeaves(string systemName) where T : class, IHierarchicalDimension {", + "\n var descendants = hierarchicalDimensionCache.Get(systemName).Descendants(includeSelf: true);", + "\n return descendants.Where(x => !descendants.Select(y => y.Parent).Contains(x.SystemName)).Select(x => x.SystemName).ToHashSet();", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Report/Reports.ipynb b/Report/Reports.ipynb index 99f0a490..a79b4e9a 100644 --- a/Report/Reports.ipynb +++ b/Report/Reports.ipynb @@ -1,516 +1,388 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "1U3-hU_f80qwkFwNsbnfIQ", - "cell_type": "markdown", - "source": [ - "

Reports

", - "\n", - "\n" - ], - "metadata": {} - }, - { - "id": "me2hD-9UBkqUzPChAMdGSA", - "cell_type": "markdown", - "source": [ - "# Infrastructure and Configuration" - ], - "metadata": {} - }, - { - "id": "u0H8pAlgYkS1PDtJ2VPLCw", - "cell_type": "markdown", - "source": [ - "## Initialize data" - ], - "metadata": {} - }, - { - "id": "uGtbh5xjQkit56ozbyiS5g", - "cell_type": "code", - "source": [ - "/* DataSource is configured and connected to real database */", - "\n//#!eval-notebook \"../Database/Configure\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TDC5BXyEaEeRJ3z9MmQClw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jZ-XCFkJ2kqGHwxkU5vMWA", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QyUqnd2bSkOLW_SKU1cJBw", - "cell_type": "markdown", - "source": [ - "## Imports and Configurations" - ], - "metadata": {} - }, - { - "id": "I99Rcm-9LUmvvSjstjY9Hw", - "cell_type": "code", - "source": [ - "#!import \"ReportScopes\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LpptbT8Q_ESVOFAw3M1HQg", - "cell_type": "code", - "source": [ - "var reportStorage = new ReportStorage(Workspace, Report);", - "\nawait reportStorage.InitializeReportIndependentCacheAsync();", - "\nvar mostRecentPartition = (await Workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last();", - "\nvar reportingNodeRoot = (await Workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName;", - "\nawait reportStorage.InitializeAsync((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);", - "\nvar identities = reportStorage.GetIdentities((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "COjZVjOdgkSk8q3E6JHEgg", - "cell_type": "markdown", - "source": [ - "## Calling Scope" - ], - "metadata": {} - }, - { - "id": "SMyYdCikXUua1hdjbI4OmA", - "cell_type": "code", - "source": [ - "var universe = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "538kYx9ba0GWU4_h7XqOqA", - "cell_type": "markdown", - "source": [ - "# Report Settings and Storage Update" - ], - "metadata": {} - }, - { - "id": "UuYESB0ub0-pmUPR8T6jIQ", - "cell_type": "code", - "source": [ - "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", - "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n //((2021, 12), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", - "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", - "\n ;", - "\n", - "\nawait reportStorage.InitializeAsync(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);", - "\nidentities = reportStorage.GetIdentities(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "spXqsA5i2k-QnXdIiPiN8g", - "cell_type": "markdown", - "source": [ - "# Present Value" - ], - "metadata": {} - }, - { - "id": "D2Y8VUl5EkSZ6EaxxjHxQw", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedBestEstimate + universe.GetScopes(identities).Aggregate().CurrentBestEstimate)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IB3NvnT2k0uFqLZP9EBMAw", - "cell_type": "markdown", - "source": [ - "# Risk Adjustment" - ], - "metadata": {} - }, - { - "id": "Vx4bYAkCsE2OfLFbPg380w", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedRiskAdjustment + universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"EconomicBasis\", \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ncU2iZ7tvEy2fxjWmU3Iqg", - "cell_type": "markdown", - "source": [ - "# Actuals" - ], - "metadata": {} - }, - { - "id": "lUNkYQ-KvUqVSA4cxDP-cg", - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Written", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"AmountType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 450)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5p79FR5-wUKCtkk4E1UKsQ", - "cell_type": "markdown", - "source": [ - "## Advance, Overdue Actuals" - ], - "metadata": {} - }, - { - "id": "9xxC0nELUk6ZaH6064_mqw", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Advance + universe.GetScopes(identities).Aggregate().Overdue)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions(reportHeight: 400)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5wuvd2c6O02jxhFkFp49GA", - "cell_type": "markdown", - "source": [ - "## Deferrable Actuals" - ], - "metadata": {} - }, - { - "id": "FlZFgvuEikyv4qcH6xvZYw", - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Deferrals", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 400)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MAO2KskzTEeZSNhRJLd0Zg", - "cell_type": "markdown", - "source": [ - "# Fulfilment Cashflow" - ], - "metadata": {} - }, - { - "id": "yQAAlgUfUkuF5u60nLLPcw", - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Fcf ", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")//, \"EstimateType\")//, \"AmountType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uF8DY0mc7UqiiYqQ6l6uxQ", - "cell_type": "markdown", - "source": [ - "# Actuarial Experience Adjustment" - ], - "metadata": {} - }, - { - "id": "HhH_UKImy0CsdcsI6-f6NA", - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().ActuarialExperienceAdjustment", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"AmountType\" )//\"LiabilityType\", \"EstimateType\")", - "\n .ReportGridOptions(reportHeight: 300, headerColumnWidth: 300)", - "\n .ToReport() " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4P1Lq_n2rkC67MsvbYyLeg", - "cell_type": "markdown", - "source": [ - "# LRC Technical Margin" - ], - "metadata": {} - }, - { - "id": "2qHsCZAs806CvGJgBNEVVQ", - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().LrcTechnicalMargin", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 600)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3F3PhlQxqkWBa0AnU5W6mA", - "cell_type": "markdown", - "source": [ - "# Contractual Service Margin / Loss Component / Loss Recovery Component" - ], - "metadata": {} - }, - { - "id": "gs0gMZiNAk2Jx8IKLuVcvA", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Csm + universe.GetScopes(identities).Aggregate().Lc + universe.GetScopes(identities).Aggregate().Loreco)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "39j6UxhSA0uSJNFLzSMRYg", - "cell_type": "markdown", - "source": [ - "# LRC Actuarial" - ], - "metadata": {} - }, - { - "id": "4kG8l2FHpkCjcnv-q5Rwkw", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LrcActuarial)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"LiabilityType\",\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Igfu5McpcUa4ORph4McI6g", - "cell_type": "markdown", - "source": [ - "# LRC" - ], - "metadata": {} - }, - { - "id": "jQtxFjgD9U2imsZ5CiVx2g", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lrc)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType),\"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions(300)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dZ8KVTA4WkuJZdxC09iuiQ", - "cell_type": "markdown", - "source": [ - "# LIC Actuarial" - ], - "metadata": {} - }, - { - "id": "CAXoAvfKdk6VKSgwRZplgA", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LicActuarial)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q1RxJxSTCk2zVjInVNdAzg", - "cell_type": "markdown", - "source": [ - "# LIC" - ], - "metadata": {} - }, - { - "id": "rc1o2W9lvUOBLnbn-MxRRw", - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lic)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions(300)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dI-BtkhyEkOSQkwJRxs0dQ", - "cell_type": "markdown", - "source": [ - "# Financial Performance" - ], - "metadata": {} - }, - { - "id": "e7jpS8lNhE2913hj-FXjxw", - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().FinancialPerformance", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CIY_4o8vO0KJafPttQEQcA", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Reports

", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Initialize data" + ] + }, + { + "cell_type": "code", + "source": [ + "/* DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"../Database/Configure\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportScopes\"" + ] + }, + { + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();", + "\nvar mostRecentPartition = (await Workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last();", + "\nvar reportingNodeRoot = (await Workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName;", + "\nawait reportStorage.InitializeAsync((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);", + "\nvar identities = reportStorage.GetIdentities((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Calling Scope" + ] + }, + { + "cell_type": "code", + "source": [ + "var universe = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Report Settings and Storage Update" + ] + }, + { + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", + "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n //((2021, 12), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", + "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", + "\n ;", + "\n", + "\nawait reportStorage.InitializeAsync(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);", + "\nidentities = reportStorage.GetIdentities(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Present Value" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedBestEstimate + universe.GetScopes(identities).Aggregate().CurrentBestEstimate)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Risk Adjustment" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedRiskAdjustment + universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"EconomicBasis\", \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Written", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"AmountType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 450)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Advance, Overdue Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Advance + universe.GetScopes(identities).Aggregate().Overdue)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions(reportHeight: 400)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Deferrable Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Deferrals", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 400)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Fulfilment Cashflow" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Fcf ", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")//, \"EstimateType\")//, \"AmountType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Actuarial Experience Adjustment" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().ActuarialExperienceAdjustment", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"AmountType\" )//\"LiabilityType\", \"EstimateType\")", + "\n .ReportGridOptions(reportHeight: 300, headerColumnWidth: 300)", + "\n .ToReport() " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LRC Technical Margin" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().LrcTechnicalMargin", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 600)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Contractual Service Margin / Loss Component / Loss Recovery Component" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Csm + universe.GetScopes(identities).Aggregate().Lc + universe.GetScopes(identities).Aggregate().Loreco)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LRC Actuarial" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LrcActuarial)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"LiabilityType\",\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LRC" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lrc)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType),\"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions(300)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LIC Actuarial" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LicActuarial)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LIC" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lic)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions(300)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Financial Performance" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().FinancialPerformance", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", + "\n .ToReport()" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/AocStructureTest.ipynb b/Test/AocStructureTest.ipynb index b2411ca2..e0b1a671 100644 --- a/Test/AocStructureTest.ipynb +++ b/Test/AocStructureTest.ipynb @@ -1,704 +1,568 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "htuauFORRUW_vpe-m5qdCw", - "cell_type": "markdown", - "source": [ - "

Test Aoc Management

" - ], - "metadata": {} - }, - { - "id": "PeSv4LBGr0qLd08ewzJ6WA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6hiubyTezEuZjfp-gctWmw", - "cell_type": "markdown", - "source": [ - "# Workspace Initialization " - ], - "metadata": {} - }, - { - "id": "54oSWDPLHEuTAVk-tNUBfA", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "JNf9Tz4s4UG65OvUoirk8Q", - "cell_type": "markdown", - "source": [ - "# Test" - ], - "metadata": {} - }, - { - "id": "LYX1kYxLHEyxrah6NZumRA", - "cell_type": "code", - "source": [ - "var args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", - "\nvar partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", - "\n x.Month == args.Month && x.Scenario == args.Scenario);", - "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MfcAgK-1_ECiXK9qP48R_Q", - "cell_type": "code", - "source": [ - "public async Task CheckAocStepStructureAsync(IEnumerable inputVariables, ", - "\n Dictionary> parentBm, ", - "\n Dictionary referenceBm, ", - "\n Dictionary> fullAocBm,", - "\n Dictionary> parentBmCdr = null)", - "\n{", - "\n //Save test input data", - "\n var importFormat = ImportFormats.Cashflow;", - "\n var inputSource = InputSource.Cashflow;", - "\n if (inputVariables.First() is RawVariable)", - "\n {", - "\n await Workspace.UpdateAsync(inputVariables.Cast());", - "\n }", - "\n if (inputVariables.First() is IfrsVariable)", - "\n {", - "\n await Workspace.UpdateAsync(inputVariables.Cast());", - "\n importFormat = ImportFormats.Actual;", - "\n inputSource = InputSource.Actual;", - "\n }", - "\n ", - "\n var newArgs = args with {ImportFormat = importFormat };", - "\n //Set up import storage and test universe", - "\n var testStorage = new ImportStorage(newArgs, DataSource, Workspace);", - "\n await testStorage.InitializeAsync();", - "\n var isReinsurance = testStorage.DataNodeDataBySystemName[inputVariables.First().DataNode].IsReinsurance;", - "\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();", - "\n //Clean up Workspace", - "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", - "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", - "\n ", - "\n var errors = new List();", - "\n ", - "\n var goc = inputVariables.First().DataNode;", - "\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == goc)).SelectMany(s => s.Identities);", - "\n ", - "\n //Assert Parents", - "\n if (importFormat != ImportFormats.Actual)", - "\n {", - "\n var parents = testUniverse.GetScopes(identities.Select(id => (object)(id, \"PR\")), o => o.WithStorage(testStorage)).Where(x => x.Values != Enumerable.Empty()).ToArray();", - "\n if (parentBm.Count() != parents.Count()) ", - "\n {", - "\n var computedIds = parents.Select(s => $\"AocType:{s.Identity.Id.AocType}, Novelty:{s.Identity.Id.Novelty}\");", - "\n var expectedIds = parentBm.Keys.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", - "\n errors.Add( $\"Parent count does not match expected: \\n Computed {parents.Count()} \\n {string.Join(\"\\n\", computedIds)} \\n Expected {parentBm.Count()} \\n {string.Join(\"\\n\", expectedIds)}.\" );", - "\n }", - "\n ", - "\n foreach(var kvp in parentBm)", - "\n {", - "\n var scopeParents = parents.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", - "\n if(scopeParents.Count() != 1)", - "\n errors.Add( $\"Parent not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", - "\n else{", - "\n var scopeParent = scopeParents.First();", - "\n if( kvp.Value.Intersect(scopeParent.Values).Count() != kvp.Value.Count() ||", - "\n kvp.Value.Intersect(scopeParent.Values).Count() != scopeParent.Values.Count()){", - "\n var computedAocSteps = scopeParent.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", - "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", - "\n errors.Add( $\"Parents of {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed: \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", - "\n }", - "\n }", - "\n }", - "\n ", - "\n //Parents for CDR", - "\n if(isReinsurance)", - "\n {", - "\n var parentsCdr = testUniverse.GetScopes(identities.Select(id => (object)(id, AmountTypes.CDR)), o => o.WithStorage(testStorage));", - "\n ", - "\n var countP = parentsCdr.Where(x => x.Values != Enumerable.Empty()).Count();", - "\n if (parentBmCdr.Count() != countP) ", - "\n errors.Add( $\"Parent count for AmountType CDR does not match expected: \\n Computed {countP} \\n Expected {parentBm.Count()}.\" );", - "\n ", - "\n foreach(var kvp in parentBmCdr)", - "\n {", - "\n var scopeParents = parentsCdr.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", - "\n if(scopeParents.Count() != 1)", - "\n errors.Add( $\"Parent for CDR not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", - "\n else{", - "\n var scopeParent = scopeParents.First();", - "\n if( kvp.Value.Intersect(scopeParent.Values).Count() != kvp.Value.Count() || ", - "\n kvp.Value.Intersect(scopeParent.Values).Count() != scopeParent.Values.Count() ){", - "\n var computedAocSteps = scopeParent.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", - "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", - "\n errors.Add( $\"Parents of {kvp.Key.AocType}, {kvp.Key.Novelty} for AmountType CDR do not match expected value: \\n Computed: \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", - "\n }", - "\n }", - "\n } ", - "\n }", - "\n }", - "\n ", - "\n //Assert Reference", - "\n if (importFormat != ImportFormats.Actual)", - "\n {", - "\n var reference = testUniverse.GetScopes(identities, o => o.WithStorage(testStorage)).ToArray();", - "\n var countR = reference.Select(x => x.Value).Count();", - "\n if (referenceBm.Count() != countR) ", - "\n errors.Add( $\"Reference count does not match expected: \\n Computed {countR} \\n Expected {referenceBm.Count()}.\" );", - "\n ", - "\n foreach(var kvp in referenceBm)", - "\n {", - "\n var scopeReferences = reference.Where(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", - "\n if(scopeReferences.Count() != 1)", - "\n errors.Add( $\"Reference not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", - "\n else{", - "\n var scopeReference = scopeReferences.First();", - "\n if( kvp.Value.AocType != scopeReference.Value.AocType || kvp.Value.Novelty != scopeReference.Value.Novelty )", - "\n errors.Add( $\"Reference of {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed {scopeReference.Value} \\n Expected {kvp.Value}.\" );", - "\n }", - "\n }", - "\n }", - "\n ", - "\n //Assert FullAoc", - "\n var fullAoc = testUniverse.GetScopes(identities.Select(id => (object)(id, inputSource)), o => o.WithStorage(testStorage)).Where(s => s.Values.Any());", - "\n var count = fullAoc.Count();", - "\n if (fullAocBm.Count() != count)", - "\n {", - "\n var computedAocSteps = fullAoc.Select(x => $\"AocType:{x.Identity.Id.AocType}, Novelty:{x.Identity.Id.Novelty}\");", - "\n var benchmarkKeys = fullAocBm.Keys.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", - "\n errors.Add( $\"Full Aoc count does not match expected: \\n Computed {count} \\n Expected {fullAocBm.Count()}.\" ); ", - "\n errors.Add( $\"In particular, \\n Computed Identities \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected \\n {string.Join(\"\\n\", benchmarkKeys)}.\" ); ", - "\n }", - "\n ", - "\n foreach(var kvp in fullAocBm)", - "\n {", - "\n var scopeAocFulls = fullAoc.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", - "\n if(scopeAocFulls.Count() != 1){", - "\n errors.Add( $\"Full AocStep not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");}", - "\n else{", - "\n var scopeAocFull = scopeAocFulls.First();", - "\n if( kvp.Value.Intersect(scopeAocFull.Values).Count() != kvp.Value.Count() || ", - "\n kvp.Value.Intersect(scopeAocFull.Values).Count() != scopeAocFull.Values.Count() ){", - "\n var computedAocSteps = scopeAocFull.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", - "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", - "\n errors.Add( $\"AocFull for {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", - "\n }", - "\n }", - "\n }", - "\n ", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}", - "\n" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sEcSO-bqzkGlpQkC24-htw", - "cell_type": "markdown", - "source": [ - "# Use Cases" - ], - "metadata": {} - }, - { - "id": "sFPFk32D7kKGHRGhl37IyA", - "cell_type": "markdown", - "source": [ - "## Gross Cashflow: InForce, NewBusiness, and Combined" - ], - "metadata": {} - }, - { - "id": "_X2FswBBHkucp_w7bEqyxQ", - "cell_type": "code", - "source": [ - "var groupOfContract = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6ZmdltQ8CUOJk6c8XSMxMg", - "cell_type": "code", - "source": [ - "var inputRawVariables = new RawVariable[]{", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "EMS3W2YP1EqkmV577yS3hg", - "cell_type": "code", - "source": [ - "var parentBm = new Dictionary>()", - "\n {", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", - "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cgrcf9GgL0qpSZnalLTzEw", - "cell_type": "code", - "source": [ - "var referenceBm = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", - "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", - "\n {new AocStep(\"BOP\",\"N\"), new AocStep(\"BOP\",\"N\")},", - "\n {new AocStep(\"CF\",\"N\"), new AocStep(\"BOP\",\"N\")},", - "\n {new AocStep(\"IA\",\"N\"), new AocStep(\"BOP\",\"N\")},", - "\n {new AocStep(\"EV\",\"N\"), new AocStep(\"EV\",\"N\")},", - "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Wpd4fY5nQkmaPPkyvSEzSQ", - "cell_type": "code", - "source": [ - "var fullAocBm = new Dictionary>()", - "\n {", - "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", - "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"IA\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", - "\n //{new AocStep(\"BOP\",\"N\"), Enumerable.Empty()},", - "\n {new AocStep(\"CF\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", - "\n {new AocStep(\"IA\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\")}},", - "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\")}},", - "\n ", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"),", - "\n }},", - "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), ", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", - "\n new AocStep(\"CL\",\"C\"),", - "\n }},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", - "\n new AocStep(\"EA\",\"C\"), new AocStep(\"CL\",\"C\"),", - "\n }},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", - "\n new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\"),", - "\n }},", - "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", - "\n ", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oYv6SIpvrU6FXuQerivFwg", - "cell_type": "code", - "source": [ - "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zbuVbeynlkiuaJciPMHc-A", - "cell_type": "markdown", - "source": [ - "## Reinsurance Cashflow: InForce, NewBusiness, and Combined" - ], - "metadata": {} - }, - { - "id": "lEAJ2MIIVkKmGnzEBLjE5g", - "cell_type": "code", - "source": [ - "groupOfContract = \"DTR1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jeehsZ9rD0uLhdYDkJo9sQ", - "cell_type": "code", - "source": [ - "inputRawVariables = new RawVariable[]{", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2Oou9pdvEU65Hdaz4jGLnw", - "cell_type": "code", - "source": [ - "parentBm = new Dictionary>()", - "\n {", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}},", - "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}}, ", - "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fd9Sd0Ya9kSZbiDpI3tpJw", - "cell_type": "code", - "source": [ - "var parentBm_CDR = new Dictionary>()", - "\n {", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", - "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}}, ", - "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"CRU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "naCBsHzkPk60cOaBsv40Fg", - "cell_type": "code", - "source": [ - "referenceBm = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", - "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"RCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", - "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", - "\n {new AocStep(\"CRU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", - "\n {new AocStep(\"BOP\",\"N\"), new AocStep(\"BOP\",\"N\")},", - "\n {new AocStep(\"CF\",\"N\"), new AocStep(\"BOP\",\"N\")},", - "\n {new AocStep(\"IA\",\"N\"), new AocStep(\"BOP\",\"N\")},", - "\n {new AocStep(\"EV\",\"N\"), new AocStep(\"EV\",\"N\")},", - "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "A_BMNMYCE0irAqOEzK1Beg", - "cell_type": "code", - "source": [ - "fullAocBm = new Dictionary>()", - "\n {", - "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"RCU\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", - "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", - "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"IA\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", - "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", - "\n //{new AocStep(\"BOP\",\"N\"), Enumerable.Empty()},", - "\n {new AocStep(\"CF\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", - "\n {new AocStep(\"IA\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\")}},", - "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\")}},", - "\n ", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"),", - "\n }},", - "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", - "\n new AocStep(\"CL\",\"C\"),", - "\n }},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", - "\n new AocStep(\"EA\",\"C\"), new AocStep(\"CL\",\"C\"),", - "\n }},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", - "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", - "\n new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\"),", - "\n }},", - "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", - "\n ", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ThWShXVvcUeceCGqOsJthQ", - "cell_type": "code", - "source": [ - "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm, parentBm_CDR)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8u10a9u8l0yb0XI7eilD8A", - "cell_type": "markdown", - "source": [ - "## Cashflow: InForce, and Combined" - ], - "metadata": {} - }, - { - "id": "BCk5iXiD6UiLl7KNQkQ1-Q", - "cell_type": "code", - "source": [ - "var groupOfContract = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_XL2aS8gh02VveW4LpykZQ", - "cell_type": "code", - "source": [ - "inputRawVariables = new RawVariable[]{", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Qd3QDM8xY0WrVZsN4inIDg", - "cell_type": "code", - "source": [ - "parentBm = new Dictionary>()", - "\n {", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lf7sWYGVQEijVikbiCG9oQ", - "cell_type": "code", - "source": [ - "referenceBm = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", - "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", - "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", - "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "B6t0lIf3ik-YHWgWpyX0YQ", - "cell_type": "code", - "source": [ - "fullAocBm = new Dictionary>()", - "\n {", - "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", - "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", - "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", - "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", - "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\")}},", - "\n ", - "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"), ", - "\n }},", - "\n ", - "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", - "\n new AocStep(\"CL\",\"C\"),}},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", - "\n new AocStep(\"CL\",\"C\"), new AocStep(\"EA\",\"C\"),}},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", - "\n new AocStep(\"CL\",\"C\"), new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"),}},", - "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qceSk87wOEOmawmXy5Vdag", - "cell_type": "code", - "source": [ - "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lo7SItfxOEOhFjgPs9KTHQ", - "cell_type": "markdown", - "source": [ - "## Actual" - ], - "metadata": {} - }, - { - "id": "LLQgmrk5cUamp-TV5Bw0MA", - "cell_type": "code", - "source": [ - "var groupOfContract = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HHKnGuczVE-EGxdD1vi1JQ", - "cell_type": "code", - "source": [ - "var inputIfrsVariables = new IfrsVariable[]{", - "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"AA\"},", - "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"CF\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"AA\"},", - "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"CF\", Novelty = \"C\", AccidentYear = null, AmountType = \"ACA\", EstimateType = \"A\"},", - "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"WO\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"OA\"},", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yv06kc8H40iji3wgMDEmEg", - "cell_type": "code", - "source": [ - "parentBm = null;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "E62fDv7kNkeH__lCPrFn8g", - "cell_type": "code", - "source": [ - "referenceBm = null;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xNjIoqwi4kqov8CpJoZu5A", - "cell_type": "code", - "source": [ - "fullAocBm = new Dictionary>()", - "\n {", - "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", - "\n {new AocStep(\"CF\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"),}},", - "\n {new AocStep(\"WO\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"),}},", - "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"), new AocStep(\"WO\",\"C\"),}},", - "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"), new AocStep(\"WO\",\"C\"), new AocStep(\"AM\",\"C\"),}},", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cokUNY_q6Eai_BLP8RbvEA", - "cell_type": "code", - "source": [ - "await CheckAocStepStructureAsync(inputIfrsVariables, parentBm, referenceBm, fullAocBm)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QwRsslb8LE-OzVKMQJyfJQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Test Aoc Management

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", + "\nvar partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckAocStepStructureAsync(IEnumerable inputVariables, ", + "\n Dictionary> parentBm, ", + "\n Dictionary referenceBm, ", + "\n Dictionary> fullAocBm,", + "\n Dictionary> parentBmCdr = null)", + "\n{", + "\n //Save test input data", + "\n var importFormat = ImportFormats.Cashflow;", + "\n var inputSource = InputSource.Cashflow;", + "\n if (inputVariables.First() is RawVariable)", + "\n {", + "\n await Workspace.UpdateAsync(inputVariables.Cast());", + "\n }", + "\n if (inputVariables.First() is IfrsVariable)", + "\n {", + "\n await Workspace.UpdateAsync(inputVariables.Cast());", + "\n importFormat = ImportFormats.Actual;", + "\n inputSource = InputSource.Actual;", + "\n }", + "\n ", + "\n var newArgs = args with {ImportFormat = importFormat };", + "\n //Set up import storage and test universe", + "\n var testStorage = new ImportStorage(newArgs, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n var isReinsurance = testStorage.DataNodeDataBySystemName[inputVariables.First().DataNode].IsReinsurance;", + "\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();", + "\n //Clean up Workspace", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", + "\n ", + "\n var errors = new List();", + "\n ", + "\n var goc = inputVariables.First().DataNode;", + "\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == goc)).SelectMany(s => s.Identities);", + "\n ", + "\n //Assert Parents", + "\n if (importFormat != ImportFormats.Actual)", + "\n {", + "\n var parents = testUniverse.GetScopes(identities.Select(id => (object)(id, \"PR\")), o => o.WithStorage(testStorage)).Where(x => x.Values != Enumerable.Empty()).ToArray();", + "\n if (parentBm.Count() != parents.Count()) ", + "\n {", + "\n var computedIds = parents.Select(s => $\"AocType:{s.Identity.Id.AocType}, Novelty:{s.Identity.Id.Novelty}\");", + "\n var expectedIds = parentBm.Keys.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n errors.Add( $\"Parent count does not match expected: \\n Computed {parents.Count()} \\n {string.Join(\"\\n\", computedIds)} \\n Expected {parentBm.Count()} \\n {string.Join(\"\\n\", expectedIds)}.\" );", + "\n }", + "\n ", + "\n foreach(var kvp in parentBm)", + "\n {", + "\n var scopeParents = parents.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", + "\n if(scopeParents.Count() != 1)", + "\n errors.Add( $\"Parent not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", + "\n else{", + "\n var scopeParent = scopeParents.First();", + "\n if( kvp.Value.Intersect(scopeParent.Values).Count() != kvp.Value.Count() ||", + "\n kvp.Value.Intersect(scopeParent.Values).Count() != scopeParent.Values.Count()){", + "\n var computedAocSteps = scopeParent.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", + "\n errors.Add( $\"Parents of {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed: \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", + "\n }", + "\n }", + "\n }", + "\n ", + "\n //Parents for CDR", + "\n if(isReinsurance)", + "\n {", + "\n var parentsCdr = testUniverse.GetScopes(identities.Select(id => (object)(id, AmountTypes.CDR)), o => o.WithStorage(testStorage));", + "\n ", + "\n var countP = parentsCdr.Where(x => x.Values != Enumerable.Empty()).Count();", + "\n if (parentBmCdr.Count() != countP) ", + "\n errors.Add( $\"Parent count for AmountType CDR does not match expected: \\n Computed {countP} \\n Expected {parentBm.Count()}.\" );", + "\n ", + "\n foreach(var kvp in parentBmCdr)", + "\n {", + "\n var scopeParents = parentsCdr.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", + "\n if(scopeParents.Count() != 1)", + "\n errors.Add( $\"Parent for CDR not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", + "\n else{", + "\n var scopeParent = scopeParents.First();", + "\n if( kvp.Value.Intersect(scopeParent.Values).Count() != kvp.Value.Count() || ", + "\n kvp.Value.Intersect(scopeParent.Values).Count() != scopeParent.Values.Count() ){", + "\n var computedAocSteps = scopeParent.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", + "\n errors.Add( $\"Parents of {kvp.Key.AocType}, {kvp.Key.Novelty} for AmountType CDR do not match expected value: \\n Computed: \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", + "\n }", + "\n }", + "\n } ", + "\n }", + "\n }", + "\n ", + "\n //Assert Reference", + "\n if (importFormat != ImportFormats.Actual)", + "\n {", + "\n var reference = testUniverse.GetScopes(identities, o => o.WithStorage(testStorage)).ToArray();", + "\n var countR = reference.Select(x => x.Value).Count();", + "\n if (referenceBm.Count() != countR) ", + "\n errors.Add( $\"Reference count does not match expected: \\n Computed {countR} \\n Expected {referenceBm.Count()}.\" );", + "\n ", + "\n foreach(var kvp in referenceBm)", + "\n {", + "\n var scopeReferences = reference.Where(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", + "\n if(scopeReferences.Count() != 1)", + "\n errors.Add( $\"Reference not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");", + "\n else{", + "\n var scopeReference = scopeReferences.First();", + "\n if( kvp.Value.AocType != scopeReference.Value.AocType || kvp.Value.Novelty != scopeReference.Value.Novelty )", + "\n errors.Add( $\"Reference of {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed {scopeReference.Value} \\n Expected {kvp.Value}.\" );", + "\n }", + "\n }", + "\n }", + "\n ", + "\n //Assert FullAoc", + "\n var fullAoc = testUniverse.GetScopes(identities.Select(id => (object)(id, inputSource)), o => o.WithStorage(testStorage)).Where(s => s.Values.Any());", + "\n var count = fullAoc.Count();", + "\n if (fullAocBm.Count() != count)", + "\n {", + "\n var computedAocSteps = fullAoc.Select(x => $\"AocType:{x.Identity.Id.AocType}, Novelty:{x.Identity.Id.Novelty}\");", + "\n var benchmarkKeys = fullAocBm.Keys.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n errors.Add( $\"Full Aoc count does not match expected: \\n Computed {count} \\n Expected {fullAocBm.Count()}.\" ); ", + "\n errors.Add( $\"In particular, \\n Computed Identities \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected \\n {string.Join(\"\\n\", benchmarkKeys)}.\" ); ", + "\n }", + "\n ", + "\n foreach(var kvp in fullAocBm)", + "\n {", + "\n var scopeAocFulls = fullAoc.Where(y => y.Identity.Id.AocType == kvp.Key.AocType && y.Identity.Id.Novelty == kvp.Key.Novelty);", + "\n if(scopeAocFulls.Count() != 1){", + "\n errors.Add( $\"Full AocStep not found for AocStep: {kvp.Key.AocType}, {kvp.Key.Novelty}.\");}", + "\n else{", + "\n var scopeAocFull = scopeAocFulls.First();", + "\n if( kvp.Value.Intersect(scopeAocFull.Values).Count() != kvp.Value.Count() || ", + "\n kvp.Value.Intersect(scopeAocFull.Values).Count() != scopeAocFull.Values.Count() ){", + "\n var computedAocSteps = scopeAocFull.Values.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\");", + "\n var expectedAocSteps = kvp.Value.Select(aoc => $\"AocType:{aoc.AocType}, Novelty:{aoc.Novelty}\"); ", + "\n errors.Add( $\"AocFull for {kvp.Key.AocType}, {kvp.Key.Novelty} do not match expected value: \\n Computed \\n {string.Join(\"\\n\", computedAocSteps)} \\n Expected: \\n {string.Join(\"\\n\", expectedAocSteps)}.\" );", + "\n }", + "\n }", + "\n }", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Use Cases" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Gross Cashflow: InForce, NewBusiness, and Combined" + ] + }, + { + "cell_type": "code", + "source": [ + "var groupOfContract = \"DT1.1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputRawVariables = new RawVariable[]{", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n};" + ] + }, + { + "cell_type": "code", + "source": [ + "var parentBm = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "var referenceBm = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"BOP\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep(\"EV\",\"N\")},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "var fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"IA\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n //{new AocStep(\"BOP\",\"N\"), Enumerable.Empty()},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\")}},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\")}},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"),", + "\n }},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), ", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", + "\n ", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Reinsurance Cashflow: InForce, NewBusiness, and Combined" + ] + }, + { + "cell_type": "code", + "source": [ + "groupOfContract = \"DTR1.1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "inputRawVariables = new RawVariable[]{", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n};" + ] + }, + { + "cell_type": "code", + "source": [ + "parentBm = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}}, ", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "var parentBm_CDR = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}}, ", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"CRU\",\"I\"), new AocStep(\"EV\",\"N\"),}},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "referenceBm = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"RCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"BOP\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep(\"BOP\",\"N\")},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep(\"EV\",\"N\")},", + "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"RCU\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"IA\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"CRU\",\"I\"), new AocStep[]{new AocStep(\"YCU\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n //{new AocStep(\"BOP\",\"N\"), Enumerable.Empty()},", + "\n {new AocStep(\"CF\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\")}},", + "\n {new AocStep(\"IA\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\")}},", + "\n {new AocStep(\"EV\",\"N\"), new AocStep[]{new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\")}},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"),", + "\n }},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"RCU\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"),new AocStep(\"YCU\",\"I\"), new AocStep(\"CRU\",\"I\"),", + "\n new AocStep(\"BOP\",\"N\"), new AocStep(\"CF\",\"N\"), new AocStep(\"IA\",\"N\"), new AocStep(\"EV\",\"N\"), ", + "\n new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\"),", + "\n }},", + "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", + "\n ", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm, parentBm_CDR)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Cashflow: InForce, and Combined" + ] + }, + { + "cell_type": "code", + "source": [ + "var groupOfContract = \"DT1.1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "inputRawVariables = new RawVariable[]{", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n};" + ] + }, + { + "cell_type": "code", + "source": [ + "parentBm = new Dictionary>()", + "\n {", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"MC\",\"I\")}}, ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"YCU\",\"I\")}},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "referenceBm = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"), new AocStep(\"BOP\",\"I\")},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep(\"MC\",\"I\")},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep(\"MC\",\"I\")}, ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EA\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep(\"CL\",\"C\")},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep(\"CF\",\"C\")},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"MC\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\")}},", + "\n {new AocStep(\"CF\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\")}},", + "\n {new AocStep(\"IA\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\")}},", + "\n {new AocStep(\"YCU\",\"I\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\")}},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"), new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"), ", + "\n }},", + "\n ", + "\n {new AocStep(\"EA\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"CL\",\"C\"),}},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"CL\",\"C\"), new AocStep(\"EA\",\"C\"),}},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"MC\",\"I\"),new AocStep(\"CF\",\"I\"), new AocStep(\"IA\",\"I\"), new AocStep(\"YCU\",\"I\"),", + "\n new AocStep(\"CL\",\"C\"), new AocStep(\"EA\",\"C\"), new AocStep(\"AM\",\"C\"),}},", + "\n //{new AocStep(\"CF\",\"C\"), Enumerable.Empty()},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputRawVariables, parentBm, referenceBm, fullAocBm)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Actual" + ] + }, + { + "cell_type": "code", + "source": [ + "var groupOfContract = \"DT1.1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputIfrsVariables = new IfrsVariable[]{", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"AA\"},", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"CF\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"AA\"},", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"CF\", Novelty = \"C\", AccidentYear = null, AmountType = \"ACA\", EstimateType = \"A\"},", + "\n new IfrsVariable{Partition = partition.Id, Value = 1.0, DataNode = groupOfContract, AocType = \"WO\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"OA\"},", + "\n};" + ] + }, + { + "cell_type": "code", + "source": [ + "parentBm = null;" + ] + }, + { + "cell_type": "code", + "source": [ + "referenceBm = null;" + ] + }, + { + "cell_type": "code", + "source": [ + "fullAocBm = new Dictionary>()", + "\n {", + "\n //{new AocStep(\"BOP\",\"I\"), Enumerable.Empty()},", + "\n {new AocStep(\"CF\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"),}},", + "\n {new AocStep(\"WO\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"),}},", + "\n {new AocStep(\"AM\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"), new AocStep(\"WO\",\"C\"),}},", + "\n {new AocStep(\"EOP\",\"C\"), new AocStep[]{new AocStep(\"BOP\",\"I\"), new AocStep(\"CF\",\"C\"), new AocStep(\"WO\",\"C\"), new AocStep(\"AM\",\"C\"),}},", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocStepStructureAsync(inputIfrsVariables, parentBm, referenceBm, fullAocBm)" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/ExportIfrsVariable.ipynb b/Test/ExportIfrsVariable.ipynb index 21cad454..bdd3aa38 100644 --- a/Test/ExportIfrsVariable.ipynb +++ b/Test/ExportIfrsVariable.ipynb @@ -1,124 +1,96 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "1fnxMsytI0SV8h59pqZxDQ", - "cell_type": "markdown", - "source": [ - "

Test Reports

" - ], - "metadata": {} - }, - { - "id": "sY2AQGDoZUaMYR5JiSxcjQ", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-xiQumLe30mD77Pvhijxtw", - "cell_type": "markdown", - "source": [ - "# BenchMarks" - ], - "metadata": {} - }, - { - "id": "jOHCgtzBxke3Wk8c8QC1Ug", - "cell_type": "code", - "source": [ - "var pathToBm = \"./Data/ReportBenchmarks/\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LvvPQ9tBmU-4pDW_tCG-1g", - "cell_type": "code", - "source": [ - "var argsArray = new ImportArgs[]{", - "\n new ImportArgs (\"CH\", 2020, 12, Periodicity.Quarterly, null, null),", - "\n new ImportArgs (\"CH\", 2021, 3, Periodicity.Quarterly, null, null)", - "\n };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CnPCEWt_aUe8ts0COdm3ZA", - "cell_type": "code", - "source": [ - "public async Task ExportBenchmarks(ImportArgs args)", - "\n{", - "\n await DataSource.Partition.SetAsync(new {ReportingNode = args.ReportingNode, Year= args.Year, Month = args.Month, Scenario = args.Scenario});", - "\n var computedVariables = (await DataSource.Query().ToArrayAsync()).ToDictionaryGrouped(x => x.EstimateType, x => x.ToArray());", - "\n", - "\n foreach (var estimateType in computedVariables.Keys)", - "\n {", - "\n await Export.ToCsv(pathToBm+\"BM_\"+args.ReportingNode+\"_\"+args.Year.ToString()+\"_\"+args.Month.ToString()+\"_\"+estimateType)", - "\n .WithTable(tableConfig => tableConfig", - "\n .AtBeginning()", - "\n .WithName(Main)", - "\n .WithSource(source => args.RepeatOnce().AsQueryable())", - "\n .WithColumn(x => x.Periodicity, x => x.Delete())", - "\n .WithColumn(x => x.ImportFormat, x => x.Delete())", - "\n )", - "\n .WithTable(tableConfig => tableConfig", - "\n .WithSource(source => computedVariables[estimateType].AsQueryable())", - "\n .WithName(estimateType)", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n )", - "\n .ExecuteAsync();", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "aa_A6kszrU67Ghv0nf-m_g", - "cell_type": "code", - "source": [ - "foreach (var args in argsArray)", - "\n await ExportBenchmarks(args);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "snRElFsmF0OjFLQvRzQNhA", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Test Reports

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# BenchMarks" + ] + }, + { + "cell_type": "code", + "source": [ + "var pathToBm = \"./Data/ReportBenchmarks/\";" + ] + }, + { + "cell_type": "code", + "source": [ + "var argsArray = new ImportArgs[]{", + "\n new ImportArgs (\"CH\", 2020, 12, Periodicity.Quarterly, null, null),", + "\n new ImportArgs (\"CH\", 2021, 3, Periodicity.Quarterly, null, null)", + "\n };" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task ExportBenchmarks(ImportArgs args)", + "\n{", + "\n await DataSource.Partition.SetAsync(new {ReportingNode = args.ReportingNode, Year= args.Year, Month = args.Month, Scenario = args.Scenario});", + "\n var computedVariables = (await DataSource.Query().ToArrayAsync()).ToDictionaryGrouped(x => x.EstimateType, x => x.ToArray());", + "\n", + "\n foreach (var estimateType in computedVariables.Keys)", + "\n {", + "\n await Export.ToCsv(pathToBm+\"BM_\"+args.ReportingNode+\"_\"+args.Year.ToString()+\"_\"+args.Month.ToString()+\"_\"+estimateType)", + "\n .WithTable(tableConfig => tableConfig", + "\n .AtBeginning()", + "\n .WithName(Main)", + "\n .WithSource(source => args.RepeatOnce().AsQueryable())", + "\n .WithColumn(x => x.Periodicity, x => x.Delete())", + "\n .WithColumn(x => x.ImportFormat, x => x.Delete())", + "\n )", + "\n .WithTable(tableConfig => tableConfig", + "\n .WithSource(source => computedVariables[estimateType].AsQueryable())", + "\n .WithName(estimateType)", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n )", + "\n .ExecuteAsync();", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "foreach (var args in argsArray)", + "\n await ExportBenchmarks(args);" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/ExportReportVariables.ipynb b/Test/ExportReportVariables.ipynb index a8002ecb..a079be72 100644 --- a/Test/ExportReportVariables.ipynb +++ b/Test/ExportReportVariables.ipynb @@ -1,186 +1,136 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "TG_x9dWCM0usAoORaJW0wA", - "cell_type": "markdown", - "source": [ - "

Report Variable Exporter

" - ], - "metadata": {} - }, - { - "id": "Y25XYadyL0aU_Fzz5elNMQ", - "cell_type": "markdown", - "source": [ - "# Infrastructure and Configuration" - ], - "metadata": {} - }, - { - "id": "cfjgktx4p0-NVKhru0UtHg", - "cell_type": "markdown", - "source": [ - "## Initialize Workspace" - ], - "metadata": {} - }, - { - "id": "LsMvspLNjUSjzwV8dPfvYA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1HOdfKtqgEyoCXzmZfFBXw", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_REnUbsBBkCMFwqQyGWg5Q", - "cell_type": "markdown", - "source": [ - "## Imports and Configurations" - ], - "metadata": {} - }, - { - "id": "txVLamtljU-DLHzCcz9PnQ", - "cell_type": "code", - "source": [ - "#!import \"ReportVariablesTestBase\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zzDardBj_kKdArEdeDsDNQ", - "cell_type": "markdown", - "source": [ - "## Storage" - ], - "metadata": {} - }, - { - "id": "37AwAO8feEOU3Vi9qBbP4Q", - "cell_type": "code", - "source": [ - "var reportStorage = new ReportStorage(Workspace, Report);", - "\nawait reportStorage.InitializeReportIndependentCacheAsync();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iFTfudfp-EetHuW8yU6YCg", - "cell_type": "markdown", - "source": [ - "## Configurations" - ], - "metadata": {} - }, - { - "id": "2qOI8dJxZ0WPMJf28ue31g", - "cell_type": "code", - "source": [ - "var path = \"./Data/ReportVariableBenchmarks/\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kXndb4zG_UO9VKIhnleT1A", - "cell_type": "markdown", - "source": [ - "# Defining Scope for the Reports and Tests" - ], - "metadata": {} - }, - { - "id": "ZC_lDkxtFEeOujJtQdnaUg", - "cell_type": "markdown", - "source": [ - "### Defining the Period and Reporting Node (...) for the Reports" - ], - "metadata": {} - }, - { - "id": "JIbgXj_2n0K5dfj-X2RJ5A", - "cell_type": "code", - "source": [ - "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType)[] exportScope = {", - "\n ((2020, 12), \"CH\", null, CurrencyType.Contractual),", - "\n// ((2020, 12), \"CH\", null, CurrencyType.Functional),", - "\n// ((2020, 12), \"CH\", null, CurrencyType.Group),", - "\n ", - "\n ((2021, 3), \"CH\", null, CurrencyType.Contractual),", - "\n// ((2021, 3), \"CH\", null, CurrencyType.Functional),", - "\n// ((2021, 3), \"CH\", null, CurrencyType.Group),", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OJE_pdhJBEKChAxri8wv9A", - "cell_type": "markdown", - "source": [ - "# Export" - ], - "metadata": {} - }, - { - "id": "hYzcfGQt4kGKYbKgl9vmqw", - "cell_type": "code", - "source": [ - "foreach(var args in exportScope){", - "\n var scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", - "\n var bmFileName = benchmarkFileNamePrefix + GetBenchmarkFileName(args) + \".csv\";", - "\n await Export.ToCsv(path + bmFileName).WithTable(tableConfig => tableConfig.WithSource(source => scopesData.AsQueryable())).ExecuteAsync(); ", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "plmvGTRjsU60fGgbLWHM3g", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Report Variable Exporter

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Initialize Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportVariablesTestBase\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Storage" + ] + }, + { + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "var path = \"./Data/ReportVariableBenchmarks/\";" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Defining Scope for the Reports and Tests" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Defining the Period and Reporting Node (...) for the Reports" + ] + }, + { + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType)[] exportScope = {", + "\n ((2020, 12), \"CH\", null, CurrencyType.Contractual),", + "\n// ((2020, 12), \"CH\", null, CurrencyType.Functional),", + "\n// ((2020, 12), \"CH\", null, CurrencyType.Group),", + "\n ", + "\n ((2021, 3), \"CH\", null, CurrencyType.Contractual),", + "\n// ((2021, 3), \"CH\", null, CurrencyType.Functional),", + "\n// ((2021, 3), \"CH\", null, CurrencyType.Group),", + "\n};" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Export" + ] + }, + { + "cell_type": "code", + "source": [ + "foreach(var args in exportScope){", + "\n var scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", + "\n var bmFileName = benchmarkFileNamePrefix + GetBenchmarkFileName(args) + \".csv\";", + "\n await Export.ToCsv(path + bmFileName).WithTable(tableConfig => tableConfig.WithSource(source => scopesData.AsQueryable())).ExecuteAsync(); ", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/IfrsVariablesTest.ipynb b/Test/IfrsVariablesTest.ipynb index 7046979f..ab282217 100644 --- a/Test/IfrsVariablesTest.ipynb +++ b/Test/IfrsVariablesTest.ipynb @@ -1,327 +1,271 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "kqZuH1dEnke7hR4QHKoNog", - "cell_type": "markdown", - "source": [ - "

Ifrs Variable

" - ], - "metadata": {} - }, - { - "id": "LjWUwb9UEkuNT2p5nWP59g", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3aLFpM2sG0yzvGW-O9CBrA", - "cell_type": "markdown", - "source": [ - "# BenchMarks" - ], - "metadata": {} - }, - { - "id": "wHzw3mkXwUaee_GWJCqXKA", - "cell_type": "code", - "source": [ - "var pathToBm = \"./Data/IfrsVariableBenchmarks/\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "A-1s2TjE8U2lTB5-1UldnA", - "cell_type": "code", - "source": [ - "public record BenchmarkMetadata(string FileName, string ReportingNode, int Year, int Month){} " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "efhvDjD2pU6uboXYUAfYxw", - "cell_type": "code", - "source": [ - "var bmFiles = new BenchmarkMetadata[]{", - "\n //2020 Q4", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_A.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_AA.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_APA.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_BE.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_BEPA.csv\", \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_C.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_DA.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_F.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_OA.csv\" , \"CH\", 2020, 12),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_RA.csv\" , \"CH\", 2020, 12),", - "\n //2021 Q1", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_A.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_AA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_AAPA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_APA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_BE.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_BEPA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_C.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_DA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_F.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_L.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_LR.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_OA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_OAPA.csv\" , \"CH\", 2021, 3),", - "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_RA.csv\" , \"CH\", 2021, 3),", - "\n};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Q7pARj6RR0K30yyk_I3omg", - "cell_type": "markdown", - "source": [ - "# Functions" - ], - "metadata": {} - }, - { - "id": "iHhg-4yNYEGh4h62o8W5zA", - "cell_type": "code", - "source": [ - "public static NumberStyles AllowedNumberStyles = NumberStyles.Float | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign | NumberStyles.AllowDecimalPoint;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jMFEw9p2r0iOR_Ru9wkGmg", - "cell_type": "code", - "source": [ - "public IfrsVariable CreateVariable (IDataRow row, Guid partition)", - "\n{", - "\n if (!double.TryParse(row[nameof(IfrsVariable.Value)]?.ToString(), AllowedNumberStyles, CultureInfo.InvariantCulture, out var doubleValue))", - "\n throw new Exception(\"Value cannot be parsed.\");", - "\n ", - "\n return new IfrsVariable(){AocType = row.Field(nameof(IfrsVariable.AocType)),", - "\n Partition = partition,", - "\n Novelty = row.Field(nameof(IfrsVariable.Novelty)),", - "\n DataNode = row.Field(nameof(IfrsVariable.DataNode)),", - "\n EstimateType = row.Field(nameof(IfrsVariable.EstimateType)),", - "\n AmountType = row.Field(nameof(IfrsVariable.AmountType)),", - "\n AccidentYear = Int32.TryParse((row.Field(nameof(IfrsVariable.AccidentYear))), out var accidentYear) ? accidentYear : (int?)null,", - "\n EconomicBasis = row.Field(nameof(IfrsVariable.EconomicBasis)),", - "\n Value = (-1.0) * doubleValue,", - "\n };", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nLcASZMlEEmL_nI0yYamvw", - "cell_type": "code", - "source": [ - "public class BenchmarkTestResult", - "\n{", - "\n public string ErrorMessage {get; set;}", - "\n public double ExpectedValue {get; set;}", - "\n public double ComputedValue {get; set;}", - "\n public BenchmarkTestResult (string message)", - "\n {", - "\n ErrorMessage = message;", - "\n }", - "\n public BenchmarkTestResult (string message, double expValue, double compValue)", - "\n {", - "\n ErrorMessage = message;", - "\n ExpectedValue = expValue;", - "\n ComputedValue = compValue; ", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LEHT1hqQo0W96ERHvf4L3A", - "cell_type": "code", - "source": [ - "public List CompareAgainstBm (List errors, IEnumerable expected, IEnumerable computed)", - "\n{", - "\n var expectedNotComputed = expected.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(computed.Select(x => x.ToIdentityString()));", - "\n var computedNotExpected = computed.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(expected.Select(x => x.ToIdentityString()));", - "\n if (expectedNotComputed.Any())", - "\n {", - "\n foreach (var error in expectedNotComputed)", - "\n {", - "\n var message = error.ToIdentityString();", - "\n errors.Add(new BenchmarkTestResult(\"Extra expected variable for: \"+ message));", - "\n }", - "\n }", - "\n if (computedNotExpected.Any())", - "\n {", - "\n foreach (var error in computedNotExpected)", - "\n {", - "\n var message = error.ToIdentityString();", - "\n errors.Add(new BenchmarkTestResult(\"Extra computed variable for: \"+ message));", - "\n }", - "\n }", - "\n ", - "\n var misMatchedVariables = expected.Concat(computed).AggregateOver().Where(x => Math.Abs(x.Value) > BenchmarkPrecision);", - "\n if (misMatchedVariables.Any())", - "\n {", - "\n foreach (var variable in misMatchedVariables)", - "\n {", - "\n var message = variable.ToIdentityString();", - "\n var bmValue = expected.FirstOrDefault(x => x.AocType == variable.AocType && ", - "\n x.Novelty == variable.Novelty &&", - "\n x.DataNode == variable.DataNode && ", - "\n x.EstimateType == variable.EstimateType && ", - "\n x.AmountType == variable.AmountType && ", - "\n x.EconomicBasis == variable.EconomicBasis && ", - "\n x.AccidentYear == variable.AccidentYear", - "\n )?.Value ?? 0.0d;", - "\n var computedValue = computed.FirstOrDefault(x => x.AocType == variable.AocType && ", - "\n x.Novelty == variable.Novelty &&", - "\n x.DataNode == variable.DataNode && ", - "\n x.EstimateType == variable.EstimateType && ", - "\n x.AmountType == variable.AmountType && ", - "\n x.EconomicBasis == variable.EconomicBasis && ", - "\n x.AccidentYear == variable.AccidentYear", - "\n )?.Value ?? 0.0d;", - "\n errors.Add(new BenchmarkTestResult(\"Value does not match for Variable: \" + message, -bmValue, computedValue));", - "\n }", - "\n }", - "\n return errors;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_OGAdCYiJ0WN7EbtgA4faQ", - "cell_type": "markdown", - "source": [ - "# Test Runner" - ], - "metadata": {} - }, - { - "id": "a5OzvwT_d0Gm2H4gGqcvEA", - "cell_type": "code", - "source": [ - "public bool ValidateMainTab(IDataRow mainRow, string reportingNode, int year, int month)", - "\n{", - "\n if (!int.TryParse(mainRow[nameof(PartitionByReportingNodeAndPeriod.Year)]?.ToString(), NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite , CultureInfo.InvariantCulture, out var mainYear))", - "\n throw new Exception(\"Value Year cannot be parsed.\"); ", - "\n if (!int.TryParse(mainRow[nameof(PartitionByReportingNodeAndPeriod.Month)]?.ToString(), NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite , CultureInfo.InvariantCulture, out var mainMonth))", - "\n throw new Exception(\"Value Month cannot be parsed.\"); ", - "\n var mainReportingNode = mainRow[nameof(PartitionByReportingNodeAndPeriod.ReportingNode)].ToString();", - "\n ", - "\n return reportingNode == mainReportingNode && year == mainYear && month == mainMonth;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HeqY0awSAUWsxllqn3M_AQ", - "cell_type": "code", - "source": [ - "var errorList = new List();", - "\n", - "\nforeach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", - "\n{", - "\n var reportingNode = g.Key.ReportingNode;", - "\n var year = g.Key.Year;", - "\n var month = g.Key.Month;", - "\n string scenario = null;", - "\n ", - "\n //Set up Args and storage", - "\n await DataSource.Partition.SetAsync(new {ReportingNode = reportingNode, ", - "\n Year= year, ", - "\n Month = month, ", - "\n Scenario = scenario});", - "\n var partition = (await DataSource.Query().ToArrayAsync())", - "\n .SingleOrDefault(x => x.ReportingNode == reportingNode && x.Year== year && x.Month == month && x.Scenario == scenario)?.Id ?? new Guid();", - "\n ", - "\n var computedVariablesByEstimateType = (await DataSource.Query().ToArrayAsync()).ToDictionaryGrouped(x => x.EstimateType, x => x.ToArray());", - "\n", - "\n foreach (var bmfile in g)", - "\n {", - "\n var extension = System.IO.Path.GetExtension(bmfile.FileName);", - "\n var stream = await Project.FileStorage.ReadAsync(bmfile.FileName);", - "\n //Read Bm csv", - "\n var bmDataTable = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync());", - "\n", - "\n var mainTab = bmDataTable.Tables[Main].Rows.First();", - "\n if(!ValidateMainTab(mainTab, reportingNode, year, month))", - "\n throw new Exception(\"Metadata and main tab of the Benchmark are different.\");", - "\n ", - "\n var bmTableName = bmDataTable.Tables.Single(x => x.TableName != Main).TableName;", - "\n var bmVariables = bmDataTable.Tables[bmTableName].Rows.Select(x => CreateVariable(x, partition));", - "\n ", - "\n //Get the computed Data", - "\n var computedVariables = computedVariablesByEstimateType.TryGetValue(bmTableName, out var ret) ? ret : Enumerable.Empty();", - "\n ", - "\n //CompareAgainstBm", - "\n if (bmVariables.Any() || computedVariables.Any()) //TODO we are adding duplicates here", - "\n errorList = errorList.Concat(CompareAgainstBm(errorList, bmVariables, computedVariables)).ToList();", - "\n }", - "\n}", - "\nerrorList = errorList.Distinct().ToList();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9p0HZCWtX0SPrElo9W915Q", - "cell_type": "code", - "source": [ - "errorList.Count().Should().Be(0)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "EBnAVHo3qEK4kPd1D8kPOw", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Ifrs Variable

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# BenchMarks" + ] + }, + { + "cell_type": "code", + "source": [ + "var pathToBm = \"./Data/IfrsVariableBenchmarks/\";" + ] + }, + { + "cell_type": "code", + "source": [ + "public record BenchmarkMetadata(string FileName, string ReportingNode, int Year, int Month){} " + ] + }, + { + "cell_type": "code", + "source": [ + "var bmFiles = new BenchmarkMetadata[]{", + "\n //2020 Q4", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_A.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_AA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_APA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_BE.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_BEPA.csv\", \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_C.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_DA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_F.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_OA.csv\" , \"CH\", 2020, 12),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2020_12_RA.csv\" , \"CH\", 2020, 12),", + "\n //2021 Q1", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_A.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_AA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_AAPA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_APA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_BE.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_BEPA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_C.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_DA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_F.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_L.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_LR.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_OA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_OAPA.csv\" , \"CH\", 2021, 3),", + "\n new BenchmarkMetadata(pathToBm+\"BM_CH_2021_3_RA.csv\" , \"CH\", 2021, 3),", + "\n};" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Functions" + ] + }, + { + "cell_type": "code", + "source": [ + "public static NumberStyles AllowedNumberStyles = NumberStyles.Float | NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite | NumberStyles.AllowLeadingSign | NumberStyles.AllowTrailingSign | NumberStyles.AllowDecimalPoint;" + ] + }, + { + "cell_type": "code", + "source": [ + "public IfrsVariable CreateVariable (IDataRow row, Guid partition)", + "\n{", + "\n if (!double.TryParse(row[nameof(IfrsVariable.Value)]?.ToString(), AllowedNumberStyles, CultureInfo.InvariantCulture, out var doubleValue))", + "\n throw new Exception(\"Value cannot be parsed.\");", + "\n ", + "\n return new IfrsVariable(){AocType = row.Field(nameof(IfrsVariable.AocType)),", + "\n Partition = partition,", + "\n Novelty = row.Field(nameof(IfrsVariable.Novelty)),", + "\n DataNode = row.Field(nameof(IfrsVariable.DataNode)),", + "\n EstimateType = row.Field(nameof(IfrsVariable.EstimateType)),", + "\n AmountType = row.Field(nameof(IfrsVariable.AmountType)),", + "\n AccidentYear = Int32.TryParse((row.Field(nameof(IfrsVariable.AccidentYear))), out var accidentYear) ? accidentYear : (int?)null,", + "\n EconomicBasis = row.Field(nameof(IfrsVariable.EconomicBasis)),", + "\n Value = (-1.0) * doubleValue,", + "\n };", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public class BenchmarkTestResult", + "\n{", + "\n public string ErrorMessage {get; set;}", + "\n public double ExpectedValue {get; set;}", + "\n public double ComputedValue {get; set;}", + "\n public BenchmarkTestResult (string message)", + "\n {", + "\n ErrorMessage = message;", + "\n }", + "\n public BenchmarkTestResult (string message, double expValue, double compValue)", + "\n {", + "\n ErrorMessage = message;", + "\n ExpectedValue = expValue;", + "\n ComputedValue = compValue; ", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public List CompareAgainstBm (List errors, IEnumerable expected, IEnumerable computed)", + "\n{", + "\n var expectedNotComputed = expected.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(computed.Select(x => x.ToIdentityString()));", + "\n var computedNotExpected = computed.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(expected.Select(x => x.ToIdentityString()));", + "\n if (expectedNotComputed.Any())", + "\n {", + "\n foreach (var error in expectedNotComputed)", + "\n {", + "\n var message = error.ToIdentityString();", + "\n errors.Add(new BenchmarkTestResult(\"Extra expected variable for: \"+ message));", + "\n }", + "\n }", + "\n if (computedNotExpected.Any())", + "\n {", + "\n foreach (var error in computedNotExpected)", + "\n {", + "\n var message = error.ToIdentityString();", + "\n errors.Add(new BenchmarkTestResult(\"Extra computed variable for: \"+ message));", + "\n }", + "\n }", + "\n ", + "\n var misMatchedVariables = expected.Concat(computed).AggregateOver().Where(x => Math.Abs(x.Value) > BenchmarkPrecision);", + "\n if (misMatchedVariables.Any())", + "\n {", + "\n foreach (var variable in misMatchedVariables)", + "\n {", + "\n var message = variable.ToIdentityString();", + "\n var bmValue = expected.FirstOrDefault(x => x.AocType == variable.AocType && ", + "\n x.Novelty == variable.Novelty &&", + "\n x.DataNode == variable.DataNode && ", + "\n x.EstimateType == variable.EstimateType && ", + "\n x.AmountType == variable.AmountType && ", + "\n x.EconomicBasis == variable.EconomicBasis && ", + "\n x.AccidentYear == variable.AccidentYear", + "\n )?.Value ?? 0.0d;", + "\n var computedValue = computed.FirstOrDefault(x => x.AocType == variable.AocType && ", + "\n x.Novelty == variable.Novelty &&", + "\n x.DataNode == variable.DataNode && ", + "\n x.EstimateType == variable.EstimateType && ", + "\n x.AmountType == variable.AmountType && ", + "\n x.EconomicBasis == variable.EconomicBasis && ", + "\n x.AccidentYear == variable.AccidentYear", + "\n )?.Value ?? 0.0d;", + "\n errors.Add(new BenchmarkTestResult(\"Value does not match for Variable: \" + message, -bmValue, computedValue));", + "\n }", + "\n }", + "\n return errors;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Runner" + ] + }, + { + "cell_type": "code", + "source": [ + "public bool ValidateMainTab(IDataRow mainRow, string reportingNode, int year, int month)", + "\n{", + "\n if (!int.TryParse(mainRow[nameof(PartitionByReportingNodeAndPeriod.Year)]?.ToString(), NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite , CultureInfo.InvariantCulture, out var mainYear))", + "\n throw new Exception(\"Value Year cannot be parsed.\"); ", + "\n if (!int.TryParse(mainRow[nameof(PartitionByReportingNodeAndPeriod.Month)]?.ToString(), NumberStyles.AllowLeadingWhite | NumberStyles.AllowTrailingWhite , CultureInfo.InvariantCulture, out var mainMonth))", + "\n throw new Exception(\"Value Month cannot be parsed.\"); ", + "\n var mainReportingNode = mainRow[nameof(PartitionByReportingNodeAndPeriod.ReportingNode)].ToString();", + "\n ", + "\n return reportingNode == mainReportingNode && year == mainYear && month == mainMonth;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var errorList = new List();", + "\n", + "\nforeach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", + "\n{", + "\n var reportingNode = g.Key.ReportingNode;", + "\n var year = g.Key.Year;", + "\n var month = g.Key.Month;", + "\n string scenario = null;", + "\n ", + "\n //Set up Args and storage", + "\n await DataSource.Partition.SetAsync(new {ReportingNode = reportingNode, ", + "\n Year= year, ", + "\n Month = month, ", + "\n Scenario = scenario});", + "\n var partition = (await DataSource.Query().ToArrayAsync())", + "\n .SingleOrDefault(x => x.ReportingNode == reportingNode && x.Year== year && x.Month == month && x.Scenario == scenario)?.Id ?? new Guid();", + "\n ", + "\n var computedVariablesByEstimateType = (await DataSource.Query().ToArrayAsync()).ToDictionaryGrouped(x => x.EstimateType, x => x.ToArray());", + "\n", + "\n foreach (var bmfile in g)", + "\n {", + "\n var extension = System.IO.Path.GetExtension(bmfile.FileName);", + "\n var stream = await Project.FileStorage.ReadAsync(bmfile.FileName);", + "\n //Read Bm csv", + "\n var bmDataTable = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync());", + "\n", + "\n var mainTab = bmDataTable.Tables[Main].Rows.First();", + "\n if(!ValidateMainTab(mainTab, reportingNode, year, month))", + "\n throw new Exception(\"Metadata and main tab of the Benchmark are different.\");", + "\n ", + "\n var bmTableName = bmDataTable.Tables.Single(x => x.TableName != Main).TableName;", + "\n var bmVariables = bmDataTable.Tables[bmTableName].Rows.Select(x => CreateVariable(x, partition));", + "\n ", + "\n //Get the computed Data", + "\n var computedVariables = computedVariablesByEstimateType.TryGetValue(bmTableName, out var ret) ? ret : Enumerable.Empty();", + "\n ", + "\n //CompareAgainstBm", + "\n if (bmVariables.Any() || computedVariables.Any()) //TODO we are adding duplicates here", + "\n errorList = errorList.Concat(CompareAgainstBm(errorList, bmVariables, computedVariables)).ToList();", + "\n }", + "\n}", + "\nerrorList = errorList.Distinct().ToList();" + ] + }, + { + "cell_type": "code", + "source": [ + "errorList.Count().Should().Be(0)" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/ImportStorageTest.ipynb b/Test/ImportStorageTest.ipynb index 93d24cd9..8f9d5663 100644 --- a/Test/ImportStorageTest.ipynb +++ b/Test/ImportStorageTest.ipynb @@ -1,707 +1,595 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "hKqEq5tZqUm8XFAYsSBT8A", - "cell_type": "markdown", - "source": [ - "

Import Storage Test

" - ], - "metadata": {} - }, - { - "id": "a__Hz48NY0-0cWKJL87Vzg", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hLZ53C2rWEanpIfkyRA2Rg", - "cell_type": "markdown", - "source": [ - "# Workspace Initialization " - ], - "metadata": {} - }, - { - "id": "8-W8hpcYnEm17E9gRTCLnQ", - "cell_type": "code", - "source": [ - "Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Dpy4U4VA5U-HxqmmZfHkmw", - "cell_type": "markdown", - "source": [ - "# Test IfrsVariables Query" - ], - "metadata": {} - }, - { - "id": "irUVLmmRJEyCsUkl3sPquQ", - "cell_type": "code", - "source": [ - "var gic = \"DT1.1\";", - "\nvar gric = \"DTR1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dihIAZaujUK6GuXDUo7Y_A", - "cell_type": "code", - "source": [ - "//Define partition", - "\nvar args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Actual);", - "\nvar partition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", - "\n x.Month == args.Month && x.Scenario == args.Scenario);", - "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);", - "\n", - "\nvar previousPeriodPartition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year - 1 && ", - "\n x.Month == MonthInAYear && x.Scenario == args.Scenario);", - "\nif(previousPeriodPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "N8Yf6JjnRU6Q4jUFGmqn3Q", - "cell_type": "code", - "source": [ - "public async Task CheckIfrsVariablesFromImportStorageAsync(string importFormat, IEnumerable inputDataSetForWorkspace, IEnumerable inputDataSetForDataSource, IEnumerable ivsBenchmark)", - "\n{", - "\n //Prepare Workspace and DataSource", - "\n await Workspace.UpdateAsync(inputDataSetForWorkspace);", - "\n await DataSource.UpdateAsync(inputDataSetForDataSource);", - "\n ", - "\n //Set up import storage and test universe", - "\n var testStorage = new ImportStorage(args with {ImportFormat = importFormat}, DataSource, Workspace);", - "\n await testStorage.InitializeAsync();", - "\n ", - "\n var ivs = testStorage.IfrsVariablesByImportIdentity.SelectMany(x => x.Value);", - "\n ", - "\n //Clean up Workspace", - "\n //Workspace.Reset(); ", - "\n await Workspace.DeleteAsync(inputDataSetForWorkspace); ", - "\n await DataSource.DeleteAsync(inputDataSetForDataSource); ", - "\n ", - "\n var errors = new List();", - "\n ", - "\n var extraVariablesInStorage = ivs.Except(ivsBenchmark).Select(x => x.ToIdentityString()).ToArray();", - "\n if(extraVariablesInStorage.Any()) errors.Add( $\"IfrsVariables in the storage contain the following items that are not present in the benchmark:\\n{string.Join(\"\\n\",extraVariablesInStorage)}.\" );", - "\n ", - "\n var extraVariablesInBenchmark = ivsBenchmark.Except(ivs).Select(x => x.ToIdentityString()).ToArray();", - "\n if(extraVariablesInBenchmark.Count() > 0) errors.Add( $\"IfrsVariables in the benchmark contain the following items that are not present in the storage:\\n{string.Join(\"\\n\",extraVariablesInBenchmark)}.\" );", - "\n ", - "\n //find duplicates in storage", - "\n var ivsByIdentityString = ivs.GroupBy(x => x.ToIdentityString()).Where(x => x.Count() > 1).Select(x => x.Key);", - "\n if(ivsByIdentityString.Any()) errors.Add($\"IfrsVariables in the storage have duplicated items for:\\n{string.Join(\"\\n\",ivsByIdentityString)}.\");", - "\n ", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bcPOId_540aVhl-n5wKQCA", - "cell_type": "code", - "source": [ - "//There is a previous year, and it's the first time Actuals are imported for the current year", - "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", - "\nvar inputDataSetForDataSource = new IfrsVariable[]{", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n };", - "\n", - "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", - "\n };", - "\n", - "\nvar ivsBenchmark = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", - "\n };", - "\n", - "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BqLp5tAfAUO_fcHJmxq2_A", - "cell_type": "code", - "source": [ - "//There is a previous year, and it's the second time Actuals are imported for the current year (reimport)", - "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", - "\nvar inputDataSetForDataSource = new IfrsVariable[]{", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 150.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 200.0},", - "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 450.0},", - "\n };", - "\n", - "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", - "\n };", - "\n", - "\nvar ivsBenchmark = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", - "\n };", - "\n", - "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1RKRtwQOPkKisKG03fEbnQ", - "cell_type": "code", - "source": [ - "//There is a previous year, Cashflows were already imported and Actuals are imported for the first time", - "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.I, EstimateType = EstimateTypes.BE};", - "\nvar inputDataSetForDataSource = new IfrsVariable[]{", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = 100.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", - "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", - "\n };", - "\n", - "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.CF, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -15.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -20.0},", - "\n };", - "\n", - "\nvar ivsBenchmark = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", - "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.AA, Value = 100.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -15.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -20.0},", - "\n };", - "\n", - "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jxo0gCLAhUWGDdD50PTpxA", - "cell_type": "code", - "source": [ - "//There is a previous year, Cashflows and Actuals were already imported and Actuals are imported again", - "\nvar basicAdvanceActualIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", - "\nvar basicBeIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.I, EstimateType = EstimateTypes.BE};", - "\nvar inputDataSetForDataSource = new IfrsVariable[]{", - "\n basicBeIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 1000.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", - "\n basicAdvanceActualIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", - "\n basicAdvanceActualIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = 150.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = 200.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.EOP, Value = 450.0},", - "\n };", - "\n", - "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", - "\n };", - "\n", - "\nvar ivsBenchmark = new IfrsVariable[]{", - "\n basicBeIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", - "\n basicBeIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", - "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", - "\n };", - "\n", - "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0BeFF1dpdEmZVGTCvBJgaw", - "cell_type": "code", - "source": [ - "//There is a previous year for Primary Scope (GRIC10) ", - "\n//There is a previous and current year for Secondary Scope (GIC10), ", - "\n//It's the first time Actuals are imported for the current year", - "\n", - "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gric, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", - "\nvar inputDataSetForDataSource = new IfrsVariable[]{", - "\n //Year", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 1000.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.CL, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 666.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 1000.0},", - "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.CL, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 666.0},", - "\n //Year -1", - "\n basicIfrsVariable with {AocType = AocTypes.IA, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", - "\n };", - "\n", - "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", - "\n };", - "\n", - "\nvar ivsBenchmark = new IfrsVariable[]{", - "\n //From previous Period", - "\n //Actuals", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.DA, Value = 1000.0},", - "\n //Cashflow", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 1000.0},", - "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 1000.0},", - "\n ", - "\n //From current Period", - "\n //from DB", - "\n basicIfrsVariable with {AocType = AocTypes.IA, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", - "\n ", - "\n //from workspace", - "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", - "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", - "\n };", - "\n", - "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XRCB3ZClf0-ZJpfkzljWUg", - "cell_type": "markdown", - "source": [ - "# Data Node Parameter related logic" - ], - "metadata": {} - }, - { - "id": "JbLy2z9stkeeonRZwUG3yQ", - "cell_type": "markdown", - "source": [ - "## Data Preparation" - ], - "metadata": {} - }, - { - "id": "RjbciW5_FECXbQhnQZ4DwQ", - "cell_type": "code", - "source": [ - "//Define partition", - "\nvar args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", - "\n", - "\nvar reportingNodePartition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Scenario == args.Scenario);", - "\nif(reportingNodePartition == null) ApplicationMessage.Log(Error.PartitionNotFound);", - "\n", - "\n", - "\nvar currentPartition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", - "\n x.Month == args.Month && x.Scenario == args.Scenario);", - "\nif(currentPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);", - "\n", - "\n", - "\nvar previousPeriodPartition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year - 1 && ", - "\n x.Month == MonthInAYear && x.Scenario == args.Scenario);", - "\nif(previousPeriodPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "E09b-uWxcUa8abPa94ONVA", - "cell_type": "code", - "source": [ - "var sampleGic = new GroupOfInsuranceContract(){Portfolio = \"P1\"};", - "\nvar inputDataGic = new GroupOfInsuranceContract[]{ sampleGic with {SystemName = \"Gross1\", LiabilityType = LiabilityTypes.LRC},", - "\n sampleGic with {SystemName = \"Gross2\", LiabilityType = LiabilityTypes.LRC},", - "\n sampleGic with {SystemName = \"Gross3\", LiabilityType = LiabilityTypes.LRC},", - "\n };", - "\n", - "\nvar sampleGric = new GroupOfReinsuranceContract(){Portfolio = \"ReP1\"};", - "\nvar inputDataGric = new GroupOfReinsuranceContract[]{ sampleGric with {SystemName = \"Reins1\", LiabilityType = LiabilityTypes.LRC},", - "\n sampleGric with {SystemName = \"Reins2\", LiabilityType = LiabilityTypes.LRC},", - "\n sampleGric with {SystemName = \"Reins3\", LiabilityType = LiabilityTypes.LRC},", - "\n };", - "\nvar sampleDnState = new DataNodeState {Partition = reportingNodePartition.Id, Year = args.Year, Month = args.Month, State = State.Active};", - "\nvar inputDataState = new DataNodeState[]{ sampleDnState with {DataNode = \"Gross1\"} ,", - "\n sampleDnState with {DataNode = \"Gross2\"} ,", - "\n sampleDnState with {DataNode = \"Gross3\"} ,", - "\n sampleDnState with {DataNode = \"Reins1\"} ,", - "\n sampleDnState with {DataNode = \"Reins2\"} ,", - "\n sampleDnState with {DataNode = \"Reins3\"} ,", - "\n };", - "\n", - "\nvar samplePreviousDnParam = new InterDataNodeParameter {Partition = reportingNodePartition.Id, ReinsuranceCoverage = 1, Year = args.Year -1, Month = args.Month};", - "\nvar sampleCurrentDnParam = new InterDataNodeParameter {Partition = reportingNodePartition.Id, ReinsuranceCoverage = 1, Year = args.Year, Month = args.Month};", - "\nvar inputDataParameter = new InterDataNodeParameter[]{", - "\n samplePreviousDnParam with {DataNode = \"Gross3\", LinkedDataNode = \"Reins3\", ReinsuranceCoverage = 1},", - "\n samplePreviousDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins1\", ReinsuranceCoverage = 0.1},", - "\n samplePreviousDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.2},", - "\n samplePreviousDnParam with {DataNode = \"Gross2\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.3},", - "\n sampleCurrentDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins1\", ReinsuranceCoverage = 0.5},", - "\n sampleCurrentDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.6},", - "\n sampleCurrentDnParam with {DataNode = \"Gross2\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.7},", - "\n sampleCurrentDnParam with {DataNode = \"Gross3\", LinkedDataNode = \"Reins3\", ReinsuranceCoverage = 1.0},", - "\n };", - "\n", - "\nvar sampleRawVar = new RawVariable{AmountType = AmountTypes.PR, AocType = AocTypes.CL, Novelty = Novelties.C, Partition = currentPartition.Id};" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "o8JTuDpfTkGmD7Wt0jogsQ", - "cell_type": "code", - "source": [ - "public async Task PrepareWorkspaceDataNodes()", - "\n{", - "\n await Workspace.UpdateAsync(inputDataGic);", - "\n await Workspace.UpdateAsync(inputDataGric);", - "\n await Workspace.UpdateAsync(inputDataState);", - "\n await Workspace.UpdateAsync(inputDataParameter);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Ozbv22ctukacRUyws-K7bw", - "cell_type": "code", - "source": [ - "public async Task CleanWorkspaceDataNodes()", - "\n{", - "\n await Workspace.DeleteAsync(inputDataGic);", - "\n await Workspace.DeleteAsync(inputDataGric);", - "\n await Workspace.DeleteAsync(inputDataState);", - "\n await Workspace.DeleteAsync(inputDataParameter);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZYnBpUzNEkWsk0zRWkUu-g", - "cell_type": "markdown", - "source": [ - "## Get Underlying Gic" - ], - "metadata": {} - }, - { - "id": "P-7XAjZPD0i7yEALKAwsnA", - "cell_type": "code", - "source": [ - "public async Task CheckGetUnderlyingGicsAsync(RawVariable[] inputDataVariable, Dictionary> underlyingGicBm)", - "\n{", - "\n var errors = new List();", - "\n ", - "\n await PrepareWorkspaceDataNodes();", - "\n await Workspace.UpdateAsync(inputDataVariable);", - "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", - "\n await testStorage.InitializeAsync();", - "\n ", - "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", - "\n ", - "\n foreach (var dn in primaryScopeDn)", - "\n {", - "\n var id = new ImportIdentity(){DataNode = dn};", - "\n if ( underlyingGicBm[dn].Except(testStorage.GetUnderlyingGic(id)).Count() != 0 )", - "\n errors.Add( $\"Underlying Gics for DataNode {dn} not matching with BM. Computed: \\n{string.Join(\"\\n\",testStorage.GetUnderlyingGic(id))} \\n Expected : \\n{string.Join(\"\\n\",underlyingGicBm[dn])}\" );", - "\n }", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query());", - "\n await CleanWorkspaceDataNodes();", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gr9n4fPaC0-7JF_Wv00Nzw", - "cell_type": "code", - "source": [ - "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", - "\n sampleRawVar with {DataNode = \"Reins2\"},", - "\n };", - "\nvar underlyingGicBm = new Dictionary>(){", - "\n {\"Reins1\",new string[]{\"Gross1\"}},", - "\n {\"Reins2\",new string[]{\"Gross1\",\"Gross2\"}},", - "\n};", - "\n", - "\nawait CheckGetUnderlyingGicsAsync(inputDataVariable, underlyingGicBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "z4P2iM4Dwk2p49Y6p3nVKw", - "cell_type": "code", - "source": [ - "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins2\"},", - "\n };", - "\nvar underlyingGicBm = new Dictionary>(){", - "\n {\"Reins2\",new string[]{\"Gross1\",\"Gross2\"}},", - "\n};", - "\n", - "\nawait CheckGetUnderlyingGicsAsync(inputDataVariable, underlyingGicBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-L7jFDaEmkyVlAyPPIHFHQ", - "cell_type": "markdown", - "source": [ - "## Get Reinsurance Coverage" - ], - "metadata": {} - }, - { - "id": "YwMf2AGd8kWzNmNK5TaXeA", - "cell_type": "code", - "source": [ - "public async Task CheckGetReinsuranceCoverageAsync(RawVariable[] inputDataVariable, ", - "\n Dictionary<(string, string),double> reinsCovBoPBm, ", - "\n Dictionary<(string, string),double> reinsCovEoPBm)", - "\n{", - "\n var errors = new List();", - "\n", - "\n await PrepareWorkspaceDataNodes();", - "\n await Workspace.UpdateAsync(inputDataVariable);", - "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", - "\n await testStorage.InitializeAsync();", - "\n ", - "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", - "\n ", - "\n foreach (var dn in primaryScopeDn)", - "\n {", - "\n var aocTypes = new AocStep[]{ new AocStep(AocTypes.BOP, Novelties.I), new AocStep(AocTypes.RCU, Novelties.I) };", - "\n foreach (var aoc in aocTypes)", - "\n {", - "\n var bm = aoc.AocType == AocTypes.BOP ? reinsCovBoPBm : reinsCovEoPBm;", - "\n var id = new ImportIdentity(){DataNode = dn, AocType = aoc.AocType, Novelty = aoc.Novelty};", - "\n ", - "\n var computedReinsCov = testStorage.GetUnderlyingGic(id)", - "\n .Select(gic => (g: gic, value: testStorage.GetReinsuranceCoverage(id, gic)))", - "\n .ToDictionary(x => (dn,x.g), x => x.value);", - "\n ", - "\n if( bm.Keys.Where(x => x.Item1 == dn).Except(computedReinsCov.Keys).Count() != 0)", - "\n errors.Add( $\"Gric-Gic links not matching with BM for DataNode {dn} and AocType {aoc.AocType}. \\n Computed: \\n{string.Join(\"\\n\",computedReinsCov.Keys)} \\n Expected: \\n{string.Join(\"\\n\",bm.Keys)}\" );", - "\n ", - "\n foreach (var reinsCov in computedReinsCov)", - "\n {", - "\n var bmKvp = bm.Single(x => x.Key.Item1 == reinsCov.Key.Item1 && x.Key.Item2 == reinsCov.Key.Item2); ", - "\n if( Math.Abs(bmKvp.Value - reinsCov.Value) > Precision )", - "\n errors.Add( $\"{dn}-{reinsCov.Key.Item2} Reinsurance Coverage not matching with BM for AocType {aoc.AocType}: \\n Computed: {reinsCov.Value} \\n Expected: {bmKvp.Value}\");", - "\n }", - "\n }", - "\n }", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query());", - "\n await CleanWorkspaceDataNodes();", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bVG2ah0oSUimPFlFmvkYwg", - "cell_type": "code", - "source": [ - "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", - "\n sampleRawVar with {DataNode = \"Reins2\"},", - "\n };", - "\nvar reinsCovBoPBm = new Dictionary<(string, string),double>(){", - "\n {(\"Reins1\",\"Gross1\"),0.1},", - "\n {(\"Reins2\",\"Gross1\"),0.2},", - "\n {(\"Reins2\",\"Gross2\"),0.3},", - "\n};", - "\n", - "\nvar reinsCovEoPBm = new Dictionary<(string, string),double>(){", - "\n {(\"Reins1\",\"Gross1\"),0.5},", - "\n {(\"Reins2\",\"Gross1\"),0.6},", - "\n {(\"Reins2\",\"Gross2\"),0.7},", - "\n};", - "\n", - "\nawait CheckGetReinsuranceCoverageAsync(inputDataVariable, reinsCovBoPBm, reinsCovEoPBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2DHkaQC6A0eHln9BqSBrLA", - "cell_type": "markdown", - "source": [ - "## Primary and Secondary Scope" - ], - "metadata": {} - }, - { - "id": "QxMSzO5gJU2IlukS0y4uIg", - "cell_type": "code", - "source": [ - "public async Task CheckSecondaryScopeAsync(RawVariable[] inputDataVariable, string[] primaryScopeBm, string[] secondaryScopeBm)", - "\n{", - "\n var errors = new List();", - "\n ", - "\n await PrepareWorkspaceDataNodes();", - "\n await Workspace.UpdateAsync(inputDataVariable);", - "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", - "\n await testStorage.InitializeAsync();", - "\n ", - "\n var activeDn = (await Workspace.Query().ToArrayAsync()).Select(x => x.DataNode);", - "\n ", - "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", - "\n ", - "\n foreach (var dn in activeDn)", - "\n {", - "\n //PrimaryScope", - "\n if ( primaryScopeBm.Contains(dn) && !primaryScopeDn.Contains(dn))", - "\n errors.Add( $\"DataNode {dn} is not added to the primary scope.\" );", - "\n if( !primaryScopeBm.Contains(dn) && primaryScopeDn.Contains(dn))", - "\n errors.Add( $\"DataNode {dn} is added to the primary scope but should have not.\" );", - "\n ", - "\n //SecondaryScope", - "\n if ( secondaryScopeBm.Contains(dn) && !testStorage.IsSecondaryScope(dn))", - "\n errors.Add( $\"DataNode {dn} is not added to the secondary scope.\" );", - "\n if( !secondaryScopeBm.Contains(dn) && testStorage.IsSecondaryScope(dn))", - "\n errors.Add( $\"DataNode {dn} is added to the secondary scope but should have not.\" );", - "\n }", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query());", - "\n await CleanWorkspaceDataNodes();", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ky7k1tjYZkuJI5AN4f01_g", - "cell_type": "code", - "source": [ - "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", - "\n sampleRawVar with {DataNode = \"Reins2\"},", - "\n };", - "\nvar primaryScopeBm = new string[]{\"Reins1\", \"Reins2\"};", - "\nvar secondaryScopeBm = new string[]{\"Gross1\", \"Gross2\"};", - "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Q7y5fkIm8Em2WkXn5-f3XA", - "cell_type": "code", - "source": [ - "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", - "\n };", - "\nvar primaryScopeBm = new string[]{\"Reins1\"};", - "\nvar secondaryScopeBm = new string[]{\"Gross1\"};", - "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kwq8FSvW2EOvmcWpP4NtmA", - "cell_type": "code", - "source": [ - "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", - "\n sampleRawVar with {DataNode = \"Gross1\"},", - "\n };", - "\nvar primaryScopeBm = new string[]{\"Reins1\",\"Gross1\",\"Reins2\"};", - "\nvar secondaryScopeBm = new string[]{\"Gross2\"};", - "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DXx87fO500-tCJcptCKJTw", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Import Storage Test

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test IfrsVariables Query" + ] + }, + { + "cell_type": "code", + "source": [ + "var gic = \"DT1.1\";", + "\nvar gric = \"DTR1.1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "//Define partition", + "\nvar args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Actual);", + "\nvar partition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);", + "\n", + "\nvar previousPeriodPartition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year - 1 && ", + "\n x.Month == MonthInAYear && x.Scenario == args.Scenario);", + "\nif(previousPeriodPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckIfrsVariablesFromImportStorageAsync(string importFormat, IEnumerable inputDataSetForWorkspace, IEnumerable inputDataSetForDataSource, IEnumerable ivsBenchmark)", + "\n{", + "\n //Prepare Workspace and DataSource", + "\n await Workspace.UpdateAsync(inputDataSetForWorkspace);", + "\n await DataSource.UpdateAsync(inputDataSetForDataSource);", + "\n ", + "\n //Set up import storage and test universe", + "\n var testStorage = new ImportStorage(args with {ImportFormat = importFormat}, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var ivs = testStorage.IfrsVariablesByImportIdentity.SelectMany(x => x.Value);", + "\n ", + "\n //Clean up Workspace", + "\n //Workspace.Reset(); ", + "\n await Workspace.DeleteAsync(inputDataSetForWorkspace); ", + "\n await DataSource.DeleteAsync(inputDataSetForDataSource); ", + "\n ", + "\n var errors = new List();", + "\n ", + "\n var extraVariablesInStorage = ivs.Except(ivsBenchmark).Select(x => x.ToIdentityString()).ToArray();", + "\n if(extraVariablesInStorage.Any()) errors.Add( $\"IfrsVariables in the storage contain the following items that are not present in the benchmark:\\n{string.Join(\"\\n\",extraVariablesInStorage)}.\" );", + "\n ", + "\n var extraVariablesInBenchmark = ivsBenchmark.Except(ivs).Select(x => x.ToIdentityString()).ToArray();", + "\n if(extraVariablesInBenchmark.Count() > 0) errors.Add( $\"IfrsVariables in the benchmark contain the following items that are not present in the storage:\\n{string.Join(\"\\n\",extraVariablesInBenchmark)}.\" );", + "\n ", + "\n //find duplicates in storage", + "\n var ivsByIdentityString = ivs.GroupBy(x => x.ToIdentityString()).Where(x => x.Count() > 1).Select(x => x.Key);", + "\n if(ivsByIdentityString.Any()) errors.Add($\"IfrsVariables in the storage have duplicated items for:\\n{string.Join(\"\\n\",ivsByIdentityString)}.\");", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "//There is a previous year, and it's the first time Actuals are imported for the current year", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "//There is a previous year, and it's the second time Actuals are imported for the current year (reimport)", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 150.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 200.0},", + "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 450.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "//There is a previous year, Cashflows were already imported and Actuals are imported for the first time", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.I, EstimateType = EstimateTypes.BE};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -20.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.AA, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -15.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, EstimateType = EstimateTypes.AA, Novelty = Novelties.C, Value = -20.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "//There is a previous year, Cashflows and Actuals were already imported and Actuals are imported again", + "\nvar basicAdvanceActualIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar basicBeIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gic, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.I, EstimateType = EstimateTypes.BE};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n basicBeIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 1000.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n basicAdvanceActualIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicAdvanceActualIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = 150.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = 200.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.EOP, Value = 450.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n basicBeIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 1000.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.IA, Value = 1500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.CF, Value = 2500.0},", + "\n basicBeIfrsVariable with {AocType = AocTypes.EOP, Value = 5000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.CF, Value = -15.0},", + "\n basicAdvanceActualIfrsVariable with {AocType = AocTypes.WO, Value = -20.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "//There is a previous year for Primary Scope (GRIC10) ", + "\n//There is a previous and current year for Secondary Scope (GIC10), ", + "\n//It's the first time Actuals are imported for the current year", + "\n", + "\nvar basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = gric, AccidentYear = null, AmountType = AmountTypes.PR, Novelty = Novelties.C, EstimateType = EstimateTypes.AA};", + "\nvar inputDataSetForDataSource = new IfrsVariable[]{", + "\n //Year", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, Value = 100.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.CL, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 666.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.EOP, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 1000.0},", + "\n basicIfrsVariable with {Partition = previousPeriodPartition.Id, AocType = AocTypes.CL, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 666.0},", + "\n //Year -1", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n };", + "\n", + "\nvar inputDataSetForWorkspace = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nvar ivsBenchmark = new IfrsVariable[]{", + "\n //From previous Period", + "\n //Actuals", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, Value = 100.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.DA, Value = 1000.0},", + "\n //Cashflow", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 1000.0},", + "\n basicIfrsVariable with {AocType = AocTypes.BOP, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.C, Value = 1000.0},", + "\n ", + "\n //From current Period", + "\n //from DB", + "\n basicIfrsVariable with {AocType = AocTypes.IA, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Novelty = Novelties.I, DataNode = gic, EstimateType = EstimateTypes.BE, EconomicBasis = EconomicBases.L, Value = 10.0},", + "\n ", + "\n //from workspace", + "\n basicIfrsVariable with {AocType = AocTypes.CF, Value = -10.0},", + "\n basicIfrsVariable with {AocType = AocTypes.WO, Value = 15.0},", + "\n };", + "\n", + "\nawait CheckIfrsVariablesFromImportStorageAsync(ImportFormats.Actual, inputDataSetForWorkspace, inputDataSetForDataSource, ivsBenchmark);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node Parameter related logic" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Preparation" + ] + }, + { + "cell_type": "code", + "source": [ + "//Define partition", + "\nvar args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", + "\n", + "\nvar reportingNodePartition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Scenario == args.Scenario);", + "\nif(reportingNodePartition == null) ApplicationMessage.Log(Error.PartitionNotFound);", + "\n", + "\n", + "\nvar currentPartition = DataSource.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(currentPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);", + "\n", + "\n", + "\nvar previousPeriodPartition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year - 1 && ", + "\n x.Month == MonthInAYear && x.Scenario == args.Scenario);", + "\nif(previousPeriodPartition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ] + }, + { + "cell_type": "code", + "source": [ + "var sampleGic = new GroupOfInsuranceContract(){Portfolio = \"P1\"};", + "\nvar inputDataGic = new GroupOfInsuranceContract[]{ sampleGic with {SystemName = \"Gross1\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGic with {SystemName = \"Gross2\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGic with {SystemName = \"Gross3\", LiabilityType = LiabilityTypes.LRC},", + "\n };", + "\n", + "\nvar sampleGric = new GroupOfReinsuranceContract(){Portfolio = \"ReP1\"};", + "\nvar inputDataGric = new GroupOfReinsuranceContract[]{ sampleGric with {SystemName = \"Reins1\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGric with {SystemName = \"Reins2\", LiabilityType = LiabilityTypes.LRC},", + "\n sampleGric with {SystemName = \"Reins3\", LiabilityType = LiabilityTypes.LRC},", + "\n };", + "\nvar sampleDnState = new DataNodeState {Partition = reportingNodePartition.Id, Year = args.Year, Month = args.Month, State = State.Active};", + "\nvar inputDataState = new DataNodeState[]{ sampleDnState with {DataNode = \"Gross1\"} ,", + "\n sampleDnState with {DataNode = \"Gross2\"} ,", + "\n sampleDnState with {DataNode = \"Gross3\"} ,", + "\n sampleDnState with {DataNode = \"Reins1\"} ,", + "\n sampleDnState with {DataNode = \"Reins2\"} ,", + "\n sampleDnState with {DataNode = \"Reins3\"} ,", + "\n };", + "\n", + "\nvar samplePreviousDnParam = new InterDataNodeParameter {Partition = reportingNodePartition.Id, ReinsuranceCoverage = 1, Year = args.Year -1, Month = args.Month};", + "\nvar sampleCurrentDnParam = new InterDataNodeParameter {Partition = reportingNodePartition.Id, ReinsuranceCoverage = 1, Year = args.Year, Month = args.Month};", + "\nvar inputDataParameter = new InterDataNodeParameter[]{", + "\n samplePreviousDnParam with {DataNode = \"Gross3\", LinkedDataNode = \"Reins3\", ReinsuranceCoverage = 1},", + "\n samplePreviousDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins1\", ReinsuranceCoverage = 0.1},", + "\n samplePreviousDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.2},", + "\n samplePreviousDnParam with {DataNode = \"Gross2\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.3},", + "\n sampleCurrentDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins1\", ReinsuranceCoverage = 0.5},", + "\n sampleCurrentDnParam with {DataNode = \"Gross1\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.6},", + "\n sampleCurrentDnParam with {DataNode = \"Gross2\", LinkedDataNode = \"Reins2\", ReinsuranceCoverage = 0.7},", + "\n sampleCurrentDnParam with {DataNode = \"Gross3\", LinkedDataNode = \"Reins3\", ReinsuranceCoverage = 1.0},", + "\n };", + "\n", + "\nvar sampleRawVar = new RawVariable{AmountType = AmountTypes.PR, AocType = AocTypes.CL, Novelty = Novelties.C, Partition = currentPartition.Id};" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task PrepareWorkspaceDataNodes()", + "\n{", + "\n await Workspace.UpdateAsync(inputDataGic);", + "\n await Workspace.UpdateAsync(inputDataGric);", + "\n await Workspace.UpdateAsync(inputDataState);", + "\n await Workspace.UpdateAsync(inputDataParameter);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CleanWorkspaceDataNodes()", + "\n{", + "\n await Workspace.DeleteAsync(inputDataGic);", + "\n await Workspace.DeleteAsync(inputDataGric);", + "\n await Workspace.DeleteAsync(inputDataState);", + "\n await Workspace.DeleteAsync(inputDataParameter);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Get Underlying Gic" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckGetUnderlyingGicsAsync(RawVariable[] inputDataVariable, Dictionary> underlyingGicBm)", + "\n{", + "\n var errors = new List();", + "\n ", + "\n await PrepareWorkspaceDataNodes();", + "\n await Workspace.UpdateAsync(inputDataVariable);", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", + "\n ", + "\n foreach (var dn in primaryScopeDn)", + "\n {", + "\n var id = new ImportIdentity(){DataNode = dn};", + "\n if ( underlyingGicBm[dn].Except(testStorage.GetUnderlyingGic(id)).Count() != 0 )", + "\n errors.Add( $\"Underlying Gics for DataNode {dn} not matching with BM. Computed: \\n{string.Join(\"\\n\",testStorage.GetUnderlyingGic(id))} \\n Expected : \\n{string.Join(\"\\n\",underlyingGicBm[dn])}\" );", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query());", + "\n await CleanWorkspaceDataNodes();", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar underlyingGicBm = new Dictionary>(){", + "\n {\"Reins1\",new string[]{\"Gross1\"}},", + "\n {\"Reins2\",new string[]{\"Gross1\",\"Gross2\"}},", + "\n};", + "\n", + "\nawait CheckGetUnderlyingGicsAsync(inputDataVariable, underlyingGicBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar underlyingGicBm = new Dictionary>(){", + "\n {\"Reins2\",new string[]{\"Gross1\",\"Gross2\"}},", + "\n};", + "\n", + "\nawait CheckGetUnderlyingGicsAsync(inputDataVariable, underlyingGicBm);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Get Reinsurance Coverage" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckGetReinsuranceCoverageAsync(RawVariable[] inputDataVariable, ", + "\n Dictionary<(string, string),double> reinsCovBoPBm, ", + "\n Dictionary<(string, string),double> reinsCovEoPBm)", + "\n{", + "\n var errors = new List();", + "\n", + "\n await PrepareWorkspaceDataNodes();", + "\n await Workspace.UpdateAsync(inputDataVariable);", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", + "\n ", + "\n foreach (var dn in primaryScopeDn)", + "\n {", + "\n var aocTypes = new AocStep[]{ new AocStep(AocTypes.BOP, Novelties.I), new AocStep(AocTypes.RCU, Novelties.I) };", + "\n foreach (var aoc in aocTypes)", + "\n {", + "\n var bm = aoc.AocType == AocTypes.BOP ? reinsCovBoPBm : reinsCovEoPBm;", + "\n var id = new ImportIdentity(){DataNode = dn, AocType = aoc.AocType, Novelty = aoc.Novelty};", + "\n ", + "\n var computedReinsCov = testStorage.GetUnderlyingGic(id)", + "\n .Select(gic => (g: gic, value: testStorage.GetReinsuranceCoverage(id, gic)))", + "\n .ToDictionary(x => (dn,x.g), x => x.value);", + "\n ", + "\n if( bm.Keys.Where(x => x.Item1 == dn).Except(computedReinsCov.Keys).Count() != 0)", + "\n errors.Add( $\"Gric-Gic links not matching with BM for DataNode {dn} and AocType {aoc.AocType}. \\n Computed: \\n{string.Join(\"\\n\",computedReinsCov.Keys)} \\n Expected: \\n{string.Join(\"\\n\",bm.Keys)}\" );", + "\n ", + "\n foreach (var reinsCov in computedReinsCov)", + "\n {", + "\n var bmKvp = bm.Single(x => x.Key.Item1 == reinsCov.Key.Item1 && x.Key.Item2 == reinsCov.Key.Item2); ", + "\n if( Math.Abs(bmKvp.Value - reinsCov.Value) > Precision )", + "\n errors.Add( $\"{dn}-{reinsCov.Key.Item2} Reinsurance Coverage not matching with BM for AocType {aoc.AocType}: \\n Computed: {reinsCov.Value} \\n Expected: {bmKvp.Value}\");", + "\n }", + "\n }", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query());", + "\n await CleanWorkspaceDataNodes();", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar reinsCovBoPBm = new Dictionary<(string, string),double>(){", + "\n {(\"Reins1\",\"Gross1\"),0.1},", + "\n {(\"Reins2\",\"Gross1\"),0.2},", + "\n {(\"Reins2\",\"Gross2\"),0.3},", + "\n};", + "\n", + "\nvar reinsCovEoPBm = new Dictionary<(string, string),double>(){", + "\n {(\"Reins1\",\"Gross1\"),0.5},", + "\n {(\"Reins2\",\"Gross1\"),0.6},", + "\n {(\"Reins2\",\"Gross2\"),0.7},", + "\n};", + "\n", + "\nawait CheckGetReinsuranceCoverageAsync(inputDataVariable, reinsCovBoPBm, reinsCovEoPBm);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Primary and Secondary Scope" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckSecondaryScopeAsync(RawVariable[] inputDataVariable, string[] primaryScopeBm, string[] secondaryScopeBm)", + "\n{", + "\n var errors = new List();", + "\n ", + "\n await PrepareWorkspaceDataNodes();", + "\n await Workspace.UpdateAsync(inputDataVariable);", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n ", + "\n var activeDn = (await Workspace.Query().ToArrayAsync()).Select(x => x.DataNode);", + "\n ", + "\n var primaryScopeDn = testStorage.DataNodesByImportScope[ImportScope.Primary];", + "\n ", + "\n foreach (var dn in activeDn)", + "\n {", + "\n //PrimaryScope", + "\n if ( primaryScopeBm.Contains(dn) && !primaryScopeDn.Contains(dn))", + "\n errors.Add( $\"DataNode {dn} is not added to the primary scope.\" );", + "\n if( !primaryScopeBm.Contains(dn) && primaryScopeDn.Contains(dn))", + "\n errors.Add( $\"DataNode {dn} is added to the primary scope but should have not.\" );", + "\n ", + "\n //SecondaryScope", + "\n if ( secondaryScopeBm.Contains(dn) && !testStorage.IsSecondaryScope(dn))", + "\n errors.Add( $\"DataNode {dn} is not added to the secondary scope.\" );", + "\n if( !secondaryScopeBm.Contains(dn) && testStorage.IsSecondaryScope(dn))", + "\n errors.Add( $\"DataNode {dn} is added to the secondary scope but should have not.\" );", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query());", + "\n await CleanWorkspaceDataNodes();", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Reins2\"},", + "\n };", + "\nvar primaryScopeBm = new string[]{\"Reins1\", \"Reins2\"};", + "\nvar secondaryScopeBm = new string[]{\"Gross1\", \"Gross2\"};", + "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n };", + "\nvar primaryScopeBm = new string[]{\"Reins1\"};", + "\nvar secondaryScopeBm = new string[]{\"Gross1\"};", + "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputDataVariable = new RawVariable[]{ sampleRawVar with {DataNode = \"Reins1\"},", + "\n sampleRawVar with {DataNode = \"Gross1\"},", + "\n };", + "\nvar primaryScopeBm = new string[]{\"Reins1\",\"Gross1\",\"Reins2\"};", + "\nvar secondaryScopeBm = new string[]{\"Gross2\"};", + "\nawait CheckSecondaryScopeAsync(inputDataVariable, primaryScopeBm, secondaryScopeBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/MapTemplateAndImportTest.ipynb b/Test/MapTemplateAndImportTest.ipynb index faec8763..e7837a9f 100644 --- a/Test/MapTemplateAndImportTest.ipynb +++ b/Test/MapTemplateAndImportTest.ipynb @@ -1,564 +1,440 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "wmh8VD39zE-Ey7EfKLRdmQ", - "cell_type": "markdown", - "source": [ - "

Test Map Template Export and Import

" - ], - "metadata": {} - }, - { - "id": "Eo2BObmmzkiC0vc1-cdonA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Utils/UtilityMethods\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vtn0keYdmU6rEcmTON0UwQ", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CQ_YlVaPK0qoXE3iHNGsUg", - "cell_type": "markdown", - "source": [ - "# Test Empty Database" - ], - "metadata": {} - }, - { - "id": "DGQyghJ1AEyT_RB_hXzB1Q", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7R24zOJDXk2KI7i6-FH_2g", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q9WzUZfKq06UWRvmoF38IA", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "U3QNuXi7wECZryFP8aqCyw", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LBo4BnS_u02vMgAJhq45-Q", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1eQBRJgPu0ei17Q9Re_f5g", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4uAB9H_tcEq0wQ9u2feWZw", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_I6QcbDYvEW7cP4LqHyMDQ", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3o3EdNofI0Sb7P0VjQv3TA", - "cell_type": "code", - "source": [ - "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6EGAGpWhukuN5vjCcTs51Q", - "cell_type": "markdown", - "source": [ - "# Test Map Template" - ], - "metadata": {} - }, - { - "id": "9s3hXWWbyU-1iykcDAJ-XA", - "cell_type": "markdown", - "source": [ - "## Data Node" - ], - "metadata": {} - }, - { - "id": "m6tebAPzHkaRzelYIbeZOg", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);", - "\n", - "\nstatic var partition = new PartitionByReportingNode() { ReportingNode = \"CH\" };", - "\nstatic var filename = \"TestMapTemplateDataNode\";", - "\n", - "\nWorkspace.InitializeFrom(DataSource);", - "\nawait Workspace.Partition.SetAsync( partition );", - "\n", - "\nvar ips = Workspace.Query().ToArray();", - "\nvar rps = Workspace.Query().ToArray();", - "\nvar gics = Workspace.Query().ToArray();", - "\nvar grics = Workspace.Query().ToArray();", - "\n", - "\nvar exportResult = await Export.ToExcel(filename)", - "\n .WithSource(Workspace)", - "\n .PortfolioConfiguration()", - "\n .PortfolioConfiguration()", - "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", - "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", - "\n .MainTabConfigurationWoScenario(partition)", - "\n.ExecuteAsync();", - "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n", - "\n// check that exporter generates only the desired columns ", - "\nvar extension = \".xlsx\";", - "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", - "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", - "\nvar mainCols = new[]{nameof(PartitionByReportingNode.ReportingNode)};", - "\nvar portfolioCols = new[]{nameof(Portfolio.SystemName),nameof(Portfolio.DisplayName),nameof(Portfolio.ContractualCurrency),", - "\n nameof(Portfolio.LineOfBusiness),nameof(Portfolio.OciType),nameof(Portfolio.ValuationApproach)};", - "\nvar gicCols = new[]{nameof(GroupOfContract.SystemName),nameof(GroupOfContract.DisplayName),nameof(GroupOfContract.AnnualCohort),", - "\n nameof(GroupOfContract.LiabilityType),nameof(InsurancePortfolio),nameof(GroupOfContract.Profitability)};", - "\nvar gricCols = new[]{nameof(GroupOfContract.SystemName),nameof(GroupOfContract.DisplayName),nameof(GroupOfContract.AnnualCohort),", - "\n nameof(GroupOfContract.LiabilityType),nameof(ReinsurancePortfolio),nameof(GroupOfContract.Profitability),nameof(GroupOfContract.Partner)};", - "\n", - "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", - "\nportfolioCols.Intersect(tables.Tables[nameof(InsurancePortfolio)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(portfolioCols.Length); ", - "\nportfolioCols.Intersect(tables.Tables[nameof(ReinsurancePortfolio)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(portfolioCols.Length); ", - "\ngicCols.Intersect(tables.Tables[nameof(GroupOfInsuranceContract)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(gicCols.Length); ", - "\ngricCols.Intersect(tables.Tables[nameof(GroupOfReinsuranceContract)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(gricCols.Length); ", - "\n", - "\n// check that imported data matches the exported data", - "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", - "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", - "\nawait storage.InitializeAsync();", - "\n", - "\nawait UploadDataNodesToWorkspaceAsync(filename+\".xlsx\");", - "\nUtils.EqualityComparer(ips, Workspace.Query().ToArray());", - "\nUtils.EqualityComparer(rps, Workspace.Query().ToArray());", - "\nUtils.EqualityComparer(gics, Workspace.Query().ToArray());", - "\nUtils.EqualityComparer(grics, Workspace.Query().ToArray());", - "\n", - "\n" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zOGhxg1IhESG_D1THv63sA", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nRI-ZaELKE6ClMkV4BLEUg", - "cell_type": "markdown", - "source": [ - "## Data Node State" - ], - "metadata": {} - }, - { - "id": "CrT3UgfIWEucISLJOkDARA", - "cell_type": "code", - "source": [ - "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2021, Month = 3 };", - "\nstatic var filename = \"TestMapTemplateDataNodeState\";", - "\n", - "\nWorkspace.InitializeFrom(DataSource);", - "\nawait Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );", - "\nawait Workspace.Partition.SetAsync( partition );", - "\n", - "\nvar dataNodeStates = await Workspace.Query()", - "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year)", - "\n .GroupBy(x => x.DataNode)", - "\n .Select(x => x.OrderByDescending(y => y.Year).ThenByDescending(y => y.Month))", - "\n .Select(x => x.Last())", - "\n .ToArrayAsync();", - "\n", - "\nvar exportResult = await Export.ToExcel(filename)", - "\n .WithSource(Workspace)", - "\n .StateEnumConfiguration() ", - "\n .DataNodeStateConfiguration(dataNodeStates)", - "\n .MainTabConfigurationWoScenario(partition)", - "\n.ExecuteAsync();", - "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n", - "\n// check that exporter generates only the desired columns ", - "\nvar extension = \".xlsx\";", - "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", - "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", - "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", - "\n nameof(PartitionByReportingNodeAndPeriod.Year),", - "\n nameof(PartitionByReportingNodeAndPeriod.Month)};", - "\nvar dataNodeStateCols = new[]{nameof(DataNodeState.DataNode),nameof(DataNodeState.State)};", - "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", - "\ndataNodeStateCols.Intersect(tables.Tables[\"DataNodeState\"].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(dataNodeStateCols.Length);", - "\n", - "\n// check that imported data matches the exported data ", - "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", - "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", - "\nawait storage.InitializeAsync();", - "\n", - "\nawait UploadDataNodeStateToWorkspaceAsync(filename+\".xlsx\");", - "\n", - "\n// Workspace is empty because ValidateDataNodeStatesAsync removes the entry, since this is already present in the DataSource.", - "\nWorkspace.Query().ToArray().Should().BeEmpty();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QNDCIM7e2UWjQM13S1JZ8A", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WVvsogjgCkGlxke3IAGi_g", - "cell_type": "markdown", - "source": [ - "## DataNodeParameter" - ], - "metadata": {} - }, - { - "id": "4U2oeNzYEEKxoH98EmjOxg", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);", - "\nstatic var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };", - "\nvar partitionByReportingNode = (await DataSource.Query().Where(x => x.ReportingNode == partition.ReportingNode).ToArrayAsync()).Single();", - "\nstatic var filename = \"TestMapTemplateDataNodeParameter\";", - "\nvar singleDataNodeParamBm = await DataSource.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month && x.Partition == partitionByReportingNode.Id ).ToArrayAsync();", - "\nvar interDataNodeParamBm = await DataSource.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month && x.Partition == partitionByReportingNode.Id ).ToArrayAsync();", - "\nawait Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );", - "\nawait Workspace.Partition.SetAsync( partition );", - "\n//--------------------Export Map Template--------------------------", - "\n//--------------------From MapTemplate NB--------------------------", - "\nvar dataNodeParameters = (await Workspace.Query()", - "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", - "\n .GroupBy(x => x.GetType().Name)", - "\n .ToDictionary(x => x.Key, ", - "\n x => x.GroupBy(y => y.DataNode)", - "\n .Select(y => y.OrderByDescending(z => z.Year).ThenByDescending(z => z.Month))", - "\n .Select(y => y.First())", - "\n .ToArray() );", - "\nvar exportResult = await Export.ToExcel(filename)", - "\n .WithSource(Workspace)", - "\n .DataNodeParameterConfiguration(dataNodeParameters)", - "\n .MainTabConfiguration(partition)", - "\n.ExecuteAsync();", - "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n//-----------------------------------------------------------------", - "\n// check that exporter generates only the desired columns ", - "\nvar extension = \".xlsx\";", - "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", - "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", - "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", - "\n nameof(PartitionByReportingNodeAndPeriod.Year),", - "\n nameof(PartitionByReportingNodeAndPeriod.Month),", - "\n nameof(PartitionByReportingNodeAndPeriod.Scenario)};", - "\nvar singleDataNodeParamCols = new[]{nameof(DataNode),", - "\n nameof(SingleDataNodeParameter.PremiumAllocation)};", - "\nvar interDataNodeParamCols = new[]{nameof(DataNodeParameter.DataNode),", - "\n nameof(InterDataNodeParameter.LinkedDataNode),", - "\n nameof(InterDataNodeParameter.ReinsuranceCoverage)};", - "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", - "\nsingleDataNodeParamCols.Intersect(tables.Tables[nameof(SingleDataNodeParameter)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(singleDataNodeParamCols.Length);", - "\ninterDataNodeParamCols.Intersect(tables.Tables[nameof(InterDataNodeParameter)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(interDataNodeParamCols.Length);", - "\n// check that imported data matches the exported data ", - "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", - "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", - "\nvar targetPartitionByReportingNodeId = new Guid();", - "\nawait storage.InitializeAsync();", - "\nawait UploadDataNodeParameterToWorkspaceAsync(filename+\".xlsx\", targetPartitionByReportingNodeId);", - "\nvar expectedSingleDataNodeParamBm = Workspace.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month).ToArray();", - "\nvar expectedInterDataNodeParamBm = Workspace.Query().ToArray();", - "\nUtils.EqualityComparer(singleDataNodeParamBm, expectedSingleDataNodeParamBm);", - "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "va-MijisUkepqmVMOLJj1Q", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "x-al4I6dSk6STwc4oylwCg", - "cell_type": "markdown", - "source": [ - "# Test Import Validation" - ], - "metadata": {} - }, - { - "id": "LG8H5pXCv0iU38uHNCvxEA", - "cell_type": "markdown", - "source": [ - "## Data Node State: entries cannot be imported which change status from Inactive to Active" - ], - "metadata": {} - }, - { - "id": "nmuP0vEnLEqamwIsJpCSfQ", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);", - "\nvar partition = Workspace.Query().Where(x => x.ReportingNode == \"CH\").ToArray().FirstOrDefault();", - "\nawait Workspace.Partition.SetAsync(partition);", - "\n", - "\nvar itemInactive = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Inactive, Partition = partition.Id };", - "\nvar itemActive = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", - "\n", - "\n// Define GIC1 State as Inactive", - "\nvar persistentDataNodeDataByDataNode = new Dictionary ", - "\n{", - "\n [\"GIC1\"] = new DataNodeData() {DataNode = \"GIC1\", State = itemInactive.State, Year = itemInactive.Year, Month = itemInactive.Month},", - "\n};", - "\n", - "\n// Set GIC1 from Inactive into Active", - "\nawait Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\nawait Workspace.UpdateAsync(itemActive);", - "\n", - "\n// Test Validation", - "\nActivity.Start();", - "\nawait ValidateDataNodeStatesAsync(persistentDataNodeDataByDataNode);", - "\nActivity.HasErrors().Should().Be(true);", - "\nvar log = Activity.Finish().Errors.First().ToString().Substring(40);", - "\n(log.Substring(0,log.Length-2) == Get(Error.ChangeDataNodeState, \"GIC1\")).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "i9-3PyG3uEW-g1CBte_ePA", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "19OZTLJqEkywyseKKCm4Uw", - "cell_type": "markdown", - "source": [ - "## Data Node State: Validation removes the entry when the DataSource already contains a previous version " - ], - "metadata": {} - }, - { - "id": "_ezSKNws4E-nHzlCVI0fIg", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);", - "\nvar partition = Workspace.Query().Where(x => x.ReportingNode == \"CH\").ToArray().FirstOrDefault();", - "\nawait Workspace.Partition.SetAsync(partition);", - "\n", - "\nvar itemPrevious = new DataNodeState { Year = 2022, Month = 3, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", - "\nvar itemImport = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", - "\n", - "\n// Define persisted Data Node State", - "\nvar persistentDataNodeDataByDataNode = new Dictionary", - "\n{", - "\n [\"GIC1\"] = new DataNodeData() {DataNode = itemPrevious.DataNode, State = itemPrevious.State, Year = itemPrevious.Year, Month = itemPrevious.Month},", - "\n};", - "\n", - "\n// Reimport Data Node State for GIC1 with State unchanged", - "\nawait Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\nawait Workspace.UpdateAsync(itemImport);", - "\n", - "\nawait ValidateDataNodeStatesAsync(persistentDataNodeDataByDataNode);", - "\n", - "\n// Check that the new redundant State is removed from the Workspace", - "\nWorkspace.Query().ToArray().Should().BeEmpty();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Pou7Chyva0qd3qanB75kiQ", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KyDTS_jfUkOIkYt3INVPtA", - "cell_type": "markdown", - "source": [ - "## Data Node Parameters : Validations" - ], - "metadata": {} - }, - { - "id": "vkBb3hOe3UuG2RuMIIoUfg", - "cell_type": "code", - "source": [ - "public async Task CheckErrors(string inputFileName, List errorBms)", - "\n{", - "\n var partitionId = new Guid();", - "\n var log = await UploadDataNodeParameterToWorkspaceAsync(inputFileName, partitionId);", - "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", - "\n errorBms.Intersect(log.Errors.Select(x => x.ToString().Substring(0,x.ToString().Length-2).Substring(40)).ToArray()).Count().Should().Be(errorBms.Count());", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZSI2-sVTMkuZTg61UVXucg", - "cell_type": "code", - "source": [ - "var inputFileName = \"Data/DataNodeParameter_InvalidDataNode.csv\";", - "\nvar errorsBm = new List(){Get(Error.InvalidDataNode, \"DataNodeInvalid0\"),", - "\n Get(Error.InvalidDataNode, \"DataNodeInvalid1\"),", - "\n Get(Error.InvalidDataNode, \"DataNodeInvalid2\")};", - "\nawait CheckErrors(inputFileName, errorsBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2unWYjVwA0mJbyzeVCVg8A", - "cell_type": "code", - "source": [ - "var inputFileName = \"Data/DataNodeParameter_Duplicate.csv\";", - "\nvar errorsBm = new List(){Get(Error.DuplicateSingleDataNode, \"DT1.1\"),", - "\n Get(Error.DuplicateInterDataNode, \"DT1.1\",\"DTR1.1\"),};", - "\nawait CheckErrors(inputFileName, errorsBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uH8Fn9T2-EGO0hSWBk1Yxg", - "cell_type": "code", - "source": [ - "var inputFileName = \"Data/DataNodeParameter_InvalidReinsCov.csv\";", - "\nvar errorsBm = new List(){Get(Error.ReinsuranceCoverageDataNode, \"DT1.1\",\"DT1.1\")};", - "\nawait CheckErrors(inputFileName, errorsBm);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lkXchyRo9U6x7lnhcliuTg", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Test Map Template Export and Import

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Utils/UtilityMethods\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Empty Database" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "(await DataSource.Query().ToArrayAsync()).Length.Should().NotBe(0);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Map Template" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\n", + "\nstatic var partition = new PartitionByReportingNode() { ReportingNode = \"CH\" };", + "\nstatic var filename = \"TestMapTemplateDataNode\";", + "\n", + "\nWorkspace.InitializeFrom(DataSource);", + "\nawait Workspace.Partition.SetAsync( partition );", + "\n", + "\nvar ips = Workspace.Query().ToArray();", + "\nvar rps = Workspace.Query().ToArray();", + "\nvar gics = Workspace.Query().ToArray();", + "\nvar grics = Workspace.Query().ToArray();", + "\n", + "\nvar exportResult = await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .PortfolioConfiguration()", + "\n .PortfolioConfiguration()", + "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", + "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync();", + "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", + "\n", + "\n// check that exporter generates only the desired columns ", + "\nvar extension = \".xlsx\";", + "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", + "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar mainCols = new[]{nameof(PartitionByReportingNode.ReportingNode)};", + "\nvar portfolioCols = new[]{nameof(Portfolio.SystemName),nameof(Portfolio.DisplayName),nameof(Portfolio.ContractualCurrency),", + "\n nameof(Portfolio.LineOfBusiness),nameof(Portfolio.OciType),nameof(Portfolio.ValuationApproach)};", + "\nvar gicCols = new[]{nameof(GroupOfContract.SystemName),nameof(GroupOfContract.DisplayName),nameof(GroupOfContract.AnnualCohort),", + "\n nameof(GroupOfContract.LiabilityType),nameof(InsurancePortfolio),nameof(GroupOfContract.Profitability)};", + "\nvar gricCols = new[]{nameof(GroupOfContract.SystemName),nameof(GroupOfContract.DisplayName),nameof(GroupOfContract.AnnualCohort),", + "\n nameof(GroupOfContract.LiabilityType),nameof(ReinsurancePortfolio),nameof(GroupOfContract.Profitability),nameof(GroupOfContract.Partner)};", + "\n", + "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", + "\nportfolioCols.Intersect(tables.Tables[nameof(InsurancePortfolio)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(portfolioCols.Length); ", + "\nportfolioCols.Intersect(tables.Tables[nameof(ReinsurancePortfolio)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(portfolioCols.Length); ", + "\ngicCols.Intersect(tables.Tables[nameof(GroupOfInsuranceContract)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(gicCols.Length); ", + "\ngricCols.Intersect(tables.Tables[nameof(GroupOfReinsuranceContract)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(gricCols.Length); ", + "\n", + "\n// check that imported data matches the exported data", + "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", + "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", + "\nawait storage.InitializeAsync();", + "\n", + "\nawait UploadDataNodesToWorkspaceAsync(filename+\".xlsx\");", + "\nUtils.EqualityComparer(ips, Workspace.Query().ToArray());", + "\nUtils.EqualityComparer(rps, Workspace.Query().ToArray());", + "\nUtils.EqualityComparer(gics, Workspace.Query().ToArray());", + "\nUtils.EqualityComparer(grics, Workspace.Query().ToArray());", + "\n", + "\n" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "static var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2021, Month = 3 };", + "\nstatic var filename = \"TestMapTemplateDataNodeState\";", + "\n", + "\nWorkspace.InitializeFrom(DataSource);", + "\nawait Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );", + "\nawait Workspace.Partition.SetAsync( partition );", + "\n", + "\nvar dataNodeStates = await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year)", + "\n .GroupBy(x => x.DataNode)", + "\n .Select(x => x.OrderByDescending(y => y.Year).ThenByDescending(y => y.Month))", + "\n .Select(x => x.Last())", + "\n .ToArrayAsync();", + "\n", + "\nvar exportResult = await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .StateEnumConfiguration() ", + "\n .DataNodeStateConfiguration(dataNodeStates)", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync();", + "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", + "\n", + "\n// check that exporter generates only the desired columns ", + "\nvar extension = \".xlsx\";", + "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", + "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", + "\n nameof(PartitionByReportingNodeAndPeriod.Year),", + "\n nameof(PartitionByReportingNodeAndPeriod.Month)};", + "\nvar dataNodeStateCols = new[]{nameof(DataNodeState.DataNode),nameof(DataNodeState.State)};", + "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", + "\ndataNodeStateCols.Intersect(tables.Tables[\"DataNodeState\"].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(dataNodeStateCols.Length);", + "\n", + "\n// check that imported data matches the exported data ", + "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", + "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", + "\nawait storage.InitializeAsync();", + "\n", + "\nawait UploadDataNodeStateToWorkspaceAsync(filename+\".xlsx\");", + "\n", + "\n// Workspace is empty because ValidateDataNodeStatesAsync removes the entry, since this is already present in the DataSource.", + "\nWorkspace.Query().ToArray().Should().BeEmpty();" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## DataNodeParameter" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\nstatic var partition = new PartitionByReportingNodeAndPeriod() { ReportingNode = \"CH\", Year = 2020, Month = 12 };", + "\nvar partitionByReportingNode = (await DataSource.Query().Where(x => x.ReportingNode == partition.ReportingNode).ToArrayAsync()).Single();", + "\nstatic var filename = \"TestMapTemplateDataNodeParameter\";", + "\nvar singleDataNodeParamBm = await DataSource.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month && x.Partition == partitionByReportingNode.Id ).ToArrayAsync();", + "\nvar interDataNodeParamBm = await DataSource.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month && x.Partition == partitionByReportingNode.Id ).ToArrayAsync();", + "\nawait Workspace.Partition.SetAsync( new PartitionByReportingNode() { ReportingNode = partition.ReportingNode } );", + "\nawait Workspace.Partition.SetAsync( partition );", + "\n//--------------------Export Map Template--------------------------", + "\n//--------------------From MapTemplate NB--------------------------", + "\nvar dataNodeParameters = (await Workspace.Query()", + "\n .Where(x => (x.Year == partition.Year && x.Month <= partition.Month) || x.Year < partition.Year).ToArrayAsync())", + "\n .GroupBy(x => x.GetType().Name)", + "\n .ToDictionary(x => x.Key, ", + "\n x => x.GroupBy(y => y.DataNode)", + "\n .Select(y => y.OrderByDescending(z => z.Year).ThenByDescending(z => z.Month))", + "\n .Select(y => y.First())", + "\n .ToArray() );", + "\nvar exportResult = await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .DataNodeParameterConfiguration(dataNodeParameters)", + "\n .MainTabConfiguration(partition)", + "\n.ExecuteAsync();", + "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", + "\n//-----------------------------------------------------------------", + "\n// check that exporter generates only the desired columns ", + "\nvar extension = \".xlsx\";", + "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", + "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", + "\n nameof(PartitionByReportingNodeAndPeriod.Year),", + "\n nameof(PartitionByReportingNodeAndPeriod.Month),", + "\n nameof(PartitionByReportingNodeAndPeriod.Scenario)};", + "\nvar singleDataNodeParamCols = new[]{nameof(DataNode),", + "\n nameof(SingleDataNodeParameter.PremiumAllocation)};", + "\nvar interDataNodeParamCols = new[]{nameof(DataNodeParameter.DataNode),", + "\n nameof(InterDataNodeParameter.LinkedDataNode),", + "\n nameof(InterDataNodeParameter.ReinsuranceCoverage)};", + "\nmainCols.Intersect(tables.Tables[Main].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(mainCols.Length);", + "\nsingleDataNodeParamCols.Intersect(tables.Tables[nameof(SingleDataNodeParameter)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(singleDataNodeParamCols.Length);", + "\ninterDataNodeParamCols.Intersect(tables.Tables[nameof(InterDataNodeParameter)].Columns.Select(x => x.ColumnName).ToArray()).Count().Should().Be(interDataNodeParamCols.Length);", + "\n// check that imported data matches the exported data ", + "\nvar args = await GetArgsFromMainAsync(filename+\".xlsx\");", + "\nvar storage = new ParsingStorage(args, DataSource, Workspace);", + "\nvar targetPartitionByReportingNodeId = new Guid();", + "\nawait storage.InitializeAsync();", + "\nawait UploadDataNodeParameterToWorkspaceAsync(filename+\".xlsx\", targetPartitionByReportingNodeId);", + "\nvar expectedSingleDataNodeParamBm = Workspace.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month).ToArray();", + "\nvar expectedInterDataNodeParamBm = Workspace.Query().ToArray();", + "\nUtils.EqualityComparer(singleDataNodeParamBm, expectedSingleDataNodeParamBm);", + "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Import Validation" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node State: entries cannot be imported which change status from Inactive to Active" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\nvar partition = Workspace.Query().Where(x => x.ReportingNode == \"CH\").ToArray().FirstOrDefault();", + "\nawait Workspace.Partition.SetAsync(partition);", + "\n", + "\nvar itemInactive = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Inactive, Partition = partition.Id };", + "\nvar itemActive = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", + "\n", + "\n// Define GIC1 State as Inactive", + "\nvar persistentDataNodeDataByDataNode = new Dictionary ", + "\n{", + "\n [\"GIC1\"] = new DataNodeData() {DataNode = \"GIC1\", State = itemInactive.State, Year = itemInactive.Year, Month = itemInactive.Month},", + "\n};", + "\n", + "\n// Set GIC1 from Inactive into Active", + "\nawait Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\nawait Workspace.UpdateAsync(itemActive);", + "\n", + "\n// Test Validation", + "\nActivity.Start();", + "\nawait ValidateDataNodeStatesAsync(persistentDataNodeDataByDataNode);", + "\nActivity.HasErrors().Should().Be(true);", + "\nvar log = Activity.Finish().Errors.First().ToString().Substring(40);", + "\n(log.Substring(0,log.Length-2) == Get(Error.ChangeDataNodeState, \"GIC1\")).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node State: Validation removes the entry when the DataSource already contains a previous version " + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);", + "\nvar partition = Workspace.Query().Where(x => x.ReportingNode == \"CH\").ToArray().FirstOrDefault();", + "\nawait Workspace.Partition.SetAsync(partition);", + "\n", + "\nvar itemPrevious = new DataNodeState { Year = 2022, Month = 3, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", + "\nvar itemImport = new DataNodeState { Year = 2022, Month = 9, DataNode = \"GIC1\", State = State.Active, Partition = partition.Id };", + "\n", + "\n// Define persisted Data Node State", + "\nvar persistentDataNodeDataByDataNode = new Dictionary", + "\n{", + "\n [\"GIC1\"] = new DataNodeData() {DataNode = itemPrevious.DataNode, State = itemPrevious.State, Year = itemPrevious.Year, Month = itemPrevious.Month},", + "\n};", + "\n", + "\n// Reimport Data Node State for GIC1 with State unchanged", + "\nawait Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\nawait Workspace.UpdateAsync(itemImport);", + "\n", + "\nawait ValidateDataNodeStatesAsync(persistentDataNodeDataByDataNode);", + "\n", + "\n// Check that the new redundant State is removed from the Workspace", + "\nWorkspace.Query().ToArray().Should().BeEmpty();" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node Parameters : Validations" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckErrors(string inputFileName, List errorBms)", + "\n{", + "\n var partitionId = new Guid();", + "\n var log = await UploadDataNodeParameterToWorkspaceAsync(inputFileName, partitionId);", + "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", + "\n errorBms.Intersect(log.Errors.Select(x => x.ToString().Substring(0,x.ToString().Length-2).Substring(40)).ToArray()).Count().Should().Be(errorBms.Count());", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_InvalidDataNode.csv\";", + "\nvar errorsBm = new List(){Get(Error.InvalidDataNode, \"DataNodeInvalid0\"),", + "\n Get(Error.InvalidDataNode, \"DataNodeInvalid1\"),", + "\n Get(Error.InvalidDataNode, \"DataNodeInvalid2\")};", + "\nawait CheckErrors(inputFileName, errorsBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_Duplicate.csv\";", + "\nvar errorsBm = new List(){Get(Error.DuplicateSingleDataNode, \"DT1.1\"),", + "\n Get(Error.DuplicateInterDataNode, \"DT1.1\",\"DTR1.1\"),};", + "\nawait CheckErrors(inputFileName, errorsBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "var inputFileName = \"Data/DataNodeParameter_InvalidReinsCov.csv\";", + "\nvar errorsBm = new List(){Get(Error.ReinsuranceCoverageDataNode, \"DT1.1\",\"DT1.1\")};", + "\nawait CheckErrors(inputFileName, errorsBm);" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/QueriesTest.ipynb b/Test/QueriesTest.ipynb index c91c0f6b..490565f0 100644 --- a/Test/QueriesTest.ipynb +++ b/Test/QueriesTest.ipynb @@ -1,535 +1,423 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "_IqpJ1KMUEGYZFSIeqTQfg", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Utils/UtilityMethods\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6-FaBdsHfk2QsR8mnBirig", - "cell_type": "code", - "source": [ - "var gic = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lpSLXRR8SUWTReUAPXdCGw", - "cell_type": "markdown", - "source": [ - "# Test Load Current and Previous Parameter for Yield Curve" - ], - "metadata": {} - }, - { - "id": "MSTglT9520GqkMaeJVIboA", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vuGCdF-iCU6ZaQX6iiwCaA", - "cell_type": "code", - "source": [ - "public async Task CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(Args args, IEnumerable testData, ", - "\n (int Year, int Month) expectedCurrentPeriod, ", - "\n (int Year, int Month) expectedPreviousPeriod)", - "\n{", - "\n await Workspace.UpdateAsync(testData);", - "\n var eurCurrentAndPreviousYieldCurve = (await Workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.Currency))[\"EUR\"];", - "\n ", - "\n //Check Current Period", - "\n eurCurrentAndPreviousYieldCurve[CurrentPeriod].Year.Should().Be(expectedCurrentPeriod.Year);", - "\n eurCurrentAndPreviousYieldCurve[CurrentPeriod].Month.Should().Be(expectedCurrentPeriod.Month);", - "\n ", - "\n //Check Previous Period", - "\n eurCurrentAndPreviousYieldCurve[PreviousPeriod].Year.Should().Be(expectedPreviousPeriod.Year);", - "\n eurCurrentAndPreviousYieldCurve[PreviousPeriod].Month.Should().Be(expectedPreviousPeriod.Month);", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RUfdhTU15EaPkO5FVp6qdw", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData.RepeatOnce(), (2020, 9),(2020, 9));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5lBUg6REDUqpF8AFQaSVMw", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData.RepeatOnce(), (2019, 12), (2019, 12));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yvs_kK9a6U-p4_zPj-yeTA", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2020, 6));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9KEHlyMSzEaR6u7TcXWcnQ", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 9), (2020, 9));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TbyTWCzxOEKJ84ZrZjk0ug", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 9}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 9), (2019, 9));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "B0cbAHylv0aRbz8NpHnX7w", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 9}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 12), (2019, 12));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mGbDxghxXkqBy6nh62h5wg", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2018, Month = 9}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 12), (2019, 12));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-aimZbUkbE69ujpiBCQHeg", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 6}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 9},", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 6}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 6), (2019, 6));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "z7N6H3nrE0ib9q25l-HOLw", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2015, Month = 9},", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3}};", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2016, 3));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "G1sMs6vn7UCUx9PcNnX0Zg", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2021, Month = 9},", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3}};", - "\n", - "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2016, 3));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bTtGvgxoRUuqc2eYUgyavQ", - "cell_type": "markdown", - "source": [ - "# Test Data Node State Query" - ], - "metadata": {} - }, - { - "id": "m6puoprjyUGBYqt7aPTc4A", - "cell_type": "code", - "source": [ - "public async Task CheckLoadDataNodeStateAsync(Args args, IEnumerable testData, bool isExpectedToBeActive)", - "\n{", - "\n await Workspace.UpdateAsync(testData);", - "\n var isActive = (await Workspace.LoadDataNodeStateAsync(args)).Keys.Contains(gic);", - "\n ", - "\n isActive.Should().Be(isExpectedToBeActive);", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1rUvJm2L4k-qth-62yWJcA", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,12,Periodicity.Monthly,null);", - "\nvar testData = new DataNodeState[] {new DataNodeState{ DataNode = gic, Year = 2019, Month = 12, State = State.Active },", - "\n new DataNodeState{ DataNode = gic, Year = 2020, Month = 6, State = State.Inactive }};", - "\nawait CheckLoadDataNodeStateAsync(args, testData, false);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "n8zP0mcxgUiGDxpciWfdUQ", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,12,Periodicity.Monthly,null);", - "\nvar testData = new DataNodeState[] {new DataNodeState{ DataNode = gic, Year = 2020, Month = 3, State = State.Active },", - "\n new DataNodeState{ DataNode = gic, Year = 2020, Month = 9, State = State.Inactive }};", - "\nawait CheckLoadDataNodeStateAsync(args, testData, false);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Bm1_QjQMz0GO56QnUrVqwg", - "cell_type": "markdown", - "source": [ - "# Test Load Yield Curve" - ], - "metadata": {} - }, - { - "id": "wAmKPPOo7kGNh3r-uijhJg", - "cell_type": "code", - "source": [ - "public async Task CheckLoadYieldCurveAsync(Args args, IEnumerable testData, ", - "\n (int year , int month) dataNodeYearAndMonth, ", - "\n double expectedCurrentPreviousFirstYcValue,", - "\n double expectedCurrentFirstYcValue,", - "\n double expectedLockedFirstYcValue)", - "\n{", - "\n await Workspace.UpdateAsync(testData);", - "\n await Workspace.UpdateAsync(new ReportingNode[]{new ReportingNode{Currency=\"EUR\",SystemName=\"CH\"}});", - "\n ", - "\n var dataNodes = new DataNodeData[]{new DataNodeData{ValuationApproach=\"BBA\", Year = dataNodeYearAndMonth.year, Month = dataNodeYearAndMonth.month, DataNode = gic, ContractualCurrency = \"EUR\"}};", - "\n var eurLockedYieldCurve = (await LoadLockedInYieldCurveAsync(Workspace, args, dataNodes));", - "\n var eurCurrentYieldCurve = (await LoadCurrentYieldCurveAsync(Workspace, args, dataNodes));", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n ", - "\n var errors = new List();", - "\n var currentPrevPeriod = eurCurrentYieldCurve[\"EUR\"][PreviousPeriod].Values.First();", - "\n if(Math.Abs(currentPrevPeriod - expectedCurrentPreviousFirstYcValue) > 1E-8)", - "\n errors.Add( $\"Current YieldCurve for Previous Period not matching:\\n Expected {expectedCurrentPreviousFirstYcValue} \\n Computed {currentPrevPeriod}.\" );", - "\n ", - "\n var currentCurrPeriod = eurCurrentYieldCurve[\"EUR\"][CurrentPeriod].Values.First();", - "\n if(Math.Abs(currentCurrPeriod - expectedCurrentFirstYcValue) > 1E-8)", - "\n errors.Add( $\"Current YieldCurve for Current Period not matching:\\n Expected {expectedCurrentFirstYcValue} \\n Computed {currentCurrPeriod}.\" );", - "\n ", - "\n var lockedYc = eurLockedYieldCurve[gic].Values.First();", - "\n if(Math.Abs(lockedYc - expectedLockedFirstYcValue) > 1E-8)", - "\n errors.Add( $\"LockedIn YieldCurve not matching:\\n Expected {expectedLockedFirstYcValue} \\n Computed {lockedYc}.\" );", - "\n ", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors)); ", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vRCMvk2zpk6YeQlQuLXkRQ", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6, Values = new double[]{0.1,0.2,0.3,0.4,0.5,0.6} }, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3, Values = new double[]{2.1,2.2,2.3,2.4,2.5,2.6} }, ", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2021, Month = 9, Values = new double[]{4.1,4.2,4.3,4.4,4.5,4.6} },", - "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3, Values = new double[]{6.1,6.2,6.3,6.4,6.5,6.6} }};", - "\n", - "\nawait CheckLoadYieldCurveAsync(args, testData, (2016, 6), 6.1, 0.1, 6.1);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZL_HAd63MUGyojndKeoyPA", - "cell_type": "markdown", - "source": [ - "# Test Load Data Node Parameter" - ], - "metadata": {} - }, - { - "id": "HHu8-DR7E0Gl3YlOdR0eWA", - "cell_type": "code", - "source": [ - "var gic2 = \"gic2\";", - "\nvar xgic = \"xgic\";", - "\nvar gric1 = \"gric1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VArCCnA-XEWWYph2oPfxmQ", - "cell_type": "code", - "source": [ - "public async Task CheckLoadInterDataNodeParameterAsync(Args args, IEnumerable testData, ", - "\n int previousYear,", - "\n int? currentYear = null)", - "\n{", - "\n currentYear = currentYear ?? previousYear;", - "\n await Workspace.UpdateAsync(testData);", - "\n ", - "\n var interDataNodeParameters = await LoadInterDataNodeParametersAsync(Workspace, args);", - "\n ", - "\n //Check Keys", - "\n var uniqueLinks = testData.Select(x => x.DataNode).Concat(testData.Select(x => x.LinkedDataNode)).ToHashSet();", - "\n uniqueLinks.Intersect(interDataNodeParameters.Keys).Count().Should().Be(uniqueLinks.Count());", - "\n ", - "\n //CheckInnerDictionaries", - "\n var currentYearData = testData.Where(x => x.Year == currentYear);", - "\n var previousYearData = testData.Where(x => x.Year == previousYear);", - "\n ", - "\n var errors = new List();", - "\n foreach(var dn in uniqueLinks)", - "\n {", - "\n //Set up BM counts", - "\n var currentLinks = currentYearData.Select(x => x.DataNode).Concat(currentYearData.Select(x => x.LinkedDataNode));", - "\n var currentLinksCount = currentLinks.Where(x => x == dn).Count();", - "\n var prevlinks = previousYearData.Select(x => x.DataNode).Concat(previousYearData.Select(x => x.LinkedDataNode));", - "\n var previousLinksCount = prevlinks.Where(x => x == dn).Count();", - "\n ", - "\n //Current Period", - "\n var computedCount = interDataNodeParameters[dn][CurrentPeriod].Count();", - "\n", - "\n if (currentYearData.Any())", - "\n {", - "\n if(computedCount != currentLinksCount)", - "\n errors.Add( $\"Current DataNode parameter count for {dn} not matching:\\n Expected {currentLinksCount} \\n Computed {computedCount}.\" );", - "\n }", - "\n else if(computedCount != previousLinksCount)", - "\n errors.Add( $\"Current DataNode parameter count for {dn} not matching:\\n Expected {previousLinksCount} \\n Computed {computedCount}.\" );", - "\n ", - "\n foreach (var param in interDataNodeParameters[dn][CurrentPeriod])", - "\n {", - "\n var linkedDn = param.DataNode == dn ? param.LinkedDataNode : param.DataNode;", - "\n var isLinkInPrevPeriod = previousYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn);", - "\n var isLinkInCurrPeriod = currentYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn); ", - "\n ", - "\n if(isLinkInPrevPeriod && !isLinkInCurrPeriod)", - "\n { ", - "\n if (param.ReinsuranceCoverage != ((double)previousYear)/1000)", - "\n errors.Add( $\"Current Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)previousYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", - "\n }", - "\n else if( param.ReinsuranceCoverage != ((double)currentYear)/1000)", - "\n errors.Add( $\"Current Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)currentYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", - "\n }", - "\n", - "\n //Previous Period", - "\n computedCount = interDataNodeParameters[dn][PreviousPeriod].Count();", - "\n ", - "\n if (currentYearData.Any())", - "\n {", - "\n if(computedCount != currentLinksCount)", - "\n errors.Add( $\"Previous DataNode parameter count for {dn} not matching:\\n Expected {currentLinksCount} \\n Computed {computedCount}.\" );", - "\n }", - "\n else if(computedCount != previousLinksCount)", - "\n errors.Add( $\"Previous DataNode parameter count for {dn} not matching:\\n Expected {previousLinksCount} \\n Computed {computedCount}.\" );", - "\n ", - "\n foreach (var param in interDataNodeParameters[dn][PreviousPeriod])", - "\n {", - "\n var linkedDn = param.DataNode == dn ? param.LinkedDataNode : param.DataNode;", - "\n var isLinkInPrevPeriod = previousYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn);", - "\n var isLinkInCurrPeriod = currentYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn); ", - "\n ", - "\n if(!isLinkInPrevPeriod && isLinkInCurrPeriod)", - "\n { ", - "\n if (param.ReinsuranceCoverage != ((double)currentYear)/1000)", - "\n errors.Add( $\"Previous Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)currentYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", - "\n }", - "\n else if( param.ReinsuranceCoverage != ((double)previousYear)/1000)", - "\n errors.Add( $\"Previous Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)previousYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", - "\n }", - "\n }", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n ", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "aOH89OGU5Eqn4PeSnUbJrw", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nint previousYear = 2019;", - "\nvar testData = new InterDataNodeParameter[] ", - "\n {new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n new InterDataNodeParameter{ DataNode = gic2, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n };", - "\n", - "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cT_97C9oW0KF2qH_aG7Scw", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nint previousYear = 2019;", - "\nint currentYear = 2020;", - "\nvar testData = new InterDataNodeParameter[] ", - "\n {", - "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9},", - "\n new InterDataNodeParameter{ DataNode = gic2, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9}, ", - "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9}, ", - "\n };", - "\n", - "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kJbew987pkum2Ge25tpsHQ", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nint previousYear = 2019;", - "\nint currentYear = 2020;", - "\nvar testData = new InterDataNodeParameter[] ", - "\n {", - "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", - "\n };", - "\n", - "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IWMBAFYZpUaB-vgsMrm8dg", - "cell_type": "code", - "source": [ - "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", - "\nint previousYear = 2019;", - "\nint currentYear = 2020;", - "\nvar testData = new InterDataNodeParameter[] ", - "\n {", - "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 3}, ", - "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 3}, ", - "\n };", - "\n", - "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jtX2WSn4c02WOwMQ-oKUqQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Utils/UtilityMethods\"" + ] + }, + { + "cell_type": "code", + "source": [ + "var gic = \"DT1.1\";" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Load Current and Previous Parameter for Yield Curve" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(Args args, IEnumerable testData, ", + "\n (int Year, int Month) expectedCurrentPeriod, ", + "\n (int Year, int Month) expectedPreviousPeriod)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n var eurCurrentAndPreviousYieldCurve = (await Workspace.LoadCurrentAndPreviousParameterAsync(args, x => x.Currency))[\"EUR\"];", + "\n ", + "\n //Check Current Period", + "\n eurCurrentAndPreviousYieldCurve[CurrentPeriod].Year.Should().Be(expectedCurrentPeriod.Year);", + "\n eurCurrentAndPreviousYieldCurve[CurrentPeriod].Month.Should().Be(expectedCurrentPeriod.Month);", + "\n ", + "\n //Check Previous Period", + "\n eurCurrentAndPreviousYieldCurve[PreviousPeriod].Year.Should().Be(expectedPreviousPeriod.Year);", + "\n eurCurrentAndPreviousYieldCurve[PreviousPeriod].Month.Should().Be(expectedPreviousPeriod.Month);", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData.RepeatOnce(), (2020, 9),(2020, 9));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData.RepeatOnce(), (2019, 12), (2019, 12));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2020, 6));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 9), (2020, 9));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 9}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 9}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 9), (2019, 9));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 9}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 12), (2019, 12));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 12}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2018, Month = 9}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 12), (2019, 12));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2019, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 9},", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 6}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2019, 6), (2019, 6));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2015, Month = 9},", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3}};", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2016, 3));" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3}, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2021, Month = 9},", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3}};", + "\n", + "\nawait CheckLoadCurrentAndPreviousParameterForYieldCurveAsync(args, testData, (2020, 6), (2016, 3));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Data Node State Query" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckLoadDataNodeStateAsync(Args args, IEnumerable testData, bool isExpectedToBeActive)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n var isActive = (await Workspace.LoadDataNodeStateAsync(args)).Keys.Contains(gic);", + "\n ", + "\n isActive.Should().Be(isExpectedToBeActive);", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,12,Periodicity.Monthly,null);", + "\nvar testData = new DataNodeState[] {new DataNodeState{ DataNode = gic, Year = 2019, Month = 12, State = State.Active },", + "\n new DataNodeState{ DataNode = gic, Year = 2020, Month = 6, State = State.Inactive }};", + "\nawait CheckLoadDataNodeStateAsync(args, testData, false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,12,Periodicity.Monthly,null);", + "\nvar testData = new DataNodeState[] {new DataNodeState{ DataNode = gic, Year = 2020, Month = 3, State = State.Active },", + "\n new DataNodeState{ DataNode = gic, Year = 2020, Month = 9, State = State.Inactive }};", + "\nawait CheckLoadDataNodeStateAsync(args, testData, false);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Load Yield Curve" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckLoadYieldCurveAsync(Args args, IEnumerable testData, ", + "\n (int year , int month) dataNodeYearAndMonth, ", + "\n double expectedCurrentPreviousFirstYcValue,", + "\n double expectedCurrentFirstYcValue,", + "\n double expectedLockedFirstYcValue)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n await Workspace.UpdateAsync(new ReportingNode[]{new ReportingNode{Currency=\"EUR\",SystemName=\"CH\"}});", + "\n ", + "\n var dataNodes = new DataNodeData[]{new DataNodeData{ValuationApproach=\"BBA\", Year = dataNodeYearAndMonth.year, Month = dataNodeYearAndMonth.month, DataNode = gic, ContractualCurrency = \"EUR\"}};", + "\n var eurLockedYieldCurve = (await LoadLockedInYieldCurveAsync(Workspace, args, dataNodes));", + "\n var eurCurrentYieldCurve = (await LoadCurrentYieldCurveAsync(Workspace, args, dataNodes));", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n ", + "\n var errors = new List();", + "\n var currentPrevPeriod = eurCurrentYieldCurve[\"EUR\"][PreviousPeriod].Values.First();", + "\n if(Math.Abs(currentPrevPeriod - expectedCurrentPreviousFirstYcValue) > 1E-8)", + "\n errors.Add( $\"Current YieldCurve for Previous Period not matching:\\n Expected {expectedCurrentPreviousFirstYcValue} \\n Computed {currentPrevPeriod}.\" );", + "\n ", + "\n var currentCurrPeriod = eurCurrentYieldCurve[\"EUR\"][CurrentPeriod].Values.First();", + "\n if(Math.Abs(currentCurrPeriod - expectedCurrentFirstYcValue) > 1E-8)", + "\n errors.Add( $\"Current YieldCurve for Current Period not matching:\\n Expected {expectedCurrentFirstYcValue} \\n Computed {currentCurrPeriod}.\" );", + "\n ", + "\n var lockedYc = eurLockedYieldCurve[gic].Values.First();", + "\n if(Math.Abs(lockedYc - expectedLockedFirstYcValue) > 1E-8)", + "\n errors.Add( $\"LockedIn YieldCurve not matching:\\n Expected {expectedLockedFirstYcValue} \\n Computed {lockedYc}.\" );", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors)); ", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nvar testData = new YieldCurve[] {new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 6, Values = new double[]{0.1,0.2,0.3,0.4,0.5,0.6} }, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2020, Month = 3, Values = new double[]{2.1,2.2,2.3,2.4,2.5,2.6} }, ", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2021, Month = 9, Values = new double[]{4.1,4.2,4.3,4.4,4.5,4.6} },", + "\n new YieldCurve{ Currency = \"EUR\", Year = 2016, Month = 3, Values = new double[]{6.1,6.2,6.3,6.4,6.5,6.6} }};", + "\n", + "\nawait CheckLoadYieldCurveAsync(args, testData, (2016, 6), 6.1, 0.1, 6.1);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Load Data Node Parameter" + ] + }, + { + "cell_type": "code", + "source": [ + "var gic2 = \"gic2\";", + "\nvar xgic = \"xgic\";", + "\nvar gric1 = \"gric1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckLoadInterDataNodeParameterAsync(Args args, IEnumerable testData, ", + "\n int previousYear,", + "\n int? currentYear = null)", + "\n{", + "\n currentYear = currentYear ?? previousYear;", + "\n await Workspace.UpdateAsync(testData);", + "\n ", + "\n var interDataNodeParameters = await LoadInterDataNodeParametersAsync(Workspace, args);", + "\n ", + "\n //Check Keys", + "\n var uniqueLinks = testData.Select(x => x.DataNode).Concat(testData.Select(x => x.LinkedDataNode)).ToHashSet();", + "\n uniqueLinks.Intersect(interDataNodeParameters.Keys).Count().Should().Be(uniqueLinks.Count());", + "\n ", + "\n //CheckInnerDictionaries", + "\n var currentYearData = testData.Where(x => x.Year == currentYear);", + "\n var previousYearData = testData.Where(x => x.Year == previousYear);", + "\n ", + "\n var errors = new List();", + "\n foreach(var dn in uniqueLinks)", + "\n {", + "\n //Set up BM counts", + "\n var currentLinks = currentYearData.Select(x => x.DataNode).Concat(currentYearData.Select(x => x.LinkedDataNode));", + "\n var currentLinksCount = currentLinks.Where(x => x == dn).Count();", + "\n var prevlinks = previousYearData.Select(x => x.DataNode).Concat(previousYearData.Select(x => x.LinkedDataNode));", + "\n var previousLinksCount = prevlinks.Where(x => x == dn).Count();", + "\n ", + "\n //Current Period", + "\n var computedCount = interDataNodeParameters[dn][CurrentPeriod].Count();", + "\n", + "\n if (currentYearData.Any())", + "\n {", + "\n if(computedCount != currentLinksCount)", + "\n errors.Add( $\"Current DataNode parameter count for {dn} not matching:\\n Expected {currentLinksCount} \\n Computed {computedCount}.\" );", + "\n }", + "\n else if(computedCount != previousLinksCount)", + "\n errors.Add( $\"Current DataNode parameter count for {dn} not matching:\\n Expected {previousLinksCount} \\n Computed {computedCount}.\" );", + "\n ", + "\n foreach (var param in interDataNodeParameters[dn][CurrentPeriod])", + "\n {", + "\n var linkedDn = param.DataNode == dn ? param.LinkedDataNode : param.DataNode;", + "\n var isLinkInPrevPeriod = previousYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn);", + "\n var isLinkInCurrPeriod = currentYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn); ", + "\n ", + "\n if(isLinkInPrevPeriod && !isLinkInCurrPeriod)", + "\n { ", + "\n if (param.ReinsuranceCoverage != ((double)previousYear)/1000)", + "\n errors.Add( $\"Current Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)previousYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n else if( param.ReinsuranceCoverage != ((double)currentYear)/1000)", + "\n errors.Add( $\"Current Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)currentYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n", + "\n //Previous Period", + "\n computedCount = interDataNodeParameters[dn][PreviousPeriod].Count();", + "\n ", + "\n if (currentYearData.Any())", + "\n {", + "\n if(computedCount != currentLinksCount)", + "\n errors.Add( $\"Previous DataNode parameter count for {dn} not matching:\\n Expected {currentLinksCount} \\n Computed {computedCount}.\" );", + "\n }", + "\n else if(computedCount != previousLinksCount)", + "\n errors.Add( $\"Previous DataNode parameter count for {dn} not matching:\\n Expected {previousLinksCount} \\n Computed {computedCount}.\" );", + "\n ", + "\n foreach (var param in interDataNodeParameters[dn][PreviousPeriod])", + "\n {", + "\n var linkedDn = param.DataNode == dn ? param.LinkedDataNode : param.DataNode;", + "\n var isLinkInPrevPeriod = previousYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn);", + "\n var isLinkInCurrPeriod = currentYearData.Any(x => x.DataNode == dn && x.LinkedDataNode == linkedDn || x.DataNode == linkedDn && x.LinkedDataNode == dn); ", + "\n ", + "\n if(!isLinkInPrevPeriod && isLinkInCurrPeriod)", + "\n { ", + "\n if (param.ReinsuranceCoverage != ((double)currentYear)/1000)", + "\n errors.Add( $\"Previous Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)currentYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n else if( param.ReinsuranceCoverage != ((double)previousYear)/1000)", + "\n errors.Add( $\"Previous Reinsurance Coverage for {dn} linked to {linkedDn} not matching:\\n Expected {((double)previousYear)/1000} \\n Computed {param.ReinsuranceCoverage}.\" );", + "\n }", + "\n }", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gic2, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear);" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nint currentYear = 2020;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9},", + "\n new InterDataNodeParameter{ DataNode = gic2, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 9}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nint currentYear = 2020;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)previousYear)/1000, Year = previousYear, Month = 3}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new Args(\"CH\",2020,9,Periodicity.Monthly,null);", + "\nint previousYear = 2019;", + "\nint currentYear = 2020;", + "\nvar testData = new InterDataNodeParameter[] ", + "\n {", + "\n new InterDataNodeParameter{ DataNode = gic, LinkedDataNode = gric1, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 3}, ", + "\n new InterDataNodeParameter{ DataNode = gric1, LinkedDataNode = xgic, ReinsuranceCoverage = ((double)currentYear)/1000, Year = currentYear, Month = 3}, ", + "\n };", + "\n", + "\nawait CheckLoadInterDataNodeParameterAsync(args, testData, previousYear, currentYear);" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/ReportStorageTest.ipynb b/Test/ReportStorageTest.ipynb index 58850654..4d728148 100644 --- a/Test/ReportStorageTest.ipynb +++ b/Test/ReportStorageTest.ipynb @@ -1,127 +1,97 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "-CZo3x5cFEuDFZgs0uV9Bg", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Report/ReportStorage\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uXciD3hgUUqyPIiuAEQo3g", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tdRjnVvg9UaWMh368aBZ3g", - "cell_type": "markdown", - "source": [ - "# Test Exchange Rate Query" - ], - "metadata": {} - }, - { - "id": "j4bt5YUenkeFF2iakkxvgg", - "cell_type": "code", - "source": [ - "Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bd3JNWC5Nk2uaw14n6g2xQ", - "cell_type": "code", - "source": [ - "public async Task CheckGetFx(string currentCurrency, string targetCurrency, int year, int month, IEnumerable testData, double fxBOPBenchmark, double fxAVGBenchmark, double fxEOPBenchmark)", - "\n{", - "\n await Workspace.UpdateAsync(testData);", - "\n ", - "\n //Create report storage", - "\n var period = (year, month);", - "\n var reportStorage = new ReportStorage(Workspace, Report);", - "\n await reportStorage.InitializeReportIndependentCacheAsync();", - "\n await reportStorage.InitializeAsync(period, \"G\", null, CurrencyType.Contractual);", - "\n ", - "\n var fxBOP = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.BeginningOfPeriod);", - "\n var fxAVG = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.Average);", - "\n var fxEOP = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.EndOfPeriod);", - "\n ", - "\n //Check FX rates", - "\n fxBOP.Should().Be(fxBOPBenchmark);", - "\n fxAVG.Should().Be(fxAVGBenchmark);", - "\n fxEOP.Should().Be(fxEOPBenchmark);", - "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "P6Lb3Bg1-ECmcI2_hG1fyQ", - "cell_type": "code", - "source": [ - "var testData = new ExchangeRate[] {new ExchangeRate{ Currency = \"EUR\", Year = 2020, Month = 12, FxType = FxType.Spot, FxToGroupCurrency = 10 }, ", - "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 3, FxType = FxType.Spot, FxToGroupCurrency = 15 },", - "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 6, FxType = FxType.Average, FxToGroupCurrency = 20 },", - "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 6, FxType = FxType.Spot, FxToGroupCurrency = 30 },", - "\n new ExchangeRate{ Currency = \"USD\", Year = 2020, Month = 12, FxType = FxType.Spot, FxToGroupCurrency = 5 },", - "\n new ExchangeRate{ Currency = \"USD\", Year = 2021, Month = 6, FxType = FxType.Average, FxToGroupCurrency = 2 },", - "\n new ExchangeRate{ Currency = \"USD\", Year = 2021, Month = 6, FxType = FxType.Spot, FxToGroupCurrency = 0.5 }};", - "\nawait CheckGetFx(\"EUR\", \"USD\", 2021, 6, testData, 2, 10, 60);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OncbMvm_E0OazTHlWRs1yQ", - "cell_type": "code", - "source": [ - "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "h7lqAB05-0eTTOzD9xJS2g", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Report/ReportStorage\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Exchange Rate Query" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization());" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckGetFx(string currentCurrency, string targetCurrency, int year, int month, IEnumerable testData, double fxBOPBenchmark, double fxAVGBenchmark, double fxEOPBenchmark)", + "\n{", + "\n await Workspace.UpdateAsync(testData);", + "\n ", + "\n //Create report storage", + "\n var period = (year, month);", + "\n var reportStorage = new ReportStorage(Workspace, Report);", + "\n await reportStorage.InitializeReportIndependentCacheAsync();", + "\n await reportStorage.InitializeAsync(period, \"G\", null, CurrencyType.Contractual);", + "\n ", + "\n var fxBOP = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.BeginningOfPeriod);", + "\n var fxAVG = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.Average);", + "\n var fxEOP = reportStorage.GetFx(period, currentCurrency, targetCurrency, FxPeriod.EndOfPeriod);", + "\n ", + "\n //Check FX rates", + "\n fxBOP.Should().Be(fxBOPBenchmark);", + "\n fxAVG.Should().Be(fxAVGBenchmark);", + "\n fxEOP.Should().Be(fxEOPBenchmark);", + "\n ", + "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var testData = new ExchangeRate[] {new ExchangeRate{ Currency = \"EUR\", Year = 2020, Month = 12, FxType = FxType.Spot, FxToGroupCurrency = 10 }, ", + "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 3, FxType = FxType.Spot, FxToGroupCurrency = 15 },", + "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 6, FxType = FxType.Average, FxToGroupCurrency = 20 },", + "\n new ExchangeRate{ Currency = \"EUR\", Year = 2021, Month = 6, FxType = FxType.Spot, FxToGroupCurrency = 30 },", + "\n new ExchangeRate{ Currency = \"USD\", Year = 2020, Month = 12, FxType = FxType.Spot, FxToGroupCurrency = 5 },", + "\n new ExchangeRate{ Currency = \"USD\", Year = 2021, Month = 6, FxType = FxType.Average, FxToGroupCurrency = 2 },", + "\n new ExchangeRate{ Currency = \"USD\", Year = 2021, Month = 6, FxType = FxType.Spot, FxToGroupCurrency = 0.5 }};", + "\nawait CheckGetFx(\"EUR\", \"USD\", 2021, 6, testData, 2, 10, 60);" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/ReportVariablesTest.ipynb b/Test/ReportVariablesTest.ipynb index 343f3835..eb31bd44 100644 --- a/Test/ReportVariablesTest.ipynb +++ b/Test/ReportVariablesTest.ipynb @@ -1,256 +1,182 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "LQUN8dM-FUOLRRCNCCfefg", - "cell_type": "markdown", - "source": [ - "

Test Reports

" - ], - "metadata": {} - }, - { - "id": "FeOU5sOWxUCzzbh-gAXjpQ", - "cell_type": "markdown", - "source": [ - "# Infrastructure and Configuration" - ], - "metadata": {} - }, - { - "id": "eULpl26ryUODapYZKqPsAg", - "cell_type": "markdown", - "source": [ - "## Imports and Configurations" - ], - "metadata": {} - }, - { - "id": "v68OhAZHnkmBFLc4VS_Wsg", - "cell_type": "code", - "source": [ - "#r \"nuget:FluentAssertions\" " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "S5Jab8aqL0q_0yz2NvANCg", - "cell_type": "code", - "source": [ - "#!import \"ReportVariablesTestBase\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "T5-epYkxdESEdRkeQzPZ-Q", - "cell_type": "markdown", - "source": [ - "## Initialize Workspace" - ], - "metadata": {} - }, - { - "id": "MjO2BvvAS0e4HFtBefzQiQ", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WYaoK2llRES_PV3X7rt7dw", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LPEQPX6GkU6oZRTDNeu9gg", - "cell_type": "markdown", - "source": [ - "## Storage" - ], - "metadata": {} - }, - { - "id": "iyzfnUDQkE-IFlJDJhToWg", - "cell_type": "code", - "source": [ - "var reportStorage = new ReportStorage(Workspace, Report);", - "\nawait reportStorage.InitializeReportIndependentCacheAsync();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "PFEVTLIKUE6H0KLbPCp60w", - "cell_type": "markdown", - "source": [ - "## Configurations" - ], - "metadata": {} - }, - { - "id": "0JhPAc6LX0Wa6M-BQfsrPw", - "cell_type": "code", - "source": [ - "var path = \"./Data/ReportVariableBenchmarks/\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XutzHhUA00KlM1bajdW_IQ", - "cell_type": "code", - "source": [ - "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args;", - "\nICollection scopesData;", - "\nICollection benchmarkData;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WTg65cXwoUC2csjHSFzPfw", - "cell_type": "markdown", - "source": [ - "# Test Cases" - ], - "metadata": {} - }, - { - "id": "7rnaJC3nVkGkge79ibM8KA", - "cell_type": "markdown", - "source": [ - "## ((2020, 12), \"CH\", null, CurrencyType.Contractual)" - ], - "metadata": {} - }, - { - "id": "E34nYeT2ckKrYWP3mxgc2g", - "cell_type": "code", - "source": [ - "args = ((2020, 12), \"CH\", null, CurrencyType.Contractual);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uBf_ViTSUUe1CC5J5UfWHA", - "cell_type": "code", - "source": [ - "scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", - "\nbenchmarkData = await GetBenchmarkDataAsync(args, path, Workspace, Import);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZB0QEVnuHUWzFbp6xXyVdg", - "cell_type": "code", - "source": [ - "scopesData.Should().BeEquivalentTo(benchmarkData,", - "\n options => options", - "\n //.ComparingRecordsByValue()", - "\n .ComparingRecordsByMembers() ", - "\n //.ComparingByMembers()", - "\n //.ComparingByValue()", - "\n //.Excluding(o => o.Value)", - "\n .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, BenchmarkPrecision))", - "\n .WhenTypeIs()", - "\n );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "g026nTeHy0a1vC2J5XM87g", - "cell_type": "markdown", - "source": [ - "## ((2021, 3), \"CH\", null, CurrencyType.Contractual)" - ], - "metadata": {} - }, - { - "id": "D7qV0NdVHE2Kdk6uavXIKw", - "cell_type": "code", - "source": [ - "args = ((2021, 3), \"CH\", null, CurrencyType.Contractual);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZYBQRO7yZ02UzX2eYt7Vnw", - "cell_type": "code", - "source": [ - "scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", - "\nbenchmarkData = await GetBenchmarkDataAsync(args, path, Workspace, Import);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "age1izMU1EmhYYO6S_LhWw", - "cell_type": "code", - "source": [ - "scopesData.Should().BeEquivalentTo(benchmarkData,", - "\n options => options", - "\n //.ComparingRecordsByValue()", - "\n .ComparingRecordsByMembers() ", - "\n //.ComparingByMembers()", - "\n //.ComparingByValue()", - "\n //.Excluding(o => o.Value)", - "\n .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, Precision))", - "\n .WhenTypeIs()", - "\n );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dl7B6Z5qnEWoD8LTXhUAYw", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Test Reports

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "#r \"nuget:FluentAssertions\" " + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportVariablesTestBase\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Initialize Workspace" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Storage" + ] + }, + { + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "var path = \"./Data/ReportVariableBenchmarks/\";" + ] + }, + { + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args;", + "\nICollection scopesData;", + "\nICollection benchmarkData;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test Cases" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## ((2020, 12), \"CH\", null, CurrencyType.Contractual)" + ] + }, + { + "cell_type": "code", + "source": [ + "args = ((2020, 12), \"CH\", null, CurrencyType.Contractual);" + ] + }, + { + "cell_type": "code", + "source": [ + "scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", + "\nbenchmarkData = await GetBenchmarkDataAsync(args, path, Workspace, Import);" + ] + }, + { + "cell_type": "code", + "source": [ + "scopesData.Should().BeEquivalentTo(benchmarkData,", + "\n options => options", + "\n //.ComparingRecordsByValue()", + "\n .ComparingRecordsByMembers() ", + "\n //.ComparingByMembers()", + "\n //.ComparingByValue()", + "\n //.Excluding(o => o.Value)", + "\n .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, BenchmarkPrecision))", + "\n .WhenTypeIs()", + "\n );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## ((2021, 3), \"CH\", null, CurrencyType.Contractual)" + ] + }, + { + "cell_type": "code", + "source": [ + "args = ((2021, 3), \"CH\", null, CurrencyType.Contractual);" + ] + }, + { + "cell_type": "code", + "source": [ + "scopesData = await GetScopesDataAsync(args, reportStorage, Scopes);", + "\nbenchmarkData = await GetBenchmarkDataAsync(args, path, Workspace, Import);" + ] + }, + { + "cell_type": "code", + "source": [ + "scopesData.Should().BeEquivalentTo(benchmarkData,", + "\n options => options", + "\n //.ComparingRecordsByValue()", + "\n .ComparingRecordsByMembers() ", + "\n //.ComparingByMembers()", + "\n //.ComparingByValue()", + "\n //.Excluding(o => o.Value)", + "\n .Using(ctx => ctx.Subject.Should().BeApproximately(ctx.Expectation, Precision))", + "\n .WhenTypeIs()", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/ReportVariablesTestBase.ipynb b/Test/ReportVariablesTestBase.ipynb index e031e8d0..77732e98 100644 --- a/Test/ReportVariablesTestBase.ipynb +++ b/Test/ReportVariablesTestBase.ipynb @@ -1,161 +1,129 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "FYwy37yMNEeDl1kHPRFpKg", - "cell_type": "markdown", - "source": [ - "

Report Variable Test Base

" - ], - "metadata": {} - }, - { - "id": "3ZyHFOIosEyHCIUotySSVQ", - "cell_type": "code", - "source": [ - "#!import \"../Report/ReportScopes\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "injwhNjFM0Gd0wGXOWk0iw", - "cell_type": "markdown", - "source": [ - "# Helpers" - ], - "metadata": {} - }, - { - "id": "16zJY8-HwUWXMwwH0PDnKA", - "cell_type": "code", - "source": [ - "const string benchmarkFileNamePrefix = \"ReportVariableBenchmarks_\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "w93TGY8caEWby3AEWexMfw", - "cell_type": "code", - "source": [ - "static string GetBenchmarkFileName(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args) => args.ToString().Replace(\"(\", \"\").Replace(\")\", \"\").Replace(\" \", \"\").Replace(\",\", \"_\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FN-2epLYEEi0XlPqNMZBmQ", - "cell_type": "markdown", - "source": [ - "# Calculated" - ], - "metadata": {} - }, - { - "id": "lpbvuOTZvkeSAcnrEI9kXQ", - "cell_type": "code", - "source": [ - "static ICollection GetScopesData(Systemorph.Vertex.Scopes.IScopeWithStorage universe, ICollection<(ReportIdentity, CurrencyType)> identities) {", - "\n ", - "\n var lockedBePvs = universe.GetScopes(identities).Aggregate().LockedBestEstimate;", - "\n var currentBePvs = universe.GetScopes(identities).Aggregate().CurrentBestEstimate; ", - "\n", - "\n var lockedRaPvs = universe.GetScopes(identities).Aggregate().LockedRiskAdjustment;", - "\n var currentRaPvs = universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment;", - "\n", - "\n var writtenActuals = universe.GetScopes(identities).Aggregate().Written;", - "\n var advanceActuals = universe.GetScopes(identities).Aggregate().Advance;", - "\n var overdueActuals = universe.GetScopes(identities).Aggregate().Overdue;", - "\n", - "\n var deferrableActuals = universe.GetScopes(identities).Aggregate().Deferrals;", - "\n", - "\n var csm = universe.GetScopes(identities).Aggregate().Csm;", - "\n var lc = universe.GetScopes(identities).Aggregate().Lc;", - "\n var loreco = universe.GetScopes(identities).Aggregate().Loreco;", - "\n", - "\n var fp = universe.GetScopes(identities).Aggregate().FinancialPerformance;", - "\n ", - "\n return Enumerable.Empty()", - "\n .Concat(lockedBePvs) ", - "\n .Concat(currentBePvs)", - "\n .Concat(lockedRaPvs)", - "\n .Concat(currentRaPvs)", - "\n .Concat(writtenActuals)", - "\n .Concat(advanceActuals)", - "\n .Concat(overdueActuals)", - "\n .Concat(deferrableActuals)", - "\n .Concat(csm)", - "\n .Concat(lc)", - "\n .Concat(loreco)", - "\n .Concat(fp)", - "\n .OrderBy(v => v.GroupOfContract).ThenBy(v => v.Scenario).ThenBy(v => v.Projection).ThenBy(v => v.AccidentYear).ThenBy(v => v.EstimateType).ThenBy(v => (v.VariableType, v.Novelty))", - "\n .ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GBx1EE3IREu7RPWu8iZFbg", - "cell_type": "code", - "source": [ - "static async Task> GetScopesDataAsync(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args, ReportStorage reportStorage, Systemorph.Vertex.Scopes.Proxy.IScopeFactory scopes ) {", - "\n await reportStorage.InitializeAsync(args.Period, args.ReportingNode, args.Scenario, args.CurrencyType);", - "\n var identities = reportStorage.GetIdentities(args.Period, args.ReportingNode, args.Scenario, args.CurrencyType);", - "\n var universe = scopes.ForSingleton().WithStorage(reportStorage).ToScope();", - "\n return GetScopesData(universe, identities);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fkOXnPgChECva8WmF0hbaQ", - "cell_type": "markdown", - "source": [ - "# Benchmarks" - ], - "metadata": {} - }, - { - "id": "BJVbgmFieEGNehAotQ38Eg", - "cell_type": "code", - "source": [ - "static async Task> GetBenchmarkDataAsync(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args, string path, IWorkspace workspace, IImportVariable importVariable) {", - "\n var bmFileName = benchmarkFileNamePrefix + GetBenchmarkFileName(args) + \".csv\";", - "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", - "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Period.Year, Month = args.Period.Month });", - "\n await importVariable.FromFile(path + bmFileName).WithType(x => x.SnapshotMode()).WithTarget(workspace).ExecuteAsync();", - "\n var ret = await workspace.Query().ToArrayAsync();", - "\n workspace.Reset(x => x.ResetCurrentPartitions().ResetType());", - "\n return ret;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Report Variable Test Base

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Report/ReportScopes\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Helpers" + ] + }, + { + "cell_type": "code", + "source": [ + "const string benchmarkFileNamePrefix = \"ReportVariableBenchmarks_\";" + ] + }, + { + "cell_type": "code", + "source": [ + "static string GetBenchmarkFileName(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args) => args.ToString().Replace(\"(\", \"\").Replace(\")\", \"\").Replace(\" \", \"\").Replace(\",\", \"_\");" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Calculated" + ] + }, + { + "cell_type": "code", + "source": [ + "static ICollection GetScopesData(Systemorph.Vertex.Scopes.IScopeWithStorage universe, ICollection<(ReportIdentity, CurrencyType)> identities) {", + "\n ", + "\n var lockedBePvs = universe.GetScopes(identities).Aggregate().LockedBestEstimate;", + "\n var currentBePvs = universe.GetScopes(identities).Aggregate().CurrentBestEstimate; ", + "\n", + "\n var lockedRaPvs = universe.GetScopes(identities).Aggregate().LockedRiskAdjustment;", + "\n var currentRaPvs = universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment;", + "\n", + "\n var writtenActuals = universe.GetScopes(identities).Aggregate().Written;", + "\n var advanceActuals = universe.GetScopes(identities).Aggregate().Advance;", + "\n var overdueActuals = universe.GetScopes(identities).Aggregate().Overdue;", + "\n", + "\n var deferrableActuals = universe.GetScopes(identities).Aggregate().Deferrals;", + "\n", + "\n var csm = universe.GetScopes(identities).Aggregate().Csm;", + "\n var lc = universe.GetScopes(identities).Aggregate().Lc;", + "\n var loreco = universe.GetScopes(identities).Aggregate().Loreco;", + "\n", + "\n var fp = universe.GetScopes(identities).Aggregate().FinancialPerformance;", + "\n ", + "\n return Enumerable.Empty()", + "\n .Concat(lockedBePvs) ", + "\n .Concat(currentBePvs)", + "\n .Concat(lockedRaPvs)", + "\n .Concat(currentRaPvs)", + "\n .Concat(writtenActuals)", + "\n .Concat(advanceActuals)", + "\n .Concat(overdueActuals)", + "\n .Concat(deferrableActuals)", + "\n .Concat(csm)", + "\n .Concat(lc)", + "\n .Concat(loreco)", + "\n .Concat(fp)", + "\n .OrderBy(v => v.GroupOfContract).ThenBy(v => v.Scenario).ThenBy(v => v.Projection).ThenBy(v => v.AccidentYear).ThenBy(v => v.EstimateType).ThenBy(v => (v.VariableType, v.Novelty))", + "\n .ToArray();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "static async Task> GetScopesDataAsync(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args, ReportStorage reportStorage, Systemorph.Vertex.Scopes.Proxy.IScopeFactory scopes ) {", + "\n await reportStorage.InitializeAsync(args.Period, args.ReportingNode, args.Scenario, args.CurrencyType);", + "\n var identities = reportStorage.GetIdentities(args.Period, args.ReportingNode, args.Scenario, args.CurrencyType);", + "\n var universe = scopes.ForSingleton().WithStorage(reportStorage).ToScope();", + "\n return GetScopesData(universe, identities);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Benchmarks" + ] + }, + { + "cell_type": "code", + "source": [ + "static async Task> GetBenchmarkDataAsync(((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) args, string path, IWorkspace workspace, IImportVariable importVariable) {", + "\n var bmFileName = benchmarkFileNamePrefix + GetBenchmarkFileName(args) + \".csv\";", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", + "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Period.Year, Month = args.Period.Month });", + "\n await importVariable.FromFile(path + bmFileName).WithType(x => x.SnapshotMode()).WithTarget(workspace).ExecuteAsync();", + "\n var ret = await workspace.Query().ToArrayAsync();", + "\n workspace.Reset(x => x.ResetCurrentPartitions().ResetType());", + "\n return ret;", + "\n}" + ] + } + ] } \ No newline at end of file diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/Test/SpecificationsFinancialPerformance.ipynb index 70570b54..6cf10521 100644 --- a/Test/SpecificationsFinancialPerformance.ipynb +++ b/Test/SpecificationsFinancialPerformance.ipynb @@ -1,1692 +1,1184 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "5nO38HYGpkascixiTUO0gw", - "cell_type": "markdown", - "source": [ - "

Financial Performance Specifications

" - ], - "metadata": {} - }, - { - "id": "YiqIuEZ5Ika8lHG2QytiBg", - "cell_type": "markdown", - "source": [ - "The aim of this notebook is to document the Financial Performance reporting system. The process is pictorially explained in the following flowchart. ", - "\n", - "\n", - "\n
", - "\n", - "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." - ], - "metadata": {} - }, - { - "id": "I_4NcYOLg0-FT87qtmCw5g", - "cell_type": "markdown", - "source": [ - "In the following the Dimensions, Parameters, Nominal Cashflows, and Actuals are imported from the corresponding csv files in Initialization/Systemorph/" - ], - "metadata": {} - }, - { - "id": "G0Y5GVas3k6z7nhLhKYi2A", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "SZwhFp3mkUKWwRMH8wcnKw", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "FCPPVD5qb0edgdnX8gE5TA", - "cell_type": "markdown", - "source": [ - "# Process Data" - ], - "metadata": {} - }, - { - "id": "8kQa9wme2E2KwZMXm_jkRQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Current Period, Reporting Node and Currency Type" - ], - "metadata": {} - }, - { - "id": "9Mil10I7XUKS9qwodcQnJQ", - "cell_type": "markdown", - "source": [ - "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" - ], - "metadata": {} - }, - { - "id": "jycgHCLPSU6SsnQh_NqdXQ", - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Q1ptu1Ih6UqNipHCM9wrFw", - "cell_type": "markdown", - "source": [ - "and the type of Currency among Contractual, Functional, and Group" - ], - "metadata": {} - }, - { - "id": "W_q-kxke4kSXENWTI_sTDg", - "cell_type": "code", - "source": [ - "var currencyType = CurrencyType.Contractual ;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Z5gPrgd79kaIdxevViMb5Q", - "cell_type": "markdown", - "source": [ - "Import the Report definitions, initialize the Workspace and the Test Suite:" - ], - "metadata": {} - }, - { - "id": "jZs86CqBw0S_Ms4QvU6Yhg", - "cell_type": "code", - "source": [ - "#!import \"../Report/ReportScopes\"", - "\n#!import \"../Report/ReportConfigurationAndUtils\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fsDoELzhOEKHVk0LvwG8lg", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FwJCyVQlg0iyVa9GIObOVA", - "cell_type": "code", - "source": [ - "var period = (year, month) ;", - "\nvar reportStorage = new ReportStorage(Workspace, Report) ;", - "\nvar Test = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0H5JBXBojEmJX2J4YxoSKQ", - "cell_type": "code", - "source": [ - "await reportStorage.InitializeReportIndependentCacheAsync();", - "\nawait reportStorage.InitializeAsync(period, reportingNode, null, currencyType);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ljauWn5bzkePv8oz0hmmcw", - "cell_type": "markdown", - "source": [ - "## View list of Identities" - ], - "metadata": {} - }, - { - "id": "ROlx1yHrOkOcN8NoaWg_kQ", - "cell_type": "markdown", - "source": [ - "Based on the Cashflows imported, the list of all possible identities, i.e. combinations of valid Contractual and Functional Currencies, Liability Types, (Re)Insurance and Oci, is contructed and reported here below:" - ], - "metadata": {} - }, - { - "id": "FWlyPQurk0e7MxUr1_Vh4Q", - "cell_type": "code", - "source": [ - "var identities = reportStorage.GetIdentities(period, reportingNode, null, currencyType);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dQr4xO85AkW_XOGwRhp3Wg", - "cell_type": "code", - "source": [ - "identities" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8WK3-WqoVkKWxMmrunWCPw", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Report" - ], - "metadata": {} - }, - { - "id": "6SapvCdFR0Wa-5iw2O7bmA", - "cell_type": "markdown", - "source": [ - "Please select here below the target Data Node for executing the tests below:" - ], - "metadata": {} - }, - { - "id": "tnnSkBvTP0OcTweKBHRVwA", - "cell_type": "code", - "source": [ - "var dataNode = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MaxaD_pix0qUJSHQFYw_Yg", - "cell_type": "markdown", - "source": [ - "The Group of Contract selected is:" - ], - "metadata": {} - }, - { - "id": "ojOHd0ltR0ysyqjaXBV7fA", - "cell_type": "code", - "source": [ - "var groupOfContract = (await Workspace.Query().Where(x => x.SystemName == dataNode).ToArrayAsync()).FirstOrDefault();", - "\ngroupOfContract" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2wrq4ud_nUywAVYp0c16ng", - "cell_type": "markdown", - "source": [ - "where ", - "\n- the **OciType** can be Default for contracts with non-zero OCI, and null otherwise, ", - "\n- the **Liability Type** can be LRC for Liability for Remaining Coverage, and LIC for Liability of Incurred Claims,", - "\n- the **Partner** can be null for Insurance contracts, or equal to the Partner System Name for Reinsurance contracts." - ], - "metadata": {} - }, - { - "id": "FLplPZmhH0uHoByRc9jzyw", - "cell_type": "markdown", - "source": [ - "The summary of the Financial Performance report is shown below" - ], - "metadata": {} - }, - { - "id": "PPVlpKTvE0utqi7d_6hsOA", - "cell_type": "code", - "source": [ - "Report.ForDataCube( Test.GetScopes(identities).Aggregate().FinancialPerformance.Filter((\"GroupOfContract\", dataNode)) )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(currencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", - "\n .ToReport() with { Height = 600 }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Y6ExKbo35kizVyUzucL8tg", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Inspection" - ], - "metadata": {} - }, - { - "id": "mljPLFn_Vk699EW8NxaqFQ", - "cell_type": "markdown", - "source": [ - "## Fulfillment Cashflows" - ], - "metadata": {} - }, - { - "id": "fXAJiiBobE-8cIFXnwQW_g", - "cell_type": "markdown", - "source": [ - "The Fulfillment Cashflow (FCF) corresponds to the sum of the Best Estimate [Present Value](../Import/ImportScopeCalculation#current-and-locked) (PV) and the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) (RA), both summed over Amounty Types, and both discounted with the Locked-In curve in the BBA valuation approach:", - "\n", - "\n$$", - "\n\\text{FCF}(\\text{AoC}) = \\text{PV Locked}(\\text{AoC})", - "\n\\bigg|_{\\substack{\\text{Non Attributable} \\\\ \\text{Amount Types} \\\\ \\text{excluded}}} ", - "\n+ \\text{RA Locked}(\\text{AoC}) ~.", - "\n$$" - ], - "metadata": {} - }, - { - "id": "EIByt77nt02vKJ6M7fbYPA", - "cell_type": "markdown", - "source": [ - "### Non Financial" - ], - "metadata": {} - }, - { - "id": "BeRPnXRcr0KgXSe9gOqr0w", - "cell_type": "markdown", - "source": [ - "The computed value for the non financial contribution to the FCF is" - ], - "metadata": {} - }, - { - "id": "Tpu5SaZ9GEGA3y-zQW_yHw", - "cell_type": "code", - "source": [ - "var computedDeltaFCF_nonFinancial = Test.GetScopes(identities).Aggregate()", - "\n .FpNonFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1lQULEdowk-gnCueOrvJrg", - "cell_type": "code", - "source": [ - "computedDeltaFCF_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "i4QyAGfVmEGE_5Igb2Z-LQ", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the full list of FCFs" - ], - "metadata": {} - }, - { - "id": "qqBotvtEjE22aC7q0898qw", - "cell_type": "code", - "source": [ - "var FCFs = Test.GetScopes(identities).Aggregate().Fcf.Filter((\"GroupOfContract\", dataNode));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VzFxq-PplkGMBBeSgTqoVg", - "cell_type": "code", - "source": [ - "var deltaFCF = FCFs.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n FCFs.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iNXYCe0l-U2neY7wtMwZ0Q", - "cell_type": "code", - "source": [ - "deltaFCF.Aggregate().Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yI_ySCVJT06znmYYyfM3zQ", - "cell_type": "code", - "source": [ - "var expectedDeltaFCF_nonFinancial = deltaFCF.Filter((\"VariableType\", \"!IA\"), ", - "\n (\"VariableType\", \"!YCU\"), ", - "\n (\"VariableType\", \"!CRU\") ).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kYVlMOqOrEeCvRN9BdzD5Q", - "cell_type": "code", - "source": [ - "expectedDeltaFCF_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vLdRwY5WPEeVSdEZ6mq5eg", - "cell_type": "markdown", - "source": [ - "For consistency, this term is taken with the minus sign" - ], - "metadata": {} - }, - { - "id": "1z_-jBHxPECdPV59L1zu3w", - "cell_type": "code", - "source": [ - "expectedDeltaFCF_nonFinancial.CheckEquality( -computedDeltaFCF_nonFinancial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zLC_x5tXRkqCJb8ko1k1pw", - "cell_type": "markdown", - "source": [ - "### Financial" - ], - "metadata": {} - }, - { - "id": "8q-L68QoyUWnE_1p9I8GrQ", - "cell_type": "markdown", - "source": [ - "Conversely, the computed value for the financial contribution to the Fulfillment Cashflows (FCF) is" - ], - "metadata": {} - }, - { - "id": "unbfg7yEZkajmEbeDpLGbw", - "cell_type": "code", - "source": [ - "var computedDeltaFCF_Financial = Test.GetScopes(identities).Aggregate()", - "\n .FpFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1Z9AZCSrsUqNaYXcDtgG9g", - "cell_type": "code", - "source": [ - "computedDeltaFCF_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QUKtT16YKECBrRssqHJ7iA", - "cell_type": "markdown", - "source": [ - "The independent recalculation of this value reads" - ], - "metadata": {} - }, - { - "id": "DBD46hb6jkmOuS8fF8AzNg", - "cell_type": "code", - "source": [ - "var expectedDeltaFCF_Financial = (deltaFCF.Filter((\"VariableType\", \"IA\")) +", - "\n deltaFCF.Filter((\"VariableType\", \"YCU\")) +", - "\n deltaFCF.Filter((\"VariableType\", \"CRU\")) ).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3Pml-0__90GYfwqGIkh8hA", - "cell_type": "code", - "source": [ - "expectedDeltaFCF_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WeeGHMbfv0yDqvE0uspuwA", - "cell_type": "markdown", - "source": [ - "taking the minus sign into account" - ], - "metadata": {} - }, - { - "id": "Jy8LN1Jl9UW7ZFn61_0E7g", - "cell_type": "code", - "source": [ - "expectedDeltaFCF_Financial.CheckEquality( -computedDeltaFCF_Financial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KdafoHd6V0WcBY3w-7FCNg", - "cell_type": "markdown", - "source": [ - "### Other Comprehensive Income" - ], - "metadata": {} - }, - { - "id": "WTWsM2t8ske9c6Qp4Sw6tw", - "cell_type": "markdown", - "source": [ - "The Other Comprehensive Income (OCI) term is by definition the sum of the financial contributions not related to the insurance sector.", - "\n", - "\nThe Default method to compute the OCI term is by subtracting the FCF computed with the *Locked-In* rates and the FCF computed with the *Current* rates. In this way the non insurance financial volatiliy of the economic input is relegated to the OCI. " - ], - "metadata": {} - }, - { - "id": "HFvK3TQALEyxtaqOa072RA", - "cell_type": "code", - "source": [ - "var computedDeltaFCF_OCI = Test.GetScopes(identities).Aggregate()", - "\n .OciFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KlV-XHswLUm60jAtrKXRxw", - "cell_type": "code", - "source": [ - "computedDeltaFCF_OCI" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wLYM_5_Cw0agX8ngdpiJNw", - "cell_type": "markdown", - "source": [ - "The OCI contribution is zero when the OCI option is disabled for the [target Group of Contract](#report).", - "\n", - "\nHere below we follow the steps to calculate independently the OCI contribution " - ], - "metadata": {} - }, - { - "id": "jExIPgxaoEKHbQ0n1CCDlg", - "cell_type": "code", - "source": [ - "var DeltaFCF_Locked = deltaFCF.Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Fi1WFLVNokSI8kGpGrtSgg", - "cell_type": "code", - "source": [ - "var FCFs_current = Test.GetScopes(identities).Aggregate().CurrentFcf.Filter((\"GroupOfContract\", dataNode));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "08PqnzK1VkqrjayuXu29Gw", - "cell_type": "code", - "source": [ - "var DeltaFCF_Current = FCFs_current.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n FCFs_current.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2H7J_REURECEUakkHg3uZQ", - "cell_type": "code", - "source": [ - "var expectedDeltaFCF_OCI = DeltaFCF_Locked - DeltaFCF_Current.Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0bDk7FRhN0C2sRCzbkIzrQ", - "cell_type": "code", - "source": [ - "DeltaFCF_Locked" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FG-gv68W_E2X5Duxt7tKlw", - "cell_type": "code", - "source": [ - "DeltaFCF_Current.Aggregate().Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HOaaRyAoI0CC6BerqeJ41Q", - "cell_type": "code", - "source": [ - "expectedDeltaFCF_OCI" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uTbfa8NPIUqm-o4eZSU8fw", - "cell_type": "code", - "source": [ - "expectedDeltaFCF_OCI.CheckEquality( computedDeltaFCF_OCI ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1IZSRJ3t_0CNXpp4ywd9VQ", - "cell_type": "markdown", - "source": [ - "## Contractual Service Margin" - ], - "metadata": {} - }, - { - "id": "5bsUEITa6kuGaTRVkZ084A", - "cell_type": "markdown", - "source": [ - "### Non Financial" - ], - "metadata": {} - }, - { - "id": "JTfLDJSJQEOWT2i89grUSQ", - "cell_type": "markdown", - "source": [ - "The computed value for the non financial change of the CSM is" - ], - "metadata": {} - }, - { - "id": "8ILRJFbhBUC62g15t754iQ", - "cell_type": "code", - "source": [ - "var computedDeltaCSM_nonFinancial = Test.GetScopes(identities).Aggregate()", - "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WKz0gPwLNU-dpX_9pel6qQ", - "cell_type": "code", - "source": [ - "computedDeltaCSM_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "M-zez2dNKEqoEuSnVmQOAQ", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the full CSM data from which the delta can be computed:" - ], - "metadata": {} - }, - { - "id": "u3qO33HX2EWTdU-FsXV1DQ", - "cell_type": "code", - "source": [ - "var CSM = Test.GetScopes(identities).Aggregate().Csm.Filter((\"GroupOfContract\", dataNode));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sUzTJENNQE2vyUAMH18-Fg", - "cell_type": "code", - "source": [ - "var deltaCSM = CSM.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n CSM.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YE8SeJsLGkigzdsg2lrthg", - "cell_type": "code", - "source": [ - "deltaCSM.Aggregate().Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "APgQnfCAvUGZOS1alGD76A", - "cell_type": "markdown", - "source": [ - "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" - ], - "metadata": {} - }, - { - "id": "RtFAIsTtqkKptF872l2QOA", - "cell_type": "code", - "source": [ - "var expectedDeltaCSM_nonFinancial = deltaCSM.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QIAfXjMAUkKl824oTIpkxg", - "cell_type": "code", - "source": [ - "expectedDeltaCSM_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ROYdG5qKq0WskXY9TubsCw", - "cell_type": "code", - "source": [ - "expectedDeltaCSM_nonFinancial.CheckEquality( -computedDeltaCSM_nonFinancial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "B3v_a4ACR0aaHYEIZ5Efmw", - "cell_type": "markdown", - "source": [ - "### Financial" - ], - "metadata": {} - }, - { - "id": "XUhfK022zUq-fhkyjtdiRA", - "cell_type": "markdown", - "source": [ - "Conversely, the computed value for the financial change of the CSM is" - ], - "metadata": {} - }, - { - "id": "ni56W_02FkyqpCsEn8POig", - "cell_type": "code", - "source": [ - "var computedDeltaCSM_Financial = Test.GetScopes(identities).Aggregate()", - "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UBEJvfmS9UOcouMKcyVlSA", - "cell_type": "code", - "source": [ - "computedDeltaCSM_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TqRsmZIHlUqsIwggU5ok1w", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" - ], - "metadata": {} - }, - { - "id": "60OowsZamEOXwPfjqtKINg", - "cell_type": "code", - "source": [ - "var expectedDeltaCSM_Financial = ( deltaCSM.Filter((\"VariableType\", \"IA\")) +", - "\n deltaCSM.Filter((\"VariableType\", \"YCU\")) +", - "\n deltaCSM.Filter((\"VariableType\", \"CRU\")) )", - "\n .Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "d89jwj04Ak-rvKD6GrFThw", - "cell_type": "code", - "source": [ - "expectedDeltaCSM_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HZ5FzlG01U-9aaQvlx_cCQ", - "cell_type": "code", - "source": [ - "expectedDeltaCSM_Financial.CheckEquality( -computedDeltaCSM_Financial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q-EaVofzPkeq9BLkL6Pk2w", - "cell_type": "markdown", - "source": [ - "## Loss Component" - ], - "metadata": {} - }, - { - "id": "LE5bZlbq_UWJBvszrykzuA", - "cell_type": "markdown", - "source": [ - "### Non Financial" - ], - "metadata": {} - }, - { - "id": "lFKLvci1FUOz6Q0a40u2-A", - "cell_type": "markdown", - "source": [ - "The computed value for the non financial change of the LC is" - ], - "metadata": {} - }, - { - "id": "NA8SeqEo5EiJhDQHBuTtjg", - "cell_type": "code", - "source": [ - "var computedDeltaLC_nonFinancial = Test.GetScopes(identities).Aggregate()", - "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yoNwfY6O-EGOYvwfX9CXKw", - "cell_type": "code", - "source": [ - "computedDeltaLC_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wQpKhvuttU2S-2T2XqWz9g", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the full CSM data from which the delta can be computed:" - ], - "metadata": {} - }, - { - "id": "ZnNiktkIsEmVeTAPp4eq0Q", - "cell_type": "code", - "source": [ - "var LC = Test.GetScopes(identities).Aggregate().Lc.Filter((\"GroupOfContract\", dataNode));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XRtrMck4ak-bF1LUNbR-bw", - "cell_type": "code", - "source": [ - "var deltaLC = LC.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n LC.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rUaX0OrwkUuo2_xNMVz34g", - "cell_type": "code", - "source": [ - "deltaLC.Aggregate().Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Xv4auAOkAE6oXxsy4JGUBw", - "cell_type": "markdown", - "source": [ - "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" - ], - "metadata": {} - }, - { - "id": "c95lLlyhYU2YCY4HE8ZVIg", - "cell_type": "code", - "source": [ - "var expectedDeltaLC_nonFinancial = deltaLC.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qmlrXNV4n0iOMmSFHVe7wA", - "cell_type": "code", - "source": [ - "expectedDeltaLC_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "k_hU6dAGrEmzN3vI30De0A", - "cell_type": "code", - "source": [ - "expectedDeltaLC_nonFinancial.CheckEquality( -computedDeltaLC_nonFinancial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q0Cm5RmXxUa4oQVQ1fuHjw", - "cell_type": "markdown", - "source": [ - "### Financial" - ], - "metadata": {} - }, - { - "id": "cAJ4Q4Rx60aaCC-Nt-gdpQ", - "cell_type": "markdown", - "source": [ - "Conversely, the computed value for the financial change of the LC is" - ], - "metadata": {} - }, - { - "id": "MtdwhbqZiU-TOLVfW0DFDg", - "cell_type": "code", - "source": [ - "var computedDeltaLC_Financial = Test.GetScopes(identities).Aggregate()", - "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cWArdm8iMESr118b9tDMkQ", - "cell_type": "code", - "source": [ - "computedDeltaLC_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "q2pAhq-A_0aROq8zEDtVCA", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" - ], - "metadata": {} - }, - { - "id": "fxZPPdSMCkG-mV0CjyLK4g", - "cell_type": "code", - "source": [ - "var expectedDeltaLC_Financial = ( deltaLC.Filter((\"VariableType\", \"IA\")) +", - "\n deltaLC.Filter((\"VariableType\", \"YCU\")) +", - "\n deltaLC.Filter((\"VariableType\", \"CRU\")) )", - "\n .Aggregate().Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WYqhArIhB0aUgSAq2pl4Ag", - "cell_type": "code", - "source": [ - "expectedDeltaLC_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IzddiJL3oUewH76M1wgr1w", - "cell_type": "code", - "source": [ - "expectedDeltaLC_Financial.CheckEquality( -computedDeltaLC_Financial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ktY-cyI15E-U1ahdw6cDuA", - "cell_type": "markdown", - "source": [ - "## Loss Recovery Component" - ], - "metadata": {} - }, - { - "id": "Jj5QAJYtR0mPDZsLbwt82w", - "cell_type": "markdown", - "source": [ - "### Non Financial" - ], - "metadata": {} - }, - { - "id": "MNr136KdUEWkl6QE99H-tQ", - "cell_type": "markdown", - "source": [ - "If the [target Group of Contract](#report) is not of type Re-Insurance, the result of the following will return null.", - "\n", - "\nThe computed value for the non financial change of the LoReCo is" - ], - "metadata": {} - }, - { - "id": "vheo4pqpoUC636g-YZNg7w", - "cell_type": "code", - "source": [ - "var computedDeltaLORECO_nonFinancial = Test.GetScopes(identities).Aggregate()", - "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gcye9gWqLUSp2DBeuZK5JA", - "cell_type": "code", - "source": [ - "computedDeltaLORECO_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1h9DSjP030GvgF_-V2wXEQ", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the full LoReCo data from which the delta can be computed:" - ], - "metadata": {} - }, - { - "id": "toras9Yo70eeiatIr1j9fw", - "cell_type": "code", - "source": [ - "var LORECO = Test.GetScopes(identities).Aggregate().Loreco.Filter((\"GroupOfContract\", dataNode));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uT9D_Ku9WkS7lCo1nrxs0Q", - "cell_type": "code", - "source": [ - "var deltaLORECO = LORECO.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", - "\n LORECO.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Qhxfbqq4OEaXyYoe5rfTUg", - "cell_type": "code", - "source": [ - "deltaLORECO.Aggregate()?.Value?? 0" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_uTlE0FJFEOI34sBONg8Mw", - "cell_type": "markdown", - "source": [ - "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" - ], - "metadata": {} - }, - { - "id": "qmBrKRZP8U-13Lup_I2e5Q", - "cell_type": "code", - "source": [ - "var expectedDeltaLORECO_nonFinancial = deltaLORECO.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tMMjF_m4D0aRpukRYlpdLA", - "cell_type": "code", - "source": [ - "expectedDeltaLORECO_nonFinancial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "in3E9cuYDEymJ4n3r_iWPA", - "cell_type": "code", - "source": [ - "expectedDeltaLORECO_nonFinancial.CheckEquality( -computedDeltaLORECO_nonFinancial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OaAYtHkPf0CohNZ6dPoGGA", - "cell_type": "markdown", - "source": [ - "### Financial" - ], - "metadata": {} - }, - { - "id": "gHC-7-HgtEWWHf6ZCY6dDQ", - "cell_type": "markdown", - "source": [ - "Conversely, the computed value for the financial change of the LoReCo is" - ], - "metadata": {} - }, - { - "id": "Y9twZB0o6ESo6PY18cZj9g", - "cell_type": "code", - "source": [ - "var computedDeltaLORECO_Financial = Test.GetScopes(identities).Aggregate()", - "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3wLUoygmE0CXCU5UFkL41Q", - "cell_type": "code", - "source": [ - "computedDeltaLORECO_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "j5qJfGmdMkGwoFc1yb_X3Q", - "cell_type": "markdown", - "source": [ - "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" - ], - "metadata": {} - }, - { - "id": "3UGSj5-MYUSI-mW2tMJXVg", - "cell_type": "code", - "source": [ - "var expectedDeltaLORECO_Financial = ( deltaLORECO.Filter((\"VariableType\", \"IA\")) +", - "\n deltaLORECO.Filter((\"VariableType\", \"YCU\")) +", - "\n deltaLORECO.Filter((\"VariableType\", \"CRU\")) )", - "\n .Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_Yk_rP1ZHEqRB6g3yMCUMg", - "cell_type": "code", - "source": [ - "expectedDeltaLORECO_Financial" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dDZLX-mHFEyX5X2GNKLW7Q", - "cell_type": "code", - "source": [ - "expectedDeltaLORECO_Financial.CheckEquality( -computedDeltaLORECO_Financial ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "S8TFuLo4eUeNTC-d5f9GjA", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Reconciliation" - ], - "metadata": {} - }, - { - "id": "GEzn2LZBRkSr7oqQsmzPDA", - "cell_type": "markdown", - "source": [ - "Based on the results calculated in Section 3, we check here the consistency of the [Financial Performance Report](#report). ", - "\n", - "\nFiner granular reconciliations can be performed by following the datails of how each report contributes to the Financial Performance Report. Please, refer to the [Report documentation](../Report/ReportScopes#financial-performance) for all the details. " - ], - "metadata": {} - }, - { - "id": "a6N6B4TD8kuk12aZT40KVg", - "cell_type": "markdown", - "source": [ - "## Insurance Revenue" - ], - "metadata": {} - }, - { - "id": "6MZPkbR47EmeDYqsSV4urQ", - "cell_type": "markdown", - "source": [ - "The Insurance Revenue (IR) contributions vary from Insurance to Re-Insurance and depend on the Liability Type of the [target Group of Contract](#report). This can be summarized by the formulas below", - "\n", - "\n$$", - "\n\\text{IR} = \\left\\{ ", - "\n\\begin{array}{ll}", - "\n\\Delta\\text{FCF Gross Non Financial} + \\Delta\\text{CSM Non Financial} + \\Delta\\text{CSM Release} \\\\", - "\n+ \\text{Incurred Incoming Cashflows} + \\text{Claims ICO} + \\text{Incurred Deferrals} \\\\", - "\n+ \\text{Exc. Experience Adjustment on Premiums} ~~,", - "\n& \\text{for LRC Insurance contracts} \\\\[0.2cm]", - "\n\\Delta\\text{CSM Non Financial} + \\Delta\\text{CSM Release} \\\\", - "\n+ \\text{Incurred Incoming Cashflows} + \\text{Claims ICO} + \\text{Incurred Deferrals} ~~,", - "\n& \\text{for LIC Insurance contracts} \\\\[0.2cm]", - "\n\\text{Claims ICO} + \\text{Incurred Deferrals} ~~,", - "\n& \\text{for Re-Insurance contracts}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nHere below we recompute the IR term:" - ], - "metadata": {} - }, - { - "id": "dFWCtF0eBkqXubXgarv3IA", - "cell_type": "code", - "source": [ - "var expectedDeltaCSM_release = deltaCSM.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cnXGdn9kHkaAPsUUjaffrg", - "cell_type": "code", - "source": [ - "var expectedIncurredIncomingCashflows = Test.GetScopes(identities).Aggregate().Premiums", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "d5AwPz1_ZUiGBL5xhIKZ4g", - "cell_type": "code", - "source": [ - "var expectedIncurredDeferralsIr = Test.GetScopes(identities).Aggregate().AmortizationToIr", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YsUQO-5qx0mI-Ze0xAxR2g", - "cell_type": "code", - "source": [ - "var expectedClaimsICO = Test.GetScopes(identities).Aggregate().ClaimsIcoToIr", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uEta4W7kvEGPG1QyEoMh7w", - "cell_type": "code", - "source": [ - "var expectedExcExperienceAdjPremiums = Test.GetScopes(identities).Aggregate().ExperienceAdjustmentOnPremium", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zOT5DeoAmUCB4VCKdUJ2lw", - "cell_type": "code", - "source": [ - "double IR = 0;", - "\nif(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LRC\")", - "\n IR = - expectedDeltaFCF_nonFinancial ", - "\n - expectedDeltaCSM_nonFinancial ", - "\n - expectedDeltaCSM_release ", - "\n + expectedIncurredIncomingCashflows", - "\n + expectedClaimsICO", - "\n + expectedIncurredDeferralsIr", - "\n + expectedExcExperienceAdjPremiums;", - "\nelse if(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LIC\")", - "\n IR = - expectedDeltaCSM_nonFinancial", - "\n - expectedDeltaCSM_release", - "\n + expectedIncurredIncomingCashflows", - "\n + expectedClaimsICO", - "\n + expectedIncurredDeferralsIr ", - "\n + expectedExcExperienceAdjPremiums;", - "\nelse if(groupOfContract.Partner != null)", - "\n IR = + expectedClaimsICO", - "\n + expectedIncurredDeferralsIr", - "\n + expectedExcExperienceAdjPremiums;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gPU-YBlmbU-CuZWTrFnM-Q", - "cell_type": "code", - "source": [ - "IR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yE-6MD2uiE6ttfKjHLsQlg", - "cell_type": "markdown", - "source": [ - "## Insurance Service Expenses" - ], - "metadata": {} - }, - { - "id": "Obp_9f3AZkCH8Lap4aYmFg", - "cell_type": "markdown", - "source": [ - "Analogously, the Insurance Service Expenses (ISE) read", - "\n", - "\n$$", - "\n\\text{ISE} = \\left\\{ ", - "\n\\begin{array}{ll}", - "\n\\Delta\\text{LC Non Financial}", - "\n+ \\Delta\\text{LC Release}", - "\n+ \\text{Incurred ClaimsNIC} \\\\", - "\n+ \\text{Incurred Expenses}", - "\n+ \\text{Incurred Commissions}", - "\n+ \\text{Incurred Deferrals}", - "\n& \\text{for LRC Insurance contracts} \\\\[0.2cm]", - "\n\\Delta\\text{FCF Reinsurance Non Financial}", - "\n+ \\Delta\\text{LC Non Financial}", - "\n+ \\Delta\\text{LC Release}", - "\n+ \\text{Incurred ClaimsNIC} \\\\", - "\n+ \\text{Incurred Expenses} ", - "\n+ \\text{Incurred Commissions}", - "\n+ \\text{Incurred Deferrals}", - "\n& \\text{for LIC Insurance contracts} \\\\[0.2cm]", - "\n\\Delta\\text{FCF Reinsurance Non Financial} ", - "\n+ \\Delta\\text{CSM Non Financial} ", - "\n+ \\Delta\\text{CSM Release} \\\\", - "\n+ \\Delta\\text{LC Non Financial} ", - "\n+ \\Delta\\text{LC Release} ", - "\n+ \\Delta\\text{LoReCo Non Financial} \\\\", - "\n+ \\text{Incurred Incoming Cashflows} ", - "\n+ \\text{Incurred ClaimsNIC} ", - "\n+ \\text{Incurred Expenses} \\\\", - "\n+ \\text{Incurred Commissions}", - "\n+ \\text{Incurred Deferrals}", - "\n& \\text{for Re-Insurance contracts}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nHere below we recompute the ISE term:" - ], - "metadata": {} - }, - { - "id": "JL2Q7lsrlEucGEc4EjA_oA", - "cell_type": "code", - "source": [ - "var expectedDeltaLC_release = deltaLC.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "O9r-rlZ5hky9sOj-zExurg", - "cell_type": "code", - "source": [ - "var expectedDeltaLoReCo_release = deltaLORECO.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bL0MmHokbUmpt_-xEliEwg", - "cell_type": "code", - "source": [ - "var expectedIncurredClaimsNIC = Test.GetScopes(identities).Aggregate().ClaimsNic", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pV3DTg_19k2Hvp6dPqucww", - "cell_type": "code", - "source": [ - "var expectedIncurredExpenses = Test.GetScopes(identities).Aggregate().Expenses", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KKkpsRFmHUiTPE7WDhV5LQ", - "cell_type": "code", - "source": [ - "var expectedIncurredCommissions = Test.GetScopes(identities).Aggregate().Commissions", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZoXGr9AuiUiZ9G1X4jUa8Q", - "cell_type": "code", - "source": [ - "var expectedIncurredClaimsICO = Test.GetScopes(identities).Aggregate().ClaimsIcoToIse", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "80_7zlUU90-JspeAvDJ9lQ", - "cell_type": "code", - "source": [ - "var expectedIncurredDeferralsIse = Test.GetScopes(identities).Aggregate().AmortizationToIse", - "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Cekx0MB6YkyVgxkvslykvQ", - "cell_type": "code", - "source": [ - "double ISE = 0;", - "\nif(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LRC\")", - "\n ISE = - expectedDeltaLC_nonFinancial ", - "\n - expectedDeltaLC_release", - "\n + expectedIncurredClaimsNIC ", - "\n + expectedIncurredExpenses ", - "\n + expectedIncurredClaimsICO", - "\n + expectedIncurredCommissions", - "\n + expectedIncurredDeferralsIse;", - "\nelse if(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LIC\")", - "\n ISE = - expectedDeltaFCF_nonFinancial", - "\n - expectedDeltaLC_nonFinancial ", - "\n - expectedDeltaLC_release", - "\n + expectedIncurredClaimsNIC ", - "\n + expectedIncurredExpenses ", - "\n + expectedIncurredClaimsICO", - "\n + expectedIncurredCommissions", - "\n + expectedIncurredDeferralsIse;", - "\nelse if(groupOfContract.Partner != null)", - "\n ISE = - expectedDeltaFCF_nonFinancial", - "\n - expectedDeltaCSM_nonFinancial", - "\n - expectedDeltaCSM_release", - "\n - expectedDeltaLC_nonFinancial ", - "\n - expectedDeltaLC_release", - "\n - expectedDeltaLoReCo_release", - "\n + expectedIncurredIncomingCashflows", - "\n + expectedIncurredClaimsNIC ", - "\n + expectedIncurredExpenses ", - "\n + expectedIncurredClaimsICO", - "\n + expectedIncurredCommissions", - "\n + expectedIncurredDeferralsIse;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "081ToSk3WESb6183HlFQlA", - "cell_type": "code", - "source": [ - "ISE" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "83VrYmGYX0uHykId27aWOQ", - "cell_type": "markdown", - "source": [ - "## Insurance Finance Income/Expenses" - ], - "metadata": {} - }, - { - "id": "NAkWvaF6NUG6tYDPqEbVNA", - "cell_type": "markdown", - "source": [ - "The Financial part associated to the Insurance business encompassing both the Income and Expenses is denoted IFIE from the initials marked in capital letters. The ", - "\n", - "\n$$", - "\n\\text{IFIE} = \\left\\{", - "\n\\begin{array}{ll}", - "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ~~,", - "\n& \\text{for Insurance contracts} \\\\[0.2cm]", - "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ", - "\n+ \\Delta\\text{LoReCo Financial} ~~, ", - "\n& \\text{for Re-Insurance contracts}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nHere below we recompute the IFIE term:" - ], - "metadata": {} - }, - { - "id": "JkwONyKiakC4XpVgxusdRg", - "cell_type": "code", - "source": [ - "double IFIE = 0;", - "\nif(groupOfContract.Partner == null) ", - "\n IFIE = - expectedDeltaFCF_Financial ", - "\n - expectedDeltaCSM_Financial", - "\n - expectedDeltaLC_Financial;", - "\nelse", - "\n IFIE = - expectedDeltaFCF_Financial ", - "\n - expectedDeltaCSM_Financial", - "\n - expectedDeltaLC_Financial", - "\n - expectedDeltaLORECO_Financial;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "grefaMt7BEaTJ7dsa0AUQA", - "cell_type": "code", - "source": [ - "IFIE" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6_E3dWyyF0COz4xLh1e-xA", - "cell_type": "markdown", - "source": [ - "## Other Comprehensive Income" - ], - "metadata": {} - }, - { - "id": "jK3nTYcm30KoVUioi71r4g", - "cell_type": "markdown", - "source": [ - "The Other Comprehensive Income (OCI) can be non-zero only when the OCI is enabled for [target Group of Contract](#report), that is, Oci Type = Default.", - "\n", - "\n$$", - "\n\\text{OCI} = \\Delta\\text{FCF} \\big|_{\\text{Locked-in}} - \\Delta\\text{FCF} \\big|_{\\text{Current}} ~~.", - "\n$$", - "\n", - "\nHere below we recompute the OCI term:" - ], - "metadata": {} - }, - { - "id": "j2wpd2OAuUmjvKWQoew9jQ", - "cell_type": "code", - "source": [ - "var OCI = expectedDeltaFCF_OCI;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7R8qKIIsGU6fcW8M2M2M5g", - "cell_type": "code", - "source": [ - "OCI" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_BPpLy2cnUKTaE-9tgr-UQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Financial Performance Specifications

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the Financial Performance reporting system. The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the following the Dimensions, Parameters, Nominal Cashflows, and Actuals are imported from the corresponding csv files in Initialization/Systemorph/" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Process Data" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period, Reporting Node and Currency Type" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" + ] + }, + { + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "and the type of Currency among Contractual, Functional, and Group" + ] + }, + { + "cell_type": "code", + "source": [ + "var currencyType = CurrencyType.Contractual ;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Import the Report definitions, initialize the Workspace and the Test Suite:" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Report/ReportScopes\"", + "\n#!import \"../Report/ReportConfigurationAndUtils\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "code", + "source": [ + "var period = (year, month) ;", + "\nvar reportStorage = new ReportStorage(Workspace, Report) ;", + "\nvar Test = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" + ] + }, + { + "cell_type": "code", + "source": [ + "await reportStorage.InitializeReportIndependentCacheAsync();", + "\nawait reportStorage.InitializeAsync(period, reportingNode, null, currencyType);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## View list of Identities" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Based on the Cashflows imported, the list of all possible identities, i.e. combinations of valid Contractual and Functional Currencies, Liability Types, (Re)Insurance and Oci, is contructed and reported here below:" + ] + }, + { + "cell_type": "code", + "source": [ + "var identities = reportStorage.GetIdentities(period, reportingNode, null, currencyType);" + ] + }, + { + "cell_type": "code", + "source": [ + "identities" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Report" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Please select here below the target Data Node for executing the tests below:" + ] + }, + { + "cell_type": "code", + "source": [ + "var dataNode = \"DT1.1\";" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Group of Contract selected is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var groupOfContract = (await Workspace.Query().Where(x => x.SystemName == dataNode).ToArrayAsync()).FirstOrDefault();", + "\ngroupOfContract" + ] + }, + { + "cell_type": "markdown", + "source": [ + "where ", + "\n- the **OciType** can be Default for contracts with non-zero OCI, and null otherwise, ", + "\n- the **Liability Type** can be LRC for Liability for Remaining Coverage, and LIC for Liability of Incurred Claims,", + "\n- the **Partner** can be null for Insurance contracts, or equal to the Partner System Name for Reinsurance contracts." + ] + }, + { + "cell_type": "markdown", + "source": [ + "The summary of the Financial Performance report is shown below" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube( Test.GetScopes(identities).Aggregate().FinancialPerformance.Filter((\"GroupOfContract\", dataNode)) )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(currencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", + "\n .ToReport() with { Height = 600 }" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Inspection" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Fulfillment Cashflows" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Fulfillment Cashflow (FCF) corresponds to the sum of the Best Estimate [Present Value](../Import/ImportScopeCalculation#current-and-locked) (PV) and the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) (RA), both summed over Amounty Types, and both discounted with the Locked-In curve in the BBA valuation approach:", + "\n", + "\n$$", + "\n\\text{FCF}(\\text{AoC}) = \\text{PV Locked}(\\text{AoC})", + "\n\\bigg|_{\\substack{\\text{Non Attributable} \\\\ \\text{Amount Types} \\\\ \\text{excluded}}} ", + "\n+ \\text{RA Locked}(\\text{AoC}) ~.", + "\n$$" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Non Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the non financial contribution to the FCF is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaFCF_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .FpNonFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaFCF_nonFinancial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full list of FCFs" + ] + }, + { + "cell_type": "code", + "source": [ + "var FCFs = Test.GetScopes(identities).Aggregate().Fcf.Filter((\"GroupOfContract\", dataNode));" + ] + }, + { + "cell_type": "code", + "source": [ + "var deltaFCF = FCFs.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n FCFs.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ] + }, + { + "cell_type": "code", + "source": [ + "deltaFCF.Aggregate().Value" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_nonFinancial = deltaFCF.Filter((\"VariableType\", \"!IA\"), ", + "\n (\"VariableType\", \"!YCU\"), ", + "\n (\"VariableType\", \"!CRU\") ).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_nonFinancial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For consistency, this term is taken with the minus sign" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_nonFinancial.CheckEquality( -computedDeltaFCF_nonFinancial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial contribution to the Fulfillment Cashflows (FCF) is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaFCF_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FpFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaFCF_Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The independent recalculation of this value reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_Financial = (deltaFCF.Filter((\"VariableType\", \"IA\")) +", + "\n deltaFCF.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaFCF.Filter((\"VariableType\", \"CRU\")) ).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "taking the minus sign into account" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_Financial.CheckEquality( -computedDeltaFCF_Financial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Other Comprehensive Income" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Other Comprehensive Income (OCI) term is by definition the sum of the financial contributions not related to the insurance sector.", + "\n", + "\nThe Default method to compute the OCI term is by subtracting the FCF computed with the *Locked-In* rates and the FCF computed with the *Current* rates. In this way the non insurance financial volatiliy of the economic input is relegated to the OCI. " + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaFCF_OCI = Test.GetScopes(identities).Aggregate()", + "\n .OciFinancial.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaFCF_OCI" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The OCI contribution is zero when the OCI option is disabled for the [target Group of Contract](#report).", + "\n", + "\nHere below we follow the steps to calculate independently the OCI contribution " + ] + }, + { + "cell_type": "code", + "source": [ + "var DeltaFCF_Locked = deltaFCF.Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "var FCFs_current = Test.GetScopes(identities).Aggregate().CurrentFcf.Filter((\"GroupOfContract\", dataNode));" + ] + }, + { + "cell_type": "code", + "source": [ + "var DeltaFCF_Current = FCFs_current.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n FCFs_current.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_OCI = DeltaFCF_Locked - DeltaFCF_Current.Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "DeltaFCF_Locked" + ] + }, + { + "cell_type": "code", + "source": [ + "DeltaFCF_Current.Aggregate().Value" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_OCI" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_OCI.CheckEquality( computedDeltaFCF_OCI ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Contractual Service Margin" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Non Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the non financial change of the CSM is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaCSM_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaCSM_nonFinancial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full CSM data from which the delta can be computed:" + ] + }, + { + "cell_type": "code", + "source": [ + "var CSM = Test.GetScopes(identities).Aggregate().Csm.Filter((\"GroupOfContract\", dataNode));" + ] + }, + { + "cell_type": "code", + "source": [ + "var deltaCSM = CSM.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n CSM.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ] + }, + { + "cell_type": "code", + "source": [ + "deltaCSM.Aggregate().Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_nonFinancial = deltaCSM.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaCSM_nonFinancial" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaCSM_nonFinancial.CheckEquality( -computedDeltaCSM_nonFinancial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial change of the CSM is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaCSM_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaCSM_Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_Financial = ( deltaCSM.Filter((\"VariableType\", \"IA\")) +", + "\n deltaCSM.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaCSM.Filter((\"VariableType\", \"CRU\")) )", + "\n .Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaCSM_Financial" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaCSM_Financial.CheckEquality( -computedDeltaCSM_Financial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Loss Component" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Non Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the non financial change of the LC is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaLC_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaLC_nonFinancial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full CSM data from which the delta can be computed:" + ] + }, + { + "cell_type": "code", + "source": [ + "var LC = Test.GetScopes(identities).Aggregate().Lc.Filter((\"GroupOfContract\", dataNode));" + ] + }, + { + "cell_type": "code", + "source": [ + "var deltaLC = LC.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n LC.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ] + }, + { + "cell_type": "code", + "source": [ + "deltaLC.Aggregate().Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLC_nonFinancial = deltaLC.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLC_nonFinancial" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLC_nonFinancial.CheckEquality( -computedDeltaLC_nonFinancial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial change of the LC is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaLC_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaLC_Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLC_Financial = ( deltaLC.Filter((\"VariableType\", \"IA\")) +", + "\n deltaLC.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaLC.Filter((\"VariableType\", \"CRU\")) )", + "\n .Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLC_Financial" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLC_Financial.CheckEquality( -computedDeltaLC_Financial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Loss Recovery Component" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Non Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "If the [target Group of Contract](#report) is not of type Re-Insurance, the result of the following will return null.", + "\n", + "\nThe computed value for the non financial change of the LoReCo is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaLORECO_nonFinancial = Test.GetScopes(identities).Aggregate()", + "\n .NonFinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaLORECO_nonFinancial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the full LoReCo data from which the delta can be computed:" + ] + }, + { + "cell_type": "code", + "source": [ + "var LORECO = Test.GetScopes(identities).Aggregate().Loreco.Filter((\"GroupOfContract\", dataNode));" + ] + }, + { + "cell_type": "code", + "source": [ + "var deltaLORECO = LORECO.Filter((\"VariableType\", \"!BOP\"),(\"VariableType\", \"!EOP\")) +", + "\n LORECO.Filter((\"VariableType\", AocTypes.BOP),(\"Novelty\", Novelties.N));" + ] + }, + { + "cell_type": "code", + "source": [ + "deltaLORECO.Aggregate()?.Value?? 0" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLORECO_nonFinancial = deltaLORECO.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_nonFinancial" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_nonFinancial.CheckEquality( -computedDeltaLORECO_nonFinancial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Conversely, the computed value for the financial change of the LoReCo is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaLORECO_Financial = Test.GetScopes(identities).Aggregate()", + "\n .FinancialChanges.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaLORECO_Financial" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLORECO_Financial = ( deltaLORECO.Filter((\"VariableType\", \"IA\")) +", + "\n deltaLORECO.Filter((\"VariableType\", \"YCU\")) +", + "\n deltaLORECO.Filter((\"VariableType\", \"CRU\")) )", + "\n .Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_Financial" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_Financial.CheckEquality( -computedDeltaLORECO_Financial ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Reconciliation" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Based on the results calculated in Section 3, we check here the consistency of the [Financial Performance Report](#report). ", + "\n", + "\nFiner granular reconciliations can be performed by following the datails of how each report contributes to the Financial Performance Report. Please, refer to the [Report documentation](../Report/ReportScopes#financial-performance) for all the details. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Insurance Revenue" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Insurance Revenue (IR) contributions vary from Insurance to Re-Insurance and depend on the Liability Type of the [target Group of Contract](#report). This can be summarized by the formulas below", + "\n", + "\n$$", + "\n\\text{IR} = \\left\\{ ", + "\n\\begin{array}{ll}", + "\n\\Delta\\text{FCF Gross Non Financial} + \\Delta\\text{CSM Non Financial} + \\Delta\\text{CSM Release} \\\\", + "\n+ \\text{Incurred Incoming Cashflows} + \\text{Claims ICO} + \\text{Incurred Deferrals} \\\\", + "\n+ \\text{Exc. Experience Adjustment on Premiums} ~~,", + "\n& \\text{for LRC Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{CSM Non Financial} + \\Delta\\text{CSM Release} \\\\", + "\n+ \\text{Incurred Incoming Cashflows} + \\text{Claims ICO} + \\text{Incurred Deferrals} ~~,", + "\n& \\text{for LIC Insurance contracts} \\\\[0.2cm]", + "\n\\text{Claims ICO} + \\text{Incurred Deferrals} ~~,", + "\n& \\text{for Re-Insurance contracts}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nHere below we recompute the IR term:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_release = deltaCSM.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredIncomingCashflows = Test.GetScopes(identities).Aggregate().Premiums", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredDeferralsIr = Test.GetScopes(identities).Aggregate().AmortizationToIr", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedClaimsICO = Test.GetScopes(identities).Aggregate().ClaimsIcoToIr", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedExcExperienceAdjPremiums = Test.GetScopes(identities).Aggregate().ExperienceAdjustmentOnPremium", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "double IR = 0;", + "\nif(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LRC\")", + "\n IR = - expectedDeltaFCF_nonFinancial ", + "\n - expectedDeltaCSM_nonFinancial ", + "\n - expectedDeltaCSM_release ", + "\n + expectedIncurredIncomingCashflows", + "\n + expectedClaimsICO", + "\n + expectedIncurredDeferralsIr", + "\n + expectedExcExperienceAdjPremiums;", + "\nelse if(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LIC\")", + "\n IR = - expectedDeltaCSM_nonFinancial", + "\n - expectedDeltaCSM_release", + "\n + expectedIncurredIncomingCashflows", + "\n + expectedClaimsICO", + "\n + expectedIncurredDeferralsIr ", + "\n + expectedExcExperienceAdjPremiums;", + "\nelse if(groupOfContract.Partner != null)", + "\n IR = + expectedClaimsICO", + "\n + expectedIncurredDeferralsIr", + "\n + expectedExcExperienceAdjPremiums;" + ] + }, + { + "cell_type": "code", + "source": [ + "IR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Insurance Service Expenses" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Analogously, the Insurance Service Expenses (ISE) read", + "\n", + "\n$$", + "\n\\text{ISE} = \\left\\{ ", + "\n\\begin{array}{ll}", + "\n\\Delta\\text{LC Non Financial}", + "\n+ \\Delta\\text{LC Release}", + "\n+ \\text{Incurred ClaimsNIC} \\\\", + "\n+ \\text{Incurred Expenses}", + "\n+ \\text{Incurred Commissions}", + "\n+ \\text{Incurred Deferrals}", + "\n& \\text{for LRC Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{FCF Reinsurance Non Financial}", + "\n+ \\Delta\\text{LC Non Financial}", + "\n+ \\Delta\\text{LC Release}", + "\n+ \\text{Incurred ClaimsNIC} \\\\", + "\n+ \\text{Incurred Expenses} ", + "\n+ \\text{Incurred Commissions}", + "\n+ \\text{Incurred Deferrals}", + "\n& \\text{for LIC Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{FCF Reinsurance Non Financial} ", + "\n+ \\Delta\\text{CSM Non Financial} ", + "\n+ \\Delta\\text{CSM Release} \\\\", + "\n+ \\Delta\\text{LC Non Financial} ", + "\n+ \\Delta\\text{LC Release} ", + "\n+ \\Delta\\text{LoReCo Non Financial} \\\\", + "\n+ \\text{Incurred Incoming Cashflows} ", + "\n+ \\text{Incurred ClaimsNIC} ", + "\n+ \\text{Incurred Expenses} \\\\", + "\n+ \\text{Incurred Commissions}", + "\n+ \\text{Incurred Deferrals}", + "\n& \\text{for Re-Insurance contracts}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nHere below we recompute the ISE term:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLC_release = deltaLC.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLoReCo_release = deltaLORECO.Filter((\"VariableType\", \"AM\")).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredClaimsNIC = Test.GetScopes(identities).Aggregate().ClaimsNic", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredExpenses = Test.GetScopes(identities).Aggregate().Expenses", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredCommissions = Test.GetScopes(identities).Aggregate().Commissions", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredClaimsICO = Test.GetScopes(identities).Aggregate().ClaimsIcoToIse", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedIncurredDeferralsIse = Test.GetScopes(identities).Aggregate().AmortizationToIse", + "\n .Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "double ISE = 0;", + "\nif(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LRC\")", + "\n ISE = - expectedDeltaLC_nonFinancial ", + "\n - expectedDeltaLC_release", + "\n + expectedIncurredClaimsNIC ", + "\n + expectedIncurredExpenses ", + "\n + expectedIncurredClaimsICO", + "\n + expectedIncurredCommissions", + "\n + expectedIncurredDeferralsIse;", + "\nelse if(groupOfContract.Partner == null && groupOfContract.LiabilityType == \"LIC\")", + "\n ISE = - expectedDeltaFCF_nonFinancial", + "\n - expectedDeltaLC_nonFinancial ", + "\n - expectedDeltaLC_release", + "\n + expectedIncurredClaimsNIC ", + "\n + expectedIncurredExpenses ", + "\n + expectedIncurredClaimsICO", + "\n + expectedIncurredCommissions", + "\n + expectedIncurredDeferralsIse;", + "\nelse if(groupOfContract.Partner != null)", + "\n ISE = - expectedDeltaFCF_nonFinancial", + "\n - expectedDeltaCSM_nonFinancial", + "\n - expectedDeltaCSM_release", + "\n - expectedDeltaLC_nonFinancial ", + "\n - expectedDeltaLC_release", + "\n - expectedDeltaLoReCo_release", + "\n + expectedIncurredIncomingCashflows", + "\n + expectedIncurredClaimsNIC ", + "\n + expectedIncurredExpenses ", + "\n + expectedIncurredClaimsICO", + "\n + expectedIncurredCommissions", + "\n + expectedIncurredDeferralsIse;" + ] + }, + { + "cell_type": "code", + "source": [ + "ISE" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Insurance Finance Income/Expenses" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Financial part associated to the Insurance business encompassing both the Income and Expenses is denoted IFIE from the initials marked in capital letters. The ", + "\n", + "\n$$", + "\n\\text{IFIE} = \\left\\{", + "\n\\begin{array}{ll}", + "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ~~,", + "\n& \\text{for Insurance contracts} \\\\[0.2cm]", + "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ", + "\n+ \\Delta\\text{LoReCo Financial} ~~, ", + "\n& \\text{for Re-Insurance contracts}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nHere below we recompute the IFIE term:" + ] + }, + { + "cell_type": "code", + "source": [ + "double IFIE = 0;", + "\nif(groupOfContract.Partner == null) ", + "\n IFIE = - expectedDeltaFCF_Financial ", + "\n - expectedDeltaCSM_Financial", + "\n - expectedDeltaLC_Financial;", + "\nelse", + "\n IFIE = - expectedDeltaFCF_Financial ", + "\n - expectedDeltaCSM_Financial", + "\n - expectedDeltaLC_Financial", + "\n - expectedDeltaLORECO_Financial;" + ] + }, + { + "cell_type": "code", + "source": [ + "IFIE" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Other Comprehensive Income" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Other Comprehensive Income (OCI) can be non-zero only when the OCI is enabled for [target Group of Contract](#report), that is, Oci Type = Default.", + "\n", + "\n$$", + "\n\\text{OCI} = \\Delta\\text{FCF} \\big|_{\\text{Locked-in}} - \\Delta\\text{FCF} \\big|_{\\text{Current}} ~~.", + "\n$$", + "\n", + "\nHere below we recompute the OCI term:" + ] + }, + { + "cell_type": "code", + "source": [ + "var OCI = expectedDeltaFCF_OCI;" + ] + }, + { + "cell_type": "code", + "source": [ + "OCI" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/SpecificationsImportActuals.ipynb b/Test/SpecificationsImportActuals.ipynb index b803db6b..cb0b1acb 100644 --- a/Test/SpecificationsImportActuals.ipynb +++ b/Test/SpecificationsImportActuals.ipynb @@ -1,705 +1,501 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "1O9abtyGKUeDiX_VyaeaAQ", - "cell_type": "markdown", - "source": [ - "

Import Actuals Specifications

" - ], - "metadata": {} - }, - { - "id": "mgxNtYdjh027T2LccTaWsA", - "cell_type": "markdown", - "source": [ - "The aim of this notebook is to document the calculations taking place when importing the Actuals. For this documentation notebook the Data is imported from the corresponding csv files located in the following path Initialization/Systemorph/. The process is pictorially explained in the following flowchart. ", - "\n", - "\n", - "\n
", - "\n", - "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." - ], - "metadata": {} - }, - { - "id": "9sXMifQXi0yuys7dMnvmmA", - "cell_type": "markdown", - "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" - ], - "metadata": {} - }, - { - "id": "TYI7B_9JxEm9gBQSiHP7Tw", - "cell_type": "code", - "source": [ - "#!import \"SpecificationsSetup\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sQZ9EDWrRUCqjDaDiUaslg", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "9VuASxTZcE64BWvOvV6Y0A", - "cell_type": "markdown", - "source": [ - "# Import Data" - ], - "metadata": {} - }, - { - "id": "cb5PqhqcY0eWhhsN18hk8Q", - "cell_type": "markdown", - "source": [ - "", - "\n## Current Period" - ], - "metadata": {} - }, - { - "id": "AYwuUnm7D0OvGFWfuLCS0g", - "cell_type": "markdown", - "source": [ - "Please select the target period (i.e. year and month), Reporting Node, Economic Basis, and Data Node based on the imported data:" - ], - "metadata": {} - }, - { - "id": "e0LWvI9K1U-qRdDpHJWU3Q", - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"L\" ;", - "\nvar dataNode = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MfXiwU7pSkeiWLcmqQJytA", - "cell_type": "markdown", - "source": [ - "Import the Dimensions, Yield Curves and Nominal Cashflows from the corresponding csv files in Initialization/Systemorph/" - ], - "metadata": {} - }, - { - "id": "VckQZIZagUGxLJK_kIkJzA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Epv9604EmEmVeKtkGt_iqA", - "cell_type": "markdown", - "source": [ - "Initialization of the Test Suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" - ], - "metadata": {} - }, - { - "id": "UWRWl2pRz0eA8IvYfBeXbQ", - "cell_type": "code", - "source": [ - "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Actual);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Ball02llF0KmddCeo9vhsw", - "cell_type": "markdown", - "source": [ - "", - "\n## View imported Actuals" - ], - "metadata": {} - }, - { - "id": "XiBDlMNVEk-oEido9aLDsA", - "cell_type": "markdown", - "source": [ - "Here the imported Actuals from csv are visualized " - ], - "metadata": {} - }, - { - "id": "CaVs88CPvEuA-lj1QXbU4A", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetIfrsVariables(dataNode)", - "\n .Where(x => new string[] {EstimateTypes.A, EstimateTypes.AA, EstimateTypes.OA}.Contains(x.EstimateType))", - "\n .Where(x => x.AocType != \"EOP\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "J2FGEyUHWk-y2N3yq7bQGQ", - "cell_type": "markdown", - "source": [ - "where the filter is selecting only those *estimate types* associated to the imported Actuals, hence excluding the IFRS variables calculated when [importing the cashflows](SpecificationsImportCashflows)." - ], - "metadata": {} - }, - { - "id": "ZFf-ptMOJUaVX3hg-LJRPA", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Base Actuals" - ], - "metadata": {} - }, - { - "id": "q2ZSjwzGV0iSYC2rHoNKBQ", - "cell_type": "markdown", - "source": [ - "The following simplified AoC Chain applies for Advance and Overdue Actuals:", - "\n1. Beginning of Period (BOP)", - "\n2. Cash flow (CF)", - "\n3. Amortization (AM) ", - "\n4. End of Period (EOP) ", - "\n", - "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", - "\n- Actuals (A)", - "\n- Advance Actuals (AA)", - "\n- Overdue Actuals (OA)", - "\n- Deferrable Actuals (DA)", - "\n", - "\nwith the Estimate Type's system name shown between parenthesis above.", - "\nThey are computed by the so-called Actual Base **Scope**", - "\n", - "\n$$", - "\n\\text{Actual Base} (\\text{AoC}) = \\left\\{", - "\n\\begin{array}{cl}", - "\n0 & \\text{if AoC step is AM,} \\\\", - "\n\\text{Actual Base}(\\rm{BOP}) + \\text{Actual Base}(\\rm{CF}) + \\text{Actual Base}(\\rm{WO}) & \\text{if AoC step is EOP and Estimate Type is not A,} \\\\", - "\n\\text{Imported Actual} & \\text{otherwise.}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nWe start by selecting one of the [imported Actual](#view-imported-actuals) and we pick up an available data node, novelty, and amount type. Then, we can retrieve the corresponding actual (if any) with AoC type BOP, R, and WO. ", - "\n", - "\nNote that the **Identity** for Actual Base contains information about the target data node, AoC type, novelty, amount type and estimate type." - ], - "metadata": {} - }, - { - "id": "3mz_ogsNkUOQiwgPjhzFSw", - "cell_type": "markdown", - "source": [ - "## End of Period" - ], - "metadata": {} - }, - { - "id": "1gmNQIcnYkWzuw3POkhHTg", - "cell_type": "markdown", - "source": [ - "The imported actuals for the AoC steps BOP, CF, and WO are:" - ], - "metadata": {} - }, - { - "id": "m0tpSB8gxUyDD338Zgkb2Q", - "cell_type": "code", - "source": [ - "var actualBaseBOP = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" }, \"PR\", \"AA\", (int?)null) ); ", - "\nactualBaseBOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dJten8gq_kyMKh4S8U_dzw", - "cell_type": "code", - "source": [ - "var actualBaseCF = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) );", - "\nactualBaseCF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YmaBzLIDzU-jXeSLLeah2Q", - "cell_type": "code", - "source": [ - "var actualBaseWO = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"WO\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) ); ", - "\nactualBaseWO" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kkzVuYU0TUq_BrtrZbS2Cg", - "cell_type": "markdown", - "source": [ - "Based on the imported actuals and according to the [formula above](#base-actual), the computed actual for AoC step EOP reads" - ], - "metadata": {} - }, - { - "id": "rJlipm8F8UqWjrerzqNxHw", - "cell_type": "code", - "source": [ - "var computedActualBaseEOP = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"EOP\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) ); ", - "\ncomputedActualBaseEOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "agUQcE0dMkGmHLSL3ckUNA", - "cell_type": "markdown", - "source": [ - "The computed value can be compared with the expected value" - ], - "metadata": {} - }, - { - "id": "iNuhJJEj4UukayFi6gCk5Q", - "cell_type": "code", - "source": [ - "computedActualBaseEOP.Value == actualBaseBOP.Value + actualBaseCF.Value + actualBaseWO.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LoHEbpUBtUKZRzu41Eyo1g", - "cell_type": "code", - "source": [ - "computedActualBaseEOP.Value.Should().Be( actualBaseBOP.Value + actualBaseCF.Value + actualBaseWO.Value );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "g-rX5A35Bk67CAhSb5UMBw", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Deferrable Actuals" - ], - "metadata": {} - }, - { - "id": "Yb0BdsMIdEmyenFYmcNP0g", - "cell_type": "markdown", - "source": [ - "The Deferrable Actuals (DA) are computed as follows", - "\n", - "\n$$", - "\n\\text{Deferrable Actual} (\\text{AoC}) = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{Actual Base}_{\\substack{\\text{Estimate Type}=\\text{A} \\\\ \\text{Amount Type}=\\text{ACA}}} (\\text{CF})", - "\n +\\text{Actual Base}_{\\substack{\\text{Estimate Type}=\\text{A} \\\\ \\text{Amount Type}=\\text{AEA}}} (\\text{CF}) & \\text{if AoC step is CF } \\\\", - "\n-\\text{AMF} \\cdot \\big( \\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) \\big) & \\text{if AoC step is AM } \\\\", - "\n\\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) + \\text{Deferrable Actual}(\\rm{AM}) & \\text{if AoC step is EOP } \\\\", - "\n\\text{Input Actual}_{\\text{Estimate Type}=\\text{DA}} (\\text{BOP}) & \\text{if AoC step is BOP } \\\\", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere ACA and AEA are *Aquisition* Amount Types from *Attributable Commission* and *Attributable Expenses*, respectively.", - "\n", - "\nNote that the **Identity** of Deferrable Actual is encompassing solely data node, Aoc type, and novelty." - ], - "metadata": {} - }, - { - "id": "dIh2Kt3mwEOjtIdYsSQLpw", - "cell_type": "markdown", - "source": [ - "## Beginning of Period" - ], - "metadata": {} - }, - { - "id": "ZwwOl_GoSEyoQi2486bksw", - "cell_type": "code", - "source": [ - "var computedDeferrableActualBOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" } );", - "\ncomputedDeferrableActualBOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rwIPbApkqk20YefMttJaBQ", - "cell_type": "markdown", - "source": [ - "The deferrable Actual for the AoC step being BOP is simply the EOP Actual of the previous period. In fact, if the latter exists among the [imported Actuals](#view-imported-actuals), it is reported here below as the BOP of the current period:" - ], - "metadata": {} - }, - { - "id": "ECOpAU6G40ecEEPHz210UQ", - "cell_type": "code", - "source": [ - "var expectedDeferrableActualBOP = Test.GetStorage().GetValue(new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" }, (string)null, EstimateTypes.DA, (int?)null);", - "\nexpectedDeferrableActualBOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "F_RpeDiSsk2xnjvgkmQyfA", - "cell_type": "markdown", - "source": [ - "The expected value is compared with the computed result: " - ], - "metadata": {} - }, - { - "id": "RAI7Dd_j4kaqQJENtCDH2Q", - "cell_type": "code", - "source": [ - "computedDeferrableActualBOP.Value == expectedDeferrableActualBOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Xj5YWVMuskWq5g578_rF3g", - "cell_type": "code", - "source": [ - "computedDeferrableActualBOP.Value.Should().Be(expectedDeferrableActualBOP);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VE3a5lAE40OUqsCPrC8OkQ", - "cell_type": "markdown", - "source": [ - "## Cash flow" - ], - "metadata": {} - }, - { - "id": "KCDTqi_VaEeLnsXIQtuFfw", - "cell_type": "code", - "source": [ - "var computedDeferrableActualCF = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" } );", - "\ncomputedDeferrableActualCF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-npyFyfnKU2HKSBOkmaWqw", - "cell_type": "markdown", - "source": [ - "The deferrable Actual for the AoC step being CF is the sum of the base Actuals with Amount Type ACA and AEA:" - ], - "metadata": {} - }, - { - "id": "DMXlh_BdV0m-gGATOlCmXw", - "cell_type": "code", - "source": [ - "var actualBaseAEA = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"AEA\", \"A\", (int?)null) );", - "\nactualBaseAEA" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0bhhirWn60Sa22kkJBKxPA", - "cell_type": "code", - "source": [ - "var actualBaseACA = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"ACA\", \"A\", (int?)null) );", - "\nactualBaseACA" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "s5th00fR9km5T_Jn7WG_Tw", - "cell_type": "code", - "source": [ - "var expectedDeferrableActualCF = actualBaseAEA.Value + actualBaseACA.Value;", - "\nexpectedDeferrableActualCF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nTo3qqybYkKSKmR3F1ElOA", - "cell_type": "markdown", - "source": [ - "The expected value is compared with the computed result: " - ], - "metadata": {} - }, - { - "id": "focF1ZcZDUOXSSNLlZkfFg", - "cell_type": "code", - "source": [ - "computedDeferrableActualCF.Value == expectedDeferrableActualCF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zj2ipSnC_UqYHMXCw093xg", - "cell_type": "code", - "source": [ - "computedDeferrableActualCF.Value.Should().Be(expectedDeferrableActualCF);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RQuw7gToOkS4hInnv9Kzww", - "cell_type": "markdown", - "source": [ - "## Amortization" - ], - "metadata": {} - }, - { - "id": "_MvSo7kpmEO8Lx_8g70chg", - "cell_type": "code", - "source": [ - "var computedDeferrableActualAM = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", - "\ncomputedDeferrableActualAM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GxyMep7IRUuKq-XPTZaSoA", - "cell_type": "markdown", - "source": [ - "The deferrable Actual for the AoC step being AM is the sum of the deferrable Actuals for AoC step BOP and CF multiplied by the current period amortization factor:" - ], - "metadata": {} - }, - { - "id": "YxvqYPNNPkGTrfpko0P9tg", - "cell_type": "code", - "source": [ - "var currentPeriodAmortizationFactor = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", - "\ncurrentPeriodAmortizationFactor" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CcAeUSZHEUy_ZLSZOjwWNQ", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetValue(new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" }, (string)null, \"F\", \"L\", (int?)null)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "R7RYD25pIkyzpVtr4bTYZQ", - "cell_type": "code", - "source": [ - "var expectedDeferrableActualAM = -currentPeriodAmortizationFactor.Value * (expectedDeferrableActualBOP + expectedDeferrableActualCF);", - "\nexpectedDeferrableActualAM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "57FkYeaQNEGS22T303mszw", - "cell_type": "markdown", - "source": [ - "The expected value is compared with the computed result: " - ], - "metadata": {} - }, - { - "id": "vj4ilsvlW0Kd_W6yb9M_LA", - "cell_type": "code", - "source": [ - "computedDeferrableActualAM.Value == expectedDeferrableActualAM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-ZnJyECl70mF5zHLrrMwJA", - "cell_type": "code", - "source": [ - "computedDeferrableActualAM.Value.Should().Be( expectedDeferrableActualAM );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xc8raQB2aECcY5vJIlfnXw", - "cell_type": "markdown", - "source": [ - "## End of Period" - ], - "metadata": {} - }, - { - "id": "LVj_SAEOeEy1V78xmool1w", - "cell_type": "code", - "source": [ - "var computedDeferrableActualEOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"EOP\", Novelty = \"C\" } );", - "\ncomputedDeferrableActualEOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4thR0prSO0KUITk7bFfW2g", - "cell_type": "markdown", - "source": [ - "The deferrable Actual for the AoC step being EOP is the sum of the deferrable Actuals for AoC step BOP, CF, and AM:" - ], - "metadata": {} - }, - { - "id": "KCOAQSqabUmBYKvz1FRHWQ", - "cell_type": "code", - "source": [ - "var deferrableActualBOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" } );", - "\ndeferrableActualBOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-goqiLAXmEa7aVplCpRGjQ", - "cell_type": "code", - "source": [ - "var deferrableActualCF = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" } );", - "\ndeferrableActualCF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IW3UXfNFZ0CCML8Omp0uKQ", - "cell_type": "code", - "source": [ - "var deferrableActualAM = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", - "\ndeferrableActualAM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LbrMeCRVTEGd8XazzJK4UQ", - "cell_type": "code", - "source": [ - "var expectedDeferrableActualEOP = deferrableActualBOP.Value + deferrableActualCF.Value + deferrableActualAM.Value;", - "\nexpectedDeferrableActualEOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bq4Rfl5WFEejDIWSCzYAgA", - "cell_type": "markdown", - "source": [ - "The expected value is compared with the computed result: " - ], - "metadata": {} - }, - { - "id": "hKN5tE4QmkuzwXxOyxc9xQ", - "cell_type": "code", - "source": [ - "computedDeferrableActualEOP.Value == expectedDeferrableActualEOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BrWWx3tS2UK7lsbEDU4TOg", - "cell_type": "code", - "source": [ - "computedDeferrableActualEOP.Value.Should().Be(expectedDeferrableActualEOP);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Rn9tO4dA3kGJWgSdp5k-hA", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Import Actuals Specifications

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the calculations taking place when importing the Actuals. For this documentation notebook the Data is imported from the corresponding csv files located in the following path Initialization/Systemorph/. The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ] + }, + { + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Data" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month), Reporting Node, Economic Basis, and Data Node based on the imported data:" + ] + }, + { + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;", + "\nvar dataNode = \"DT1.1\";" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Import the Dimensions, Yield Curves and Nominal Cashflows from the corresponding csv files in Initialization/Systemorph/" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Initialization of the Test Suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ] + }, + { + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Actual);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## View imported Actuals" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here the imported Actuals from csv are visualized " + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetIfrsVariables(dataNode)", + "\n .Where(x => new string[] {EstimateTypes.A, EstimateTypes.AA, EstimateTypes.OA}.Contains(x.EstimateType))", + "\n .Where(x => x.AocType != \"EOP\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "where the filter is selecting only those *estimate types* associated to the imported Actuals, hence excluding the IFRS variables calculated when [importing the cashflows](SpecificationsImportCashflows)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Base Actuals" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The following simplified AoC Chain applies for Advance and Overdue Actuals:", + "\n1. Beginning of Period (BOP)", + "\n2. Cash flow (CF)", + "\n3. Amortization (AM) ", + "\n4. End of Period (EOP) ", + "\n", + "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", + "\n- Actuals (A)", + "\n- Advance Actuals (AA)", + "\n- Overdue Actuals (OA)", + "\n- Deferrable Actuals (DA)", + "\n", + "\nwith the Estimate Type's system name shown between parenthesis above.", + "\nThey are computed by the so-called Actual Base **Scope**", + "\n", + "\n$$", + "\n\\text{Actual Base} (\\text{AoC}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n0 & \\text{if AoC step is AM,} \\\\", + "\n\\text{Actual Base}(\\rm{BOP}) + \\text{Actual Base}(\\rm{CF}) + \\text{Actual Base}(\\rm{WO}) & \\text{if AoC step is EOP and Estimate Type is not A,} \\\\", + "\n\\text{Imported Actual} & \\text{otherwise.}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nWe start by selecting one of the [imported Actual](#view-imported-actuals) and we pick up an available data node, novelty, and amount type. Then, we can retrieve the corresponding actual (if any) with AoC type BOP, R, and WO. ", + "\n", + "\nNote that the **Identity** for Actual Base contains information about the target data node, AoC type, novelty, amount type and estimate type." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## End of Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The imported actuals for the AoC steps BOP, CF, and WO are:" + ] + }, + { + "cell_type": "code", + "source": [ + "var actualBaseBOP = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" }, \"PR\", \"AA\", (int?)null) ); ", + "\nactualBaseBOP" + ] + }, + { + "cell_type": "code", + "source": [ + "var actualBaseCF = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) );", + "\nactualBaseCF" + ] + }, + { + "cell_type": "code", + "source": [ + "var actualBaseWO = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"WO\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) ); ", + "\nactualBaseWO" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Based on the imported actuals and according to the [formula above](#base-actual), the computed actual for AoC step EOP reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedActualBaseEOP = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"EOP\", Novelty = \"C\" }, \"PR\", \"AA\", (int?)null) ); ", + "\ncomputedActualBaseEOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value can be compared with the expected value" + ] + }, + { + "cell_type": "code", + "source": [ + "computedActualBaseEOP.Value == actualBaseBOP.Value + actualBaseCF.Value + actualBaseWO.Value" + ] + }, + { + "cell_type": "code", + "source": [ + "computedActualBaseEOP.Value.Should().Be( actualBaseBOP.Value + actualBaseCF.Value + actualBaseWO.Value );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Deferrable Actuals" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Deferrable Actuals (DA) are computed as follows", + "\n", + "\n$$", + "\n\\text{Deferrable Actual} (\\text{AoC}) = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{Actual Base}_{\\substack{\\text{Estimate Type}=\\text{A} \\\\ \\text{Amount Type}=\\text{ACA}}} (\\text{CF})", + "\n +\\text{Actual Base}_{\\substack{\\text{Estimate Type}=\\text{A} \\\\ \\text{Amount Type}=\\text{AEA}}} (\\text{CF}) & \\text{if AoC step is CF } \\\\", + "\n-\\text{AMF} \\cdot \\big( \\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) \\big) & \\text{if AoC step is AM } \\\\", + "\n\\text{Deferrable Actual}(\\rm{BOP}) + \\text{Deferrable Actual}(\\rm{CF}) + \\text{Deferrable Actual}(\\rm{AM}) & \\text{if AoC step is EOP } \\\\", + "\n\\text{Input Actual}_{\\text{Estimate Type}=\\text{DA}} (\\text{BOP}) & \\text{if AoC step is BOP } \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere ACA and AEA are *Aquisition* Amount Types from *Attributable Commission* and *Attributable Expenses*, respectively.", + "\n", + "\nNote that the **Identity** of Deferrable Actual is encompassing solely data node, Aoc type, and novelty." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Beginning of Period" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeferrableActualBOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" } );", + "\ncomputedDeferrableActualBOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being BOP is simply the EOP Actual of the previous period. In fact, if the latter exists among the [imported Actuals](#view-imported-actuals), it is reported here below as the BOP of the current period:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeferrableActualBOP = Test.GetStorage().GetValue(new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" }, (string)null, EstimateTypes.DA, (int?)null);", + "\nexpectedDeferrableActualBOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualBOP.Value == expectedDeferrableActualBOP" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualBOP.Value.Should().Be(expectedDeferrableActualBOP);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Cash flow" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeferrableActualCF = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" } );", + "\ncomputedDeferrableActualCF" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being CF is the sum of the base Actuals with Amount Type ACA and AEA:" + ] + }, + { + "cell_type": "code", + "source": [ + "var actualBaseAEA = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"AEA\", \"A\", (int?)null) );", + "\nactualBaseAEA" + ] + }, + { + "cell_type": "code", + "source": [ + "var actualBaseACA = Test.GetScope( (new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" }, \"ACA\", \"A\", (int?)null) );", + "\nactualBaseACA" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeferrableActualCF = actualBaseAEA.Value + actualBaseACA.Value;", + "\nexpectedDeferrableActualCF" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualCF.Value == expectedDeferrableActualCF" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualCF.Value.Should().Be(expectedDeferrableActualCF);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Amortization" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeferrableActualAM = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", + "\ncomputedDeferrableActualAM" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being AM is the sum of the deferrable Actuals for AoC step BOP and CF multiplied by the current period amortization factor:" + ] + }, + { + "cell_type": "code", + "source": [ + "var currentPeriodAmortizationFactor = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", + "\ncurrentPeriodAmortizationFactor" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetValue(new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" }, (string)null, \"F\", \"L\", (int?)null)" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeferrableActualAM = -currentPeriodAmortizationFactor.Value * (expectedDeferrableActualBOP + expectedDeferrableActualCF);", + "\nexpectedDeferrableActualAM" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualAM.Value == expectedDeferrableActualAM" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualAM.Value.Should().Be( expectedDeferrableActualAM );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## End of Period" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeferrableActualEOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"EOP\", Novelty = \"C\" } );", + "\ncomputedDeferrableActualEOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The deferrable Actual for the AoC step being EOP is the sum of the deferrable Actuals for AoC step BOP, CF, and AM:" + ] + }, + { + "cell_type": "code", + "source": [ + "var deferrableActualBOP = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"BOP\", Novelty = \"I\" } );", + "\ndeferrableActualBOP" + ] + }, + { + "cell_type": "code", + "source": [ + "var deferrableActualCF = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"CF\", Novelty = \"C\" } );", + "\ndeferrableActualCF" + ] + }, + { + "cell_type": "code", + "source": [ + "var deferrableActualAM = Test.GetScope( new ImportIdentity {DataNode = \"DT1.1\", AocType = \"AM\", Novelty = \"C\" } );", + "\ndeferrableActualAM" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeferrableActualEOP = deferrableActualBOP.Value + deferrableActualCF.Value + deferrableActualAM.Value;", + "\nexpectedDeferrableActualEOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected value is compared with the computed result: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualEOP.Value == expectedDeferrableActualEOP" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeferrableActualEOP.Value.Should().Be(expectedDeferrableActualEOP);" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/SpecificationsImportCashflows.ipynb b/Test/SpecificationsImportCashflows.ipynb index 27b2e084..eac7cd32 100644 --- a/Test/SpecificationsImportCashflows.ipynb +++ b/Test/SpecificationsImportCashflows.ipynb @@ -1,2906 +1,1990 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showtags": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "lI4yThFtAkGBL2c6iGY6NA", - "cell_type": "markdown", - "source": [ - "

Import Cashflows Specifications

" - ], - "metadata": {} - }, - { - "id": "XPSBZvgeJUWm3KfISi0_kw", - "cell_type": "markdown", - "source": [ - "The aim of this notebook is to document the calculation of the Present Values and Amortization Factors starting from the nominal Cashflows and the Yearly Yield Curve. These starting data is imported from the corresponding csv files located in the following path Initialization/Systemorph/. The process is pictorially explained in the following flowchart. ", - "\n", - "\n", - "\n
", - "\n", - "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." - ], - "metadata": {} - }, - { - "id": "KuBokOZnNEKyeai5pecD_A", - "cell_type": "markdown", - "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" - ], - "metadata": {} - }, - { - "id": "ymRDCUIfokuZuGhcIgRC2Q", - "cell_type": "code", - "source": [ - "#!import \"SpecificationsSetup\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "K2nnKAzJ1kWqqKCw6hgCpg", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "vDUrjRR4W0Cab2XwoLh66g", - "cell_type": "markdown", - "source": [ - "# Import Data" - ], - "metadata": {} - }, - { - "id": "25t6_azELkmmpL2KrlobIg", - "cell_type": "markdown", - "source": [ - "", - "\n## Current Period" - ], - "metadata": {} - }, - { - "id": "p89NHTl7QUan7LJZcHQ7CA", - "cell_type": "markdown", - "source": [ - "Please select the target period (i.e. year and month), Reporting Node, Economic Basis, and Data Node based on the imported data:" - ], - "metadata": {} - }, - { - "id": "1AQXjlCH5UqQtZhHE_ToWA", - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"C\" ;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "C7KE2ugMTEeeZXpow5IctQ", - "cell_type": "markdown", - "source": [ - "Import the Dimensions, Yield Curves and Nominal Cashflows from the corresponding csv files in Initialization/Systemorph/" - ], - "metadata": {} - }, - { - "id": "o-K6Iedo20-WGrgowVvxNA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Kd4etWIfVECgbQOUwpJjng", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wRwk6MvytEO_Ynh6H4re9g", - "cell_type": "markdown", - "source": [ - "At this point reference data are loaded. Import now a cashfow file with a 720 elements." - ], - "metadata": {} - }, - { - "id": "u4C4qyNFokyVYXTnBsqhGw", - "cell_type": "code", - "source": [ - "var groupOfContract = \"GricComplex\";", - "\nawait UploadCashflowsAsync(\"Data/CashflowComplex.csv\")" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5qP7HJWjK0K-tb_-qAYFaw", - "cell_type": "markdown", - "source": [ - "Initialization of the Test suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" - ], - "metadata": {} - }, - { - "id": "_NJvnl5PKE6FQXhN5Pr_tw", - "cell_type": "code", - "source": [ - "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "raVSJGuqL0i16HubdvKRSQ", - "cell_type": "markdown", - "source": [ - "", - "\n## View loaded Data Nodes" - ], - "metadata": {} - }, - { - "id": "C-jrvc1_akme8Lq4zXXNnA", - "cell_type": "markdown", - "source": [ - "The imported active Data Nodes from Initialization/Systemorph/DataNodes.csv are " - ], - "metadata": {} - }, - { - "id": "ayPI03mGFEuJqDditI5Zcg", - "cell_type": "code", - "source": [ - "Test.GetStorage().DataNodeDataBySystemName" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "PNkJZPN3D0OTE4K9m7yhtw", - "cell_type": "markdown", - "source": [ - "", - "\n## View loaded Yearly Yield Curve" - ], - "metadata": {} - }, - { - "id": "449EmK-s0EC-qvpkUic0Ng", - "cell_type": "markdown", - "source": [ - "Here the correct Yield Curve is chosen among those imported from Initialization/Systemorph/Data.csv according to the [current period](#year-and-period) and the Aoc Step according the [Aoc Configuration](../DataModel/DataStructure#aoc-configuration). In the following we retrieve the desired identity." - ], - "metadata": {} - }, - { - "id": "GFBbfoECXkyIOhUvzUj1YA", - "cell_type": "code", - "source": [ - "var aocType = \"CL\";", - "\nvar novelty = \"C\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Xh9Ph958zUaWPoHyXTfa7g", - "cell_type": "code", - "source": [ - "var id = Test.GetIdentity(groupOfContract, aocType, novelty);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LSypuaGSnkmcuusalSOIMw", - "cell_type": "code", - "source": [ - "var yearlyYieldCurve = Test.GetStorage().GetYearlyYieldCurve(id, economicBasis);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZVGOGlL470Cv6pGp5K4TQA", - "cell_type": "code", - "source": [ - "yearlyYieldCurve" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YHtOWxQvJUygOp9bM9DnOg", - "cell_type": "markdown", - "source": [ - "", - "\n## View loaded Nominal Cashflows" - ], - "metadata": {} - }, - { - "id": "nuWozOR2zUqFJgmjZjSpSw", - "cell_type": "markdown", - "source": [ - "The nominal Cashflows for the current period are loaded together with last period Cashflows for Group of Contract that were already existent. ", - "\n", - "\nThe relative files are located in: Files/.", - "\n", - "\nThe result is showed in the following list to be compared with the entries of the csv files" - ], - "metadata": {} - }, - { - "id": "5XHFiMOI_k6ZLxFuzYGObA", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetRawVariables(groupOfContract)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "i5XQoNnkHkCwFkZK-wvzeg", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Interest and Discount Rates" - ], - "metadata": {} - }, - { - "id": "QvPW08NJs0mc35ufVdJITA", - "cell_type": "markdown", - "source": [ - "The Yield Curve ${\\text{YC}_i}$ associated to the the [selected period](#year-and-period) and target currency of the Group of Contract Reporting Node is [displayed above](#view-loaded-yearly-yield-curve) and used in this section to calculate the Interest and Discount factors", - "\n", - "\n$$", - "\n\\text{Interest}_i = \\big( 1 + \\text{YC}_i \\big) ^{\\frac{1}{12}} ~,", - "\n$$", - "\n", - "\nand", - "\n", - "\n\\begin{align}", - "\n\\text{Discount}_i = \\big( 1 + \\text{YC}_i \\big) ^{-\\frac{1}{12}} ~.", - "\n\\end{align}" - ], - "metadata": {} - }, - { - "id": "Tx3o3lO8s0m5gv72S8Okfw", - "cell_type": "markdown", - "source": [ - "In the Scope named *MonthlyRate* the Interest and Discount factors are computed" - ], - "metadata": {} - }, - { - "id": "WjCiyKVx3UKysYDWgLig9w", - "cell_type": "code", - "source": [ - "var computedMonthlyRates = Test.GetScope( id );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Q4y_soImlkyK0gLglSALsQ", - "cell_type": "code", - "source": [ - "computedMonthlyRates" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fl25D0dZKk6SeRoszzGp6Q", - "cell_type": "markdown", - "source": [ - "## Interest" - ], - "metadata": {} - }, - { - "id": "Z9R5ky64QUmw-BnZLN2Jug", - "cell_type": "markdown", - "source": [ - "In the following, the Interest factors computed by the application are recalculated independently according to the formula above in two different ways" - ], - "metadata": {} - }, - { - "id": "JAjIqFrQ-UizVR9ENdEB5Q", - "cell_type": "code", - "source": [ - "var expectedInterest = yearlyYieldCurve.Select( yc => (1 + yc)^( 1.0 / 12.0) );", - "\nexpectedInterest" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KHb-pVU5lkKoPw1Yx6IOLw", - "cell_type": "code", - "source": [ - "from yc in yearlyYieldCurve select (1 + yc)^( 1.0 / 12.0 ) " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "eWIhGYRQQUSp9YT53BxCgw", - "cell_type": "code", - "source": [ - "computedMonthlyRates.Interest.CheckEquality( expectedInterest ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Pt64D8ANL06gXx9he1WVzw", - "cell_type": "markdown", - "source": [ - "## Discount" - ], - "metadata": {} - }, - { - "id": "TPUopwWBTUG3gPPmb2B5Nw", - "cell_type": "markdown", - "source": [ - "The following recalculates the Discount factors to be compared with the computed values" - ], - "metadata": {} - }, - { - "id": "YtUiQ2xnzE2FfAa6LlAcfw", - "cell_type": "code", - "source": [ - "var expectedDiscount = yearlyYieldCurve.Select( yc => (1 + yc)^( -1.0 / 12.0) );", - "\nexpectedDiscount" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZGVBiwBOUk-I3JmXZnK4JA", - "cell_type": "code", - "source": [ - "computedMonthlyRates.Discount.CheckEquality( expectedDiscount ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lMyTCC6GPUW45Cvx6U3JRw", - "cell_type": "markdown", - "source": [ - "## Test method: Get Valid Element" - ], - "metadata": {} - }, - { - "id": "FZ9_fdXlIECy7PDdcDlH1Q", - "cell_type": "markdown", - "source": [ - "Given the present Yield Curve array has finite *length*, the extrapolation implemented is taking the last element for all successive years. This behavior is given by the function *GetValidElement*. The test in this section assures that constant extrapolation is taken for *index* > *length*" - ], - "metadata": {} - }, - { - "id": "IfoqWI9zGkGc-Po9tnOcoQ", - "cell_type": "code", - "source": [ - "expectedDiscount.GetValidElement( 120 )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Z5ZpUs9wmUWbGWk6GcxNeA", - "cell_type": "code", - "source": [ - "expectedDiscount.GetValidElement( 120 ).Should().Be( expectedDiscount.Last() );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-KgziQbrF0mQYRsvkSkeGw", - "cell_type": "markdown", - "source": [ - "

", - "\n# Cashflows" - ], - "metadata": {} - }, - { - "id": "ITDv12Ph90ObEuoxNIr45w", - "cell_type": "markdown", - "source": [ - "This section deals with the calculation of the *Cumulated Discounted Cashflows* (CDC) starting from the nominal Cashflows. " - ], - "metadata": {} - }, - { - "id": "Isggf5h2S0unL3O7pgAirQ", - "cell_type": "markdown", - "source": [ - "## Choose identity" - ], - "metadata": {} - }, - { - "id": "pwQ4TMUvhUK-StHJEDFlCg", - "cell_type": "markdown", - "source": [ - "Each loaded nominal Cashflows is assigned to a so-called *Identity* which uniquely identifies it based on the *Data Node*, *Aoc Type*, and *Novelty*. In the following cells we retrieve the desired Identity:" - ], - "metadata": {} - }, - { - "id": "3MHGdD0V1k6cXBNxvaUgHA", - "cell_type": "code", - "source": [ - "var aocType = \"CL\";", - "\nvar novelty = \"C\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gPX1Ygo_DECIrwFPBvRXSQ", - "cell_type": "code", - "source": [ - "var id = Test.GetIdentity(groupOfContract, aocType, novelty);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KOWB-LuZSE6jCwSkVWLqLQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Nominal Cashflow" - ], - "metadata": {} - }, - { - "id": "7wA9Mo5SWkGRA9UpDIfDug", - "cell_type": "markdown", - "source": [ - "Consider the two Amount Type *PR* and *NIC*, with Transaction Period being *Beginning of Period* (BOP) and *End of Period* (EOP), respectively. The corresponding nominal Cashflows are deposited in the Scopes named *NominalCashflow* with the Identity provided above, Calculation Type *BE*, and the aforementioned Amount Types. These nominal Cashflows correspond with those [loaded from the csv files](#view-loaded-nominal-cashflows). " - ], - "metadata": {} - }, - { - "id": "mlWZ7mpOFkSD2Ru1TCl59g", - "cell_type": "code", - "source": [ - "var amountTypePR = \"PR\";", - "\nvar amountTypeNIC = \"NIC\";", - "\nvar calculationType = \"BE\";", - "\nvar accidentYear = (int?)null;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9TXHMp0XEEKq8LfUzqH9CA", - "cell_type": "code", - "source": [ - "var nominalPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WlEihYtxbECHWuuKVgue_w", - "cell_type": "code", - "source": [ - "nominalPR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "NERNBoD-OkiRREaV55ijeA", - "cell_type": "code", - "source": [ - "var nominalNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hFfWM0bKxkW3mOhIZgZ5AQ", - "cell_type": "code", - "source": [ - "nominalNIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "765s5aL5Z0K0t5ZLuyCojg", - "cell_type": "markdown", - "source": [ - "", - "\n## Cumulated Discounted Cashflow" - ], - "metadata": {} - }, - { - "id": "JT4SSHYyVkK6kvw6pm1RYQ", - "cell_type": "markdown", - "source": [ - "The CDC is defined by the following recursive formulas", - "\n", - "\n$$", - "\n\\text{CDC}_t = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{Nominal}_t + \\text{CDC}_{t+1} \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} ~, & \\text{if Transaction Period is Beginning of Period} \\\\", - "\n\\big( \\text{Nominal}_t + \\text{CDC}_{t+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} ~, & \\text{if Transaction Period is End of Period}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere the Transaction Period depends on the given cashflow Amount Type. " - ], - "metadata": {} - }, - { - "id": "d_iKZefoME6wTrnz9UAv5A", - "cell_type": "markdown", - "source": [ - "### Beginning of Period" - ], - "metadata": {} - }, - { - "id": "espKPj1dtUuJz8XXQUAKzg", - "cell_type": "markdown", - "source": [ - "The Amount Type **Premiums** (PR) has Transaction Period **Beginning of Period** (BOP). The corresponding CDC calculated by the application is" - ], - "metadata": {} - }, - { - "id": "T7aVgGRgDEakkG-s3lfN0g", - "cell_type": "code", - "source": [ - "var computedDiscountedPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3FU71v2QJkyxs_bZfP4Uow", - "cell_type": "code", - "source": [ - "computedDiscountedPR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4YMOoutvQU-8pkN7n6TASQ", - "cell_type": "markdown", - "source": [ - "In the following cell we independently evaluate the expected discounted cashflow according to the formula above:" - ], - "metadata": {} - }, - { - "id": "ybObocoOVUKh6wl-2THKMA", - "cell_type": "code", - "source": [ - "var expectedDiscountedPR = new double[nominalPR.Values.Length];", - "\n", - "\nEnumerable.Range(0, nominalPR.Values.Length).Reverse()", - "\n .ForEach( i => expectedDiscountedPR[i] = nominalPR.Values[i] + expectedDiscountedPR.GetValidElement(i+1) * expectedDiscount.GetValidElement(i/12) );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "z256hRI3W0-dt-SPwhspvA", - "cell_type": "code", - "source": [ - "expectedDiscountedPR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kS81thpvcUK8_BDbmIGAew", - "cell_type": "code", - "source": [ - "(nominalPR.Values, nominalPR.Values.Length)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BVho0r3vFECpLdRKqXPiJQ", - "cell_type": "markdown", - "source": [ - "The expected cumulated discount is compared with the computed values" - ], - "metadata": {} - }, - { - "id": "rFrYAjOqPU6GlakOLi6Whg", - "cell_type": "code", - "source": [ - "computedDiscountedPR.Values.CheckEquality( expectedDiscountedPR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CNA426Ac4ESI3ob66JKdfg", - "cell_type": "code", - "source": [ - "computedDiscountedPR.Values.CheckEquality( expectedDiscountedPR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qGuikH-yU0uOYPbqe-xgiA", - "cell_type": "markdown", - "source": [ - "### End Of Period" - ], - "metadata": {} - }, - { - "id": "PxdI661DkEOx8fXIEikCeg", - "cell_type": "markdown", - "source": [ - "The Amount Type **Non Investment Component** (NIC) has Transaction Period **End of Period** (EOP). The corresponding CDC calculated by the application is" - ], - "metadata": {} - }, - { - "id": "glGfJSBB_UyhR3a-IkrEyw", - "cell_type": "code", - "source": [ - "var computedDiscountedNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RYBSPN2Cvk-wIGFAo24vXA", - "cell_type": "code", - "source": [ - "computedDiscountedNIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qHM_Iqz93Ee9T-BENSbB6Q", - "cell_type": "markdown", - "source": [ - "In the following cell we independently evaluate the expected discounted cashflow according to the formula above:" - ], - "metadata": {} - }, - { - "id": "MROITxwMj0ujWWt4L-Up3w", - "cell_type": "code", - "source": [ - "var expectedDiscountedNIC = new double[nominalNIC.Values.Length];", - "\n", - "\nEnumerable.Range(0, nominalNIC.Values.Length).Reverse()", - "\n .ForEach( i => expectedDiscountedNIC[i] = ( nominalNIC.Values[i] + expectedDiscountedNIC.GetValidElement(i+1) ) * expectedDiscount.GetValidElement(i/12) );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oHNnWbOAC02remoQuB3xeQ", - "cell_type": "code", - "source": [ - "expectedDiscountedNIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pxhcnJV1UUuGT40Y5o79JA", - "cell_type": "markdown", - "source": [ - "The expected cumulated discount is compared with the computed values" - ], - "metadata": {} - }, - { - "id": "fB_CWCbH30qYOnXykKpInQ", - "cell_type": "code", - "source": [ - "computedDiscountedNIC.Values.CheckEquality( expectedDiscountedNIC )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "s2gR76itBESoEBFxheTs2g", - "cell_type": "code", - "source": [ - "computedDiscountedNIC.Values.CheckEquality( expectedDiscountedNIC ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WdMso-NBKku_uV1NVbeBoQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Non Performance Risk Adjustment" - ], - "metadata": {} - }, - { - "id": "x6qIuyV8iUmHNpSrP7kT_Q", - "cell_type": "markdown", - "source": [ - "In this section we treat the determination of the non-performance risk adjustment, an element offsetting partially future", - "\nclaims according to the risk that the reinsurance company cannot fulfil the full extent of its obligations.", - "\n", - "\nFirstly, the discounting recursive relation can be written explicitly as", - "\n", - "\n$$", - "\n\\begin{array}{l}", - "\n\\text{CDC}_t = \\big( \\text{Nominal}_t + \\text{CDC}_{t+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} \\\\", - "\n\\Rightarrow \\text{CDC}_t = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau ", - "\n\\end{array}", - "\n$$", - "\n", - "\nFor nominal Cashflows with Amount Type being *Claims*, the risk-adjusted Cumulated Discounted Cashflow ", - "\nis assigned the Amount Type **Credit Default Risk** (CDR), ", - "\nand is obtained by multiplying the right hand side of the latter formula by the corresponding risk factor", - "\n", - "\n$$", - "\n\\text{CDC}_t^{\\text{Amount Type}=\\text{CDR}} = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau^{\\text{Claim}} \\cdot \\big( e^{-\\gamma(\\tau-t)} -1 \\big)", - "\n$$", - "\n", - "\nwhere $\\gamma$ is the assumed non-performance probability of the reinsurer to be provided as an [input parameter](../DataModel/DataStructure#credit-default-rate).", - "\n", - "\nThis rate is constant for the whole projection period, that is, $\\gamma$ is not a function of $t$. ", - "\nIt effectively amounts to a constant increase in the continuous discount rate by $\\gamma$. " - ], - "metadata": {} - }, - { - "id": "a0Ap0lOGJE21INUHWmjGoQ", - "cell_type": "markdown", - "source": [ - "### Explicit vs recursive formula" - ], - "metadata": {} - }, - { - "id": "pbGuRNJm70SkHeIktIoBDQ", - "cell_type": "markdown", - "source": [ - "The explicit formula is tested versus the expected result obtained with the recursive formula" - ], - "metadata": {} - }, - { - "id": "e6e-jV9vnE6RTUlNhgK1Vw", - "cell_type": "code", - "source": [ - "var expectedDiscountedNICbis = new double[nominalNIC.Values.Length];", - "\n", - "\n//for(int t = 0; t < 12; t++)", - "\n// for(int tau = t; tau < 12; tau++)", - "\n// expectedDiscountedNICbis[t] += nominalNIC.Values[tau] * Math.Pow(expectedDiscount.GetValidElement(t/12), tau-t+1);", - "\n", - "\nEnumerable.Range(0, nominalNIC.Values.Length)", - "\n .ForEach( i => expectedDiscountedNICbis[i] = ", - "\n Enumerable.Range(i, nominalNIC.Values.Length-i).Select( tau => nominalNIC.Values[tau] * Math.Pow(expectedDiscount.GetValidElement(i/12), tau-i+1) ).Sum() );", - "\n ", - "\nexpectedDiscountedNIC.CheckEquality( expectedDiscountedNICbis )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7VKY58rmN0i4hNUObTx5Lg", - "cell_type": "markdown", - "source": [ - "### Risk Adjusted Claims " - ], - "metadata": {} - }, - { - "id": "CDMXGMuNGUWSY2-VFbiSkQ", - "cell_type": "markdown", - "source": [ - "The computed CDC with Amount Type being CDR reads" - ], - "metadata": {} - }, - { - "id": "XnvESgljxkSWyht7EqW7NA", - "cell_type": "code", - "source": [ - "var computedDiscountedCRD = Test.GetScope((id, \"CDR\", calculationType, accidentYear));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "reDXOTbUxEGUchxSzysJog", - "cell_type": "code", - "source": [ - "computedDiscountedCRD" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nv4x6ysZxEmmtipcaDJy9g", - "cell_type": "markdown", - "source": [ - "The starting point for the non performance risk adjustment is the computation of the sum of nominal Cashflows with Amount Type **Claims** listed below" - ], - "metadata": {} - }, - { - "id": "bOQ1CXDjbUOygxJaPI-XYQ", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetClaims()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0pTAfl977UK_SmRREnPF6Q", - "cell_type": "markdown", - "source": [ - "with the corresponding nominal Cashflows being" - ], - "metadata": {} - }, - { - "id": "syJWhInzsEObE2ykdoGLew", - "cell_type": "code", - "source": [ - "var nominalNIC = Test.GetScope((id, \"NIC\", calculationType, accidentYear));", - "\nnominalNIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "C7ko6wgyUkSyCQS2-Q8GuQ", - "cell_type": "code", - "source": [ - "var nominalICO = Test.GetScope((id, \"ICO\", calculationType, accidentYear));", - "\nnominalICO" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GrTtn99Pc0KsTrYaIj7vhg", - "cell_type": "code", - "source": [ - "var nominalALE = Test.GetScope((id, \"ALE\", calculationType, accidentYear));", - "\nnominalNIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gAGXa9ftTUODRVbLikWr2A", - "cell_type": "code", - "source": [ - "var nominalULE = Test.GetScope((id, \"ULE\", calculationType, accidentYear));", - "\nnominalNIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ybob0Y2K00ysBNz_vpid2w", - "cell_type": "code", - "source": [ - "var nominalClaims = nominalICO.Values + nominalNIC.Values + nominalALE.Values + nominalULE.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7UXMUmrFwEKfhXV-EPyNOQ", - "cell_type": "markdown", - "source": [ - "Secondly, the correct credit risk rate (parameter $\\gamma$ in the [formula above](#non-performance-risk-adjustment)) is retrieved from the list of imported [Partner Rating](../DataModel/DataStructure) and [Credit Default Rates](../DataModel/DataStructure) relative to the target [Data Node](#year-and-period)'s Partner" - ], - "metadata": {} - }, - { - "id": "to_RSXazSEKtePbtjP11bA", - "cell_type": "code", - "source": [ - "groupOfContract" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qblrNkgGZkibWZqeduwsJg", - "cell_type": "code", - "source": [ - "var creditDefaultRate = Test.GetStorage().GetNonPerformanceRiskRate( id );", - "\ncreditDefaultRate" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OAZT23-9Uk2Bs3qRbvUOKw", - "cell_type": "markdown", - "source": [ - "Lastly, using the [formula above](#non-performance-risk-adjustment), the expected CDR discounted Cashflow can be computed" - ], - "metadata": {} - }, - { - "id": "rUJBZVBNdU-8u5dSP4bv8w", - "cell_type": "code", - "source": [ - "var expectedDiscountedCDR = new double[nominalNIC.Values.Length];", - "\n", - "\nEnumerable.Range(0, nominalClaims.Length).ForEach( t => ", - "\n expectedDiscountedCDR[t] = Enumerable.Range(t, nominalClaims.Length-t).Select( tau => ", - "\n nominalClaims[tau] * Math.Pow(expectedDiscount.GetValidElement(t/12), tau-t+1) * (Math.Exp(-creditDefaultRate*(tau-t)) - 1)", - "\n ).Sum() );", - "\n", - "\nexpectedDiscountedCDR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kKmpjPuP70GAVkBoNBqNrA", - "cell_type": "markdown", - "source": [ - "Finally, the expected cumulated discount is compared with the computed values" - ], - "metadata": {} - }, - { - "id": "m_bSBl61DE26IDp7VpY6dg", - "cell_type": "code", - "source": [ - "computedDiscountedCRD.Values.CheckEquality( expectedDiscountedCDR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DqkJo2YgcE65RX7db90WKQ", - "cell_type": "code", - "source": [ - "computedDiscountedCRD.Values.CheckEquality( expectedDiscountedCDR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mvwCM2Umf0OZHCcpOt9V5Q", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Present Values" - ], - "metadata": {} - }, - { - "id": "jzTF3NdnHkqzQ4KSajU3ig", - "cell_type": "markdown", - "source": [ - "For an implementation of these formulas refer to the [ImportScopeCalculation notebook](../Import/ImportScopeCalculation). " - ], - "metadata": {} - }, - { - "id": "g03stTrBDk-qgVynbAHR8w", - "cell_type": "markdown", - "source": [ - "The company portfolio value in one period is given by the following Analysis of Change AoC steps:", - "\n1. Beginning of Period (BoP): starting value of the portfolio as of December last year (in the Year to Date view), ", - "\n2. Model Corrections (MC): change of the portfolio value based on the model change,", - "\n3. Cash Flow (CF):", - "\n4. Interest Accretion (IA): ", - "\n5. Assumption Update (AU): ", - "\n6. Yield Curve Update (YCU): impact of yield curve update occured during the reporting period,", - "\n7. Credit Risk Update (CRU): impact of credit default rate update occured during the reporting period,", - "\n8. Experience Variance (EV): value adjustments following insurance related events which took place (e.g. mortality),", - "\n9. Combined Liabilities (CL):", - "\n10. End of Period (EOP): portfolio value at the end of the current period.", - "\n", - "\nNote: the AoC steps WO, EA and AM are not included in the Present Value calculation, hence their values if inquired is zero." - ], - "metadata": {} - }, - { - "id": "YcUNq4BqbUuS6xpbevFZDw", - "cell_type": "markdown", - "source": [ - "The Present Value Base (PVB) values are valid for all [Economic Basis](../DataModel/DataStructure#economic-basis) and depends on the corresponding [AoCType](../DataModel/DataStructure#aoc-type):", - "\n", - "\n$$", - "\n\\text{PVB}_t \\big(\\text{AoC}\\big) = ", - "\n\\left\\{", - "\n\\begin{array}{cl}", - "\n\\text{CDC}_t & \\text{if AoC is Beginning of Period (BOP) } \\\\", - "\n-\\text{Nominal}_t(\\text{Parent AoC}) & \\text{if AoC is Expected Cashflow (CF) } \\\\", - "\n\\text{InterestAccretion}_t & \\text{if AoC is Interest Accretion (IA) } \\\\", - "\n\\text{CDC}_t(\\text{Parent AoC}) & \\text{if AoC is End of Period (EOP) } \\\\", - "\n\\text{CDC}_{t}(\\text{current AoC}) - \\text{CDC}_{t}(\\text{parent AoC}) & \\text{otherwise}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nand the Projected Present Value (PPV) reads", - "\n", - "\n$$", - "\n\\text{PPV} \\big(\\text{AoC},\\text{TS},\\text{S}\\big) = \\left\\{", - "\n\\begin{array}{cll}", - "\n\\text{PVB}_{S} & \\text{if AoC Valuation Period is Beginning of Period } & \\text{ (e.g. BOP, MC) } \\\\", - "\n\\text{PVB}_{S+TS/2 -1} & \\text{if AoC Valuation Period is Mid of Period } & \\text{ (no examples in current data model) } \\\\", - "\n\\sum_{i=S}^{S + TS -1}\\text{PVB}_{i} & \\text{if AoC Valuation Period is Delta } & \\text{ (e.g. CF, IA) } \\\\", - "\n\\text{PVB}_{S + TS} & \\text{if AoC Valuation Period is End of Period } & \\text{ (e.g. YCU, CRU, EV, CL, EOP) } \\\\", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere the Shift (S) and Time Step (TS) are derived from the current [Year and Period](#year-and-period)" - ], - "metadata": {} - }, - { - "id": "96OPjQu30EWs42-nfLhp4A", - "cell_type": "code", - "source": [ - "var projectionPeriod = 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4ZzZwXo6T0-e0QLjP8y4hg", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetShift(projectionPeriod)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "netwTLrv3EmUheR4K9fkww", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetTimeStep(projectionPeriod)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HMUKlLJN6kCSVDgFWS5NUw", - "cell_type": "markdown", - "source": [ - "## Load Cashflow Data" - ], - "metadata": {} - }, - { - "id": "HZbqZPP1wUiVXHajP55O6w", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZWm_0QT1NEy3vrI1pssFEg", - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ERPDxPrxRE2F80hUf91cqQ", - "cell_type": "markdown", - "source": [ - "At this point standard Cashflows are loaded." - ], - "metadata": {} - }, - { - "id": "5qSxlX_u-0a1kyOkKpWkrw", - "cell_type": "markdown", - "source": [ - "Initialization of the Test suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" - ], - "metadata": {} - }, - { - "id": "yQhC05DCzEGeOGNpEf3mbg", - "cell_type": "code", - "source": [ - "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "R-gHWFQh4USaSbZeSX4nRA", - "cell_type": "markdown", - "source": [ - "## Select Group of Contract", - "\n", - "\nHere, it is possible to select the Group of Contract used to run the next section of this Notebook." - ], - "metadata": {} - }, - { - "id": "S6Fw2Fa0UUOkuS8wyQfBtg", - "cell_type": "code", - "source": [ - "groupOfContract = \"DTR1.1\" ;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hT5J5i-Tk0evmsGzFslKZA", - "cell_type": "markdown", - "source": [ - "## Beginning of Period" - ], - "metadata": {} - }, - { - "id": "nvqfr4Ux3kWlzwsCW0_USg", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type Beginning of Period is:" - ], - "metadata": {} - }, - { - "id": "fC63Uw1ey0OYVorrzegYrA", - "cell_type": "code", - "source": [ - "var idBoP = Test.GetIdentity(groupOfContract, \"BOP\", \"I\");", - "\nidBoP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-_jk2YKNT0u7l9uCTrc18w", - "cell_type": "code", - "source": [ - "var computedPresentValueBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueBoP_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ddqVdgtt20KgvWxmw6d8tQ", - "cell_type": "markdown", - "source": [ - "According to the [formula](#present-values) above, the expected BOP AoCType for PVB is defined to be equal to the discounted cashflows with the same Identity, Amount Type, and Calculation Type, whereas the PPV is the S-th element of the PVB." - ], - "metadata": {} - }, - { - "id": "UCd_zlXg7UKAz7Ak8etIKQ", - "cell_type": "code", - "source": [ - "var discountedBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", - "\ndiscountedBoP_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "he2CNq7s20a2kIAEI1Ew5A", - "cell_type": "code", - "source": [ - "var expectedPresentValueBoP_PR = discountedBoP_PR.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "k8y7lMCUU0ahMIV2XNly5w", - "cell_type": "markdown", - "source": [ - "In the following cell we check whether the expected values match the computed values" - ], - "metadata": {} - }, - { - "id": "E_a4AaUiYU-qVqiFMH4Ffg", - "cell_type": "code", - "source": [ - "computedPresentValueBoP_PR.Values.CheckEquality( expectedPresentValueBoP_PR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "USXwqdZpmEOlDJdxqDBZaA", - "cell_type": "code", - "source": [ - "computedPresentValueBoP_PR.Values.CheckEquality( expectedPresentValueBoP_PR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-zbiX1EOvUaXOZIuba9Jbw", - "cell_type": "markdown", - "source": [ - "", - "\n## Model Corrections" - ], - "metadata": {} - }, - { - "id": "8tg7sZov10aMykVfqjUstg", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type Model Corrections is:" - ], - "metadata": {} - }, - { - "id": "CxmloqNXXkaE5PpJU1ydAQ", - "cell_type": "code", - "source": [ - "var idMC = Test.GetIdentity(groupOfContract, \"MC\", \"I\");", - "\nidMC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nvbs4pu8Sk-fnfw1MqBJEQ", - "cell_type": "code", - "source": [ - "var computedPresentValueMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueMC_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8I2WEVons0iuf2UA4TyGtQ", - "cell_type": "markdown", - "source": [ - "According to the [formula](#present-values) above, for MC AoCType, the PVB is equal to the difference between the CDC of the current AoCType and the CDC of its parent. Additionally, the PPV is the S-th element of the PVB." - ], - "metadata": {} - }, - { - "id": "XX3McWqdQECPv33I70zR8w", - "cell_type": "code", - "source": [ - "Test.GetScope((idMC, \"PR\")).Values" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dnlMbprPGEefEvBLpE3SVA", - "cell_type": "code", - "source": [ - "var discountedMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", - "\ndiscountedMC_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "pqOSCzCTJEyNauxM07RTvg", - "cell_type": "code", - "source": [ - "var expectedPresentValueMC_PR = discountedMC_PR.Values - discountedBoP_PR.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gjdYsN-ftE-HlOKgEwvQLg", - "cell_type": "markdown", - "source": [ - "The expected PVB and PPV are compared with the computed results in the following two cells: " - ], - "metadata": {} - }, - { - "id": "WOMu6tnVOEWiRZqaziMRcg", - "cell_type": "code", - "source": [ - "computedPresentValueMC_PR.Values.CheckEquality( expectedPresentValueMC_PR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TvZ78p6vLkCL-xejOqvUcw", - "cell_type": "code", - "source": [ - "computedPresentValueMC_PR.Value == expectedPresentValueMC_PR[0]" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "w9D4tVGk5UmDB-tTCeS5Rw", - "cell_type": "code", - "source": [ - "computedPresentValueMC_PR.Values.CheckEquality( expectedPresentValueMC_PR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nnvwi_zKy0ebrac1nrqanQ", - "cell_type": "code", - "source": [ - "computedPresentValueMC_PR.Value.Should().Be( expectedPresentValueMC_PR[0] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jiKZ8kbywUK4oPhyLtuzFg", - "cell_type": "markdown", - "source": [ - "## Cashflow" - ], - "metadata": {} - }, - { - "id": "LG4pdtcxt0K_GSnJ0CDHLA", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type Cashflow is:" - ], - "metadata": {} - }, - { - "id": "CIshbPDh_0OC_HeMFEe2Rw", - "cell_type": "code", - "source": [ - "var idCF = Test.GetIdentity(groupOfContract, \"CF\", \"I\");", - "\nidCF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5sLKCaklikuTAXBf9hAoGQ", - "cell_type": "code", - "source": [ - "var computedPresentValueCF_PR = Test.GetScope((idCF, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueCF_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VNaRi132eUy9m4SnHizakQ", - "cell_type": "markdown", - "source": [ - "According to the [formula](#present-values) above, for CF AoCType, the PVB is equal to the nominal cashflow of its parent AoC step with opposite sign. The PPV is given by the sum of the first 3 elements." - ], - "metadata": {} - }, - { - "id": "pad5L8Zv40a1HYc508KwvA", - "cell_type": "code", - "source": [ - "var cfReferenceAocStep = Test.GetScope(idCF).Value;", - "\ncfReferenceAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "d_4naEye_0ez9ceQFlUsHg", - "cell_type": "code", - "source": [ - "var cfNominalReference_PR = Test.GetScope((idCF with {AocType = cfReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", - "\ncfNominalReference_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YSGvWpZAgk676PWkouVFvg", - "cell_type": "code", - "source": [ - "var expectedPresentValueCF_PR = -1.0 * cfNominalReference_PR.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "T8i5WyGKH0eb6JTHWt3k3w", - "cell_type": "markdown", - "source": [ - "The expected PVB and PPV are compared with the computed results in the following two cells: " - ], - "metadata": {} - }, - { - "id": "mlrKZMMExkOXb_z-QA-nzQ", - "cell_type": "code", - "source": [ - "computedPresentValueCF_PR.Values.CheckEquality( expectedPresentValueCF_PR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_iXoBI2Ra06t95Lv-UKmdQ", - "cell_type": "code", - "source": [ - "computedPresentValueCF_PR.Values[0] + computedPresentValueCF_PR.Values[1] + computedPresentValueCF_PR.Values[2] == computedPresentValueCF_PR.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QWPx_7NUmEyE5Xu_kEeyjg", - "cell_type": "code", - "source": [ - "computedPresentValueCF_PR.Values.CheckEquality( expectedPresentValueCF_PR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MSbSF0-9w0-iu_c3cNINjA", - "cell_type": "code", - "source": [ - "computedPresentValueCF_PR.Value.Should().Be( computedPresentValueCF_PR.Values[0] + computedPresentValueCF_PR.Values[1] + computedPresentValueCF_PR.Values[2] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iO7keKMcaE2t2gXC_7kqsA", - "cell_type": "markdown", - "source": [ - "", - "\n## Interest Accretion" - ], - "metadata": {} - }, - { - "id": "m6ZEzxBBsUyJ_QAcvMD6dA", - "cell_type": "markdown", - "source": [ - "For IA AoCType, the PVB is given by the following relation ", - "\n", - "\n$$", - "\n\\text{InterestAccretion}_i = \\left\\{", - "\n\\begin{array}{cl}", - "\n\\big(\\text{CDC}_i(\\text{Parent AoC}) - \\text{Nominal}_i(\\text{parent AoC}) \\big) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, ", - "\n & \\text{if AmountType Transaction Period is Beginning of Period} \\\\", - "\n\\text{CDC}_i(\\text{parent AoC}) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, ", - "\n & \\text{otherwise}", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhile the PPV is given by the sum of the first S elements.", - "\n", - "\nWhen selecting the Identity, note that the Novelty *C* is not contemplated for Interest Accretion." - ], - "metadata": {} - }, - { - "id": "NMCk4gASMU62Bn6JnDxQmQ", - "cell_type": "code", - "source": [ - "var idIA = Test.GetIdentity(groupOfContract, \"IA\", \"I\");", - "\nidIA" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fGjntj5jp0KxtiO6hKj29A", - "cell_type": "markdown", - "source": [ - "### Amount Type BOP" - ], - "metadata": {} - }, - { - "id": "byoRIpg2MkegjRvCvI9Ung", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Amount Type **Premiums** (PR) with Transaction Period **Beginning of Period** (BOP) is" - ], - "metadata": {} - }, - { - "id": "ZiyHW9AJqEqeFgbYLv9FQA", - "cell_type": "code", - "source": [ - "var computedPresentValueIA_PR = Test.GetScope((idIA, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueIA_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XsDT4dnWfEqsJ28QKuHueg", - "cell_type": "markdown", - "source": [ - "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the interest factors, the nominal and discounted Cashflow of the parent Aoc Step" - ], - "metadata": {} - }, - { - "id": "yFVC3VGv4E2tNAJb0CRucw", - "cell_type": "code", - "source": [ - "var iaComputedMonthlyRates = Test.GetScope( idIA );", - "\niaComputedMonthlyRates" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kNS1BMQgXUCkSOuUK_IS7g", - "cell_type": "code", - "source": [ - "var iaReferenceAocStep = Test.GetScope(idIA).Value;", - "\niaReferenceAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "m6gpvEMNwEqFRImTGZBmTQ", - "cell_type": "code", - "source": [ - "var nominalIaReference_PR = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", - "\nnominalIaReference_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kEFdXGJHjkK39Ed9UMwNQA", - "cell_type": "code", - "source": [ - "var discountedIaReference_PR = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", - "\ndiscountedIaReference_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "b-s6yRRvEUeLF_z6-rD7lw", - "cell_type": "code", - "source": [ - "var expectedPresentValueIA_PR = discountedIaReference_PR.Values.Select((val, index) => ( val - nominalIaReference_PR.Values[index]) * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kpN29rNO-Uu2al_yAtJQVg", - "cell_type": "markdown", - "source": [ - "The expected PVB and PPV are compared with the computed results in the following two cells: " - ], - "metadata": {} - }, - { - "id": "2R1QDTLoAkSYgN3VL0pXxg", - "cell_type": "code", - "source": [ - "computedPresentValueIA_PR.Values.CheckEquality( expectedPresentValueIA_PR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ioWKmAEOBk6ly7qdPm8UcQ", - "cell_type": "code", - "source": [ - "computedPresentValueIA_PR.Values[0] + computedPresentValueIA_PR.Values[1] + computedPresentValueIA_PR.Values[2] == computedPresentValueIA_PR.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lLcVd6QU_E-CV-zx6UKKyw", - "cell_type": "code", - "source": [ - "computedPresentValueIA_PR.Values.CheckEquality( expectedPresentValueIA_PR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nksstSVXV0KMKV3s1Qzbjw", - "cell_type": "code", - "source": [ - "computedPresentValueIA_PR.Value.Should().Be( computedPresentValueIA_PR.Values[0] + computedPresentValueIA_PR.Values[1] + computedPresentValueIA_PR.Values[2] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-DoJ5d5hPkGgyuUIARfcpw", - "cell_type": "markdown", - "source": [ - "### Amount Type EOP" - ], - "metadata": {} - }, - { - "id": "AIiYNFEf4EC9W5W55HyRuw", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Amount Type **Non Investment Component** (NIC) with Transaction Period **End of Period** (EOP) is" - ], - "metadata": {} - }, - { - "id": "1sPIRjZ290ekFi_RcQIo0g", - "cell_type": "code", - "source": [ - "var computedPresentValueIA_NIC = Test.GetScope((idIA, \"NIC\", \"BE\", (int?)null));", - "\ncomputedPresentValueIA_NIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8nDAQ54uqUOqhCa5ArK8Ig", - "cell_type": "markdown", - "source": [ - "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the interest monthly rates, the discounted Cashflow of the parent Aoc Step" - ], - "metadata": {} - }, - { - "id": "HMwmW4WN50q8XsSBrLA9mw", - "cell_type": "code", - "source": [ - "var iaReferenceAocStep = Test.GetScope(idIA).Value;", - "\niaReferenceAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "harsyLraKU-NCaV-qs_10A", - "cell_type": "code", - "source": [ - "var discountedIaReference_NIC = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"NIC\", \"BE\", (int?)null));", - "\ndiscountedIaReference_NIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CeJcWORR1USjRX0vRrD9uw", - "cell_type": "code", - "source": [ - "var expectedPresentValueIA_NIC = discountedIaReference_NIC.Values.Select((val, index) => val * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Bg1hcEUU9UarAJ7j6K3Cgg", - "cell_type": "markdown", - "source": [ - "The expected PVB and PPV are compared with the computed results in the following two cells: " - ], - "metadata": {} - }, - { - "id": "hiB4BkoAvUWvG3yaH-lUgg", - "cell_type": "code", - "source": [ - "computedPresentValueIA_NIC.Values.CheckEquality( expectedPresentValueIA_NIC )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FAOKIDlrpEiY95BXbRJ9Lg", - "cell_type": "code", - "source": [ - "computedPresentValueIA_NIC.Values[0] + computedPresentValueIA_NIC.Values[1] + computedPresentValueIA_NIC.Values[2] == computedPresentValueIA_NIC.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3XieKhmULE2hpsAGvEz6Jw", - "cell_type": "code", - "source": [ - "computedPresentValueIA_NIC.Values.CheckEquality( expectedPresentValueIA_NIC ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7eg7INUm50qXDWFveCVSJA", - "cell_type": "code", - "source": [ - "computedPresentValueIA_NIC.Value.Should().Be( computedPresentValueIA_NIC.Values[0] + computedPresentValueIA_NIC.Values[1] + computedPresentValueIA_NIC.Values[2] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6PbcOZfV3Ua46NCV9bNvnw", - "cell_type": "markdown", - "source": [ - "## Yield Curve Update" - ], - "metadata": {} - }, - { - "id": "AJCuWf4c_kG-MTka3KHH9A", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type Yield Curve Update is:" - ], - "metadata": {} - }, - { - "id": "xECM9ubIAUWuJJQrVhS96Q", - "cell_type": "code", - "source": [ - "var idYcu = Test.GetIdentity(groupOfContract, \"YCU\", \"I\");", - "\nidYcu" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZtcMBnMzIkCuhjXxj25VQA", - "cell_type": "code", - "source": [ - "var computedPresentValueYCU_PR = Test.GetScope((idYcu, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueYCU_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "i_nXQ_NxtkanS4_VPwpXAA", - "cell_type": "markdown", - "source": [ - "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the discount factors for beginning of period and for end of period applied to the reference Aoc step, followed by the difference between the CDC obtained with end of period discount factor and the CDC obtained with beginning of period discount factor. " - ], - "metadata": {} - }, - { - "id": "qPgsLajbvEek7uwPNGMznw", - "cell_type": "code", - "source": [ - "var ycReferenceAocStep = Test.GetScope(idYcu).Value;", - "\nycReferenceAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "s8uI23FdzE6M9phEhZvlpg", - "cell_type": "code", - "source": [ - "var ycParentAocStep = Test.GetScope((idYcu, \"PR\")).Values.Single();", - "\nycParentAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "utP-1N2gHk2noyPx1Bz_Xw", - "cell_type": "code", - "source": [ - "var ycParentId = idYcu with {AocType = ycParentAocStep.AocType, Novelty = ycParentAocStep.Novelty};", - "\nycParentId" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mtfbhW8_Fkar_ZID9fIKvw", - "cell_type": "markdown", - "source": [ - "Here is the parent AocStep discounted with the beginning of period discount factor." - ], - "metadata": {} - }, - { - "id": "m-hTC4iApEK8Ex_Oq8nqYQ", - "cell_type": "code", - "source": [ - "var discountedYcParent = Test.GetScope((ycParentId, \"PR\", \"BE\", (int?)null));", - "\ndiscountedYcParent" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "y1gdrxvTuE6sNtropNbIvg", - "cell_type": "markdown", - "source": [ - "Here we independently compute the CDC of the parent AocStep discounted with end of period discount factor." - ], - "metadata": {} - }, - { - "id": "v2NdunV9lUCmDXNy3tWk5g", - "cell_type": "code", - "source": [ - "var nominalYcParent = Test.GetScope((ycParentId, \"PR\", \"BE\", (int?)null));", - "\nnominalYcParent" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Y5RkFcGlxUWUCsWbNDtAbg", - "cell_type": "code", - "source": [ - "var ycComputedMonthlyRates = Test.GetScope( idYcu );", - "\nycComputedMonthlyRates" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Yko2CYybLEGJHMKwCDW3-g", - "cell_type": "code", - "source": [ - "var ycReferenceDiscountedEop = new double[nominalYcParent.Values.Length];", - "\n", - "\nEnumerable.Range(0, nominalYcParent.Values.Length).Reverse()", - "\n .ForEach( i => ycReferenceDiscountedEop[i] = nominalYcParent.Values[i] + ycReferenceDiscountedEop.GetValidElement(i+1) * ycComputedMonthlyRates.Discount.GetValidElement(i/12) );", - "\nycReferenceDiscountedEop" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-nB_BwXaFUSg1RGG9OtRWQ", - "cell_type": "code", - "source": [ - "var expectedPresentValueYCU_PR = ycReferenceDiscountedEop - discountedYcParent.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oqAvk5VK906PkRkAT2OaRg", - "cell_type": "code", - "source": [ - "computedPresentValueYCU_PR.Values.CheckEquality( expectedPresentValueYCU_PR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tUv9lq_VLEqCkXFKJJuQig", - "cell_type": "code", - "source": [ - "computedPresentValueYCU_PR.Value == expectedPresentValueYCU_PR[3]" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "m4ee2o2DZ0aKf2FH92STsw", - "cell_type": "code", - "source": [ - "computedPresentValueYCU_PR.Values.CheckEquality( expectedPresentValueYCU_PR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kA0wrkGJaUG-mcZFz8IYPw", - "cell_type": "code", - "source": [ - "computedPresentValueYCU_PR.Value.Should().Be( expectedPresentValueYCU_PR[3] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "USKTbJfkSE607v_NwHKjvA", - "cell_type": "markdown", - "source": [ - "## Credit Risk Update" - ], - "metadata": {} - }, - { - "id": "QxohiF0860mtmiIoW8C26A", - "cell_type": "markdown", - "source": [ - "This Aoc Step is relevant only in the case of a Group of Reinsurance Contract." - ], - "metadata": {} - }, - { - "id": "aN_4K8LWFU-JoAvOSlRyvw", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type Credit Risk Update is:" - ], - "metadata": {} - }, - { - "id": "JuGimhzAIEKT0SIZKqog0w", - "cell_type": "code", - "source": [ - "var idCru = Test.GetIdentity(groupOfContract, \"CRU\", \"I\");", - "\nidCru" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "77exgwl5wUefPwQGSvv_nA", - "cell_type": "code", - "source": [ - "var computedPresentValueCRU = Test.GetScope((idCru, \"CDR\", \"BE\", (int?)null));", - "\ncomputedPresentValueCRU" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ltjSbNI1_k-mVdX0EBv-xA", - "cell_type": "markdown", - "source": [ - "The Present Value can be recomputed independently starting as the difference between the CDC obtained with end of period credit default risk rate and the CDC obtained with beginning of period credit default risk rate, both computed using the Nominal cashflow of the reference Aoc Step and the End Of Period discounting factors. " - ], - "metadata": {} - }, - { - "id": "5Mi2lhLj9kivaiTjvv2G1Q", - "cell_type": "code", - "source": [ - "var cruReferenceAocStep = Test.GetScope(idCru).Value;", - "\ncruReferenceAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "px7VkUXT10yK8uLGIu7UEw", - "cell_type": "code", - "source": [ - "var cruReferenceId = idCru with {AocType = cruReferenceAocStep.AocType, Novelty = cruReferenceAocStep.Novelty};", - "\ncruReferenceId" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0EZECyt5MEWdc8mjDVvhuA", - "cell_type": "code", - "source": [ - "var cruParentAocStep = Test.GetScope((idCru, \"CDR\")).Values.Single();", - "\ncruParentAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "osW4gCnv2EKUPFxXxAMqJA", - "cell_type": "code", - "source": [ - "var cruParentId = idCru with {AocType = cruParentAocStep.AocType, Novelty = cruParentAocStep.Novelty};", - "\ncruParentId" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LpyKsQ8EekaZw0sPwhs2Vw", - "cell_type": "markdown", - "source": [ - "Here is the parent AocStep discounted with beginning of period credit default risk rate." - ], - "metadata": {} - }, - { - "id": "72C7qsrN9Ui9B_XYbrIpsQ", - "cell_type": "code", - "source": [ - "var discountedCruParent = Test.GetScope((cruParentId, \"CDR\", \"BE\", (int?)null));", - "\ndiscountedCruParent" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vRLrx8ecq02PiEdHXn3hBg", - "cell_type": "code", - "source": [ - "var nominalCruReference = Test.GetScope((cruReferenceId, \"CDR\", \"BE\", (int?)null)).Values;", - "\nnominalCruReference" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jLV_5_vMx0OrVHD_Yu5mVA", - "cell_type": "code", - "source": [ - "var creditDefaultRate = Test.GetStorage().GetNonPerformanceRiskRate( idCru );", - "\ncreditDefaultRate" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VEgXXlyhrEawDMht-nAV9A", - "cell_type": "code", - "source": [ - "var cruComputedMonthlyRates = Test.GetScope( idCru );", - "\ncruComputedMonthlyRates" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "owmqecMemE-q5q164EhXnw", - "cell_type": "markdown", - "source": [ - "Lastly, using the [formula above](#non-performance-risk-adjustment), the expected CDR discounted Cashflow can be computed" - ], - "metadata": {} - }, - { - "id": "LYbZBgKavEO7IynuEAXGcA", - "cell_type": "code", - "source": [ - "var cruExpectedDiscountedCDR = new double[nominalCruReference.Length];", - "\n", - "\nEnumerable.Range(0, nominalCruReference.Length).ForEach( t => ", - "\n cruExpectedDiscountedCDR[t] = Enumerable.Range(t, nominalCruReference.Length-t).Select( tau => ", - "\n nominalCruReference[tau] * ", - "\n Math.Pow(cruComputedMonthlyRates.Discount.GetValidElement(t/12), tau-t+1) * ", - "\n (Math.Exp(-creditDefaultRate*(tau-t)) - 1)", - "\n ).Sum() );", - "\n", - "\ncruExpectedDiscountedCDR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "f8a9p87_WUCugmBsw0E4sA", - "cell_type": "code", - "source": [ - "var expectedPresentValueCRU = cruExpectedDiscountedCDR - discountedCruParent.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7odSeJ5RTUmTR32M-5tlAA", - "cell_type": "code", - "source": [ - "computedPresentValueCRU.Values.CheckEquality( expectedPresentValueCRU )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ojtYz8I9xkaTA1AcV3U1Cw", - "cell_type": "code", - "source": [ - "computedPresentValueCRU.Value == expectedPresentValueCRU[3]" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WH8Cl5EMp0ewbK4iQ7-W3A", - "cell_type": "code", - "source": [ - "computedPresentValueCRU.Values.CheckEquality( expectedPresentValueCRU ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-4irtBVO70uLS-mVjr-3jQ", - "cell_type": "code", - "source": [ - "computedPresentValueCRU.Value.Should().Be( expectedPresentValueCRU[3] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QLzUGR2eJk-J02bHAg78sg", - "cell_type": "markdown", - "source": [ - "## Combined Liabilities" - ], - "metadata": {} - }, - { - "id": "bxMjiXdzt0a-HXTolLPSig", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type Combined Liabilities and Amount Type PR is:" - ], - "metadata": {} - }, - { - "id": "iWOEJ3tfb02n5-nhXKNWPg", - "cell_type": "code", - "source": [ - "var idCL = Test.GetIdentity(groupOfContract, \"CL\", \"C\");", - "\nidCL" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RxytwcSRIEOh4gnpLjM-6A", - "cell_type": "code", - "source": [ - "var computedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueCL_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "L0VyPzCrw02LlbNwi8lo6Q", - "cell_type": "markdown", - "source": [ - "According to the [formula](#present-values) above, for CL AoCType, the PVB is equal to the difference between the CDC of the current AoCType and the CDC of its parent(s). Additionally, the PPV is the $(\\text{S}+\\text{TS})$-th element of the PVB." - ], - "metadata": {} - }, - { - "id": "eWjL6y9C3k-py-95Mi0SJg", - "cell_type": "code", - "source": [ - "var clParents = Test.GetScope((idCL,\"PR\")).Values;", - "\nclParents" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "o7Xu2o42K0SylUpXrn5bIw", - "cell_type": "code", - "source": [ - "var expectedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values -", - "\n clParents.Select(aocStep => Test.GetScope((idCL with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, \"PR\", \"BE\", (int?)null)).Values).Aggregate();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "2Pzjvmq7BEGnPjDo-Jvo3g", - "cell_type": "markdown", - "source": [ - "The expected PVB and PPV are compared with the computed results in the following two cells: " - ], - "metadata": {} - }, - { - "id": "mJ3zeyh3YUSL7myhsdowKg", - "cell_type": "code", - "source": [ - "computedPresentValueCL_PR.Values.CheckEquality( expectedPresentValueCL_PR )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "t8dZLcMcYEiQaGohNjbhbw", - "cell_type": "code", - "source": [ - "computedPresentValueCL_PR.Value == expectedPresentValueCL_PR[3]" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CG2NuOh-OUWD0O9KjUlTKg", - "cell_type": "code", - "source": [ - "computedPresentValueCL_PR.Values.CheckEquality( expectedPresentValueCL_PR ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FNsLWW7W6UmZwW_agz-FbQ", - "cell_type": "code", - "source": [ - "computedPresentValueCL_PR.Value.Should().Be( expectedPresentValueCL_PR[3] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YAUW6hLjTkSDSB8hvqc-Ow", - "cell_type": "markdown", - "source": [ - "## End of Period" - ], - "metadata": {} - }, - { - "id": "ED73CBkcQkyvPg6_7eDFSg", - "cell_type": "markdown", - "source": [ - "The computed Present Value for Aoc type End of Period is:" - ], - "metadata": {} - }, - { - "id": "k3jsi34sxkSGoxKA1Btb1g", - "cell_type": "code", - "source": [ - "var idEOP = Test.GetIdentity(groupOfContract, \"EOP\", \"C\");", - "\nidEOP" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "s86AHJ-4Pk6Va461mh5gBQ", - "cell_type": "code", - "source": [ - "var computedPresentValueEOP_NIC = Test.GetScope((idEOP, \"NIC\", \"BE\", (int?)null));", - "\ncomputedPresentValueEOP_NIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QVXK0fUvN0-yuvBbKXPPrw", - "cell_type": "markdown", - "source": [ - "According to the [formula](#present-values) above, for EOP AoCType, the PVB is equal to the CDC of the parent AoC step, while the PPV is the $(\\text{S}+\\text{TS})$-th element of the PVB." - ], - "metadata": {} - }, - { - "id": "22vabLHnN0uty9-9BNNPNg", - "cell_type": "code", - "source": [ - "var eopReferenceAocStep = Test.GetScope(idEOP).Value;", - "\neopReferenceAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ECiuOq0oL0eK5tMnQpoHtg", - "cell_type": "code", - "source": [ - "var discountedCL_NIC = Test.GetScope((idEOP with {AocType = eopReferenceAocStep.AocType, Novelty = eopReferenceAocStep.Novelty}, \"NIC\", \"BE\", (int?)null));", - "\ndiscountedCL_NIC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TgfGcomxyEu_Bi31dr0a8Q", - "cell_type": "code", - "source": [ - "var expectedPresentValueEOP_NIC = discountedCL_NIC.Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "COrZzNoVR0uPcoTvusJl9A", - "cell_type": "markdown", - "source": [ - "The expected PVB and PPV are compared with the computed results in the following two cells: " - ], - "metadata": {} - }, - { - "id": "uHz3FD5pz0KtlPWvehPSTw", - "cell_type": "code", - "source": [ - "computedPresentValueEOP_NIC.Values.CheckEquality( expectedPresentValueEOP_NIC )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "NgccZKROIUGyHphm6Pt3mA", - "cell_type": "code", - "source": [ - "computedPresentValueEOP_NIC.Value == expectedPresentValueEOP_NIC[3]" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9jo2Z3ljfkyeYFEYk8YevQ", - "cell_type": "code", - "source": [ - "computedPresentValueEOP_NIC.Values.CheckEquality( expectedPresentValueEOP_NIC ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wQEKDnBmiEiCcxaQ5z8n_Q", - "cell_type": "code", - "source": [ - "computedPresentValueEOP_NIC.Value.Should().Be( expectedPresentValueEOP_NIC[3] );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TYv8HCkwJ0-eIPL5UgmkSg", - "cell_type": "markdown", - "source": [ - "## Check for zero PVB values" - ], - "metadata": {} - }, - { - "id": "ypVkZQiC50KtLKlrkxwfWA", - "cell_type": "markdown", - "source": [ - "### Amortization" - ], - "metadata": {} - }, - { - "id": "f6LQtXZHZE60NfgYXKiAmg", - "cell_type": "markdown", - "source": [ - "For AM AoCType, the PVB values are zero, i.e. Amortization is not part of the Present Value computation. In this subsection we check whether the corresponding values are zero accordingly. " - ], - "metadata": {} - }, - { - "id": "YmNDcj0tDEObggNuOxfFVg", - "cell_type": "code", - "source": [ - "var idAM = Test.GetIdentity(groupOfContract, \"AM\", \"C\");", - "\nidAM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Hbvbc_-ghkCPuBcY4CaNSw", - "cell_type": "code", - "source": [ - "var computedPresentValueAM_PR = Test.GetScope((idAM, \"PR\", \"BE\", (int?)null));", - "\ncomputedPresentValueAM_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vtA_SwM1FkWUvn7cz_gsEg", - "cell_type": "code", - "source": [ - "var computedPresentValueAM_PR = Test.GetScope((idAM, \"NIC\", \"BE\", (int?)null));", - "\ncomputedPresentValueAM_PR" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Hm9t12cEPEq0qfPXqqQKDA", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Amortization Factors" - ], - "metadata": {} - }, - { - "id": "HIn4-XNBlUC_ryCdXqFJXw", - "cell_type": "markdown", - "source": [ - "The amortization factors (AMF) are calculated from the corresponding Nominal and Discounted Cashflows with Calculation Type being *Coverage Units* (CU). ", - "\nThe monthly AMF is", - "\n", - "\n$$", - "\n\\text{AMF}^{\\text{Monthly}}_t = 1 - \\frac{ \\text{Nominal}^{\\text{Coverage Units}}_t } { \\text{CDC}^{\\text{Coverage Units}}_t } ~,", - "\n$$", - "\n", - "\nwhile the AMF related to the current period is", - "\n", - "\n$$", - "\n\\text{AMF} = \\prod _{t = \\text{S}}^{\\text{S}+\\text{TS}} \\text{AMF}^{\\text{Monthly}}_t ~.", - "\n$$", - "\n", - "\nwhere the shift S and Time Step TS for the [current period](#year-and-period) are" - ], - "metadata": {} - }, - { - "id": "GMNrVzKXH0ymV23dJDvYKQ", - "cell_type": "code", - "source": [ - "var projectionPeriod = 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YPFhl76CQkyB4G8ObloZRg", - "cell_type": "code", - "source": [ - "var shift = Test.GetStorage().GetShift(projectionPeriod);", - "\nshift" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-kXqVC_kq0CICZBKBb1HlQ", - "cell_type": "code", - "source": [ - "var timeStep = Test.GetStorage().GetTimeStep(projectionPeriod);", - "\ntimeStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "t4HaEWnCNk6mQabiDiws1w", - "cell_type": "markdown", - "source": [ - "## Monthly Amortization" - ], - "metadata": {} - }, - { - "id": "xeALkGs7xUeu3Y4WpeNO1Q", - "cell_type": "markdown", - "source": [ - "The computed monthly and current period Amortization Factors derived from a non-zero [imported](#year-and-period) nominal cashflows and its corresponding discounted are shown in the following" - ], - "metadata": {} - }, - { - "id": "L1ZjEB2bYkqJCYEQcSaCLA", - "cell_type": "code", - "source": [ - "var idAM = Test.GetIdentity(groupOfContract, \"CL\", \"C\");", - "\nidAM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "P_fB5G8CbkOe7_gqmr8nQA", - "cell_type": "code", - "source": [ - "var nominalCashflowAmortizationFactorTest = Test.GetScope( (idAM, default(string), \"CU\", (int?)null) );", - "\nnominalCashflowAmortizationFactorTest" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nwNr460Q5kO_3WOTIbp0qQ", - "cell_type": "code", - "source": [ - "var discountedCashflowAmortizationFactorTest = Test.GetScope(idAM);", - "\ndiscountedCashflowAmortizationFactorTest" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "uCI4iAP0DUGsPQOWdrwDuA", - "cell_type": "code", - "source": [ - "var computedMonthlyAmortizationFactor = Test.GetScope(idAM with {AocType = \"AM\"});", - "\ncomputedMonthlyAmortizationFactor" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gHcGaR3jfEWKUAK4D2kCVw", - "cell_type": "markdown", - "source": [ - "In the following cell we independently evaluate the expected monthly amortization factor according to the [formula above](#amortization-factor) and we check whether expected vs computed match" - ], - "metadata": {} - }, - { - "id": "I8F4XooarU6ejB9dIO3ByA", - "cell_type": "code", - "source": [ - "var expectedMonthlyAmortizationFactor = nominalCashflowAmortizationFactorTest.Values.Zip(discountedCashflowAmortizationFactorTest.Values, ", - "\n (nominal, discountedCumulated) => 1 - nominal / discountedCumulated ).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QwB0UIilbkK-CRTF-jWgEA", - "cell_type": "code", - "source": [ - "expectedMonthlyAmortizationFactor.RepeatOnce()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_66rpQUzrU-3wQQMLfLqTw", - "cell_type": "code", - "source": [ - "computedMonthlyAmortizationFactor.MonthlyAmortizationFactors.CheckEquality( expectedMonthlyAmortizationFactor )" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ibllj4WfMkCzKaaYRuhfmA", - "cell_type": "code", - "source": [ - "computedMonthlyAmortizationFactor.MonthlyAmortizationFactors.CheckEquality( expectedMonthlyAmortizationFactor ).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Jk9YlP6QCkqRxZo-o68MsA", - "cell_type": "markdown", - "source": [ - "## Current Period" - ], - "metadata": {} - }, - { - "id": "DTl5o5jz_0erzyZWFTpUHQ", - "cell_type": "markdown", - "source": [ - "The computed current period amortization factor is" - ], - "metadata": {} - }, - { - "id": "PCy8Dakbh0mPaY2sEWzjGg", - "cell_type": "code", - "source": [ - "var computedCurrentPeriodAmortizationFactor = Test.GetScope(idAM with {AocType = \"AM\"});", - "\ncomputedCurrentPeriodAmortizationFactor" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FdbZR9Yuy0-UNKH3vCixGw", - "cell_type": "markdown", - "source": [ - "Conversely, the current period Amortization factor can be independently computed using the [formula above](#amortization-factor) as" - ], - "metadata": {} - }, - { - "id": "w8ypGjX1wUGEjtCySuAp3w", - "cell_type": "code", - "source": [ - "var expectedCurrentPeriodAmortizationFactor = expectedMonthlyAmortizationFactor.Skip(shift).Take(timeStep).Aggregate(1d, (x, y) => x * y);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YwRfJmVI3UmwsjBL1JE48Q", - "cell_type": "code", - "source": [ - "expectedCurrentPeriodAmortizationFactor" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "33_7tRKRmUu9inImy1G2VQ", - "cell_type": "code", - "source": [ - "computedCurrentPeriodAmortizationFactor.Value == expectedCurrentPeriodAmortizationFactor" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rM6pE_9pL0SCB56yFBmlUA", - "cell_type": "code", - "source": [ - "computedCurrentPeriodAmortizationFactor.Value.Should().Be( expectedCurrentPeriodAmortizationFactor );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zJ4a8KsYUEWmMuBSKeJn0g", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Results persisted" - ], - "metadata": {} - }, - { - "id": "c4kFsHdrzEut20I1sKx5wQ", - "cell_type": "markdown", - "source": [ - "The last step during the Cashflow import is to save, namely *persist* the Present Values computed with *locked* (L) and *current* (C) economic basis, and calculation type being *Best Estimate* (BE). ", - "\n", - "\nThese data is the starting point of the [Contractual Service Margin calculation](\"SpecificationsCSM\")." - ], - "metadata": {} - }, - { - "id": "zco2828uiUeNWEkjLJSbmA", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False", + "toc-showtags": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Import Cashflows Specifications

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the calculation of the Present Values and Amortization Factors starting from the nominal Cashflows and the Yearly Yield Curve. These starting data is imported from the corresponding csv files located in the following path Initialization/Systemorph/. The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ] + }, + { + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Data" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month), Reporting Node, Economic Basis, and Data Node based on the imported data:" + ] + }, + { + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"C\" ;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Import the Dimensions, Yield Curves and Nominal Cashflows from the corresponding csv files in Initialization/Systemorph/" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "At this point reference data are loaded. Import now a cashfow file with a 720 elements." + ] + }, + { + "cell_type": "code", + "source": [ + "var groupOfContract = \"GricComplex\";", + "\nawait UploadCashflowsAsync(\"Data/CashflowComplex.csv\")" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Initialization of the Test suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ] + }, + { + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Data Nodes" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The imported active Data Nodes from Initialization/Systemorph/DataNodes.csv are " + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().DataNodeDataBySystemName" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Yearly Yield Curve" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here the correct Yield Curve is chosen among those imported from Initialization/Systemorph/Data.csv according to the [current period](#year-and-period) and the Aoc Step according the [Aoc Configuration](../DataModel/DataStructure#aoc-configuration). In the following we retrieve the desired identity." + ] + }, + { + "cell_type": "code", + "source": [ + "var aocType = \"CL\";", + "\nvar novelty = \"C\";" + ] + }, + { + "cell_type": "code", + "source": [ + "var id = Test.GetIdentity(groupOfContract, aocType, novelty);" + ] + }, + { + "cell_type": "code", + "source": [ + "var yearlyYieldCurve = Test.GetStorage().GetYearlyYieldCurve(id, economicBasis);" + ] + }, + { + "cell_type": "code", + "source": [ + "yearlyYieldCurve" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Nominal Cashflows" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The nominal Cashflows for the current period are loaded together with last period Cashflows for Group of Contract that were already existent. ", + "\n", + "\nThe relative files are located in: Files/.", + "\n", + "\nThe result is showed in the following list to be compared with the entries of the csv files" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetRawVariables(groupOfContract)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Interest and Discount Rates" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Yield Curve ${\\text{YC}_i}$ associated to the the [selected period](#year-and-period) and target currency of the Group of Contract Reporting Node is [displayed above](#view-loaded-yearly-yield-curve) and used in this section to calculate the Interest and Discount factors", + "\n", + "\n$$", + "\n\\text{Interest}_i = \\big( 1 + \\text{YC}_i \\big) ^{\\frac{1}{12}} ~,", + "\n$$", + "\n", + "\nand", + "\n", + "\n\\begin{align}", + "\n\\text{Discount}_i = \\big( 1 + \\text{YC}_i \\big) ^{-\\frac{1}{12}} ~.", + "\n\\end{align}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the Scope named *MonthlyRate* the Interest and Discount factors are computed" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedMonthlyRates = Test.GetScope( id );" + ] + }, + { + "cell_type": "code", + "source": [ + "computedMonthlyRates" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Interest" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the following, the Interest factors computed by the application are recalculated independently according to the formula above in two different ways" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedInterest = yearlyYieldCurve.Select( yc => (1 + yc)^( 1.0 / 12.0) );", + "\nexpectedInterest" + ] + }, + { + "cell_type": "code", + "source": [ + "from yc in yearlyYieldCurve select (1 + yc)^( 1.0 / 12.0 ) " + ] + }, + { + "cell_type": "code", + "source": [ + "computedMonthlyRates.Interest.CheckEquality( expectedInterest ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Discount" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The following recalculates the Discount factors to be compared with the computed values" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDiscount = yearlyYieldCurve.Select( yc => (1 + yc)^( -1.0 / 12.0) );", + "\nexpectedDiscount" + ] + }, + { + "cell_type": "code", + "source": [ + "computedMonthlyRates.Discount.CheckEquality( expectedDiscount ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Test method: Get Valid Element" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Given the present Yield Curve array has finite *length*, the extrapolation implemented is taking the last element for all successive years. This behavior is given by the function *GetValidElement*. The test in this section assures that constant extrapolation is taken for *index* > *length*" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDiscount.GetValidElement( 120 )" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDiscount.GetValidElement( 120 ).Should().Be( expectedDiscount.Last() );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n# Cashflows" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This section deals with the calculation of the *Cumulated Discounted Cashflows* (CDC) starting from the nominal Cashflows. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Choose identity" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Each loaded nominal Cashflows is assigned to a so-called *Identity* which uniquely identifies it based on the *Data Node*, *Aoc Type*, and *Novelty*. In the following cells we retrieve the desired Identity:" + ] + }, + { + "cell_type": "code", + "source": [ + "var aocType = \"CL\";", + "\nvar novelty = \"C\";" + ] + }, + { + "cell_type": "code", + "source": [ + "var id = Test.GetIdentity(groupOfContract, aocType, novelty);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Nominal Cashflow" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Consider the two Amount Type *PR* and *NIC*, with Transaction Period being *Beginning of Period* (BOP) and *End of Period* (EOP), respectively. The corresponding nominal Cashflows are deposited in the Scopes named *NominalCashflow* with the Identity provided above, Calculation Type *BE*, and the aforementioned Amount Types. These nominal Cashflows correspond with those [loaded from the csv files](#view-loaded-nominal-cashflows). " + ] + }, + { + "cell_type": "code", + "source": [ + "var amountTypePR = \"PR\";", + "\nvar amountTypeNIC = \"NIC\";", + "\nvar calculationType = \"BE\";", + "\nvar accidentYear = (int?)null;" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" + ] + }, + { + "cell_type": "code", + "source": [ + "nominalPR" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" + ] + }, + { + "cell_type": "code", + "source": [ + "nominalNIC" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Cumulated Discounted Cashflow" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The CDC is defined by the following recursive formulas", + "\n", + "\n$$", + "\n\\text{CDC}_t = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{Nominal}_t + \\text{CDC}_{t+1} \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} ~, & \\text{if Transaction Period is Beginning of Period} \\\\", + "\n\\big( \\text{Nominal}_t + \\text{CDC}_{t+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} ~, & \\text{if Transaction Period is End of Period}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the Transaction Period depends on the given cashflow Amount Type. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Beginning of Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Amount Type **Premiums** (PR) has Transaction Period **Beginning of Period** (BOP). The corresponding CDC calculated by the application is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDiscountedPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedPR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the following cell we independently evaluate the expected discounted cashflow according to the formula above:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDiscountedPR = new double[nominalPR.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalPR.Values.Length).Reverse()", + "\n .ForEach( i => expectedDiscountedPR[i] = nominalPR.Values[i] + expectedDiscountedPR.GetValidElement(i+1) * expectedDiscount.GetValidElement(i/12) );" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDiscountedPR" + ] + }, + { + "cell_type": "code", + "source": [ + "(nominalPR.Values, nominalPR.Values.Length)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected cumulated discount is compared with the computed values" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedPR.Values.CheckEquality( expectedDiscountedPR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedPR.Values.CheckEquality( expectedDiscountedPR ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### End Of Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Amount Type **Non Investment Component** (NIC) has Transaction Period **End of Period** (EOP). The corresponding CDC calculated by the application is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDiscountedNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedNIC" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the following cell we independently evaluate the expected discounted cashflow according to the formula above:" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDiscountedNIC = new double[nominalNIC.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalNIC.Values.Length).Reverse()", + "\n .ForEach( i => expectedDiscountedNIC[i] = ( nominalNIC.Values[i] + expectedDiscountedNIC.GetValidElement(i+1) ) * expectedDiscount.GetValidElement(i/12) );" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDiscountedNIC" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected cumulated discount is compared with the computed values" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedNIC.Values.CheckEquality( expectedDiscountedNIC )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedNIC.Values.CheckEquality( expectedDiscountedNIC ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Non Performance Risk Adjustment" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In this section we treat the determination of the non-performance risk adjustment, an element offsetting partially future", + "\nclaims according to the risk that the reinsurance company cannot fulfil the full extent of its obligations.", + "\n", + "\nFirstly, the discounting recursive relation can be written explicitly as", + "\n", + "\n$$", + "\n\\begin{array}{l}", + "\n\\text{CDC}_t = \\big( \\text{Nominal}_t + \\text{CDC}_{t+1} \\big) \\cdot {\\text{Valid Discount}_{\\frac{t}{12}}} \\\\", + "\n\\Rightarrow \\text{CDC}_t = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau ", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor nominal Cashflows with Amount Type being *Claims*, the risk-adjusted Cumulated Discounted Cashflow ", + "\nis assigned the Amount Type **Credit Default Risk** (CDR), ", + "\nand is obtained by multiplying the right hand side of the latter formula by the corresponding risk factor", + "\n", + "\n$$", + "\n\\text{CDC}_t^{\\text{Amount Type}=\\text{CDR}} = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau^{\\text{Claim}} \\cdot \\big( e^{-\\gamma(\\tau-t)} -1 \\big)", + "\n$$", + "\n", + "\nwhere $\\gamma$ is the assumed non-performance probability of the reinsurer to be provided as an [input parameter](../DataModel/DataStructure#credit-default-rate).", + "\n", + "\nThis rate is constant for the whole projection period, that is, $\\gamma$ is not a function of $t$. ", + "\nIt effectively amounts to a constant increase in the continuous discount rate by $\\gamma$. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Explicit vs recursive formula" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The explicit formula is tested versus the expected result obtained with the recursive formula" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDiscountedNICbis = new double[nominalNIC.Values.Length];", + "\n", + "\n//for(int t = 0; t < 12; t++)", + "\n// for(int tau = t; tau < 12; tau++)", + "\n// expectedDiscountedNICbis[t] += nominalNIC.Values[tau] * Math.Pow(expectedDiscount.GetValidElement(t/12), tau-t+1);", + "\n", + "\nEnumerable.Range(0, nominalNIC.Values.Length)", + "\n .ForEach( i => expectedDiscountedNICbis[i] = ", + "\n Enumerable.Range(i, nominalNIC.Values.Length-i).Select( tau => nominalNIC.Values[tau] * Math.Pow(expectedDiscount.GetValidElement(i/12), tau-i+1) ).Sum() );", + "\n ", + "\nexpectedDiscountedNIC.CheckEquality( expectedDiscountedNICbis )" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Risk Adjusted Claims " + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed CDC with Amount Type being CDR reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDiscountedCRD = Test.GetScope((id, \"CDR\", calculationType, accidentYear));" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedCRD" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The starting point for the non performance risk adjustment is the computation of the sum of nominal Cashflows with Amount Type **Claims** listed below" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetClaims()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "with the corresponding nominal Cashflows being" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalNIC = Test.GetScope((id, \"NIC\", calculationType, accidentYear));", + "\nnominalNIC" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalICO = Test.GetScope((id, \"ICO\", calculationType, accidentYear));", + "\nnominalICO" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalALE = Test.GetScope((id, \"ALE\", calculationType, accidentYear));", + "\nnominalNIC" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalULE = Test.GetScope((id, \"ULE\", calculationType, accidentYear));", + "\nnominalNIC" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalClaims = nominalICO.Values + nominalNIC.Values + nominalALE.Values + nominalULE.Values;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Secondly, the correct credit risk rate (parameter $\\gamma$ in the [formula above](#non-performance-risk-adjustment)) is retrieved from the list of imported [Partner Rating](../DataModel/DataStructure) and [Credit Default Rates](../DataModel/DataStructure) relative to the target [Data Node](#year-and-period)'s Partner" + ] + }, + { + "cell_type": "code", + "source": [ + "groupOfContract" + ] + }, + { + "cell_type": "code", + "source": [ + "var creditDefaultRate = Test.GetStorage().GetNonPerformanceRiskRate( id );", + "\ncreditDefaultRate" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Lastly, using the [formula above](#non-performance-risk-adjustment), the expected CDR discounted Cashflow can be computed" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDiscountedCDR = new double[nominalNIC.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalClaims.Length).ForEach( t => ", + "\n expectedDiscountedCDR[t] = Enumerable.Range(t, nominalClaims.Length-t).Select( tau => ", + "\n nominalClaims[tau] * Math.Pow(expectedDiscount.GetValidElement(t/12), tau-t+1) * (Math.Exp(-creditDefaultRate*(tau-t)) - 1)", + "\n ).Sum() );", + "\n", + "\nexpectedDiscountedCDR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Finally, the expected cumulated discount is compared with the computed values" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedCRD.Values.CheckEquality( expectedDiscountedCDR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDiscountedCRD.Values.CheckEquality( expectedDiscountedCDR ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Present Values" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For an implementation of these formulas refer to the [ImportScopeCalculation notebook](../Import/ImportScopeCalculation). " + ] + }, + { + "cell_type": "markdown", + "source": [ + "The company portfolio value in one period is given by the following Analysis of Change AoC steps:", + "\n1. Beginning of Period (BoP): starting value of the portfolio as of December last year (in the Year to Date view), ", + "\n2. Model Corrections (MC): change of the portfolio value based on the model change,", + "\n3. Cash Flow (CF):", + "\n4. Interest Accretion (IA): ", + "\n5. Assumption Update (AU): ", + "\n6. Yield Curve Update (YCU): impact of yield curve update occured during the reporting period,", + "\n7. Credit Risk Update (CRU): impact of credit default rate update occured during the reporting period,", + "\n8. Experience Variance (EV): value adjustments following insurance related events which took place (e.g. mortality),", + "\n9. Combined Liabilities (CL):", + "\n10. End of Period (EOP): portfolio value at the end of the current period.", + "\n", + "\nNote: the AoC steps WO, EA and AM are not included in the Present Value calculation, hence their values if inquired is zero." + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Present Value Base (PVB) values are valid for all [Economic Basis](../DataModel/DataStructure#economic-basis) and depends on the corresponding [AoCType](../DataModel/DataStructure#aoc-type):", + "\n", + "\n$$", + "\n\\text{PVB}_t \\big(\\text{AoC}\\big) = ", + "\n\\left\\{", + "\n\\begin{array}{cl}", + "\n\\text{CDC}_t & \\text{if AoC is Beginning of Period (BOP) } \\\\", + "\n-\\text{Nominal}_t(\\text{Parent AoC}) & \\text{if AoC is Expected Cashflow (CF) } \\\\", + "\n\\text{InterestAccretion}_t & \\text{if AoC is Interest Accretion (IA) } \\\\", + "\n\\text{CDC}_t(\\text{Parent AoC}) & \\text{if AoC is End of Period (EOP) } \\\\", + "\n\\text{CDC}_{t}(\\text{current AoC}) - \\text{CDC}_{t}(\\text{parent AoC}) & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nand the Projected Present Value (PPV) reads", + "\n", + "\n$$", + "\n\\text{PPV} \\big(\\text{AoC},\\text{TS},\\text{S}\\big) = \\left\\{", + "\n\\begin{array}{cll}", + "\n\\text{PVB}_{S} & \\text{if AoC Valuation Period is Beginning of Period } & \\text{ (e.g. BOP, MC) } \\\\", + "\n\\text{PVB}_{S+TS/2 -1} & \\text{if AoC Valuation Period is Mid of Period } & \\text{ (no examples in current data model) } \\\\", + "\n\\sum_{i=S}^{S + TS -1}\\text{PVB}_{i} & \\text{if AoC Valuation Period is Delta } & \\text{ (e.g. CF, IA) } \\\\", + "\n\\text{PVB}_{S + TS} & \\text{if AoC Valuation Period is End of Period } & \\text{ (e.g. YCU, CRU, EV, CL, EOP) } \\\\", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere the Shift (S) and Time Step (TS) are derived from the current [Year and Period](#year-and-period)" + ] + }, + { + "cell_type": "code", + "source": [ + "var projectionPeriod = 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetShift(projectionPeriod)" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetTimeStep(projectionPeriod)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Load Cashflow Data" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "At this point standard Cashflows are loaded." + ] + }, + { + "cell_type": "markdown", + "source": [ + "Initialization of the Test suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ] + }, + { + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Select Group of Contract", + "\n", + "\nHere, it is possible to select the Group of Contract used to run the next section of this Notebook." + ] + }, + { + "cell_type": "code", + "source": [ + "groupOfContract = \"DTR1.1\" ;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Beginning of Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Beginning of Period is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idBoP = Test.GetIdentity(groupOfContract, \"BOP\", \"I\");", + "\nidBoP" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueBoP_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, the expected BOP AoCType for PVB is defined to be equal to the discounted cashflows with the same Identity, Amount Type, and Calculation Type, whereas the PPV is the S-th element of the PVB." + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedBoP_PR = Test.GetScope((idBoP, \"PR\", \"BE\", (int?)null));", + "\ndiscountedBoP_PR" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueBoP_PR = discountedBoP_PR.Values;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the following cell we check whether the expected values match the computed values" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueBoP_PR.Values.CheckEquality( expectedPresentValueBoP_PR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueBoP_PR.Values.CheckEquality( expectedPresentValueBoP_PR ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Model Corrections" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Model Corrections is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idMC = Test.GetIdentity(groupOfContract, \"MC\", \"I\");", + "\nidMC" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueMC_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for MC AoCType, the PVB is equal to the difference between the CDC of the current AoCType and the CDC of its parent. Additionally, the PPV is the S-th element of the PVB." + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetScope((idMC, \"PR\")).Values" + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedMC_PR = Test.GetScope((idMC, \"PR\", \"BE\", (int?)null));", + "\ndiscountedMC_PR" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueMC_PR = discountedMC_PR.Values - discountedBoP_PR.Values;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueMC_PR.Values.CheckEquality( expectedPresentValueMC_PR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueMC_PR.Value == expectedPresentValueMC_PR[0]" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueMC_PR.Values.CheckEquality( expectedPresentValueMC_PR ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueMC_PR.Value.Should().Be( expectedPresentValueMC_PR[0] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Cashflow" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Cashflow is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idCF = Test.GetIdentity(groupOfContract, \"CF\", \"I\");", + "\nidCF" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueCF_PR = Test.GetScope((idCF, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueCF_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for CF AoCType, the PVB is equal to the nominal cashflow of its parent AoC step with opposite sign. The PPV is given by the sum of the first 3 elements." + ] + }, + { + "cell_type": "code", + "source": [ + "var cfReferenceAocStep = Test.GetScope(idCF).Value;", + "\ncfReferenceAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var cfNominalReference_PR = Test.GetScope((idCF with {AocType = cfReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", + "\ncfNominalReference_PR" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueCF_PR = -1.0 * cfNominalReference_PR.Values;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCF_PR.Values.CheckEquality( expectedPresentValueCF_PR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCF_PR.Values[0] + computedPresentValueCF_PR.Values[1] + computedPresentValueCF_PR.Values[2] == computedPresentValueCF_PR.Value" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCF_PR.Values.CheckEquality( expectedPresentValueCF_PR ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCF_PR.Value.Should().Be( computedPresentValueCF_PR.Values[0] + computedPresentValueCF_PR.Values[1] + computedPresentValueCF_PR.Values[2] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Interest Accretion" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For IA AoCType, the PVB is given by the following relation ", + "\n", + "\n$$", + "\n\\text{InterestAccretion}_i = \\left\\{", + "\n\\begin{array}{cl}", + "\n\\big(\\text{CDC}_i(\\text{Parent AoC}) - \\text{Nominal}_i(\\text{parent AoC}) \\big) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, ", + "\n & \\text{if AmountType Transaction Period is Beginning of Period} \\\\", + "\n\\text{CDC}_i(\\text{parent AoC}) \\cdot \\big({\\text{Valid Interest}_{\\frac{i}{12}}} - 1 \\big)~, ", + "\n & \\text{otherwise}", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhile the PPV is given by the sum of the first S elements.", + "\n", + "\nWhen selecting the Identity, note that the Novelty *C* is not contemplated for Interest Accretion." + ] + }, + { + "cell_type": "code", + "source": [ + "var idIA = Test.GetIdentity(groupOfContract, \"IA\", \"I\");", + "\nidIA" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Amount Type BOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Amount Type **Premiums** (PR) with Transaction Period **Beginning of Period** (BOP) is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueIA_PR = Test.GetScope((idIA, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueIA_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the interest factors, the nominal and discounted Cashflow of the parent Aoc Step" + ] + }, + { + "cell_type": "code", + "source": [ + "var iaComputedMonthlyRates = Test.GetScope( idIA );", + "\niaComputedMonthlyRates" + ] + }, + { + "cell_type": "code", + "source": [ + "var iaReferenceAocStep = Test.GetScope(idIA).Value;", + "\niaReferenceAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalIaReference_PR = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", + "\nnominalIaReference_PR" + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedIaReference_PR = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"PR\", \"BE\", (int?)null));", + "\ndiscountedIaReference_PR" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueIA_PR = discountedIaReference_PR.Values.Select((val, index) => ( val - nominalIaReference_PR.Values[index]) * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_PR.Values.CheckEquality( expectedPresentValueIA_PR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_PR.Values[0] + computedPresentValueIA_PR.Values[1] + computedPresentValueIA_PR.Values[2] == computedPresentValueIA_PR.Value" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_PR.Values.CheckEquality( expectedPresentValueIA_PR ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_PR.Value.Should().Be( computedPresentValueIA_PR.Values[0] + computedPresentValueIA_PR.Values[1] + computedPresentValueIA_PR.Values[2] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Amount Type EOP" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Amount Type **Non Investment Component** (NIC) with Transaction Period **End of Period** (EOP) is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueIA_NIC = Test.GetScope((idIA, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPresentValueIA_NIC" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the interest monthly rates, the discounted Cashflow of the parent Aoc Step" + ] + }, + { + "cell_type": "code", + "source": [ + "var iaReferenceAocStep = Test.GetScope(idIA).Value;", + "\niaReferenceAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedIaReference_NIC = Test.GetScope((idIA with {AocType = iaReferenceAocStep.AocType}, \"NIC\", \"BE\", (int?)null));", + "\ndiscountedIaReference_NIC" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueIA_NIC = discountedIaReference_NIC.Values.Select((val, index) => val * ( iaComputedMonthlyRates.Interest.GetValidElement(index/12) -1));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_NIC.Values.CheckEquality( expectedPresentValueIA_NIC )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_NIC.Values[0] + computedPresentValueIA_NIC.Values[1] + computedPresentValueIA_NIC.Values[2] == computedPresentValueIA_NIC.Value" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_NIC.Values.CheckEquality( expectedPresentValueIA_NIC ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueIA_NIC.Value.Should().Be( computedPresentValueIA_NIC.Values[0] + computedPresentValueIA_NIC.Values[1] + computedPresentValueIA_NIC.Values[2] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Yield Curve Update" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Yield Curve Update is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idYcu = Test.GetIdentity(groupOfContract, \"YCU\", \"I\");", + "\nidYcu" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueYCU_PR = Test.GetScope((idYcu, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueYCU_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently following the aforementioned [equation](#interest-accretion) starting from the discount factors for beginning of period and for end of period applied to the reference Aoc step, followed by the difference between the CDC obtained with end of period discount factor and the CDC obtained with beginning of period discount factor. " + ] + }, + { + "cell_type": "code", + "source": [ + "var ycReferenceAocStep = Test.GetScope(idYcu).Value;", + "\nycReferenceAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var ycParentAocStep = Test.GetScope((idYcu, \"PR\")).Values.Single();", + "\nycParentAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var ycParentId = idYcu with {AocType = ycParentAocStep.AocType, Novelty = ycParentAocStep.Novelty};", + "\nycParentId" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here is the parent AocStep discounted with the beginning of period discount factor." + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedYcParent = Test.GetScope((ycParentId, \"PR\", \"BE\", (int?)null));", + "\ndiscountedYcParent" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here we independently compute the CDC of the parent AocStep discounted with end of period discount factor." + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalYcParent = Test.GetScope((ycParentId, \"PR\", \"BE\", (int?)null));", + "\nnominalYcParent" + ] + }, + { + "cell_type": "code", + "source": [ + "var ycComputedMonthlyRates = Test.GetScope( idYcu );", + "\nycComputedMonthlyRates" + ] + }, + { + "cell_type": "code", + "source": [ + "var ycReferenceDiscountedEop = new double[nominalYcParent.Values.Length];", + "\n", + "\nEnumerable.Range(0, nominalYcParent.Values.Length).Reverse()", + "\n .ForEach( i => ycReferenceDiscountedEop[i] = nominalYcParent.Values[i] + ycReferenceDiscountedEop.GetValidElement(i+1) * ycComputedMonthlyRates.Discount.GetValidElement(i/12) );", + "\nycReferenceDiscountedEop" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueYCU_PR = ycReferenceDiscountedEop - discountedYcParent.Values;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueYCU_PR.Values.CheckEquality( expectedPresentValueYCU_PR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueYCU_PR.Value == expectedPresentValueYCU_PR[3]" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueYCU_PR.Values.CheckEquality( expectedPresentValueYCU_PR ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueYCU_PR.Value.Should().Be( expectedPresentValueYCU_PR[3] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Credit Risk Update" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This Aoc Step is relevant only in the case of a Group of Reinsurance Contract." + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Credit Risk Update is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idCru = Test.GetIdentity(groupOfContract, \"CRU\", \"I\");", + "\nidCru" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueCRU = Test.GetScope((idCru, \"CDR\", \"BE\", (int?)null));", + "\ncomputedPresentValueCRU" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Present Value can be recomputed independently starting as the difference between the CDC obtained with end of period credit default risk rate and the CDC obtained with beginning of period credit default risk rate, both computed using the Nominal cashflow of the reference Aoc Step and the End Of Period discounting factors. " + ] + }, + { + "cell_type": "code", + "source": [ + "var cruReferenceAocStep = Test.GetScope(idCru).Value;", + "\ncruReferenceAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var cruReferenceId = idCru with {AocType = cruReferenceAocStep.AocType, Novelty = cruReferenceAocStep.Novelty};", + "\ncruReferenceId" + ] + }, + { + "cell_type": "code", + "source": [ + "var cruParentAocStep = Test.GetScope((idCru, \"CDR\")).Values.Single();", + "\ncruParentAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var cruParentId = idCru with {AocType = cruParentAocStep.AocType, Novelty = cruParentAocStep.Novelty};", + "\ncruParentId" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here is the parent AocStep discounted with beginning of period credit default risk rate." + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedCruParent = Test.GetScope((cruParentId, \"CDR\", \"BE\", (int?)null));", + "\ndiscountedCruParent" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalCruReference = Test.GetScope((cruReferenceId, \"CDR\", \"BE\", (int?)null)).Values;", + "\nnominalCruReference" + ] + }, + { + "cell_type": "code", + "source": [ + "var creditDefaultRate = Test.GetStorage().GetNonPerformanceRiskRate( idCru );", + "\ncreditDefaultRate" + ] + }, + { + "cell_type": "code", + "source": [ + "var cruComputedMonthlyRates = Test.GetScope( idCru );", + "\ncruComputedMonthlyRates" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Lastly, using the [formula above](#non-performance-risk-adjustment), the expected CDR discounted Cashflow can be computed" + ] + }, + { + "cell_type": "code", + "source": [ + "var cruExpectedDiscountedCDR = new double[nominalCruReference.Length];", + "\n", + "\nEnumerable.Range(0, nominalCruReference.Length).ForEach( t => ", + "\n cruExpectedDiscountedCDR[t] = Enumerable.Range(t, nominalCruReference.Length-t).Select( tau => ", + "\n nominalCruReference[tau] * ", + "\n Math.Pow(cruComputedMonthlyRates.Discount.GetValidElement(t/12), tau-t+1) * ", + "\n (Math.Exp(-creditDefaultRate*(tau-t)) - 1)", + "\n ).Sum() );", + "\n", + "\ncruExpectedDiscountedCDR" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueCRU = cruExpectedDiscountedCDR - discountedCruParent.Values;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCRU.Values.CheckEquality( expectedPresentValueCRU )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCRU.Value == expectedPresentValueCRU[3]" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCRU.Values.CheckEquality( expectedPresentValueCRU ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCRU.Value.Should().Be( expectedPresentValueCRU[3] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Combined Liabilities" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type Combined Liabilities and Amount Type PR is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idCL = Test.GetIdentity(groupOfContract, \"CL\", \"C\");", + "\nidCL" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueCL_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for CL AoCType, the PVB is equal to the difference between the CDC of the current AoCType and the CDC of its parent(s). Additionally, the PPV is the $(\\text{S}+\\text{TS})$-th element of the PVB." + ] + }, + { + "cell_type": "code", + "source": [ + "var clParents = Test.GetScope((idCL,\"PR\")).Values;", + "\nclParents" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values -", + "\n clParents.Select(aocStep => Test.GetScope((idCL with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, \"PR\", \"BE\", (int?)null)).Values).Aggregate();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCL_PR.Values.CheckEquality( expectedPresentValueCL_PR )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCL_PR.Value == expectedPresentValueCL_PR[3]" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCL_PR.Values.CheckEquality( expectedPresentValueCL_PR ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueCL_PR.Value.Should().Be( expectedPresentValueCL_PR[3] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## End of Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed Present Value for Aoc type End of Period is:" + ] + }, + { + "cell_type": "code", + "source": [ + "var idEOP = Test.GetIdentity(groupOfContract, \"EOP\", \"C\");", + "\nidEOP" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueEOP_NIC = Test.GetScope((idEOP, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPresentValueEOP_NIC" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#present-values) above, for EOP AoCType, the PVB is equal to the CDC of the parent AoC step, while the PPV is the $(\\text{S}+\\text{TS})$-th element of the PVB." + ] + }, + { + "cell_type": "code", + "source": [ + "var eopReferenceAocStep = Test.GetScope(idEOP).Value;", + "\neopReferenceAocStep" + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedCL_NIC = Test.GetScope((idEOP with {AocType = eopReferenceAocStep.AocType, Novelty = eopReferenceAocStep.Novelty}, \"NIC\", \"BE\", (int?)null));", + "\ndiscountedCL_NIC" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedPresentValueEOP_NIC = discountedCL_NIC.Values;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The expected PVB and PPV are compared with the computed results in the following two cells: " + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueEOP_NIC.Values.CheckEquality( expectedPresentValueEOP_NIC )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueEOP_NIC.Value == expectedPresentValueEOP_NIC[3]" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueEOP_NIC.Values.CheckEquality( expectedPresentValueEOP_NIC ).Should().Be(true);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedPresentValueEOP_NIC.Value.Should().Be( expectedPresentValueEOP_NIC[3] );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Check for zero PVB values" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Amortization" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For AM AoCType, the PVB values are zero, i.e. Amortization is not part of the Present Value computation. In this subsection we check whether the corresponding values are zero accordingly. " + ] + }, + { + "cell_type": "code", + "source": [ + "var idAM = Test.GetIdentity(groupOfContract, \"AM\", \"C\");", + "\nidAM" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueAM_PR = Test.GetScope((idAM, \"PR\", \"BE\", (int?)null));", + "\ncomputedPresentValueAM_PR" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedPresentValueAM_PR = Test.GetScope((idAM, \"NIC\", \"BE\", (int?)null));", + "\ncomputedPresentValueAM_PR" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Amortization Factors" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The amortization factors (AMF) are calculated from the corresponding Nominal and Discounted Cashflows with Calculation Type being *Coverage Units* (CU). ", + "\nThe monthly AMF is", + "\n", + "\n$$", + "\n\\text{AMF}^{\\text{Monthly}}_t = 1 - \\frac{ \\text{Nominal}^{\\text{Coverage Units}}_t } { \\text{CDC}^{\\text{Coverage Units}}_t } ~,", + "\n$$", + "\n", + "\nwhile the AMF related to the current period is", + "\n", + "\n$$", + "\n\\text{AMF} = \\prod _{t = \\text{S}}^{\\text{S}+\\text{TS}} \\text{AMF}^{\\text{Monthly}}_t ~.", + "\n$$", + "\n", + "\nwhere the shift S and Time Step TS for the [current period](#year-and-period) are" + ] + }, + { + "cell_type": "code", + "source": [ + "var projectionPeriod = 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var shift = Test.GetStorage().GetShift(projectionPeriod);", + "\nshift" + ] + }, + { + "cell_type": "code", + "source": [ + "var timeStep = Test.GetStorage().GetTimeStep(projectionPeriod);", + "\ntimeStep" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Monthly Amortization" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed monthly and current period Amortization Factors derived from a non-zero [imported](#year-and-period) nominal cashflows and its corresponding discounted are shown in the following" + ] + }, + { + "cell_type": "code", + "source": [ + "var idAM = Test.GetIdentity(groupOfContract, \"CL\", \"C\");", + "\nidAM" + ] + }, + { + "cell_type": "code", + "source": [ + "var nominalCashflowAmortizationFactorTest = Test.GetScope( (idAM, default(string), \"CU\", (int?)null) );", + "\nnominalCashflowAmortizationFactorTest" + ] + }, + { + "cell_type": "code", + "source": [ + "var discountedCashflowAmortizationFactorTest = Test.GetScope(idAM);", + "\ndiscountedCashflowAmortizationFactorTest" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedMonthlyAmortizationFactor = Test.GetScope(idAM with {AocType = \"AM\"});", + "\ncomputedMonthlyAmortizationFactor" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In the following cell we independently evaluate the expected monthly amortization factor according to the [formula above](#amortization-factor) and we check whether expected vs computed match" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedMonthlyAmortizationFactor = nominalCashflowAmortizationFactorTest.Values.Zip(discountedCashflowAmortizationFactorTest.Values, ", + "\n (nominal, discountedCumulated) => 1 - nominal / discountedCumulated ).ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedMonthlyAmortizationFactor.RepeatOnce()" + ] + }, + { + "cell_type": "code", + "source": [ + "computedMonthlyAmortizationFactor.MonthlyAmortizationFactors.CheckEquality( expectedMonthlyAmortizationFactor )" + ] + }, + { + "cell_type": "code", + "source": [ + "computedMonthlyAmortizationFactor.MonthlyAmortizationFactors.CheckEquality( expectedMonthlyAmortizationFactor ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Current Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed current period amortization factor is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedCurrentPeriodAmortizationFactor = Test.GetScope(idAM with {AocType = \"AM\"});", + "\ncomputedCurrentPeriodAmortizationFactor" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Conversely, the current period Amortization factor can be independently computed using the [formula above](#amortization-factor) as" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedCurrentPeriodAmortizationFactor = expectedMonthlyAmortizationFactor.Skip(shift).Take(timeStep).Aggregate(1d, (x, y) => x * y);" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedCurrentPeriodAmortizationFactor" + ] + }, + { + "cell_type": "code", + "source": [ + "computedCurrentPeriodAmortizationFactor.Value == expectedCurrentPeriodAmortizationFactor" + ] + }, + { + "cell_type": "code", + "source": [ + "computedCurrentPeriodAmortizationFactor.Value.Should().Be( expectedCurrentPeriodAmortizationFactor );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Results persisted" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The last step during the Cashflow import is to save, namely *persist* the Present Values computed with *locked* (L) and *current* (C) economic basis, and calculation type being *Best Estimate* (BE). ", + "\n", + "\nThese data is the starting point of the [Contractual Service Margin calculation](\"SpecificationsCSM\")." + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb index 96e7025a..d112b3d2 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/Test/SpecificationsSetup.ipynb @@ -1,137 +1,125 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "fE38qOjHW0a08mH8kJrwSg", - "cell_type": "code", - "source": [ - "#!import \"../Import/ImportScopeCalculation\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9xNRIpaJukO9dK_x-P6MAg", - "cell_type": "code", - "source": [ - "public interface Universe : IMutableScopeWithStorage{}", - "\n", - "\npublic async Task StartCalculatorAsync(string reportingNode, int year, int month, string economicBasis, Periodicity period, string format) ", - "\n{", - "\n ", - "\n var importArgs = new ImportArgs(reportingNode, year, month, period, null, format);", - "\n Workspace.Reset();", - "\n Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization());", - "\n", - "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == importArgs.ReportingNode &&", - "\n p.Year == importArgs.Year &&", - "\n p.Month == importArgs.Month &&", - "\n p.Scenario == importArgs.Scenario", - "\n ).ToArrayAsync()).Single().Id;", - "\n await DataSource.Partition.SetAsync(partition);", - "\n", - "\n //Set Workspace as when the parsing is completed.", - "\n if(importArgs.ImportFormat == ImportFormats.Actual)", - "\n { ", - "\n await Workspace.UpdateAsync(await DataSource.Query()", - "\n .Where(x => x.Partition == partition && ", - "\n new string[]{EstimateTypes.A, EstimateTypes.AA, EstimateTypes.OA}.Contains(x.EstimateType) && ", - "\n new string[]{AocTypes.CF, AocTypes.WO}.Contains(x.AocType))", - "\n .ToArrayAsync());", - "\n }", - "\n else if(importArgs.ImportFormat == ImportFormats.Opening)", - "\n { ", - "\n await Workspace.UpdateAsync(await DataSource.Query()", - "\n .Where(x => x.Partition == partition && ", - "\n new string[]{ EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.DA}.Contains(x.EstimateType) && ", - "\n x.AocType == AocTypes.BOP && x.Novelty == Novelties.I)", - "\n .ToArrayAsync());", - "\n }", - "\n else", - "\n {", - "\n await Workspace.UpdateAsync(await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync());", - "\n }", - "\n var storage = new ImportStorage(importArgs, DataSource, Workspace);", - "\n await storage.InitializeAsync();", - "\n return Scopes.ForStorage(storage).WithContext(economicBasis).ToScope();", - "\n}", - "\n", - "\npublic static ImportIdentity GetIdentity (this Universe universe, string dataNode, string aocType, string novelty) ", - "\n => universe.GetScope(dataNode).Identities.Single( x => x.AocType == aocType && x.Novelty == novelty );", - "\n", - "\nstatic T GetValidElement(this IList array, int index) => GetElementOrDefault(array, index);", - "\n", - "\nstatic T GetValidElement(this IEnumerable array, int index) => GetElementOrDefault(array.ToArray(), index);", - "\n", - "\nstatic void ForEach(this IEnumerable self, Action action) => self.ToList().ForEach(action);", - "\n", - "\npublic static IfrsVariable FromPvToIfrsVariable(this PresentValue scope)", - "\n => new IfrsVariable{ EconomicBasis = scope.EconomicBasis, ", - "\n EstimateType = scope.Identity.CalculationType, ", - "\n DataNode = scope.Identity.Id.DataNode, ", - "\n AocType = scope.Identity.Id.AocType, ", - "\n Novelty = scope.Identity.Id.Novelty, ", - "\n AccidentYear = scope.Identity.AccidentYear,", - "\n AmountType = scope.Identity.AmountType,", - "\n Value = scope.Value,", - "\n Partition = scope.GetStorage().TargetPartition };", - "\n", - "\npublic static IfrsVariable FromCsmToIfrsVariable(this Csm scope)", - "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", - "\n DataNode = scope.Identity.DataNode, ", - "\n AocType = scope.Identity.AocType, ", - "\n Novelty = scope.Identity.Novelty, ", - "\n Value = scope.Value,", - "\n Partition = scope.GetStorage().TargetPartition };", - "\n", - "\npublic static IfrsVariable FromLcToIfrsVariable(this Lc scope)", - "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", - "\n DataNode = scope.Identity.DataNode, ", - "\n AocType = scope.Identity.AocType, ", - "\n Novelty = scope.Identity.Novelty, ", - "\n Value = scope.Value,", - "\n Partition = scope.GetStorage().TargetPartition };", - "\n", - "\npublic static IfrsVariable FromLoReCoToIfrsVariable(this LoReCo scope)", - "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", - "\n DataNode = scope.Identity.DataNode, ", - "\n AocType = scope.Identity.AocType, ", - "\n Novelty = scope.Identity.Novelty, ", - "\n Value = scope.Value,", - "\n Partition = scope.GetStorage().TargetPartition };" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nbL-Fjewnk-tw5Vk1IJ2rg", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../Import/ImportScopeCalculation\"" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface Universe : IMutableScopeWithStorage{}", + "\n", + "\npublic async Task StartCalculatorAsync(string reportingNode, int year, int month, string economicBasis, Periodicity period, string format) ", + "\n{", + "\n ", + "\n var importArgs = new ImportArgs(reportingNode, year, month, period, null, format);", + "\n Workspace.Reset();", + "\n Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());", + "\n", + "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == importArgs.ReportingNode &&", + "\n p.Year == importArgs.Year &&", + "\n p.Month == importArgs.Month &&", + "\n p.Scenario == importArgs.Scenario", + "\n ).ToArrayAsync()).Single().Id;", + "\n await DataSource.Partition.SetAsync(partition);", + "\n", + "\n //Set Workspace as when the parsing is completed.", + "\n if(importArgs.ImportFormat == ImportFormats.Actual)", + "\n { ", + "\n await Workspace.UpdateAsync(await DataSource.Query()", + "\n .Where(x => x.Partition == partition && ", + "\n new string[]{EstimateTypes.A, EstimateTypes.AA, EstimateTypes.OA}.Contains(x.EstimateType) && ", + "\n new string[]{AocTypes.CF, AocTypes.WO}.Contains(x.AocType))", + "\n .ToArrayAsync());", + "\n }", + "\n else if(importArgs.ImportFormat == ImportFormats.Opening)", + "\n { ", + "\n await Workspace.UpdateAsync(await DataSource.Query()", + "\n .Where(x => x.Partition == partition && ", + "\n new string[]{ EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.DA}.Contains(x.EstimateType) && ", + "\n x.AocType == AocTypes.BOP && x.Novelty == Novelties.I)", + "\n .ToArrayAsync());", + "\n }", + "\n else", + "\n {", + "\n await Workspace.UpdateAsync(await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync());", + "\n }", + "\n var storage = new ImportStorage(importArgs, DataSource, Workspace);", + "\n await storage.InitializeAsync();", + "\n return Scopes.ForStorage(storage).WithContext(economicBasis).ToScope();", + "\n}", + "\n", + "\npublic static ImportIdentity GetIdentity (this Universe universe, string dataNode, string aocType, string novelty) ", + "\n => universe.GetScope(dataNode).Identities.Single( x => x.AocType == aocType && x.Novelty == novelty );", + "\n", + "\nstatic T GetValidElement(this IList array, int index) => GetElementOrDefault(array, index);", + "\n", + "\nstatic T GetValidElement(this IEnumerable array, int index) => GetElementOrDefault(array.ToArray(), index);", + "\n", + "\nstatic void ForEach(this IEnumerable self, Action action) => self.ToList().ForEach(action);", + "\n", + "\npublic static IfrsVariable FromPvToIfrsVariable(this PresentValue scope)", + "\n => new IfrsVariable{ EconomicBasis = scope.EconomicBasis, ", + "\n EstimateType = scope.Identity.CalculationType, ", + "\n DataNode = scope.Identity.Id.DataNode, ", + "\n AocType = scope.Identity.Id.AocType, ", + "\n Novelty = scope.Identity.Id.Novelty, ", + "\n AccidentYear = scope.Identity.AccidentYear,", + "\n AmountType = scope.Identity.AmountType,", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };", + "\n", + "\npublic static IfrsVariable FromCsmToIfrsVariable(this Csm scope)", + "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", + "\n DataNode = scope.Identity.DataNode, ", + "\n AocType = scope.Identity.AocType, ", + "\n Novelty = scope.Identity.Novelty, ", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };", + "\n", + "\npublic static IfrsVariable FromLcToIfrsVariable(this Lc scope)", + "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", + "\n DataNode = scope.Identity.DataNode, ", + "\n AocType = scope.Identity.AocType, ", + "\n Novelty = scope.Identity.Novelty, ", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };", + "\n", + "\npublic static IfrsVariable FromLoReCoToIfrsVariable(this LoReCo scope)", + "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", + "\n DataNode = scope.Identity.DataNode, ", + "\n AocType = scope.Identity.AocType, ", + "\n Novelty = scope.Identity.Novelty, ", + "\n Value = scope.Value,", + "\n Partition = scope.GetStorage().TargetPartition };" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/SpecificationsTechnicalMargin.ipynb b/Test/SpecificationsTechnicalMargin.ipynb index 5e35ce33..83eaaba1 100644 --- a/Test/SpecificationsTechnicalMargin.ipynb +++ b/Test/SpecificationsTechnicalMargin.ipynb @@ -1,2576 +1,1762 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "g8tjy1GbI0uoEDhZW9OubA", - "cell_type": "markdown", - "source": [ - "

Technical Margin Specifications

" - ], - "metadata": {} - }, - { - "id": "x6HTq-dyx0CT0axGCN5uCw", - "cell_type": "markdown", - "source": [ - "The aim of this notebook is to document the Technical Margin (TM) and its allocation to the Contractual Service Margin (CSM), Loss Component (LC), or Loss Recovery Component (LoReCo). The process is pictorially explained in the following flowchart. ", - "\n", - "\n", - "\n
", - "\n", - "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." - ], - "metadata": {} - }, - { - "id": "LhxZv_5tLEW3BCU74MttbA", - "cell_type": "markdown", - "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" - ], - "metadata": {} - }, - { - "id": "yPpeVsREbUy--NQi9jbNpw", - "cell_type": "code", - "source": [ - "#!import \"SpecificationsSetup\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "U3AjnYiM5kuSmp75cguUSA", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "ECkaAKQIMEu5hqUdpeBq8Q", - "cell_type": "markdown", - "source": [ - "# Import Data" - ], - "metadata": {} - }, - { - "id": "SEMqfkxNU0e_-5mrR4lZTw", - "cell_type": "markdown", - "source": [ - "", - "\n## Current Period" - ], - "metadata": {} - }, - { - "id": "IvTb1XGZ1kuJ-VvXkuWNJw", - "cell_type": "markdown", - "source": [ - "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" - ], - "metadata": {} - }, - { - "id": "KdFdFW3OhUy3KzhPTiarkg", - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"L\" ;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UnwIzmJO6EeRXQWBbmoK1g", - "cell_type": "markdown", - "source": [ - "Import the Dimensions, Parameters, Nominal Cashflows, and Actuals from the corresponding csv files in Initialization/Systemorph/" - ], - "metadata": {} - }, - { - "id": "xPBxX-MYjEirprXfdCjqHw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8lAk_SdyNEmrDVylgM3ueg", - "cell_type": "markdown", - "source": [ - "Initialization of the Test Suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" - ], - "metadata": {} - }, - { - "id": "LZ2n8pzel0OnpsJ86gHLDw", - "cell_type": "code", - "source": [ - "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YRjwR8fuJkK9bvH84fq8dA", - "cell_type": "markdown", - "source": [ - "", - "\n## View loaded Data Nodes" - ], - "metadata": {} - }, - { - "id": "YEMgdgKuwEe_bIe-xkd09g", - "cell_type": "markdown", - "source": [ - "The imported active Data Nodes from Initialization/Systemorph/DataNodes.csv are " - ], - "metadata": {} - }, - { - "id": "uS9vfK-rBUiZsfCYiJzIpA", - "cell_type": "code", - "source": [ - "Test.GetStorage().DataNodeDataBySystemName" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LvO_qjZPmEOI6YxzgwM4vg", - "cell_type": "markdown", - "source": [ - "whereas the Data Nodes of your imported Cashflows are" - ], - "metadata": {} - }, - { - "id": "jpqlfwEBkU20upkPfktIQA", - "cell_type": "code", - "source": [ - "Test.GetStorage().DataNodesByImportScope[ImportScope.Primary]" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Km-AMREk2ECK0lggstN9yA", - "cell_type": "markdown", - "source": [ - "Please select here below the target Data Node for executing the tests below:" - ], - "metadata": {} - }, - { - "id": "KeB4MbA30U-GTokbWzsbNw", - "cell_type": "code", - "source": [ - "var dataNode = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "yjMtNI_UpEOFhOhlYPIjdg", - "cell_type": "markdown", - "source": [ - "## View list of Identities" - ], - "metadata": {} - }, - { - "id": "2suX-6pDYUu9ZRoKpbzwtg", - "cell_type": "markdown", - "source": [ - "Based on the Cashflows imported, the list of all possible identities, i.e. combinations of valid Data Nodes, Aoc steps, and Novelties, is contructed and reported here below:" - ], - "metadata": {} - }, - { - "id": "uXw2nYCpZ0i16yt57O-hZw", - "cell_type": "code", - "source": [ - "var allIdentities = Test.GetScopes(Test.GetStorage().DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "PpgNb9iz3kaMC2BeZoDKXQ", - "cell_type": "code", - "source": [ - "allIdentities" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "FX3f8E0cn0iRfjDMfGMWMw", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Present Value" - ], - "metadata": {} - }, - { - "id": "bjt2kV7OaU-pgEwV4_f7cw", - "cell_type": "markdown", - "source": [ - "Projected Present Values (PPVs) are calculated for each Amount Type (AT) either with the *locked-in* (L) and with the *current* (C) Yield Curves. While the former is the latest available as per end of the DataNode's inception year, the latter is the latest available as per the current period. ", - "\nPPVs for both Economic Basis L and C have been defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", - "\n", - "\nAccording to the BBA methodology, the CSM calculation uses the PV with locked-in Yield Curve simply defined as", - "\n", - "\n$$", - "\n\\text{PV Locked}(\\text{AoC}, \\text{AT}) = \\text{PPV}(\\text{AoC}, \\text{AT}) \\big|_{\\substack{ \\text{Calculation Type = BE} \\\\ \\text{Economic Base = L} } }", - "\n$$" - ], - "metadata": {} - }, - { - "id": "z3MoqQ9eQUS09tb1mXkFyA", - "cell_type": "code", - "source": [ - "var pvsLocked = allIdentities.SelectMany(id => Test.GetScope(id).PresentValues", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => x.FromPvToIfrsVariable())).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "t7tRCeCG10KKMVZzfO_pPg", - "cell_type": "markdown", - "source": [ - "Below a view of the computed locked-in PV " - ], - "metadata": {} - }, - { - "id": "OIen-nXHD0SiauOT9N-_Bg", - "cell_type": "code", - "source": [ - "Report.ForObjects(pvsLocked)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n .GroupColumnsBy(x => x.AmountType)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "muPGuU2J_0C0ajt9hkta5A", - "cell_type": "markdown", - "source": [ - "Aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type):", - "\n", - "\n$$", - "\n\\text{PV Locked Value}(\\text{AoC}) = \\sum_{\\text{AT}} \\text{PV Locked}(\\text{AoC}, \\text{AT})", - "\n$$" - ], - "metadata": {} - }, - { - "id": "kvGGn3Q4rUex05dzYM9qdg", - "cell_type": "markdown", - "source": [ - "Here below an example" - ], - "metadata": {} - }, - { - "id": "9_XxzJoITE-6372AHPhE3g", - "cell_type": "code", - "source": [ - "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "R9nUtmCCQECPK-w_Mp_yVw", - "cell_type": "code", - "source": [ - "id_BoP_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "du2mo7J8002QJbtRt584Mw", - "cell_type": "code", - "source": [ - "Test.GetScope( id_BoP_I ).Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_OxvDZWrPka_CFvaMAisxg", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Risk Adjustment" - ], - "metadata": {} - }, - { - "id": "376Njyw59EGhWrieNRi8jQ", - "cell_type": "markdown", - "source": [ - "The CSM calculation also uses locked-in Risk Adjustment (RA Locked) which is retrieved from the corresponding Present Value with [Calculation Type](../DataModel/DataStructure#calculation-type) being RA defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", - "\n", - "\nRisk Adjustment values can be written as", - "\n", - "\n$$", - "\n\\text{RA Locked Value}(\\text{AoC}) = \\text{PV}(\\text{AoC})|_{\\substack{ \\text{Calculation Type = RA} \\\\ \\text{Economic Base = L} }}", - "\n$$", - "\n", - "\nwhere the imported Cashflows for the RA Calculation Type are already aggregated over all [Amount Types](../DataModel/DataStructure#amount-type)." - ], - "metadata": {} - }, - { - "id": "3siM-DZsEEiBkk5Y3FRKFg", - "cell_type": "markdown", - "source": [ - "Here below an example" - ], - "metadata": {} - }, - { - "id": "Xl2yuS6a60C9Quny8zQ-5A", - "cell_type": "code", - "source": [ - "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LSaHrUxyq0i4azSGh961Jg", - "cell_type": "code", - "source": [ - "id_BoP_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RuOYh7rjz0G8Mc61JSv5Yg", - "cell_type": "code", - "source": [ - "Test.GetScope( id_BoP_I ).Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qAzxMRN-SkuuSQuz6UYYYQ", - "cell_type": "markdown", - "source": [ - "The RA Locked per Data Node imported are" - ], - "metadata": {} - }, - { - "id": "I6YzC1vPqUKXP9iGgM9VCw", - "cell_type": "code", - "source": [ - "var rasLocked = allIdentities.SelectMany(id => Test.GetScope(id).PresentValues", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => x.FromPvToIfrsVariable())).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iYZeYBNeU0C41iCvscI1CA", - "cell_type": "code", - "source": [ - "Report.ForObjects(rasLocked)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fuyUZe63NEiB09VJA2Na4A", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Technical Margin" - ], - "metadata": {} - }, - { - "id": "2VStZINSF0KMaeav25AQSQ", - "cell_type": "markdown", - "source": [ - "For the computation of the CSM or LC components for each AoC step, it is convenient to introduce the notion of technical margin (TM).", - "\n", - "\nFirstly, it is useful to define the so-called Aggregated Technical Margin (ATM)", - "\n", - "\n$$", - "\n\\text{ATM} (\\text{AoC}) = \\sum_{s\\in\\text{previous AoC steps}} \\text{TM}(s) ~,", - "\n$$", - "\n", - "\nand the Interest Accretion Factor (IAF) ", - "\n", - "\n$$", - "\n\\text{IAF} = \\prod_{i=1}^{\\text{TS}} (1 + \\text{YC}_i) - 1 ~.", - "\n$$", - "\n", - "\nThe TM is defined as", - "\n", - "\n$$", - "\n\\text{TM}(\\text{AoC}) = \\left\\{", - "\n\\begin{array}{rl}", - "\n\\text{TM}(\\rm{EOP}) \\text{ of the previous period} ~ & \\text{if }s = \\text{BOP and Novelty is In-Force}. \\\\", - "\n0 ~ & \\text{if }s = \\text{CF}. \\\\", - "\n\\text{IAF} \\cdot ~ \\text{ATM}(\\text{AoC}) ~ & \\text{if }s = \\text{IA}. \\\\", - "\n\\rm{Premiums} + \\text{Attributable Expense and Commissions} + \\text{Investment Claims} ~ & \\text{if }s = \\text{EA}. \\\\", - "\n-\\text{AMF} \\cdot ~ \\text{ATM}(\\text{AoC}) ~ & \\text{if }s = \\text{AM}. \\\\", - "\n\\text{PV Locked Value}(\\text{AoC}) ", - "\n\\bigg|_{\\substack{\\text{Non Attributable} \\\\ ", - "\n \\text{Amount Types} \\\\ ", - "\n \\text{excluded}}} ", - "\n+ \\text{RA Locked Value}(\\text{AoC}) ~ & \\text{otherwise} ", - "\n\\end{array}", - "\n\\right.", - "\n$$", - "\n", - "\nwhere AMF is the Amortization Factor that is defined [here](../Import/ImportScopeCalculation#amortization-factor) and tested [here](SpecificationsImportCashflows#amortization-factor), with YC being the [Yield Curve](#yield-curves) and TS is the Time-Step, ", - "\nand the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", - "\n", - "\n$$", - "\n\\begin{array}{lcl}", - "\n\\rm{Premiums} &=& \\text{Premium Allocation Factor} \\cdot \\sum_{\\text{Amount Type}\\in\\{\\text{PR and its children}\\}}", - "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - ", - "\n \\big(\\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}} + \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~, \\\\", - "\n\\text{Attributable Expense and Commissions} &=& \\sum_{\\text{Amount Type}\\in\\{\\rm{ACA}, \\rm{AEA}\\}}", - "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - \\text{Actual}_{\\text{Novelty=C}} ~, \\\\", - "\n\\text{Investment Claims } &=& \\sum_{\\text{Amount Type}\\in\\{\\text{ICO and its children}\\}}", - "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - ", - "\n \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}} + \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~.", - "\n\\end{array}", - "\n$$", - "\n", - "\nThe AoC Type **CF** is implicit for all formulas, PV is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **OA** and **AA** (see details [here](../Import/ImportScopeCalculation#actual-base))." - ], - "metadata": {} - }, - { - "id": "dHH8INfYdk6Y3NzMtPgJbA", - "cell_type": "markdown", - "source": [ - "## Beginning of Period" - ], - "metadata": {} - }, - { - "id": "X49_KQk8ek2l9u2XuCXQPw", - "cell_type": "code", - "source": [ - "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-MSegalanEGCyd9Lmbhk2g", - "cell_type": "code", - "source": [ - "id_BoP_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GauKnHaTZk2qPtNwgM0kgQ", - "cell_type": "code", - "source": [ - "var computedTM_BoP_I = Test.GetScope(id_BoP_I);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sDV3uzZnZE-xy3w3XNF0xA", - "cell_type": "code", - "source": [ - "computedTM_BoP_I.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3rv0eEV93Euw7OXSDpqR0w", - "cell_type": "markdown", - "source": [ - "The TM for BOP is equal to the TM for EOP of the previous period, that is, the sum of Csm, Loss Component and LoReCo as of at the end of last period (see the corresponding [formula](#technical-margins)). ", - "\n", - "\nThe corresponding **IFRS Variables** can be loaded directly from the *Storage*" - ], - "metadata": {} - }, - { - "id": "AOE-Piw6OUGsQ3Bl1AuGbw", - "cell_type": "code", - "source": [ - "var valueCsm = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.C, null);", - "\nvalueCsm" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YdYcIzhRG0CLSLEWQblsEA", - "cell_type": "code", - "source": [ - "var valueLc = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.L, null);", - "\nvalueLc" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0Onxmh3pPU6pxWFOSJt6DA", - "cell_type": "code", - "source": [ - "var valueLr = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.LR, null);", - "\nvalueLr" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0x0FA_cjZEWhsLSbrQq40g", - "cell_type": "code", - "source": [ - "var expectedTM_BoP_I = -valueCsm + valueLc + valueLr;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "SJSNzLoPJUiPGHBvEduNeQ", - "cell_type": "code", - "source": [ - "expectedTM_BoP_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8VnVUHSzbE-KpM6n4ONuQg", - "cell_type": "code", - "source": [ - "computedTM_BoP_I.Value.Should().BeApproximately( expectedTM_BoP_I, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xIQdOuzLvESRKcPIgcUsPQ", - "cell_type": "markdown", - "source": [ - "", - "\n## Model Corrections" - ], - "metadata": {} - }, - { - "id": "fNltK5PaA0Kw7wchmSNY_w", - "cell_type": "code", - "source": [ - "var id_MC_I = Test.GetIdentity(dataNode, \"MC\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RRBZvtJHhUikmA_j6oodwg", - "cell_type": "code", - "source": [ - "id_MC_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "AOGe1hxqB0auL-m48n4LEQ", - "cell_type": "code", - "source": [ - "var computedTM_MC_I = Test.GetScope(id_MC_I);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "glwYLenix0mbVAzz2QauDg", - "cell_type": "code", - "source": [ - "computedTM_MC_I.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "NmTxRKBaJUSBln-u_LqjRA", - "cell_type": "markdown", - "source": [ - "The TM for MC is given by the default [formula](#technical-margins), i.e. it is equal to the sum of PV and RA Locked, where the former does not encompass the *NonAttributable* Amount Types" - ], - "metadata": {} - }, - { - "id": "cZmPuuHgGEiu5xbMXe88xQ", - "cell_type": "code", - "source": [ - "var expectedTM_MC_I = Test.GetScope(id_MC_I).Value + Test.GetScope( id_MC_I ).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4L9o1tHqWki3eAAa7xkajA", - "cell_type": "code", - "source": [ - "expectedTM_MC_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "98q4ZQeegkuz71N9nfEHJg", - "cell_type": "code", - "source": [ - "computedTM_MC_I.Value.Should().BeApproximately( expectedTM_MC_I, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "B5PYDN0vMkqQxtE9Hyw25A", - "cell_type": "markdown", - "source": [ - "## Cash Flow" - ], - "metadata": {} - }, - { - "id": "499xH8CoX0GNNMn3D9roXg", - "cell_type": "code", - "source": [ - "var id_CF_I = Test.GetIdentity(dataNode, \"CF\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "D0CbUxy5UUKrMhBCxYOZgg", - "cell_type": "code", - "source": [ - "id_CF_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5Wp3bWCQyUGxZdn4_VfQ6Q", - "cell_type": "code", - "source": [ - "var computedTM_CF_I = Test.GetScope(id_CF_I);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nd6a0CNEH0S7s7gB7otViA", - "cell_type": "code", - "source": [ - "computedTM_CF_I.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3n9f5rJGHUulpGouIZZY-w", - "cell_type": "markdown", - "source": [ - "According to the [formula](#technical-margins) above, the tecnical margin is 0 for the Cash Flow AoC step " - ], - "metadata": {} - }, - { - "id": "rKHBn4AQB0-Xf3R7XoqAaQ", - "cell_type": "code", - "source": [ - "computedTM_CF_I.Value.Should().BeApproximately( 0, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "AVeLuFLOC0C5EG_ODOOKgg", - "cell_type": "markdown", - "source": [ - "", - "\n## Interest Accretion" - ], - "metadata": {} - }, - { - "id": "fb9GTLqZ10S_IGiMHnsjtA", - "cell_type": "code", - "source": [ - "var id_IA_I = Test.GetIdentity(dataNode, \"IA\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qTqnPKarN0W0KXR3GY0C2Q", - "cell_type": "code", - "source": [ - "id_IA_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-A6XSrwceEml_t5TZg447g", - "cell_type": "code", - "source": [ - "var computedTM_IA_I = Test.GetScope(id_IA_I);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "grxq6Y2xxkeWfYaEXojn4w", - "cell_type": "code", - "source": [ - "computedTM_IA_I.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "S4WYAmNv9kOPoeM8Utgblg", - "cell_type": "markdown", - "source": [ - "According to the [formula](#technical-margins) above, for the AoC step IA, the TM is equal to sum of the TMs of its previous AoC step multiplied by the IAF. " - ], - "metadata": {} - }, - { - "id": "4WhIgYaOr0aGNomU8C5-uA", - "cell_type": "markdown", - "source": [ - "The IAF associated to the current period (i.e. shift and time step) can be calculated from the shift, the time Step, and the Interest Rates" - ], - "metadata": {} - }, - { - "id": "4xfyE1DlUEqKdYMjYcygRw", - "cell_type": "code", - "source": [ - "var projectionPeriod = 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "RjAsyz82BECP1W48K-a7rA", - "cell_type": "code", - "source": [ - "var shift = Test.GetStorage().GetShift(projectionPeriod);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wsHHDSkq-0-huGE1nvj3wQ", - "cell_type": "code", - "source": [ - "var timeStep = Test.GetStorage().GetTimeStep(projectionPeriod);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_gEJdoVPuUyxvU1oEF2Clw", - "cell_type": "code", - "source": [ - "(shift, timeStep)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "lNmbEvWOU0KMR_ZMy4DQpQ", - "cell_type": "code", - "source": [ - "var monthlyRates = Test.GetScope(id_IA_I);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "p4EWaRtorkCe5b4KbM6kFA", - "cell_type": "code", - "source": [ - "monthlyRates" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WhnDXZb69ES2SSJKZBdqPA", - "cell_type": "code", - "source": [ - "var IAF = Enumerable.Range(shift,timeStep).Select(i => monthlyRates.Interest.GetValidElement(i/12)).Aggregate(1.0d, (x, y) => x * y ) - 1.0d;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "A4PMm2aaGEejwDCTGWNc2w", - "cell_type": "code", - "source": [ - "IAF" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bJTIxBr6wUSGCYZKPko5RA", - "cell_type": "markdown", - "source": [ - "Since the previous AoC steps are" - ], - "metadata": {} - }, - { - "id": "fJq-TMlCuE-9Xsfek5KWug", - "cell_type": "code", - "source": [ - "var previousAocStep = Test.GetScope((id_IA_I, InputSource.Cashflow)).Values;", - "\npreviousAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "__ftTIzmrUS_DQUcSg34vg", - "cell_type": "markdown", - "source": [ - "the expected TM for the Amortization step reads" - ], - "metadata": {} - }, - { - "id": "FMyRgLCS30mHjSbBaZ6LgA", - "cell_type": "code", - "source": [ - "var expectedTM_IA_I = IAF * previousAocStep.Sum(aoc => Test.GetScope(id_IA_I with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UBacH9pFIkG_rxoWOux8Rg", - "cell_type": "code", - "source": [ - "expectedTM_IA_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1-tr5DyvAEyE3oMQwJnJyA", - "cell_type": "code", - "source": [ - "computedTM_IA_I.Value.Should().BeApproximately( expectedTM_IA_I, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TAmMb4uGQ0CGG-bwB1k0bg", - "cell_type": "markdown", - "source": [ - "## Combined Liabilities" - ], - "metadata": {} - }, - { - "id": "RH193aFtkEq65MfZGDWFgQ", - "cell_type": "code", - "source": [ - "var id_CL_C = Test.GetIdentity(dataNode, \"CL\", \"C\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8Ug4OQB9lEWCTqQm6mWYdA", - "cell_type": "code", - "source": [ - "id_CL_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YDa8Beon7Umu1aUF0ONGJQ", - "cell_type": "code", - "source": [ - "var computedTM_CL_C = Test.GetScope(id_CL_C);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "eyyv-oaJE0KWTDaGRKqDpw", - "cell_type": "code", - "source": [ - "computedTM_CL_C.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VWU-qT5aV0GrakHpIsqPgQ", - "cell_type": "markdown", - "source": [ - "According to the default TM [formula](#technical-margins), for the CL step the TM is equal to the sum of PV and RA Locked, where the former does not encompass the *NonAttributable* Amount Types" - ], - "metadata": {} - }, - { - "id": "6EyiiEVRzkuI6YRXJQ1MTQ", - "cell_type": "code", - "source": [ - "var expectedTM_CL_C = Test.GetScope(id_CL_C).Value + Test.GetScope( id_CL_C ).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0dDkPEAfeE-XhvLA7DH1Wg", - "cell_type": "code", - "source": [ - "expectedTM_CL_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MKmlpGv4-E64crKcv0Zlig", - "cell_type": "code", - "source": [ - "computedTM_CL_C.Value.Should().BeApproximately( expectedTM_CL_C, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WDBCcZKCLUeobaNw-juV1g", - "cell_type": "markdown", - "source": [ - "## Experience Adjustment" - ], - "metadata": {} - }, - { - "id": "2dBJGbhnzk6wE_QuqLi-RQ", - "cell_type": "code", - "source": [ - "var id_EA_C = Test.GetIdentity(dataNode, \"EA\", \"C\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hyawxe-JhUqkLHKOWPTdQw", - "cell_type": "code", - "source": [ - "id_EA_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "goQMZoAJfkSEn4o50YRUew", - "cell_type": "code", - "source": [ - "var computedTM_EA_C = Test.GetScope(id_EA_C);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8dX7PfDfwEWf7hkrubnBxw", - "cell_type": "code", - "source": [ - "computedTM_EA_C.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-WJt_6_ZIkGH0yWrnqftrQ", - "cell_type": "markdown", - "source": [ - "According to the [formula](#technical-margins) above, for the AoC step EA, the TM is equal to sum of the Premiums, Attributable Expense and Commissions, and Investment Claims. Here below we calculate these terms individually." - ], - "metadata": {} - }, - { - "id": "DB62V_OoakmF-fa0ir-6vg", - "cell_type": "markdown", - "source": [ - "The Premiums, Attributable Expense and Commissions and Investment Claims Present Values and Actuals are calculated using the CF AoC step. Therefore, as first step we define the relevant AoC step and Novelties:" - ], - "metadata": {} - }, - { - "id": "tGqV5u76l0-NIz-zJDKesQ", - "cell_type": "code", - "source": [ - "var referenceAoCType = Test.GetScope(id_EA_C).Value.AocType;", - "\nvar referenceAoC = Test.GetStorage().GetNovelties().Select(n => new AocStep(referenceAoCType, n));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tFXCsZ7yPkaUO_sP6Rf4dw", - "cell_type": "code", - "source": [ - "referenceAoC" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Zn9OSvz3M02EYNKavRdHWA", - "cell_type": "markdown", - "source": [ - "**Premiums**" - ], - "metadata": {} - }, - { - "id": "hD28G9xlTki7-KNMU73QQQ", - "cell_type": "markdown", - "source": [ - "The list of Premiums Amount Type defined in the imported dimensions and the Premium Allocation Factor can be retrieved" - ], - "metadata": {} - }, - { - "id": "WPVewiJ-ZUKbnl0snAuRBA", - "cell_type": "code", - "source": [ - "Test.GetStorage().GetPremiums()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "N6sWBi5BvkKF2O4N78nT_Q", - "cell_type": "code", - "source": [ - "var premiumAllocationFactor = Test.GetStorage().GetPremiumAllocationFactor(id_EA_C);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Fmxi3kQshEaXnPNNsbhPNg", - "cell_type": "code", - "source": [ - "premiumAllocationFactor" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GY7vCaRdK0GOmI8q5PX9_Q", - "cell_type": "markdown", - "source": [ - "Lastly, the Premiums term is" - ], - "metadata": {} - }, - { - "id": "5-HIYLo-bk2YFsABuEJCsQ", - "cell_type": "code", - "source": [ - "var premiums = premiumAllocationFactor * Test.GetStorage().GetPremiums()", - "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", - "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.A, (int?)null)).Value)", - "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.AA, (int?)null)).Value)", - "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.OA, (int?)null)).Value)", - "\n );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fg0ynhRLfEiTL68jnBFYPg", - "cell_type": "code", - "source": [ - "premiums" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GpYhgIs7bkijYtGnn_rmug", - "cell_type": "markdown", - "source": [ - "**Attributable Expense and Commissions**" - ], - "metadata": {} - }, - { - "id": "HLALKVc8NE233oTSH12a-Q", - "cell_type": "markdown", - "source": [ - "Analogously, the Attributable Expense and Commissions term can be computed" - ], - "metadata": {} - }, - { - "id": "tPhUn5VaikiP2WaFNmIoiA", - "cell_type": "code", - "source": [ - "var attributableExpenseAndCommissions = new string[] {AmountTypes.ACA, AmountTypes.AEA}", - "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", - "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, EstimateTypes.A, (int?)null)).Value));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CBelGvY28Uef9-9DjuaJSA", - "cell_type": "code", - "source": [ - "attributableExpenseAndCommissions" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "endWZOKckEWp2c6BLELK1w", - "cell_type": "markdown", - "source": [ - "**Investment Claims**" - ], - "metadata": {} - }, - { - "id": "AHIdM5P7nUyMySdWDQN-kA", - "cell_type": "markdown", - "source": [ - "Finally the Investment Claims term reads" - ], - "metadata": {} - }, - { - "id": "bETNZXjO2EuzRVFBP4Nykw", - "cell_type": "code", - "source": [ - "var investmentClaims = Test.GetStorage().GetInvestmentClaims()", - "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", - "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.A, (int?)null)).Value)", - "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.AA, (int?)null)).Value)", - "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.OA, (int?)null)).Value)", - "\n );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hKxm4Ea8-kCpGkmuQ8-P1g", - "cell_type": "code", - "source": [ - "investmentClaims" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tHqLLnVgKE6pcPnvAv06Tg", - "cell_type": "markdown", - "source": [ - "**Expected TM**" - ], - "metadata": {} - }, - { - "id": "ffxLkcddWUifhMB2Ybvzzw", - "cell_type": "code", - "source": [ - "var expectedTM_EA_C = premiums + attributableExpenseAndCommissions + investmentClaims;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "SUkya34JlUm2dEmvnV6bTQ", - "cell_type": "code", - "source": [ - "expectedTM_EA_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KL-ACiIWbkaCFXsaDZoW-g", - "cell_type": "code", - "source": [ - "computedTM_EA_C.Value.Should().BeApproximately( expectedTM_EA_C, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "aly806PPsk6nb1bq-n7-Sg", - "cell_type": "markdown", - "source": [ - "## Amortization" - ], - "metadata": {} - }, - { - "id": "bsMWbnZzwkiwXgJ8qAvFvw", - "cell_type": "code", - "source": [ - "var id_AM_C = Test.GetIdentity(dataNode, \"AM\", \"C\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "f4APi5_3CUmHUbP4cXLdcg", - "cell_type": "code", - "source": [ - "id_AM_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Rh7epJw7NUaRJ1RMc2rMQg", - "cell_type": "code", - "source": [ - "var computedTM_AM_C = Test.GetScope(id_AM_C);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8zkFkhgH00CXbsv5T8h-Hg", - "cell_type": "code", - "source": [ - "computedTM_AM_C.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "exXE3mAyIEi-kS4auuzrKQ", - "cell_type": "code", - "source": [ - "computedTM_AM_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "EpoM-9UMx0qwL68EXUoiiA", - "cell_type": "markdown", - "source": [ - "According to the [formula](#technical-margins) above, for the AoC step AM, the TM is equal to sum of the TMs of its previous AoC step multiplied by the amortization factor with opposite sign. ", - "\n", - "\nThe AoC step previous to Amortization are" - ], - "metadata": {} - }, - { - "id": "RWUkvmQU9kqvjgKafKtMGg", - "cell_type": "code", - "source": [ - "var previousAocStep = Test.GetScope((id_AM_C, InputSource.Cashflow)).Values;", - "\npreviousAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WvdwUX-cX0SvELfpTOrxHA", - "cell_type": "markdown", - "source": [ - "while the Amortization Factor can be retrieved in the following" - ], - "metadata": {} - }, - { - "id": "HTgPDX8Zw0agihg2o3LoWQ", - "cell_type": "code", - "source": [ - "Test.GetScope(id_AM_C)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "r74wo-n4PEiaFDs1bW_41w", - "cell_type": "markdown", - "source": [ - "Therefore, the expected TM for the Amortization step reads" - ], - "metadata": {} - }, - { - "id": "SznuOL-o1Uy5mmuI-jmWPw", - "cell_type": "code", - "source": [ - "var expectedTM_AM_C = -Test.GetScope(id_AM_C).Value * ", - "\n previousAocStep.Sum(aoc => Test.GetScope(id_AM_C with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rEbKtIir70eeIiyYnSAFiA", - "cell_type": "code", - "source": [ - "expectedTM_AM_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5Boj82BZcUanZERZtQH1mA", - "cell_type": "code", - "source": [ - "computedTM_AM_C.Value.Should().BeApproximately( expectedTM_AM_C, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IoyFPh2DekK36wAQkduuFw", - "cell_type": "markdown", - "source": [ - "## End of Period" - ], - "metadata": {} - }, - { - "id": "e7GBWeapNUCJFEwl3Hdlfw", - "cell_type": "code", - "source": [ - "var id_EoP_C = Test.GetIdentity(dataNode, \"EOP\", \"C\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bFFAsDW4HU21gY0oQl4w-g", - "cell_type": "code", - "source": [ - "id_EoP_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-NF7JtObB0el7f59d8rHzw", - "cell_type": "code", - "source": [ - "var computedTM_EoP_C = Test.GetScope(id_EoP_C);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "J6OQYmtTy0O6Pa4dqCaYEQ", - "cell_type": "code", - "source": [ - "computedTM_EoP_C.Value" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ar4enZGkDkahHzmCKHvxBA", - "cell_type": "code", - "source": [ - "var expectedTM_EoP_C = Test.GetScope( id_EoP_C ).Value + Test.GetScope( id_EoP_C ).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Q-Rv4WF-uEOJenziP5Ko6w", - "cell_type": "code", - "source": [ - "expectedTM_EoP_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "GE0JdvladkOqE6BxVNRMcA", - "cell_type": "code", - "source": [ - "computedTM_EoP_C.Value.Should().BeApproximately( expectedTM_EoP_C, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XDuHL9hx2E6DU5ayGYHutQ", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Switch Logic " - ], - "metadata": {} - }, - { - "id": "NHk1HPZ3y0K-uGfMOBF1gQ", - "cell_type": "markdown", - "source": [ - "The CSM and LC figures are allocated for each AoC step based on the sign of the ATM. Specifically, for positive (negative) ATM, the TM of the current step is allocated to the LC (CSM), unless the TM flips the sign of the ATM. This special circumstance is named **switch**. It can happen at any AoC step with the only exception of Amortization where there is no switch from the previous step.", - "\nWhen a switch occurs the total contribution to the CSM (LC) prior the switching step is brought to 0 and the remaing amount is allocated to LC (CSM).", - "\n", - "\nIn the following the AoC chain is investigated." - ], - "metadata": {} - }, - { - "id": "qkwHpG9GrUmO52LhVW0gMw", - "cell_type": "markdown", - "source": [ - "## Beginning of Period", - "\n", - "\nFor the BOP, the last period is considered, which dictates that the corresponding EOP figures considered have necessarily Novelty of type *In-Force*.", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{BOP}) &=& \\text{CSM}(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force} \\\\", - "\n\\text{LC}(\\text{BOP}) &=& \\text{LC}(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", - "\n\\end{array}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "x2DkfQwGp0q67zTOEqWSDg", - "cell_type": "code", - "source": [ - "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "U1ZDbeNAYUSlPIqSHFql-A", - "cell_type": "code", - "source": [ - "id_BoP_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OeYWN1P_DEOPTJgMbEYdwg", - "cell_type": "code", - "source": [ - "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", - "\nvar computedLC_BoP_I = Test.GetScope(id_BoP_I).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ihEr80PWCkGZdhvb1ggfKw", - "cell_type": "code", - "source": [ - "(computedCSM_BoP_I, computedLC_BoP_I)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "gGKUWa-n40u9Xu3VNw4n7A", - "cell_type": "markdown", - "source": [ - "To understand where the BOP is allocated, we retrieve the corresponding TM and, based on its sign, we expect the CSM or the LC to be non-zero according to the [formula](#switch-logic) above" - ], - "metadata": {} - }, - { - "id": "GbsT5_IX40yquehB3bXzWg", - "cell_type": "code", - "source": [ - "var TM_BOP_I = Test.GetScope(id_BoP_I).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VzVSQA_NVE2D__qk77LRuQ", - "cell_type": "code", - "source": [ - "TM_BOP_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VyqxO7jhD06tjnlyZWgklA", - "cell_type": "code", - "source": [ - "var expectedCSM_BoP_I = TM_BOP_I < 0 ? -TM_BOP_I : 0;", - "\nvar expectedLC_BoP_I = TM_BOP_I > 0 ? +TM_BOP_I : 0;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "I9Ou_OG9n0-4enuli2WR8w", - "cell_type": "code", - "source": [ - "(expectedCSM_BoP_I, expectedLC_BoP_I)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZGzRu0gOjEuAs_AaPiyaAA", - "cell_type": "code", - "source": [ - "computedCSM_BoP_I.CheckEquality(computedCSM_BoP_I).Should().Be(true);", - "\nexpectedLC_BoP_I.CheckEquality(computedLC_BoP_I).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Dmr2QZObzkCiSqWNVstsqA", - "cell_type": "markdown", - "source": [ - "## Following AoC steps" - ], - "metadata": {} - }, - { - "id": "QhyguKxmFkur5akQ_kuU4w", - "cell_type": "markdown", - "source": [ - "From the BOP up to the CL step, the switch logic is applied separately to the In-Force and New Business novelties." - ], - "metadata": {} - }, - { - "id": "j2v9TGxKBEi9vyAXzjnYRQ", - "cell_type": "code", - "source": [ - "var id_MC_I = Test.GetIdentity(dataNode, \"MC\", \"I\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "oURGBY049UO_6rpp5Yvd8w", - "cell_type": "code", - "source": [ - "id_MC_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Zz6IYfaXW0eEwAt1CFXLqQ", - "cell_type": "code", - "source": [ - "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", - "\nvar computedLC_MC_I = Test.GetScope(id_MC_I).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "anLo2TEZn0a-c-b58-NptA", - "cell_type": "code", - "source": [ - "(computedCSM_MC_I, computedLC_MC_I)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "_3ECx3xw6kaAPhipr_o3IQ", - "cell_type": "markdown", - "source": [ - "According to the [formula](#switch-logic) above this AoC step is allocated either to CSM or to LC based on the sign of ATM + TM. Both these two terms can be retrieved from the **TechnicalMargin** Scope." - ], - "metadata": {} - }, - { - "id": "vDlb6A-66UaV1dj-A7BpwA", - "cell_type": "code", - "source": [ - "var TM_MC_I = Test.GetScope(id_MC_I);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "tWklX6ndd0eQuh10WyJwow", - "cell_type": "code", - "source": [ - "TM_MC_I" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VShlk81fLE6vcS4-zPChpA", - "cell_type": "markdown", - "source": [ - "The correctness of the ATM can be checked by firstly withdrawing the previous AoC steps" - ], - "metadata": {} - }, - { - "id": "ZeVVDyOg8kiQOSI9_cx7Sg", - "cell_type": "code", - "source": [ - "var previousAocStep = Test.GetScope((id_MC_I, InputSource.Cashflow)).Values;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TGc_r6IcEUWsmmbS1dH8gA", - "cell_type": "code", - "source": [ - "previousAocStep" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "4LVnT3VEWkyKk021jdSe1g", - "cell_type": "markdown", - "source": [ - "and then evaluating the sum of the corresponding TMs" - ], - "metadata": {} - }, - { - "id": "C4MRuXZBHEWOoGmxdDMPNQ", - "cell_type": "code", - "source": [ - "var expectedATM = previousAocStep.Sum(aoc => Test.GetScope(id_MC_I with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "AjUcTq64mUiQGuUK9WLhpQ", - "cell_type": "code", - "source": [ - "expectedATM" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qG0nHl69Y0qX9agYsei91g", - "cell_type": "markdown", - "source": [ - "Therefore, the following condition for ATM calculated by the **TechnicalMargin** Scope needs to be fullfilled" - ], - "metadata": {} - }, - { - "id": "-2a6HsG0-U6ss9qGHoExYw", - "cell_type": "code", - "source": [ - "TM_MC_I.AggregatedValue.Should().BeApproximately( expectedATM, Precision );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "z3e8UQynb02Bjtq0B_KbcA", - "cell_type": "markdown", - "source": [ - "The CSM and LC can be allocated according to the [Switch Logic](#switch-logic)." - ], - "metadata": {} - }, - { - "id": "SpZykQISGUS5t5LfteXTqg", - "cell_type": "code", - "source": [ - "double expectedCSM_MC_I; ", - "\ndouble expectedLC_MC_I; " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8I15mZw2KUKeZMDPsOvYfg", - "cell_type": "code", - "source": [ - "var aggregated = TM_MC_I.Value + TM_MC_I.AggregatedValue;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Qw1GlZ5Edkaz3I-5i96u9A", - "cell_type": "markdown", - "source": [ - "If there is no switch from LC, i.e. $\\text{ATM} (\\text{AoC}) > 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\ge 0 $, then:", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{AoC}) &=& 0 ~, \\\\", - "\n\\text{LC}(\\text{AoC}) &=& \\text{TM}(\\text{AoC}) ~.", - "\n\\end{array}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "7da5XEhrhEu35M4vNuKJ7Q", - "cell_type": "code", - "source": [ - "if(TM_MC_I.AggregatedValue > 0 && aggregated >= 0) {", - "\n expectedCSM_MC_I = 0 ;", - "\n expectedLC_MC_I = TM_MC_I.Value ;", - "\n} " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "KbFNOw70mEePHWniU_e5Gw", - "cell_type": "markdown", - "source": [ - "If there is no switch from CSM, i.e. $\\text{ATM} (\\text{AoC}) \\le 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\le 0 $, then:", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) ~, \\\\", - "\n\\text{LC}(\\text{AoC}) &=& 0 ~.", - "\n\\end{array}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "fgaGOnieo0qKvh_7zYB2Iw", - "cell_type": "code", - "source": [ - "if(TM_MC_I.AggregatedValue < 0 && aggregated <= 0) {", - "\n expectedCSM_MC_I = -TM_MC_I.Value ;", - "\n expectedLC_MC_I = 0 ;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "wI01nxemTE6PWDDgvWjtww", - "cell_type": "markdown", - "source": [ - "If $\\text{ATM} (\\text{AoC}) > 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\le 0$, then there is a switch to CSM:", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) -\\text{ATM} (\\text{AoC}) ~, \\\\", - "\n\\text{LC}(\\text{AoC}) &=& -\\text{ATM} (\\text{AoC}) ~.", - "\n\\end{array}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "r_Z-PV3jnEe61s5dxqqeAQ", - "cell_type": "code", - "source": [ - "if(TM_MC_I.AggregatedValue > 0 && aggregated <= 0) {", - "\n expectedCSM_MC_I = -aggregated;", - "\n expectedLC_MC_I = -TM_MC_I.AggregatedValue ;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UGTIjdFCpUOf3okJiq05Xw", - "cell_type": "markdown", - "source": [ - "On the other hand, if $\\text{ATM} (\\text{AoC}) \\le 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) > 0$, ", - "\nthen the switch is to LC:", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{AoC}) &=& \\text{ATM} (\\text{AoC}) ~, \\\\", - "\n\\text{LC}(\\text{AoC}) &=& \\text{TM}(\\text{AoC}) + \\text{ATM} (\\text{AoC}) ~.", - "\n\\end{array}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "b4tllqavSUaAPPPQ9-2xNw", - "cell_type": "code", - "source": [ - "if(TM_MC_I.AggregatedValue <= 0 && aggregated > 0) {", - "\n expectedCSM_MC_I = TM_MC_I.AggregatedValue ;", - "\n expectedLC_MC_I = aggregated ;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "7DcRpZcCLEurfCz1WhmBsA", - "cell_type": "markdown", - "source": [ - "Therefore, the expected CSM and LC for this step are" - ], - "metadata": {} - }, - { - "id": "Cynr0d0AokyhPo5thwHxng", - "cell_type": "code", - "source": [ - "(expectedCSM_MC_I, expectedLC_MC_I)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "jt1m57jeUUOnClnAWUh4GQ", - "cell_type": "code", - "source": [ - "expectedCSM_MC_I.CheckEquality(computedCSM_MC_I).Should().Be(true);", - "\nexpectedLC_MC_I.CheckEquality(computedLC_MC_I).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0CzQml-85UuZbrhJFsKLDw", - "cell_type": "markdown", - "source": [ - "", - "\n## Combined Liabilities" - ], - "metadata": {} - }, - { - "id": "l3-1ZxlOU06br5k6_VWJgw", - "cell_type": "markdown", - "source": [ - "The CL Aoc Step brings both contributions to CSM and LC together as the novelities are summed.", - "\n", - "\nFor the CL step, the logic is similar to the one above, except that a switch from LC to CSM can happen **because of New Business and despite of In-Force**, in which case we have:", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) - \\text{ATM}(\\text{Last In-Force AoC step}) - \\text{TM}(\\text{Last In-Force AoC step}) \\\\", - "\n\\text{LC}(\\text{AoC}) &=& -\\text{ATM}(\\text{Last In-Force AoC step}) - \\text{TM}(\\text{Last In-Force AoC step})", - "\n\\end{array}", - "\n$$", - "\n", - "\nIf, on the other hand, the switch from LC to CSM happens **because of In-Force and despite of New Business**, then we have:", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{AoC}) &=& - \\text{TM}(\\text{AoC}) - \\text{ATM}(\\text{Last NB AoC step}) - \\text{TM}(\\text{Last NB AoC step}) \\\\", - "\n\\text{LC}(\\text{AoC}) &=& - \\text{ATM}(\\text{Last NB AoC step}) - \\text{TM}(\\text{Last NB AoC step})", - "\n\\end{array}", - "\n$$", - "\n", - "\nFor the switch in the other direction, i.e. from CSM to LC the formulas are similar except that LC and CSM are swapped." - ], - "metadata": {} - }, - { - "id": "LbA7zjeoTUmzsL20pTogpg", - "cell_type": "code", - "source": [ - "var id_CL_C = Test.GetIdentity(dataNode, \"CL\", \"C\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "BQ0_Jmo4GUCeoSwaNpzSEQ", - "cell_type": "code", - "source": [ - "id_CL_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "b1ZovjyK206ocT3in7tJJg", - "cell_type": "code", - "source": [ - "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", - "\nvar computedLC_CL_C = Test.GetScope(id_CL_C).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "di_k8t-Q8k6S_g2qUV6UKA", - "cell_type": "code", - "source": [ - "(computedCSM_CL_C, computedLC_CL_C)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HNbDZeZA-0q7FhEWN2i1AA", - "cell_type": "markdown", - "source": [ - "The CL step considers the last step of both the New Business and the In Force Novelties to decide what to allocate to CSM or LC. " - ], - "metadata": {} - }, - { - "id": "gFyHo7Xd80Kx9qUhOBfakQ", - "cell_type": "code", - "source": [ - "var lastAocSteps = Test.GetScope((id_CL_C, InputSource.Cashflow)).Values.GroupBy(x => x.Novelty).Select(g => g.Last());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Z0o-1_Kj7kqDfc6VHr5cxQ", - "cell_type": "code", - "source": [ - "lastAocSteps" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "OJYdM2hIAk-hyqf4zANz0A", - "cell_type": "markdown", - "source": [ - "Selecting the corresponding AocTypes:" - ], - "metadata": {} - }, - { - "id": "W0LNije6AESOhExOn3cEIQ", - "cell_type": "code", - "source": [ - "var lastAocTypeNb = lastAocSteps.Single(x => x.Novelty == Novelties.N).AocType;", - "\nvar lastAocTypeI = lastAocSteps.Single(x => x.Novelty == Novelties.I).AocType;", - "\n(lastAocTypeI, lastAocTypeNb)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LQ6g6NwhGkaAn6cNDgnwLw", - "cell_type": "code", - "source": [ - "var lastTM_NewBusiness = Test.GetScope(id_CL_C with {AocType = lastAocTypeNb, Novelty = Novelties.N});" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "h_-vLUO1a0CaiTlvHdl-Qw", - "cell_type": "code", - "source": [ - "lastTM_NewBusiness" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "vx-ERfMXoEmPlM7YjfSpVg", - "cell_type": "code", - "source": [ - "var lastTM_InForce = Test.GetScope(id_CL_C with {AocType = lastAocTypeI, Novelty = Novelties.I});" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nEAfJcJBfU6e8ESe_G-HGQ", - "cell_type": "code", - "source": [ - "lastTM_InForce" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "IsysT0dxB02V9LtXUi4WKw", - "cell_type": "markdown", - "source": [ - "Conversely the TM and ATM for the CL step is" - ], - "metadata": {} - }, - { - "id": "0nCrk056Kki5-Lj4k_DNUA", - "cell_type": "code", - "source": [ - "var TM_Combined = Test.GetScope(id_CL_C);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HYP4Ehlpz06WTCeicsf-TA", - "cell_type": "code", - "source": [ - "TM_Combined" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VizwJ9n3JUWNn8VHtyyZRg", - "cell_type": "markdown", - "source": [ - "where the ATM of CL is given by the sum of the ATMs of the New Business and In Force Novelties" - ], - "metadata": {} - }, - { - "id": "_6wJKgMbikuQcgsNrkRUKA", - "cell_type": "code", - "source": [ - "var aggregatedNewBusiness = lastTM_NewBusiness.Value + lastTM_NewBusiness.AggregatedValue;", - "\nvar aggregatedInForce = lastTM_InForce.Value + lastTM_InForce.AggregatedValue;", - "\nvar sum = aggregatedNewBusiness + aggregatedInForce;", - "\nsum" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VmDd0wzbzEW0oE885Kyqww", - "cell_type": "code", - "source": [ - "( (sum - TM_Combined.AggregatedValue)/sum < 1.0e-12).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "19uVR0w7F02xd9KaJ2yVIQ", - "cell_type": "markdown", - "source": [ - "In order to decide where the TM of the CL step is allocated, one has to check the sign of the ATM + TM for both the New Business and the In Force" - ], - "metadata": {} - }, - { - "id": "QeZXbaKXGk2Vyp4P4dxgJg", - "cell_type": "code", - "source": [ - "var aggregatedCombined = TM_Combined.Value + TM_Combined.AggregatedValue;", - "\naggregatedCombined" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Njb3qejxeU6T_QL3ocb23g", - "cell_type": "markdown", - "source": [ - "According to the [formulas above](#combined-liabilities), for a positive (negative) aggregated CL value, the CL TM has to be allocated to LC (CSM). ", - "\n
In case the one of last Aoc step of the novelties (I, NB) has the sign of the CL ATM opposite to the CL ATM, the CL AocStep is used to introduce a balancing item to bring the ATM of the novelty with opposite sign to 0. ", - "\n
This is equivalent to execute the switch logic with a balancing item = ATM of the last AocStep having opposite sign to CL ATM. ", - "\n
Note that if CL TM is zero this results in allocating the same amount with opposite sign to CSM(note that the sign of the CSM componet is flipped) and LC." - ], - "metadata": {} - }, - { - "id": "PKCnye7OH0qMHL6PW1vWMw", - "cell_type": "code", - "source": [ - "double expectedCSM_CL_C; ", - "\ndouble expectedLC_CL_C; " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mR_PzvyP50CGygsS3pFx9g", - "cell_type": "code", - "source": [ - "var balancingItem = aggregatedCombined < 0 ? aggregatedNewBusiness : aggregatedInForce;", - "\nbalancingItem" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hhE70xjs-EGuXjI4ztfscQ", - "cell_type": "code", - "source": [ - "", - "\nif(aggregatedCombined > 0) {", - "\n expectedCSM_CL_C = balancingItem ;", - "\n expectedLC_CL_C = TM_Combined.Value + balancingItem;", - "\n} else {", - "\n expectedLC_CL_C = - balancingItem ;", - "\n expectedCSM_CL_C = TM_Combined.Value - balancingItem ;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "474WEtEUPEqOIsiRVbHO0g", - "cell_type": "code", - "source": [ - "(expectedCSM_CL_C, expectedLC_CL_C)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-gNe5T_ZLEeVHsBfCLPhWA", - "cell_type": "code", - "source": [ - "expectedCSM_CL_C.CheckEquality(computedCSM_CL_C).Should().Be(true);", - "\nexpectedLC_CL_C.CheckEquality(computedLC_CL_C).Should().Be(true);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DyvDoHzrBEq3_wVcCchkEw", - "cell_type": "markdown", - "source": [ - "## End Of Period", - "\n", - "\nFor the last AoC step, the EOP is the sum of all previous steps", - "\n", - "\n$$", - "\n\\begin{array}{rcl}", - "\n\\text{CSM}(\\text{EOP}) &=& \\sum_{s~\\in~\\text{previous AoC steps}} \\text{CSM}(s) ~, \\\\", - "\n\\text{LC}(\\text{EOP}) &=& \\sum_{s~\\in~\\text{previous AoC steps}} \\text{LC}(s) ~.", - "\n\\end{array}", - "\n$$" - ], - "metadata": {} - }, - { - "id": "_ESoopqaZU-By3wLhIBkgw", - "cell_type": "code", - "source": [ - "var id_EoP_C = Test.GetIdentity(dataNode, \"EOP\", \"C\");" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZqMiKYtLj0mrhg2Bk0SKbQ", - "cell_type": "code", - "source": [ - "id_EoP_C" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qHO12xBFj0OKhZj66J3uxQ", - "cell_type": "code", - "source": [ - "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", - "\nvar computedLC_EoP_C = Test.GetScope(id_EoP_C).Value;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "C54gDBF8B0iE8erZtf9PDA", - "cell_type": "code", - "source": [ - "(computedCSM_EoP_C, computedLC_EoP_C)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MoN2gU7CgkmSAoAH8E3P4g", - "cell_type": "markdown", - "source": [ - "

", - "\n
", - "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the corresponding gross case TM to allocate the figure either to CSM or to LoReCo. The reinsurance gross TM multiplied by the weights coming from the Reinsurance Coverage Parameter (Data Node Parameters). In case a GRIC has multiple GICs, then these weighted TMs are aggregated.", - "\n
" - ], - "metadata": {} - }, - { - "id": "-17yUzUfYU-46uPh5jCLzQ", - "cell_type": "markdown", - "source": [ - "" - ], - "metadata": {} - }, - { - "id": "LHXDcjueYUy1IKvyMPuZyQ", - "cell_type": "markdown", - "source": [ - "

", - "\n", - "\n# Contractual Service Margin and Loss Component" - ], - "metadata": {} - }, - { - "id": "O7oZvk5RIk-EplmELWCLLw", - "cell_type": "markdown", - "source": [ - "Here below a view of the CSM and Loss Component results are shown. ", - "\n", - "\nNote: the Data Nodes with LiabilityType being *LIC* are excluded." - ], - "metadata": {} - }, - { - "id": "WQsEnHxeUkWa24cVa17ASw", - "cell_type": "code", - "source": [ - "var allIdentitiesWoLic = allIdentities.Where(id => Test.GetStorage().DataNodeDataBySystemName[id.DataNode].LiabilityType != \"LIC\").ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "ZClqTg9_EEKdli2o4Blwqw", - "cell_type": "code", - "source": [ - "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => x.FromCsmToIfrsVariable())).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VYCT72rdHE6fE0HDC7ygOQ", - "cell_type": "markdown", - "source": [ - "## Gross case" - ], - "metadata": {} - }, - { - "id": "UsRkibKobkCtFXhm5l__xQ", - "cell_type": "code", - "source": [ - "var allInsuranceIdentitiesWoLic = allIdentitiesWoLic.Where(id => !id.IsReinsurance).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "PirmpNw8w0yTsQZmMWqgKw", - "cell_type": "code", - "source": [ - "var lc = allInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => x.FromLcToIfrsVariable())).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rqcC8OgZSEWmclwqnva9LQ", - "cell_type": "markdown", - "source": [ - "## Re-Insurance case (LoReCo)" - ], - "metadata": {} - }, - { - "id": "9FlZC2iKzkimZWgYZNcsRw", - "cell_type": "code", - "source": [ - "var allReInsuranceIdentitiesWoLic = allIdentitiesWoLic.Where(id => id.IsReinsurance).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "NZ39ut9ark6eMKtKoBbyOg", - "cell_type": "code", - "source": [ - "var loreco = allReInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", - "\n .Where(x => Math.Abs(x.Value) >= Precision)", - "\n .Select(x => x.FromLoReCoToIfrsVariable())).ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "x-kOOIetOka_mQDABgu3oQ", - "cell_type": "markdown", - "source": [ - "## Summary" - ], - "metadata": {} - }, - { - "id": "mF7UvAY_-EKAlqSsnrQcNQ", - "cell_type": "code", - "source": [ - "Report.ForObjects( csm.Concat(lc).Concat(loreco) )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "WMr4L1n4PUOCiZT5gKh9ug", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Technical Margin Specifications

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The aim of this notebook is to document the Technical Margin (TM) and its allocation to the Contractual Service Margin (CSM), Loss Component (LC), or Loss Recovery Component (LoReCo). The process is pictorially explained in the following flowchart. ", + "\n", + "\n", + "\n
", + "\n", + "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." + ] + }, + { + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Data" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Current Period" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" + ] + }, + { + "cell_type": "code", + "source": [ + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Import the Dimensions, Parameters, Nominal Cashflows, and Actuals from the corresponding csv files in Initialization/Systemorph/" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Initialization of the Test Suite: the data loaded from csv files are ready to be used by the Scopes for the calculations" + ] + }, + { + "cell_type": "code", + "source": [ + "var Test = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## View loaded Data Nodes" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The imported active Data Nodes from Initialization/Systemorph/DataNodes.csv are " + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().DataNodeDataBySystemName" + ] + }, + { + "cell_type": "markdown", + "source": [ + "whereas the Data Nodes of your imported Cashflows are" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().DataNodesByImportScope[ImportScope.Primary]" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Please select here below the target Data Node for executing the tests below:" + ] + }, + { + "cell_type": "code", + "source": [ + "var dataNode = \"DT1.1\";" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## View list of Identities" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Based on the Cashflows imported, the list of all possible identities, i.e. combinations of valid Data Nodes, Aoc steps, and Novelties, is contructed and reported here below:" + ] + }, + { + "cell_type": "code", + "source": [ + "var allIdentities = Test.GetScopes(Test.GetStorage().DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities).ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "allIdentities" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Present Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Projected Present Values (PPVs) are calculated for each Amount Type (AT) either with the *locked-in* (L) and with the *current* (C) Yield Curves. While the former is the latest available as per end of the DataNode's inception year, the latter is the latest available as per the current period. ", + "\nPPVs for both Economic Basis L and C have been defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", + "\n", + "\nAccording to the BBA methodology, the CSM calculation uses the PV with locked-in Yield Curve simply defined as", + "\n", + "\n$$", + "\n\\text{PV Locked}(\\text{AoC}, \\text{AT}) = \\text{PPV}(\\text{AoC}, \\text{AT}) \\big|_{\\substack{ \\text{Calculation Type = BE} \\\\ \\text{Economic Base = L} } }", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "var pvsLocked = allIdentities.SelectMany(id => Test.GetScope(id).PresentValues", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromPvToIfrsVariable())).ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Below a view of the computed locked-in PV " + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForObjects(pvsLocked)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n .GroupColumnsBy(x => x.AmountType)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type):", + "\n", + "\n$$", + "\n\\text{PV Locked Value}(\\text{AoC}) = \\sum_{\\text{AT}} \\text{PV Locked}(\\text{AoC}, \\text{AT})", + "\n$$" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here below an example" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_BoP_I" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetScope( id_BoP_I ).Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Risk Adjustment" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The CSM calculation also uses locked-in Risk Adjustment (RA Locked) which is retrieved from the corresponding Present Value with [Calculation Type](../DataModel/DataStructure#calculation-type) being RA defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", + "\n", + "\nRisk Adjustment values can be written as", + "\n", + "\n$$", + "\n\\text{RA Locked Value}(\\text{AoC}) = \\text{PV}(\\text{AoC})|_{\\substack{ \\text{Calculation Type = RA} \\\\ \\text{Economic Base = L} }}", + "\n$$", + "\n", + "\nwhere the imported Cashflows for the RA Calculation Type are already aggregated over all [Amount Types](../DataModel/DataStructure#amount-type)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here below an example" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_BoP_I" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetScope( id_BoP_I ).Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The RA Locked per Data Node imported are" + ] + }, + { + "cell_type": "code", + "source": [ + "var rasLocked = allIdentities.SelectMany(id => Test.GetScope(id).PresentValues", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromPvToIfrsVariable())).ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForObjects(rasLocked)", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.EconomicBasis)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Technical Margin" + ] + }, + { + "cell_type": "markdown", + "source": [ + "For the computation of the CSM or LC components for each AoC step, it is convenient to introduce the notion of technical margin (TM).", + "\n", + "\nFirstly, it is useful to define the so-called Aggregated Technical Margin (ATM)", + "\n", + "\n$$", + "\n\\text{ATM} (\\text{AoC}) = \\sum_{s\\in\\text{previous AoC steps}} \\text{TM}(s) ~,", + "\n$$", + "\n", + "\nand the Interest Accretion Factor (IAF) ", + "\n", + "\n$$", + "\n\\text{IAF} = \\prod_{i=1}^{\\text{TS}} (1 + \\text{YC}_i) - 1 ~.", + "\n$$", + "\n", + "\nThe TM is defined as", + "\n", + "\n$$", + "\n\\text{TM}(\\text{AoC}) = \\left\\{", + "\n\\begin{array}{rl}", + "\n\\text{TM}(\\rm{EOP}) \\text{ of the previous period} ~ & \\text{if }s = \\text{BOP and Novelty is In-Force}. \\\\", + "\n0 ~ & \\text{if }s = \\text{CF}. \\\\", + "\n\\text{IAF} \\cdot ~ \\text{ATM}(\\text{AoC}) ~ & \\text{if }s = \\text{IA}. \\\\", + "\n\\rm{Premiums} + \\text{Attributable Expense and Commissions} + \\text{Investment Claims} ~ & \\text{if }s = \\text{EA}. \\\\", + "\n-\\text{AMF} \\cdot ~ \\text{ATM}(\\text{AoC}) ~ & \\text{if }s = \\text{AM}. \\\\", + "\n\\text{PV Locked Value}(\\text{AoC}) ", + "\n\\bigg|_{\\substack{\\text{Non Attributable} \\\\ ", + "\n \\text{Amount Types} \\\\ ", + "\n \\text{excluded}}} ", + "\n+ \\text{RA Locked Value}(\\text{AoC}) ~ & \\text{otherwise} ", + "\n\\end{array}", + "\n\\right.", + "\n$$", + "\n", + "\nwhere AMF is the Amortization Factor that is defined [here](../Import/ImportScopeCalculation#amortization-factor) and tested [here](SpecificationsImportCashflows#amortization-factor), with YC being the [Yield Curve](#yield-curves) and TS is the Time-Step, ", + "\nand the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", + "\n", + "\n$$", + "\n\\begin{array}{lcl}", + "\n\\rm{Premiums} &=& \\text{Premium Allocation Factor} \\cdot \\sum_{\\text{Amount Type}\\in\\{\\text{PR and its children}\\}}", + "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - ", + "\n \\big(\\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}} + \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~, \\\\", + "\n\\text{Attributable Expense and Commissions} &=& \\sum_{\\text{Amount Type}\\in\\{\\rm{ACA}, \\rm{AEA}\\}}", + "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - \\text{Actual}_{\\text{Novelty=C}} ~, \\\\", + "\n\\text{Investment Claims } &=& \\sum_{\\text{Amount Type}\\in\\{\\text{ICO and its children}\\}}", + "\n \\big(\\text{PV}_{\\text{Novelty = I}} + \\text{PV}_{\\text{Novelty = N}} \\big) - ", + "\n \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}} + \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~.", + "\n\\end{array}", + "\n$$", + "\n", + "\nThe AoC Type **CF** is implicit for all formulas, PV is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **OA** and **AA** (see details [here](../Import/ImportScopeCalculation#actual-base))." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Beginning of Period" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_BoP_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_BoP_I = Test.GetScope(id_BoP_I);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_BoP_I.Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The TM for BOP is equal to the TM for EOP of the previous period, that is, the sum of Csm, Loss Component and LoReCo as of at the end of last period (see the corresponding [formula](#technical-margins)). ", + "\n", + "\nThe corresponding **IFRS Variables** can be loaded directly from the *Storage*" + ] + }, + { + "cell_type": "code", + "source": [ + "var valueCsm = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.C, null);", + "\nvalueCsm" + ] + }, + { + "cell_type": "code", + "source": [ + "var valueLc = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.L, null);", + "\nvalueLc" + ] + }, + { + "cell_type": "code", + "source": [ + "var valueLr = Test.GetStorage().GetValue(id_BoP_I, null, EstimateTypes.LR, null);", + "\nvalueLr" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_BoP_I = -valueCsm + valueLc + valueLr;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_BoP_I" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_BoP_I.Value.Should().BeApproximately( expectedTM_BoP_I, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Model Corrections" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_MC_I = Test.GetIdentity(dataNode, \"MC\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_MC_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_MC_I = Test.GetScope(id_MC_I);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_MC_I.Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The TM for MC is given by the default [formula](#technical-margins), i.e. it is equal to the sum of PV and RA Locked, where the former does not encompass the *NonAttributable* Amount Types" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_MC_I = Test.GetScope(id_MC_I).Value + Test.GetScope( id_MC_I ).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_MC_I" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_MC_I.Value.Should().BeApproximately( expectedTM_MC_I, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Cash Flow" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_CF_I = Test.GetIdentity(dataNode, \"CF\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_CF_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_CF_I = Test.GetScope(id_CF_I);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_CF_I.Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, the tecnical margin is 0 for the Cash Flow AoC step " + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_CF_I.Value.Should().BeApproximately( 0, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Interest Accretion" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_IA_I = Test.GetIdentity(dataNode, \"IA\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_IA_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_IA_I = Test.GetScope(id_IA_I);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_IA_I.Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, for the AoC step IA, the TM is equal to sum of the TMs of its previous AoC step multiplied by the IAF. " + ] + }, + { + "cell_type": "markdown", + "source": [ + "The IAF associated to the current period (i.e. shift and time step) can be calculated from the shift, the time Step, and the Interest Rates" + ] + }, + { + "cell_type": "code", + "source": [ + "var projectionPeriod = 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "var shift = Test.GetStorage().GetShift(projectionPeriod);" + ] + }, + { + "cell_type": "code", + "source": [ + "var timeStep = Test.GetStorage().GetTimeStep(projectionPeriod);" + ] + }, + { + "cell_type": "code", + "source": [ + "(shift, timeStep)" + ] + }, + { + "cell_type": "code", + "source": [ + "var monthlyRates = Test.GetScope(id_IA_I);" + ] + }, + { + "cell_type": "code", + "source": [ + "monthlyRates" + ] + }, + { + "cell_type": "code", + "source": [ + "var IAF = Enumerable.Range(shift,timeStep).Select(i => monthlyRates.Interest.GetValidElement(i/12)).Aggregate(1.0d, (x, y) => x * y ) - 1.0d;" + ] + }, + { + "cell_type": "code", + "source": [ + "IAF" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Since the previous AoC steps are" + ] + }, + { + "cell_type": "code", + "source": [ + "var previousAocStep = Test.GetScope((id_IA_I, InputSource.Cashflow)).Values;", + "\npreviousAocStep" + ] + }, + { + "cell_type": "markdown", + "source": [ + "the expected TM for the Amortization step reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_IA_I = IAF * previousAocStep.Sum(aoc => Test.GetScope(id_IA_I with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_IA_I" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_IA_I.Value.Should().BeApproximately( expectedTM_IA_I, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Combined Liabilities" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_CL_C = Test.GetIdentity(dataNode, \"CL\", \"C\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_CL_C" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_CL_C = Test.GetScope(id_CL_C);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_CL_C.Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the default TM [formula](#technical-margins), for the CL step the TM is equal to the sum of PV and RA Locked, where the former does not encompass the *NonAttributable* Amount Types" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_CL_C = Test.GetScope(id_CL_C).Value + Test.GetScope( id_CL_C ).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_CL_C" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_CL_C.Value.Should().BeApproximately( expectedTM_CL_C, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Experience Adjustment" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_EA_C = Test.GetIdentity(dataNode, \"EA\", \"C\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_EA_C" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_EA_C = Test.GetScope(id_EA_C);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_EA_C.Value" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, for the AoC step EA, the TM is equal to sum of the Premiums, Attributable Expense and Commissions, and Investment Claims. Here below we calculate these terms individually." + ] + }, + { + "cell_type": "markdown", + "source": [ + "The Premiums, Attributable Expense and Commissions and Investment Claims Present Values and Actuals are calculated using the CF AoC step. Therefore, as first step we define the relevant AoC step and Novelties:" + ] + }, + { + "cell_type": "code", + "source": [ + "var referenceAoCType = Test.GetScope(id_EA_C).Value.AocType;", + "\nvar referenceAoC = Test.GetStorage().GetNovelties().Select(n => new AocStep(referenceAoCType, n));" + ] + }, + { + "cell_type": "code", + "source": [ + "referenceAoC" + ] + }, + { + "cell_type": "markdown", + "source": [ + "**Premiums**" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The list of Premiums Amount Type defined in the imported dimensions and the Premium Allocation Factor can be retrieved" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetStorage().GetPremiums()" + ] + }, + { + "cell_type": "code", + "source": [ + "var premiumAllocationFactor = Test.GetStorage().GetPremiumAllocationFactor(id_EA_C);" + ] + }, + { + "cell_type": "code", + "source": [ + "premiumAllocationFactor" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Lastly, the Premiums term is" + ] + }, + { + "cell_type": "code", + "source": [ + "var premiums = premiumAllocationFactor * Test.GetStorage().GetPremiums()", + "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.A, (int?)null)).Value)", + "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.AA, (int?)null)).Value)", + "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.OA, (int?)null)).Value)", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "premiums" + ] + }, + { + "cell_type": "markdown", + "source": [ + "**Attributable Expense and Commissions**" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Analogously, the Attributable Expense and Commissions term can be computed" + ] + }, + { + "cell_type": "code", + "source": [ + "var attributableExpenseAndCommissions = new string[] {AmountTypes.ACA, AmountTypes.AEA}", + "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, EstimateTypes.A, (int?)null)).Value));" + ] + }, + { + "cell_type": "code", + "source": [ + "attributableExpenseAndCommissions" + ] + }, + { + "cell_type": "markdown", + "source": [ + "**Investment Claims**" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Finally the Investment Claims term reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var investmentClaims = Test.GetStorage().GetInvestmentClaims()", + "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.A, (int?)null)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.AA, (int?)null)).Value)", + "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.OA, (int?)null)).Value)", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "investmentClaims" + ] + }, + { + "cell_type": "markdown", + "source": [ + "**Expected TM**" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_EA_C = premiums + attributableExpenseAndCommissions + investmentClaims;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_EA_C" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_EA_C.Value.Should().BeApproximately( expectedTM_EA_C, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Amortization" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_AM_C = Test.GetIdentity(dataNode, \"AM\", \"C\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_AM_C" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_AM_C = Test.GetScope(id_AM_C);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_AM_C.Value" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_AM_C" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#technical-margins) above, for the AoC step AM, the TM is equal to sum of the TMs of its previous AoC step multiplied by the amortization factor with opposite sign. ", + "\n", + "\nThe AoC step previous to Amortization are" + ] + }, + { + "cell_type": "code", + "source": [ + "var previousAocStep = Test.GetScope((id_AM_C, InputSource.Cashflow)).Values;", + "\npreviousAocStep" + ] + }, + { + "cell_type": "markdown", + "source": [ + "while the Amortization Factor can be retrieved in the following" + ] + }, + { + "cell_type": "code", + "source": [ + "Test.GetScope(id_AM_C)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Therefore, the expected TM for the Amortization step reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_AM_C = -Test.GetScope(id_AM_C).Value * ", + "\n previousAocStep.Sum(aoc => Test.GetScope(id_AM_C with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_AM_C" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_AM_C.Value.Should().BeApproximately( expectedTM_AM_C, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## End of Period" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_EoP_C = Test.GetIdentity(dataNode, \"EOP\", \"C\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_EoP_C" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedTM_EoP_C = Test.GetScope(id_EoP_C);" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_EoP_C.Value" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedTM_EoP_C = Test.GetScope( id_EoP_C ).Value + Test.GetScope( id_EoP_C ).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedTM_EoP_C" + ] + }, + { + "cell_type": "code", + "source": [ + "computedTM_EoP_C.Value.Should().BeApproximately( expectedTM_EoP_C, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Switch Logic " + ] + }, + { + "cell_type": "markdown", + "source": [ + "The CSM and LC figures are allocated for each AoC step based on the sign of the ATM. Specifically, for positive (negative) ATM, the TM of the current step is allocated to the LC (CSM), unless the TM flips the sign of the ATM. This special circumstance is named **switch**. It can happen at any AoC step with the only exception of Amortization where there is no switch from the previous step.", + "\nWhen a switch occurs the total contribution to the CSM (LC) prior the switching step is brought to 0 and the remaing amount is allocated to LC (CSM).", + "\n", + "\nIn the following the AoC chain is investigated." + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Beginning of Period", + "\n", + "\nFor the BOP, the last period is considered, which dictates that the corresponding EOP figures considered have necessarily Novelty of type *In-Force*.", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{BOP}) &=& \\text{CSM}(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force} \\\\", + "\n\\text{LC}(\\text{BOP}) &=& \\text{LC}(\\text{EOP}) \\text{ of the previous period, for Novelty In-Force}", + "\n\\end{array}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_BoP_I = Test.GetIdentity(dataNode, \"BOP\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_BoP_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", + "\nvar computedLC_BoP_I = Test.GetScope(id_BoP_I).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "(computedCSM_BoP_I, computedLC_BoP_I)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "To understand where the BOP is allocated, we retrieve the corresponding TM and, based on its sign, we expect the CSM or the LC to be non-zero according to the [formula](#switch-logic) above" + ] + }, + { + "cell_type": "code", + "source": [ + "var TM_BOP_I = Test.GetScope(id_BoP_I).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "TM_BOP_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedCSM_BoP_I = TM_BOP_I < 0 ? -TM_BOP_I : 0;", + "\nvar expectedLC_BoP_I = TM_BOP_I > 0 ? +TM_BOP_I : 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "(expectedCSM_BoP_I, expectedLC_BoP_I)" + ] + }, + { + "cell_type": "code", + "source": [ + "computedCSM_BoP_I.CheckEquality(computedCSM_BoP_I).Should().Be(true);", + "\nexpectedLC_BoP_I.CheckEquality(computedLC_BoP_I).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Following AoC steps" + ] + }, + { + "cell_type": "markdown", + "source": [ + "From the BOP up to the CL step, the switch logic is applied separately to the In-Force and New Business novelties." + ] + }, + { + "cell_type": "code", + "source": [ + "var id_MC_I = Test.GetIdentity(dataNode, \"MC\", \"I\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_MC_I" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", + "\nvar computedLC_MC_I = Test.GetScope(id_MC_I).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "(computedCSM_MC_I, computedLC_MC_I)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formula](#switch-logic) above this AoC step is allocated either to CSM or to LC based on the sign of ATM + TM. Both these two terms can be retrieved from the **TechnicalMargin** Scope." + ] + }, + { + "cell_type": "code", + "source": [ + "var TM_MC_I = Test.GetScope(id_MC_I);" + ] + }, + { + "cell_type": "code", + "source": [ + "TM_MC_I" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The correctness of the ATM can be checked by firstly withdrawing the previous AoC steps" + ] + }, + { + "cell_type": "code", + "source": [ + "var previousAocStep = Test.GetScope((id_MC_I, InputSource.Cashflow)).Values;" + ] + }, + { + "cell_type": "code", + "source": [ + "previousAocStep" + ] + }, + { + "cell_type": "markdown", + "source": [ + "and then evaluating the sum of the corresponding TMs" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedATM = previousAocStep.Sum(aoc => Test.GetScope(id_MC_I with {AocType = aoc.AocType, Novelty = aoc.Novelty}).Value);" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedATM" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Therefore, the following condition for ATM calculated by the **TechnicalMargin** Scope needs to be fullfilled" + ] + }, + { + "cell_type": "code", + "source": [ + "TM_MC_I.AggregatedValue.Should().BeApproximately( expectedATM, Precision );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The CSM and LC can be allocated according to the [Switch Logic](#switch-logic)." + ] + }, + { + "cell_type": "code", + "source": [ + "double expectedCSM_MC_I; ", + "\ndouble expectedLC_MC_I; " + ] + }, + { + "cell_type": "code", + "source": [ + "var aggregated = TM_MC_I.Value + TM_MC_I.AggregatedValue;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "If there is no switch from LC, i.e. $\\text{ATM} (\\text{AoC}) > 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\ge 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& 0 ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& \\text{TM}(\\text{AoC}) ~.", + "\n\\end{array}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue > 0 && aggregated >= 0) {", + "\n expectedCSM_MC_I = 0 ;", + "\n expectedLC_MC_I = TM_MC_I.Value ;", + "\n} " + ] + }, + { + "cell_type": "markdown", + "source": [ + "If there is no switch from CSM, i.e. $\\text{ATM} (\\text{AoC}) \\le 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\le 0 $, then:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& 0 ~.", + "\n\\end{array}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue < 0 && aggregated <= 0) {", + "\n expectedCSM_MC_I = -TM_MC_I.Value ;", + "\n expectedLC_MC_I = 0 ;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "If $\\text{ATM} (\\text{AoC}) > 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) \\le 0$, then there is a switch to CSM:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) -\\text{ATM} (\\text{AoC}) ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& -\\text{ATM} (\\text{AoC}) ~.", + "\n\\end{array}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue > 0 && aggregated <= 0) {", + "\n expectedCSM_MC_I = -aggregated;", + "\n expectedLC_MC_I = -TM_MC_I.AggregatedValue ;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "On the other hand, if $\\text{ATM} (\\text{AoC}) \\le 0$ and $\\text{ATM} (\\text{AoC}) + \\text{TM}(\\text{AoC}) > 0$, ", + "\nthen the switch is to LC:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& \\text{ATM} (\\text{AoC}) ~, \\\\", + "\n\\text{LC}(\\text{AoC}) &=& \\text{TM}(\\text{AoC}) + \\text{ATM} (\\text{AoC}) ~.", + "\n\\end{array}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "if(TM_MC_I.AggregatedValue <= 0 && aggregated > 0) {", + "\n expectedCSM_MC_I = TM_MC_I.AggregatedValue ;", + "\n expectedLC_MC_I = aggregated ;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Therefore, the expected CSM and LC for this step are" + ] + }, + { + "cell_type": "code", + "source": [ + "(expectedCSM_MC_I, expectedLC_MC_I)" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedCSM_MC_I.CheckEquality(computedCSM_MC_I).Should().Be(true);", + "\nexpectedLC_MC_I.CheckEquality(computedLC_MC_I).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Combined Liabilities" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The CL Aoc Step brings both contributions to CSM and LC together as the novelities are summed.", + "\n", + "\nFor the CL step, the logic is similar to the one above, except that a switch from LC to CSM can happen **because of New Business and despite of In-Force**, in which case we have:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& -\\text{TM}(\\text{AoC}) - \\text{ATM}(\\text{Last In-Force AoC step}) - \\text{TM}(\\text{Last In-Force AoC step}) \\\\", + "\n\\text{LC}(\\text{AoC}) &=& -\\text{ATM}(\\text{Last In-Force AoC step}) - \\text{TM}(\\text{Last In-Force AoC step})", + "\n\\end{array}", + "\n$$", + "\n", + "\nIf, on the other hand, the switch from LC to CSM happens **because of In-Force and despite of New Business**, then we have:", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{AoC}) &=& - \\text{TM}(\\text{AoC}) - \\text{ATM}(\\text{Last NB AoC step}) - \\text{TM}(\\text{Last NB AoC step}) \\\\", + "\n\\text{LC}(\\text{AoC}) &=& - \\text{ATM}(\\text{Last NB AoC step}) - \\text{TM}(\\text{Last NB AoC step})", + "\n\\end{array}", + "\n$$", + "\n", + "\nFor the switch in the other direction, i.e. from CSM to LC the formulas are similar except that LC and CSM are swapped." + ] + }, + { + "cell_type": "code", + "source": [ + "var id_CL_C = Test.GetIdentity(dataNode, \"CL\", \"C\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_CL_C" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", + "\nvar computedLC_CL_C = Test.GetScope(id_CL_C).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "(computedCSM_CL_C, computedLC_CL_C)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The CL step considers the last step of both the New Business and the In Force Novelties to decide what to allocate to CSM or LC. " + ] + }, + { + "cell_type": "code", + "source": [ + "var lastAocSteps = Test.GetScope((id_CL_C, InputSource.Cashflow)).Values.GroupBy(x => x.Novelty).Select(g => g.Last());" + ] + }, + { + "cell_type": "code", + "source": [ + "lastAocSteps" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Selecting the corresponding AocTypes:" + ] + }, + { + "cell_type": "code", + "source": [ + "var lastAocTypeNb = lastAocSteps.Single(x => x.Novelty == Novelties.N).AocType;", + "\nvar lastAocTypeI = lastAocSteps.Single(x => x.Novelty == Novelties.I).AocType;", + "\n(lastAocTypeI, lastAocTypeNb)" + ] + }, + { + "cell_type": "code", + "source": [ + "var lastTM_NewBusiness = Test.GetScope(id_CL_C with {AocType = lastAocTypeNb, Novelty = Novelties.N});" + ] + }, + { + "cell_type": "code", + "source": [ + "lastTM_NewBusiness" + ] + }, + { + "cell_type": "code", + "source": [ + "var lastTM_InForce = Test.GetScope(id_CL_C with {AocType = lastAocTypeI, Novelty = Novelties.I});" + ] + }, + { + "cell_type": "code", + "source": [ + "lastTM_InForce" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Conversely the TM and ATM for the CL step is" + ] + }, + { + "cell_type": "code", + "source": [ + "var TM_Combined = Test.GetScope(id_CL_C);" + ] + }, + { + "cell_type": "code", + "source": [ + "TM_Combined" + ] + }, + { + "cell_type": "markdown", + "source": [ + "where the ATM of CL is given by the sum of the ATMs of the New Business and In Force Novelties" + ] + }, + { + "cell_type": "code", + "source": [ + "var aggregatedNewBusiness = lastTM_NewBusiness.Value + lastTM_NewBusiness.AggregatedValue;", + "\nvar aggregatedInForce = lastTM_InForce.Value + lastTM_InForce.AggregatedValue;", + "\nvar sum = aggregatedNewBusiness + aggregatedInForce;", + "\nsum" + ] + }, + { + "cell_type": "code", + "source": [ + "( (sum - TM_Combined.AggregatedValue)/sum < 1.0e-12).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "In order to decide where the TM of the CL step is allocated, one has to check the sign of the ATM + TM for both the New Business and the In Force" + ] + }, + { + "cell_type": "code", + "source": [ + "var aggregatedCombined = TM_Combined.Value + TM_Combined.AggregatedValue;", + "\naggregatedCombined" + ] + }, + { + "cell_type": "markdown", + "source": [ + "According to the [formulas above](#combined-liabilities), for a positive (negative) aggregated CL value, the CL TM has to be allocated to LC (CSM). ", + "\n
In case the one of last Aoc step of the novelties (I, NB) has the sign of the CL ATM opposite to the CL ATM, the CL AocStep is used to introduce a balancing item to bring the ATM of the novelty with opposite sign to 0. ", + "\n
This is equivalent to execute the switch logic with a balancing item = ATM of the last AocStep having opposite sign to CL ATM. ", + "\n
Note that if CL TM is zero this results in allocating the same amount with opposite sign to CSM(note that the sign of the CSM componet is flipped) and LC." + ] + }, + { + "cell_type": "code", + "source": [ + "double expectedCSM_CL_C; ", + "\ndouble expectedLC_CL_C; " + ] + }, + { + "cell_type": "code", + "source": [ + "var balancingItem = aggregatedCombined < 0 ? aggregatedNewBusiness : aggregatedInForce;", + "\nbalancingItem" + ] + }, + { + "cell_type": "code", + "source": [ + "", + "\nif(aggregatedCombined > 0) {", + "\n expectedCSM_CL_C = balancingItem ;", + "\n expectedLC_CL_C = TM_Combined.Value + balancingItem;", + "\n} else {", + "\n expectedLC_CL_C = - balancingItem ;", + "\n expectedCSM_CL_C = TM_Combined.Value - balancingItem ;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "(expectedCSM_CL_C, expectedLC_CL_C)" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedCSM_CL_C.CheckEquality(computedCSM_CL_C).Should().Be(true);", + "\nexpectedLC_CL_C.CheckEquality(computedLC_CL_C).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## End Of Period", + "\n", + "\nFor the last AoC step, the EOP is the sum of all previous steps", + "\n", + "\n$$", + "\n\\begin{array}{rcl}", + "\n\\text{CSM}(\\text{EOP}) &=& \\sum_{s~\\in~\\text{previous AoC steps}} \\text{CSM}(s) ~, \\\\", + "\n\\text{LC}(\\text{EOP}) &=& \\sum_{s~\\in~\\text{previous AoC steps}} \\text{LC}(s) ~.", + "\n\\end{array}", + "\n$$" + ] + }, + { + "cell_type": "code", + "source": [ + "var id_EoP_C = Test.GetIdentity(dataNode, \"EOP\", \"C\");" + ] + }, + { + "cell_type": "code", + "source": [ + "id_EoP_C" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", + "\nvar computedLC_EoP_C = Test.GetScope(id_EoP_C).Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "(computedCSM_EoP_C, computedLC_EoP_C)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n
", + "\nFor the reinsurance case, the switch logic is identical to the one described above, except that it uses the corresponding gross case TM to allocate the figure either to CSM or to LoReCo. The reinsurance gross TM multiplied by the weights coming from the Reinsurance Coverage Parameter (Data Node Parameters). In case a GRIC has multiple GICs, then these weighted TMs are aggregated.", + "\n
" + ] + }, + { + "cell_type": "markdown", + "source": [ + "" + ] + }, + { + "cell_type": "markdown", + "source": [ + "

", + "\n", + "\n# Contractual Service Margin and Loss Component" + ] + }, + { + "cell_type": "markdown", + "source": [ + "Here below a view of the CSM and Loss Component results are shown. ", + "\n", + "\nNote: the Data Nodes with LiabilityType being *LIC* are excluded." + ] + }, + { + "cell_type": "code", + "source": [ + "var allIdentitiesWoLic = allIdentities.Where(id => Test.GetStorage().DataNodeDataBySystemName[id.DataNode].LiabilityType != \"LIC\").ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromCsmToIfrsVariable())).ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Gross case" + ] + }, + { + "cell_type": "code", + "source": [ + "var allInsuranceIdentitiesWoLic = allIdentitiesWoLic.Where(id => !id.IsReinsurance).ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "var lc = allInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromLcToIfrsVariable())).ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Re-Insurance case (LoReCo)" + ] + }, + { + "cell_type": "code", + "source": [ + "var allReInsuranceIdentitiesWoLic = allIdentitiesWoLic.Where(id => id.IsReinsurance).ToArray();" + ] + }, + { + "cell_type": "code", + "source": [ + "var loreco = allReInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "\n .Where(x => Math.Abs(x.Value) >= Precision)", + "\n .Select(x => x.FromLoReCoToIfrsVariable())).ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Summary" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForObjects( csm.Concat(lc).Concat(loreco) )", + "\n .WithQuerySource(Workspace)", + "\n .GroupColumnsBy(x => x.DataNode)", + "\n .GroupColumnsBy(x => x.EstimateType)", + "\n .GroupRowsBy(x => x.Novelty)", + "\n .GroupRowsBy(x => x.AocType)", + "\n .WithGridOptionsForIfrsVariable()", + "\n .ToReport()" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/TechnicalMarginTest.ipynb b/Test/TechnicalMarginTest.ipynb index d42316d9..9a79f348 100644 --- a/Test/TechnicalMarginTest.ipynb +++ b/Test/TechnicalMarginTest.ipynb @@ -1,305 +1,259 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "jaNl5tr4gEGSSk1KTK2HpA", - "cell_type": "markdown", - "source": [ - "

Technical Margin Allocation

" - ], - "metadata": {} - }, - { - "id": "E5WE0di2k0aFigu3aInmKw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "YndlmtSQOkuhu3OKAyNj0g", - "cell_type": "markdown", - "source": [ - "# Workspace Initialization " - ], - "metadata": {} - }, - { - "id": "7vwzSP8vUkSmgw1mvnWC1Q", - "cell_type": "code", - "source": [ - "Workspace.Initialize(x => x.FromSource(DataSource)", - "\n .DisableInitialization()", - "\n .DisableInitialization());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TP-eEY5maEC5c7pVOpolxQ", - "cell_type": "markdown", - "source": [ - "# Test switch logic" - ], - "metadata": {} - }, - { - "id": "nhjoP-0CWUadpg116YgH6Q", - "cell_type": "code", - "source": [ - "//define group of contract", - "\nvar groupOfContract = \"DT1.1\";" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "nvCLj-DBhk211_Y_UDi0uQ", - "cell_type": "code", - "source": [ - "//Define partition", - "\n var args = new ImportArgs(\"CH\", 2020, 12, Periodicity.Quarterly, null, ImportFormats.Actual);", - "\n var partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", - "\n x.Month == args.Month && x.Scenario == args.Scenario);", - "\n if(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UmXmnz87HUKCgw066Gsx5A", - "cell_type": "code", - "source": [ - "public async Task CheckSwitchLogicAsync(IEnumerable inputDataSet, Dictionary csmLcSwitchBenchmark)", - "\n{", - "\n //Save test input data", - "\n await Workspace.UpdateAsync(inputDataSet);", - "\n ", - "\n //Set up import storage and test universe", - "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", - "\n await testStorage.InitializeAsync();", - "\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();", - "\n ", - "\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == groupOfContract)).SelectMany(s => s.Identities);", - "\n var csm = testUniverse.GetScopes(identities, o => o.WithContext(\"C\")).Where(x => Math.Abs(x.Value) > Precision);", - "\n var lc = testUniverse.GetScopes(identities, o => o.WithContext(\"L\")).Where(x => Math.Abs(x.Value) > Precision);", - "\n //Clean up Workspace", - "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", - "\n ", - "\n var csmBenchmark = csmLcSwitchBenchmark.Where(x => Math.Abs(x.Value.valueCsm) > Precision).ToDictionary(x => x.Key, x => x.Value);", - "\n var lcBenchmark = csmLcSwitchBenchmark.Where(x => Math.Abs(x.Value.valueLc) > Precision).ToDictionary(x => x.Key, x => x.Value);", - "\n ", - "\n ", - "\n var errors = new List();", - "\n if(csm.Count() > csmBenchmark.Count()) ", - "\n {", - "\n var extraVariables = csm.Where(x => !csmBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))", - "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}.\");", - "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for CSM has more non zero items than benchmark. Extra computed variables : \\n {string.Join(\"\\n\", extraVariables)}.\" );", - "\n }", - "\n if(lc.Count() > lcBenchmark.Count()) ", - "\n {", - "\n var extraVariables = lc.Where(x => !lcBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))", - "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}, \");", - "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for LC has more non zero items compared to benchmark: \\n {string.Join(\"\\n\", extraVariables)}.\" );", - "\n }", - "\n ", - "\n //Check ValueCsm", - "\n foreach(var kvp in csmBenchmark)", - "\n {", - "\n var scopeSwitch = csm.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", - "\n ", - "\n if(scopeSwitch == null)", - "\n {", - "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );", - "\n continue;", - "\n }", - "\n ", - "\n if(Math.Abs(-1.0 * scopeSwitch.Value - kvp.Value.valueCsm) > Precision) ", - "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Csm {-1 * scopeSwitch.Value}; Benchmark: Csm {kvp.Value.valueCsm}.\" );", - "\n }", - "\n //Check ValueLc", - "\n foreach(var kvp in lcBenchmark)", - "\n {", - "\n var scopeSwitch = lc.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", - "\n ", - "\n if(scopeSwitch == null)", - "\n {", - "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );", - "\n continue;", - "\n }", - "\n ", - "\n if(Math.Abs(scopeSwitch.Value - kvp.Value.valueLc) > Precision) ", - "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Lc {scopeSwitch.Value}; Benchmark: Lc {kvp.Value.valueLc}.\" );", - "\n }", - "\n ", - "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "qKbQQyYPQU-Iye0tiP7x5A", - "cell_type": "code", - "source": [ - "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", - "\nvar inputDataSet = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", - "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", - "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 15.0},", - "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = 100.0},", - "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = 100.0},", - "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", - "\n };", - "\n", - "\nvar csmLcSwitch_benchmark = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"N\"),(0d, 100d)},", - "\n {new AocStep(\"IA\",\"N\"), (0d, 15d)},", - "\n {new AocStep(\"EV\",\"N\"), (0d, 100d)},", - "\n {new AocStep(\"CL\",\"C\"), (0d, 100d)},", - "\n {new AocStep(\"EA\",\"C\"), (0d, -8.0)},", - "\n {new AocStep(\"AM\",\"C\"), (0d, -153.5)},", - "\n {new AocStep(\"EOP\",\"C\"),(0d, 153.5)},", - "\n };", - "\n", - "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "TK8_VLRvbkOFHfCgScgBGg", - "cell_type": "code", - "source": [ - "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", - "\nvar inputDataSet = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", - "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", - "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 15.0},", - "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = 100.0},", - "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = -500.0},", - "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", - "\n };", - "\n", - "\nvar csmLcSwitch_benchmark = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"N\"),(0d, 100d)},", - "\n {new AocStep(\"IA\",\"N\"), (0d, 15d)},", - "\n {new AocStep(\"EV\",\"N\"), (0d, 100d)},", - "\n {new AocStep(\"CL\",\"C\"), (285d, -215d)},", - "\n {new AocStep(\"EA\",\"C\"), (8d, 0d)},", - "\n {new AocStep(\"AM\",\"C\"), (-146.5d, 0d)},", - "\n {new AocStep(\"EOP\",\"C\"),(146.5d, 0d)},", - "\n };", - "\n", - "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zFF7F81APUmclfr-m3jMcw", - "cell_type": "code", - "source": [ - "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", - "\nvar inputDataSet = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", - "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", - "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = -150.0},", - "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", - "\n };", - "\n", - "\nvar csmLcSwitch_benchmark = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"N\"), (0d, 100d)},", - "\n {new AocStep(\"IA\",\"N\"), (50d, -100d)},", - "\n {new AocStep(\"EA\",\"C\"), (8d, 0d)},", - "\n {new AocStep(\"AM\",\"C\"), (-29d, 0d)},", - "\n {new AocStep(\"EOP\",\"C\"),(29d, 0d)},", - "\n };", - "\n", - "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HBM6I7rP8UeMjn0PNDOkvg", - "cell_type": "code", - "source": [ - "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", - "\nvar inputDataSet = new IfrsVariable[]{", - "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"I\", Value = 5010.0, EstimateType = \"L\", AmountType = null},", - "\n basicIfrsVariable with {AocType = \"MC\", Novelty = \"I\", Value = -10.0},", - "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"I\", Value = -5015.0},", - "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = -100.0},", - "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = 10.0},", - "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 150.0},", - "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = -45.0},", - "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = -30.0},", - "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", - "\n };", - "\n", - "\nvar csmLcSwitch_benchmark = new Dictionary()", - "\n {", - "\n {new AocStep(\"BOP\",\"I\"),( 0d, 5010.0)},", - "\n {new AocStep(\"MC\",\"I\"), ( 0d, -10d)},", - "\n {new AocStep(\"IA\",\"I\"), ( 0d, 10d)},", - "\n {new AocStep(\"EV\",\"I\"), ( 5d,-5010d)},", - "\n ", - "\n {new AocStep(\"BOP\",\"N\"),(100d, 0d)},", - "\n {new AocStep(\"IA\",\"N\"), (-100d, 50d)},", - "\n {new AocStep(\"EV\",\"N\"), ( 0d, -45d)},", - "\n ", - "\n {new AocStep(\"CL\",\"C\"), ( 25d, -5d)},", - "\n {new AocStep(\"EA\",\"C\"), ( -8d, 0d)},", - "\n {new AocStep(\"AM\",\"C\"), ( -11d, 0d)},", - "\n {new AocStep(\"EOP\",\"C\"),( 11d, 0d)},", - "\n };", - "\n", - "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0mf1wwWN00-8_xIdPwv8aA", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Technical Margin Allocation

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.Initialize(x => x.FromSource(DataSource)", + "\n .DisableInitialization()", + "\n .DisableInitialization());" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test switch logic" + ] + }, + { + "cell_type": "code", + "source": [ + "//define group of contract", + "\nvar groupOfContract = \"DT1.1\";" + ] + }, + { + "cell_type": "code", + "source": [ + "//Define partition", + "\n var args = new ImportArgs(\"CH\", 2020, 12, Periodicity.Quarterly, null, ImportFormats.Actual);", + "\n var partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\n if(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ] + }, + { + "cell_type": "code", + "source": [ + "public async Task CheckSwitchLogicAsync(IEnumerable inputDataSet, Dictionary csmLcSwitchBenchmark)", + "\n{", + "\n //Save test input data", + "\n await Workspace.UpdateAsync(inputDataSet);", + "\n ", + "\n //Set up import storage and test universe", + "\n var testStorage = new ImportStorage(args, DataSource, Workspace);", + "\n await testStorage.InitializeAsync();", + "\n var testUniverse = Scopes.ForStorage(testStorage).ToScope();", + "\n ", + "\n var identities = testUniverse.GetScopes(testStorage.DataNodesByImportScope[ImportScope.Primary].Where(dn => dn == groupOfContract)).SelectMany(s => s.Identities);", + "\n var csm = testUniverse.GetScopes(identities, o => o.WithContext(\"C\")).Where(x => Math.Abs(x.Value) > Precision);", + "\n var lc = testUniverse.GetScopes(identities, o => o.WithContext(\"L\")).Where(x => Math.Abs(x.Value) > Precision);", + "\n //Clean up Workspace", + "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync()); ", + "\n ", + "\n var csmBenchmark = csmLcSwitchBenchmark.Where(x => Math.Abs(x.Value.valueCsm) > Precision).ToDictionary(x => x.Key, x => x.Value);", + "\n var lcBenchmark = csmLcSwitchBenchmark.Where(x => Math.Abs(x.Value.valueLc) > Precision).ToDictionary(x => x.Key, x => x.Value);", + "\n ", + "\n ", + "\n var errors = new List();", + "\n if(csm.Count() > csmBenchmark.Count()) ", + "\n {", + "\n var extraVariables = csm.Where(x => !csmBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))", + "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}.\");", + "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for CSM has more non zero items than benchmark. Extra computed variables : \\n {string.Join(\"\\n\", extraVariables)}.\" );", + "\n }", + "\n if(lc.Count() > lcBenchmark.Count()) ", + "\n {", + "\n var extraVariables = lc.Where(x => !lcBenchmark.Keys.Contains(new AocStep(x.Identity.AocType, x.Identity.Novelty)))", + "\n .Select(x => $\"AocType:{x.Identity.AocType}, Novelty:{x.Identity.Novelty}, EstimateType:{x.EstimateType}, Value:{x.Value}, \");", + "\n errors.Add( $\"{nameof(AllocateTechnicalMargin)} scope for LC has more non zero items compared to benchmark: \\n {string.Join(\"\\n\", extraVariables)}.\" );", + "\n }", + "\n ", + "\n //Check ValueCsm", + "\n foreach(var kvp in csmBenchmark)", + "\n {", + "\n var scopeSwitch = csm.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", + "\n ", + "\n if(scopeSwitch == null)", + "\n {", + "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );", + "\n continue;", + "\n }", + "\n ", + "\n if(Math.Abs(-1.0 * scopeSwitch.Value - kvp.Value.valueCsm) > Precision) ", + "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Csm {-1 * scopeSwitch.Value}; Benchmark: Csm {kvp.Value.valueCsm}.\" );", + "\n }", + "\n //Check ValueLc", + "\n foreach(var kvp in lcBenchmark)", + "\n {", + "\n var scopeSwitch = lc.SingleOrDefault(y => y.Identity.AocType == kvp.Key.AocType && y.Identity.Novelty == kvp.Key.Novelty);", + "\n ", + "\n if(scopeSwitch == null)", + "\n {", + "\n errors.Add( $\"Missing calculated scope for AocType and Novelty: {kvp.Key.AocType}, {kvp.Key.Novelty}.\" );", + "\n continue;", + "\n }", + "\n ", + "\n if(Math.Abs(scopeSwitch.Value - kvp.Value.valueLc) > Precision) ", + "\n errors.Add( $\"Values not matching for AocType {kvp.Key.AocType} and Novelty {kvp.Key.Novelty}. Scope: Lc {scopeSwitch.Value}; Benchmark: Lc {kvp.Value.valueLc}.\" );", + "\n }", + "\n ", + "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 15.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"N\"),(0d, 100d)},", + "\n {new AocStep(\"IA\",\"N\"), (0d, 15d)},", + "\n {new AocStep(\"EV\",\"N\"), (0d, 100d)},", + "\n {new AocStep(\"CL\",\"C\"), (0d, 100d)},", + "\n {new AocStep(\"EA\",\"C\"), (0d, -8.0)},", + "\n {new AocStep(\"AM\",\"C\"), (0d, -153.5)},", + "\n {new AocStep(\"EOP\",\"C\"),(0d, 153.5)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 15.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = -500.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"N\"),(0d, 100d)},", + "\n {new AocStep(\"IA\",\"N\"), (0d, 15d)},", + "\n {new AocStep(\"EV\",\"N\"), (0d, 100d)},", + "\n {new AocStep(\"CL\",\"C\"), (285d, -215d)},", + "\n {new AocStep(\"EA\",\"C\"), (8d, 0d)},", + "\n {new AocStep(\"AM\",\"C\"), (-146.5d, 0d)},", + "\n {new AocStep(\"EOP\",\"C\"),(146.5d, 0d)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = 100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = -150.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"N\"), (0d, 100d)},", + "\n {new AocStep(\"IA\",\"N\"), (50d, -100d)},", + "\n {new AocStep(\"EA\",\"C\"), (8d, 0d)},", + "\n {new AocStep(\"AM\",\"C\"), (-29d, 0d)},", + "\n {new AocStep(\"EOP\",\"C\"),(29d, 0d)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "var basicIfrsVariable = new IfrsVariable{Partition = partition.Id, DataNode = groupOfContract, AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\", EconomicBasis = \"L\"};", + "\nvar inputDataSet = new IfrsVariable[]{", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"I\", Value = 5010.0, EstimateType = \"L\", AmountType = null},", + "\n basicIfrsVariable with {AocType = \"MC\", Novelty = \"I\", Value = -10.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"I\", Value = -5015.0},", + "\n basicIfrsVariable with {AocType = \"BOP\", Novelty = \"N\", Value = -100.0},", + "\n basicIfrsVariable with {AocType = \"CF\", Novelty = \"N\", Value = 10.0},", + "\n basicIfrsVariable with {AocType = \"IA\", Novelty = \"N\", Value = 150.0},", + "\n basicIfrsVariable with {AocType = \"EV\", Novelty = \"N\", Value = -45.0},", + "\n basicIfrsVariable with {AocType = \"CL\", Novelty = \"C\", Value = -30.0},", + "\n basicIfrsVariable with {AocType = \"AM\", Novelty = \"C\", Value = 0.5, EstimateType = \"F\", AmountType = null},", + "\n };", + "\n", + "\nvar csmLcSwitch_benchmark = new Dictionary()", + "\n {", + "\n {new AocStep(\"BOP\",\"I\"),( 0d, 5010.0)},", + "\n {new AocStep(\"MC\",\"I\"), ( 0d, -10d)},", + "\n {new AocStep(\"IA\",\"I\"), ( 0d, 10d)},", + "\n {new AocStep(\"EV\",\"I\"), ( 5d,-5010d)},", + "\n ", + "\n {new AocStep(\"BOP\",\"N\"),(100d, 0d)},", + "\n {new AocStep(\"IA\",\"N\"), (-100d, 50d)},", + "\n {new AocStep(\"EV\",\"N\"), ( 0d, -45d)},", + "\n ", + "\n {new AocStep(\"CL\",\"C\"), ( 25d, -5d)},", + "\n {new AocStep(\"EA\",\"C\"), ( -8d, 0d)},", + "\n {new AocStep(\"AM\",\"C\"), ( -11d, 0d)},", + "\n {new AocStep(\"EOP\",\"C\"),( 11d, 0d)},", + "\n };", + "\n", + "\nawait CheckSwitchLogicAsync(inputDataSet, csmLcSwitch_benchmark);" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Test/Tests.ipynb b/Test/Tests.ipynb index 1cd4f874..538dbf00 100644 --- a/Test/Tests.ipynb +++ b/Test/Tests.ipynb @@ -1,183 +1,123 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "TZgppEey_UevldeIhLk-Zg", - "cell_type": "markdown", - "source": [ - "

Tests

" - ], - "metadata": {} - }, - { - "id": "SyI_QtXCw0yCEOXRPFFsww", - "cell_type": "code", - "source": [ - "#!eval-notebook \"IfrsVariablesTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-uMg4UaFbECZuIbtwJCvJw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"ImportStorageTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "x_X1-9LqmkCGI9R1UOQo6A", - "cell_type": "code", - "source": [ - "#!eval-notebook \"ReportStorageTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fTEQQtLuT0uQ01JBhmVGzw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"QueriesTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "iRWR94CbKU-eP1eVu7LpbA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"AocStructureTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Omg1EkcRJ0miK9epGdB5Fg", - "cell_type": "code", - "source": [ - "#!eval-notebook \"TechnicalMarginTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "EMHkr07qoEyWT3n-TUrE_A", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "XYHMD6zOzUS3CLOcyaAq_g", - "cell_type": "code", - "source": [ - "#!eval-notebook \"SpecificationsImportCashflows\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HfcLmG39kE2VFzt18WLEKA", - "cell_type": "code", - "source": [ - "#!eval-notebook \"SpecificationsImportActuals\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XgjC6ZJsvkGNTDeP374MXw", - "cell_type": "code", - "source": [ - "#!eval-notebook \"SpecificationsTechnicalMargin\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-zjdp-ODe0qnHVp1-wr02A", - "cell_type": "code", - "source": [ - "#!eval-notebook \"SpecificationsFinancialPerformance\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "QtahA_wtJUmc5mWycmnjzA", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "xfKpAnti3UaiKrOBQeD8gw", - "cell_type": "code", - "source": [ - "//#!eval-notebook \"MapTemplateAndImportTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "5jyZtMUGUU6YhrXXY2mMqQ", - "cell_type": "markdown", - "source": [ - "---" - ], - "metadata": {} - }, - { - "id": "hvH198RRBUGXwPc-HsgU0A", - "cell_type": "code", - "source": [ - "#!eval-notebook \"ReportVariablesTest\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Q8h-6uY0TkCHeLq1bFnNhQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Tests

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"IfrsVariablesTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"ImportStorageTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"ReportStorageTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"QueriesTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"AocStructureTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"TechnicalMarginTest\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsImportCashflows\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsImportActuals\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsTechnicalMargin\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"SpecificationsFinancialPerformance\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "code", + "source": [ + "//#!eval-notebook \"MapTemplateAndImportTest\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"ReportVariablesTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Utils/ApplicationMessage.ipynb b/Utils/ApplicationMessage.ipynb index 80df11f5..a41569e3 100644 --- a/Utils/ApplicationMessage.ipynb +++ b/Utils/ApplicationMessage.ipynb @@ -1,149 +1,117 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "broxX4LAHEyOyWz2MhegDg", - "cell_type": "markdown", - "source": [ - "

Application Message

" - ], - "metadata": {} - }, - { - "id": "h1R2W32vMUu5tJyRO8rd4A", - "cell_type": "code", - "source": [ - "#r \"nuget:Systemorph.Activities,1.2.3\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "84ytRYskFU-7SEmFS1wFiA", - "cell_type": "code", - "source": [ - "#!import \"../Constants/Validations\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zdCOoGGKDUad4bauxbDx8A", - "cell_type": "code", - "source": [ - "using Microsoft.Extensions.Logging;", - "\n", - "\npublic class ApplicationMessage {", - "\n private static ILogger log;", - "\n ", - "\n private static IActivityVariable activity;", - "\n ", - "\n public static void Configure (ILogger log, IActivityVariable activity) ", - "\n {", - "\n ApplicationMessage.log = log;", - "\n ApplicationMessage.activity = activity;", - "\n }", - "\n ", - "\n public static Object Log (Error e, params string[] s) { log.LogError(Get(e,s)); return null; }", - "\n ", - "\n public static Object Log (Warning w, params string[] s) { log.LogWarning(Get(w,s)); return null; }", - "\n ", - "\n public static bool HasErrors () => activity.HasErrors();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "rmXkyteAs0qIkylMj_uzoA", - "cell_type": "code", - "source": [ - "ApplicationMessage.Configure(Log, Activity)" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "C5Sz9dotT0ye5OfZ9kKzZg", - "cell_type": "markdown", - "source": [ - "# Utils" - ], - "metadata": {} - }, - { - "id": "PI-rD5MuDkm1oNDAzAlxdQ", - "cell_type": "code", - "source": [ - "public static bool HasErrors (this ActivityLog[] logs) {", - "\n foreach (var log in logs)", - "\n if(log.Errors.Any())", - "\n return true;", - "\n return false;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zP4DHMB7v0iJBQU0evmyJQ", - "cell_type": "code", - "source": [ - "public static ActivityLog Merge (this ActivityLog a, ActivityLog b) {", - "\n return a with { ", - "\n StartDateTime = a.StartDateTime < b.StartDateTime ? a.StartDateTime : b.StartDateTime,", - "\n FinishDateTime = a.FinishDateTime > b.FinishDateTime ? a.FinishDateTime : b.FinishDateTime,", - "\n Errors = a.Errors.Concat(b.Errors).ToList(),", - "\n Warnings = a.Warnings.Concat(b.Warnings).ToList(),", - "\n Infos = a.Infos.Concat(b.Infos).ToList(),", - "\n Status = a.Status == ActivityLogStatus.Failed || b.Status == ActivityLogStatus.Failed ? ActivityLogStatus.Failed : ActivityLogStatus.Succeeded", - "\n };", - "\n}", - "\n", - "\npublic static ActivityLog Merge (this ActivityLog[] logs) ", - "\n{", - "\n if(logs == null || logs.Length == 0) return null;", - "\n return logs.Aggregate((x, y) => x.Merge(y));", - "\n}", - "\n", - "\npublic static ActivityLog Merge (this ActivityLog[] logs, ActivityLog log) => logs.Merge().Merge(log);", - "\npublic static ActivityLog Merge (this ActivityLog log, ActivityLog[] logs) => log.Merge(logs.Merge());" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CdUfdMGymkqjIXT66mL65g", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Application Message

" + ] + }, + { + "cell_type": "code", + "source": [ + "#r \"nuget:Systemorph.Activities,1.2.3\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Constants/Validations\"" + ] + }, + { + "cell_type": "code", + "source": [ + "using Microsoft.Extensions.Logging;", + "\n", + "\npublic class ApplicationMessage {", + "\n private static ILogger log;", + "\n ", + "\n private static IActivityVariable activity;", + "\n ", + "\n public static void Configure (ILogger log, IActivityVariable activity) ", + "\n {", + "\n ApplicationMessage.log = log;", + "\n ApplicationMessage.activity = activity;", + "\n }", + "\n ", + "\n public static Object Log (Error e, params string[] s) { log.LogError(Get(e,s)); return null; }", + "\n ", + "\n public static Object Log (Warning w, params string[] s) { log.LogWarning(Get(w,s)); return null; }", + "\n ", + "\n public static bool HasErrors () => activity.HasErrors();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "ApplicationMessage.Configure(Log, Activity)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Utils" + ] + }, + { + "cell_type": "code", + "source": [ + "public static bool HasErrors (this ActivityLog[] logs) {", + "\n foreach (var log in logs)", + "\n if(log.Errors.Any())", + "\n return true;", + "\n return false;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static ActivityLog Merge (this ActivityLog a, ActivityLog b) {", + "\n return a with { ", + "\n StartDateTime = a.StartDateTime < b.StartDateTime ? a.StartDateTime : b.StartDateTime,", + "\n FinishDateTime = a.FinishDateTime > b.FinishDateTime ? a.FinishDateTime : b.FinishDateTime,", + "\n Errors = a.Errors.Concat(b.Errors).ToList(),", + "\n Warnings = a.Warnings.Concat(b.Warnings).ToList(),", + "\n Infos = a.Infos.Concat(b.Infos).ToList(),", + "\n Status = a.Status == ActivityLogStatus.Failed || b.Status == ActivityLogStatus.Failed ? ActivityLogStatus.Failed : ActivityLogStatus.Succeeded", + "\n };", + "\n}", + "\n", + "\npublic static ActivityLog Merge (this ActivityLog[] logs) ", + "\n{", + "\n if(logs == null || logs.Length == 0) return null;", + "\n return logs.Aggregate((x, y) => x.Merge(y));", + "\n}", + "\n", + "\npublic static ActivityLog Merge (this ActivityLog[] logs, ActivityLog log) => logs.Merge().Merge(log);", + "\npublic static ActivityLog Merge (this ActivityLog log, ActivityLog[] logs) => log.Merge(logs.Merge());" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file diff --git a/Utils/UtilityMethods.ipynb b/Utils/UtilityMethods.ipynb index 8390e86f..c3706f06 100644 --- a/Utils/UtilityMethods.ipynb +++ b/Utils/UtilityMethods.ipynb @@ -1,1155 +1,899 @@ { - "metadata": { - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "authors": [], - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - } - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "id": "72RJn3yBk0-cdIRCo3QO6A", - "cell_type": "code", - "source": [ - "#!import \"../DataModel/DataStructure\"", - "\n#!import \"./ApplicationMessage\"" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "bTXVV8ziO0GApQeS_y9z3Q", - "cell_type": "code", - "source": [ - "using System.Linq.Expressions;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "0rrQ118FOkCCJosdbGYr_Q", - "cell_type": "markdown", - "source": [ - "# Math Functions" - ], - "metadata": {} - }, - { - "id": "JSuwpYPWEE-_BxSyEyzsbQ", - "cell_type": "code", - "source": [ - "static double DivideOrDefault(double numerator, double denominator, double defaultValue = default) => Math.Abs(denominator) > double.Epsilon ? numerator / denominator : defaultValue;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9dxEM2ggXU-zTLNvvCHsOQ", - "cell_type": "code", - "source": [ - "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", - "\nstatic T GetElementOrDefault(this ICollection array, int index)", - "\n{ ", - "\n var count = array.Count;", - "\n if (array == null || count == 0)", - "\n return default(T);", - "\n", - "\n return index < 0", - "\n ? array.ElementAt(0) // should this case be removed?", - "\n : index < count", - "\n ? array.ElementAt(index)", - "\n : array.ElementAt(count -1);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "A-gLq4O2eE6IW3jx-1tDCw", - "cell_type": "markdown", - "source": [ - "# Enumerable Extensions" - ], - "metadata": {} - }, - { - "id": "QhtXvQfGpkOPqpRxznrgcg", - "cell_type": "code", - "source": [ - "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Brh1Yk0MoEO5H52znFTqUQ", - "cell_type": "code", - "source": [ - "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "3hPGQtfhI0ic1_w5PyiBgw", - "cell_type": "code", - "source": [ - "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "-Y6HUEHIgEidj23uHIcscQ", - "cell_type": "code", - "source": [ - "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xZnDqW6rXEagl6N5IPFBHg", - "cell_type": "markdown", - "source": [ - "# String Extensions" - ], - "metadata": {} - }, - { - "id": "3TZ5QaWLL0eXsicw9mEhrA", - "cell_type": "code", - "source": [ - "using System.Globalization;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "DLkjFfpXp0ODlwc_imkUwA", - "cell_type": "code", - "source": [ - "public static double CheckStringForExponentialAndConvertToDouble (this string s)", - "\n{ ", - "\n if (s == null) return default;", - "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", - "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "740WQ9Xg6ESwS7mzcd_UDQ", - "cell_type": "markdown", - "source": [ - "# Enum Extentions" - ], - "metadata": {} - }, - { - "id": "WNoxcMPslUm-66pmOH5a8g", - "cell_type": "code", - "source": [ - "public static bool Contains(this T value, T lookingForFlag) ", - "\n where T : struct", - "\n{", - "\n int intValue = (int) (object) value;", - "\n int intLookingForFlag = (int) (object) lookingForFlag;", - "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "NgzAK-3L_kW3JQNLVUSQoQ", - "cell_type": "markdown", - "source": [ - "# Queries" - ], - "metadata": {} - }, - { - "id": "ekflioBoz0ukcAPWv4xRtQ", - "cell_type": "markdown", - "source": [ - "## FX" - ], - "metadata": {} - }, - { - "id": "B24vyYMc9kOlNnSUAfEHGQ", - "cell_type": "code", - "source": [ - "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", - "\n => (await querySource.Query()", - "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", - "\n x.Year == year && x.Month == month)", - "\n .ToArrayAsync())", - "\n .ToDictionaryGrouped(x => x.Currency,", - "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", - "\n {", - "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", - "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", - "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", - "\n },", - "\n y => y.FxToGroupCurrency));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hSaegw7GtEWvUosF-y231g", - "cell_type": "code", - "source": [ - "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", - "\n{", - "\n if(currency == groupCurrency)", - "\n return 1;", - "\n", - "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", - "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", - "\n", - "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", - "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", - "\n", - "\n return currencyToGroupFx;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "hcDcg_DFUEOgLrrWw8cE2g", - "cell_type": "markdown", - "source": [ - "## Current and Previous Parameters" - ], - "metadata": {} - }, - { - "id": "qgieIWL7ZUe7mJIVbU_1gQ", - "cell_type": "markdown", - "source": [ - "TODOs:", - "\n
    ", - "\n
  • DataNodes Query: After merging with the new import storage, define IsFirstPeriod property.
  • ", - "\n
  • Once Scenario is defined as a simple property (e.g. in DataNodeState), introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", - "\n
" - ], - "metadata": {} - }, - { - "id": "X01D1mGxS06sfFEPjwyG-A", - "cell_type": "code", - "source": [ - "public static async Task LoadParameterAsync(", - "\n this IQuerySource querySource,", - "\n int year,", - "\n int month,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n return await querySource.Query()", - "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", - "\n .Where(filterExpression?? (Expression>)(x => true))", - "\n .ToArrayAsync();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "sKO5N-LgyEGBEZam7l9_Fg", - "cell_type": "code", - "source": [ - "public static async Task> LoadCurrentParameterAsync (", - "\n this IQuerySource querySource,", - "\n Args args,", - "\n Func identityExpression,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", - "\n .GroupBy(identityExpression)", - "\n .Select(y => y.OrderByDescending(x => x.Year)", - "\n .ThenByDescending(x => x.Month)", - "\n .FirstOrDefault())", - "\n .ToDictionary(identityExpression);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "I0M5hxr91UGl2zNnwXzW-g", - "cell_type": "code", - "source": [ - "public static async Task>> LoadCurrentAndPreviousParameterAsync (", - "\n this IQuerySource querySource,", - "\n Args args,", - "\n Func identityExpression,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", - "\n ", - "\n var ret = new Dictionary>();", - "\n foreach(var p in parameters)", - "\n {", - "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", - "\n", - "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", - "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", - "\n ", - "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", - "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", - "\n }", - "\n return ret;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "UMrZ966740-j48yfqsXM2g", - "cell_type": "markdown", - "source": [ - "", - "\n## Yield Curve" - ], - "metadata": {} - }, - { - "id": "qcQgXJr-l0Gql-aOiCdRrQ", - "cell_type": "code", - "source": [ - "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", - "\n IEnumerable dataNodes)", - "\n{", - "\n var lockedInYieldCurveByGoc = new Dictionary();", - "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", - "\n {", - "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", - "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", - "\n ", - "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", - "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", - "\n ", - "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", - "\n }", - "\n ", - "\n return lockedInYieldCurveByGoc;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "mkhcBCMjAku6Fqv8M8fhmg", - "cell_type": "code", - "source": [ - "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", - "\n IEnumerable dataNodes)", - "\n{", - "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", - "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", - "\n x => x.Currency,", - "\n x => contractualCurrenciesInScope.Contains(x.Currency)", - "\n ));", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "11r0X9aBAUKWja2qSlbOWQ", - "cell_type": "markdown", - "source": [ - "## Data Node State" - ], - "metadata": {} - }, - { - "id": "ineEPRxhfkOAuclOvhZ1lw", - "cell_type": "code", - "source": [ - "//TODO : remove this method and clean up in queriesTest. We need a new test for LoadDataNodes.", - "\npublic static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n //This querySource is partitioned", - "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", - "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", - "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "B1n-fWXBi0GL93ngrSSRbQ", - "cell_type": "markdown", - "source": [ - "## Data Nodes" - ], - "metadata": {} - }, - { - "id": "jdq7blDf4U6-pmv3CMUQTQ", - "cell_type": "code", - "source": [ - "// TODO: the name of this method is strange, one expects DataNodes in return but instead obtains DataNodeData...", - "\npublic static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args) //How do we force the user to provide here a partitioned source? IWorkspace?", - "\n{", - "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", - "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", - "\n ", - "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", - "\n .ToDictionary(dn => dn.SystemName, dn => {", - "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", - "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", - "\n return new DataNodeData(){Year = dnPreviousState.Year, ", - "\n Month = dnPreviousState.Month,", - "\n State = dnCurrentState.State,", - "\n PreviousState = dnPreviousState.State,", - "\n //from Group of Contract", - "\n DataNode = dn.SystemName,", - "\n ContractualCurrency = dn.ContractualCurrency,", - "\n FunctionalCurrency = dn.FunctionalCurrency,", - "\n LineOfBusiness = dn.LineOfBusiness,", - "\n ValuationApproach = dn.ValuationApproach,", - "\n OciType = dn.OciType,", - "\n Portfolio = dn.Portfolio,", - "\n AnnualCohort = dn.AnnualCohort,", - "\n LiabilityType = dn.LiabilityType,", - "\n Profitability = dn.Profitability,", - "\n Partner = dn.Partner,", - "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", - "\n };", - "\n }", - "\n );", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "o0-QY0CD_U6QtHo8DUg-XA", - "cell_type": "markdown", - "source": [ - "## Data Node Parameters" - ], - "metadata": {} - }, - { - "id": "u2AAh0Om8k-FVnzV99qeXw", - "cell_type": "markdown", - "source": [ - "### Single data Node" - ], - "metadata": {} - }, - { - "id": "fGw6yDyGdkGSnMtEzlCWNg", - "cell_type": "code", - "source": [ - "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "fqKznL41TkGOYs41YCJkIw", - "cell_type": "markdown", - "source": [ - "### Inter data Node" - ], - "metadata": {} - }, - { - "id": "9TJH-kJoTEmIucE-PjX7sw", - "cell_type": "code", - "source": [ - "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", - "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", - "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", - "\n ", - "\n return parameters.SelectMany(p => p", - "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", - "\n .Select(gg =>", - "\n {", - "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", - "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", - "\n return (key: p.Key,", - "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", - "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", - "\n })", - "\n )", - "\n .ToDictionaryGrouped(x => x.key,", - "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", - "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "m5W0i-9h_USmOALgfJ5ynw", - "cell_type": "markdown", - "source": [ - "## Aoc Step Configuration" - ], - "metadata": {} - }, - { - "id": "foNau3wankChqmtvuPVxmw", - "cell_type": "code", - "source": [ - "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", - "\n => (await querySource.LoadParameterAsync(year, month)).GroupBy(x => (x.AocType, x.Novelty), (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "u2cguHXQ-kyIKbXgTS6P_g", - "cell_type": "code", - "source": [ - "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) => (await querySource.LoadAocStepConfigurationAsync(year, month)).ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "kujIpDbHiUyTpBosaNnjDg", - "cell_type": "markdown", - "source": [ - "# Export Configurations" - ], - "metadata": {} - }, - { - "id": "cdft6A5YOU-JKits9tdQ0w", - "cell_type": "markdown", - "source": [ - "## Main Tab" - ], - "metadata": {} - }, - { - "id": "qAmPBlXGBkanj2uTVSqlCA", - "cell_type": "code", - "source": [ - "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", - "\n => builder.WithTable( config => config .AtBeginning() ", - "\n .WithName(Main) ", - "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.Scenario, x => x.Delete()));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xDi9MN7YXE6TzDsUxJKv_g", - "cell_type": "code", - "source": [ - "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", - "\n => builder.WithTable( config => config .AtBeginning() ", - "\n .WithName(Main) ", - "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", - "\n .WithColumn(x => x.Id, x => x.Delete()));" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "CRZfO8bZy0G9fSLekjFWUg", - "cell_type": "markdown", - "source": [ - "## Dimensions" - ], - "metadata": {} - }, - { - "id": "Ln1Wggqu406eomb1E8Akcw", - "cell_type": "code", - "source": [ - "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", - "\n => builder.WithTable(config => { ", - "\n if(DependsOnType != default)", - "\n config = config.DependsOn(DependsOnType); ", - "\n return config .AtBeginning() ", - "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", - "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", - "\n });" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6qc9dAkjOkSfbiofWgLnXw", - "cell_type": "code", - "source": [ - "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", - "\n => builder.WithTable(config => { ", - "\n if(DependsOnType != default)", - "\n config = config.DependsOn(DependsOnType); ", - "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", - "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", - "\n return config .AtBeginning() ", - "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", - "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", - "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", - "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", - "\n .WithColumn(x => x.OciType, x => x.Delete())", - "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", - "\n });" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "1dhHyd3JGEOohmsGAjA_gw", - "cell_type": "markdown", - "source": [ - "## Data Node State" - ], - "metadata": {} - }, - { - "id": "Ymq2Wq7sjkeLyNlifepNaQ", - "cell_type": "code", - "source": [ - "using DocumentFormat.OpenXml.Spreadsheet;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "dGKqDg0S5Eq62tKaxG_7yg", - "cell_type": "code", - "source": [ - "public record HelperState { public string State {get; init;} }" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "8HjMW_4oEkSc8gt502-Lkw", - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", - "\n => builder", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data.AsQueryable())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", - "\n );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "G2bKdGeyiEeKBz1bG8g86w", - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", - "\n{", - "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", - "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", - "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", - "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", - "\n .WithSource(source => helperState.AsQueryable()) );", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "zb2wO1m1uUaw0RbXeMwHGw", - "cell_type": "markdown", - "source": [ - "## Data Node Parameter" - ], - "metadata": {} - }, - { - "id": "4hvQE9cObUS1h9wW2WA_LA", - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", - "\n => builder", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n )", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", - "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n );" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "HYdwh4HjBkC--t3kyqy0jg", - "cell_type": "markdown", - "source": [ - "# Report Configurations" - ], - "metadata": {} - }, - { - "id": "qnzf570gh0uWBWG5tHisdw", - "cell_type": "code", - "source": [ - "using Systemorph.Vertex.Pivot.Reporting.Builder;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "L21IHsS-ukOp7q2KpQYwrg", - "cell_type": "code", - "source": [ - "public static ReportBuilder WithGridOptionsForIfrsVariable", - "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", - "\n{", - "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", - "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", - "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", - "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", - "\n );", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "xcQnRFiM80yaO6WWqlVJ3w", - "cell_type": "markdown", - "source": [ - "# Utility Methods Class" - ], - "metadata": {} - }, - { - "id": "Yl-kOA4SvkmoX4bFR30uGA", - "cell_type": "markdown", - "source": [ - "This class contains:", - "\n- EqualityComparer" - ], - "metadata": {} - }, - { - "id": "MzSS_gk3YUqeeUoxH5615g", - "cell_type": "code", - "source": [ - "public static class Utils {", - "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", - "\n {", - "\n collection1.Length.Should().Be(collection2.Length);", - "\n var type = typeof(T);", - "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", - "\n if(properties.Count() == 0) {", - "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", - "\n isEqual.Should().Be(true);", - "\n }", - "\n foreach(var item1 in collection1) {", - "\n var item2 = collection2.Where(x => ", - "\n properties.All(prop => {", - "\n var propType = prop.PropertyType;", - "\n var val = prop.GetValue(item1);", - "\n var otherVal = prop.GetValue(x);", - "\n if(val == null && otherVal == null) return true;", - "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", - "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", - "\n })", - "\n );", - "\n item2.Count().Should().NotBe(0);", - "\n }", - "\n }", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Fnb9erxecEyh69YlvuE30Q", - "cell_type": "code", - "source": [ - "// TODO: find a better arrangement to these methods", - "\nstatic var NumericalPrecisionEqualityChecker = 1.0E-10;", - "\n", - "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", - "\n{", - "\n if(arr1.Length != arr2.Length) return false;", - "\n for(int i = 0; i < arr1.Length; i++) {", - "\n double d1 = arr1[i];", - "\n double d2 = arr2[i];", - "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", - "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", - "\n }", - "\n return true;", - "\n}", - "\n", - "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", - "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", - "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", - "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", - "\n", - "\nstatic bool CheckEquality(this double? d1, double? d2) ", - "\n{", - "\n if(d1 == null && d2 == null) return true;", - "\n else return CheckEquality((double)d1, (double)d2);", - "\n}", - "\n" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "etIXAOoMHEGKXFbnzCCRWA", - "cell_type": "markdown", - "source": [ - "## ToIdentityString" - ], - "metadata": {} - }, - { - "id": "-0U7OSuELUeCMTZ487kI_A", - "cell_type": "code", - "source": [ - "using System.Text;", - "\npublic static string ToIdentityString(this T v)", - "\n where T : class", - "\n{", - "\n StringBuilder sb = new StringBuilder();", - "\n var propertyInfos = v.GetType()", - "\n .GetProperties()", - "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", - "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", - "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", - "\n", - "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "cq_4STuakk6krLbs6TZ4yg", - "cell_type": "markdown", - "source": [ - "## GetPreviousIdentities" - ], - "metadata": {} - }, - { - "id": "XYOo4uHfnkeKWMF_MQ5r-Q", - "cell_type": "code", - "source": [ - "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", - "\n{", - "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", - "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", - "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", - "\n return identities.Where(id => id.AocType != AocTypes.BOP)", - "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", - "\n : previousStep[x.Novelty].RepeatOnce();", - "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", - "\n return ret;});", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "XbcZgL57GUy04M44loxF-g", - "cell_type": "markdown", - "source": [ - "## GetReferenceAocStepForCalculated" - ], - "metadata": {} - }, - { - "id": "MLNCUWgSAkyrA-DMWc-JpQ", - "cell_type": "code", - "source": [ - "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", - "\n{", - "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", - "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", - "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", - "\n && aocStep.Novelty == identityAocStep.Novelty) ", - "\n ?? new AocStep(default, default);", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "VxJI9sGp3UyCFxyJM7MGKg", - "cell_type": "markdown", - "source": [ - "# Change Sign Rules" - ], - "metadata": {} - }, - { - "id": "Uv2X9RT3wkKLJvMvooTbSw", - "cell_type": "code", - "source": [ - "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", - "\n{", - "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", - "\n return isActual;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "MOV5tqPp2kSr4kp0wet0ag", - "cell_type": "markdown", - "source": [ - "# EstimateType And AmountType" - ], - "metadata": {} - }, - { - "id": "jf_kmDreZUyVr-gBkFuuCg", - "cell_type": "code", - "source": [ - "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", - "\n{", - "\n return new Dictionary>(){", - "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", - "\n };", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "j0oOSZn9ZkK6D6BR_YxuJg", - "cell_type": "markdown", - "source": [ - "# Technical Margin EstimateType" - ], - "metadata": {} - }, - { - "id": "86CBe5DnrkOi6irqUzCLNw", - "cell_type": "code", - "source": [ - "public static HashSet GetTechnicalMarginEstimateType()", - "\n{", - "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "9OeFmvwQJECtzHY6Dg8Yzw", - "cell_type": "markdown", - "source": [ - "# Discount and Cumulate" - ], - "metadata": {} - }, - { - "id": "Ajyhr4n0106OnU6fEIdL5g", - "cell_type": "code", - "source": [ - "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", - "\n{ ", - "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", - "\n ", - "\n var ret = new double[nominalValues.Length];", - "\n ", - "\n if(periodType == PeriodType.BeginningOfPeriod)", - "\n {", - "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", - "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", - "\n return ret;", - "\n }", - "\n ", - "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", - "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", - "\n ", - "\n return ret;", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "LoqMwHfd8kOJYFyQxw5KNQ", - "cell_type": "code", - "source": [ - "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", - "\n{ ", - "\n return Enumerable.Range(0, nominalValues.Length)", - "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", - "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", - "\n .Sum() )", - "\n .ToArray();", - "\n}" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "Y9wSV5wvy0mvkCNsCiRmlQ", - "cell_type": "markdown", - "source": [ - "# Import Configuration" - ], - "metadata": {} - }, - { - "id": "11et4IQ_0US7mUdWWNnouw", - "cell_type": "markdown", - "source": [ - "## Data Nodes" - ], - "metadata": {} - }, - { - "id": "fd6J9NnbXkmWF-7Qi2FmWA", - "cell_type": "code", - "source": [ - "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "z4UEzk2bPEOGnwoC6UN3pg", - "cell_type": "code", - "source": [ - "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - }, - { - "id": "6k1Zt47Wtk6cltgFOwSPXQ", - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 1, - "outputs": [] - } - ] + "metadata": { + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"", + "\n#!import \"./ApplicationMessage\"" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Linq.Expressions;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Math Functions" + ] + }, + { + "cell_type": "code", + "source": [ + "static double DivideOrDefault(double numerator, double denominator, double defaultValue = default) => Math.Abs(denominator) > double.Epsilon ? numerator / denominator : defaultValue;" + ] + }, + { + "cell_type": "code", + "source": [ + "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", + "\nstatic T GetElementOrDefault(this ICollection array, int index)", + "\n{ ", + "\n var count = array.Count;", + "\n if (array == null || count == 0)", + "\n return default(T);", + "\n", + "\n return index < 0", + "\n ? array.ElementAt(0) // should this case be removed?", + "\n : index < count", + "\n ? array.ElementAt(index)", + "\n : array.ElementAt(count -1);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Enumerable Extensions" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# String Extensions" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Globalization;" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double CheckStringForExponentialAndConvertToDouble (this string s)", + "\n{ ", + "\n if (s == null) return default;", + "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", + "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Enum Extentions" + ] + }, + { + "cell_type": "code", + "source": [ + "public static bool Contains(this T value, T lookingForFlag) ", + "\n where T : struct", + "\n{", + "\n int intValue = (int) (object) value;", + "\n int intLookingForFlag = (int) (object) lookingForFlag;", + "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Queries" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## FX" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.Query()", + "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", + "\n x.Year == year && x.Month == month)", + "\n .ToArrayAsync())", + "\n .ToDictionaryGrouped(x => x.Currency,", + "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", + "\n {", + "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", + "\n },", + "\n y => y.FxToGroupCurrency));" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", + "\n{", + "\n if(currency == groupCurrency)", + "\n return 1;", + "\n", + "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", + "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", + "\n", + "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", + "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", + "\n", + "\n return currencyToGroupFx;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Current and Previous Parameters" + ] + }, + { + "cell_type": "markdown", + "source": [ + "TODOs:", + "\n
    ", + "\n
  • DataNodes Query: After merging with the new import storage, define IsFirstPeriod property.
  • ", + "\n
  • Once Scenario is defined as a simple property (e.g. in DataNodeState), introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", + "\n
" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task LoadParameterAsync(", + "\n this IQuerySource querySource,", + "\n int year,", + "\n int month,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return await querySource.Query()", + "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", + "\n .Where(filterExpression?? (Expression>)(x => true))", + "\n .ToArrayAsync();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadCurrentParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", + "\n .GroupBy(identityExpression)", + "\n .Select(y => y.OrderByDescending(x => x.Year)", + "\n .ThenByDescending(x => x.Month)", + "\n .FirstOrDefault())", + "\n .ToDictionary(identityExpression);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentAndPreviousParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", + "\n ", + "\n var ret = new Dictionary>();", + "\n foreach(var p in parameters)", + "\n {", + "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", + "\n", + "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n ", + "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", + "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", + "\n }", + "\n return ret;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Yield Curve" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var lockedInYieldCurveByGoc = new Dictionary();", + "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", + "\n {", + "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", + "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", + "\n ", + "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", + "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", + "\n ", + "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", + "\n }", + "\n ", + "\n return lockedInYieldCurveByGoc;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", + "\n x => x.Currency,", + "\n x => contractualCurrenciesInScope.Contains(x.Currency)", + "\n ));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "//TODO : remove this method and clean up in queriesTest. We need a new test for LoadDataNodes.", + "\npublic static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n //This querySource is partitioned", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", + "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", + "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Nodes" + ] + }, + { + "cell_type": "code", + "source": [ + "// TODO: the name of this method is strange, one expects DataNodes in return but instead obtains DataNodeData...", + "\npublic static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args) //How do we force the user to provide here a partitioned source? IWorkspace?", + "\n{", + "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", + "\n ", + "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", + "\n .ToDictionary(dn => dn.SystemName, dn => {", + "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", + "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", + "\n return new DataNodeData(){Year = dnPreviousState.Year, ", + "\n Month = dnPreviousState.Month,", + "\n State = dnCurrentState.State,", + "\n PreviousState = dnPreviousState.State,", + "\n //from Group of Contract", + "\n DataNode = dn.SystemName,", + "\n ContractualCurrency = dn.ContractualCurrency,", + "\n FunctionalCurrency = dn.FunctionalCurrency,", + "\n LineOfBusiness = dn.LineOfBusiness,", + "\n ValuationApproach = dn.ValuationApproach,", + "\n OciType = dn.OciType,", + "\n Portfolio = dn.Portfolio,", + "\n AnnualCohort = dn.AnnualCohort,", + "\n LiabilityType = dn.LiabilityType,", + "\n Profitability = dn.Profitability,", + "\n Partner = dn.Partner,", + "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", + "\n };", + "\n }", + "\n );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node Parameters" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Single data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "### Inter data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", + "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", + "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", + "\n ", + "\n return parameters.SelectMany(p => p", + "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", + "\n .Select(gg =>", + "\n {", + "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n return (key: p.Key,", + "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", + "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", + "\n })", + "\n )", + "\n .ToDictionaryGrouped(x => x.key,", + "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", + "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Aoc Step Configuration" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.LoadParameterAsync(year, month)).GroupBy(x => (x.AocType, x.Novelty), (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) => (await querySource.LoadAocStepConfigurationAsync(year, month)).ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Export Configurations" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Main Tab" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Scenario, x => x.Delete()));" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete()));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Dimensions" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", + "\n });" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", + "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", + "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", + "\n .WithColumn(x => x.OciType, x => x.Delete())", + "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", + "\n });" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "using DocumentFormat.OpenXml.Spreadsheet;" + ] + }, + { + "cell_type": "code", + "source": [ + "public record HelperState { public string State {get; init;} }" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data.AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", + "\n{", + "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", + "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", + "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", + "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", + "\n .WithSource(source => helperState.AsQueryable()) );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Node Parameter" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n )", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n );" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Report Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "using Systemorph.Vertex.Pivot.Reporting.Builder;" + ] + }, + { + "cell_type": "code", + "source": [ + "public static ReportBuilder WithGridOptionsForIfrsVariable", + "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", + "\n{", + "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", + "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", + "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", + "\n );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Utility Methods Class" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This class contains:", + "\n- EqualityComparer" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class Utils {", + "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", + "\n {", + "\n collection1.Length.Should().Be(collection2.Length);", + "\n var type = typeof(T);", + "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", + "\n if(properties.Count() == 0) {", + "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", + "\n isEqual.Should().Be(true);", + "\n }", + "\n foreach(var item1 in collection1) {", + "\n var item2 = collection2.Where(x => ", + "\n properties.All(prop => {", + "\n var propType = prop.PropertyType;", + "\n var val = prop.GetValue(item1);", + "\n var otherVal = prop.GetValue(x);", + "\n if(val == null && otherVal == null) return true;", + "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", + "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", + "\n })", + "\n );", + "\n item2.Count().Should().NotBe(0);", + "\n }", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "// TODO: find a better arrangement to these methods", + "\nstatic var NumericalPrecisionEqualityChecker = 1.0E-10;", + "\n", + "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", + "\n{", + "\n if(arr1.Length != arr2.Length) return false;", + "\n for(int i = 0; i < arr1.Length; i++) {", + "\n double d1 = arr1[i];", + "\n double d2 = arr2[i];", + "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", + "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", + "\n }", + "\n return true;", + "\n}", + "\n", + "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", + "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", + "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", + "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", + "\n", + "\nstatic bool CheckEquality(this double? d1, double? d2) ", + "\n{", + "\n if(d1 == null && d2 == null) return true;", + "\n else return CheckEquality((double)d1, (double)d2);", + "\n}", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## ToIdentityString" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Text;", + "\npublic static string ToIdentityString(this T v)", + "\n where T : class", + "\n{", + "\n StringBuilder sb = new StringBuilder();", + "\n var propertyInfos = v.GetType()", + "\n .GetProperties()", + "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", + "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", + "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", + "\n", + "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## GetPreviousIdentities" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", + "\n{", + "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", + "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", + "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", + "\n return identities.Where(id => id.AocType != AocTypes.BOP)", + "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", + "\n : previousStep[x.Novelty].RepeatOnce();", + "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", + "\n return ret;});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## GetReferenceAocStepForCalculated" + ] + }, + { + "cell_type": "code", + "source": [ + "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", + "\n{", + "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", + "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", + "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", + "\n && aocStep.Novelty == identityAocStep.Novelty) ", + "\n ?? new AocStep(default, default);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Change Sign Rules" + ] + }, + { + "cell_type": "code", + "source": [ + "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", + "\n return isActual;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# EstimateType And AmountType" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n return new Dictionary>(){", + "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", + "\n };", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Technical Margin EstimateType" + ] + }, + { + "cell_type": "code", + "source": [ + "public static HashSet GetTechnicalMarginEstimateType()", + "\n{", + "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Discount and Cumulate" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", + "\n{ ", + "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", + "\n ", + "\n var ret = new double[nominalValues.Length];", + "\n ", + "\n if(periodType == PeriodType.BeginningOfPeriod)", + "\n {", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n return ret;", + "\n }", + "\n ", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n ", + "\n return ret;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", + "\n{ ", + "\n return Enumerable.Range(0, nominalValues.Length)", + "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", + "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", + "\n .Sum() )", + "\n .ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Nodes" + ] + }, + { + "cell_type": "code", + "source": [ + "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" + ] + }, + { + "cell_type": "code", + "source": [ + "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] } \ No newline at end of file From 95c90f9c9cdab784cbea37e9afdc692254b34adc Mon Sep 17 00:00:00 2001 From: Sara Busato Date: Thu, 6 Oct 2022 12:11:08 +0200 Subject: [PATCH 06/38] reorder global metadata using alphabetical order --- Constants/Consts.ipynb | 10 +++++----- Constants/Enums.ipynb | 10 +++++----- Constants/Validations.ipynb | 10 +++++----- DataModel/DataStructure.ipynb | 10 +++++----- Database/Configure.ipynb | 10 +++++----- Database/Schema Delete.ipynb | 10 +++++----- Export/MapTemplate.ipynb | 10 +++++----- Import/ImportResultPreview.ipynb | 10 +++++----- Import/ImportScopeCalculation.ipynb | 10 +++++----- Import/ImportStorage.ipynb | 10 +++++----- Import/Importers.ipynb | 10 +++++----- Initialization/InitSystemorphBaseToMemory.ipynb | 10 +++++----- Initialization/InitSystemorphToDatabase.ipynb | 10 +++++----- Initialization/InitSystemorphToMemory.ipynb | 10 +++++----- InputFormatDescription.ipynb | 10 +++++----- OverviewCalculationEngine.ipynb | 10 +++++----- Report/ReportConfigurationAndUtils.ipynb | 10 +++++----- Report/ReportScopes.ipynb | 10 +++++----- Report/ReportStorage.ipynb | 10 +++++----- Report/Reports.ipynb | 10 +++++----- Test/AocStructureTest.ipynb | 10 +++++----- Test/ExportIfrsVariable.ipynb | 10 +++++----- Test/ExportReportVariables.ipynb | 10 +++++----- Test/IfrsVariablesTest.ipynb | 10 +++++----- Test/ImportStorageTest.ipynb | 10 +++++----- Test/MapTemplateAndImportTest.ipynb | 10 +++++----- Test/QueriesTest.ipynb | 10 +++++----- Test/ReportStorageTest.ipynb | 10 +++++----- Test/ReportVariablesTest.ipynb | 10 +++++----- Test/ReportVariablesTestBase.ipynb | 10 +++++----- Test/SpecificationsFinancialPerformance.ipynb | 10 +++++----- Test/SpecificationsImportActuals.ipynb | 10 +++++----- Test/SpecificationsImportCashflows.ipynb | 10 +++++----- Test/SpecificationsSetup.ipynb | 10 +++++----- Test/SpecificationsTechnicalMargin.ipynb | 10 +++++----- Test/TechnicalMarginTest.ipynb | 10 +++++----- Test/Tests.ipynb | 10 +++++----- Utils/ApplicationMessage.ipynb | 10 +++++----- Utils/UtilityMethods.ipynb | 10 +++++----- 39 files changed, 195 insertions(+), 195 deletions(-) diff --git a/Constants/Consts.ipynb b/Constants/Consts.ipynb index 12992f46..808308c2 100644 --- a/Constants/Consts.ipynb +++ b/Constants/Consts.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/Constants/Enums.ipynb b/Constants/Enums.ipynb index 63b1b56f..04c87848 100644 --- a/Constants/Enums.ipynb +++ b/Constants/Enums.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/Constants/Validations.ipynb b/Constants/Validations.ipynb index 18f30a6f..d1b09cc0 100644 --- a/Constants/Validations.ipynb +++ b/Constants/Validations.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/DataModel/DataStructure.ipynb b/DataModel/DataStructure.ipynb index 871ff938..55885f24 100644 --- a/DataModel/DataStructure.ipynb +++ b/DataModel/DataStructure.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/Database/Configure.ipynb b/Database/Configure.ipynb index edca53dd..9b23844f 100644 --- a/Database/Configure.ipynb +++ b/Database/Configure.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/Database/Schema Delete.ipynb b/Database/Schema Delete.ipynb index e3e1eb69..f1f25629 100644 --- a/Database/Schema Delete.ipynb +++ b/Database/Schema Delete.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "documentInfo": "{\r\n \"authors\": [\r\n \"Peter Kunszt\"\r\n ],\r\n \"contributors\": [],\r\n \"tags\": [\r\n \"storage\",\r\n \"database\",\r\n \"persistence\",\r\n \"dependency\"\r\n ],\r\n \"title\": \"Multiple Storages with Persistence\",\r\n \"description\": \"Demo the usage of database backend to resolve a data dependency.\",\r\n \"createdDate\": \"Jan. 2022\",\r\n \"publishedDate\": \"Jan. 2022\",\r\n \"changelog\": [\r\n {\r\n \"version\": \"1.0\",\r\n \"description\": \"Initial Notebook\"\r\n }\r\n ]\r\n }", "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" } }, "nbformat": 4, diff --git a/Export/MapTemplate.ipynb b/Export/MapTemplate.ipynb index 1f91daa0..9d6cc89b 100644 --- a/Export/MapTemplate.ipynb +++ b/Export/MapTemplate.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Import/ImportResultPreview.ipynb b/Import/ImportResultPreview.ipynb index 22cd4398..ba23909b 100644 --- a/Import/ImportResultPreview.ipynb +++ b/Import/ImportResultPreview.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index b932e924..b9949cc3 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb index ea1af2cc..ae040ef3 100644 --- a/Import/ImportStorage.ipynb +++ b/Import/ImportStorage.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index eb140724..808b4cbe 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/Initialization/InitSystemorphBaseToMemory.ipynb b/Initialization/InitSystemorphBaseToMemory.ipynb index 097ddb40..d28022d0 100644 --- a/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/Initialization/InitSystemorphBaseToMemory.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Initialization/InitSystemorphToDatabase.ipynb b/Initialization/InitSystemorphToDatabase.ipynb index 8dba5617..c994f78b 100644 --- a/Initialization/InitSystemorphToDatabase.ipynb +++ b/Initialization/InitSystemorphToDatabase.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Initialization/InitSystemorphToMemory.ipynb b/Initialization/InitSystemorphToMemory.ipynb index 80f655a5..884cc8fd 100644 --- a/Initialization/InitSystemorphToMemory.ipynb +++ b/Initialization/InitSystemorphToMemory.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/InputFormatDescription.ipynb b/InputFormatDescription.ipynb index 02152194..857d2cc9 100644 --- a/InputFormatDescription.ipynb +++ b/InputFormatDescription.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/OverviewCalculationEngine.ipynb b/OverviewCalculationEngine.ipynb index db79df0c..a4ba1b36 100644 --- a/OverviewCalculationEngine.ipynb +++ b/OverviewCalculationEngine.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Report/ReportConfigurationAndUtils.ipynb b/Report/ReportConfigurationAndUtils.ipynb index 61e8193f..575ece44 100644 --- a/Report/ReportConfigurationAndUtils.ipynb +++ b/Report/ReportConfigurationAndUtils.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Report/ReportScopes.ipynb b/Report/ReportScopes.ipynb index 719b2f66..bc470121 100644 --- a/Report/ReportScopes.ipynb +++ b/Report/ReportScopes.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Report/ReportStorage.ipynb b/Report/ReportStorage.ipynb index 477fc0bb..655f0888 100644 --- a/Report/ReportStorage.ipynb +++ b/Report/ReportStorage.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Report/Reports.ipynb b/Report/Reports.ipynb index a79b4e9a..36b8aa3e 100644 --- a/Report/Reports.ipynb +++ b/Report/Reports.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/AocStructureTest.ipynb b/Test/AocStructureTest.ipynb index e0b1a671..1dbad859 100644 --- a/Test/AocStructureTest.ipynb +++ b/Test/AocStructureTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/ExportIfrsVariable.ipynb b/Test/ExportIfrsVariable.ipynb index bdd3aa38..9d21556c 100644 --- a/Test/ExportIfrsVariable.ipynb +++ b/Test/ExportIfrsVariable.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/ExportReportVariables.ipynb b/Test/ExportReportVariables.ipynb index a079be72..96db0b99 100644 --- a/Test/ExportReportVariables.ipynb +++ b/Test/ExportReportVariables.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/IfrsVariablesTest.ipynb b/Test/IfrsVariablesTest.ipynb index ab282217..1a40358a 100644 --- a/Test/IfrsVariablesTest.ipynb +++ b/Test/IfrsVariablesTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/ImportStorageTest.ipynb b/Test/ImportStorageTest.ipynb index 8f9d5663..effe2de0 100644 --- a/Test/ImportStorageTest.ipynb +++ b/Test/ImportStorageTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/MapTemplateAndImportTest.ipynb b/Test/MapTemplateAndImportTest.ipynb index e7837a9f..cdb93e65 100644 --- a/Test/MapTemplateAndImportTest.ipynb +++ b/Test/MapTemplateAndImportTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/QueriesTest.ipynb b/Test/QueriesTest.ipynb index 490565f0..3c102747 100644 --- a/Test/QueriesTest.ipynb +++ b/Test/QueriesTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/ReportStorageTest.ipynb b/Test/ReportStorageTest.ipynb index 4d728148..acb1f22c 100644 --- a/Test/ReportStorageTest.ipynb +++ b/Test/ReportStorageTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/ReportVariablesTest.ipynb b/Test/ReportVariablesTest.ipynb index eb31bd44..fb6904bf 100644 --- a/Test/ReportVariablesTest.ipynb +++ b/Test/ReportVariablesTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/ReportVariablesTestBase.ipynb b/Test/ReportVariablesTestBase.ipynb index 77732e98..4f320987 100644 --- a/Test/ReportVariablesTestBase.ipynb +++ b/Test/ReportVariablesTestBase.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/Test/SpecificationsFinancialPerformance.ipynb index 6cf10521..44816ee6 100644 --- a/Test/SpecificationsFinancialPerformance.ipynb +++ b/Test/SpecificationsFinancialPerformance.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/SpecificationsImportActuals.ipynb b/Test/SpecificationsImportActuals.ipynb index cb0b1acb..d71638e8 100644 --- a/Test/SpecificationsImportActuals.ipynb +++ b/Test/SpecificationsImportActuals.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/SpecificationsImportCashflows.ipynb b/Test/SpecificationsImportCashflows.ipynb index eac7cd32..b392feef 100644 --- a/Test/SpecificationsImportCashflows.ipynb +++ b/Test/SpecificationsImportCashflows.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False", diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb index d112b3d2..15228d6f 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/Test/SpecificationsSetup.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/SpecificationsTechnicalMargin.ipynb b/Test/SpecificationsTechnicalMargin.ipynb index 83eaaba1..13c6c98b 100644 --- a/Test/SpecificationsTechnicalMargin.ipynb +++ b/Test/SpecificationsTechnicalMargin.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/TechnicalMarginTest.ipynb b/Test/TechnicalMarginTest.ipynb index 9a79f348..827833ed 100644 --- a/Test/TechnicalMarginTest.ipynb +++ b/Test/TechnicalMarginTest.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Test/Tests.ipynb b/Test/Tests.ipynb index 538dbf00..ba71bfbc 100644 --- a/Test/Tests.ipynb +++ b/Test/Tests.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, diff --git a/Utils/ApplicationMessage.ipynb b/Utils/ApplicationMessage.ipynb index a41569e3..2bc8ec97 100644 --- a/Utils/ApplicationMessage.ipynb +++ b/Utils/ApplicationMessage.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" diff --git a/Utils/UtilityMethods.ipynb b/Utils/UtilityMethods.ipynb index c3706f06..3436c3e7 100644 --- a/Utils/UtilityMethods.ipynb +++ b/Utils/UtilityMethods.ipynb @@ -1,16 +1,16 @@ { "metadata": { - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, "toc-autonumbering": "True", "toc-showcode": "False" }, From fc7816fe278fdbcd108505026824300a1e0caca3 Mon Sep 17 00:00:00 2001 From: Davide Colleoni <103409906+dcolleoni@users.noreply.github.com> Date: Thu, 6 Oct 2022 16:47:38 +0200 Subject: [PATCH 07/38] Break utils nb (#33) * working on reports doc * metadata * break down utils * remove preview * update references to utils * fix image paths * reset doc around reports * fixing test + a ton of metadata * Cleanup redundant comments and import /Tests/TestHelper in SpecificationsFinancialPerformance * Move Export.ipynb inside the Export folder, fix import /Export/Export statement and comments cleanup in Utils/Extensions.ipynb * Empty commit to refresh the meta-data * Remove all *.orig files Co-authored-by: nnikolopoulos --- Export/Export.ipynb | 206 ++++ Export/MapTemplate.ipynb | 20 +- Import/ImportResultPreview.ipynb | 250 ----- Import/ImportScopeCalculation.ipynb | 2 +- Import/ImportStorage.ipynb | 4 +- InputFormatDescription.ipynb | 12 +- OverviewCalculationEngine.ipynb | 2 +- Report/ReportConfigurationAndUtils.ipynb | 26 +- Report/Reports.ipynb | 30 +- Test/MapTemplateAndImportTest.ipynb | 76 +- Test/QueriesTest.ipynb | 2 +- Test/SpecificationsFinancialPerformance.ipynb | 12 + Test/SpecificationsSetup.ipynb | 9 +- Test/Tests.ipynb | 2 +- Utils/Extensions.ipynb | 147 +++ Utils/ImportCalculationMethods.ipynb | 185 ++++ Utils/Queries.ipynb | 320 +++++++ Utils/TestHelper.ipynb | 113 +++ Utils/UtilityMethods.ipynb | 899 ------------------ 19 files changed, 1133 insertions(+), 1184 deletions(-) create mode 100644 Export/Export.ipynb delete mode 100644 Import/ImportResultPreview.ipynb create mode 100644 Utils/Extensions.ipynb create mode 100644 Utils/ImportCalculationMethods.ipynb create mode 100644 Utils/Queries.ipynb create mode 100644 Utils/TestHelper.ipynb delete mode 100644 Utils/UtilityMethods.ipynb diff --git a/Export/Export.ipynb b/Export/Export.ipynb new file mode 100644 index 00000000..e3fa8ad4 --- /dev/null +++ b/Export/Export.ipynb @@ -0,0 +1,206 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Main Tab" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Scenario, x => x.Delete()));" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete()));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Porfolio" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", + "\n });" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Group of Contract" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", + "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", + "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", + "\n .WithColumn(x => x.OciType, x => x.Delete())", + "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", + "\n });" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "using DocumentFormat.OpenXml.Spreadsheet;" + ] + }, + { + "cell_type": "code", + "source": [ + "public record HelperState { public string State {get; init;} }" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data.AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", + "\n{", + "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", + "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", + "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", + "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", + "\n .WithSource(source => helperState.AsQueryable()) );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node Parameter" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n )", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Export/MapTemplate.ipynb b/Export/MapTemplate.ipynb index 9d6cc89b..2f6034eb 100644 --- a/Export/MapTemplate.ipynb +++ b/Export/MapTemplate.ipynb @@ -38,34 +38,34 @@ { "cell_type": "markdown", "source": [ - "# Import dependencies" + "# Select Initialization" ] }, { - "cell_type": "code", + "cell_type": "markdown", "source": [ - "#!import \"../Utils/UtilityMethods\"" + "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." ] }, { - "cell_type": "markdown", + "cell_type": "code", "source": [ - "# Select Initialization" + "/* The DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"../Database/Configure\"", + "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", + "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" ] }, { "cell_type": "markdown", "source": [ - "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." + "# Import dependencies" ] }, { "cell_type": "code", "source": [ - "/* The DataSource is configured and connected to real database */", - "\n//#!eval-notebook \"Database/Configure\"", - "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", - "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + "#!import \"../Export/Export\"" ] }, { diff --git a/Import/ImportResultPreview.ipynb b/Import/ImportResultPreview.ipynb deleted file mode 100644 index ba23909b..00000000 --- a/Import/ImportResultPreview.ipynb +++ /dev/null @@ -1,250 +0,0 @@ -{ - "metadata": { - "authors": [], - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False" - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Temporary for debugging (initialize data and construct/initialize storage)" - ] - }, - { - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"../Test/SpecificationsSetup\"" - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\nGiven the current status of the implementation, in order to display Actual reports it is necessary to set Actual format in the Args while to display Cashflow it is necessary to set Cashflow format." - ] - }, - { - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"L\" ;" - ] - }, - { - "cell_type": "code", - "source": [ - "var UniversePreview = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" - ] - }, - { - "cell_type": "code", - "source": [ - "var importStorage = UniversePreview.GetStorage();" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Import Preview" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Present Value" - ] - }, - { - "cell_type": "code", - "source": [ - "var identities = UniversePreview.GetScopes(importStorage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);" - ] - }, - { - "cell_type": "code", - "source": [ - "var pvs = UniversePreview.GetScopes(identities, o => o.WithStorage(importStorage)).SelectMany(x => x.PvCurrent.Concat(x.PvLocked));" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(pvs", - "\n //.Where(x => x.DataNode == \"DTR1.1\")", - "\n )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n //.GroupColumnsBy(x => x.AmountType)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n //VariableType", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n //.GroupColumnsBy(x => x.Novelty)", - "\n .WithGridOptionsForIfrsVariable(720)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Risk Adjustment" - ] - }, - { - "cell_type": "code", - "source": [ - "var ras = UniversePreview.GetScopes(identities).SelectMany(x => x.RaCurrent.Concat(x.RaLocked));" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(ras)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n //.GroupRowsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n //VariableType", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n //.GroupColumnsBy(x => x.Novelty)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "var actuals = UniversePreview.GetScopes(identities).SelectMany(x => x.Actual);" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(actuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupRowsBy(x => x.AmountType)", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n .WithGridOptionsForIfrsVariable(550)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Advance, Overdue Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "var aoActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.AdvanceActual.Concat(x.OverdueActual));" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(aoActuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupColumnsBy(x => x.AmountType)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable(300)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Deferrable Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "var deferrableActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.DeferrableActual);" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(deferrableActuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable(350)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Csm Lc LoReCo" - ] - }, - { - "cell_type": "code", - "source": [ - "var csm = UniversePreview.GetScopes(identities).SelectMany(x => x.Csms);", - "\nvar loss = UniversePreview.GetScopes(identities).SelectMany(x => x.Loss);", - "\nvar csmLcLoReCo = Enumerable.Empty().Concat(csm).Concat(loss);" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(csmLcLoReCo", - "\n //.Where(x => x.DataNode == \"DT1.1\")", - "\n )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ] - }, - { - "cell_type": "code", - "source": [ - "" - ] - } - ] -} \ No newline at end of file diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index b9949cc3..4f8e78f5 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -404,7 +404,7 @@ "\n- For the **Locked-in** economic basis, the yield curve used is the latest available as per end of the DataNode's inception year;", "\n- Whereas for the **Current** economic base, the yield curve used is the latest available as per the current period.", "\n", - "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/UtilityMethods#yield-curve)." + "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/Queries#yield-curve)." ] }, { diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb index ae040ef3..291e0e0b 100644 --- a/Import/ImportStorage.ipynb +++ b/Import/ImportStorage.ipynb @@ -32,6 +32,7 @@ "\n- [IfrsVariables](../DataModel/DataStructure)", "\n- [Projection Configuration](../DataModel/DataStructure)", "\n- [YieldCurve](../DataModel/DataStructure)", + "\n- [DataNodeParameters](../DataModel/DataStructure)", "\n- [AocType](../DataModel/DataStructure)", "\n- [AmountType](../DataModel/DataStructure)", "\n- [CalculationType](../DataModel/DataStructure)", @@ -43,7 +44,8 @@ { "cell_type": "code", "source": [ - "#!import \"../Utils/UtilityMethods\"" + "#!import \"../Utils/ImportCalculationMethods\"", + "\n#!import \"../Utils/Queries\"" ] }, { diff --git a/InputFormatDescription.ipynb b/InputFormatDescription.ipynb index 857d2cc9..bee76506 100644 --- a/InputFormatDescription.ipynb +++ b/InputFormatDescription.ipynb @@ -28,7 +28,7 @@ "\n# The Cashflows File Structure ", "\n", "\n", - "\n
" + "\n
" ] }, { @@ -56,7 +56,7 @@ "\n# The Actuals File Structure ", "\n", "\n", - "\n
" + "\n
" ] }, { @@ -80,7 +80,7 @@ "\n# The Openings File Structure ", "\n", "\n", - "\n
" + "\n
" ] }, { @@ -96,6 +96,12 @@ "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." ] + }, + { + "cell_type": "markdown", + "source": [ + "" + ] } ] } \ No newline at end of file diff --git a/OverviewCalculationEngine.ipynb b/OverviewCalculationEngine.ipynb index a4ba1b36..d3d3e77b 100644 --- a/OverviewCalculationEngine.ipynb +++ b/OverviewCalculationEngine.ipynb @@ -34,7 +34,7 @@ "source": [ "# Introduction", "\n", - "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key inpute: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", "\n", "\nThis notebook provides an **overview** of Systemorph's IFRS 17 Calculation Engine with brief introductions to all the main steps.", "\n", diff --git a/Report/ReportConfigurationAndUtils.ipynb b/Report/ReportConfigurationAndUtils.ipynb index 575ece44..d482e339 100644 --- a/Report/ReportConfigurationAndUtils.ipynb +++ b/Report/ReportConfigurationAndUtils.ipynb @@ -26,7 +26,7 @@ { "cell_type": "code", "source": [ - "#!import \"../Utils/UtilityMethods\"" + "#!import \"../Utils/Queries\"" ] }, { @@ -51,6 +51,12 @@ "\n with { Height = reportHeight, GroupDefaultExpanded = groupDefaultExpanded, OnGridReady = null } );" ] }, + { + "cell_type": "markdown", + "source": [ + "# Currency methods" + ] + }, { "cell_type": "code", "source": [ @@ -60,6 +66,24 @@ "\n _ => string.Empty };" ] }, + { + "cell_type": "code", + "source": [ + "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", + "\n{", + "\n if(currency == groupCurrency)", + "\n return 1;", + "\n", + "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", + "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", + "\n", + "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", + "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", + "\n", + "\n return currencyToGroupFx;", + "\n}" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/Report/Reports.ipynb b/Report/Reports.ipynb index 36b8aa3e..91d3d680 100644 --- a/Report/Reports.ipynb +++ b/Report/Reports.ipynb @@ -103,7 +103,6 @@ "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n //((2021, 12), reportingNodeRoot, null,CurrencyType.Contractual)", "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", "\n ;", @@ -115,7 +114,28 @@ { "cell_type": "markdown", "source": [ - "# Present Value" + "# Data Constellation", + "\n", + "\nWe have " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Present Value", + "\n", + "\nPresent values of the best estimate of future cashflows are shown here in an Analysis of Change report.", + "\n", + "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", + "\nThe figures displayed in the report are automatically aggregated to meet the granularity desired by the user.", + "\n", + "\nCurrently, the data is sliced by :", + "\n- CurrencyType", + "\n- LiabilityType", + "\n- EconomicBasis", + "\n", + "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", + "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data." ] }, { @@ -126,7 +146,7 @@ "\n )", "\n .WithQuerySource(DataSource)", "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\", \"EconomicBasis\") //\"GroupOfContract\"", "\n .ReportGridOptions()", "\n .ToReport()" ] @@ -362,7 +382,9 @@ { "cell_type": "markdown", "source": [ - "# Financial Performance" + "# Financial Performance", + "\n", + "\nUse the expand and collapse buttons in the report rows to change the granularity of the figures displayed." ] }, { diff --git a/Test/MapTemplateAndImportTest.ipynb b/Test/MapTemplateAndImportTest.ipynb index cdb93e65..6dc5c63c 100644 --- a/Test/MapTemplateAndImportTest.ipynb +++ b/Test/MapTemplateAndImportTest.ipynb @@ -26,7 +26,8 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"../Utils/UtilityMethods\"" + "#!import \"../Export/Export\"", + "\n#!import \"../Utils/TestHelper\"" ] }, { @@ -132,8 +133,27 @@ "\n .MainTabConfigurationWoScenario(partition)", "\n.ExecuteAsync();", "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .PortfolioConfiguration()", + "\n .PortfolioConfiguration()", + "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", + "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "// Run this only after having imported the file exported in the above cell.", + "\n/*", "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", @@ -162,8 +182,7 @@ "\nUtils.EqualityComparer(rps, Workspace.Query().ToArray());", "\nUtils.EqualityComparer(gics, Workspace.Query().ToArray());", "\nUtils.EqualityComparer(grics, Workspace.Query().ToArray());", - "\n", - "\n" + "\n*/" ] }, { @@ -202,8 +221,25 @@ "\n .MainTabConfigurationWoScenario(partition)", "\n.ExecuteAsync();", "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .StateEnumConfiguration() ", + "\n .DataNodeStateConfiguration(dataNodeStates)", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "// Run this only after having imported the file exported in the above cell.", + "\n/*", "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", @@ -223,7 +259,8 @@ "\nawait UploadDataNodeStateToWorkspaceAsync(filename+\".xlsx\");", "\n", "\n// Workspace is empty because ValidateDataNodeStatesAsync removes the entry, since this is already present in the DataSource.", - "\nWorkspace.Query().ToArray().Should().BeEmpty();" + "\nWorkspace.Query().ToArray().Should().BeEmpty();", + "\n*/" ] }, { @@ -265,8 +302,24 @@ "\n .MainTabConfiguration(partition)", "\n.ExecuteAsync();", "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n//-----------------------------------------------------------------", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .DataNodeParameterConfiguration(dataNodeParameters)", + "\n .MainTabConfiguration(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "// Run this only after having imported the file exported in the above cell.", + "\n/*", "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", @@ -292,7 +345,8 @@ "\nvar expectedSingleDataNodeParamBm = Workspace.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month).ToArray();", "\nvar expectedInterDataNodeParamBm = Workspace.Query().ToArray();", "\nUtils.EqualityComparer(singleDataNodeParamBm, expectedSingleDataNodeParamBm);", - "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);" + "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);", + "\n*/" ] }, { diff --git a/Test/QueriesTest.ipynb b/Test/QueriesTest.ipynb index 3c102747..2eddc72f 100644 --- a/Test/QueriesTest.ipynb +++ b/Test/QueriesTest.ipynb @@ -20,7 +20,7 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"../Utils/UtilityMethods\"" + "#!eval-notebook \"../Utils/Queries\"" ] }, { diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/Test/SpecificationsFinancialPerformance.ipynb index 44816ee6..219121be 100644 --- a/Test/SpecificationsFinancialPerformance.ipynb +++ b/Test/SpecificationsFinancialPerformance.ipynb @@ -240,6 +240,18 @@ "### Non Financial" ] }, + { + "cell_type": "markdown", + "source": [ + "Import `CheckEquality`" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Utils/TestHelper\"" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb index 15228d6f..f4d8ab6f 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/Test/SpecificationsSetup.ipynb @@ -17,10 +17,17 @@ "nbformat": 4, "nbformat_minor": 5, "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Specifications Setup

" + ] + }, { "cell_type": "code", "source": [ - "#!import \"../Import/ImportScopeCalculation\"" + "#!import \"../Import/ImportScopeCalculation\"", + "\n#!import \"../Utils/TestHelper\"" ] }, { diff --git a/Test/Tests.ipynb b/Test/Tests.ipynb index ba71bfbc..40b15ba1 100644 --- a/Test/Tests.ipynb +++ b/Test/Tests.ipynb @@ -98,7 +98,7 @@ { "cell_type": "code", "source": [ - "//#!eval-notebook \"MapTemplateAndImportTest\"" + "#!eval-notebook \"MapTemplateAndImportTest\"" ] }, { diff --git a/Utils/Extensions.ipynb b/Utils/Extensions.ipynb new file mode 100644 index 00000000..9e0adcb9 --- /dev/null +++ b/Utils/Extensions.ipynb @@ -0,0 +1,147 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"", + "\n#!import \"ApplicationMessage\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Enumerable Extensions" + ] + }, + { + "cell_type": "code", + "source": [ + "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", + "\nstatic T GetElementOrDefault(this ICollection array, int index)", + "\n{ ", + "\n var count = array.Count;", + "\n if (array == null || count == 0)", + "\n return default(T);", + "\n", + "\n return index < 0", + "\n ? array.ElementAt(0) // should this case be removed?", + "\n : index < count", + "\n ? array.ElementAt(index)", + "\n : array.ElementAt(count -1);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# String Extensions" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Globalization;" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double CheckStringForExponentialAndConvertToDouble (this string s)", + "\n{ ", + "\n if (s == null) return default;", + "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", + "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Enum Extentions" + ] + }, + { + "cell_type": "code", + "source": [ + "public static bool Contains(this T value, T lookingForFlag) ", + "\n where T : struct", + "\n{", + "\n int intValue = (int) (object) value;", + "\n int intLookingForFlag = (int) (object) lookingForFlag;", + "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# ToIdentityString" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Text;", + "\npublic static string ToIdentityString(this T v)", + "\n where T : class", + "\n{", + "\n StringBuilder sb = new StringBuilder();", + "\n var propertyInfos = v.GetType()", + "\n .GetProperties()", + "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", + "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", + "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", + "\n", + "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/ImportCalculationMethods.ipynb b/Utils/ImportCalculationMethods.ipynb new file mode 100644 index 00000000..ec78d688 --- /dev/null +++ b/Utils/ImportCalculationMethods.ipynb @@ -0,0 +1,185 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"./Extensions\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Get Previous Identities" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", + "\n{", + "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", + "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", + "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", + "\n return identities.Where(id => id.AocType != AocTypes.BOP)", + "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", + "\n : previousStep[x.Novelty].RepeatOnce();", + "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", + "\n return ret;});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Get Reference AocStep for calculated steps" + ] + }, + { + "cell_type": "code", + "source": [ + "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", + "\n{", + "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", + "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", + "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", + "\n && aocStep.Novelty == identityAocStep.Novelty) ", + "\n ?? new AocStep(default, default);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Discount and Cumulate" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", + "\n{ ", + "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", + "\n ", + "\n var ret = new double[nominalValues.Length];", + "\n ", + "\n if(periodType == PeriodType.BeginningOfPeriod)", + "\n {", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n return ret;", + "\n }", + "\n ", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n ", + "\n return ret;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", + "\n{ ", + "\n return Enumerable.Range(0, nominalValues.Length)", + "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", + "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", + "\n .Sum() )", + "\n .ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Configuration " + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Nodes" + ] + }, + { + "cell_type": "code", + "source": [ + "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" + ] + }, + { + "cell_type": "code", + "source": [ + "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Change Sign Rules" + ] + }, + { + "cell_type": "code", + "source": [ + "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", + "\n return isActual;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## EstimateType And AmountType" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n return new Dictionary>(){", + "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", + "\n };", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Technical Margin EstimateType" + ] + }, + { + "cell_type": "code", + "source": [ + "public static HashSet GetTechnicalMarginEstimateType()", + "\n{", + "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", + "\n}" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/Queries.ipynb b/Utils/Queries.ipynb new file mode 100644 index 00000000..02105032 --- /dev/null +++ b/Utils/Queries.ipynb @@ -0,0 +1,320 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"./Extensions\"" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Linq.Expressions;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Exchange Rates" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.Query()", + "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", + "\n x.Year == year && x.Month == month)", + "\n .ToArrayAsync())", + "\n .ToDictionaryGrouped(x => x.Currency,", + "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", + "\n {", + "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", + "\n },", + "\n y => y.FxToGroupCurrency));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Current and Previous Parameters" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task LoadParameterAsync(", + "\n this IQuerySource querySource,", + "\n int year,", + "\n int month,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return await querySource.Query()", + "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", + "\n .Where(filterExpression?? (Expression>)(x => true))", + "\n .ToArrayAsync();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadCurrentParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", + "\n .GroupBy(identityExpression)", + "\n .Select(y => y.OrderByDescending(x => x.Year)", + "\n .ThenByDescending(x => x.Month)", + "\n .FirstOrDefault())", + "\n .ToDictionary(identityExpression);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentAndPreviousParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", + "\n ", + "\n var ret = new Dictionary>();", + "\n foreach(var p in parameters)", + "\n {", + "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", + "\n", + "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n ", + "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", + "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", + "\n }", + "\n return ret;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Yield Curve" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Locked-in" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var lockedInYieldCurveByGoc = new Dictionary();", + "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", + "\n {", + "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", + "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", + "\n ", + "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", + "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", + "\n ", + "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", + "\n }", + "\n ", + "\n return lockedInYieldCurveByGoc;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Current" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", + "\n x => x.Currency,", + "\n x => contractualCurrenciesInScope.Contains(x.Currency)", + "\n ));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", + "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", + "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Nodes" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", + "\n ", + "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", + "\n .ToDictionary(dn => dn.SystemName, dn => {", + "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", + "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", + "\n return new DataNodeData(){Year = dnPreviousState.Year, ", + "\n Month = dnPreviousState.Month,", + "\n State = dnCurrentState.State,", + "\n PreviousState = dnPreviousState.State,", + "\n DataNode = dn.SystemName,", + "\n ContractualCurrency = dn.ContractualCurrency,", + "\n FunctionalCurrency = dn.FunctionalCurrency,", + "\n LineOfBusiness = dn.LineOfBusiness,", + "\n ValuationApproach = dn.ValuationApproach,", + "\n OciType = dn.OciType,", + "\n Portfolio = dn.Portfolio,", + "\n AnnualCohort = dn.AnnualCohort,", + "\n LiabilityType = dn.LiabilityType,", + "\n Profitability = dn.Profitability,", + "\n Partner = dn.Partner,", + "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", + "\n };", + "\n }", + "\n );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node Parameters" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Single data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Inter data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", + "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", + "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", + "\n ", + "\n return parameters.SelectMany(p => p", + "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", + "\n .Select(gg =>", + "\n {", + "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n return (key: p.Key,", + "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", + "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", + "\n })", + "\n )", + "\n .ToDictionaryGrouped(x => x.key,", + "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", + "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Aoc Step Configuration" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.LoadParameterAsync(year, month))", + "\n .GroupBy(x => (x.AocType, x.Novelty), ", + "\n (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) ", + "\n => (await querySource.LoadAocStepConfigurationAsync(year, month))", + "\n .ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/TestHelper.ipynb b/Utils/TestHelper.ipynb new file mode 100644 index 00000000..a627b204 --- /dev/null +++ b/Utils/TestHelper.ipynb @@ -0,0 +1,113 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class Utils {", + "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", + "\n {", + "\n collection1.Length.Should().Be(collection2.Length);", + "\n var type = typeof(T);", + "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", + "\n if(properties.Count() == 0) {", + "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", + "\n isEqual.Should().Be(true);", + "\n }", + "\n foreach(var item1 in collection1) {", + "\n var item2 = collection2.Where(x => ", + "\n properties.All(prop => {", + "\n var propType = prop.PropertyType;", + "\n var val = prop.GetValue(item1);", + "\n var otherVal = prop.GetValue(x);", + "\n if(val == null && otherVal == null) return true;", + "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", + "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", + "\n })", + "\n );", + "\n item2.Count().Should().NotBe(0);", + "\n }", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "static var NumericalPrecisionEqualityChecker = 1.0E-10;", + "\n", + "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", + "\n{", + "\n if(arr1.Length != arr2.Length) return false;", + "\n for(int i = 0; i < arr1.Length; i++) {", + "\n double d1 = arr1[i];", + "\n double d2 = arr2[i];", + "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", + "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", + "\n }", + "\n return true;", + "\n}", + "\n", + "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", + "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", + "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", + "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", + "\n", + "\nstatic bool CheckEquality(this double? d1, double? d2) ", + "\n{", + "\n if(d1 == null && d2 == null) return true;", + "\n else return CheckEquality((double)d1, (double)d2);", + "\n}", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# IfrsVariable Report configuration" + ] + }, + { + "cell_type": "code", + "source": [ + "using Systemorph.Vertex.Pivot.Reporting.Builder;" + ] + }, + { + "cell_type": "code", + "source": [ + "public static ReportBuilder WithGridOptionsForIfrsVariable", + "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", + "\n{", + "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", + "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", + "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", + "\n );", + "\n}" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/UtilityMethods.ipynb b/Utils/UtilityMethods.ipynb deleted file mode 100644 index 3436c3e7..00000000 --- a/Utils/UtilityMethods.ipynb +++ /dev/null @@ -1,899 +0,0 @@ -{ - "metadata": { - "authors": [], - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False" - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "cell_type": "code", - "source": [ - "#!import \"../DataModel/DataStructure\"", - "\n#!import \"./ApplicationMessage\"" - ] - }, - { - "cell_type": "code", - "source": [ - "using System.Linq.Expressions;" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Math Functions" - ] - }, - { - "cell_type": "code", - "source": [ - "static double DivideOrDefault(double numerator, double denominator, double defaultValue = default) => Math.Abs(denominator) > double.Epsilon ? numerator / denominator : defaultValue;" - ] - }, - { - "cell_type": "code", - "source": [ - "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", - "\nstatic T GetElementOrDefault(this ICollection array, int index)", - "\n{ ", - "\n var count = array.Count;", - "\n if (array == null || count == 0)", - "\n return default(T);", - "\n", - "\n return index < 0", - "\n ? array.ElementAt(0) // should this case be removed?", - "\n : index < count", - "\n ? array.ElementAt(index)", - "\n : array.ElementAt(count -1);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Enumerable Extensions" - ] - }, - { - "cell_type": "code", - "source": [ - "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# String Extensions" - ] - }, - { - "cell_type": "code", - "source": [ - "using System.Globalization;" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double CheckStringForExponentialAndConvertToDouble (this string s)", - "\n{ ", - "\n if (s == null) return default;", - "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", - "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Enum Extentions" - ] - }, - { - "cell_type": "code", - "source": [ - "public static bool Contains(this T value, T lookingForFlag) ", - "\n where T : struct", - "\n{", - "\n int intValue = (int) (object) value;", - "\n int intLookingForFlag = (int) (object) lookingForFlag;", - "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Queries" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## FX" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", - "\n => (await querySource.Query()", - "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", - "\n x.Year == year && x.Month == month)", - "\n .ToArrayAsync())", - "\n .ToDictionaryGrouped(x => x.Currency,", - "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", - "\n {", - "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", - "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", - "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", - "\n },", - "\n y => y.FxToGroupCurrency));" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", - "\n{", - "\n if(currency == groupCurrency)", - "\n return 1;", - "\n", - "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", - "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", - "\n", - "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", - "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", - "\n", - "\n return currencyToGroupFx;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Current and Previous Parameters" - ] - }, - { - "cell_type": "markdown", - "source": [ - "TODOs:", - "\n
    ", - "\n
  • DataNodes Query: After merging with the new import storage, define IsFirstPeriod property.
  • ", - "\n
  • Once Scenario is defined as a simple property (e.g. in DataNodeState), introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", - "\n
" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task LoadParameterAsync(", - "\n this IQuerySource querySource,", - "\n int year,", - "\n int month,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n return await querySource.Query()", - "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", - "\n .Where(filterExpression?? (Expression>)(x => true))", - "\n .ToArrayAsync();", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadCurrentParameterAsync (", - "\n this IQuerySource querySource,", - "\n Args args,", - "\n Func identityExpression,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", - "\n .GroupBy(identityExpression)", - "\n .Select(y => y.OrderByDescending(x => x.Year)", - "\n .ThenByDescending(x => x.Month)", - "\n .FirstOrDefault())", - "\n .ToDictionary(identityExpression);", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> LoadCurrentAndPreviousParameterAsync (", - "\n this IQuerySource querySource,", - "\n Args args,", - "\n Func identityExpression,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", - "\n ", - "\n var ret = new Dictionary>();", - "\n foreach(var p in parameters)", - "\n {", - "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", - "\n", - "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", - "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", - "\n ", - "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", - "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", - "\n }", - "\n return ret;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Yield Curve" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", - "\n IEnumerable dataNodes)", - "\n{", - "\n var lockedInYieldCurveByGoc = new Dictionary();", - "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", - "\n {", - "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", - "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", - "\n ", - "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", - "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", - "\n ", - "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", - "\n }", - "\n ", - "\n return lockedInYieldCurveByGoc;", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", - "\n IEnumerable dataNodes)", - "\n{", - "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", - "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", - "\n x => x.Currency,", - "\n x => contractualCurrenciesInScope.Contains(x.Currency)", - "\n ));", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node State" - ] - }, - { - "cell_type": "code", - "source": [ - "//TODO : remove this method and clean up in queriesTest. We need a new test for LoadDataNodes.", - "\npublic static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n //This querySource is partitioned", - "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", - "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", - "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Nodes" - ] - }, - { - "cell_type": "code", - "source": [ - "// TODO: the name of this method is strange, one expects DataNodes in return but instead obtains DataNodeData...", - "\npublic static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args) //How do we force the user to provide here a partitioned source? IWorkspace?", - "\n{", - "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", - "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", - "\n ", - "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", - "\n .ToDictionary(dn => dn.SystemName, dn => {", - "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", - "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", - "\n return new DataNodeData(){Year = dnPreviousState.Year, ", - "\n Month = dnPreviousState.Month,", - "\n State = dnCurrentState.State,", - "\n PreviousState = dnPreviousState.State,", - "\n //from Group of Contract", - "\n DataNode = dn.SystemName,", - "\n ContractualCurrency = dn.ContractualCurrency,", - "\n FunctionalCurrency = dn.FunctionalCurrency,", - "\n LineOfBusiness = dn.LineOfBusiness,", - "\n ValuationApproach = dn.ValuationApproach,", - "\n OciType = dn.OciType,", - "\n Portfolio = dn.Portfolio,", - "\n AnnualCohort = dn.AnnualCohort,", - "\n LiabilityType = dn.LiabilityType,", - "\n Profitability = dn.Profitability,", - "\n Partner = dn.Partner,", - "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", - "\n };", - "\n }", - "\n );", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node Parameters" - ] - }, - { - "cell_type": "markdown", - "source": [ - "### Single data Node" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "### Inter data Node" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", - "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", - "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", - "\n ", - "\n return parameters.SelectMany(p => p", - "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", - "\n .Select(gg =>", - "\n {", - "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", - "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", - "\n return (key: p.Key,", - "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", - "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", - "\n })", - "\n )", - "\n .ToDictionaryGrouped(x => x.key,", - "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", - "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Aoc Step Configuration" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", - "\n => (await querySource.LoadParameterAsync(year, month)).GroupBy(x => (x.AocType, x.Novelty), (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) => (await querySource.LoadAocStepConfigurationAsync(year, month)).ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Export Configurations" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Main Tab" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", - "\n => builder.WithTable( config => config .AtBeginning() ", - "\n .WithName(Main) ", - "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.Scenario, x => x.Delete()));" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", - "\n => builder.WithTable( config => config .AtBeginning() ", - "\n .WithName(Main) ", - "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", - "\n .WithColumn(x => x.Id, x => x.Delete()));" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Dimensions" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", - "\n => builder.WithTable(config => { ", - "\n if(DependsOnType != default)", - "\n config = config.DependsOn(DependsOnType); ", - "\n return config .AtBeginning() ", - "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", - "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", - "\n });" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", - "\n => builder.WithTable(config => { ", - "\n if(DependsOnType != default)", - "\n config = config.DependsOn(DependsOnType); ", - "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", - "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", - "\n return config .AtBeginning() ", - "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", - "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", - "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", - "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", - "\n .WithColumn(x => x.OciType, x => x.Delete())", - "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", - "\n });" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node State" - ] - }, - { - "cell_type": "code", - "source": [ - "using DocumentFormat.OpenXml.Spreadsheet;" - ] - }, - { - "cell_type": "code", - "source": [ - "public record HelperState { public string State {get; init;} }" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", - "\n => builder", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data.AsQueryable())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", - "\n );" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", - "\n{", - "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", - "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", - "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", - "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", - "\n .WithSource(source => helperState.AsQueryable()) );", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node Parameter" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", - "\n => builder", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n )", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", - "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n );" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Report Configurations" - ] - }, - { - "cell_type": "code", - "source": [ - "using Systemorph.Vertex.Pivot.Reporting.Builder;" - ] - }, - { - "cell_type": "code", - "source": [ - "public static ReportBuilder WithGridOptionsForIfrsVariable", - "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", - "\n{", - "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", - "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", - "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", - "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", - "\n );", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Utility Methods Class" - ] - }, - { - "cell_type": "markdown", - "source": [ - "This class contains:", - "\n- EqualityComparer" - ] - }, - { - "cell_type": "code", - "source": [ - "public static class Utils {", - "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", - "\n {", - "\n collection1.Length.Should().Be(collection2.Length);", - "\n var type = typeof(T);", - "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", - "\n if(properties.Count() == 0) {", - "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", - "\n isEqual.Should().Be(true);", - "\n }", - "\n foreach(var item1 in collection1) {", - "\n var item2 = collection2.Where(x => ", - "\n properties.All(prop => {", - "\n var propType = prop.PropertyType;", - "\n var val = prop.GetValue(item1);", - "\n var otherVal = prop.GetValue(x);", - "\n if(val == null && otherVal == null) return true;", - "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", - "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", - "\n })", - "\n );", - "\n item2.Count().Should().NotBe(0);", - "\n }", - "\n }", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "// TODO: find a better arrangement to these methods", - "\nstatic var NumericalPrecisionEqualityChecker = 1.0E-10;", - "\n", - "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", - "\n{", - "\n if(arr1.Length != arr2.Length) return false;", - "\n for(int i = 0; i < arr1.Length; i++) {", - "\n double d1 = arr1[i];", - "\n double d2 = arr2[i];", - "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", - "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", - "\n }", - "\n return true;", - "\n}", - "\n", - "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", - "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", - "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", - "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", - "\n", - "\nstatic bool CheckEquality(this double? d1, double? d2) ", - "\n{", - "\n if(d1 == null && d2 == null) return true;", - "\n else return CheckEquality((double)d1, (double)d2);", - "\n}", - "\n" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## ToIdentityString" - ] - }, - { - "cell_type": "code", - "source": [ - "using System.Text;", - "\npublic static string ToIdentityString(this T v)", - "\n where T : class", - "\n{", - "\n StringBuilder sb = new StringBuilder();", - "\n var propertyInfos = v.GetType()", - "\n .GetProperties()", - "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", - "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", - "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", - "\n", - "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## GetPreviousIdentities" - ] - }, - { - "cell_type": "code", - "source": [ - "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", - "\n{", - "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", - "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", - "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", - "\n return identities.Where(id => id.AocType != AocTypes.BOP)", - "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", - "\n : previousStep[x.Novelty].RepeatOnce();", - "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", - "\n return ret;});", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## GetReferenceAocStepForCalculated" - ] - }, - { - "cell_type": "code", - "source": [ - "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", - "\n{", - "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", - "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", - "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", - "\n && aocStep.Novelty == identityAocStep.Novelty) ", - "\n ?? new AocStep(default, default);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Change Sign Rules" - ] - }, - { - "cell_type": "code", - "source": [ - "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", - "\n{", - "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", - "\n return isActual;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# EstimateType And AmountType" - ] - }, - { - "cell_type": "code", - "source": [ - "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", - "\n{", - "\n return new Dictionary>(){", - "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", - "\n };", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Technical Margin EstimateType" - ] - }, - { - "cell_type": "code", - "source": [ - "public static HashSet GetTechnicalMarginEstimateType()", - "\n{", - "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Discount and Cumulate" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", - "\n{ ", - "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", - "\n ", - "\n var ret = new double[nominalValues.Length];", - "\n ", - "\n if(periodType == PeriodType.BeginningOfPeriod)", - "\n {", - "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", - "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", - "\n return ret;", - "\n }", - "\n ", - "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", - "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", - "\n ", - "\n return ret;", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", - "\n{ ", - "\n return Enumerable.Range(0, nominalValues.Length)", - "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", - "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", - "\n .Sum() )", - "\n .ToArray();", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Import Configuration" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Nodes" - ] - }, - { - "cell_type": "code", - "source": [ - "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" - ] - }, - { - "cell_type": "code", - "source": [ - "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" - ] - }, - { - "cell_type": "code", - "source": [ - "" - ] - } - ] -} \ No newline at end of file From 9d1844a6e7da1581a0a518cf4c292e5c035ffeb4 Mon Sep 17 00:00:00 2001 From: Sara Busato Date: Thu, 6 Oct 2022 18:35:51 +0200 Subject: [PATCH 08/38] Including FX positions to FP scope --- Files/DimensionsAndPartitions.csv | 6 ++++-- Report/ReportScopes.ipynb | 32 ++++++++++++++++++++++++++----- 2 files changed, 31 insertions(+), 7 deletions(-) diff --git a/Files/DimensionsAndPartitions.csv b/Files/DimensionsAndPartitions.csv index 80f592bd..b6ad39bb 100644 --- a/Files/DimensionsAndPartitions.csv +++ b/Files/DimensionsAndPartitions.csv @@ -202,8 +202,10 @@ ISE12,Non Financial LIC Changes,ISE,23,,,,,,,, IFIE,Insurance Finance Income/Expense,PNL,24,,,,,,,, IFIE1,Financial LRC Changes,IFIE,25,,,,,,,, IFIE2,Financial LIC Changes,IFIE,26,,,,,,,, -OCI1,Financial LRC Changes,OCI,27,,,,,,,, -OCI2,Financial LIC Changes,OCI,28,,,,,,,, +IFIE3,FX Changes,IFIE,27,,,,,,,, +OCI1,Financial LRC Changes,OCI,28,,,,,,,, +OCI2,Financial LIC Changes,OCI,29,,,,,,,, +OCI3,FX Changes,OCI,30,,,,,,,, ,,,,,,,,,,, @@Profitability,,,,,,,,,,, SystemName,DisplayName,,,,,,,,,, diff --git a/Report/ReportScopes.ipynb b/Report/ReportScopes.ipynb index bc470121..ae87b53d 100644 --- a/Report/ReportScopes.ipynb +++ b/Report/ReportScopes.ipynb @@ -546,7 +546,7 @@ "\n };", "\n ", "\n private IDataCube NonFinancialFcfDeltas => FcfDeltas", - "\n .Filter((\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")); ", + "\n .Filter((\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\")); ", "\n ", "\n IDataCube FpNonFinancial => -1 * NonFinancialFcfDeltas", "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", @@ -568,10 +568,20 @@ "\n FcfDeltas.Filter((\"VariableType\", AocTypes.YCU)) +", "\n FcfDeltas.Filter((\"VariableType\", AocTypes.CRU));", "\n ", + "\n IDataCube FpFx => -1 * FcfDeltas", + "\n .Filter((\"VariableType\", AocTypes.FX))", + "\n .AggregateOver(nameof(Novelty))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = \"IFIE3\"});", + "\n ", "\n IDataCube FpFinancial => -1 * FinancialFcfDeltas", "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeFpFinancial});", "\n", + "\n IDataCube OciFx => (FcfDeltas - CurrentFcfDeltas)", + "\n .Filter((\"VariableType\", AocTypes.FX))", + "\n .AggregateOver(nameof(Novelty))", + "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = \"OCI3\"});", + "\n", "\n IDataCube OciFinancial => (FcfDeltas - CurrentFcfDeltas)", "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", "\n .SelectToDataCube(rv => rv with { Novelty = Novelties.C, VariableType = variableTypeOciFinancial});", @@ -616,10 +626,14 @@ "\n IDataCube Amortization => -1 * Csm.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = variableType.amortization });", "\n ", "\n IDataCube NonFinancialChanges => -1 * Csm", - "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\"))", "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = variableType.nonFinancial });", - "\n ", + "\n", + "\n IDataCube Fx => -1 * Csm.Filter((\"VariableType\", AocTypes.FX))", + "\n .AggregateOver(nameof(Novelty))", + "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IFIE3\" });", + "\n", "\n IDataCube FinancialChanges => -1 * (Csm.Filter((\"VariableType\", AocTypes.IA)) +", "\n Csm.Filter((\"VariableType\", AocTypes.YCU)) +", "\n Csm.Filter((\"VariableType\", AocTypes.CRU)) )", @@ -655,10 +669,14 @@ "\n IDataCube Amortization => -1 * Lc.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE9\" });", "\n ", "\n IDataCube NonFinancialChanges => -1 * Lc", - "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\"))", "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", "\n ", + "\n IDataCube Fx => -1 * Lc.Filter((\"VariableType\", AocTypes.FX))", + "\n .AggregateOver(nameof(Novelty))", + "\n .SelectToDataCube(v => v with { VariableType = \"IFIE3\" });", + "\n", "\n IDataCube FinancialChanges => -1 * (Lc.Filter((\"VariableType\", AocTypes.IA)) +", "\n Lc.Filter((\"VariableType\", AocTypes.YCU)) +", "\n Lc.Filter((\"VariableType\", AocTypes.CRU)) )", @@ -694,10 +712,14 @@ "\n IDataCube Amortization => -1 * Loreco.Filter((\"VariableType\", AocTypes.AM)).SelectToDataCube(v => v with { VariableType = \"ISE8\" });", "\n ", "\n IDataCube NonFinancialChanges => -1 * Loreco", - "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"))", + "\n .Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\"))", "\n .AggregateOver(nameof(Novelty), nameof(VariableType))", "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE11\" });", "\n ", + "\n IDataCube Fx => -1 * Loreco.Filter((\"VariableType\", AocTypes.FX))", + "\n .AggregateOver(nameof(Novelty))", + "\n .SelectToDataCube(v => v with { VariableType = \"IFIE3\" });", + "\n", "\n IDataCube FinancialChanges => -1 * (Loreco.Filter((\"VariableType\", AocTypes.IA)) +", "\n Loreco.Filter((\"VariableType\", AocTypes.YCU)) +", "\n Loreco.Filter((\"VariableType\", AocTypes.CRU)) )", From d171be71bf9c1f9850265fc735c88a37a665c7d2 Mon Sep 17 00:00:00 2001 From: Sara Busato Date: Fri, 7 Oct 2022 11:17:17 +0200 Subject: [PATCH 09/38] FP specification nb - add FX aoc step --- Test/SpecificationsFinancialPerformance.ipynb | 319 +++++++++++++++++- 1 file changed, 304 insertions(+), 15 deletions(-) diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/Test/SpecificationsFinancialPerformance.ipynb index 219121be..e52a0f5e 100644 --- a/Test/SpecificationsFinancialPerformance.ipynb +++ b/Test/SpecificationsFinancialPerformance.ipynb @@ -88,7 +88,7 @@ { "cell_type": "code", "source": [ - "var currencyType = CurrencyType.Contractual ;" + "var currencyType = CurrencyType.Functional ;" ] }, { @@ -301,7 +301,8 @@ "source": [ "var expectedDeltaFCF_nonFinancial = deltaFCF.Filter((\"VariableType\", \"!IA\"), ", "\n (\"VariableType\", \"!YCU\"), ", - "\n (\"VariableType\", \"!CRU\") ).Aggregate().Value;" + "\n (\"VariableType\", \"!CRU\"), ", + "\n (\"VariableType\", \"!FX\") ).Aggregate().Value;" ] }, { @@ -382,7 +383,63 @@ { "cell_type": "markdown", "source": [ - "### Other Comprehensive Income" + "### FX" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the FX contribution to the Fulfillment Cashflows (FCF) is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaFCF_Fx = Test.GetScopes(identities).Aggregate()", + "\n .FpFx.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaFCF_Fx" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The independent recalculation of this value reads" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaFCF_Fx = deltaFCF.Filter((\"VariableType\", \"FX\")).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_Fx" + ] + }, + { + "cell_type": "markdown", + "source": [ + "taking the minus sign into account" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaFCF_Fx.CheckEquality( -computedDeltaFCF_Fx ).Should().Be(true);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n### Other Comprehensive Income" ] }, { @@ -463,6 +520,83 @@ "expectedDeltaFCF_OCI.CheckEquality( computedDeltaFCF_OCI ).Should().Be(true);" ] }, + { + "cell_type": "markdown", + "source": [ + "### FX Other Comprehensive Income" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The FX impact on the Other Comprehensive Income is calculated using the same formulas defined [above](#oci) but is presented separately in the Financial Performance.", + "\n", + "\nThe computed value for the FX contribution to the Other Comprehensive Income (OCI) is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedFxFCF_OCI = Test.GetScopes(identities).Aggregate()", + "\n .OciFx.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedFxFCF_OCI" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The OCI contribution is zero when the OCI option is disabled for the [target Group of Contract](#report).", + "\n", + "\nHere below we follow the steps to calculate independently the FX OCI contribution " + ] + }, + { + "cell_type": "code", + "source": [ + "var FxFCF_Locked = deltaFCF.Filter((\"VariableType\", AocTypes.FX)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "var FxFCF_Current = FCFs_current.Filter((\"VariableType\", AocTypes.FX)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedFxFCF_OCI = FxFCF_Locked - FxFCF_Current;" + ] + }, + { + "cell_type": "code", + "source": [ + "FxFCF_Locked" + ] + }, + { + "cell_type": "code", + "source": [ + "FxFCF_Current" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedFxFCF_OCI" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedFxFCF_OCI.CheckEquality( computedFxFCF_OCI ).Should().Be(true);" + ] + }, { "cell_type": "markdown", "source": [ @@ -528,7 +662,7 @@ { "cell_type": "code", "source": [ - "var expectedDeltaCSM_nonFinancial = deltaCSM.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" + "var expectedDeltaCSM_nonFinancial = deltaCSM.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\")).Aggregate().Value;" ] }, { @@ -571,7 +705,7 @@ { "cell_type": "markdown", "source": [ - "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only Interest Accretion, Yield Curve Update and Credit Risk Update terms" ] }, { @@ -595,6 +729,55 @@ "expectedDeltaCSM_Financial.CheckEquality( -computedDeltaCSM_Financial ).Should().Be(true);" ] }, + { + "cell_type": "markdown", + "source": [ + "### FX" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the FX change of the CSM is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaCSM_Fx = Test.GetScopes(identities).Aggregate()", + "\n .Fx.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaCSM_Fx" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the FX term" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaCSM_Fx = deltaCSM.Filter((\"VariableType\", AocTypes.FX)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaCSM_Fx" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaCSM_Fx.CheckEquality( -computedDeltaCSM_Fx ).Should().Be(true);" + ] + }, { "cell_type": "markdown", "source": [ @@ -654,13 +837,13 @@ { "cell_type": "markdown", "source": [ - "The non Financial contribution is calculated subtracting the Amortization and the Interest Accretion terms:" + "The non Financial contribution is calculated subtracting the Amortization, Interest Accretion, Yield Curve Update, Credit Risk Update, Fx terms:" ] }, { "cell_type": "code", "source": [ - "var expectedDeltaLC_nonFinancial = deltaLC.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate().Value;" + "var expectedDeltaLC_nonFinancial = deltaLC.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\")).Aggregate().Value;" ] }, { @@ -703,7 +886,7 @@ { "cell_type": "markdown", "source": [ - "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + "This value can be independently computed starting from the $\\Delta\\text{LC}$, and considering only the Interest Accretion, Yield Curve Update, Credit Risk Update terms" ] }, { @@ -727,6 +910,55 @@ "expectedDeltaLC_Financial.CheckEquality( -computedDeltaLC_Financial ).Should().Be(true);" ] }, + { + "cell_type": "markdown", + "source": [ + "### FX" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the FX change of the LC is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaLC_Fx = Test.GetScopes(identities).Aggregate()", + "\n .Fx.Filter((\"GroupOfContract\", dataNode)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaLC_Fx" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{LC}$, and considering only the FX term" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLC_Fx = deltaLC.Filter((\"VariableType\", AocTypes.FX)).Aggregate().Value;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLC_Fx" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLC_Fx.CheckEquality( -computedDeltaLC_Fx ).Should().Be(true);" + ] + }, { "cell_type": "markdown", "source": [ @@ -794,7 +1026,7 @@ { "cell_type": "code", "source": [ - "var expectedDeltaLORECO_nonFinancial = deltaLORECO.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\")).Aggregate()?.Value?? 0;" + "var expectedDeltaLORECO_nonFinancial = deltaLORECO.Filter((\"VariableType\", \"!AM\"), (\"VariableType\", \"!IA\"), (\"VariableType\", \"!YCU\"), (\"VariableType\", \"!CRU\"), (\"VariableType\", \"!FX\")).Aggregate()?.Value?? 0;" ] }, { @@ -837,7 +1069,7 @@ { "cell_type": "markdown", "source": [ - "This value can be independently computed starting from the $\\Delta\\text{CSM}$, and considering only the Interest Accretion term" + "This value can be independently computed starting from the $\\Delta\\text{LoReCo}$, and considering only the Interest Accretion, Yield Curve Update, Credit Risk Update terms" ] }, { @@ -861,6 +1093,55 @@ "expectedDeltaLORECO_Financial.CheckEquality( -computedDeltaLORECO_Financial ).Should().Be(true);" ] }, + { + "cell_type": "markdown", + "source": [ + "### FX" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The computed value for the FX change of the LoReCo is" + ] + }, + { + "cell_type": "code", + "source": [ + "var computedDeltaLORECO_Fx = Test.GetScopes(identities).Aggregate()", + "\n .Fx.Filter((\"GroupOfContract\", dataNode)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "computedDeltaLORECO_Fx" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This value can be independently computed starting from the $\\Delta\\text{LoReCo}$, and considering only the FX term" + ] + }, + { + "cell_type": "code", + "source": [ + "var expectedDeltaLORECO_Fx = deltaLORECO.Filter((\"VariableType\", AocTypes.FX)).Aggregate()?.Value?? 0;" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_Fx" + ] + }, + { + "cell_type": "code", + "source": [ + "expectedDeltaLORECO_Fx.CheckEquality( -computedDeltaLORECO_Fx ).Should().Be(true);" + ] + }, { "cell_type": "markdown", "source": [ @@ -1123,10 +1404,11 @@ "\n$$", "\n\\text{IFIE} = \\left\\{", "\n\\begin{array}{ll}", - "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ~~,", + "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} + \\Delta\\text{FCF FX} + \\Delta\\text{CSM FX} + \\Delta\\text{LC FX} ~~,", "\n& \\text{for Insurance contracts} \\\\[0.2cm]", "\n\\Delta\\text{FCF Financial} + \\Delta\\text{CSM Financial} + \\Delta\\text{LC Financial} ", - "\n+ \\Delta\\text{LoReCo Financial} ~~, ", + "\n+ \\Delta\\text{LoReCo Financial} + \\Delta\\text{FCF FX} + \\Delta\\text{CSM FX} + \\Delta\\text{LC FX} ", + "\n+ \\Delta\\text{LoReCo FX} ~~, ", "\n& \\text{for Re-Insurance contracts}", "\n\\end{array}", "\n\\right.", @@ -1142,12 +1424,19 @@ "\nif(groupOfContract.Partner == null) ", "\n IFIE = - expectedDeltaFCF_Financial ", "\n - expectedDeltaCSM_Financial", - "\n - expectedDeltaLC_Financial;", + "\n - expectedDeltaLC_Financial", + "\n - expectedDeltaFCF_Fx ", + "\n - expectedDeltaCSM_Fx", + "\n - expectedDeltaLC_Fx;", "\nelse", "\n IFIE = - expectedDeltaFCF_Financial ", "\n - expectedDeltaCSM_Financial", "\n - expectedDeltaLC_Financial", - "\n - expectedDeltaLORECO_Financial;" + "\n - expectedDeltaLORECO_Financial", + "\n - expectedDeltaFCF_Fx ", + "\n - expectedDeltaCSM_Fx", + "\n - expectedDeltaLC_Fx", + "\n - expectedDeltaLORECO_Fx;" ] }, { @@ -1177,7 +1466,7 @@ { "cell_type": "code", "source": [ - "var OCI = expectedDeltaFCF_OCI;" + "var OCI = expectedDeltaFCF_OCI + expectedFxFCF_OCI;" ] }, { From 2695c4e46035c527a009638b836ad6e651b444ba Mon Sep 17 00:00:00 2001 From: nnikolopoulos <114566025+nnikolopoulos@users.noreply.github.com> Date: Fri, 7 Oct 2022 16:14:43 +0200 Subject: [PATCH 10/38] Rename calculation type with estimate type (#34) * Replace CalculationType with EstimateType * Correct estimateType capitalization error in Test/SpecificationsImportCashflows.ipynb * Clean up notebooks spaces * Empty commit to refresh the meta-data * Cleanup comments in Import/ImportStorage.ipynb * Fix capitalization in Importers & ImportStorage NB * Fix column order in csv * Add blank cell DataNodeParameters link --- Constants/Consts.ipynb | 11 +-- Constants/Validations.ipynb | 3 +- DataModel/DataStructure.ipynb | 25 ++----- Files/DimensionsAndPartitions.csv | 39 +++++----- Import/ImportScopeCalculation.ipynb | 74 +++++++++---------- Import/ImportStorage.ipynb | 10 +-- Import/Importers.ipynb | 14 ++-- .../InitSystemorphBaseToMemory.ipynb | 1 - Initialization/InitSystemorphToDatabase.ipynb | 1 - InputFormatDescription.ipynb | 6 -- Test/AocStructureTest.ipynb | 26 +++---- Test/SpecificationsImportCashflows.ipynb | 20 ++--- Test/SpecificationsSetup.ipynb | 2 +- Test/SpecificationsTechnicalMargin.ipynb | 6 +- 14 files changed, 99 insertions(+), 139 deletions(-) diff --git a/Constants/Consts.ipynb b/Constants/Consts.ipynb index 808308c2..79179ff2 100644 --- a/Constants/Consts.ipynb +++ b/Constants/Consts.ipynb @@ -169,22 +169,13 @@ "\n}" ] }, - { - "cell_type": "code", - "source": [ - "public static class CalculationTypes{", - "\n public const string BE = nameof(BE); //Best Estimate", - "\n public const string CU = nameof(CU); //Coverage Units", - "\n public const string RA = nameof(RA); //Risk Adjustment", - "\n}" - ] - }, { "cell_type": "code", "source": [ "public static class EstimateTypes{", "\n public const string BE = nameof(BE); //Best Estimate", "\n public const string RA = nameof(RA); //Risk Adjustment", + "\n public const string CU = nameof(CU); //Coverage Units", "\n public const string A = nameof(A); //Actuals", "\n public const string AA = nameof(AA); //Advance Actuals", "\n public const string OA = nameof(OA); //Overdue Actuals", diff --git a/Constants/Validations.ipynb b/Constants/Validations.ipynb index d1b09cc0..56dec561 100644 --- a/Constants/Validations.ipynb +++ b/Constants/Validations.ipynb @@ -57,7 +57,7 @@ "\n // Partition", "\n PartitionNotFound, ParsedPartitionNotFound, PartititionNameNotFound, PartitionTypeNotFound,", "\n // Dimensions", - "\n AmountTypeNotFound, EstimateTypeNotFound,CalculationTypeNotFound, ReportingNodeNotFound, AocTypeMapNotFound, AocTypeNotFound, PortfolioGicNotFound, PortfolioGricNotFound, ", + "\n AmountTypeNotFound, EstimateTypeNotFound, ReportingNodeNotFound, AocTypeMapNotFound, AocTypeNotFound, PortfolioGicNotFound, PortfolioGricNotFound, ", "\n InvalidAmountTypeEstimateType, MultipleTechnicalMarginOpening,", "\n // Exchange Rate", "\n ExchangeRateNotFound, ExchangeRateCurrency,", @@ -103,7 +103,6 @@ "\n // Dimensions", "\n (Error.AmountTypeNotFound , 1) => $\"AmountType {s[0]} not found.\",", "\n (Error.EstimateTypeNotFound , 1) => $\"EstimateType {s[0]} not found.\",", - "\n (Error.CalculationTypeNotFound , 1) => $\"CalculationType {s[0]} not found.\",", "\n (Error.ReportingNodeNotFound , 1) => $\"Reporting Node {s[0]} not found.\",", "\n (Error.AocTypeNotFound , 1) => $\"AocType {s[0]} not found.\",", "\n (Error.AocTypeMapNotFound , 2) => $\"AocType {s[0]} and Novelty {s[1]} combination not defined in the mapping.\",", diff --git a/DataModel/DataStructure.ipynb b/DataModel/DataStructure.ipynb index 55885f24..98114494 100644 --- a/DataModel/DataStructure.ipynb +++ b/DataModel/DataStructure.ipynb @@ -305,24 +305,6 @@ "\npublic record DeferrableAmountType : AmountType {}" ] }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Calculation Type", - "\nThis dimension is used to distinguish between e.g. **Best Estimate** values and **Risk Adjustment** values:" - ] - }, - { - "cell_type": "code", - "source": [ - "public record CalculationType : KeyedOrderedDimension {", - "\n [Display(Order = 10)]", - "\n [Dimension(typeof(PeriodType))]", - "\n public PeriodType PeriodType { get; init; }", - "\n}" - ] - }, { "cell_type": "markdown", "source": [ @@ -364,6 +346,9 @@ "\n ", "\n [Display(Order = 120)]", "\n public StructureType StructureType { get; init; }", + "\n", + "\n [Dimension(typeof(PeriodType))]", + "\n public PeriodType PeriodType { get; init; }", "\n}" ] }, @@ -1443,9 +1428,9 @@ "\n public double[] Values { get; init; }", "\n ", "\n [NotVisible]", - "\n [Dimension(typeof(CalculationType))]", + "\n [Dimension(typeof(EstimateType))]", "\n [IdentityProperty]", - "\n public string CalculationType { get; init; }", + "\n public string EstimateType { get; init; }", "\n}" ] }, diff --git a/Files/DimensionsAndPartitions.csv b/Files/DimensionsAndPartitions.csv index b6ad39bb..4c2662b4 100644 --- a/Files/DimensionsAndPartitions.csv +++ b/Files/DimensionsAndPartitions.csv @@ -65,12 +65,6 @@ AM,C,Calculated,6,EndOfPeriod,NotApplicable,NotApplicable,NotApplicable,EndOfPer FX,C,Calculated,0,NotApplicable,NotApplicable,NotApplicable,NotApplicable,NotApplicable,210,1900,1 EOP,C,Calculated,6,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,220,1900,1 ,,,,,,,,,,, -@@CalculationType,,,,,,,,,,, -SystemName,DisplayName,PeriodType,Order,,,,,,,, -BE,Best Estimate,EndOfPeriod,10,,,,,,,, -RA,Risk Adjustment,EndOfPeriod,20,,,,,,,, -CU,Coverage Unit,EndOfPeriod,30,,,,,,,, -,,,,,,,,,,, @@CreditRiskRating,,,,,,,,,,, SystemName,DisplayName,,,,,,,,,, AAA,AAA,,,,,,,,,, @@ -115,22 +109,23 @@ L,Locked-in,10,,,,,,,,, C,Current,20,,,,,,,,, ,,,,,,,,,,, @@EstimateType,,,,,,,,,,, -SystemName,DisplayName,Order,StructureType,InputSource,ExternalId0,ExternalId1,ExternalId2,,,, -BE,Best Estimate of Present Value,1,AoC,4,,,,,,, -RA,Risk Adjustment,10,AoC,4,,,,,,, -C,Contractual Service Margin,20,AoC,7,,,,,,, -L,Loss Component,30,AoC,7,,,,,,, -LR,Loss Recovery Component,40,AoC,7,,,,,,, -PL,Profit and Loss,50,None,7,,,,,,, -AA,Advance Actuals,60,AoC,3,PayablePR,ReceivableNIC,ReceivableICO,,,, -OA,Overdue Actuals,70,AoC,3,ReceivablePR,PayableNIC,PayableICO,,,, -DA,Deferrable Actuals,80,AoC,3,,,,,,, -A,Actuals,90,None,2,,,,,,, -F,Factors,100,None,4,,,,,,, -AAPA,Advance Actuals,110,None,2,,,,,,, -OAPA,Overdue Actuals,120,None,2,,,,,,, -APA,Actuals,130,None,2,,,,,,, -BEPA,Best Estimate of Present Value,140,None,4,,,,,,, +SystemName,DisplayName,Order,StructureType,InputSource,PeriodType,ExternalId0,ExternalId1,ExternalId2,,, +BE,Best Estimate of Present Value,1,AoC,4,,,,EndOfPeriod,,, +RA,Risk Adjustment,10,AoC,4,,,,EndOfPeriod,,, +CU,CoverageUnit,15,AoC,4,,,,EndOfPeriod,,, +C,Contractual Service Margin,20,AoC,7,,,,NotApplicable,,, +L,Loss Component,30,AoC,7,,,,NotApplicable,,, +LR,Loss Recovery Component,40,AoC,7,,,,NotApplicable,,, +PL,Profit and Loss,50,None,7,,,,NotApplicable,,, +AA,Advance Actuals,60,AoC,3,PayablePR,ReceivableNIC,ReceivableICO,NotApplicable,,, +OA,Overdue Actuals,70,AoC,3,ReceivablePR,PayableNIC,PayableICO,NotApplicable,,, +DA,Deferrable Actuals,80,AoC,3,,,,NotApplicable,,, +A,Actuals,90,None,2,,,,NotApplicable,,, +F,Factors,100,None,4,,,,NotApplicable,,, +AAPA,Advance Actuals,110,None,2,,,,NotApplicable,,, +OAPA,Overdue Actuals,120,None,2,,,,NotApplicable,,, +APA,Actuals,130,None,2,,,,NotApplicable,,, +BEPA,Best Estimate of Present Value,140,None,4,,,,NotApplicable,,, ,,,,,,,,,,, @@LiabilityType,,,,,,,,,,, SystemName,DisplayName,,,,,,,,,, diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index 4f8e78f5..ce766089 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -464,20 +464,20 @@ { "cell_type": "code", "source": [ - "public interface NominalCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "public interface NominalCashflow : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", "\n{", "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR && x.Identity.Id.AocType == AocTypes.CF)", "\n .WithApplicability(x => x.Identity.AmountType == AmountTypes.CDR));", "\n", "\n AocStep referenceAocStep => GetScope(Identity.Id).Value;", - "\n double[] Values => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.AccidentYear);", + "\n double[] Values => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, Identity.AmountType, Identity.EstimateType, Identity.AccidentYear);", "\n}", "\n", "\npublic interface CreditDefaultRiskNominalCashflow : NominalCashflow", "\n{", "\n private double[] NominalClaimsCashflow => GetStorage().GetClaims()", - "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", + "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.EstimateType, Identity.AccidentYear))", "\n .Aggregate();", "\n ", "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", @@ -494,7 +494,7 @@ "\npublic interface AllClaimsCashflow : NominalCashflow", "\n{", "\n double[] NominalCashflow.Values => GetStorage().GetClaims()", - "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.CalculationType, Identity.AccidentYear))", + "\n .Select(claim => GetStorage().GetValues(Identity.Id with {AocType = referenceAocStep.AocType, Novelty = referenceAocStep.Novelty}, claim, Identity.EstimateType, Identity.AccidentYear))", "\n .Aggregate();", "\n}" ] @@ -547,9 +547,9 @@ { "cell_type": "code", "source": [ - "public interface DiscountedCashflow : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", + "public interface DiscountedCashflow : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? Accidentyear), ImportStorage>", "\n{", - "\n private PeriodType periodType => GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType); ", + "\n private PeriodType periodType => GetStorage().GetPeriodType(Identity.AmountType, Identity.EstimateType); ", "\n ", "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", "\n builder.ForScope(s => s.WithApplicability(x => x.Identity.Id.IsReinsurance && x.Identity.AmountType == AmountTypes.CDR));", @@ -604,7 +604,7 @@ { "cell_type": "code", "source": [ - "public interface TelescopicDifference : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? Accidentyear), ImportStorage>", + "public interface TelescopicDifference : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? Accidentyear), ImportStorage>", "\n{", "\n [NotVisible]", "\n string EconomicBasis => GetContext();", @@ -612,7 +612,7 @@ "\n ", "\n private double[] PreviousValues => (GetScope((Identity.Id, Identity.AmountType)))", "\n .Values", - "\n .Select(aoc => GetScope((Identity.Id with {AocType = aoc.AocType, Novelty = aoc.Novelty}, Identity.AmountType, Identity.CalculationType, Identity.Accidentyear)).Values)", + "\n .Select(aoc => GetScope((Identity.Id with {AocType = aoc.AocType, Novelty = aoc.Novelty}, Identity.AmountType, Identity.EstimateType, Identity.Accidentyear)).Values)", "\n .Where(cf => cf.Count() > 0)", "\n .Aggregate();", "\n ", @@ -654,7 +654,7 @@ { "cell_type": "code", "source": [ - "public interface IWithGetValueFromValues : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "public interface IWithGetValueFromValues : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", "\n{", "\n private int shift => GetStorage().GetShift(0);//Identity.Id.ProjectionPeriod", "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.Id.ProjectionPeriod", @@ -701,7 +701,7 @@ { "cell_type": "code", "source": [ - "public interface IWithInterestAccretion : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "public interface IWithInterestAccretion : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", "\n{", "\n private double[] parentDiscountedValues => GetScope(Identity).Values; ", "\n private double[] parentNominalValues => GetScope(Identity).Values;", @@ -709,7 +709,7 @@ "\n ", "\n double[] GetInterestAccretion() ", "\n {", - "\n var periodType = GetStorage().GetPeriodType(Identity.AmountType, Identity.CalculationType);", + "\n var periodType = GetStorage().GetPeriodType(Identity.AmountType, Identity.EstimateType);", "\n var ret = new double[parentDiscountedValues.Length];", "\n ", "\n switch (periodType) {", @@ -727,7 +727,7 @@ "\n }", "\n}", "\n", - "\npublic interface IWithInterestAccretionForCreditRisk : IScope<(ImportIdentity Id, string AmountType, string CalculationType, int? AccidentYear), ImportStorage>", + "\npublic interface IWithInterestAccretionForCreditRisk : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", "\n{", "\n private double[] nominalClaimsCashflow => GetScope(Identity).Values;", "\n private double[] nominalValuesCreditRisk => -1 * GetScope(Identity with {Id = Identity.Id with {AocType = AocTypes.CF}}).Values;", @@ -806,7 +806,7 @@ "\n", "\npublic interface ComputePresentValueWithIfrsVariable : PresentValue", "\n{", - "\n double PresentValue.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.CalculationType, EconomicBasis, Identity.AccidentYear); //unify CalculationType and EstimateTypeGet", + "\n double PresentValue.Value => GetStorage().GetValue(Identity.Id, Identity.AmountType, Identity.EstimateType, EconomicBasis, Identity.AccidentYear);", "\n double[] PresentValue.Values => Enumerable.Empty().ToArray();", "\n}", "\n", @@ -887,15 +887,15 @@ "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", "\n string EconomicBasis => EconomicBases.L;", "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.BE;", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.BE;", "\n ", "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", "\n ", "\n [NotVisible]", "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay), o => o.WithContext(EconomicBasis))))", "\n .ToArray();", "\n double Value => PresentValues.Aggregate().Value;", "\n}", @@ -905,15 +905,15 @@ "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", "\n string EconomicBasis => EconomicBases.C;", "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.BE;", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.BE;", "\n ", "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray();", "\n ", "\n [NotVisible]", "\n PresentValue[] PresentValues => GetScope(Identity.DataNode).BeAmountTypes", "\n .SelectMany(at => accidentYears", - "\n .Select(ay => GetScope((Identity, at, CalculationType, ay), o => o.WithContext(EconomicBasis))))", + "\n .Select(ay => GetScope((Identity, at, EstimateType, ay), o => o.WithContext(EconomicBasis))))", "\n .ToArray();", "\n ", "\n double Value => PresentValues.Aggregate().Value;", @@ -947,12 +947,12 @@ "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", "\n string EconomicBasis => EconomicBases.L;", "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.RA;", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.RA;", "\n ", "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", "\n ", - "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray();", + "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, EstimateType, ay), o => o.WithContext(EconomicBasis))).ToArray();", "\n ", "\n double Value => PresentValues.Aggregate().Value;", "\n}", @@ -961,12 +961,12 @@ "\n [IdentityProperty][NotVisible][Dimension(typeof(EconomicBasis))]", "\n string EconomicBasis => EconomicBases.C;", "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.RA;", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.RA;", "\n ", "\n private int?[] accidentYears => GetStorage().GetAccidentYears(Identity.DataNode).ToArray(); ", "\n ", - "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, CalculationType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n PresentValue[] PresentValues => accidentYears.Select(ay => GetScope((Identity, (string)null, EstimateType, ay), o => o.WithContext(EconomicBasis))).ToArray(); ", "\n ", "\n double Value => PresentValues.Aggregate().Value;", "\n}" @@ -1000,10 +1000,10 @@ "\n{ ", "\n [NotVisible] string EconomicBasis => GetContext();", "\n ", - "\n [IdentityProperty][NotVisible][Dimension(typeof(CalculationType))]", - "\n string CalculationType => CalculationTypes.CU;", + "\n [IdentityProperty][NotVisible][Dimension(typeof(EstimateType))]", + "\n string EstimateType => EstimateTypes.CU;", "\n ", - "\n double[] Values => GetScope((Identity, (string)null, CalculationType, (int?)null)).Values;", + "\n double[] Values => GetScope((Identity, (string)null, EstimateType, (int?)null)).Values;", "\n}" ] }, @@ -1034,7 +1034,7 @@ "source": [ "public interface MonthlyAmortizationFactorCashflow : IScope", "\n{", - "\n private double[] NominalCuCashflow => GetScope((Identity with {AocType = AocTypes.CL}, (string)null, CalculationTypes.CU, (int?)null)).Values;", + "\n private double[] NominalCuCashflow => GetScope((Identity with {AocType = AocTypes.CL}, (string)null, EstimateTypes.CU, (int?)null)).Values;", "\n private double[] DiscountedCuCashflow => GetScope(Identity with {AocType = AocTypes.CL}, o => o.WithContext(EconomicBasis)).Values;", "\n ", "\n [NotVisible] string EconomicBasis => GetContext();", @@ -1086,7 +1086,7 @@ "\n", "\npublic interface AmfFromIfrsVariable : CurrentPeriodAmortizationFactor", "\n{", - "\n double CurrentPeriodAmortizationFactor.Value => GetStorage().GetValue(Identity, (string)null, EstimateType, EconomicBasis, (int?)null); //unify CalculationType and EstimateTypeGet", + "\n double CurrentPeriodAmortizationFactor.Value => GetStorage().GetValue(Identity, (string)null, EstimateType, EconomicBasis, (int?)null);", "\n}" ] }, @@ -1497,7 +1497,7 @@ "\n ", "\n double Value => GetScope(Identity.DataNode).BeAmountTypes", "\n .Except(GetStorage().GetNonAttributableAmountType())", - "\n .Sum(at => GetScope((Identity, at, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", + "\n .Sum(at => GetScope((Identity, at, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) +", "\n GetScope(Identity).Value;", "\n ", "\n double AggregatedValue => GetScope((Identity, InputSource.Cashflow)).Values", @@ -1550,12 +1550,12 @@ "\n ", "\n private double attributableExpenseAndCommissions => GetStorage().GetAttributableExpenseAndCommissionAmountType().Sum(d =>", "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, d, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, d, EstimateTypes.A, (int?)null)).Value);", "\n", "\n private double investmentClaims => GetStorage().GetInvestmentClaims().Sum(ic =>", "\n GetStorage().GetNovelties(referenceAocType, InputSource.Cashflow)", - "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, CalculationTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", + "\n .Sum(n => GetScope((Identity with {AocType = referenceAocType, Novelty = n}, ic, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)).Value) -", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.A, (int?)null)).Value - ", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.AA, (int?)null)).Value -", "\n GetScope((Identity with {AocType = referenceAocType, Novelty = Novelties.C}, ic, EstimateTypes.OA, (int?)null)).Value);", @@ -1875,7 +1875,7 @@ "public interface ComputeAllScopes: IScope //ComputeIfrsVariable", "\n{", "\n IEnumerable PvLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", + "\n EstimateType = x.Identity.EstimateType, ", "\n DataNode = x.Identity.Id.DataNode, ", "\n AocType = x.Identity.Id.AocType, ", "\n Novelty = x.Identity.Id.Novelty, ", @@ -1885,7 +1885,7 @@ "\n Partition = GetStorage().TargetPartition", "\n });", "\n IEnumerable PvCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", + "\n EstimateType = x.Identity.EstimateType, ", "\n DataNode = x.Identity.Id.DataNode, ", "\n AocType = x.Identity.Id.AocType, ", "\n Novelty = x.Identity.Id.Novelty, ", @@ -1895,7 +1895,7 @@ "\n Partition = GetStorage().TargetPartition", "\n });", "\n IEnumerable RaCurrent => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", + "\n EstimateType = x.Identity.EstimateType, ", "\n DataNode = x.Identity.Id.DataNode, ", "\n AocType = x.Identity.Id.AocType, ", "\n Novelty = x.Identity.Id.Novelty, ", @@ -1905,7 +1905,7 @@ "\n Partition = GetStorage().TargetPartition", "\n });", "\n IEnumerable RaLocked => GetScope(Identity).PresentValues.Where(x => Math.Abs(x.Value) >= Precision).Select(x => new IfrsVariable{ EconomicBasis = x.EconomicBasis, ", - "\n EstimateType = x.Identity.CalculationType, ", + "\n EstimateType = x.Identity.EstimateType, ", "\n DataNode = x.Identity.Id.DataNode, ", "\n AocType = x.Identity.Id.AocType, ", "\n Novelty = x.Identity.Id.Novelty, ", diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb index 291e0e0b..8dc36adc 100644 --- a/Import/ImportStorage.ipynb +++ b/Import/ImportStorage.ipynb @@ -35,7 +35,7 @@ "\n- [DataNodeParameters](../DataModel/DataStructure)", "\n- [AocType](../DataModel/DataStructure)", "\n- [AmountType](../DataModel/DataStructure)", - "\n- [CalculationType](../DataModel/DataStructure)", + "\n- [EstimateType](../DataModel/DataStructure)", "\n- [DataNodes](../DataModel/DataStructure)", "\n", "\nSuch storage is then passed to calculations defined in the corresponding [Import Scopes](./ImportScopeCalculation)." @@ -105,7 +105,6 @@ "\n //Dimensions", "\n public Dictionary AmountTypeDimension { get; private set; }", "\n public Dictionary NoveltyDimension { get; private set; }", - "\n public Dictionary CalculationTypeDimension { get; private set; }", "\n public Dictionary EstimateTypeDimension { get; private set; }", "\n public Dictionary> EstimateTypesByImportFormat { get; private set; }", "\n public Dictionary ExperienceAdjustEstimateTypeMapping { get; private set; } ", @@ -128,7 +127,6 @@ "\n EstimateTypeDimension = estimateTypes.ToDictionary(x => x.SystemName);", "\n AmountTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", "\n NoveltyDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", - "\n CalculationTypeDimension = (await workspace.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", "\n ", "\n ExperienceAdjustEstimateTypeMapping = new Dictionary{{EstimateTypes.A, EstimateTypes.APA}, {EstimateTypes.AA, EstimateTypes.AAPA}, {EstimateTypes.OA, EstimateTypes.OAPA}}; //TODO move this logic", "\n ", @@ -296,10 +294,10 @@ "\n public int GetShift(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].Shift;", "\n public int GetTimeStep(int projectionPeriod) => ProjectionConfiguration[projectionPeriod].TimeStep;", "\n ", - "\n public PeriodType GetPeriodType(string amountType, string calculationType) => ", + "\n public PeriodType GetPeriodType(string amountType, string estimateType) => ", "\n amountType != null && AmountTypeDimension.TryGetValue(amountType, out var at) ", "\n ? at.PeriodType", - "\n : calculationType != null && CalculationTypeDimension.TryGetValue(calculationType, out var ct) ", + "\n : estimateType != null && EstimateTypeDimension.TryGetValue(estimateType, out var ct) ", "\n ? ct.PeriodType : PeriodType.EndOfPeriod;", "\n", "\n //Variables and Cashflows", @@ -309,7 +307,7 @@ "\n public double[] GetValues(ImportIdentity id, Func whereClause) => GetRawVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Values ?? Enumerable.Empty().ToArray();", "\n public double GetValue(ImportIdentity id, Func whereClause) => GetIfrsVariables(id.DataNode).Where(v => (v.AocType, v.Novelty) == id.AocStep && whereClause(v)).Aggregate()?.Value ?? 0;", "\n ", - "\n public double[] GetValues(ImportIdentity id, string amountType, string calculationType, int? accidentYear) => GetValues(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.CalculationType == calculationType);", + "\n public double[] GetValues(ImportIdentity id, string amountType, string estimateType, int? accidentYear) => GetValues(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType);", "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType);", "\n public double GetValue(ImportIdentity id, string amountType, string estimateType, string economicBasis, int? accidentYear) => GetValue(id, v => v.AccidentYear == accidentYear && v.AmountType == amountType && v.EstimateType == estimateType && v.EconomicBasis == economicBasis);", "\n ", diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index 808b4cbe..319f9b9e 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -55,7 +55,7 @@ "\n public Dictionary DataNodeDataBySystemName;", "\n ", "\n // Dimensions", - "\n public Dictionary CalculationType;", + "\n public Dictionary EstimateType;", "\n public Dictionary PvAmountType; ", "\n public HashSet AocTypeMap;", "\n private HashSet estimateTypes;", @@ -128,7 +128,7 @@ "\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 // Dimensions", - "\n CalculationType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", + "\n EstimateType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", "\n PvAmountType = (await dataSource.Query().ToArrayAsync()).ToDictionary(x => x.SystemName);", "\n amountTypes = (await dataSource.Query().ToArrayAsync()).Select(at => at.SystemName).ToHashSet();", "\n estimateTypes = args.ImportFormat switch {", @@ -748,9 +748,9 @@ "\n }", "\n ", "\n var amountTypeFromFile = datarow.Field(nameof(RawVariable.AmountType));", - "\n var isCalculationType = parsingStorage.CalculationType.ContainsKey(amountTypeFromFile);", - "\n var amountType = isCalculationType ? null : amountTypeFromFile;", - "\n var calculationType = isCalculationType ? amountTypeFromFile : CalculationTypes.BE;", + "\n var isEstimateType = parsingStorage.EstimateType.ContainsKey(amountTypeFromFile);", + "\n var amountType = isEstimateType ? null : amountTypeFromFile;", + "\n var estimateType = isEstimateType ? amountTypeFromFile : EstimateTypes.BE;", "\n ", "\n var values = datarow.Table.Columns.Where(c => c.ColumnName.StartsWith(nameof(RawVariable.Values))).OrderBy(c => c.ColumnName.Length).ThenBy(c => c.ColumnName)", "\n .Select(x => datarow.Field(x.ColumnName).CheckStringForExponentialAndConvertToDouble()).Prune();", @@ -763,10 +763,10 @@ "\n AocType = aocType,", "\n Novelty = novelty,", "\n AmountType = amountType,", - "\n CalculationType = calculationType,", + "\n EstimateType = estimateType,", "\n AccidentYear = Int32.TryParse((datarow.Field(nameof(RawVariable.AccidentYear))), out var tempVal)? tempVal : (int?)null,", "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Values = Multiply(GetSign((aocType, amountType, calculationType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), values)", + "\n Values = Multiply(GetSign((aocType, amountType, estimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), values)", "\n };", "\n return item;", "\n }, ImportFormats.Cashflow", diff --git a/Initialization/InitSystemorphBaseToMemory.ipynb b/Initialization/InitSystemorphBaseToMemory.ipynb index d28022d0..e7b7b98d 100644 --- a/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/Initialization/InitSystemorphBaseToMemory.ipynb @@ -80,7 +80,6 @@ "\n .WithType()", "\n .WithType()", "\n .WithType()", - "\n .WithType()", "\n .WithType()", "\n .WithType()", "\n .WithType()", diff --git a/Initialization/InitSystemorphToDatabase.ipynb b/Initialization/InitSystemorphToDatabase.ipynb index c994f78b..bb25efb5 100644 --- a/Initialization/InitSystemorphToDatabase.ipynb +++ b/Initialization/InitSystemorphToDatabase.ipynb @@ -70,7 +70,6 @@ "\n .WithType()", "\n .WithType()", "\n .WithType()", - "\n .WithType()", "\n .WithType()", "\n .WithType()", "\n .WithType()", diff --git a/InputFormatDescription.ipynb b/InputFormatDescription.ipynb index bee76506..2e81506f 100644 --- a/InputFormatDescription.ipynb +++ b/InputFormatDescription.ipynb @@ -96,12 +96,6 @@ "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." ] - }, - { - "cell_type": "markdown", - "source": [ - "" - ] } ] } \ No newline at end of file diff --git a/Test/AocStructureTest.ipynb b/Test/AocStructureTest.ipynb index 1dbad859..f279ad6f 100644 --- a/Test/AocStructureTest.ipynb +++ b/Test/AocStructureTest.ipynb @@ -223,11 +223,11 @@ "cell_type": "code", "source": [ "var inputRawVariables = new RawVariable[]{", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", "\n};" ] }, @@ -322,11 +322,11 @@ "cell_type": "code", "source": [ "inputRawVariables = new RawVariable[]{", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"EV\", Novelty = \"N\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", "\n};" ] }, @@ -439,9 +439,9 @@ "cell_type": "code", "source": [ "inputRawVariables = new RawVariable[]{", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", - "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", CalculationType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"BOP\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"MC\", Novelty = \"I\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", + "\n new RawVariable{Partition = partition.Id, Values = new []{1.0}, DataNode = groupOfContract, AocType = \"CL\", Novelty = \"C\", AccidentYear = null, AmountType = \"PR\", EstimateType = \"BE\"},", "\n};" ] }, diff --git a/Test/SpecificationsImportCashflows.ipynb b/Test/SpecificationsImportCashflows.ipynb index b392feef..481da388 100644 --- a/Test/SpecificationsImportCashflows.ipynb +++ b/Test/SpecificationsImportCashflows.ipynb @@ -383,14 +383,14 @@ "source": [ "var amountTypePR = \"PR\";", "\nvar amountTypeNIC = \"NIC\";", - "\nvar calculationType = \"BE\";", + "\nvar estimateType = \"BE\";", "\nvar accidentYear = (int?)null;" ] }, { "cell_type": "code", "source": [ - "var nominalPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" + "var nominalPR = Test.GetScope((id, amountTypePR, estimateType, accidentYear));" ] }, { @@ -402,7 +402,7 @@ { "cell_type": "code", "source": [ - "var nominalNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" + "var nominalNIC = Test.GetScope((id, amountTypeNIC, estimateType, accidentYear));" ] }, { @@ -450,7 +450,7 @@ { "cell_type": "code", "source": [ - "var computedDiscountedPR = Test.GetScope((id, amountTypePR, calculationType, accidentYear));" + "var computedDiscountedPR = Test.GetScope((id, amountTypePR, estimateType, accidentYear));" ] }, { @@ -519,7 +519,7 @@ { "cell_type": "code", "source": [ - "var computedDiscountedNIC = Test.GetScope((id, amountTypeNIC, calculationType, accidentYear));" + "var computedDiscountedNIC = Test.GetScope((id, amountTypeNIC, estimateType, accidentYear));" ] }, { @@ -646,7 +646,7 @@ { "cell_type": "code", "source": [ - "var computedDiscountedCRD = Test.GetScope((id, \"CDR\", calculationType, accidentYear));" + "var computedDiscountedCRD = Test.GetScope((id, \"CDR\", estimateType, accidentYear));" ] }, { @@ -676,28 +676,28 @@ { "cell_type": "code", "source": [ - "var nominalNIC = Test.GetScope((id, \"NIC\", calculationType, accidentYear));", + "var nominalNIC = Test.GetScope((id, \"NIC\", estimateType, accidentYear));", "\nnominalNIC" ] }, { "cell_type": "code", "source": [ - "var nominalICO = Test.GetScope((id, \"ICO\", calculationType, accidentYear));", + "var nominalICO = Test.GetScope((id, \"ICO\", estimateType, accidentYear));", "\nnominalICO" ] }, { "cell_type": "code", "source": [ - "var nominalALE = Test.GetScope((id, \"ALE\", calculationType, accidentYear));", + "var nominalALE = Test.GetScope((id, \"ALE\", estimateType, accidentYear));", "\nnominalNIC" ] }, { "cell_type": "code", "source": [ - "var nominalULE = Test.GetScope((id, \"ULE\", calculationType, accidentYear));", + "var nominalULE = Test.GetScope((id, \"ULE\", estimateType, accidentYear));", "\nnominalNIC" ] }, diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb index f4d8ab6f..73244da4 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/Test/SpecificationsSetup.ipynb @@ -88,7 +88,7 @@ "\n", "\npublic static IfrsVariable FromPvToIfrsVariable(this PresentValue scope)", "\n => new IfrsVariable{ EconomicBasis = scope.EconomicBasis, ", - "\n EstimateType = scope.Identity.CalculationType, ", + "\n EstimateType = scope.Identity.EstimateType, ", "\n DataNode = scope.Identity.Id.DataNode, ", "\n AocType = scope.Identity.Id.AocType, ", "\n Novelty = scope.Identity.Id.Novelty, ", diff --git a/Test/SpecificationsTechnicalMargin.ipynb b/Test/SpecificationsTechnicalMargin.ipynb index 13c6c98b..5ef06971 100644 --- a/Test/SpecificationsTechnicalMargin.ipynb +++ b/Test/SpecificationsTechnicalMargin.ipynb @@ -840,7 +840,7 @@ "cell_type": "code", "source": [ "var premiums = premiumAllocationFactor * Test.GetStorage().GetPremiums()", - "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n .Sum(p => referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.A, (int?)null)).Value)", "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.AA, (int?)null)).Value)", "\n -referenceAoC.Sum(aoc => Test.GetScope((Test.GetIdentity(dataNode, aoc.AocType, aoc.Novelty), p, EstimateTypes.OA, (int?)null)).Value)", @@ -869,7 +869,7 @@ "cell_type": "code", "source": [ "var attributableExpenseAndCommissions = new string[] {AmountTypes.ACA, AmountTypes.AEA}", - "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n .Sum(d => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, EstimateTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), d, EstimateTypes.A, (int?)null)).Value));" ] }, @@ -895,7 +895,7 @@ "cell_type": "code", "source": [ "var investmentClaims = Test.GetStorage().GetInvestmentClaims()", - "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, CalculationTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", + "\n .Sum(ic => referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.BE, (int?)null), o => o.WithContext(economicBasis)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.A, (int?)null)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.AA, (int?)null)).Value)", "\n -referenceAoC.Sum(s => Test.GetScope((Test.GetIdentity(dataNode, s.AocType, s.Novelty), ic, EstimateTypes.OA, (int?)null)).Value)", From 56fded2053127272d6c839e075d56987b970dfe4 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Sat, 8 Oct 2022 11:58:41 +0200 Subject: [PATCH 11/38] new data node factory --- Import/Importers.ipynb | 71 +++++++++++++++++++++--------------------- 1 file changed, 36 insertions(+), 35 deletions(-) diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index 808b4cbe..6e3e0a55 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -1,19 +1,19 @@ { "metadata": { - "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, + "toc-autonumbering": "True", + "toc-showcode": "False", "language_info": { "file_extension": ".cs", "mimetype": "text/plain", "name": "C#" }, - "toc-autonumbering": "True", - "toc-showcode": "False", - "toc-showmarkdowntxt": "False" + "toc-showmarkdowntxt": "False", + "authors": [] }, "nbformat": 4, "nbformat_minor": 5, @@ -266,36 +266,31 @@ { "cell_type": "code", "source": [ - "// TODO: think of a better Factory to instantiate DataNode/State/Parameter simultaneously while avoiding public contructors (see Factory Patterns)", - "\n// ATTENTION: this Factory method provides default states and parameters so that it is not mandatory to import them (=> simpler calculation engine). ", - "\n// This method weakness is that these defaults aren't always replaced with the imported values, e,g, when Month > DefaultDataNodeActivationMonth.", - "\n// Therefore they will remain in the DataSource (hopefully without producing any harm).", - "\npublic async Task DataNodeFactoryAsync ()", + "public async Task DataNodeFactoryAsync(string file, string tab, ImportArgs args)", "\n{", - "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", - "\n var existingGroupOfContracts = await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync();", - "\n var importedGroupOfContracts = await Workspace.Query().ToArrayAsync();", - "\n var listOfPartitionsWithPeriod = new List();", - "\n ", - "\n foreach (var groupOfContract in importedGroupOfContracts)", - "\n {", - "\n var name = groupOfContract.SystemName;", - "\n if(!existingGroupOfContracts.Any(x => x.SystemName == name))", - "\n {", - "\n var state = new DataNodeState { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", - "\n var parameter = new SingleDataNodeParameter { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", - "\n await Workspace.UpdateAsync(state);", - "\n if(groupOfContract is GroupOfInsuranceContract) await Workspace.UpdateAsync(parameter);", - "\n }", - "\n }", - "\n ", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n //Hot fix: Disabling default as using Annual Cohort breakes Opening importer logic. ", - "\n //await CommitToDatabase(partition, snapshot: false);", - "\n //await CommitToDatabase(partition, snapshot: false);", + "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).SingleOrDefault();", + "\n if(partition == null) { ApplicationMessage.Log(Error.ParsedPartitionNotFound); return; }", + "\n", + "\n var extension = System.IO.Path.GetExtension(file);", + "\n var stream = await Project.FileStorage.ReadAsync(file);", + "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[tab];", + "\n", + "\n var dataNodesImported = target.Rows.Select(x => x.Field(nameof(RawVariable.DataNode))).ToHashSet();", + "\n var dataNodesDefined = await DataSource.Query().Where(x => dataNodesImported.Contains(x.SystemName)).ToArrayAsync();", + "\n var dataNodeStatesDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync();", + "\n var dataNodeParametersDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync(); ", + "\n", + "\n var dataNodeStatesUndefined = dataNodesImported.Where(x => !dataNodeStatesDefined.Contains(x)).Where(x => x != null).ToHashSet();", + "\n var dataNodeSingleParametersUndefined = dataNodesImported.Where(x => !dataNodeParametersDefined.Contains(x)).Where(x => x != null)", + "\n .Where(x => dataNodesDefined.SingleOrDefault(y => y.SystemName == x) is GroupOfInsuranceContract).ToHashSet();", + "\n", + "\n await DataSource.UpdateAsync( dataNodeStatesUndefined.Select(x => ", + "\n new DataNodeState {DataNode = x, Year = args.Year, Month = DefaultDataNodeActivationMonth, State = State.Active, Partition = partition.Id}).ToArray() );", + "\n", + "\n await DataSource.UpdateAsync( dataNodeSingleParametersUndefined.Select(x => ", + "\n new SingleDataNodeParameter {DataNode = x, Year = args.Year, Month = DefaultDataNodeActivationMonth, PremiumAllocation = DefaultPremiumExperienceAdjustmentFactor, Partition = partition.Id}).ToArray() );", + "\n", + "\n await DataSource.CommitAsync();", "\n}" ] }, @@ -491,8 +486,10 @@ "\n{", "\n var log = await UploadDataNodesToWorkspaceAsync(fileName);", "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", - "\n ", - "\n await DataNodeFactoryAsync(); ", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", "\n return log;", "\n}" ] @@ -784,6 +781,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Cashflow};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.Cashflow, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(fileName, args);", @@ -886,6 +884,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Actual};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.Actual, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", "\n var parsingLog = await ParseActualsToWorkspaceAsync(fileName, args);", @@ -997,6 +996,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.SimpleValue};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.SimpleValue, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n Guid partitionId = new Guid();", @@ -1026,6 +1026,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Opening};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.Opening, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n Guid partitionId = new Guid();", From 74a381bb0a486a8becd62169680358d8137933ab Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Mon, 10 Oct 2022 10:14:56 +0200 Subject: [PATCH 12/38] metadata --- Import/Importers.ipynb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index cfde246c..399ef397 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -1,19 +1,21 @@ { "metadata": { + "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", "name": "C#" }, - "toc-autonumbering": "True", - "toc-showcode": "False", + + "language_info": { "file_extension": ".cs", "mimetype": "text/plain", "name": "C#" }, - "toc-showmarkdowntxt": "False", - "authors": [] + "toc-autonumbering": "True", + "toc-showcode": "False", + "toc-showmarkdowntxt": "False" }, "nbformat": 4, "nbformat_minor": 5, @@ -1059,4 +1061,4 @@ ] } ] -} \ No newline at end of file +} From 10ef85f5ea57b05083ac3ff65a75ba90d71e81ab Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Mon, 10 Oct 2022 10:16:11 +0200 Subject: [PATCH 13/38] metadata x2 --- Import/Importers.ipynb | 2 -- 1 file changed, 2 deletions(-) diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index 399ef397..b9c2ad24 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -6,8 +6,6 @@ "language": "C#", "name": "C#" }, - - "language_info": { "file_extension": ".cs", "mimetype": "text/plain", From 28fd4f99c22626244f0a8c7c334dce0550f94a95 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Mon, 10 Oct 2022 10:18:01 +0200 Subject: [PATCH 14/38] metadata x3 --- Import/Importers.ipynb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index b9c2ad24..db76e980 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -1,6 +1,6 @@ { "metadata": { - "authors": [], + "authors": [], "kernelspec": { "display_name": "Formula Framework", "language": "C#", @@ -11,7 +11,7 @@ "mimetype": "text/plain", "name": "C#" }, - "toc-autonumbering": "True", + "toc-autonumbering": "True", "toc-showcode": "False", "toc-showmarkdowntxt": "False" }, From 4a6c9462807bc13b16bd25585bdc14e43d4b731a Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Mon, 10 Oct 2022 13:54:20 +0200 Subject: [PATCH 15/38] implement feedback --- Import/Importers.ipynb | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Import/Importers.ipynb b/Import/Importers.ipynb index db76e980..cbf48bab 100644 --- a/Import/Importers.ipynb +++ b/Import/Importers.ipynb @@ -268,7 +268,7 @@ "source": [ "public async Task DataNodeFactoryAsync(string file, string tab, ImportArgs args)", "\n{", - "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == args.ReportingNode).ToArrayAsync()).SingleOrDefault();", + "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == args.ReportingNode && p.Scenario == null).ToArrayAsync()).SingleOrDefault();", "\n if(partition == null) { ApplicationMessage.Log(Error.ParsedPartitionNotFound); return; }", "\n", "\n var extension = System.IO.Path.GetExtension(file);", @@ -280,9 +280,10 @@ "\n var dataNodeStatesDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync();", "\n var dataNodeParametersDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync(); ", "\n", - "\n var dataNodeStatesUndefined = dataNodesImported.Where(x => !dataNodeStatesDefined.Contains(x)).Where(x => x != null).ToHashSet();", - "\n var dataNodeSingleParametersUndefined = dataNodesImported.Where(x => !dataNodeParametersDefined.Contains(x)).Where(x => x != null)", - "\n .Where(x => dataNodesDefined.SingleOrDefault(y => y.SystemName == x) is GroupOfInsuranceContract).ToHashSet();", + "\n var dataNodeStatesUndefined = dataNodesImported.Where(x => x != null && !dataNodeStatesDefined.Contains(x)).ToHashSet();", + "\n var dataNodeSingleParametersUndefined = dataNodesImported.Where(x => x != null &&", + "\n !dataNodeParametersDefined.Contains(x) && ", + "\n dataNodesDefined.SingleOrDefault(y => y.SystemName == x) is GroupOfInsuranceContract).ToHashSet();", "\n", "\n await DataSource.UpdateAsync( dataNodeStatesUndefined.Select(x => ", "\n new DataNodeState {DataNode = x, Year = args.Year, Month = DefaultDataNodeActivationMonth, State = State.Active, Partition = partition.Id}).ToArray() );", @@ -1059,4 +1060,4 @@ ] } ] -} +} \ No newline at end of file From 260b8728a9464bdf0361322c4184dd1c646b9ebc Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Mon, 10 Oct 2022 16:01:03 +0200 Subject: [PATCH 16/38] split directories --- .../Database}/.gitignore | 0 .../Database}/Configure.ipynb | 0 .../Database}/Schema Delete.ipynb | 0 .../Export}/MapTemplate.ipynb | 2 +- .../300.ReportingNodes/ReportingNodes.csv | 0 .../DataNodeParameters_CH_2020_12.csv | 0 .../DataNodeStates_CH_2020_12.csv | 0 .../Files}/700.DataNodes/DataNodes_CH.csv | 0 .../800.Parameters/CreditDefaultRate.csv | 0 .../Files}/800.Parameters/ExchangeRate.csv | 0 .../Files}/800.Parameters/PartnerRating.csv | 0 .../Files}/800.Parameters/YieldCurve.csv | 0 .../Actuals_CH_2020_12.csv | 0 .../Actuals_CH_2021_3.csv | 0 .../NominalCashflows_CH_2020_12.csv | 0 .../NominalCashflows_CH_2021_3.csv | 0 .../Openings_CH_2020_12.csv | 0 .../Files}/DimensionsAndPartitions.csv | 32 +- .../Images}/ActualFormat.png | Bin .../Images}/CashflowFormat.png | Bin .../Images}/OpeningFormat.png | Bin .../Images}/SpecificationsCSM.PNG | Bin .../Images}/SpecificationsImportActuals.PNG | Bin .../Images}/SpecificationsImportCashflows.PNG | Bin .../Images}/SpecificationsPL.PNG | Bin .../Images}/Systemorph_logo.png | Bin .../InitSystemorphBaseToMemory.ipynb | 0 .../InitSystemorphToDatabase.ipynb | 0 .../InitSystemorphToMemory.ipynb | 0 .../InputFormatDescription.ipynb | 0 LICENSE => full-ifrs17-template/LICENSE | 0 README.md => full-ifrs17-template/README.md | 0 .../Report}/Reports.ipynb | 0 .../Test}/AocStructureTest.ipynb | 0 .../Test}/Data/CashflowComplex.csv | 0 .../Data/DataNodeParameter_Duplicate.csv | 0 .../DataNodeParameter_InvalidDataNode.csv | 0 .../DataNodeParameter_InvalidReinsCov.csv | 0 .../BM_CH_2020_12_A.csv | 0 .../BM_CH_2020_12_AA.csv | 0 .../BM_CH_2020_12_APA.csv | 0 .../BM_CH_2020_12_BE.csv | 0 .../BM_CH_2020_12_BEPA.csv | 0 .../BM_CH_2020_12_C.csv | 0 .../BM_CH_2020_12_DA.csv | 0 .../BM_CH_2020_12_F.csv | 0 .../BM_CH_2020_12_OA.csv | 0 .../BM_CH_2020_12_RA.csv | 0 .../IfrsVariableBenchmarks/BM_CH_2021_3_A.csv | 0 .../BM_CH_2021_3_AA.csv | 0 .../BM_CH_2021_3_AAPA.csv | 0 .../BM_CH_2021_3_APA.csv | 0 .../BM_CH_2021_3_BE.csv | 0 .../BM_CH_2021_3_BEPA.csv | 0 .../IfrsVariableBenchmarks/BM_CH_2021_3_C.csv | 0 .../BM_CH_2021_3_DA.csv | 0 .../IfrsVariableBenchmarks/BM_CH_2021_3_F.csv | 0 .../IfrsVariableBenchmarks/BM_CH_2021_3_L.csv | 0 .../BM_CH_2021_3_LR.csv | 0 .../BM_CH_2021_3_OA.csv | 0 .../BM_CH_2021_3_OAPA.csv | 0 .../BM_CH_2021_3_RA.csv | 0 ...ableBenchmarks_2020_12_CH__Contractual.csv | 0 ...iableBenchmarks_2021_3_CH__Contractual.csv | 0 .../Test}/ExportIfrsVariable.ipynb | 0 .../Test}/ExportReportVariables.ipynb | 0 .../Test}/IfrsVariablesTest.ipynb | 0 .../Test}/ImportStorageTest.ipynb | 0 .../Test}/MapTemplateAndImportTest.ipynb | 2 +- .../Test}/QueriesTest.ipynb | 0 .../Test}/ReportStorageTest.ipynb | 0 .../Test}/ReportVariablesTest.ipynb | 0 .../Test}/ReportVariablesTestBase.ipynb | 0 .../SpecificationsFinancialPerformance.ipynb | 0 .../Test}/SpecificationsImportActuals.ipynb | 0 .../Test}/SpecificationsImportCashflows.ipynb | 0 .../Test}/SpecificationsSetup.ipynb | 6 +- .../Test}/SpecificationsTechnicalMargin.ipynb | 18 +- .../Test}/TechnicalMarginTest.ipynb | 0 .../Test}/Tests.ipynb | 0 {Constants => ifrs17/Constants}/Consts.ipynb | 0 {Constants => ifrs17/Constants}/Enums.ipynb | 0 .../Constants}/Validations.ipynb | 0 .../DataModel}/DataStructure.ipynb | 0 .../Export/ExportConfiguration.ipynb | 0 ifrs17/Images/ActualFormat.png | Bin 0 -> 25544 bytes ifrs17/Images/CashflowFormat.png | Bin 0 -> 66204 bytes ifrs17/Images/OpeningFormat.png | Bin 0 -> 19729 bytes ifrs17/Images/SpecificationsCSM.PNG | Bin 0 -> 40913 bytes ifrs17/Images/SpecificationsImportActuals.PNG | Bin 0 -> 12211 bytes .../Images/SpecificationsImportCashflows.PNG | Bin 0 -> 38471 bytes ifrs17/Images/SpecificationsPL.PNG | Bin 0 -> 79272 bytes ifrs17/Images/Systemorph_logo.png | Bin 0 -> 17061 bytes .../Import}/ImportScopeCalculation.ipynb | 12 +- {Import => ifrs17/Import}/ImportStorage.ipynb | 0 {Import => ifrs17/Import}/Importers.ipynb | 0 ifrs17/LICENSE | 21 + .../OverviewCalculationEngine.ipynb | 0 ifrs17/README.md | 1 + .../Report}/ReportConfigurationAndUtils.ipynb | 0 {Report => ifrs17/Report}/ReportScopes.ipynb | 0 {Report => ifrs17/Report}/ReportStorage.ipynb | 0 ifrs17/Report/Reports.ipynb | 410 ++++++++++++++++++ .../Utils}/ApplicationMessage.ipynb | 0 {Utils => ifrs17/Utils}/Extensions.ipynb | 0 .../Utils}/ImportCalculationMethods.ipynb | 0 {Utils => ifrs17/Utils}/Queries.ipynb | 0 {Utils => ifrs17/Utils}/TestHelper.ipynb | 0 108 files changed, 468 insertions(+), 36 deletions(-) rename {Database => full-ifrs17-template/Database}/.gitignore (100%) rename {Database => full-ifrs17-template/Database}/Configure.ipynb (100%) rename {Database => full-ifrs17-template/Database}/Schema Delete.ipynb (100%) rename {Export => full-ifrs17-template/Export}/MapTemplate.ipynb (99%) rename {Files => full-ifrs17-template/Files}/300.ReportingNodes/ReportingNodes.csv (100%) rename {Files => full-ifrs17-template/Files}/700.DataNodes/DataNodeParameters_CH_2020_12.csv (100%) rename {Files => full-ifrs17-template/Files}/700.DataNodes/DataNodeStates_CH_2020_12.csv (100%) rename {Files => full-ifrs17-template/Files}/700.DataNodes/DataNodes_CH.csv (100%) rename {Files => full-ifrs17-template/Files}/800.Parameters/CreditDefaultRate.csv (100%) rename {Files => full-ifrs17-template/Files}/800.Parameters/ExchangeRate.csv (100%) rename {Files => full-ifrs17-template/Files}/800.Parameters/PartnerRating.csv (100%) rename {Files => full-ifrs17-template/Files}/800.Parameters/YieldCurve.csv (100%) rename {Files => full-ifrs17-template/Files}/900.TransactionalData/Actuals_CH_2020_12.csv (100%) rename {Files => full-ifrs17-template/Files}/900.TransactionalData/Actuals_CH_2021_3.csv (100%) rename {Files => full-ifrs17-template/Files}/900.TransactionalData/NominalCashflows_CH_2020_12.csv (100%) rename {Files => full-ifrs17-template/Files}/900.TransactionalData/NominalCashflows_CH_2021_3.csv (100%) rename {Files => full-ifrs17-template/Files}/900.TransactionalData/Openings_CH_2020_12.csv (100%) rename {Files => full-ifrs17-template/Files}/DimensionsAndPartitions.csv (91%) rename {Images => full-ifrs17-template/Images}/ActualFormat.png (100%) rename {Images => full-ifrs17-template/Images}/CashflowFormat.png (100%) rename {Images => full-ifrs17-template/Images}/OpeningFormat.png (100%) rename {Images => full-ifrs17-template/Images}/SpecificationsCSM.PNG (100%) rename {Images => full-ifrs17-template/Images}/SpecificationsImportActuals.PNG (100%) rename {Images => full-ifrs17-template/Images}/SpecificationsImportCashflows.PNG (100%) rename {Images => full-ifrs17-template/Images}/SpecificationsPL.PNG (100%) rename {Images => full-ifrs17-template/Images}/Systemorph_logo.png (100%) rename {Initialization => full-ifrs17-template/Initialization}/InitSystemorphBaseToMemory.ipynb (100%) rename {Initialization => full-ifrs17-template/Initialization}/InitSystemorphToDatabase.ipynb (100%) rename {Initialization => full-ifrs17-template/Initialization}/InitSystemorphToMemory.ipynb (100%) rename InputFormatDescription.ipynb => full-ifrs17-template/InputFormatDescription.ipynb (100%) rename LICENSE => full-ifrs17-template/LICENSE (100%) rename README.md => full-ifrs17-template/README.md (100%) rename {Report => full-ifrs17-template/Report}/Reports.ipynb (100%) rename {Test => full-ifrs17-template/Test}/AocStructureTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/Data/CashflowComplex.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/DataNodeParameter_Duplicate.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/DataNodeParameter_InvalidDataNode.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/DataNodeParameter_InvalidReinsCov.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv (100%) rename {Test => full-ifrs17-template/Test}/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv (100%) rename {Test => full-ifrs17-template/Test}/ExportIfrsVariable.ipynb (100%) rename {Test => full-ifrs17-template/Test}/ExportReportVariables.ipynb (100%) rename {Test => full-ifrs17-template/Test}/IfrsVariablesTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/ImportStorageTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/MapTemplateAndImportTest.ipynb (99%) rename {Test => full-ifrs17-template/Test}/QueriesTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/ReportStorageTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/ReportVariablesTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/ReportVariablesTestBase.ipynb (100%) rename {Test => full-ifrs17-template/Test}/SpecificationsFinancialPerformance.ipynb (100%) rename {Test => full-ifrs17-template/Test}/SpecificationsImportActuals.ipynb (100%) rename {Test => full-ifrs17-template/Test}/SpecificationsImportCashflows.ipynb (100%) rename {Test => full-ifrs17-template/Test}/SpecificationsSetup.ipynb (98%) rename {Test => full-ifrs17-template/Test}/SpecificationsTechnicalMargin.ipynb (98%) rename {Test => full-ifrs17-template/Test}/TechnicalMarginTest.ipynb (100%) rename {Test => full-ifrs17-template/Test}/Tests.ipynb (100%) rename {Constants => ifrs17/Constants}/Consts.ipynb (100%) rename {Constants => ifrs17/Constants}/Enums.ipynb (100%) rename {Constants => ifrs17/Constants}/Validations.ipynb (100%) rename {DataModel => ifrs17/DataModel}/DataStructure.ipynb (100%) rename Export/Export.ipynb => ifrs17/Export/ExportConfiguration.ipynb (100%) create mode 100644 ifrs17/Images/ActualFormat.png create mode 100644 ifrs17/Images/CashflowFormat.png create mode 100644 ifrs17/Images/OpeningFormat.png create mode 100644 ifrs17/Images/SpecificationsCSM.PNG create mode 100644 ifrs17/Images/SpecificationsImportActuals.PNG create mode 100644 ifrs17/Images/SpecificationsImportCashflows.PNG create mode 100644 ifrs17/Images/SpecificationsPL.PNG create mode 100644 ifrs17/Images/Systemorph_logo.png rename {Import => ifrs17/Import}/ImportScopeCalculation.ipynb (99%) rename {Import => ifrs17/Import}/ImportStorage.ipynb (100%) rename {Import => ifrs17/Import}/Importers.ipynb (100%) create mode 100644 ifrs17/LICENSE rename OverviewCalculationEngine.ipynb => ifrs17/OverviewCalculationEngine.ipynb (100%) create mode 100644 ifrs17/README.md rename {Report => ifrs17/Report}/ReportConfigurationAndUtils.ipynb (100%) rename {Report => ifrs17/Report}/ReportScopes.ipynb (100%) rename {Report => ifrs17/Report}/ReportStorage.ipynb (100%) create mode 100644 ifrs17/Report/Reports.ipynb rename {Utils => ifrs17/Utils}/ApplicationMessage.ipynb (100%) rename {Utils => ifrs17/Utils}/Extensions.ipynb (100%) rename {Utils => ifrs17/Utils}/ImportCalculationMethods.ipynb (100%) rename {Utils => ifrs17/Utils}/Queries.ipynb (100%) rename {Utils => ifrs17/Utils}/TestHelper.ipynb (100%) diff --git a/Database/.gitignore b/full-ifrs17-template/Database/.gitignore similarity index 100% rename from Database/.gitignore rename to full-ifrs17-template/Database/.gitignore diff --git a/Database/Configure.ipynb b/full-ifrs17-template/Database/Configure.ipynb similarity index 100% rename from Database/Configure.ipynb rename to full-ifrs17-template/Database/Configure.ipynb diff --git a/Database/Schema Delete.ipynb b/full-ifrs17-template/Database/Schema Delete.ipynb similarity index 100% rename from Database/Schema Delete.ipynb rename to full-ifrs17-template/Database/Schema Delete.ipynb diff --git a/Export/MapTemplate.ipynb b/full-ifrs17-template/Export/MapTemplate.ipynb similarity index 99% rename from Export/MapTemplate.ipynb rename to full-ifrs17-template/Export/MapTemplate.ipynb index 2f6034eb..4aa026ea 100644 --- a/Export/MapTemplate.ipynb +++ b/full-ifrs17-template/Export/MapTemplate.ipynb @@ -65,7 +65,7 @@ { "cell_type": "code", "source": [ - "#!import \"../Export/Export\"" + "#!import \"../Export/ExportConfiguration\"" ] }, { diff --git a/Files/300.ReportingNodes/ReportingNodes.csv b/full-ifrs17-template/Files/300.ReportingNodes/ReportingNodes.csv similarity index 100% rename from Files/300.ReportingNodes/ReportingNodes.csv rename to full-ifrs17-template/Files/300.ReportingNodes/ReportingNodes.csv diff --git a/Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv b/full-ifrs17-template/Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv similarity index 100% rename from Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv rename to full-ifrs17-template/Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv diff --git a/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv b/full-ifrs17-template/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv similarity index 100% rename from Files/700.DataNodes/DataNodeStates_CH_2020_12.csv rename to full-ifrs17-template/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv diff --git a/Files/700.DataNodes/DataNodes_CH.csv b/full-ifrs17-template/Files/700.DataNodes/DataNodes_CH.csv similarity index 100% rename from Files/700.DataNodes/DataNodes_CH.csv rename to full-ifrs17-template/Files/700.DataNodes/DataNodes_CH.csv diff --git a/Files/800.Parameters/CreditDefaultRate.csv b/full-ifrs17-template/Files/800.Parameters/CreditDefaultRate.csv similarity index 100% rename from Files/800.Parameters/CreditDefaultRate.csv rename to full-ifrs17-template/Files/800.Parameters/CreditDefaultRate.csv diff --git a/Files/800.Parameters/ExchangeRate.csv b/full-ifrs17-template/Files/800.Parameters/ExchangeRate.csv similarity index 100% rename from Files/800.Parameters/ExchangeRate.csv rename to full-ifrs17-template/Files/800.Parameters/ExchangeRate.csv diff --git a/Files/800.Parameters/PartnerRating.csv b/full-ifrs17-template/Files/800.Parameters/PartnerRating.csv similarity index 100% rename from Files/800.Parameters/PartnerRating.csv rename to full-ifrs17-template/Files/800.Parameters/PartnerRating.csv diff --git a/Files/800.Parameters/YieldCurve.csv b/full-ifrs17-template/Files/800.Parameters/YieldCurve.csv similarity index 100% rename from Files/800.Parameters/YieldCurve.csv rename to full-ifrs17-template/Files/800.Parameters/YieldCurve.csv diff --git a/Files/900.TransactionalData/Actuals_CH_2020_12.csv b/full-ifrs17-template/Files/900.TransactionalData/Actuals_CH_2020_12.csv similarity index 100% rename from Files/900.TransactionalData/Actuals_CH_2020_12.csv rename to full-ifrs17-template/Files/900.TransactionalData/Actuals_CH_2020_12.csv diff --git a/Files/900.TransactionalData/Actuals_CH_2021_3.csv b/full-ifrs17-template/Files/900.TransactionalData/Actuals_CH_2021_3.csv similarity index 100% rename from Files/900.TransactionalData/Actuals_CH_2021_3.csv rename to full-ifrs17-template/Files/900.TransactionalData/Actuals_CH_2021_3.csv diff --git a/Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv b/full-ifrs17-template/Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv similarity index 100% rename from Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv rename to full-ifrs17-template/Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv diff --git a/Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv b/full-ifrs17-template/Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv similarity index 100% rename from Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv rename to full-ifrs17-template/Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv diff --git a/Files/900.TransactionalData/Openings_CH_2020_12.csv b/full-ifrs17-template/Files/900.TransactionalData/Openings_CH_2020_12.csv similarity index 100% rename from Files/900.TransactionalData/Openings_CH_2020_12.csv rename to full-ifrs17-template/Files/900.TransactionalData/Openings_CH_2020_12.csv diff --git a/Files/DimensionsAndPartitions.csv b/full-ifrs17-template/Files/DimensionsAndPartitions.csv similarity index 91% rename from Files/DimensionsAndPartitions.csv rename to full-ifrs17-template/Files/DimensionsAndPartitions.csv index 4c2662b4..bcfe9d1d 100644 --- a/Files/DimensionsAndPartitions.csv +++ b/full-ifrs17-template/Files/DimensionsAndPartitions.csv @@ -110,22 +110,22 @@ C,Current,20,,,,,,,,, ,,,,,,,,,,, @@EstimateType,,,,,,,,,,, SystemName,DisplayName,Order,StructureType,InputSource,PeriodType,ExternalId0,ExternalId1,ExternalId2,,, -BE,Best Estimate of Present Value,1,AoC,4,,,,EndOfPeriod,,, -RA,Risk Adjustment,10,AoC,4,,,,EndOfPeriod,,, -CU,CoverageUnit,15,AoC,4,,,,EndOfPeriod,,, -C,Contractual Service Margin,20,AoC,7,,,,NotApplicable,,, -L,Loss Component,30,AoC,7,,,,NotApplicable,,, -LR,Loss Recovery Component,40,AoC,7,,,,NotApplicable,,, -PL,Profit and Loss,50,None,7,,,,NotApplicable,,, -AA,Advance Actuals,60,AoC,3,PayablePR,ReceivableNIC,ReceivableICO,NotApplicable,,, -OA,Overdue Actuals,70,AoC,3,ReceivablePR,PayableNIC,PayableICO,NotApplicable,,, -DA,Deferrable Actuals,80,AoC,3,,,,NotApplicable,,, -A,Actuals,90,None,2,,,,NotApplicable,,, -F,Factors,100,None,4,,,,NotApplicable,,, -AAPA,Advance Actuals,110,None,2,,,,NotApplicable,,, -OAPA,Overdue Actuals,120,None,2,,,,NotApplicable,,, -APA,Actuals,130,None,2,,,,NotApplicable,,, -BEPA,Best Estimate of Present Value,140,None,4,,,,NotApplicable,,, +BE,Best Estimate of Present Value,1,AoC,4,EndOfPeriod,,,,,, +RA,Risk Adjustment,10,AoC,4,EndOfPeriod,,,,,, +CU,CoverageUnit,15,AoC,4,EndOfPeriod,,,,,, +C,Contractual Service Margin,20,AoC,7,NotApplicable,,,,,, +L,Loss Component,30,AoC,7,NotApplicable,,,,,, +LR,Loss Recovery Component,40,AoC,7,NotApplicable,,,,,, +PL,Profit and Loss,50,None,7,NotApplicable,,,,,, +AA,Advance Actuals,60,AoC,3,NotApplicable,PayablePR,ReceivableNIC,ReceivableICO,,, +OA,Overdue Actuals,70,AoC,3,NotApplicable,ReceivablePR,PayableNIC,PayableICO,,, +DA,Deferrable Actuals,80,AoC,3,NotApplicable,,,,,, +A,Actuals,90,None,2,NotApplicable,,,,,, +F,Factors,100,None,4,NotApplicable,,,,,, +AAPA,Advance Actuals,110,None,2,NotApplicable,,,,,, +OAPA,Overdue Actuals,120,None,2,NotApplicable,,,,,, +APA,Actuals,130,None,2,NotApplicable,,,,,, +BEPA,Best Estimate of Present Value,140,None,4,NotApplicable,,,,,, ,,,,,,,,,,, @@LiabilityType,,,,,,,,,,, SystemName,DisplayName,,,,,,,,,, diff --git a/Images/ActualFormat.png b/full-ifrs17-template/Images/ActualFormat.png similarity index 100% rename from Images/ActualFormat.png rename to full-ifrs17-template/Images/ActualFormat.png diff --git a/Images/CashflowFormat.png b/full-ifrs17-template/Images/CashflowFormat.png similarity index 100% rename from Images/CashflowFormat.png rename to full-ifrs17-template/Images/CashflowFormat.png diff --git a/Images/OpeningFormat.png b/full-ifrs17-template/Images/OpeningFormat.png similarity index 100% rename from Images/OpeningFormat.png rename to full-ifrs17-template/Images/OpeningFormat.png diff --git a/Images/SpecificationsCSM.PNG b/full-ifrs17-template/Images/SpecificationsCSM.PNG similarity index 100% rename from Images/SpecificationsCSM.PNG rename to full-ifrs17-template/Images/SpecificationsCSM.PNG diff --git a/Images/SpecificationsImportActuals.PNG b/full-ifrs17-template/Images/SpecificationsImportActuals.PNG similarity index 100% rename from Images/SpecificationsImportActuals.PNG rename to full-ifrs17-template/Images/SpecificationsImportActuals.PNG diff --git a/Images/SpecificationsImportCashflows.PNG b/full-ifrs17-template/Images/SpecificationsImportCashflows.PNG similarity index 100% rename from Images/SpecificationsImportCashflows.PNG rename to full-ifrs17-template/Images/SpecificationsImportCashflows.PNG diff --git a/Images/SpecificationsPL.PNG b/full-ifrs17-template/Images/SpecificationsPL.PNG similarity index 100% rename from Images/SpecificationsPL.PNG rename to full-ifrs17-template/Images/SpecificationsPL.PNG diff --git a/Images/Systemorph_logo.png b/full-ifrs17-template/Images/Systemorph_logo.png similarity index 100% rename from Images/Systemorph_logo.png rename to full-ifrs17-template/Images/Systemorph_logo.png diff --git a/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb similarity index 100% rename from Initialization/InitSystemorphBaseToMemory.ipynb rename to full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb diff --git a/Initialization/InitSystemorphToDatabase.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb similarity index 100% rename from Initialization/InitSystemorphToDatabase.ipynb rename to full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb diff --git a/Initialization/InitSystemorphToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb similarity index 100% rename from Initialization/InitSystemorphToMemory.ipynb rename to full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb diff --git a/InputFormatDescription.ipynb b/full-ifrs17-template/InputFormatDescription.ipynb similarity index 100% rename from InputFormatDescription.ipynb rename to full-ifrs17-template/InputFormatDescription.ipynb diff --git a/LICENSE b/full-ifrs17-template/LICENSE similarity index 100% rename from LICENSE rename to full-ifrs17-template/LICENSE diff --git a/README.md b/full-ifrs17-template/README.md similarity index 100% rename from README.md rename to full-ifrs17-template/README.md diff --git a/Report/Reports.ipynb b/full-ifrs17-template/Report/Reports.ipynb similarity index 100% rename from Report/Reports.ipynb rename to full-ifrs17-template/Report/Reports.ipynb diff --git a/Test/AocStructureTest.ipynb b/full-ifrs17-template/Test/AocStructureTest.ipynb similarity index 100% rename from Test/AocStructureTest.ipynb rename to full-ifrs17-template/Test/AocStructureTest.ipynb diff --git a/Test/Data/CashflowComplex.csv b/full-ifrs17-template/Test/Data/CashflowComplex.csv similarity index 100% rename from Test/Data/CashflowComplex.csv rename to full-ifrs17-template/Test/Data/CashflowComplex.csv diff --git a/Test/Data/DataNodeParameter_Duplicate.csv b/full-ifrs17-template/Test/Data/DataNodeParameter_Duplicate.csv similarity index 100% rename from Test/Data/DataNodeParameter_Duplicate.csv rename to full-ifrs17-template/Test/Data/DataNodeParameter_Duplicate.csv diff --git a/Test/Data/DataNodeParameter_InvalidDataNode.csv b/full-ifrs17-template/Test/Data/DataNodeParameter_InvalidDataNode.csv similarity index 100% rename from Test/Data/DataNodeParameter_InvalidDataNode.csv rename to full-ifrs17-template/Test/Data/DataNodeParameter_InvalidDataNode.csv diff --git a/Test/Data/DataNodeParameter_InvalidReinsCov.csv b/full-ifrs17-template/Test/Data/DataNodeParameter_InvalidReinsCov.csv similarity index 100% rename from Test/Data/DataNodeParameter_InvalidReinsCov.csv rename to full-ifrs17-template/Test/Data/DataNodeParameter_InvalidReinsCov.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_A.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_AA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_APA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BE.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_BEPA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_OA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_RA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_A.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_AAPA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_APA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BE.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_BEPA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_OAPA.csv diff --git a/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv similarity index 100% rename from Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv rename to full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_RA.csv diff --git a/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv b/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv similarity index 100% rename from Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv rename to full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv diff --git a/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv b/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv similarity index 100% rename from Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv rename to full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv diff --git a/Test/ExportIfrsVariable.ipynb b/full-ifrs17-template/Test/ExportIfrsVariable.ipynb similarity index 100% rename from Test/ExportIfrsVariable.ipynb rename to full-ifrs17-template/Test/ExportIfrsVariable.ipynb diff --git a/Test/ExportReportVariables.ipynb b/full-ifrs17-template/Test/ExportReportVariables.ipynb similarity index 100% rename from Test/ExportReportVariables.ipynb rename to full-ifrs17-template/Test/ExportReportVariables.ipynb diff --git a/Test/IfrsVariablesTest.ipynb b/full-ifrs17-template/Test/IfrsVariablesTest.ipynb similarity index 100% rename from Test/IfrsVariablesTest.ipynb rename to full-ifrs17-template/Test/IfrsVariablesTest.ipynb diff --git a/Test/ImportStorageTest.ipynb b/full-ifrs17-template/Test/ImportStorageTest.ipynb similarity index 100% rename from Test/ImportStorageTest.ipynb rename to full-ifrs17-template/Test/ImportStorageTest.ipynb diff --git a/Test/MapTemplateAndImportTest.ipynb b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb similarity index 99% rename from Test/MapTemplateAndImportTest.ipynb rename to full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb index 6dc5c63c..2fb9a200 100644 --- a/Test/MapTemplateAndImportTest.ipynb +++ b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb @@ -26,7 +26,7 @@ { "cell_type": "code", "source": [ - "#!import \"../Export/Export\"", + "#!import \"../Export/ExportConfiguration\"", "\n#!import \"../Utils/TestHelper\"" ] }, diff --git a/Test/QueriesTest.ipynb b/full-ifrs17-template/Test/QueriesTest.ipynb similarity index 100% rename from Test/QueriesTest.ipynb rename to full-ifrs17-template/Test/QueriesTest.ipynb diff --git a/Test/ReportStorageTest.ipynb b/full-ifrs17-template/Test/ReportStorageTest.ipynb similarity index 100% rename from Test/ReportStorageTest.ipynb rename to full-ifrs17-template/Test/ReportStorageTest.ipynb diff --git a/Test/ReportVariablesTest.ipynb b/full-ifrs17-template/Test/ReportVariablesTest.ipynb similarity index 100% rename from Test/ReportVariablesTest.ipynb rename to full-ifrs17-template/Test/ReportVariablesTest.ipynb diff --git a/Test/ReportVariablesTestBase.ipynb b/full-ifrs17-template/Test/ReportVariablesTestBase.ipynb similarity index 100% rename from Test/ReportVariablesTestBase.ipynb rename to full-ifrs17-template/Test/ReportVariablesTestBase.ipynb diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb similarity index 100% rename from Test/SpecificationsFinancialPerformance.ipynb rename to full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb diff --git a/Test/SpecificationsImportActuals.ipynb b/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb similarity index 100% rename from Test/SpecificationsImportActuals.ipynb rename to full-ifrs17-template/Test/SpecificationsImportActuals.ipynb diff --git a/Test/SpecificationsImportCashflows.ipynb b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb similarity index 100% rename from Test/SpecificationsImportCashflows.ipynb rename to full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb diff --git a/Test/SpecificationsSetup.ipynb b/full-ifrs17-template/Test/SpecificationsSetup.ipynb similarity index 98% rename from Test/SpecificationsSetup.ipynb rename to full-ifrs17-template/Test/SpecificationsSetup.ipynb index 73244da4..c4be9928 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/full-ifrs17-template/Test/SpecificationsSetup.ipynb @@ -97,7 +97,7 @@ "\n Value = scope.Value,", "\n Partition = scope.GetStorage().TargetPartition };", "\n", - "\npublic static IfrsVariable FromCsmToIfrsVariable(this Csm scope)", + "\npublic static IfrsVariable FromCsmToIfrsVariable(this ContractualServiceMaring scope)", "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", "\n DataNode = scope.Identity.DataNode, ", "\n AocType = scope.Identity.AocType, ", @@ -105,7 +105,7 @@ "\n Value = scope.Value,", "\n Partition = scope.GetStorage().TargetPartition };", "\n", - "\npublic static IfrsVariable FromLcToIfrsVariable(this Lc scope)", + "\npublic static IfrsVariable FromLcToIfrsVariable(this LossComponent scope)", "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", "\n DataNode = scope.Identity.DataNode, ", "\n AocType = scope.Identity.AocType, ", @@ -113,7 +113,7 @@ "\n Value = scope.Value,", "\n Partition = scope.GetStorage().TargetPartition };", "\n", - "\npublic static IfrsVariable FromLoReCoToIfrsVariable(this LoReCo scope)", + "\npublic static IfrsVariable FromLoReCoToIfrsVariable(this LossRecoveryComponent scope)", "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", "\n DataNode = scope.Identity.DataNode, ", "\n AocType = scope.Identity.AocType, ", diff --git a/Test/SpecificationsTechnicalMargin.ipynb b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb similarity index 98% rename from Test/SpecificationsTechnicalMargin.ipynb rename to full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb index 5ef06971..ca6f0aca 100644 --- a/Test/SpecificationsTechnicalMargin.ipynb +++ b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb @@ -1115,8 +1115,8 @@ { "cell_type": "code", "source": [ - "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", - "\nvar computedLC_BoP_I = Test.GetScope(id_BoP_I).Value;" + "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", + "\nvar computedLC_BoP_I = Test.GetScope(id_BoP_I).Value;" ] }, { @@ -1190,8 +1190,8 @@ { "cell_type": "code", "source": [ - "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", - "\nvar computedLC_MC_I = Test.GetScope(id_MC_I).Value;" + "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", + "\nvar computedLC_MC_I = Test.GetScope(id_MC_I).Value;" ] }, { @@ -1441,8 +1441,8 @@ { "cell_type": "code", "source": [ - "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", - "\nvar computedLC_CL_C = Test.GetScope(id_CL_C).Value;" + "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", + "\nvar computedLC_CL_C = Test.GetScope(id_CL_C).Value;" ] }, { @@ -1638,8 +1638,8 @@ { "cell_type": "code", "source": [ - "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", - "\nvar computedLC_EoP_C = Test.GetScope(id_EoP_C).Value;" + "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", + "\nvar computedLC_EoP_C = Test.GetScope(id_EoP_C).Value;" ] }, { @@ -1688,7 +1688,7 @@ { "cell_type": "code", "source": [ - "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => x.FromCsmToIfrsVariable())).ToArray();" ] diff --git a/Test/TechnicalMarginTest.ipynb b/full-ifrs17-template/Test/TechnicalMarginTest.ipynb similarity index 100% rename from Test/TechnicalMarginTest.ipynb rename to full-ifrs17-template/Test/TechnicalMarginTest.ipynb diff --git a/Test/Tests.ipynb b/full-ifrs17-template/Test/Tests.ipynb similarity index 100% rename from Test/Tests.ipynb rename to full-ifrs17-template/Test/Tests.ipynb diff --git a/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb similarity index 100% rename from Constants/Consts.ipynb rename to ifrs17/Constants/Consts.ipynb diff --git a/Constants/Enums.ipynb b/ifrs17/Constants/Enums.ipynb similarity index 100% rename from Constants/Enums.ipynb rename to ifrs17/Constants/Enums.ipynb diff --git a/Constants/Validations.ipynb b/ifrs17/Constants/Validations.ipynb similarity index 100% rename from Constants/Validations.ipynb rename to ifrs17/Constants/Validations.ipynb diff --git a/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb similarity index 100% rename from DataModel/DataStructure.ipynb rename to ifrs17/DataModel/DataStructure.ipynb diff --git a/Export/Export.ipynb b/ifrs17/Export/ExportConfiguration.ipynb similarity index 100% rename from Export/Export.ipynb rename to ifrs17/Export/ExportConfiguration.ipynb diff --git a/ifrs17/Images/ActualFormat.png b/ifrs17/Images/ActualFormat.png new file mode 100644 index 0000000000000000000000000000000000000000..e055a0a7fae2ea3eebedf69392d79299c25ab40b GIT binary patch literal 25544 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 literal 0 HcmV?d00001 diff --git a/ifrs17/Images/OpeningFormat.png b/ifrs17/Images/OpeningFormat.png new file mode 100644 index 0000000000000000000000000000000000000000..8bd3a0d7487a0a82cbdacf4dd0e68ec56e58278f GIT binary patch literal 19729 zcmeFYWn5d)(=G}WN}*6%+zM^6;uH%GEyW4$?(Pz-NDWG{;*dbm;O-W*K(XQuffknl z#UaSq^nc#>o_p{4dOqEoA0f%k&XQScX3aeFOt_kg93eh6J_ZH`p@RHd4Gat%;4Rk3 zgL}Zsc@C!)@Pg^7A@>HO>=*48@B!QQHTX3KMrF*yD|6shtYbB0Et%WfTW*b*y}iA| z!^8Rcc?1HnzrX+Y@88wc)w;U6+1c5yuCCG1(W9fIfq{X(zP|DC@y^c9i;Ih!o13ev ztCN!x6bf~Edb+fC>lo@7^URC-?XFA0HntFE4-m_%R?LATcrV=g*%92M1eQ zTWM)&(b3T>D=QNd6JNf3X>V^YDk^GeX^D%Ala-a#)6=uDu`xF{mywZia&lT+Tuewv z(9zMcwzig&lXGxz;OFND=2BT%iAJM8eE9JB^XK#P^Kak2ot>RQAP{YB?H@mWY;0_J zcz75Z8vgn7M?*uSqoZScd)wRFTT4qzQ&W?VkI&uR-N3+ri;F8NDyprm?f38BYinye zJ3HOo-D6{8>FMc4Mn)AC6)r9=xw*Lu3kw+;8JnA%p`oFfnVHqq)vm6t+1c5Cetwsi zmveJ-H8nL>R#stQVPaxpAP|UygTu$i$JyCgR8*9mo!!jL?E3mTFfdR`O3K&QS6NwE zK|#UP)HEa{1Plfb4-c!UsTC9y38jCgr@<>%+aV6cdYi0SF+p`jsrdwV-OyOfla zXV0E_dU~p>t2Z?@#mC1(q0okghTz~}X=!OiMMZyqe*po3s;a8q-d+ z@SdKY!NI}S*4AIYex;_S#>B+f+S-eZ|7 z-@iLLI?~b6F)=YcdGh4>^XFf`e#OSd&dSQd#l>Y|VR`)cF$oC?IXO840|O~3sT)rw zD=RA%6%_#i0U;qF4i3)!`}c{6h=9#w$;fE{yj*!{sAvNF|NpBGj0ykVAV3ayZu0t` z7#NSb?w**vt_6VQkpHgm_O+I;2?{Zgn4?T$H_$=L$xM)PLVC{)XT0Vhq?W%cns-^m zZ6%glt7w0p>v_1C?fwH^1}w$?7tcvExAQQ8hX4P^|8WU~-0EIPV&p%g{f4p6NE?Vj zpLeao$I&4otRw`>6zLqrJurX6HLI?GMJpdN`9cmk^2tw3V5gslC`W(VEd5gvNhWF0 zZ>JC2BiNMde-}7dM6Kz^OS~sIc09_&z&H;wvY^;{U>wRwPtUqR4IeD0W;emt-alh? zdsz+TaP*Y0R*BE$3ov#*;~(f1Uhs3h3mYl9_P^KLF$CaZfTz@eahQVbbA~nbqDkUH?!kL{8&h^SM|h6m0F5 zSy)$Oj8f+W`^q7gK^>%3$^QEZ`!cL#%m03s+&+2OiakTHC}#TSq|Og?i>qHBL1>Ox z?Lwd-tMU5LpYRXv1}PKW0!pt+cHTt?ZC~G-@VG8a(3A!9KM_32h$uUpH0Her^!oT2B?GgNyYdDfeQNzi~nHwSro^Evhk=7g3WYRgTiAnd6Y&lB}Q)d81y!`BB zsb%Q8uC_QKMB~;tuaTZb|G5bWxr%=-I6UNR2s@b*xGqg?Yl1Z9-PVNoQLM_|mp9V)iq+aW}f|bh3Zbe*`S&KY_8g z^F(pyrgBG3c%z=_HYB$;F3h3www&!<5ZDxr_}|5Mz>6aCvn*t0`*`2*56J%KBDNG_ zwJ6}sfZ~=yWjr#C9xLH&A}yvH>z$2g3NiAP#yJdt-YS9wlyT0f|BbN11R0Mp@9i{g zzl+{sq$<~+n9l~uJ2wO=AXpUsdOYnlsmdh%crA}}&Rc*%^clax0GWVs@&VGo;q2o$ z?>C7K=yJB7XfAQC7p&uOoaab((W7_;lOej{N-wZVV#vZ0BW7#&k7d~B%-`h+mHf1q zr!?O%E$Fc&ssu@3Q++6I$Wf9f8xj2QKkFF=h? !ko!SkQbywyi)w^~x(8-S(`S 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 literal 0 HcmV?d00001 diff --git a/ifrs17/Images/SpecificationsCSM.PNG b/ifrs17/Images/SpecificationsCSM.PNG new file mode 100644 index 0000000000000000000000000000000000000000..a04d351d21e730028ab328c8311e70b0f77f19fa GIT binary patch literal 40913 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 literal 0 HcmV?d00001 diff --git a/ifrs17/Images/SpecificationsImportActuals.PNG b/ifrs17/Images/SpecificationsImportActuals.PNG new file mode 100644 index 0000000000000000000000000000000000000000..7f3d5d05a460fba884f58baaeeb41c84a4617c0b GIT binary patch literal 12211 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 z zGk``Oerpa(iPi<=r!C%E(Bbz8?*40 zeoXb7UBBkFJOmZ7Sr7aXI8pmYHhAhV-?@TD7n_EOm#&vg17*k=pqc|P4L49fAuLnJ zj;Vh4IM%R8F8Dd=3akpkoM~0Fxa1r6R}r}6LY+dm!+e3Dr7%;A?Y4=)x3HVQrv`M4 zf%qeXzRp_J3YdH2el00r&Z&calkacOWznvJDX@m}FfEHSP8A4lC+nE z5dGFOdbH}wALTKgsp1+Cvg>Y(IS^OP2?BKgziM*W(*=$t?zGIcX+fRTY4Fmk3XXR&Xt!;o&W|MH&CB0u&P zXb7(@QTJ7`-FKL*FDE<+JrS;mEjYCM3a`|U8R-C>_~}ng#C0;#)epZjDcwE6fbE*# zAa+jVuLJiSrEskmTFO-?!Uq>27J(tl*yO!qbq$V80J7)MIY+}Y)Gd!rBkfA$EfLgDvDy*dt5{PSOeV~~r2T*aW%fiou`tzM>_ ox%0PE;r~}h%K!V16_2fjnV)nRz3RMsoja$#4qUrL^XL2j3jj;*0{{R3 literal 0 HcmV?d00001 diff --git a/ifrs17/Images/SpecificationsImportCashflows.PNG b/ifrs17/Images/SpecificationsImportCashflows.PNG new file mode 100644 index 0000000000000000000000000000000000000000..bcb093c83f1aeed76336d9853ce6074735e120e8 GIT binary patch literal 38471 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 z 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", + "public interface ContractualServiceMaring : IScope", "\n{", "\n [NotVisible]string EstimateType => EstimateTypes.C;", "\n ", @@ -1842,7 +1842,7 @@ { "cell_type": "code", "source": [ - "public interface Lc : IScope", + "public interface LossComponent : IScope", "\n{", "\n [NotVisible]string EstimateType => EstimateTypes.L;", "\n ", @@ -1853,7 +1853,7 @@ { "cell_type": "code", "source": [ - "public interface LoReCo : IScope", + "public interface LossRecoveryComponent : IScope", "\n{ ", "\n [NotVisible]string EstimateType => EstimateTypes.LR;", "\n ", @@ -1998,7 +1998,7 @@ "\n ", "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", "\n ? Enumerable.Empty()", - "\n : GetScope(Identity).RepeatOnce()", + "\n : GetScope(Identity).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", "\n DataNode = x.Identity.DataNode,", @@ -2011,7 +2011,7 @@ "\n IEnumerable Loss => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", "\n ? Enumerable.Empty()", "\n : Identity.IsReinsurance ", - "\n ? GetScope(Identity).RepeatOnce()", + "\n ? GetScope(Identity).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", "\n DataNode = x.Identity.DataNode,", @@ -2020,7 +2020,7 @@ "\n Value = x.Value,", "\n Partition = GetStorage().TargetPartition", "\n })", - "\n : GetScope(Identity).RepeatOnce()", + "\n : GetScope(Identity).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", "\n DataNode = x.Identity.DataNode,", diff --git a/Import/ImportStorage.ipynb b/ifrs17/Import/ImportStorage.ipynb similarity index 100% rename from Import/ImportStorage.ipynb rename to ifrs17/Import/ImportStorage.ipynb diff --git a/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb similarity index 100% rename from Import/Importers.ipynb rename to ifrs17/Import/Importers.ipynb diff --git a/ifrs17/LICENSE b/ifrs17/LICENSE new file mode 100644 index 00000000..e0b8588d --- /dev/null +++ b/ifrs17/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Systemorph + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/OverviewCalculationEngine.ipynb b/ifrs17/OverviewCalculationEngine.ipynb similarity index 100% rename from OverviewCalculationEngine.ipynb rename to ifrs17/OverviewCalculationEngine.ipynb diff --git a/ifrs17/README.md b/ifrs17/README.md new file mode 100644 index 00000000..5173f5ae --- /dev/null +++ b/ifrs17/README.md @@ -0,0 +1 @@ +# IFRS17CalculationEngine \ No newline at end of file diff --git a/Report/ReportConfigurationAndUtils.ipynb b/ifrs17/Report/ReportConfigurationAndUtils.ipynb similarity index 100% rename from Report/ReportConfigurationAndUtils.ipynb rename to ifrs17/Report/ReportConfigurationAndUtils.ipynb diff --git a/Report/ReportScopes.ipynb b/ifrs17/Report/ReportScopes.ipynb similarity index 100% rename from Report/ReportScopes.ipynb rename to ifrs17/Report/ReportScopes.ipynb diff --git a/Report/ReportStorage.ipynb b/ifrs17/Report/ReportStorage.ipynb similarity index 100% rename from Report/ReportStorage.ipynb rename to ifrs17/Report/ReportStorage.ipynb diff --git a/ifrs17/Report/Reports.ipynb b/ifrs17/Report/Reports.ipynb new file mode 100644 index 00000000..91d3d680 --- /dev/null +++ b/ifrs17/Report/Reports.ipynb @@ -0,0 +1,410 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Reports

", + "\n", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Infrastructure and Configuration" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Initialize data" + ] + }, + { + "cell_type": "code", + "source": [ + "/* DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"../Database/Configure\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Imports and Configurations" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportScopes\"" + ] + }, + { + "cell_type": "code", + "source": [ + "var reportStorage = new ReportStorage(Workspace, Report);", + "\nawait reportStorage.InitializeReportIndependentCacheAsync();", + "\nvar mostRecentPartition = (await Workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last();", + "\nvar reportingNodeRoot = (await Workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName;", + "\nawait reportStorage.InitializeAsync((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);", + "\nvar identities = reportStorage.GetIdentities((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Calling Scope" + ] + }, + { + "cell_type": "code", + "source": [ + "var universe = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Report Settings and Storage Update" + ] + }, + { + "cell_type": "code", + "source": [ + "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", + "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", + "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", + "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", + "\n ;", + "\n", + "\nawait reportStorage.InitializeAsync(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);", + "\nidentities = reportStorage.GetIdentities(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Constellation", + "\n", + "\nWe have " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Present Value", + "\n", + "\nPresent values of the best estimate of future cashflows are shown here in an Analysis of Change report.", + "\n", + "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", + "\nThe figures displayed in the report are automatically aggregated to meet the granularity desired by the user.", + "\n", + "\nCurrently, the data is sliced by :", + "\n- CurrencyType", + "\n- LiabilityType", + "\n- EconomicBasis", + "\n", + "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", + "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data." + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedBestEstimate + universe.GetScopes(identities).Aggregate().CurrentBestEstimate)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\", \"EconomicBasis\") //\"GroupOfContract\"", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Risk Adjustment" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedRiskAdjustment + universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"EconomicBasis\", \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Written", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"AmountType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 450)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Advance, Overdue Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Advance + universe.GetScopes(identities).Aggregate().Overdue)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions(reportHeight: 400)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Deferrable Actuals" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Deferrals", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 400)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Fulfilment Cashflow" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Fcf ", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")//, \"EstimateType\")//, \"AmountType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Actuarial Experience Adjustment" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().ActuarialExperienceAdjustment", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"AmountType\" )//\"LiabilityType\", \"EstimateType\")", + "\n .ReportGridOptions(reportHeight: 300, headerColumnWidth: 300)", + "\n .ToReport() " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LRC Technical Margin" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().LrcTechnicalMargin", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 600)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Contractual Service Margin / Loss Component / Loss Recovery Component" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Csm + universe.GetScopes(identities).Aggregate().Lc + universe.GetScopes(identities).Aggregate().Loreco)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LRC Actuarial" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LrcActuarial)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"LiabilityType\",\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LRC" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lrc)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType),\"GroupOfContract\", \"EstimateType\")", + "\n .ReportGridOptions(300)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LIC Actuarial" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LicActuarial)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions()", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# LIC" + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lic)", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", + "\n .ReportGridOptions(300)", + "\n .ToReport()" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Financial Performance", + "\n", + "\nUse the expand and collapse buttons in the report rows to change the granularity of the figures displayed." + ] + }, + { + "cell_type": "code", + "source": [ + "Report.ForDataCube(universe.GetScopes(identities).Aggregate().FinancialPerformance", + "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", + "\n )", + "\n .WithQuerySource(DataSource)", + "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", + "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", + "\n .ToReport()" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/ApplicationMessage.ipynb b/ifrs17/Utils/ApplicationMessage.ipynb similarity index 100% rename from Utils/ApplicationMessage.ipynb rename to ifrs17/Utils/ApplicationMessage.ipynb diff --git a/Utils/Extensions.ipynb b/ifrs17/Utils/Extensions.ipynb similarity index 100% rename from Utils/Extensions.ipynb rename to ifrs17/Utils/Extensions.ipynb diff --git a/Utils/ImportCalculationMethods.ipynb b/ifrs17/Utils/ImportCalculationMethods.ipynb similarity index 100% rename from Utils/ImportCalculationMethods.ipynb rename to ifrs17/Utils/ImportCalculationMethods.ipynb diff --git a/Utils/Queries.ipynb b/ifrs17/Utils/Queries.ipynb similarity index 100% rename from Utils/Queries.ipynb rename to ifrs17/Utils/Queries.ipynb diff --git a/Utils/TestHelper.ipynb b/ifrs17/Utils/TestHelper.ipynb similarity index 100% rename from Utils/TestHelper.ipynb rename to ifrs17/Utils/TestHelper.ipynb From 5b072d77dd2be0d107fdf0b841e35400e94c77cf Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Tue, 11 Oct 2022 14:46:48 +0200 Subject: [PATCH 17/38] fix tests + add readme + seperate overview nb --- full-ifrs17-template/Database/Configure.ipynb | 2 +- .../InitSystemorphBaseToMemory.ipynb | 2 +- .../InitSystemorphToDatabase.ipynb | 6 - .../OverviewIFRS17Template.ipynb | 135 ++++++++++++++++++ full-ifrs17-template/README.md | 36 ++++- full-ifrs17-template/Report/Reports.ipynb | 24 ++-- .../Test/MapTemplateAndImportTest.ipynb | 7 - full-ifrs17-template/Test/QueriesTest.ipynb | 2 +- .../Test/ReportStorageTest.ipynb | 6 - .../Test/ReportVariablesTest.ipynb | 18 --- .../Test/ReportVariablesTestBase.ipynb | 8 +- .../SpecificationsFinancialPerformance.ipynb | 19 --- .../Test/SpecificationsImportActuals.ipynb | 42 +++--- .../Test/SpecificationsImportCashflows.ipynb | 42 +++--- .../Test/SpecificationsSetup.ipynb | 7 - .../Test/SpecificationsTechnicalMargin.ipynb | 44 +++--- ifrs17/CalculationEngine.ipynb | 30 ++++ ifrs17/Images/ActualFormat.png | Bin 25544 -> 0 bytes ifrs17/Images/BigPicture.PNG | Bin 0 -> 38530 bytes ifrs17/Images/CashflowFormat.png | Bin 66204 -> 0 bytes ifrs17/Images/OpeningFormat.png | Bin 19729 -> 0 bytes ifrs17/Images/SpecificationsCSM.PNG | Bin 40913 -> 0 bytes ifrs17/Images/SpecificationsImportActuals.PNG | Bin 12211 -> 0 bytes .../Images/SpecificationsImportCashflows.PNG | Bin 38471 -> 0 bytes ifrs17/Images/SpecificationsPL.PNG | Bin 79272 -> 0 bytes ifrs17/OverviewCalculationEngine.ipynb | 68 +-------- ifrs17/README.md | 32 ++++- 27 files changed, 325 insertions(+), 205 deletions(-) create mode 100644 full-ifrs17-template/OverviewIFRS17Template.ipynb create mode 100644 ifrs17/CalculationEngine.ipynb delete mode 100644 ifrs17/Images/ActualFormat.png create mode 100644 ifrs17/Images/BigPicture.PNG delete mode 100644 ifrs17/Images/CashflowFormat.png delete mode 100644 ifrs17/Images/OpeningFormat.png delete mode 100644 ifrs17/Images/SpecificationsCSM.PNG delete mode 100644 ifrs17/Images/SpecificationsImportActuals.PNG delete mode 100644 ifrs17/Images/SpecificationsImportCashflows.PNG delete mode 100644 ifrs17/Images/SpecificationsPL.PNG diff --git a/full-ifrs17-template/Database/Configure.ipynb b/full-ifrs17-template/Database/Configure.ipynb index 9b23844f..b332a43c 100644 --- a/full-ifrs17-template/Database/Configure.ipynb +++ b/full-ifrs17-template/Database/Configure.ipynb @@ -27,7 +27,7 @@ { "cell_type": "code", "source": [ - "#!import \"../DataModel/DataStructure\"" + "#!import \"//ifrs17ce/dev/CalculationEngine\"" ] }, { diff --git a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb index e7b7b98d..293cb431 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb @@ -29,7 +29,7 @@ { "cell_type": "code", "source": [ - "#!import \"../Import/Importers\"" + "#!import \"//ifrs17ce/dev/CalculationEngine\"" ] }, { diff --git a/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb index bb25efb5..9b7b5ab5 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb @@ -29,12 +29,6 @@ "#!import \"../Database/Configure\"" ] }, - { - "cell_type": "code", - "source": [ - "#!import \"../Import/Importers\"" - ] - }, { "cell_type": "markdown", "source": [ diff --git a/full-ifrs17-template/OverviewIFRS17Template.ipynb b/full-ifrs17-template/OverviewIFRS17Template.ipynb new file mode 100644 index 00000000..7145abb7 --- /dev/null +++ b/full-ifrs17-template/OverviewIFRS17Template.ipynb @@ -0,0 +1,135 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

IFRS17 Template - an Overview

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Introduction", + "\n", + "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\n", + "\nThis notebook provides an **overview** of Systemorph's Full IFRS 17 Template with brief introductions to all the main steps." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# IFRS 17", + "\n", + "\nIFRS 17 is a new accounting standard for insurance contracts. The previous standard IFRS 4, which is based on nominal accounting, is replaced by the economic accounting standard IFRS 17.", + "\n", + "\nIFRS 17 deals with insurance contracts which are on the liability side of the balance sheet. Other accounting standards deal with other parts of the business, primarily IFRS 9 for invested assets.", + "\n", + "\nInsurance policies need to be allocated to homogeneous groups of insurance contracts (GICs) according to high-level principles established by the IFRS 17 standard, such as contract type, line of business, annual cohort etc. Insurers have some degree of freedom to optmize those GICs, as long as they respect the high-level principles.", + "\n", + "\nInsurance contracts generate different types of cashflows. For example, **Amount Type** is a dimension refering to premiums, claims, expenses of different kinds, etc. for these cashflows. The Calculation Engine presented here expects input files of all the projected cashflows for each GIC, for different regular time points (quarterly or monthly, ...) and corresponding actual amounts observed for a given period. ", + "\n", + "\nEach cashflow is characterized by all the necessary attributes: business unit, start time, amount type, novelty of business etc. and projected cashflow amounts in a regular time grid until the final run-off of all contracts.", + "\n", + "\nIf the entered cashflows are nominal (the usual case), the the present value (PV) of each cashflow is computed using proper yield curves for discounting.", + "\n", + "\nA central element of IFRS 17 is the Analysis of Change (AoC). The present value of the business (future cashflows) changes from the beginning to the end of the accounting period due to different effects, each of them constituting a modeled AoC step.", + "\n", + "\nIn IFRS 17, the value of future profitable business has a component called the Contractual Service Margin (CSM), defined at GIC level. The profit measured as CSM is recognized slowly over time rather than immediately in financial performance statements. On the other hand, a GIC can be onerous and produce a Loss Component (LC) instead, which needs to be recognized immediately.", + "\n", + "\nSeveral reports on the valuation of cashflows, balance sheet and financial performance can be produced, each dealing with different aspects, such as", + "\n - Present Value of Future Cash Flows (PVFCF)", + "\n - Contractual Service Margin (CSM) and Loss Component (LC)", + "\n - Liability for Remaining Coverage (LRC)", + "\n - Liability for Incurred Claims (LIC)", + "\n - Financial Performance", + "\n - Accounting Events" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data input" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Reporting nodes, dimensions and partitions", + "\n", + "\nSee folders *Files* (DimensionsAndPartitions) and *Files/300.ReportingNodes* (ReportingNodes).", + "\n- **ReportingNodes**: List of business units, often per country, with system name and display name, currency and \"G\" for the whole group", + "\n- **DimensionsAndPartitions**: The many dimensions (21) required to characterize all of the data and results, with system names and display names. This information is quite stable, but some information related to partitions refers to the reporting nodes " + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Groups of insurance and reinsurance contracts", + "\n", + "\nSee folder Files/700.DataNodes. The information is about data nodes, that is Groups of Insurance Contracts (GICs) and Groups of Reinsurance Contracts (GRICs) and portfolios of these.", + "\n- **DataNodes**: List of all GICs and GRICs, each with several attributes and the portfolios to which they belong; an additional attribute of GRICs being the reinsurance partner", + "\n- **DataNodeParameters** *\\_* *\\_* *\\_*: List of those GICs and GRICs that are actually used for the given reporting node/year/month combination with few attributes; if needed, more such files may be added for other reporting node/year/month combinations", + "\n- **DataNodeStates** *\\_* *\\_* *\\_*: Switching data nodes on and off, the normal state is (\"Active\") for all the GICs and GRICs of the reporting node/year/month combination; if needed, more such files may be added for other reporting node/year/month combinations" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Parameters from financial markets", + "\n", + "\nSee folder Files/800.Parameters.", + "\n- **YieldCurve**: List of all yield curves to be used, for different currencies and as-of dates (year/month), using a yearly grid of interest rate maturities extending as far as needed", + "\n- **ExchangeRate**: List of exchange rates to be used, for different currencies and as-of dates (year/month), with a type (Spot/Average); defined as the value of 1 foreign unit expressed in the group currency of the insurance company ", + "\n- **CreditDefaultRate**: For relevant year/month combinations, each with a full list of all credit ratings in S&P notation with their default rate (= probabilty of default within 1 year)", + "\n- **PartnerRating**: For each reinsurance partner of a relevant GRIC, the rating in S&P notation with the as-of date (year/month)" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n## Data input: Groups of insurance and reinsurance contracts", + "\n", + "\nSee folder Files/900.TransactionalData.", + "\n- **Actuals** *\\_* *\\_* *\\_*: List of all actual amounts for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types and other attributes; we need at least two such files for the two dates of the Analysis of Change", + "\n- **Openings** *\\_* *\\_* *\\_*: List of the opening amounts for some GICs that are used by the given reporting node. The year/month combination corresponds to the beginning of the planned Analysis of Change period, so only one such file is required. The entries are by EstimateType and AmountType.", + "\n- **NominalCashflows** *\\_* *\\_* *\\_*: List of all projected cash flows for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types, novelty types and other attributes, where the cash flow amounts are given in a regular sequence extending as far as needed; we need at least two such files for the two dates of the Analysis of Change", + "\n", + "\nThe structure of the [Actuals](./InputFormatDescription#actual), [Openings](./InputFormatDescription#opening) and [NominalCashflows](./InputFormatDescription#cashflow) files is explained in a special [notebook](./InputFormatDescription).", + "\n", + "\nThe less usual option of having discounted instead of nominal cash flows in the input is also supported." + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Reports", + "\n", + "\nThe production of reports is done by a notebook such as **[Reports](./Report/Reports#report-production)**." + ] + } + ] +} \ No newline at end of file diff --git a/full-ifrs17-template/README.md b/full-ifrs17-template/README.md index 5173f5ae..5c22a397 100644 --- a/full-ifrs17-template/README.md +++ b/full-ifrs17-template/README.md @@ -1 +1,35 @@ -# IFRS17CalculationEngine \ No newline at end of file +![Systemorph_logo.png](https://portal.systemorph.cloud/api/project/userclone/env/dev/file/download?path=Images/Systemorph_logo.png) + +**Full IFRS 17 Template** + +Systemorph's IFRS 17 [Calculation Engine](https://portal.systemorph.cloud/api/project/ifrs17ce/env/dev/) is a tool to conduct all the essential IFRS 17 calculations given some key figures. +Systemorph's *Full IFRS 17 Template* uses our IFRS 17 Calculation Engine to import several use-cases and show the results. + +# Get Started + +Interact with this *Full IFRS 17 Template* after having cloned the project. + +# Supporting Material + +Check out the [video]() (this is a youtube link to Marketing) + +# Report + +Check out the IFRS 17 reports [here](./Report/Reports) + +# Testing + +If you want a step by step guide into the calculation logic, please go to the "Specification" notebook you are interested in: +- [Cashflow Calculation](./Test/SpecificationsImportCashflows) +- [Actuals Calculation](./Test/SpecificationsImportActuals) +- [Technical Margin Calculation](./Test/SpecificationsTechnicalMargin) +- [Financial Performance Calculation](./Test/SpecificationsFinancialPerformance) + +# Got Questions + +For support around the IFRS17 CalculationEngine you can personally reach out to one of our IFRS17 experts: +- [Dr. Andrea Muolo]() +- [Dr. Davide Colleoni](https://www.linkedin.com/in/davidecolleoni/) +- [Mrs. Sara Busato]() + +If you are interested in adapting the IFRS17 CalculationEngine to your data and would like to start a collaboration with us, you can contact [Wolfgang Maehr]() \ No newline at end of file diff --git a/full-ifrs17-template/Report/Reports.ipynb b/full-ifrs17-template/Report/Reports.ipynb index 91d3d680..1dc742bd 100644 --- a/full-ifrs17-template/Report/Reports.ipynb +++ b/full-ifrs17-template/Report/Reports.ipynb @@ -62,12 +62,6 @@ "## Imports and Configurations" ] }, - { - "cell_type": "code", - "source": [ - "#!import \"ReportScopes\"" - ] - }, { "cell_type": "code", "source": [ @@ -114,9 +108,12 @@ { "cell_type": "markdown", "source": [ - "# Data Constellation", + "# Use cases", "\n", - "\nWe have " + "\nFor demostration purposes we import data for 7 *Group of Insurance Contract* (GIC) and 4 *Group of Reinsurance Contract* (GRIC). ", + "\n
Data set consists in cashflows, actuals, and parameters.", + "\n", + "\n" ] }, { @@ -127,15 +124,10 @@ "\nPresent values of the best estimate of future cashflows are shown here in an Analysis of Change report.", "\n", "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", - "\nThe figures displayed in the report are automatically aggregated to meet the granularity desired by the user.", - "\n", - "\nCurrently, the data is sliced by :", - "\n- CurrencyType", - "\n- LiabilityType", - "\n- EconomicBasis", - "\n", "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", - "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data." + "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data.", + "\n", + "\nAggregated values are displayed when the data has a finer granularity than the one selected by the report slice options." ] }, { diff --git a/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb index 2fb9a200..f82db019 100644 --- a/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb +++ b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb @@ -23,13 +23,6 @@ "

Test Map Template Export and Import

" ] }, - { - "cell_type": "code", - "source": [ - "#!import \"../Export/ExportConfiguration\"", - "\n#!import \"../Utils/TestHelper\"" - ] - }, { "cell_type": "code", "source": [ diff --git a/full-ifrs17-template/Test/QueriesTest.ipynb b/full-ifrs17-template/Test/QueriesTest.ipynb index 2eddc72f..ab6ca4d9 100644 --- a/full-ifrs17-template/Test/QueriesTest.ipynb +++ b/full-ifrs17-template/Test/QueriesTest.ipynb @@ -20,7 +20,7 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"../Utils/Queries\"" + "#!import \"../CalculationEngine\"" ] }, { diff --git a/full-ifrs17-template/Test/ReportStorageTest.ipynb b/full-ifrs17-template/Test/ReportStorageTest.ipynb index acb1f22c..5fc57968 100644 --- a/full-ifrs17-template/Test/ReportStorageTest.ipynb +++ b/full-ifrs17-template/Test/ReportStorageTest.ipynb @@ -17,12 +17,6 @@ "nbformat": 4, "nbformat_minor": 5, "cells": [ - { - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Report/ReportStorage\"" - ] - }, { "cell_type": "code", "source": [ diff --git a/full-ifrs17-template/Test/ReportVariablesTest.ipynb b/full-ifrs17-template/Test/ReportVariablesTest.ipynb index fb6904bf..cbaca38e 100644 --- a/full-ifrs17-template/Test/ReportVariablesTest.ipynb +++ b/full-ifrs17-template/Test/ReportVariablesTest.ipynb @@ -47,24 +47,6 @@ "#!import \"ReportVariablesTestBase\"" ] }, - { - "cell_type": "markdown", - "source": [ - "## Initialize Workspace" - ] - }, - { - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ] - }, - { - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ] - }, { "cell_type": "markdown", "source": [ diff --git a/full-ifrs17-template/Test/ReportVariablesTestBase.ipynb b/full-ifrs17-template/Test/ReportVariablesTestBase.ipynb index 4f320987..99e9ac16 100644 --- a/full-ifrs17-template/Test/ReportVariablesTestBase.ipynb +++ b/full-ifrs17-template/Test/ReportVariablesTestBase.ipynb @@ -26,7 +26,13 @@ { "cell_type": "code", "source": [ - "#!import \"../Report/ReportScopes\"" + "#!import \"../Initialization/InitSystemorphToMemory\"" + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" ] }, { diff --git a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb index e52a0f5e..3cfaff8e 100644 --- a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb +++ b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb @@ -97,13 +97,6 @@ "Import the Report definitions, initialize the Workspace and the Test Suite:" ] }, - { - "cell_type": "code", - "source": [ - "#!import \"../Report/ReportScopes\"", - "\n#!import \"../Report/ReportConfigurationAndUtils\"" - ] - }, { "cell_type": "code", "source": [ @@ -240,18 +233,6 @@ "### Non Financial" ] }, - { - "cell_type": "markdown", - "source": [ - "Import `CheckEquality`" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"../Utils/TestHelper\"" - ] - }, { "cell_type": "markdown", "source": [ diff --git a/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb b/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb index d71638e8..7785ed4a 100644 --- a/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb @@ -34,24 +34,6 @@ "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." ] }, - { - "cell_type": "markdown", - "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"SpecificationsSetup\"" - ] - }, - { - "cell_type": "markdown", - "source": [ - "---" - ] - }, { "cell_type": "markdown", "source": [ @@ -93,6 +75,30 @@ "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" ] }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb index 481da388..7831cbde 100644 --- a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb @@ -36,24 +36,6 @@ "\nThroughout this notebook we adopt the following variable notation: we use the words *computed* vs. *expected* to differentiate the results provided by the application vs. this test notebook, respectively." ] }, - { - "cell_type": "markdown", - "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"SpecificationsSetup\"" - ] - }, - { - "cell_type": "markdown", - "source": [ - "---" - ] - }, { "cell_type": "markdown", "source": [ @@ -100,6 +82,30 @@ "Workspace.InitializeFrom(DataSource);" ] }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, + { + "cell_type": "markdown", + "source": [ + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/full-ifrs17-template/Test/SpecificationsSetup.ipynb b/full-ifrs17-template/Test/SpecificationsSetup.ipynb index c4be9928..335f1ca3 100644 --- a/full-ifrs17-template/Test/SpecificationsSetup.ipynb +++ b/full-ifrs17-template/Test/SpecificationsSetup.ipynb @@ -23,13 +23,6 @@ "

Specifications Setup

" ] }, - { - "cell_type": "code", - "source": [ - "#!import \"../Import/ImportScopeCalculation\"", - "\n#!import \"../Utils/TestHelper\"" - ] - }, { "cell_type": "code", "source": [ diff --git a/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb index ca6f0aca..26e2d8f3 100644 --- a/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb +++ b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb @@ -37,59 +37,65 @@ { "cell_type": "markdown", "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + "# Import Data" ] }, { - "cell_type": "code", + "cell_type": "markdown", "source": [ - "#!import \"SpecificationsSetup\"" + "", + "\n## Current Period" ] }, { "cell_type": "markdown", "source": [ - "---" + "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" ] }, { - "cell_type": "markdown", + "cell_type": "code", "source": [ - "# Import Data" + "var year = 2021 ;", + "\nvar month = 3 ;", + "\nvar reportingNode = \"CH\" ;", + "\nvar economicBasis = \"L\" ;" ] }, { "cell_type": "markdown", "source": [ - "", - "\n## Current Period" + "Import the Dimensions, Parameters, Nominal Cashflows, and Actuals from the corresponding csv files in Initialization/Systemorph/" ] }, { - "cell_type": "markdown", + "cell_type": "code", "source": [ - "Please select the target period (i.e. year and month) and Reporting Node based on the imported data:" + "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" ] }, { - "cell_type": "code", + "cell_type": "markdown", "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"L\" ;" + "---" ] }, { "cell_type": "markdown", "source": [ - "Import the Dimensions, Parameters, Nominal Cashflows, and Actuals from the corresponding csv files in Initialization/Systemorph/" + "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" ] }, { "cell_type": "code", "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" + "#!import \"SpecificationsSetup\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "---" ] }, { @@ -1708,7 +1714,7 @@ { "cell_type": "code", "source": [ - "var lc = allInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "var lc = allInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => x.FromLcToIfrsVariable())).ToArray();" ] @@ -1728,7 +1734,7 @@ { "cell_type": "code", "source": [ - "var loreco = allReInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "var loreco = allReInsuranceIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => x.FromLoReCoToIfrsVariable())).ToArray();" ] diff --git a/ifrs17/CalculationEngine.ipynb b/ifrs17/CalculationEngine.ipynb new file mode 100644 index 00000000..d6a34d5e --- /dev/null +++ b/ifrs17/CalculationEngine.ipynb @@ -0,0 +1,30 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"DataModel/DataStructure\"", + "\n#!import \"Report/ReportScopes\"", + "\n#!import \"Import/Importers\"", + "\n#!import \"Export/ExportConfiguration\"", + "\n#!import \"Utils/TestHelper\"", + "\n#!import \"Utils/ImportCalculationMethods\"" + ] + } + ] +} \ No newline at end of file diff --git a/ifrs17/Images/ActualFormat.png b/ifrs17/Images/ActualFormat.png deleted file mode 100644 index e055a0a7fae2ea3eebedf69392d79299c25ab40b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25544 zcmeFYg;yNk(l$Df5Pm=i!2<+Ia1ZVh2s$_nE`dOBcN-uA0fNim4#C}JhCpz4cXt_F zzs~v2dEayYguCwTwR(;0?ya?JS3UJqu!@olHYO=12n52Gll`Cu0-*t4QHTF|0(@L$ zvzh`QD9&m!5}?w-*E_(Er{?b!--AFE5mkB^V+Y7vKrhsVdqGcz;4 zfB!x>I5;{wT3T9aY;5f5=@}dxJUu<_?(RN0IT;@x|MTY$5{bOLyu7`=y}7x$zP>&? zJG;2JI6psMSy^doYbz}+t*EHz=;+wk*eEM2TU}j6AP{gke0zI)c6N4ha&muvzpJZj zWMpK0eLXEL&EDSL$jC@RK|xtr`QyirPEJlGB_%sMJGr^Jj*gCsii!pX1`ZAmy}iBf z-n}CyCwF&u$HKyjjEvmc+WPwStE;Q4m6g@h)YRJA+Su4wc6N4bZ0wgWUrbF+fBpJZ zTwMI^+qbK$D=-+$!^0CD9nH$h3WLGs=jVfhf^2PV7Z(>hJ3E(`mz$fLtE;Q^_4S>d zo#W%X zT6lQ4pP%2u!-KA_Zf0g?U|`_F!h)uz=KcNs#KeTJuWx>SzLu6&dV2cY++0RR#^&Z` zR8&-OaIlGq2`?{iWo6~3PoIAL_)%0;WNB#`6BFa_?_X0>t_!&6dHVq;@tWMq_-lyq}*lb4s5k&*fQ`Lm#)ATcp9 zKR>^ys3;2yinhsi>$ZDJikBv2k&69o}Vd zadB~Sa?;b&laZ0(;NWm`bJNh!ynXwYnwpxFl=S7xmuP5cuV25Wpr9ZiAi&4RM?pb( z@!|y`A>p%U&wwoeTvKNMC;}h1E^12Zfbjo+^a8D=Kj{Xh0mDI7#~B2A(f;>F>9WrU zw1$z6+=urX9)<_0V6SX>{JaU9P?3rk6u%Q#%PBNlGjzG^m-__|NrKk}f5}HnJ>0k8 zn(E`t>E!%F+ik}7cZ&c2>;J_waP=7X_@tGwoR|hACTm_M3KCUt@8V2$wqxrvHOIGj zK_KpcSDZo<-;)ya6?K|TA7o29)F*7zFU03e%^Z&(j*s@z=bJQUh5$YK+MTru=(mhG ziqD&ppU7|D(SV|-1g*qh93OZX{FkY@)j*Co$8jIgu5?vEb7;)}Tap2SzbpnlCUv2e zC$3on&4$xqE`LM4QY%OGVP)_?_(Hgh^&9iJ>^;g;%FHO#A2{y~F*N6_&PaMMR^);UMkEsho%_!?DH;9mdD#{!e}2^v2xoX5l!m!{ z-nn5n1JBvrv5F+KCM1ZT0{UwG9>oTh&ftG9T@w(pC~T|lu2Z+c8G+;+YWGO2E&26* zx!(5HY$j+gF8=#HROi<9<5a>i<1rW*Voe69whxD(wIRI;IxXAOaZ`Vd!kp!E+q`OYw!jvxqFoDdiQ(u5p6;lCCMOl*&ax;0~S4J$9tC?lT617If ze<5SN-IjMhsGI9%ZjCDqZDK7AP}MfX`uE%~8i8QYq@e3j#W^1xEykcTuN4BLmpDGm zk@0?H?D)5ijk}nUn9CB3w?zNlSUKu`*Y{G->+Hy2c}n8elhKl|AF5Gv_7-e2Q5pI^ zF#GRG8wC+AH?{unbod_J?9Ce4KY<86tbdL7x);Zt_#G_2b|tmf5Z~^1d&Ks#FgUuJC+BWluAftaY{r#{psjmJ}BxuDzJI?*@ZTIgtB&g9|BG9ko|Gh^>KcJj}mpA5T2L@8g zH&f96Rz&Bup-6AODC0a>GFI>G4eeY=K^||L@sIKA@n>)=2_=g=vz+zn4GwZAJ3DOx zO2WC#QPhW|)>-(#2KC^5SumxiGX&1!er+9Depl8m z<22VK-`e?(<%+5N=0?-|~h)2)Euvsk3k4-t?k7HFfS+mn2 z8{_iHW!f4;)(qUhE}!x=R^Aj3;zz9f7Hf~?)k6u4r)ww+ zfy^68i~bPq<$hYlEx>K{qD7L8m6q)^kzYg0U+M!+9f7{a(95C@T8F+rn8TZ6TNj9b zT0WE+wY%0E%E)z-z18Ew-M=-{DJa#+-{kbezU!SqzfK(CC>|}!beX{%Zj0D9L&%}M ze)fX9qvD5) zEwUJ*slK_8ybcv~(|WGyKY+*FnxO2&U4Oaz!z~w8Hn(i=hB^IXV|m6@$(dz$u-%T< zQS9r~FO^FNQ}QEl9qCKMz*O=X15U3tC*rzv+|e*_zx?CyRnSaob$O#n52?}X2j)+f z-NP$$h|;?U&V|ztKUx&peMojhq$4s5AD;ZVOwo%tGw~#-cbB!Cb>Qix( zUe3xzV!9}UQ*p{_*IDP*zX<#Ik94)P_rM>A9&(~pq7uEY-IY!wUQK$Edg*!}RPBGz z^R<*q<~Ny-%j3=Ldcl?Hie4mjM<-#=0P`e6FZ6hV?XVp`CyhViKIXdLSq9DfWbJ*6 z83}n^)AK_&!pio;W3`yn>J6PpC8~xo4>d7noaW@kqcPY}Ew}>JCjOR?if8wObWLR= z8PC+*`9-KwMW3(&d8!T4CtHfVK&a9ai^xyqV{Kzc6d&l@~RrlXTWMu9Q@Zq*-usezA zYjVZM<+(%?9Xa~NeacK&WZk|u(cdyow099?C45?h zh!P4{+8mtdQs0WRIl`TBN2wR%*5eNT@J)oX3T0DYa2i<6aXE z%`R-)vZ*`J(5wq!3%sZA>6L#HtOM1sq)xQ3m1h>ccOQ+TGcs|){<*R(B0i^4i4T{N zYOfkxGhCUlRGXE(u%0Sg5FB|!UY0_kDKa}J!4rkU3$gZ;j4F##mKSzdO10@%7eh}2 z7YNGg>R8S57{wX|uFGm%oO%1>nJJSGY3OK%E)rSGkNs;n@blddM5+*Lyrlw0kCI@x??Xxl)p5hA8#wB?kSS(P+%&expC;oT>1$ zfmNA~7OG$m{4JSrQr=J&JNv3Tp)KRNYa@vby~{TxTK@6{|{!Wo*er)3x-`~tQ?ghw1pR^{c?BOi^6e#{29dGAH z`58OgoTC6w@zRXSOzC+u$mwB3hhPIM!^1UN_zeTSZw@>TR z2dwyz>Vh$J`Q(~u$-Pubd%%O{rj=)?gRFv0X3AFH5ky`8^aZ%6otwoQmJzrlOTj(|XTXBcfZd@D>gn`#P zNP|%L47|FmDgAxiFpyNXy%5$~t0Vdv9N&p7?b?>QhXg%k@W=jS-@*&Cw4%0#yAnsZ z>NEt7;6*6c+RhcEVSiF4HmJ7I+mVRh{mz1W>$*t%U|?Y=?7ATOv)W1bjF`&}K2>Kg zf(VI+lDQiaU+5i8e1pg75NmRY<<1|M5yT|&va!1KG$YQvsw%Oq@-tKC)*Lr3c7>2-=Jq?_3qVdp z$dt@j?VQ`CM)rEY_2op^^N~Cyv zl=G7%)#ku+DI7IXD%9^COCqFLikh=!2WMBkGN4hjJtdg8@q`10wYY_y;isa-rFr#n zgs$>l={$_5If9!yf*MtMcrrAFI_kmHcoR09xW`}$Zn=i1wL3~k{UjA)h*cZM1Zu+A z%r+fyz0Z`giE=1z7hHn8w$bF|Y-qO*mxngHv#Y?$5Lc6HQoV_7#&g}XZ9e*4pTXz{ z)24(CiGh_jeNa1viPxNLUDLE@+eAG{i$S^Ixk^-Sh&o=Bn%IF(L#Ah0?2CK$`_0(E zzy8~L$<${qjSa(siUD7+-WQjdYg-``#gI5n)0tZlm>ez-5n($o+YJB9YYyMngvlZX z724gpWFzZV+fkiF-!>m)iHE-YaLQIovAFl}%2Ax`g%pG}pr`XRk3$;rR=q!j5wymt zupgo{TEu*HfFSzfkJ*ghpX4%PU=@~I0c-Q_I&RBpcwDu496za}%1WME)335IS|NFZ zRZWD5=)NsI^2XfLG!UO6_=dLJyv>8U_D7+olmxha*Ek_tJxNl+rZ*1kYCq3ve8P&` z%jkZ1cKhMtJ~_XfnD}ibjTu_^Tx#H+aq5JET+WM$##=+gju>tFnci_2|`l~%BbV@z}Zu&6&|>fK*H zx%tu|W=W;(N1t8^O^=z3p7o#4J-Rcd`Z;>Oew1#wBF!ge0^FN4$&eC$_k!b^x~t+I zb|(vM!0nbY^n5Fvxf$~9v)tj)ZHVcohm$Q?bu`Eaht!&I8f!=~Hb-dt`O<8yWx9XyW2dH%D2V25@_#kvcc#jR|6mf!j? zpvo-SVWU3umrAUc;h|RX`+&)zX=-gGl>G;d6LwL5`Ik#*!uB7=9Tw@wwu(FheQu@5LV>u8hx{6kvW6vVBXn13CPY84Q1F~~@s zi&?z+B*6VE>Xo2F+XIg_%9o*G36wv*yEWYEAdaKu1#VT49wSS=#-m<2>eKYh@2Jzg zwC~s^9+UF0s5Jet|MMb%ws587gV@&i9Sf2-&c}njt75x^Y#a&n82w8K;y+{Z{H-B!aQtxe1fO?<@%NoSR}VfV z;%R&rWtrsE$yj(@D&-wpM00YW4#k0K%8{Dy4#Ljm)pddQ>9{8v<(Fo_Ee;d_qpXuk zx&TJP`BlUwb2_`fP}oP3&y2lm;>5AB`aylYJh?Ehfs~^UulPJy^MAT8al7~8*Y2SH z05AW2ImJ%(XwsNo)3Y(!A)FA4usO>52diR}@x*K$EN)^)>09`s_WnD!xnL|FP5))d zlw44_PeI;3!p^9!tV|78`2>}$Y|U(aYsL~~op}|@09y;~*asHRtt<4?w;|X6f2V3# zlSxBzGVSrtuuB&Bqsi8gxG7q9gd2iIP5Gt~ly)-ZS`6Ct2>Xn=j1jR#U5;v#P(>h) zK%Z8=c+>5ahdNzynt1l1NYqmBUIB85vg?q@mG+Obt3r@+fy_ST+x?V@9CYWn^NbzW1)V34t?4a#<-Urxa96y2B^Ec*z3B#=kLN`UD~g zTKmTBg%GiH*Bycn-(Rh*!CJ?ppX=}BL351{UZ4IdTwqK8`pUc+y&Ii_I_`;0)NGKyMAIAT~usd)Z9xeU5T${I_f)9+fR1IndB-OLZese;aMG;IUw{ z?#hmP@RX3=Qkz`)IE3~N$t$entW?V2KTuiSD*P9NXy7`UuXYlK_3Y0CBmTkA&Avr| z{E0uB6Ifsph=UBjq^f4H+FXD@%Et7-Uxp}#S9wUe59d@5Z@OosM4wuUH`1b+$7^;9 zAO+h78HNdTL1X$*O^r~V^KmJ(keFza%QnkS$JLDXFqqE(MRZqS;B!?3U|b$!zRNpZ;}s@^ zFtfy8d2)!@b=0Sw;nnl92r5k=F*#tWX=9b6fvD3gju;AsYRT#0iW459O4Ip8>#IImQwaaC(0n8$H7lmnm>lTTB(#^CY@)@^G8)OTcbZmjr5#Fd zrFhYz0#;e)ajfg6&uN2x=NnfR`m>=9Rk+vp~F|1mfwcmNSJT+x8|{(${?_ zbMj@Mq6=Ua*==1TFyW`c-&_~#J5OMqg?pt6-7lr72dKQ}c-#7uYaE?LM`Qf0Hb)BhIyeTaIA!CSvTUhU6#RzycUFh}jj{W~8* zIIJo@b5{lUEl9^KggLBgUCAB1N!=< zT@>!8rsF87M32<@T=(QV0(KWFBl?;Z?taW}2$ql?xRC_Sy<=-H+iSk4)$(gGEZ|o| z8MohH7Ki=y=acYsB=$apFwqx*oz$ls(YB-Y|K;cZ`+qnF!}@@h=4er(yoCB&u!X!S zhGH;FrfXKXHlpQe9-R+1PYm9Qb$(*(KSq)RIUlY_t>|cdVnBfOuBv~uZaa}Kz9Q8= zvt?mpo~rcSzBSg4hpw0#C=u9BMWy>fXX@-$Wj=;aInI=g$wHUZ4RQ+WY`G>{r7$y~ zRZcy5CH#w?@3Q=6)89I_bL_S0eraMT0Sy?Jgl!kys?(I(Lk!>IdP*`TdY7Em;QG4y zg}kLY;UiF%RZkxN6qNX1cPKZ2`I|6{r^-UY+Sp6wn@w4ZZw=VT+!9USxE}~ISiP z$O^hu&Gs7OLgtA}p4m6|uPF=W>l$upqp&fvlG$spyQ0Y|62zZU&!4|biB?m-XZq_* zM<)vzP~_`aQW&9DZMHfyp3B_pFoVOIRw$*CcM%B%(5-^>Cqud8l;`Fp#XPj~mrRf< zBW~e6;X}ejtXoOiR?KppLgj!3FVnEge6<*#^ZtDEhk9q%7(LIi$pPQ4%R9C`>8Vbn zSxf0t)|cpoUJKOGOrF3MY;URo$)uSJqfVanp|=PQJM$uOTO}; z0p|Nu@xOfL;m2u8IEl0Nz4b+@LZ@Sa-voJ#tPaK0K!p%d9$SaMk<9y5e{`$+jZmc@WJ0ZIBFYW(4l*(*u zH@XTm+8Kl&s!jlX15n}Vt!i1-C7PlVsl((77CvNo|5WA@{EFJ(K{jWu)MduIX;i}g zmzPYF0-usvqn=&mWvyJ^Qs5qqR@Y5Sb-5`7qf5Wev|pFN)7gs5&h|8%DHC^crV=&w zT~5NMmryy#Z^c_9SO&)e7wm^`*&e^QH9;bH3fi{trgg$>7) z83yx-mwxz$={!#_I~_6n4uQOmJ%Goep!TxEl%^ zjMWcObai=8YHD8KgiscA-KSx1MfN9=InRfzur56L*-YP?Hd_F%om_c;LVaGpRJEcp zd3yN$^u!cDOxK-zBU~C+_yT-9&Hnq7kxkA#0I+lFgNhQ(3KqNv@VxeQYQyATabVv| zXw~@0fm!anM{2S3q;*{v-aVLH#>Lso>C9`87gl`rCMr-xOgq>jO`Ra~V%kl0n-yp) z7BRYUv!28D$x_DhD&UD9tng=^QmHrdbYTzg8XyI!==ZffFHAzWCRurrkt8(DSyd{%8 z<=St>D{*<1hdP-T3LKNxCZzDBw~!e>+-0hQG@w%aSf0Ea8GFp5xprER$h8hhpX@F?%r137-Jte zWvFI-XT3l_Wt(pgm)Y25V>BZ*>}fFDc&Dj};~phG_k;DO4mz<;Az@v~9wv}Uq?dWo zX;6{I`2JA6Xjd&s=3c5DY*1qw$FDg)tNU`XqJ1H2<=z*uAzUVXuL6XiR#5ZD639}g zifai^=(wX-)CxYWLSovcyOK=i!@9+uR;;IPi5A(*QSQGEx8&TlN*Py!C|4{R!&(dD z2BZzfR^#br&`ZJV@>)(sSFdgW;FfbS_GjSkM1??J2diSG4nmoLz38Vpxpj={(XcAq zjA)Fh*F;xJsu?#KA2(_ha1AL+K;RgCShQx1jpaCQI<=gKJQqb%b`%|r#?*JEr`UTr z$?KD9KhZnHwpHPd66#9oyIq(nYLi8_YQ!TBV0%n$p7{C9B21d-pU*Noq$}t3LR~&A zCfvkdIN)MWt$vE6wKfB*g#P5p(rw1o%Xy{AqZ48biIL)IWP*J1mg)}yY_WB3f6l~9 zwdCx1A-4Ja&vI;Xma;FFvg-l=JxljMU*QB;O&OUJx`u)^!)S1pG&?J+6yBg}^j`G* zZn6c#!X}iyaHp$?W{MUFsQi$oNeNO*X6e~zE#Wn(nipbP{Bcg`x^K2=*j(_1CHMOB zp-CymtIQ_{a0!U-c@kpUVG`I>FdNq4UjC+;eM(8Gow_@{N6Ifi&seyf!2>oIXs;0y zlu+vhU&FksM&j@ToU4oUD8bKoK_+2?4xn2ID zgr<9Mll5~9_WNB83KM_7WxuL>5Hm|t0qFs;U)XP0tCdk}D2#ze%t1Jv0^#!&@p=n! ze+;A4{~JpCo|p}@!RO{0>_~|j>*Z&!N1tY6?VtbBcB-b!IIf|c1fu-H4Mb_mp8Sm? z6H<8y0fEgIK>Txbm>+Od|3;Tb`Y}QY&%r=IJb@0A3bPMvX<;_;3^?9L+xlyqFn)s1 z|MM`~v1>+oGhlcJ6Mk%OcHhi%HMnG)DsxHf_G3s&pb!2c_xRIlRfe5)>*Tj`j34^W z(NH&EdbwN1emU-?%&u5Ca-++6RLo6pWTu&N3zqT3EXXt1um6dt7dW#jyXk7rxWKTB zy!P`JDQ>=eWgL4S{BLU9b5YOyxArJKTUb? zmi)Ba>H)mTd*?JCkpbfEPsXB3&+6;M`Lj>-pq`H`uM|T<4xDZ~7K9MPjZ#MYp~6hs z#edqA4N-@_{?wFSk52;Ejd{+?1;;$z6RauH?<98>$ZS@gB4f-SDw2hHd!dIWzv#uF ziI4MO5hcM@lkYI%_=-AR8!_qU_YM!L3rt96a^AGkrT9K*HVPOYUH4J5^o1eUrq5HT z+M6)rH5soRuzM7>?PIAhFQ5oKkNRz0Do?$)Ty(s2F~ec!d)5er#oba++VwG$}vYC^=haa*T}m_&)qbS6k#tx_}xd;wT-p?OF2y^;ROnW^RZrBwUkGsYeAT#t31)}UZYs&-{u0#QBCxtb}dp!bd%ioS(E z_twqP3i<*Aw-Q0C=5+vJM)P1@+9ax$AhTOxkT)NWNNPP+`Y6CL=$EjTEc6?zRR8`u z$TP9mRi6c85l2g`lwx6+z1hhi&^6JrUq9KBKzPw}yR$5=Qzp(Qp}Uh7*`%xurCveW zFKyc8oMVKAcJ-n~PHKb-dm3U?Wunv%$?fCVh3pEswg>CaBFMfvvf^EPYq z6pW2nJPibezq!XE_KX3-`DB{|%;GJaSRMj>k8t%5zt61 z*tJC2&)=MvZu}CP8}qY-+I|0=DLiCF-kw2&@;q6E{oq8t{&ZH4#1ENkQfT0src<-fjXkqp5B>xPR+xXQ(?Y{1&e~lUF_e+DTrsHCO!wHTeKUu zQI}h5f@33jb`8^aPaoCJbk@V_O-Nji%B=l_aSFyXR@+zo&lbyZA`U;x9monRIlW<|#j`0XBJg7jE^ImLaPpuq?H=-xZALzxYHi;U4FFE%BAi zl1A;Rr|BKC1~i)3TILJ4%Z{UZEP5u|5O+zudmSoMv3R9@*bFx;ebPY9ihS1SwUus< zV69g_$Y$z+S#iVDx^xy*484RmvPneUG{P-sub>$T-~Fb(f4&J_)NrFnBNB&mQzA_B zovJ<8tKIp!L%$FOSUQOD94%EKk1S`v?wiRtLgb!}qLEr?Fni!g3 z=MZU@i8fYQij>f5xIuuV4c~{|Acz}%Q?K}rEsxG9IidTKky4W?E^3G5CBL{6yzcL# zbc~LijQn12LaMUQF^?$C>-wCWbFw9af+NNy(CrAo%*>t8M{P~Dv3CcJN+jO5zc|?0 z{N0{j`F)-KjYs|HY_cnJZS*$g?k+fpKdK68cjrV!Ik7G^2+ zPwf(jJ|Au!qCAkTg^4{3d;49cY<){D<&~EZu+(?zt79b zkHmgyZI#m#8+>avzsk8$Fh90ezjHQkeEL9M^0O+jZM6I34*=5uG`ttZ#ecbH%LhRD zzQ~a5djAJm$l%-F4y}{3H%*;)k=FeN&1*J2kre$$MQ{s;}KU zCCVPbV=wo((Z`gT`#AG$;!*Lk^Y4b((}Ru0Jl?KVDO>ov+#HB9MhROQQ~a6g(?$9wyxz{F-9x?6NZ z%WvY5k8D0Yntu0O$rjg>LEl0Oz2TnrM3a>*PAO%xyA@Wb0O|rL97RVjGVgY}vY6w; z8lnl7!c)Gnfk%>(4MWN;Gc=Fx7R`npv4y&5h%p2y>ycuXZq7GyHQDt))lC};4rA}2CfihC~OJ+G2%Rt7ua@GXN~gBh1MTCC;e=27fY{|48+@zjC5xRZp00=m`#nn zEUi{Gv}25INyDF%~46{IJ8E>=G8hmRGB(XkcAIhAeH6vbY7@!V*c-$3cj3%{1!Bj&Ja$%HS>Qm{~I zseAR0lQA~qy9t#5J`F^sKd~*ni9mR(^2GPSXVU@u_p5YeZ$+T`*#fh;{h!59*8=&s z!cN>TeOEBwar<`dZ;95ip@*4rLores#aM--O<7w1LYw^^AK=FLuE{mivHiLqu=Sxgsw0x(tb}e2sO&PARk~1NF<;k`=s9Wg27$Y7`JG^$ik9h`p1ik14s5; zf&Gk2jSgxaBnN93XR+%FK;5Ya%?iUIzW8xlN$1RuQrp4%^2t8SU4AUn7ush!0=r=2 z6Lx5kEnpj? z6~NsRo9gwVDwVgb<`e2E%K9n^+ud#OQDVoU6u%Z)AsFMxr7rRv|BIE}c>8n29mNkH zOuc)4HyvU5%I;CW>`uJD6tOeFXhj4){gO_;p|)M(^;08+P~A5AD)B;jNB<0ICtk4+^j2x+d?f(3&^n&BxoQ%zHD@*9N>|6oo;TT*Myz?8 zszD~#q!#1axt4v?Db%S=eoAkG^ifq{_$LkQJw=?r88H;E!M*ClQFj+Yy7bNo5}Ryu z>Xo5u6NI-aADv*0>#zo;dXX=sw;I#hkJoA2SO z(JaVhNKR|tJR0hp`KecVW^Jp^jSL|nSMVEB58n6b0uS;r-tZ~2|q z!MZ>TY@_!`pz>=8=%||81X3t%bE4Ke7LO?+ZCYK@SiBV}$J`oSN?O4Lq1Mc``ctR@ zK%a%UV5h{})buKrqSif@A>9@94`6m6JOiN7u5^C#I|u4R(hWZ2gjCa7i^TH z({)giSXULzJkh8`IhF!zw$L+lv;e2BPt`K?qCDbO4McB3PIof$-THvEl(w8FI3H#3WVNI$JCMwlS9 zh$<{u7%&YP(^0!j5lV;TglY}YVL=9F@$hZh+%k^~!1)H)m&M#CY;oz#Vnb?^KTiDJ z_FT8uS?kK?4r-+Y`%Y2fb* z7!B2k3Vlr14MR#nayg(`C0&r>VtpkO-d7}@j$@DP9`RP_;uD2ikyl$qXDja6bhn>* zz|5`2OIlDSJRFY^*CLl#M~d;v75XW%3aLs8&V~ZPkkL)(ehj`D+N;zW4zY&CA7Ou% zwk#Wi_5`tSn~l2IH2q!9i()IWAMHmm4ud;Lrw&Q2yHgy0z%IJX8xzsO&(Sk@;X zT3XUjbTRd;4qcDYoarW3j$R?KR*d^p^j*;WPh&P-ct}@n#k4IqQBzo_$)ffKOCrqk zb!RErwy*b|kZ3KIU%0stpd1Yrt5Fq}B1o~+wk|@KG&Z8Aurds>j6N#@u+;fO^uhUR z*z{UN&kJnxrWfsTrC;Kc#}gu}D+@O~6_$W=YmNrJ{z+H06J`jTezz(wbo!`bY`^+gBTpX*eTi&PU^Z&I5(O-sELf{x zm~iHbD1DD&!0q^~@)V1}s^#0d8(KFEn{4DJ#0s0Fs^Eytq-LZjj61jtBodcpE>+{P zE3db@AC)i^UTr0N?-5)%{eeN#QCHAT1z zmhcPlittHBs!=rxlFY|*uWCl_`(+tQ&{hhqGTGFU*6X!WqWkU{rMP-C?P>71!kSQLsc1eI2TVXfYOm%#`Ht`f@nz!wlKR9Fxc$7`S?C4CRG zzP{L0T`SclR&{pD{{DTUZvN3-H%X|@l;!i1x|wp_s@1DC1^F;r#!r*TG*wndd9PT7 zrvT<_^OR|^JYIr4Jmi4NZuH+0P(;;miNdq{L-`qSB84NK#cZ7qNln=1=Tz5FY4AD= zCz3hd3BUVv2HC*!XBtbbV#Z(#*X|@sbP6A+N-=dW((Asv* z+~dcUxfDsy&o}ByIw{aGTfrpcjOb6XJ(-sTi-qF3vn^|q92A+08jCO=?>vFGQ7uil4d?|J{?Id-y!4eb93VzXo&Oj0-RU#mmIbN^+fy_O` zVofP(wuYRhIE?o%mB|-#U){>t>SPJbyD0|HKUYVHM=d952ilT!89ki;68Z)Pd9>mMw*<`Vf}DP-Xh_2!(_rT0C@ zDFkwe<8yB^P_QZPC26gWM*CiV?K#4OUDdYt(p|3!hchj|jq!Q~azmAWp|PjOQ8Np5 zjpo*0ViEl2nUcn}bu1$9KnWp%*g8o=k_qxMZt4;$`h_z=wIR@dB#JyV^@hC};5?58 zWA6EI-Ug}m(EjWnS}gGq)iSer^L}TPNyB)d#8HLkNf;Agu-kaEnk9Z0zMb{u`@rl^ zbbkMwS{xPAmU=PiotuV1k>H1@WXY4$Uq*SgV;rnZ1wUB2jTvl%eiqIU5HF1~1qlNI zcmORODJuTUBr+N70bCSfAIy0Giha%cG$|vo?aSJ=+OhRJ?5~8&d#wOjsG9Q#SQZ5! zHH&^9{5})P`Y#Xz@ZNMAp4x4yk$=C*1t7`inE!cNNgtI@0gG#@KLiaZ;&u@Rz}vqm zCxm_A-~2|;0fLf`#pXJ@M8w$(u?orl*!?S#&z)IAuZaiUFyTcp`_;|RheQl_2b7bDB97;_DIm`(GDryw@>a%Kb<5p%1U zSq`;F?k9P-rcrPls~FjbzX0=4e~K`1f^LD+DGLphbTo{zsn=!gphycQFco4(;zf!h zMqm^5%Zuo$Y%=A`JuxEAg^W;KFz4oY9-#qcsF8dRok-6uv24V#4A8s+k zZv2;}D9Y`8vpa$*QO5G3)AfvR!j61O(O^@bzF3$%xl?rHc+8d7F^!Ol^{SD<|3O0u;YT3C75g6dV1o9g4LQ6oNGim`i?;pMdmub>L-=4XU?EQ-&b!~yN zzdr9%kE*ZijWev}zpxs)ar827?LO)z-f5;JO?-(m_htYPP(jLq>K-aK*i*f2|l{Sbi5?XG9Els+gNb{VSMOXjgmE+fpBV zafagqwp!3-+3)Ax>064_%qw|e6rcya5N{yd;I1dedWT?YtFTZCEgD;>PM?Y^a^aga-?miJ7V!`k7D-yDKD4yC zdby6H ziUB|t9%!In5zBFq>lZq;RL;RMXB`i-2~b~~t?Rzn>K!u|kYwb5 zVhZL`lo+$sqgh-jPimNYQjIV`bw;Y5~@ZMn({R?W>u~pki+#0@aO87TE5aV)#sJ zeGic8MRZ#|OXf~}sUB|YNTl({rXm{EiJ?D&HMpr!n(P&dyDZYK^9+jn2 zNqJ7c`9#v&Nq~eo&b0PCz2^DM!H~s$OoT)Ta0cBlmJgL$CFzVE8^&a^szsbJsA_9h zV)(*JoLz0?lQ;Ii4Wy=zWh>@2XIkvWGJUOzLx3$RHW5PtR@2>)s}vub0P-FofT=3-#y>VcLX1n#v_zgYq9nwLLh_^sqjG)uL#wi7CPA z^!A@I0=^Tm_bjezamoR%S9y#KY4p@IzH~^c-To`0{dd5&_UEctBIc3bItyo zt3AK#a;0~ZrB{k@#P&>-LCV4rrhRHjuns$L#^UtlT~`Jy?is>1#;gRSdrU&xpimU{ z$?(=Se!RF#>--MZ$_5A0cfvBd!Q^$OYU|kKJ$BKB!WTY~A`#$ax0S>g&+3M8Pw26{ z`ao8a6i=uXA-KxdHd)xjm9%!RY>!vrYO4e6p4mue;m1v0t-9sb==cJWYW&I*z8lfAbq(GrK8 z*UkaiTWieXBhVN})+a4pDkfR)728M4^lLoP#nNhTNhSif5a_QQ7miN(lun|vvvxHN zE`LF1Ej&ebodXJ@xB=Ytxc~aBauX&V9-S;w_ZW}S#Zm&AIYvTSK&P%{u|$i>=~%_y z(X*JtvAnQYS5`%*M|BoygLCJ!@z+f6Hit2fXYI)#M8VlAeT(TTcI(DS>#}%feY9Ic zC9Q>^h+q3&CL9y6ue2cvL`OqBzGUvUp`t_H03G1Yzzv$VSKT2&dI{Ki>;Yy@wxt78 zi7i-FKnkMS{M5&oKH0*rrgYF<(TyFNIBR1fCjUlubhwGJTv&BYg6^5UV||0G05{XT z1qw|j+WyqJS1z*kqG#>SQ*~p@t?w-)f@$l@bFo^t1goaeT+?cwt0G0~lOivLERsEu zz+*ky*@V?Bv)SAlC56v(=`)~z0c^IHMr?HS2V^Ka%LAfAAbSWXyYbc=yLMJo<=}J?O zqCh~36eGRe&AH>e-k1CKk3TO-#$F?1uQ}#gd(E%RynP`sepX}s09QRXjz*?0tL;QM z0`8{?-_Zz!5ulrwwhQA%TeiDNuIml?eES+=Ks0y&1_PVawT^SN{>(77viZ{yS)!TG zG26oeq(i$=a$*}@eh_|tG1Hg2+!30f+L=V90Xf|2mz{dmv3B+(um&y=4dQ5}AAk{v^_yyzm2I%Lji!Q@@YKe-an%!Qu&n&n4J^J3WHQv64J)$UYjjY_J3 zFO-(ms)d@55jY~o2i@+ee?{xe({K|zE&y$|XM2fOxcmcQB{6A;&NjI3w#t^j^8?u> z6ir*uEHHcY%%Eq$ZQIFGJu#s{J>BJ98@#m|nc+y`6`;+wt{o>E7zQ0_%Bc?bVbTjh z^=g%F;W4w+kVyQ<5J%_xXB+}h@;G*KZ+3jUn{fwCON8nJs4s@Zq7hp(dU~y;{>A@# zx|tS!sL7#6f5D^ALEZ@Hx3d-%ib%?QDm+Q02wtyoH`i!qE*|@^Nzd7%Mo%p~dU8@e zt$vD&-0BkcX2|!MuL=g#V&^O-0i@tnKG4iX!zN#SgR|GHZm0r zxYr=J%B#xkMvy$EPXzUJF$_!bKfv?@hf;^G5Vf{%$8pn|W%8-I>zMd}GKdMBZd=aaSWe_j67x zc>)p?6*na~{hM1cpU3?-U#^;CdJrBq!RGgfdxnfIQl;^DIrW)to9G);P`}(R@4=|7 z5PK9>nQ1+L2=Jz8_?$DLjJt9#OKC*HzN#pamPk(x8bBmm1W$8++yD&y-w4X3G<`QN~O&dmJ9|Y#}PbGQK-Dw6bo*;z<&2!B8#yz1UZrk0d8R zvTxsOOyiv$Qxbf(J#BIiMIksxG?)R?ZebqDBnv%%LY(B< z>XU^RRAyeQ9hO|(SvQlt)GW-2)1|!2+UM`*f#r|_LJ8h!S{N0V$&OJ&VPse9ur@lO z@Ng9S*XiAI9nI2%Y_;AADg82kP{C1~ts1z6DUw#!z7BpMjPmOi1*pwl!6#Y9v(En0 zCTgOC)W+DM#dV1MZ{-MXIx`g`6N6n`D3gnaJ_+*0yk2VI>(o5RtD%UB7e@ehe{@45 zq48wB4dcr1F)1~=x}zN@0QSqS#&K8SqQsw)Pq7`=DeqVQDa_;jaR!l8?)5rc^P4?C z``;h5GO=YEQD`r<_|^iE=(hkqQXsNuyCwKUA6%XXQKreXhUiLtdbc8hG30D~=2(0X zgr>`vRxCN;bsW?3WlK4xsMW~yxrO+&$J2Q~-%WTiV$BwwNNUCGqoM6!(XI}Ug^XSU z?f&H3g=RdBw&=wdn%{C;cMMK+9Oq*yUDGv6PVc>soVKKt&(fn_1P{iVi_Ts_sUSCX z%YiPO_@5MNo&tm>Be4NvaDzL#`@Z(r;8~a7Hy`*Y*X2=F1MW4oC;R)OUI>i%e2U z5RRk|su?{NzejT!uhs#WCDha`Q|y_8@{llTvSWUqL3d7>E+po)oIg;|`)#LuQ+gZq zNjpsY?$RHwVRjPhtIxA*?0}*zJ;NTJA*jC7!F9x%GS8*|OC=>hAOk9kF$3P!t3RZL z^K!MQsqZWeM*znyIgf@|B%+VXOXGMQzgT=mcT(*GAcdp%@PRefIY;Qq+ z{d(#Oqbxjba;`!Qjhm*nWZY+eBfF|)Q%v76(e#I_`j)(n4Zv{lw-Xeab+c&vsdOx7 zwnN&=d5qKay?D|xSxTBE5WE7gVL%+#2C$8uY~sWWUG!Z*H4In;ko5Lr^r5At8E%C{ zxcmQ95I}bYnM~927uo+bCCM}){`Zs*h?%ahy(T{gnx1rj{fjt|l~1S!g>VC;Z`U;g z(94N$ss>d+2L|d8z}{2$!jHe%Amq9rxUQ6&T)uewhiTg~2IH8nu$C{`MjwqeVmAA$ zmK?M+wQsODKG;x)eu3k=H-0o0tp6q4q0kBKW*({^3A81&14Qdkv_1T6t}(b7uxOlZ zfzV;+>-&3(S#UTUmKFbPWW?GjvES3smN zJVx7T9!l~>G%rIsSmZIbBRid7xXG5&bb2hh`K1Q-%To+*fpq>g|0uYcm9DG3S_V>J zb(T9mI-A5p<&ETS3?n%fa%xq01enk8N@Aafm7GqxThG%B`9oL6k}{2E91vt=g6AQ| zqB8=LWm8kmf!f368YhXL5e2(NJ{@{Xci zX7%)Tq=FjpYF5PBy>&C<%~YQZ6%kQC`LgVy+IYZmbWwi7<70dxhic0DwdS7gb}3uR zy6(Qve-Nwr?TS>Pm8AVcP};2P1q!TbNu=$?k%rxHZ=>wRf=Ku7M`p5zjvdjjZMihx zHJ14}?6v!&XW?{QbPOiMJzHKEy`ZNxy8Hb+kM+e>hbwRObLHg0v z^zMRt#cpKYa>PQkLv~34C>s0q)Qw54Wl12PNMUfK^QE|}0>GO@olH^G?zX~PH4s_L zH19qOc?YE%hpxBUZZ%q$)KOIgMd?fRk_$Fn9j9g{Qskd^d&5jz-8L4rh~=i+c}u>2 z5ytyo=b!?X| z#M|6Gvn@ICPgZ>2T|3E>JsqMvd&aG$3IG;B0FnVu(miHqz@T@2hMR<5nH%8C6dth< zZkBSe*w7fHqy4&hu2K&%C)i%T&WMfYd))<0E}TWVLlF6HSn zrDfQIEkcH^m*BZnG1^jAhu`BHn{_*d>d%K?W#Yy*I%YE}{r$1ChsDDORS zkhK-kWimRTLOLfKU;L#=Q!v=k)?jd!s$fpw9CBpj58Ye@V{+b)H{CB>F;Hl;y|z{3 z+49Hiz%`%V>9}l;2-BmxVRSTw>Y5DS%Mg#hpKj=M9Q2+YjR| zx`CiXc8$^?yC#m~dAv?`{hWl|$qn16dTTd&Ne3U{6>oKHr@akY%ay%|TaLh%xO*af zjvaeq-uAb+$kMf;O1r6gf57yNLhVQFD0dD07Uz?)Rcyw|YQB~ZPwB6T?kaT#l-_sT zH<$-SVSNilY6g9fF^LZuG4kvR3Wc;syXK(IGY$b)K2r^XK2BD`s*!epGeKX*76jDP zfO$c+^u%hL?zwLAu51rW)g4LX&l%T?*Q_A13|Q}sKG5GHW_5r_(!|kJu|CfAt1#bSQ2l_DNIZlXk-m{q*wZ( zsE2#T?-w)BcWw=@4Do??iaJlmEg101`5<*c`nchy_0OxPjFn z+xdldeMl)nKDb_nqe>5%Gb89Z@&mX~D=2Kq2e~nG(OmoC5@$LW9?f)SYnUpAb_9qK zO7MAL3H$+mcG=)y)xku3%I&%A7icR&z&^zH%p18zRQfIIJgS5+!mg1gPaHB+>B zqhS`u;39NwW&56H1*u4f>zNV%5{)$`G9zk9&3nUtF)ulRe$qJt=;&#-PQrr{#?jXB zxL@QC)1eDrU6^m-mUx2v`d;)0A_LU$%%x=!pY%-$729(lCGD4$l|=YTJk+tpd`ZXi z=odGAAaB9ZuLb0#gtm=o&B91z1jQY8Ew(?Ao5LRljJaxvrup~J&N-6TzFQs3+pPuQ z2zKjkP)~A@ETA@wzyBnoFZ!Bhqx{@dtfG@kp*Y>+$U!(~@pigXWE#N;30$5!dfiTn2mLlrepwyQ> z1n$SIdbmS;pywIIV~51RfMTjbn-qZ9V-$FLXCrx&JRxFB94kMKL?m(3(Jv-7t+dyt ztwDn4G}uAsrJ7B!riA_u!ae*?vr}Lv6d72$(XNlBj#5YuU$f2mNcV85q>1j~%Tg2K ziQxoAY(q{EDPKWjVR9UwQyqUsp{%x&Sh7Aj3K3UL)Yg)9Vx&{<;P74_<2yCat%$5-8>tq|qpvsc{2P{chclSGEj_GXmjZVXAAJ1)`;O6G}4=c8p2Z9ZfehnyG zar*SzoI6W5RzK5RLBrZB`GiSzeA1KVJbfq*lxw@3Up4a^{AoxCTBJ?teZ8R9k&bDi zT5ykB3jN-19GXkBRme0Lp03I|&Te@}Q-b@$r%>Zi+eQc|%%NCZ1T9i$FfDoi&Pb~| zqqn7jM{2#A?gi8&z-oJI8dOuf7N*#k{?$>&S2tK`5XP0ct$A*%@z%g)90ZZcw7BD% z+ODH!h1)a+QsGVwkzHmG+Nndc%xH$mtw(=fRpL&c^94qz$Vwqy^SKrAuN+satCNbn zDFz|5iUH?_l{*0Ae2z36t<%n0_K$*wy1et{radYi8*EPR53;Bh z@5ykj`?*k@cS(Ss_A|g%9W-OidpZfi(Ec;|x9Kw>=L6;ITXVwlAoLmh(7dAI4q&E6 zo!(n5xD;`Fl|qT-VX6NLH0-T02Wj$H>8b1O5bM!xSI?iRAO}vt(E*{$%Ffd8!pUWg z-Z(9F6TSFWbaIVL2=~m6s0U3y({aE|G;s;^Ex0jag8j6Ly2`E*!5MNdy2_@_#$%z_tg zh}$eZ(gFx$T=T#){p1*-!N4=GBIMTlm9`=5*^?C^JR{Ia?Gr3~Fg57yDw<{Cc+-~M z(XKRTUQI@F7Pfjtv_}yeg7qw*MVxx?%$$b@gkpU;CC&!D_WKu>>!NHVw2aVvqKBH2 z=^mjHK-bg!*~g0}dKZ;A^`>Vtb39kCrt%IXtyIk}_UjP6qsZ=*4s%mK4+HR`101mO zpv057GF5orErC=WWo2?@`vPs%PLk+L&c}6xDJzcCHFiRNFI4s1N2RHVTd}bx_1LhxpMl(%6a<|C=vU~^*3dPeOL zjTw`V{ykvj{()5;=;cf?3RGRjm|sS^xW13AsghX^ICsUhz!wM~Ce|u!-hx!c=8FRU zH?3XR>ZM=dTYXc{Hor*1`;^PVqzb0q!&ROQQ|M&9t|YHoR?CUr{^YOR@A9B&@tB@b zbb~ElN`(vAkSLxy|3>_Klmw+kQgWO`qv?<^`*=gRQ}bZiR?lhBTSLg0t)c!YR-JY3 zm>CAmaSEm_nBli z`6ppW;@f>xAHbcH1^=4)5aDLNI@XL*HEWvNYmWn&|JhjT!;_G^bWG2pM?<#)kKy3% zuX+%8dqT*as#dEM;)24eZ^CH*qGL;A@{vpYh_YfwmP+Fkz6i?=!B7 z2Y+worqvCq!N6l-+`Uz4jq~3VT+^v5tmsYJ$N*f_$b)n+gXSp4%-=%WQu?i&W1kaeNv``hl5u#8@qeN;o!@*&|UxQiQB( z-Zf>_xA8vx^u!x^&t~BQ0q}$wP8<^n7%XqgQ_rT=N-UgtfjFEjG@>I?&=+P}!m-&I zm4~|#fOfXzXl(;&F4UeXaMatP;g+(lL zB7W0tQQ97tyxMwRarP`FE0VdXuF!~l;P34a&{1L=Rp;XtA@o|Z+$B@T&0wL~cUJ+@ z;v8PTtK_^*8?GVt-=CjD?_LdUv;SI$?XS;Y!~?+4BgH?9uljcf{MZ&1#uy-j08J_+ zHaagie#a%Mb$-Gd$t(Wzk@?bttyVD%U1k3o~7uY);9VyJsgE@)5%3C26FVw zISwF?4p^`K-B96PHRbBNZd-n*1j2NcW#LU`)(op(e!MV|;v;EH3<{ z9@s~Q{OsW;2jlRa6X~<(ZjYDxYeIMkG=S8@y^!R1`lHOZ?eM7OZ|>jIO-%ZW9e6UJZt8yuCRt-RU!n*i9C{c^3fMy;kY z)%~!0`8h5Q|5>rEg&fcbTxSrO4)J@6y^!1gdCAkOwv(4uPeo5gcnN@K2*SwxudTd= zd4k73QAmJYX{~Wz$IXDWHpi>$pCl7W54mIig)m5O%)lZ-Q{XbLVyqg1PDn;c<(s#oacSs>zwoLT;~Hf+&kH8uf5j#t+n^sYm@lEME4TQRTd^D zrc3&If0{Ef{Q_oU`f2mRe}EQ)Utqexub%?Vb+wpk$F6MwFTc9oGrq^fgh*pObvg&U zGyCb;1Tr!4h%kPB(l;00V`6&4tN-Uci!eugclg{jmweKQG9j`SXHRHfDaNKXc8$DH zda?GU?U{*Dn-F{@%HBgPrr!Fz2g3p2o1h5sqPE zek|m~{Of1vw%syP42j*??e6HTq!PPNzAjsaE?YWSE~5w;ot+U`e_Xf`!>)DVMoHOq z@Q*)Y*e4#bO8_m5x2-z~-2Z$YbNE|-661?NbHqhw?SH$e{|E8=KiysmMq6|I^SNHy zz3K}$gwst0yKZ-ph7^B#Ax{{&4iI)^5Z3=wdp#+>kmI+%&UaS$h? zjq_eL6Jx|JVMd$qbL*cN#3%HBaPj}`fKZMqY{BABOu>5c(f>W{Q;qwTeEptx&nPQw zu?`{gB3<9k$>hm7q{*uf0V4Va&0LN-O)nlx_^i!(Hwl4leY=*F7)sNl0)nDktZ-$o`rO1>_4-qoIbLp9 z_dYiu)C(yEB*W^UG}`#{7*-LCzvZFJe-7K9tJ$>2#b1;FB`{tekWiWM-&o0rjBY zfHP=IK(*I}ubo|FLGC`@xKwbiNyxrFOm~hj!ETb1WjtK^;muFK@%)(Eqzqz$RPN(xFbKvj2w-Ss z({C2nam^a^EW*?-$S-rIz_G{E+MM_f4m>(yEo2j>AKNBcvcO}zr=sqgbEWZk2#<_p z?l=2Fk(dkMGG`H+#$$ZccfV^4ER@hL8ddkE3SjojLSq!KWz`(=%kvG#Zsy+T+MQ!B zSaEzZ={}FWYm(P0)U_8cpSU2xC4mznh~bD$xfcBzaI*OOai#Sh?y6pbiKc`a`MZKT z?XlfWo^?$8Y;1<9x_Wi^-uqMkN{6zSp8rAQ7-fqi+D^g62Jk=5vQK^0t6{KxSA^E>!eez09g%-Me9f1F=`o-v!%fFvD; zt!1e8s+!g|CuYgYMI1q3?7auN1!&#O2R;r_x+hggsO8`;CjX4`Z10Nmbm;3#{ED%& zF6JMgG8NsVo=ozg1=Zxn^hIa+?4kjKE41-$6AIBh>y=#jvmdbGduyE^I+Cgn`YBIX zCtD7Bq$Q;so;_-czd%r`Xt!YgypYUx*~xIGXMBjc>S@3t-mn+ly&a6HJA<+Hd;W2g zU(x%rFKn^1&(QJMvp?xO0NY761gE24&>dDynZdNX=LI@ zwVslCoVBKTA4G6?S>*_YPTE{{%?E?cNL#{*u{Rl<URNBQL;0|p>k zW5}(0(fR+1Srn{0<}M8`49YT?#babcnnWzM@I8_9W9tvCgU;sN&aTlWRlx8pXZY1cyBqF%(Ojo;1~T$W0eKTjt8nww${L}Fw zK7|p|J?JYH^fkN*CTkKJd5YB}*dt4)7di%QcHVDHAAcSr&miCTI|rkaa;$HuwzeP7 z&CE;xmtRPdsi_^>CsjDFCOecYgbCZvfVDQT@*Ta`r+&m227X*uG7=|R8@UzOg{U{* zS=UGCo@mmAatls0z$_`&`EWz;`LJcMA39=D0Q0Rc^)iTh$lDvKd6>9|F^!VmIm?Ld zm6vsOJvcC08GJ*Y9LS1YGgTAG^PBMP8@8+x8ztUUTnY+2nXWUvJmm7FAP}lCx>3_{ z_H3_;%k**~t=Ebe4Et7Gco}^<#@0*bb$kUW(VCw}J>SEj^RB`u#J&JT#Fm63zvJ0P z=woOhr-{lsiL6qKbb_tS)Im5uxWJEzeT~>-vX?pt<;$jal5iXTvFMZ>$?+Ac->ZzJ z-MUt&u31C;7%zC4m1p@XeJx&dv}OMx1`47-KB2Up38585J=oN{6wshTa?Au}{KLZV9ea(@Y;1(HPh!L)5VeY{k8&yZprr~Fc02E-IobdeB=}+Df&%=63u6eO zhMcUm^L|I^?nC9Ge;BRTYcYDaSVj?;_o@4gN!A0!@$_G_?a3VCQgtrf!hAEO95B9= z2lGKSv!q{8=NU_dV_9~D`FIy?UI1e}mETRXknp<>eZ z@0}s#b8o75D2jC#Wax`lu?`T*@ZM^cYb%^MeEK_wc#l=Jb*67;K>zqq>={YMk&})@ zp62?UmZfb?#bxJ0m%qDV(P9o;kdYI6CaADWab3#lbJjL?lAoF4d6o&yGLd zCdB2#>r<6B+V;*)2OwDQ=9*Ps2$>C|J+Htzs(P3J`R?5ebHS~devdr^JVefEyN3Wd zu)1!|_pUN^A9eY1n&$qWD=RJ3Ex?7gB5_c%0*-8WEN4*cJw3oLXIrWvXG-0j8EB1f z?V_pApJrjH#*?AcPIXUQ82L%>9i*C5k?*2rOUl(})K<1AN#9%o$iTgvYq*cTx^2F4=1Aox2VZTm`#gM4V)B33Fo!XYt7Hn$3k|F8}i^^ zVl0NVX^X@Mk?Kfwz<}-ZxRKH_;5zzHYs@c~)#SQPr_Ww%x_RS#<~2UIDo36oOraXp zk>AIolySv;3>5#nWc!7q%GSSK=t~a}t13~%cs%S7iq1%m+vuh_ z5H8uZc#W0~K@F8cU|xji?7!8rO=o={;P)x5k0&Ad$wMQglc7Bn;k0#cP@Oaks-m5R z?V~q}Zz|Z9j`QkIqX~2hGlDZhQjW0sNLF_A_n+o_X!B7PTQZGWXiC(YCQ{-QN7cMa z-HH%5JZs(;~V(JTq#SRBeJ z^?^e&?yAqU;Mzw!dyaJ>#UTrVqmv3A%HD+Cy2!xP-LugVh$>>V(G@k4)fk*@ zZ39|R@Sc^p+a58h*)5NT8BeM$mL+9<)L{hwf7j!Hzl`bM`t;<9)%m8hUvvIgZmLu` zOQv*JDj@AdrjAv!+-oY1Vo%rH#2YNH5V}#b2WeRKbmo^j*QC2n8un)3w5+DJybb4wiQik`oepXT_)cyge znL0d6V#Uq+R?C=CofbZXO0)7pBD5X54AqXmw0L8R1~922p>YGP%N&9c?%v(O7qE_g zH#)#a+EcY zVTA!tb{|A*+*vv_UBu58TPVJ0u!qDu4XK9I#T%M7L@*!#+$8NW}E(p~)2~ zy$k*ooep6mp3aW<8x@6y(z)h^jj}jJuZx6mwC;gM6H?eb3IB*o;s`N> zTe;@bjX#d+7|^-N%_Xrn!1OC z%H+;`9Abh5xUZq>%nu#-QUoiM;KW6=KyBN>cD?taiH({0NW~`5w35mD?bUx$qHZd{ zho?N+{qz=&SKQFdTV`^cqGk_%s!Pv#2n!wT9}t(^AL6M&gR|_cwSIO|rN_Oj{dxi$RobdP-mvg3Z)}QW8hWog$n^^^L>8ta^uBhRus19G^r(&F# z&NI2*#wLx`689hjAo$S2p&5_GrWo#A%J!{XFdm1R5iy(A3|vtv&dSFVYTr zKwJ`d#T1?S&Fp5xBVw#kQ?rJ5F0{#fAB~vsw`<#+iHhhFg#LQ_Y|Or;s|Q|sqHs&E z`CxOStk0XI&Z809U-bAr^KFxV7lhJaEzYBFk5qfnpaSo|twJ0*{3r(k-f3XwlnAKi znWt&-QB1uOSEg0hM&ZG8o7h&3rN&iZ79q)U+l;mf%zJTtXWVF;|u8lOHIX)G$Dh@GUV2rETgzB>KtwRD$@zs7Pa zu);}vN+9v4p`J^*?dD!+B92rh40#v13Rb}%9#p*UJEz! zL8EYe6adF-)Gx=Mi(k%|fF|W^sFnN!L}$y+r3k#U=>CE3HQLC+kfv;q8aG<>T!oI{ za+lOn{o%OZ{Lz!%*hZ^(p|NfW8~2}IaK-00t1Xeft<6JhfZR#V-75&rSMOulb}pQ) zYicPS#VxFPj4be0oq9fHt4A=`JB)dhkFk|#t$`pBNjV*<1RH549G57OYM?fVi~*+*(L!+&m9KZ zO7uadQ>5D0VfpxkX&Y=_;mETE59*YHwzQfJzr*#_>9fO`o$wirO6-6Eb#0K$dawl( z$mkch8!EE%9Vw$Kq-oM0hfzDxS*_zCOS}EzXQ{R=XyMygrtRW|t|JtULuhNLyZU^K z`xGwq!^pu_5^oikiHdw756OwvBmt((m9*#&9X^bN-zqHach02HUk5a4Y}lYn`?f*6 zhu-Ed1F-2v<+U~^58D2k8O}4rE`xZ`t#_h!6JkGWas6fA7CAcOxBrD2Slb0NZVO!B z*gKTX(Bw3^aO1HXkdM&P3OX(la559M?ttTR1TdOnwO8M26{X#32DTd^ONwaUh1n3k2)h~5{!~j@pW_+*Ju~6}8itr4c;E5|&6svN zfAB_()WNp{9TKJyj@1)ct7$jZM~>YJS=nmgYFw4)d&!NvqwSAZlIkC?5AOB1ERZgd zQ@Q`z zJY}$Y1cATQ{}kQ4ZVnx?R`8m84bj6)7M=w-CKz6@I7L#SpwHU(_D43K^NQ~dpxD&K z3rl+)&;k<;tUN2POo_O=JCW+9YWo&%<*}4gmRO2)(M(lZPxk?6Mae(?T(i{zN7X{P zq3C&=T+^tK!YH||(p+Bo?|@+u6*$FR*qx8?1lnz0eSGUfQ&ri2ET|Y+7rC|=@P3>$ z4z67y?|*?MOq1aq!nnp`J9}!Byz2P&z3M?B)MKsSq2VJ;QZ6`-=(?O=OdXl^8pe`= zq@XJD(b49hSl{U)h$YK067?(Vo9atxK9#g(;TU%FpAj9$y8@V4YP?@0O$d7CZ{sZ| zE@BZU9WlPsX?aJyzUEWQ=6*P@V;*F~&ivi;B^cM|HxG9q-J-~_*p0K1NDcNn;r`!FfYi~GzbFg(xBxM9FSGTu+Nl-sqM~lK_jkdtm=Dc2OeJ--QIo~MS zRejMoQOLVQcCEoX_j#+(EA>Lirvs`c6MX_sWFggF*1O{qE>jQ9MTEid^0Rk-m5{U| z=Vh2|CD;oaN@VQ)Mn&|`ot}da!`X4+Be(#Z_@IarfkI+i=M8*7og6!Tq=9a2bvcYQ zr_h9wXC$sTB;1Q_r<}}xjK@xTwGXsT4~R?b9j*17s z%RYIpoLV1jhXL|vpGChlOghdy&aJtRz%LdsW3a~+(8mv`tGQ_MJ&k1wL8m&Vht#t1 zF&>Ee9k&NHyN@6T3Rgc&g%Ttarrlj9*B0--x8zfF{YiLR6lEeWTXBUKTr+Rsd+)-HwXFBa(`>b$6jpKaHYy&D-V14U z)y9VUnP0osTxSpF6oDEibuU- z{~Wzwz~e}bQ=jDR{zRW#UlK8*BrMKj9h5w-=%52B{cgy&q%w{wh@eby_0jvySL-s1 zYe!_2L#p*vjJco#@>P<5#?rHAc!mjqMF+m8=C@MwVo8zryf zma@Xjpp(tA0FPJIUF&$l=i{@yYINDb(G%glPR$d2jqOsGX&p^UmG#+jf~9v8VVazF z8wIJq3EI#2zRh_=c?PL5#Z9nX$F+W9h|p!Zbf~W=5_Fk&%;D--L3kugb!~<_+kG0Q zSqtQXm}+ENYmv7ktm@cgu~KYS_JNUO@{PL}L(#3$YBVGKbJH01yV86e*3hlf91D+_ zZTP8VOuXPCM?sXUZkPkO(KEulx?!u(-5d!2NH0cZVHn|(#THDgs@w$no02Q54o&V zEbJWI*Kky*Chvt5&Us7nsrKFf+yE<_QTVY~-jc7dFnuV0F!#M0>h#&kn<#425`=y< z(wBDmB)sQE3+fF4Ts>9xW|9VMci6rUopRSf@6)5?>sm~ufvwg$N7Z;j%=YlPkv>pe zr#$w#a%c>HR?X$ymKGU{Hw_8X$sx3=`Vr|)qt$aVVNNHrB-l-Rzxfy6@4EaoJ~53s zuc`ca;uuFS(`YqqP=B2Pc3vlb?aS@GL?m2(Sh}q8@s-Py-Zj%HjR_#?6&Fk-SV|i~ z*f5dd-JL>`c0ek4^Iem@elH#S?1ma8tR~F@t<~;2_$8|8&!3B)+iv!-Jkn3oNjVOq zN)E39(SyB@t z`?|6+vmYc1epQN`!xQ?F9S;udpL+Ei)uex5?7D1nv(|ACcG_RH2PZ%RF+$@r$cOPpJX~~Ph5ZmMPd9|3(hc5UwtWqZ2|<=LUmShd#f3v6gHu20 zMn%I`hfJcr)Z*n=O^O6^>h~_k2ZalO$HLE0qB?;i6uJG=(?ci!&2h2siw|8r1cdVw zGF@nKQcmMiq&SH>N2QN7$%K&=w@_F_G`p4#!&67s)-q=@PoB}%*ulP)qm$>P93$q& z$Qj?oxoRgjW*0tC6kh8JI)F^n@obok!eueuXS2X^g&gX=LR?9UDWsq7)t~O>TWuJ= z|I+3Imi|TjYcM$oiqiL(q9+;|9rk^MERgKTX`7z;fMtiq004tx?9en!%ol5aLe}&U zZ?I*z;tqK%N?EFo5MEObxr1t*cF&PU(h;Wc8(mw4=*+tNyhA5`qV{5i5w`S414&ZF zM_bSNuX>vmzG^!mV-JoFW!sg?Q+lXZ&i<-h*fifdFA(r}MaN3bKKSgHjD-u@BZ5(L z;}~@URj&u#oYL`NAPaenKYjEDPA3)y|5n(##7HxpB@nET`^$co(S|K{cJO_clqC-c zZSQIH0myYmW6J+*)vAZjb+jO>l|*%z&(U8s1rknhX*8LhMohmi;)rswG8%2wwZGyZ zjpQiNOn%M_pf;f7#bhSTR)nV8B7qS#waxQ%sZ%kdU)TFTda z(V^PMx?SiLOY<~$=?z+4T2R~nwjqFtE_0hiX6}!^p!nKv(VxIMdRy=|oz(^=N50kt zk-P2n;lwxg_J;_h_b#OI;RxTbDVvHUX#cDGSHy0lS;_-U?PdsWMy$6(SMXArM#l~0 zVTVX_-q*VwmETH@bBXIsT}2)hElE9)W{=57Hq;|>jkN81cUaepJ^ds8R{c?4jS6ya z5uw!sX&59D(}GW#@g-*JpzZ?+h@kf1NV;9akvnLcYJr+oH9EQxWlq%YT>O4xU?bbD z@KUms8v9s&llnYq#Pr)M-jT5vwroH2OP)YrLECeBFe0~>EUk@oIj-qZasS3 z@vgsNJrq0n5dUa3SiB^*P)!V3f>pvnqRc@S+93NpnTHKY4p~3|o zpB^_CCAZ^Kzrp5NtUYw(l^@|gj)hy?kh|Z&y-A#hiwes~ac5rE#HaC^HjRhodll${ zW*ZfT3Zpjqbty4DLeq(o70|}CTctgkqQb5@zO>Dmg0er&g`9JIL5WR6g2p7&z}I8y zQDw@TthWnIZ+&LVpkh-iGh4_739JD+o2o1x4nm# z^0Fs=SxC!`Dqir??!rqqVqV^L+jMRgy3b82Iv*1A$aVJux<@z$XI1`N%EIHc!tfB? zHvje1y~e7Ln9wtYn5=6&y>>8x-cqqA&=Xj)*0{?YzSBICkTGxn=5EqRTalV+_0`j! zx!c#fUGSx&*$-+y#cap-}+SM?5rr%l_f-eQ7G$Oq<}}Z`?wxF6%f4 zRfXrc_6i&IcunbRxe|>o2cc)CFJ!1l3EeYn9uMMD^G4PT^$!%}Qh>M>Ufw;bxYdaL zj?kdVJ@Lgg(46sdqYLipE$X5w3UwJrTjWI*ul$@c?7OYwE;&?cZb2Qv?d_FYV2vlB zDB-0jS`8*g!gbxK@UE()U4UuWsz1!{ExY+L0IrLP8RI9#P8o|^kDk7&ENis;Y~`8l zSl@e^F%Pot-0U65a!jw`uMp=-O3akDeoy%O26!6Pm;JyYcx2UY;f0N|8>%2nbGP+@ zO{FB5^G(>){oaxg@EresLmVYV*LA9Fq4nWORSm^5a$K+8iz>pCvXK~O7juM8-JBz) z>1HT$MB6C{bqrZ~>V7UER4EM8!+Y;Y}EzSa4ktmt2dZ)hc$@l)=Guv>0Kcv$XQ@{=p z15*=vnb+~UpsmQT$x^?q)7(CSn|&5>$R@B?id6GSlSS#1g-!LAA2M3T$bde|a|06(8$^U>k`YUj^K&ntV>M8PQq#CKb*);28~Eh3Vg__5n- z4NpYd*5kA>>G3nucI;Yu|F`Gu$IFTv>VT4q+pg-L&F33F|r2jlA@;-ib zRa1WSYv|LdcuI?g-0*}~^vLEZ6LaJEyZwLDaV-(&u;rbbmBw+*jQ<@`(&#te(5@y$g|0^7u;>9 zrS5$P|A0;H4_7gN7ap z(^FFcKEjz_?@h)m4DwdIWPkgKymiMm9&}IE$hPZd_JvXnitFN%UbQ*R1NoMTjP(@q z+mD!9VJ(LaRV?Fun>3t;hD>F>G)skz7iD*az!hHhtSS_q$!PCK$u$aB+k-HO~`#q>bBXSIuHfp zhk@lG|NNeNPSXCAd;9}4pI%{$>Z%$RsBzk24$}qxiu6-=0a10^vW<$9Svj;WOA0#~ z*4*_b<%5A<$xe8sZ=|CrsA62`zPFK1Q+3Py_q(v#{lEr=eOMFLeG%W<&hVg5Itn)s zYmada8mo9dQI{(cBa@~YeBc$BT^r_Aa_UA-YVEY>^5>L)H%Fhh^{Co@ZF$K3RRVe_F=x}xkcV46Tp^XE3Q``zwKIYFl za4XcdBN=QYu>uukTQ{F5)Q-k@-cwp%2<&5?9Q)!c<9J(&x5kXc`P>62qCt(=zvgsQ zL+pD_goAu2YoC={A>mG8-&b51#xW5I)SBtp*);BB{KhT;bpmDiZvqdR;TI>fz5rD3 zcMrIqL;U<3kQGuR?KEOAs=V<7S$W(Wg~85aHN5$Jf*p^{PGosIuK!bhH*uSiYGGV1 zeR;?M>N)0HOS|8;RiN!O^3V=fqa&NZ{r6^KCW^ux8mn67$nHb$+gD~qY22xHye;On zXihJTz8>=$_|}c@;o%X~Nz7m*Ph6w#$-|TN>9X&6LHI4q8_QNKaqtE}$UQl89dX_& zHnO%`Qc{VS#Z~<_(lYEcJ)U7ZCEY;s|7GG-%=U)g>I-!IqdJva*xp>3k(lik1cx{) zU@w9U$8VS4cU{G_+%8Wnug<|LM9w>9=rw z>kilXIp$1;P-GawJ$ZzAAKTdL?IytQqfGmh*D0+jRE?yzM6d#dgn*78zaah{C-1b; zpp1#(6N`UTOR*dy6J=P^yuzDSoTGr+yBB5FHU*I(k=CI@#+Wfy6PDJ35bLoCB3xi* zIpi0HXoZ0qxVv%TfA#&6{fEPEsRa>UWBZe)UqG4-u^?0vfbKOZum<3^rIrH89+(!i zKwcn~FFrng!<5Z5Z4PAw6hs21^6BlLpe?(6=4n3S*hO7qbrr1Dr0IoOG!z=PQ!%t% zlK{-=kLpz~8)&GtJU-8lT5;ZF@9%2EUM`$qdF%C<7lDAO=%_8W__Bspw+nGq%J!x| zO#4EfK7_=^O7LzF^;8&zkJC3zH5x>@DwBH!km`Rux3r?&@N($x0u1(UDo~fjH?Ehn zv8=9`r$#I>D!q&vr=64Fy>8+CquSASJ-a5icOkcyCA8qUvHtsO(E3v7eqCSbIxEBX zu3hO*ddZPovbCUE77uX@G*Vg}z8^5wzEy2hz9D2G@Po#}Xy9TYGmaN^nUn{8Y#njH z7O+cS!^}6?U{I*N9>Y&6E~h5)*|hn{pD?@DxF?M>1Y;N3kPB?Y{p9mhK@U$Tn9+iyO9na<{{tv3*O z7MGd*N4_A;e-wkMmw@M>x9?~H6`y@0YgKRJ&X=AlNUC}unFTwJclM?_sEqj(^8oWn z($PBVR2GZ7Uv?^ted`e)vlVJG8ncaI7|@Nrv6kSf-agqemeBl@6lTG;RmJQusS1WR z3;=D2UxDg+k{49_DgsR|#2b;F#>OXMg03=!A4z2Z3i{`JT%ch=D+8F_j2?kEh4sE; zG%Scuu#-3lP}iFV%*y>j5ynCl<3Js7x?!vx4Q$yzI=GE$jz0#Pt#>F+(R(e=gnDyxyigYN=^Ywymb%k zs&$k*uNzb7NKeV@tEIr&9`A$t`qF9`0tV89^F84Xb4t{m`faPo_)O%9#n^r9shpRC zN*Q3y=7WHfxOj__IyHP08lT|`;QVZ*DXz zR=zAsy;@~sP5Frl&2_H9j|BjCNelxNel6bcyBTE?ci*cBXH>{wuSHD5Fmcq{Q7ofk z*}r84<{fszrg?z`qG9r;k(8i0HEJ4Wen^nP=|x7h=Pw3;+hvP4qPd=Yc7c2$(~flA zwB!Ze1I5o1;DRpf#@=S^`S@vF=wHuMtY|7~zzK%p?~mtz!M6ex)Y~Prp7Q%>v#Sh?N`d-lj1%ig} z*~A=bno1X36{Ia&_1%xB8IJW0bt!sflc{@HDF&EfK)rZLyjn9YvEJ{fdao*5^MYpE zVX?Ai=K;}a1^SQ}4$SCNeS~kPI=>cE{x1jVc%(MF7g?&u=ebU9W(^F$*ep9N!TnM#^(OU-S z?IA=`?+~^R86xzVmPXx;BD^B4pStdv_C}}GR5OfPt1?|+u_aCnTfnDqjY`0bN7HY) ztucd`O;^IC8Ri%dShd{eK`{`s*eK2HWdC(qEWz=>ms}&Lc`}#u!zqsZkW=MTa=Tk#0n{gQj*fM^TW}eb z;MVHWy4X93(#UMY&x`f7;7w!7S~LXI1^)J-Z6XW|RLm-wk4f%b*> zab!m7!pMyDh0xk=Wl0BBO-blUY5kvSL66$j-t+h3*&H?Bg~xVSV_f;LS2!1ACwfaP?^? zn_h(5p5k6`^~Saef~477PsQ`#BmS5!JD9S67o#~24|8nc^>n#!sF$8?Nj zy1-;3&o#gx`vS+h$n}03r}z8#h-}PdXyMD3%TTDcEi9(#1sWapVDK3xRFN);o#Kb( z`2TU@J$P&OOn7ZbSu8nRlLeVg>U%+xHWZNzd^A^{`liCj6;ZN;3uEN~B zvnGN0#0R;oYjkEFLj7=hoUlcW=_`ZZxfU|YE2?yugNnajh8MW}nQX6gvWgwV3{ zqH8HZN}Jm+sx-JSUwNp>2U9rW!jwJKELeuAA=SSPr@2JQxxK!NxAVPd6}8XJ^l0=F zI?U1z~OD zwz(IKUluRl*0$_^cc4A}r&Dt^*m^ptGQug7*Q&W_`#=P_Xk+1W&eG9(eZUfIT~R*F zQfX@zJn^SlFsA0HX#33?ZosmpzM*K_UZRp`CaE%z$HpnxqPs0Xd-@dk;s#KuSlyake+Az>iS!#3N>_nPgv zdsSezS*2TH+ieAEbs;Z^zpHfCJ-5aFQS+&Gzmwl03}>%=Q#CYbWfP1wt9dX>vmJ+h z>TfT#<31*n+untk%&?pZiH%t;Z=b4n!m0vov8^`}%k^XZ?WOsfXZ7&Mrbn|c991JO z%|Fp^<#nr*>K=@7^o>~FIHLyayJwJP-wx9IoyfCsckfWA)f5|9S&YKF&HbHD=Db+_Snbc86yWNa`A zxQZq`j!q0YP(w_Bj35?UkR+(t2WN4aYI`#mYqQKV)+UL{gWh3oOL==UOQfZlC0C=Z znTS~xvmN-s7Gw~xy9#d0X81i6OI3Aw1Ke`f+tH#O9*#<`q#%b;BWJN1K!12m9XD9K z+~>=g2+|P%N#)rSqz|!3T%vqOL8kJ6<7a-UPf3-Oo6lt`eJq{UlPbIFe}GZE^q{xW z(LyS`9Q?reiY41DOO?wL%Lh``Xla%aoOY%U)GQeFr@y5{U)hJa%9+#q@%U@jN^S z+%IDS?jiwC%FoWghiktwp3t9uborU_?0IVa6Vo5E8k8PV3~+JFg|lv%#_cpbUnaVk z1!NNbtK(=Gw!jxwV9gg;t0dF@33f3f(>13TQQuJ9)9vc%=@g)ZR(c2!% zt4|5oG(tPMqkgd#uI#Z;e=E}(Pd;uH#%7)KF4i0Uh3V-okP%~g$A_?HUM5Wn+Jpq2 zjJG1M((8D8t`|!0t6*QRi7qS-G5faf9wgGIW?DJ6Q6SX zHd<^U!Ylhqf+bY!!v-)H60osl`uf6E2rQ~oL2zQG3ckszXiG`Cn=Luu&X<_GF#jmm z?K$s57DSGQuP5Dla)5Q4zc!6!C2VnLZ(auG=^Twb>aH_BEDqUTt7bK2?d&M9HY#c_oI9Pl;gW_nuJ0 z^)2vI!rn_^XV(@J%#$;fw%hs+Jg!ubgImDYudGn&xpeV;~{3 zW*ONP;N0^vVZb}aSLmwod8Vf;fBd7#D`cSR^YKm*C%yRTotbzaeDTv`b*ax8M@~>r zzB98wplbC32y<0_{U`mO5;6(*8Jg<*VZW~Z<TnTsdV!$Iy!3>;@@%9B@#N=nMU+ z)v#VSC+3WJ#WW91v7V0=|8ptc=V(sn9dIDyGxA%Go6uh!-U^UT^(;(umPv-ovD%1hZ!48Y)JhG1!~lKqu8n~GzECFMa(OvB7S8V7rR zS=TgCl4KaqChI@A{lF_heOqw034H4{h{3>M;zTllWect!FaPgYzI_w1aFCnE79+2@ zpsp6udtRr&0s%P0njc7$xoA+WKo3gW+vyvjjx|HVUBX;HAExV2?^;SSG5zu6A2y<| zRNZ@gO@k!?@C!j~3_byOQ7H&;_b;+|*{imn{ojAc?S@PyJ!i>KDJ}ll*-{-K_ygqP zsY!w6qu0R$zaqpLLS?|^X;QScrDB5RoqN?uzW|PCQxHg7u3iUEUvjoIVy{|dSX2ja z>9brZ!7@17nwzV?QtAJqciGu;`Tu`%WfRUHihiv$+(&vQjBbz~X<-GU=j7f~EhSO1TevmGg6JZU*qaswZ&s8342X7X0AHtRtqpIJHvqD(rYU6rJZf?~>&py0^G8*5JbS zKlH>PHLWb6C~0g0azQM3w=Ro%*R`OZTW5m$DoCT@)8vdbf1z%}S(@dz*C#Yhtv|LXd}|87HW-}{Go6T5lTyLE8jJHY+m z<&+rlBQ+?;y!e8&)TD8Q&CGM_;M9Hts&UvygYL^$wXu4V;Ez^X z=R;DfK=8}9k;%J5b=vyI2IZ2X>J_v1x~jdAzEwvy{ELpr7cJujX{&{G3j@@_f~vx@ zO$4EJ`2_{X^k3+CQDQwXuvov!itw56B2N)5-j}&7Bywjjmt?s}727^=44hRa2lD?) zh0vefhEF%0!aB#5omc;A_>1$yX5N8wQH$us4uXpof^H7ImE(%7NBVl`>NTm`f=|4Y zvy8n9;rUI0D-;b{kNIg&VxeJc9kW2^RJfctfT|x5D?o5c7?Wb(vWP`ihl8*2_2|98 z4xGyutkN7+rJt;cHFNh|Antp6b=K$|^?Mwu(E`nb(3JXP+ZmFSBrHcpTx#@9GuF3X zy9HIw^P01YvBL^*teZ>7jM*+}r^XLF+4w$5l>*y}_V|vIKWxodT|*ac4AuQ2ML^BE zB4*zm@yb-;6Q~U?t5l5z9b?66w&ew4GuCa9uo$WGuhM>VK}-Zj2fS3#xUFVB`PPTdtTK!ceYO6n4n7I&X0X*t0KU=m&?68`PIEtnc?wfI7S!Z2G6e9|@QKh&Z z0%Q`8P!|J@wqkvW&~a~lDSqG18Lrm-d(|q~xomWvu*Kl*fnkc_(FgaO{62b*c3q=& zT+VlCA+#;5z@;5fJ7;MN(q20T_0eXJqpY;hAM}ZkP1l} zAYJq7s5`=|T4u3e``-r6eUP~VMY!y1+gHAOxEg$N@*Ks<3(J?Tlgp_+!E)3|Wa{A3 zvb@X6Q=_eeO`^tG9=&w_aIAnH`^C-?e~SA9Piudx0=n8Aa;5o*=oRTr+i%#9(#Bb- zifH(9OZgJHM_XqT-gpPmD~*fsyTX7A<+Ct*YHgY8FD*Fo`hR0<$g_XAX!VwK(&}?_ zGga;<;zd#WA5MT2Nw;j}c1N_?sj}h|k zhH1wASGn^L)dOZAI%Mh*N7C$8Mnr+_jOO_xEOk~5r}^gn2?Ad@MOkY}npr13n_1jc zy7|ME4u}P(mN^D?GkhyBqK;*CfkU?vI=;X-zUNk9fhWZBKfwhrH^%+-1VFzDuAMI2 zq(oiQN0{HcQoK2noXX3`Z6tne%|+55*;A--xhP|qR4UIUfviqwy)li1 z#4kMQ;7*1`%9~E|*JwI|$DwvBrl!EeFZWk!>UR$&0m0AcKbBWs93)J0@d~^o=&mJ7 zTsCZ}x*M%xsz=;ZDoJI#nC1`jz5>-q&9e^XPkfpsGJyu%`<z)VKqgpHk<aaa%&V*yk3BQXCk*NtA#{SECWNxxJD z@l~PiblR|2(SfM{1A;zD&wZX-{}2qox#(TT9Lat6H`^S|iWLp3Q=UB3NUyuDX=}&Z zle}-~zTwET+Sc5n)c@7ncZM~Ub^qE6Hd;XGN|7E5pi%`59g&g{K!XNRT3}FMsKJIp z5F$uXkRrVVAyh?*B_SdMNQXpV3`!L-v_L}O?x4;%?>ql{pL;*tFFpw8oW1wjtL?RZ zYi)&+)Q?}yw2n=E5CzRMZjQkSUs~j21_Qpdy#GW=JiILWz}ve*v#G0*g`lr+nw~r$ zS9PEL(gI(s|3YjL5Sq`Lsw7PjB=s!%X1o2D#_MVy{>maR4G3G(4@9M1obq6&jBhTA z{glmfnp0ODwrzo_(v!roU|Km-2#0|l^YyICTAvD`U>I!DxOL(NECM{4SoOWoO zU&Q*xOcJ}Zsw9SVv78E1EB5=nj>L}Q-FNgJ)_89{i>Y-*b~Wl%ZFE0~2sx5NXCvnN zyzi!aA55F~#!rzL2a7TTUuP~Xx7woz<;H%8<~^riSM4%nzOV8eqlf2mSrrg zt&~~0a+x~hJizq34x8l+p`%x(9tk* zG>^`Xsn%zBKV~%1hb}-I(`5&}w6-U7)hO4e^6Qm!nTVDYfo3wmTU+y=_u1YE|GvF% z276b$e_KA*6UTC#^wP1ebo@`dC;(itDU$mYEuS}GRgg$LfP29x%!?VE2kY})A<}u&rrZB6N#T^ zcDZkGY+boS8*-?e#TVDXLaS^pG**(OY`PAAuC&=roEZ%eD-sX&-R&6dVWpMY{2C=K z)F6?{^a(SCj$Y&La4@msRrmVHJr&fkbyWR|1;z~VI%(F1SPxN|96C2lIvDkp{Xi9! zKJCaj_{1scE6tZ&Z9^aJZZ=8b`BkYQBf9^zxzv7iEEE%Fw`;Z9vE4akbaD@;c)oe5 zVH{C3=I!fVPfvnOw7GAV9!%8F&3At1k@o@ZqMp~P9)_iz_~NXdS7M`5uN&ZdjeR4!44GN!k_I(Uy(tD9p)s*5sj-_wKyr z)Hr`dtfiCvpt8KCcfulAtT(A zlvc<+vK-0ZQ1l1dh1jrt;n=13k*lq9$v~3zQx9^?p_?z+TX!864SAeomS!s!9fJf=wM^%%JrPg2k+7|T>fEt zkZ@il*_Ev)R`IT=pb7$KSNYP4oOKnEv3VL;pp=#!f4nDPAU$jaPa44(W>f;O}satM_eV&#nCgy?7} z*l0nG{lth|l|!-@>tWU|nGk5vVnbj-Ls$gFEddB1MS!Sy05)}MBawSv+B|g= z2?x_suk#94Hi{E*s&GZ|$jT!4rJ)E7O_z3U(RKrZ@iB#ohgY@xlYR`$J@{pu2ZrS4 z_ceTeE0MxGj@6#HWD*IHMr05DZy&d8iX}CMS-uOq`;L+rZS>4MQEk91E|=|>LsG2N zsmlf?DL%?*Y8H9387Pc#dC4~aH}zk1{&mWxm(c6ukmJOQnJ&$yuRT%A19t=L)8ml} z$xo}IZ$Eti2xnUvP%-S5bzjqv;nNX9a$kP^uOEA(?23~(KVgJZ4l>LMI8AW(y{gU8 zli2&_gHwTXpT!*_)JWyOrvTpKE&2${I=kYW=&!s?Ht;sSkt=|8S;N-991TE)PL|DO9`STwPcRQYi?~`Ms<$s zdTw6xD|o1ziG`{WaE~pOQw8_RkUAim@*4PChuo-#n0{iAx%yJOkKPAz7MB=4rjXCc z(>v@3s;B!CR8l2unyx4Ep-MGRq!Ez{)GO3#Asvn7mF}{tHVn4byRv~ZqZ{OTAkRPg zQy+60?@~Tj2Cci`R|XX&w_c1&D^G2U=$-}E+u#;b{{=X1Y$m$5WK`7^j#rJvBHipS z-h@|$7H^>OSibOvReep_21-p){N`KU?G@j;-CD_ZQPf{~S4%JEMI_l2&(V#B+2W`A zkd7(dls602R90v)8+E9wM-M@F?kf%;v2#Q<2a=*QM~9h27~86?#n~!YZvZbvJzN^d zIBZMj^jXY(7-r&8Ckfox!apWN%p3)tXNs-svDd<%9ePSBE;t^T5>N3r#QFl)pmT2> zt;yLV6m){()n;DtyHm`;_x#aMw+%2Uj3$qml)Zs&$EcEsj2#W$*4D#JCwHd_Vs0K_ zN@>3#Nl{tdJ3W>kp292k(3$ay3>k8oaT^E26igFn{xU{PPEY#PqRN#=gX!F zcOotoz3*~{Bp^;U!p7wz62f*>7*OE+QqOxrQwEzDbL=-fzM`>Z98u>f8@4rj2q1l< ztt)E9_k<0_Y2LwVdD0wmXrXQfE}c;!n7(V@*ngy@$jX}Fa{KGc_>?5)3ph_*QSL*( zC!b+nR8mwyWbGthQU|K^Zm)r#KEdH=KBmOIMkQ#@>ZE{T3ZgNz`1M(GCgi@N2>dtp z&BLmuHsSS9;{@B3vg}T0#r5C#F95+9<~*TP;fFb*2P>ff9%|Fv*ue|vC5sT6Jen9| zTN4;MR|BO*r_xMo(>*20?MD_IzA;r$xnK6qC3`JgJjz=XXK>iw0=Q!zE6)N&vPPn0 zuPBLV2Xg1TXC?4+>;qJuvrdOJ6iq|52AJev(=G4fGI{#X#9XP>^OU6O+7JixjeC77 zD-R6C+!a5nGAV1q;a)-{OGc<*bc7(qXCtrKYqu_oK^Q&6X>2&I8O zucnitdb8Y!$fe#Amhb{H`}To^i-0L&w*|HnLv#CPF=|fjx`+5|L?ROs+qD}!pk@zie*>8yh--2O z2j)E`;cJSWhB-EF(v&c=1j?@zSE03Wl5A82XGf`%;cQ57LoKV?W%vN4&4!K{R|6!2 zD@quhfQfhNi(8Tk&nd71fYskcD$G7>jsRiPfB+TSH7n!!f@h~m^tYRkX7fVcSebq! z?`4i5BeW2seBPm9`{UK5PyQ^gL|{r4A^5DvTyu3zo0&6cxy*Jf`Bz%v`uv-sl8WMy zOI9*u!{m6wnXDy=NgGa{A;Fx0=2fDv*~~I%lriv)P7+Lc{=xk=T~%zW>;r~`xjyDc zc2_9$Ox0jl1iXan=x_rD|1@O($u^g1vPZC+-Wf)Fl1yipLj)uQq{vY=(nMT%6ZP1G zgL=vE)4-fGJ`Yf~0rVELTyWw0*EIls2qE z3SA1Ui$DPPKVKM6Je#BrsBEQ|Hg!9+KNv^7y9EummX|96QB>_(p~4;L?&LynUGT5Wna|xRR>oc;bmJXt!2d^hQ<@bp(>2~bjM0*$c z;w;$2xv~<`NO;!kGn+4*`&4kU%U5M`hgno&Z*3;&op%Yn+GLWsnb32^N;D;DBCi)H zuI@eYHU!^65}vcv^Azcprc>4XxK7n~sMVsNqUKpg@32}gd;p_B~(Pv%wOSAp+(`7909{hhp_`lG`;j6Q~+ zhGhb$V+MNyYL0lAENCC{%6*c-AQxw9^q`Q8LelK*;x^%G9IHYDtM$U7JzRP2Ov&^q zAg*mrX3FO7v|?nSNO1{#Er1i}^JkakNO<-W3jb4EM|nvQzkOpY7tf^R2UDH#?OZbieDHQdRraNr&|9DR#!z;V^!r+U?Lq=Ju? z=39&kH}F+JWuJ{*J$`m=HoT&h=n8Ibg^bQZ+(W>Ds#pKdklGXXlISkIbBpay&seX$ z6z_Zm`=Gs$=g3ZCT);^`6QIu46K@^?7Dze*zLZb*ICbE&(fJqqimer)h=SJ}GK8&1 z`%CvGB4gciJx9IUr4VQ3c#EzA11JdsoO`ze&||(7qBgfsY%PWKes=`?1W5YqAt}~5 z)vPBTNZ5@gdlbF{J`eZ2bN%};CkY+E@8ngo9{>OHYR2rQclr~HFTWX!XZakcw5-|u z>%1aY4(;Z4-d(2#PG$d??z(j@pgZsX&9BD3lr^hf9IOqTH{z_NGeBZjeq#jul|2y+ zLp>Z%oYRYdhoNj%?^JtX!S${0I8z-S7Fpb;GA+$)>P$p6nwd zApgb_Jk>pL&9jm)QqYobNU^0f;TKo-bTmodE z{+W&bCD?O_iAxlw8lQFx^0@xJ84NRZA~!QIng=ys5_*aFx^#de2pyX4tDj+?rcvGa zqL2_MLheYxHH*TwcB`9l}eYFk(WGcD4Fxr zihvU^vR&(;qA8 znnsmJkQ{s_+x?M_Iz}mjV@nReX(pR8C~qY<>cq4il~o@|7i9#ZM^n9qXHmp!1JorK z8>?UsXXcc4SLozWS`xX{Bz^I@s}@}Y1_Jnh5e!~rUYd!AALE{VQ<#X#P|rjRY*HG(t%0jK8^vIKInwRV30$6cn** z)JQrvQ#BUdeAEU&!gaL^)$Z%q+NuzxcTgpH+G&SFPXhwClbhjPa0 z+jh}44dQ^vSlaMj_`FX;m3YDDkOtFpr3yanBk6X9bknWy^gc17&Y*-n zjiaNg94b%6!%B2jyQ=}>n*24%E@XWk+b1kJDNa-tm4v2YI=j;`FTPD$s!Y>xmnVB_ z)SM^=)vtTJ8SJ;9){bA&2!`hnL3$1X;?5F`!`~=_>2GjfJ@$#)H9U@aq_>bPoW7$6 zpSpvwlw?}&?{Jq@F$<%Kc_$^#)1GLoEXgx8tuZ(dZTv|-K_$px#Pz&PgC=2Gy_6l_ zryUA!cj0Ty+F35xO2uwNexs77N7@(*$i#TdFLtm;=H3sC4R^87v63CRRa=^H}d@J zL&b&=k<5$boJDCy;GyKWG90(U-v%7u7dO?5# z6r2Ifn0yXW0r5w$vQMm#@TVH@=KTBBfyE?KPT$o#(B;sE*NG2o1ICSuDfDW}CnMM7 zp6Sn&OYeGQ0Y1pQcEyklV@!5j#nK3&S$?!xxM)<`-Q1kF>;rt!ah?7tANxT`)V`MfWWn34&O0p5pW$1gW)Vb5xtx7I2;*)FE#D zssyjRxrUhIRT5tHIo{st3fbqyt3=}3xI)mO2mrKhAY)Cp66xx{jCPV>oO27wNG`kz z@|52JPg02N4t+vUum#z!LM)+Tmh<+=CSoCiD{!t`&@e?1#Rx&?=-yRP2L}i&e@6OH zx=PnV9S1>XT64V_WWbXZtSu4KTUH$L7w z+WI!>k-7(>E^iQ&i~*n@Z_#0s7fCU8nr>QOq!9OzIj@1m9zzghPQ^)Y@7&?E_}WAm zG9hG=bekXy!jD{lUIMQY#F!!3w0O)%X2S~Q%H4fz3qodCwGn&&yqHZA4nOSDM4i+~ zI73qWYSipb&A|5VASxOXd~5waEHlhGRVl4{VY{hEUT>}-uoU40VvVDeQpFVM=yAVEKS-ocelCAa;%Q7v9H=(LAhC0!=jo44R>&H$f2Jsc? zZzWEgC;0BPNHf14k3e^i)y{TWxPBqdyN%w<4fbI)H(EQlKQFjeVZU5fwQEJY+d0^h zLF4syDwL#2QnyTI(WDUSPvSl;#ws-3|71+hUV@#bC-5IDelg(3wL$Oinc@=og-_N; zdle(g^wQk(4BkpmI7?x~Dg#rK`Oi_BLwTi{X3Wt2qe;vuL7fGT+5-__h7_^MRqEY% zRyCz+nvOX%_juTa6QXh@G@xRa0W&m2bf{$hBb&*t2fc~N_mE3t$H$K6whE*=z5bfl z3Lld5({)YN9KjVg(`go0YNiVjTRbD%MEeLONsgMVKvhoUZPbBi%MN85YbD>(1yU+S%4#a7#)4E>5-% zgk|5bA>mV|h0iG&1lBRM3v+nbc{CoM+doOFj%>3dmvojC*>~ysopE=V2x+hA zT0qj5sJq`V*GT&mor51VDLk$8Xy0kIn=Z6Y^KWZH-1s&IX@5978>gjG^m+)#-m65X z*9*2V$r&ocQK}x!913w>$tSG9k40)`f!5h-Ev1;5IA>Zmt!sg7ASj%MO_N|_m~00Q zsZF}lYrsKM1;tl1NPZ`|F*SH)aiYHN>6gCT7`)yU&f&SyTd*mDWu=GzQ%Cx>4mx{= zL35`4*=7R{pZ8hwvmqgR?$gW!iM*ZxlSVi}&D2(?pv?HGZ-{zO4^WK2`OPXry8s97 zbbU1RPQ0y89@;eAs_+>zl5M>l6sk6WQ}^i14;wQ2;N+gFtKl>`GvzxZTvz`R?x(~;^^KsJiFc5Lm-_taOoWR9rjwG zCo#%Z?Yp_iCm;(-8JnMZ3kaVopr3)oLM+{B`491I>#ii$y?$AF~Q6hni=c3^Te+?E2)SBc|B)HQ_) zq!4wHkieBmsP0|%BOi#;`BH-{giBO(w)&4L+(Q<;XDp&o3~RpTlZ9t-;V1E-tB4O2 zfX*t>EglNkN2Ve}R#E2h&oJ((KA!1|5A*k;tbxUkUF2~wfVSg;)nDMb!G0aW^r8M^?#r5)u0I32di<^$K<><m2y zQsDX?YhOT3XFWMWb6MWVn?HY$68Ml~JfUyy)nEBs!XE)TLu?!W9ppfU!^|H}pWn3y z#K%E0wZojSTl?F~<-(A-eFJGejr-=G--^6#+HmD_wf@cUpD*DufD3|R)D?aFLDJ;N z1l^#6&-;U?>kb-5`49N@p7Zi0*JEL!!36@W`rbl#(X)Wfpu5ox;M(z)PuIyn4gFG* z_i#3X1Ofm|RPZZBU83wrJS%Ep^TG>eM$dIoKO%c^_DIf(tS!qziQA}Q|0Q01g5n*{ z!_uc>55cSJf4r)M5Q@B?>+$KGS)$Rb%;}n&=_Io(%Q(3w<8cQo+cmA5J!%q7nneEk zLIn6i{qG6MdjOHw7*G?UBpEF;9&9IPu3+LG-s3!!+QE{siK_+z0rn4cynu(dGoQ*J zxk05A>?F2p7xzy{&LDPHTd$Nd8b=nbNic z4nGIP2^C@U4iX*wE^I3=*Gss6nUgaw4i+dAZ1)(r-a&m}Ft{Ru?>gXu5D3cQw>=Uhz58eslJPh@h9(8pdF3HR zASmk(^yjd>eK(Qw3ZTyTwmA>_^Vugxp#P40#Yw=&_GHr}kLsc4K*O*=e*sVlmjvo!bjXhLj@b3?Nkw*LwvIuxO_X4Q5*-{7qqxk^VvIERM9!?M} z4g)eZZ&WFT2<7>)k`o~O1|WATfNQNU6HNh*+UDmHKon04w73MoARt8ZE6gio|E5d~ z7@qfE=JyCWu62g>)W-g5nV&Yp3I zOpt$Lw85gVLPv!>k=wBI;^6A`)I+0scMmZevPajiyT{+#kg-C^1QZ3)%&$_2tQ#f? zJ{=!852i9|)dY&_n1jIvPksIB;YEn<(cP-7*bB7Xm`>0WuHS($cXu|D_C&xd%yFB? zksD_~dC*?jxnr5pe^F#(^qD|n^7mLPSe=XAXBu#44{kCW^640}(#skuKJui)|6$*_ zb0p?`?FQn67&wbHZYC98<1KP%)tas?rFp&R21+HOd+fqmyc9H>bZHNTA`R%yGu>t~ z))S{f10V5Mi7!aMs=*`Y*Z+J!IkFoSJf+Ssa%8G-67OF$K2z@Z73`b<`_=J@{H%#< zjz-N<0Ad%t`+ES_&5ocfqCO+ZH)mWsXQdPEUeI!5tHeXRm)ky33_p9S+G)@bqt5>s zW;#X$!5#t7R;2qNum*cUVMVK(41#|>)P_GYaCYP~lVU|cAGWp{W?Gg@A*QlMcXZ48 znHz?eg>xqfnnvWaig9=1cN&*2O9nmQ ztL)a+>G3r|Dhnzh2yaKnd(cziiQZieUb1?L$lG0r&gCOjx~D?fq}h-#UB+yw>xl*n z&|9c{0o&DPS&dO&)@AIwOw?2+9smvIyRmb1@=b|}ovsO|O{DFxf@YoO8C?i|2;Nlv zA4{=)>+mt1ABS`oth5Oh?Y35Hfl5ZfmA!ke6o%<6@C#I1H874Ok0dc@!X;XjwX#?V zp`p899fuaQr+jK_bBpR=v&+uu&yd}eCZUo?M|pu=(<0$2z`+>UXBM}TZFmDHI%wgs z*P{=UGh&fT8m8JUQ3(x_d5**x>t0V$o5?ek)ugsJ9j-O>>S}wfoc@|&G(5`~n9(a2 z9@qUjW->Vqsxv?lMS{{V)XN(%=xK%@bz?;41wJ9N3$j_v%uEu-8lB^In3~pAV>4Ni zot8p3A`mR`7;pDLodt|&ad1~u_ue%S+&c)V&=UA4hg78yshwW?i>9UeDc#omadBH! zhVybr0LX65@feU(H2q*0S}8&-%kCKicW*}od{j;Gk}Qv|;g0AzDqb5-IN&bs-O;3_0xS{ciP1d^!st z$CI2SF4^EEpfZ$hIq|#zQ>#;jrC}YbldNU21a@>!G%~gj#BuF-i*!Nd$IEBe0USNc zpeOsSab$RIid6QeQ|%$3CH$N;OrveYk-n1ftT>6!B8vR(wgO63-LhFDPE-dvgfNZ? zSzfW$qkiqG@jMZXHQ*d`I0lMe_(|>oCg)Xnf0_H)w~3(T1b0avFM(70lE&DPDcxV_ ze%GK1C_iI3fU6#KsE)?6V?kWyFG`-;?+BDiwxT}ajsPd1G~1MR1G#J6PbrnZ)C~Mx zTiJ;2-wr&Y0)w1hz3aa|y(MYUJ$gW16JG^6!^*GGTuG+-hv@ZVT5^3^O# z@okqrwE7>$WAt>TF*WcWSMGI>R0J^StoV;cv`kD#mHIBgy+8ML&2n_xdv@j7%UEi} zeTFFtDY2hiIfcI5U@{`xvUw9prou>Ef2eXmM_ zMQ?FVEV3XvNqK%+aRzrD(~L@b?0?{J>^IPQlisdmb`T9YD0?QF zr07+&=y!~|J6Kh>V3glGk7Yne?ldRFgRXj?+3oi~jZuQx;@i8|l%};?9q1~4v#uD3 z5(r?eF)0AR14c*%EyribC9X1v0<6gP=*sAD7>6`j&b{U@!>xX#lDa#+>slnag*7ER ztct*$HWiM3zoNGA;ac0d5E&Hg^no1wq8s>aUMZiVqn*)_yGTE7sot7OQM{A!0k{JB znWHo_8AZiIqOdabfgE2=khxp+Cn*jlA}>2c!k4vc&HWTX3~m057TP6tk#y5#jOS)@ z9-qqgB*P?`^9I&36}7sk{6K#B%F3eUz*umt&J*{g&_Y|F=)nPjtEn4Pnv<4Q#k6Kq zngY-63Ied<*St};CCm(J|9JQ~oAi#0NUaHNO}(S%wvyY|eD4 zlOM0gI2{Bvnsub5(G1smonEh7$Q)_?IKh6SdE84?hAN|D8=@C%#gCm4u|#+wMX+JR z`hgdJ2N_a1+DUbJ1A^f82j!X`p~(6$?XEx;Yc{B8v}r1MW9lD@-X8P za7CV42J9GHp%!J zFm{KPB^2m?ZQJbc#d`9faPp^a8h$hFtu5d1N07UOZ4wsO9XOhr6m{3=FflHp&$n`( z(X1vQ+rmUc%u*!S^|hM{QZ1@otUL0Ss&)$~2^iw%r}7FKumJ4@-Q!gc9kSc%#OY_n z3)!zZ^4H+iFrYGjxLfYp@Aqst>Y$#y(}QH%X`XBTQdz`r#vqeI46v_wEUW}Q>eCQJ zs0a05;P$^b5#r1&8>po^*9ud%X@yv2himsdln|NV74^&V12SS24T}sPT#SU9qGaT! zs;cvgDQ1a@jGMVg(Fdwfm?%|+$Xx)WdFGVU%Tkg8s$Puj_JtTqNshtZbXg}hkS6|nZkls@S@T=aOg`*Mh$;EcX ztdIE#lEp`G5|wM(&3#X53HK(imnR8^lF_z|TQ9Sscv`THregm=C~d{ zJTeD;(}fufQHr9HLm~S>86F50;CPjq-Hvf;IZ<}<97StBt`eYbBmz{m(jnfW_C~{^ zMg2e9bB53fadEGw>Bq7he9ZYDEF&b6LtUNO^C=4ff*1g80n`R}j=0QrMFFMg3qThEsNE0p?^xrB z;mvDv2Upe>%C8*>JpQ7FxSB)GG@=D`=s6*227y990DuXZ*_p|Ne7THRv z++3UOZkGN9!=lFTTTE?3MkG}21MH0Szr|A2=bmd!j;MPN)}E^{ejpeqak3H|9`6E- z$I&F9lJ;_O;($N&oB=T0VV^!R?(|d@&1>GM4KLX;GbM9Dxl2Se8K-<6>`Pcp~6;=R8tOR;@4jAmWC-4?Kt~3Q#kuZPcBS45LF&09ww?kbF&4zw7vI~(1?YbB&L2Fwfz2gTT*YOfXKzbPf zb2V>g76d7j9akD>By|NenS=^jT0?duC1u4U`;Rb;IQNiabhjMS2Hf1L(D!j zoO3RSt?+R|tF2J)0Bj3U1lYBIeyJKirNI9fnGv69L=b^BlO`2lEO<8Mn}pRlmfs&B zEohWw%T=tUj3&Q%h3vOdh&SB08ldM{H8>O|bVc^WN*uU#Q6ci4WZ;n|>$zwBzY{!t zn-j|^J%g7D&tEj%eompIqt|d~S`FlHb0&m<7oaVKlW6|y>u7xO^ za;xdpb>D}9>eP7pfu0-%c;{RTDTNR>Xt%8sw0|7^jd6@9(*FyUK`ZKL!y;SH`zxFOlM1n$zj}NeG%CMk%n~BGF9HDr#~of=?nKU8y60`Y9vaU3ojs0{3X`pF_|QL0 z_e#bBb@d-49$vIN#!>8WK5q15M_P;vH5HE-+x^$lkFRuFaQCh?_6MDyti^Oy;u)6Y ze~y1|*lA#GSz-#R9L>vhxbB=Jl!$8WH-o)WTb<@U|Mn#v`|$DBsdk|GJ_5}LKwv-E z@@Pz$Unh4nu4QxCZe9_gXno9kaOXz))2%{xB~dG{O8q&vnwH)J3=7v6`DM*J@eSA{ z#TA_*(_AN5(9XXoC6qLH)%}dSLm%{aWzxF_g$8E;U3c_t#`Rv7icG-7k0Z5TNF>i^MeSkQyT2AFT7*$EI8k}OI*o! zdl7oL82w^wewQ-fJ86`fG-C51`smw}ooj5hHQF{caQI_W;CsO2mEeou)W2V)%6@Y` zk5yD;Vs;KKn^Y)i(iHEaOm=@|cIw&cpG}>LXVqx(@#Ne6JL<(PQ}P^Bool@N0N>2a zDn7yrj%(_DWzBtZ+x%FX%EX4Tnekp(*yR%$!%i&ce!Me)oVj1fg0o`a?z$C#kAE!R zI0_R303@q)Z&*pJNaPXExtEsZ3-y+uONm9ffBkh_6q>K(7(B!=q~Z0Z=ETDUUb~7j zI#uX_L`EB>+74iY=+*mCPhDzMT1Pm&)UujN`g5mI&sXi(GH18ZZ1Iickzk_rm&dcj zP;cU}!*kzY3AIz`94zd{Xv6|h4;A!*5hzJc7f3MCi+Kd-@QUD)6mByjasTnwR1k#Y z2JwKDbf8m;Bj($kE$plWgpUPzZjQ%w+rCN$uvf+8Q8qlRY8UZP0VZpMMW-ml$>+%x z4pl?mArF(6%O1^jP4k{kvRkbpOdV8O;AqPZCMLEYc4XD_dWF%>cm+;fQq%nWe7vDI zarU7rT#D+nQrm&;!P-=W4bNsJAeV+m*oC%V_BM_o^CH@|$7*^npFqz&TokMBy$z$- z;&-hkcQY8Xm)p{G#))TxE6Zn3w)-{^xUCCXj`|Mvow&4kEeEu=$Q`^J460$a7@b)) zMb^&T`J_Fz^Dnl&FGLd)R#J?y^^{kOQ8VsPCpYc#8mHT>GiEpOVS{cz{o*U7{FWeXKe+R2<2hG%UJ!q>xo zz_d}Vcx_8`%Z8oVrqxtDb=1F}#6ISCZrHh#u>v*o{Ze&qHN^Lv4QcdtM4RaL7p%(J z(^&|>NsP&sh8Vvu%PYN%Z21`70JYiR-Dm-etAr+r(;yqs7VFPk0@|J zZnI#T?`cS0N(Bq#VnM#kC0L**EQXRvmr*@QryF9do3~4gp!%%0vZB^!SxOg4qGVwDHiGEO&wZbl@3n~ z<6}qIE-H+x44-?TTs^=&*fSKMk&cGvNK(u}48h1+mg}$q&+->J2e5010wN!29Ztyf z*U+ha4E3Zh)g!CeY5oGjmi48knCh^v1)K~@{hpybkguBltfl!Ly|mWFe)V=%H@bC`Sm+Ue2SIt}`wvwI{y7KXtD)t(Cx8(vxoH5$D+A{t#) zJlgC27%L9!%ZIU>kY%agh+yM4e7C(7eIp21-UxdGS@@JgYg;*zp+v}Fgvawdx=b#^ zi94dysP)fMp=G{9xwIgT+Q+EkE^GwNBL(v)pkZ6XO2Ck>Z7sz9@%$w4DJ_A~dAOl9 z_A)x>+E7E)m&ymYu=H=tghh3chLH-afKuh`tcWZYI&lKnnuzX^-&#+M#wXgeYH2+7 zYu(or_(rZ0TD0zO?MLSEa1ygmhG5-bZPu;S%J{3F|dS3xpI?q!5SX|6xHJ86{p^Z|t`it|R(iGyCr6_$)`Q z7H8_`aINzHZbbV?0Au8zues{j&Tku!baUMCA{(o9#7>}K&_>$BIVIL+VW2;DCc4e_jr2s`=~dL?t1mU3ad2U~4k z?LO)OSv}Q`s16`VrXvaT&&%56wxjXS(ih_f!}ET1Fec6rz8JOKLt+0QB*>Fz9V;bI z^D6BHebs*TW5*U#K7iJBU$(}n)OZ_Y=hvB>$%-xL@&%z~PjNXLxg$b)mKf1)b5sPO zhdBCV5z`C$Xe^v6FTi@HRlQ-!D|2160K7ccodWR*vw#cKQ(mQ z;eQx7_#-j@^4TfgUIAQ*g86;AYmgEVH(DgwbdPhYBGRHCLB*LyD@=dA<`e$hTt7L)!j?%|TfO7L zoQiIY3$p1Hy;ElbQgvNrSkb9^3%iD(TSUya$#I##sldP5e%JlJX5v6bJx|2;yWI+? z`+_Y;_gfQGBZfWj&vsi?oYO+f(p^N!X7{^~Axh+fJk_JZVtlv&B-#WqY$ZJV?d%0X zSF=} zRM8l!da!CVC_~k=e}2*J_-_*jugM^4bV69VOLMlt@?f)0ZWWYA_=wY2TOGxnkvbW! z_Ihnl;c9O?5Y=>U7A?q69g^r)!tN_di4REoHaW{#Zya$YCNFDA~R?d46R1vrL3x>K^?BdGM?U}PkWIWNc8P^zvX zBuQ>i$o`ano@lMs)}TLLFDzGSCpvUjrE@9;ir&mI%(9V#a~ndHdJeq4q$LmKF7aMI zP%88=(v+X5jh~IX&c+>Rb#Nkf5viwwjGF5Fjano|6CaO@IQ~ zL^K6C0bgJe!A3j)g)^WBH#gV6Wep_$U&C#QUt|(-i^X?Aq)=qnTKBaa?uLN|UEuuI zB!y79h1?|{r@;PrffG<7VOI4H97xpw9AG;-0o)ot20FNac#RwgPVGdiUnd;^Df6u) zpdq-3^tHh6 zy81OKI*9HZ(tfs7Z@}%wrwG!-M9V2mV`9DH21Lt5~!g?T&CFo0wc*@fdT^4YV-_&>Qwk)OS2lZ7{eK>m%1sP|S;MlaeakLY-9KaiRM z2<|g~$=JF^UZ9_Ni!`#Pf9w0*h?)RUG^J7qE*|*1aQz&EdT*17)4kpZfJuwVrrbZ< zpESNpKzV=_wVpJSL&2U9C_oZKDks6m|5gq^*`$*1#d0}+)cs5fs>&0aRh8_;z?gqf z7TI4;AtJ}I?RF>sRgT=H895nsT>;~`&H^NvF>8%Z5IONbj1U{(Yn)}Q5tlta6%m`0 zfb3^JyJv{bL5e~{L0hn2l*-Qq3&k!zd`U9Cswqy4yRXi#6n%1O0gEyvCWU->gmoAowOU{KM~r#((HvAo`op;YdG$f9(8q;)d^j zxw^>Ts_iB62ACB%6Nv1R*>rYi0Y?iYYuBwigpfi+z>fian*rgX5AT70(cKmxJ?*-g zTmSL%`#kF$xNRu^`pSmu;KhG^9h_V;u359oc);Ipt#vd8)4AybIvwua`E!JOqTtG( z3tSy=fpC&=;RE<-%f=tWZ64kN?(^BZhQm|>2JslMZLhf9khx>OdIn~(a|@9Ab&WhE zo<`7m_rjr{6FKDd|1xBnP0Xs>T5O-#t2M}*iwZ%Ph4Ovy?+jlGLa`^3WJiSouK4ds zeG~J0i)|B7%G&n4Y{k!`)6klLT6`^hh8hUPGNRrH*MAEyMU!!t*r=t?(6C1(qc4Uy zURQPR0Tl3zO0v#b<#P{d2_s@hlwXg0|`1GIphld<_iq)0R^)B#6I`sbpr9~3I; zs@S#XkL~QQv+du)>b|Z1kvECJs}De(XDc5Y=J*y-Btqxj8xp!u%~WSll(5uycOe;h z*DGw96Dl_nSW%0i%}+VeDH!br>UYjk2_HATU#Lt}Bu+{%=Q%ZsdT;7kd0&b907QRiOm!5&K21!<0u zwD-QnPLfJp+5^;uhtJ$jtRiRU`AA)wLQs@8Q37AQ!*Juzo%+*FMmbJwdz8ro3A37t zd%_A9<+|oK)tokbX7?5sm&YO_15P|R_CW1{e6bn6k|1&H5)$qAUVp2F`GfZX1v8KR zscwP6DbOZjphN3dQTI_cUXuMeIzasJ8pQ4gb7(6NJB+@WU+}Egy)&9rZlxR61}>UiW|mV69AFOu5;in(R20CXc@QqX!%ETV_Nq7 zicefTlT~j%q4d;0LO%LnpANbq*OXX6=ViM}a@{2E?fzwBouyAjj|3m)2QD5`+D-&k zhM%<$EBLI%r<8IzDZCo5Fi}-pB(&R%Aah7g%|MdTN%=Lt#c{Xu0(rzT1;;o6LS8 zs!W4f^ph3Q%STM!9YAQ93OZ+IIqJla6}_M`S5k2aiJ;~aua0w}Zvj5&4@HnKB4^L9 z$(GNs5b$A}>~tWAgjSs4^ih_4MV(a7R|gTstM1)40-eQA1K8G-8}~w4F-sdK4LW2v z>Ba4E_RazF{Q_>ewrqKQM&n( zF-mH~$tz;NeKwjb$>w`E56$O%+_Y|8#G`?;kK}Ud5a8YyfCT0>5CM+$_n+^BR$APv zg~0!e@oP9??jzY0aQn;mXFHs^XjJasw~Zg>0!r6@JqNCP`u=x=Ak%HDdQfBC0efU2 SK+msRX97EO`l-Q%oBstmTnmqnlsvRY_p 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 diff --git a/ifrs17/Images/OpeningFormat.png b/ifrs17/Images/OpeningFormat.png deleted file mode 100644 index 8bd3a0d7487a0a82cbdacf4dd0e68ec56e58278f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19729 zcmeFYWn5d)(=G}WN}*6%+zM^6;uH%GEyW4$?(Pz-NDWG{;*dbm;O-W*K(XQuffknl z#UaSq^nc#>o_p{4dOqEoA0f%k&XQScX3aeFOt_kg93eh6J_ZH`p@RHd4Gat%;4Rk3 zgL}Zsc@C!)@Pg^7A@>HO>=*48@B!QQHTX3KMrF*yD|6shtYbB0Et%WfTW*b*y}iA| z!^8Rcc?1HnzrX+Y@88wc)w;U6+1c5yuCCG1(W9fIfq{X(zP|DC@y^c9i;Ih!o13ev ztCN!x6bf~Edb+fC>lo@7^URC-?XFA0HntFE4-m_%R?LATcrV=g*%92M1eQ zTWM)&(b3T>D=QNd6JNf3X>V^YDk^GeX^D%Ala-a#)6=uDu`xF{mywZia&lT+Tuewv z(9zMcwzig&lXGxz;OFND=2BT%iAJM8eE9JB^XK#P^Kak2ot>RQAP{YB?H@mWY;0_J zcz75Z8vgn7M?*uSqoZScd)wRFTT4qzQ&W?VkI&uR-N3+ri;F8NDyprm?f38BYinye zJ3HOo-D6{8>FMc4Mn)AC6)r9=xw*Lu3kw+;8JnA%p`oFfnVHqq)vm6t+1c5Cetwsi zmveJ-H8nL>R#stQVPaxpAP|UygTu$i$JyCgR8*9mo!!jL?E3mTFfdR`O3K&QS6NwE zK|#UP)HEa{1Plfb4-c!UsTC9y38jCgr@<>%+aV6cdYi0SF+p`jsrdwV-OyOfla zXV0E_dU~p>t2Z?@#mC1(q0okghTz~}X=!OiMMZyqe*po3s;a8q-d+ z@SdKY!NI}S*4AIYex;_S#>B+f+S-eZ|7 z-@iLLI?~b6F)=YcdGh4>^XFf`e#OSd&dSQd#l>Y|VR`)cF$oC?IXO840|O~3sT)rw zD=RA%6%_#i0U;qF4i3)!`}c{6h=9#w$;fE{yj*!{sAvNF|NpBGj0ykVAV3ayZu0t` z7#NSb?w**vt_6VQkpHgm_O+I;2?{Zgn4?T$H_$=L$xM)PLVC{)XT0Vhq?W%cns-^m zZ6%glt7w0p>v_1C?fwH^1}w$?7tcvExAQQ8hX4P^|8WU~-0EIPV&p%g{f4p6NE?Vj zpLeao$I&4otRw`>6zLqrJurX6HLI?GMJpdN`9cmk^2tw3V5gslC`W(VEd5gvNhWF0 zZ>JC2BiNMde-}7dM6Kz^OS~sIc09_&z&H;wvY^;{U>wRwPtUqR4IeD0W;emt-alh? zdsz+TaP*Y0R*BE$3ov#*;~(f1Uhs3h3mYl9_P^KLF$CaZfTz@eahQVbbA~nbqDkUH?!kL{8&h^SM|h6m0F5 zSy)$Oj8f+W`^q7gK^>%3$^QEZ`!cL#%m03s+&+2OiakTHC}#TSq|Og?i>qHBL1>Ox z?Lwd-tMU5LpYRXv1}PKW0!pt+cHTt?ZC~G-@VG8a(3A!9KM_32h$uUpH0Her^!oT2B?GgNyYdDfeQNzi~nHwSro^Evhk=7g3WYRgTiAnd6Y&lB}Q)d81y!`BB zsb%Q8uC_QKMB~;tuaTZb|G5bWxr%=-I6UNR2s@b*xGqg?Yl1Z9-PVNoQLM_|mp9V)iq+aW}f|bh3Zbe*`S&KY_8g z^F(pyrgBG3c%z=_HYB$;F3h3www&!<5ZDxr_}|5Mz>6aCvn*t0`*`2*56J%KBDNG_ zwJ6}sfZ~=yWjr#C9xLH&A}yvH>z$2g3NiAP#yJdt-YS9wlyT0f|BbN11R0Mp@9i{g zzl+{sq$<~+n9l~uJ2wO=AXpUsdOYnlsmdh%crA}}&Rc*%^clax0GWVs@&VGo;q2o$ z?>C7K=yJB7XfAQC7p&uOoaab((W7_;lOej{N-wZVV#vZ0BW7#&k7d~B%-`h+mHf1q zr!?O%E$Fc&ssu@3Q++6I$Wf9f8xj2QKkFF=h? !ko!SkQbywyi)w^~x(8-S(`S z7VqDln;K{)&dh6vH}^4>+O{ChD1eCr-~3xyG;yZM#GJKrJ5pjM7&CPZ5G1e$zzkC{ zGCus1>%R#UDTMs5BP);AO!~jR1bzZ6fvy^6r)>cm!s^dzPjjKh&0w;e)XUw7YkI*A+Y|Ht zFT+_k!dKw1JqZulMDx&Uydvr778iA4(Rvua$e<^;i1JdFE&0>DldnD*&TBmUM<(2U z@#A$>4BU6d;|p14a7wzS*1R_Ch);`m&yToBz=qbb4i57NZ0&#+z=J>;zccYJM{CM90 zCIB2Fn2bzwADvRw7f>zxuCG$QbZTRcV9y3G=zCDElj$SAle5eI`5ON=TNSH>yclEr z?RT&dxQMm%-H%G){B0g3pMAZf!!J~$;bdk`*^NmZ&E8Y*c;m*O;Z+z|U`3AmS20B^ zaD@Ut=oIq#O;Q-n)Q5suzN7k}{KI2{ZD7N0)5(>O7FL%!FTGD9^Bc=a( z^O5X_s5-G(tuIz2iJzcCZ<;mviAtG&|6IYO1RNWDCjMqHXOt@t6!Vpl5WKm{b49M5 zh|eSZiZ*%pZ3z+Na7~kFn^7l3BG%qOvT?OcY!lMm?#EcQ}!ycgi zUmbQfd&Y(0^MnO{4nEPwt{MK%82@{)9do5*a6k;;5O?Z`z4*g|!au}%*EOn}{5)o_1C2P2|Yf;Kllc$8bRc+zGS61^JfoVSf2OL%%LIzMOEC zHR6$(eKlnHWNrZa16=fT|6y&r11x5e8fIuJ0SP*$>A0WC=<2$_ao%WEeijD?*~@iK zf(bvLs;OrZDkATjPRe-f*reZVlTJ^-MC~)3y+T_mO%&>gjZybp!Mw!t#&Pdz_Dm=QR9_@tm8GDsn49ovkuyiJ$ z=Fq`}lC2*kuo^4!i!#P5ICIGChtIlon#yc1i`S?R9K|i0_@5k(#Q3ui$m_> zQDSB3ymi7J?|=lI?4mcgxsTt-Iyo3Tz}x3CjbMjGe0nn(#NYB}WW;Lz(oW`RL;iT| zYp#BFGEFJQ5u~wFRm!w--$P7js)g6W#=dv53OIC?N-$QOEUQklL)_LyBaXz}=uk!Iahk%&m&$q<-JBJi8F4Qr6cM%x=1##aN0F7w=R z5!T%O5+?Hs8h@^l*A`rq7)6>hXio?Q7i3LZVW%8I8}#=Ew*>xdhetcKadxDrU*q!3iS<{%wk<*?9G z%-H_Q=~={veew+Hb%d5x;&5tZs;h=Z1nc{tsX%sm-cp?q|CrY#X0(dJTOIw`1}RG) ztcB#HdHl2bqN%za_7Pw*vj>fPT<<+i9rQ9v_u29J^wdAX(qB*tG~Q0eVidy*Fmf8! znXv~KyK{;uisPtr^~QJeHd2@>ORMqKhLt%bYp^B)Li~wcibk_trGl>@zn(D zxI=2OCZ-SSzkwRdF&-X?QzJF@o#x6JZg`FF4+Z%jaeg(eS)>0tw8MW~wZV9H;>gE| z#&@g6AL%jD3b}N*kfaS-C{3>i?Ky#Re%mDB8t?jG@=Z)&rv%2>uaKE}Nbmmv^Y_=n zB@E&@r{x^0w6}@qOh0HvXoocS5qM?{(dr;P;mOzqTbXDBXv72^v_lrXZb_MI;(%5k zAZk=g5@9vMQo^w_O^x*M%R3u|Uc@ZjtBG0@IF3$Syf?uuy^FBGp+xe*_BHi)@8_?& zUOZj(X;Qu{_QjzDH4luJl@sf_*6hNp&6=c9bj#jgvP{xqA2PEB?bIN#S-5V~XoT#s zu~M^|ealesK;D;rbINzFIaK8n(j;99(wndO4L*~Ijt4KUBe}!@uMIe{(}r`cc|cQ3 zpP5jp&$miOU0vXG+x70_5#2Bo;xHPu9dDXkEZQ~N$#}2yJokhj1;QG?3}&;(qt>dm zOe|Xz|Lm;Q`v1KS>~|ax3prER_!yfv;cr zD2xfJalHCtDBjn`K|7GB_N=Dh30zJF!?H6Uba z=8$|S%APWokTZJ1d8spu>fMe-hDC39vA+3Z3rBi!qQWPrXWdK{xF0n85q|kg(5i<` zp33lWrQ_PzE}mJNPgAbLj6-04V+h!w-cd1;nd-Iz%s;MZtgHaUWYRdB*#;u^_gt$g z_iM1U*s;4H>pv4O9ayX&I9+}Vfe;=9Ih{vnI1*_4#2L>egk*@Ow&yKsYDY~97cPzl1snN%AuMX~WE^*25FJ4RX*vm<@C`cx|AapOx*}|zjAO?ta0BvIyh3RV{JVm#WB#AwSe#Q?|^8?+o zUDI6?KKMCra(+X*;k85{bPynhQyG%v$CW0GMB|sa=E84`2AF%aatwbQGWT(mO_ZvB z_a0UFPBl6V=Fhg=Q;AQ!q^-yl4Z@?fq|=d>II(zHuC$&0x!T@kVino_LAIVCl(}iP zF@hX$2`$7h$vsmAxbo_Xc=i#2w(L2idF2x)t)CJr6>RjfOXC#TALeoCl|R<4wxEA8 z8sjqBI~bP(|Fj%WZNkn!s$AK^=4&3msz`I1=V;!fXz8q{O__B)oy0yY(s;9@kL&@dTVpI?`CIz3mB3cE*t&hJGS1PHDoF4U~4jCMw@8G zAL)4<=^4eBzQ}i~sA_06*&8yGV;%aVc>SJq-4)JbY}BSCXkqH*my(5^T~IPFB3=JT z&(@qh94AtWQJukvyhrNJ*^>Rxrtb7TN2BKs7x7T@&!EprP9+<3W(Yg1gyFiQ>Zw=C z2)p8tYQk~0cHELINnrpX0KgR9l9(R?hGn9XLNY9&oGwYf$D*Q6;ABjn7V1VS7>Dn5 z_@~RdF9wX(aKTO^6!Bn(j8D}GQS+XLr+0g~|xsO}_&DSOpGie|yAYQKgmLH5m_Uv7# z194`Mr7mV#)jy!-BduS84(=PAb9Oe>karJ_I48C4Le%G&bPAk))UDE3V&sR%<>${a zr#ze$fQEz*e{$fy89HPy!1&Dv1i%mdE_El;F$ytu)|~Jvc6v=*S(kQW<-5}EpIr=& zMV;QZIFvKca>1f%((9Gz=BZR?BM5y?pYD9ah{;V7BU}>J#d1QUJYeM%0q;KZY{qk> z#jv!`do_X)5>2bTs!HREB5CEw7)$Df3$}L14MRBhBajr9Si)5wR^oFxWVp(#K0Wuu zrsu>7rj3W$mULX2>h04^@m3Y$Dscx?wrW$n*{;BP+FpWj{T7>L6-&Zp{?|8HVsQqC z{O>lj$TG!yl)v#hoU#yXV4wdTQ6+RhLz^1~MnxCN&wguY zUie};1)xKFT2rPt8kCcAIM4LS`Be-tx#F)0RYS0SU*0qll6jP2HyAb7QT3Dxn`6~n zvCN%;*~9%uKE2oz;ao!ukbJMw!7MXxz$9Ldoruf-ExMr?qG14@pBVT8NN!lX{bXmy z|GKFxE`#OTv;AUN`>N8u$)4?NakWl}$U=GfxJlvdw|{bqr1jenv7YXZW|owWI67Vl z#w{2g9kFd3cw9TVq0J#U1z`<^bXrJda2Cd7C7V7YEQ`bT?L=IB0mMKgq>ppX$HGxc zr{2e-5E2Fik$1aTt@`R85W?7Q`CRq(Yd^bGD^3}(D=}20gr4~T*hvJQ9DREj9`5RQ zMc#)%O#2TF?Zj;Si2vARXoL_P@Zxyi7#~a^%_H$8nuQ~;QC;8{&*1*%=AQ>q=8KK_ z)-y!tG=9!Aj2-Jn4r#&?N1k7VU1D*y(UzX_x1$^rJ-4_RxQ|s{7DVs_U>uPC{`8^g zK{YOh>J#A7!_>ytuB#a`S`kbGZXe8T0xKHQ%u|-SYrlCuI%+O~d#b1#D}>Y%lPvpr zakEOCH^pxg65Snmk*drI>{=wj2D#-W>PkB8(6ovl}AT4U{*o+9S8; z--b`(d4o!LRVjW~+mn%H;@<%oIKFg!L%-@ZPph+`LmG2E^J)6OSVYGqRNm~SIWUZ4 z+ufv6+`$xfSOnF+1wjw5;Fs=g5A{5g#@P6mJ|KGnLN>-4-jXTMvvf$NV_#q8BX7y? z?)Sw3hL8}N{0LXh?aC~?uG~L&s*o{Jwn+e2q5#RF%m2e-1Fu5wR-Y5*L_yEO>LFXJ zw9M75vKnioDj!=$ z1fz8WQgWg>7i-6SF1|5x%DUTT{8n6KisbMOFg)_Al2OT@`|_?C`&ZNnS96blvauy% zpsW)4pCG-&r%w@pTl6sZSdORX1dqTPGtOIWf_G}D1Pp4FQAxlxI=xWl|w zy0LbbOm4^7`sbqq;IU@rE#vs(G6nx>Mo#6sU4wOO&tY?1KUZ@-rzkVc;gK59$nTl2 zUv3X?Fcic5%6~NT^Q6+MWxzk(HTj}x=3at`l#Bn7ymN7Q?9c`*r54umV5dwf>jZ6lhXk1*2Lwg%C1JASxLcxqgEnsl-VFC>pOu`unGvq)&Px~-!Jr<-U}8=DugH?zC1-~+jyAE-Oj@HlbmHZ8%Ztx?=J z*GSoa9Nbp2P98X+R}iGr^&mG~>5GhJIj1K-Kg;OCC-e2+IP4_^O4|!{5;J`}&P<7Mg%Z?I%^ywfN_4mSC<1b}q@r8DzvR6#JR z2VYm!e04n&jEY;B(QB*L{LZD*YDiba|JgCQeeV-<$$3Rm_I7Y72_hG%KLeglZ}i0X z+#p^5#X2Zz%WaMWWQ=~`A1Ks*d|gY$Z>yk^$fsPLVzLd*PgU2c-*KRcsn;QhD)HCn zkTkc2e@}swit-oJT|*gAC)Wv+8G}Qjj0HY@gx?KED|$%Go&>h72Z27V8YGu)3qbB>wL{vbJN4^Z$8ozC>h$^2NZl_nzPn5WBEgEx5scO9U&sl%tVHvX|{% z+J7}pk-!XnouhWkhbc4!S960^H#sY^|O}@T=2Zs z5)A1x$dCrLy}GG{%0k8Zk%q&omu>WEIYlnbBut>GL~3ZD8b3ce)6R|#J3_*5Dh`94 z8OV&uJGImc3XKwm&OWCTn`~g5WOgQ3EcRFd75G@ct?|l!Tl+>pwx7&(B4DY8GEP1= zKf+m}z@8^dvle0hUHJ7PgxgD9GndpgJGL8UXZ4qvda7GO6#nH-&xp;S1JaBj{Z<;T zve`$*_*Su+bq5}24xH9YD4pi@!MIh1rT{eVuQT)S>WuY2&~)ybaAV3oyi*_6K@EIQ z?$7$IUc39B+U}K*r#5QGR5LJw;I@GYxl1c&RiJr+?yol|e=a?5!Mo)?3y&7_e+Zn3 z;>FV~@Y&f_l?J*yH6=mZg6hsRQrH?F>aaHYHTZL*D!ySj%GkJ29q(&>mobqxWp2^> z{rQVKee}*7)22}!Y45)hms#P9#dEk3kV2nMY9>O@>Fzb-(icg>mBU|}&vV1b%t`ho z;B};R-WM|j>I^eWx_&%8XS><%?9Oyf->260dYzf-fZ5B~sFZQCOSQ?DVO-N3;G3m{ zbuzit{v6bf)8D4F;q-&X#4`Z#u>+7}1LQ58h4pC~a1DV-Ay$hII0Z_74#w&~`UGSz zCrOI{Z>BI0Yqe}LmS+%1%9SKL5I;+9m(%F$RRFxK3*uY@tM$8>!rmLmbskvUWx>R* z>#v5Qix@FIh=3H@H;m>jf5hDFM|%Avv!Bmfx2oSj;Y%4r)e8 z%k_+(p0?x#gmNKJGC}ge@nWZPEq@Z83Zj=RZ$H#JHt`I)in{gw?lL;oFF5<8Put_V zKLv>rCpHKzx!pQbeaDY!;=gk|YZ5B4dHV`T@V?+X+lIoMkxhG$ldirL&Mo0_dU4EM zbtum11Nc*1=5`2FlnIf2vvhq)e;jN(Y3n5-J#E~&3cA>LZ^_2mWe%)DE@i4N#haUO z8=oyny8GHRD*LH2bxPFA-JnLVMO2&o-yL|Ssxr4vW|;d%gyo6vU%mp2jh{4*9nod2 zt+`+qysbuqb0%ke!(CPX zX;64NqrdnfkHChqoEK^S9idnm<_o#(TIBWW+U-IN9a6{YPH^NzYBX8vuf69PPJ3wtO_RxZs0WcX|r*?5f7StQA%6K+kF`VgwkHoJeA)JvaC0;e(0A~x8xs) zR9MC#TW-3jUgw?;O3K=#OK2G#<{gxYCs+mPm{Eo)iDmWk4LcL!I#!Y zJrg{>FX?NQ!ChC*;_fPP>+$Vp zbQFBbmLwD9J&X1S5+XIbI)M|#dtQsTGOy)WIDN*;Zo$Ik)Wz+&&n z+#ZM_ZXqEYt7g|@_IRs($PLAB?vP!XK^EPD-D;9=-?Z(=#?5vwR-@)AZn6CFS7q4| z`_Azr-TPU%2r}*OuEz@daplw8eQX|MhJnSZLhdGR{l5-hWwGwQ*l!I|=uc;KJr8f# zWO!?RjbcM2RYEd4zQ1A<)zMHAwF4KleN%bUP|QRtt~{&V#Ak@`uKWeD^ht*WRkA6{ z=7<0C2#+*9n{r@Cl~X`M+fO_zMw?VktVY0C8Q_r9*V&p*VW=XqOuCpuN8hN@i_uI# zq3g9mAenX+j-hMWcxp#7qF#u!#6SIbRq~Jt&o|K=!pW<-4FdDNskVg=u)>h{c3tb| zWq#GWR~2*m)k6~QEvTxfGIaTme}yM|%?=-}Dalz+d-zwGuFJ|gZAi5luMeyXoA|!Q z5n9Y8o^0Xh8rx;>>n!VLTIp+inZMaxT@g8OYF^-0%d;zh>tNQPTm_N?FZXoZ1)H7p z$D_lizb=Ew_nKe#&bxHEq1LY3$Z0Be#oOxVRG|EDj5O}cig&^y{t6+#!=gH`Fb+p8 za6i-49kOz^rLjmA8rvc?Dok|%?nUt$A>PP7rh^P95@saKk!0=SA;7YhB!1zO#+0t- z$LmzgB-QvJ?j+8SUy>@!1S{Y4g4bk?6rmKtyF4X3XAd*d{h4Gyuw3@YUvZB;J6))c%zW(^8jz3pXlFXb8udDeV1Ke&Uts zzB3rodoh^UpG9W&Q}=Rd7v#~H=PJ;TS%#;EH0Cub2hlT?kY%P1ot{Dxx$Li)9XYA` z%gKxM?ITy%+k;$ir~uGH8*vTc{(E-}IC8beS` zX~KI6Shev-B2RWaJ;^02f}{u58@s^aGn7?NX_bwOC`m?HoN7s=VZhu+w`$ua#!P>) zOI=JH;foCm00FSo`Xfo}{f5495ikE&%|j@j;8Li`)K0dkgfGs_!cC;d?y!ehU*jup z)LOBli12Xo)rM18(8G7*w>`Qla(?Xk9KE~j?e0#vPe0|g_!-VeP-q9aY)=ynT?!Cg zR`b5SkU1uO1$4ogDnE8WYeSZq7O^5kfY36Uo*yxeP%>uWVnCVL4jzQNo?+RKw&loi69ThN_k^<$-T=rMbR9 z=e@UU-&SJJY%aE&r*Xt`%unpFpuk+kHTYhSN-^398n@$$mHZwyX4|7DZ$<TUL>a4Rg+2KZ|3AZeKgrGc$3{o4(izqGx&4RUVHk2SlqNMk!XL#zo#f zQ{81<3ft7@A&8+|^dN^wCQsgk;=Ya1n|4_z$BBw5*V`yoqen*vP^Q*!qF0=+=tLcH zjuxv2l&|}FOCk|~)K?zP2QTdtMkCb8QmKcYzp$8Q9N%D(r%6RW;@nn(~2+-9}@%cK7Wl;6h@fixKBJ@_4> z;@SV`hT<(`=;A4WjHzKx-4SyD;>#h{-k_ES=Alo>7~(x`n^=zRQ&}2Uu2~iC$3_qrEL_t*FMdk(YbV-3aAWg&OTlNPK%3fa-y%}1 zq|wyq);zY(i9=QHi1e~R9l&oQbVDRy^z#nkI5+$jYprhVOb4&Yh+xROkXOmpSZ9AwE!73ZwqP=(A z+;HdV15^2Kny+p&uwF?TWs^jEUK^UX`+eeNnXqd9$aDXt{O%=`Yq#hqZh+^sl4gpZ zwRsOSv@%9ztjdq0(zCik1IPD%B6BlRCK*U1KrvRVS~d2L%PthEsdyv0gILPWuGOiR zq{C7dau@|aQ>|r81UMcdl?_rxxBiGG&6p>LU!-^vnKg6DP4Lk02Hm|K`c-abmv`QM&WjGb4 zHHeW54;ovxnuewu9uuAP_Jm!qvT8%ER=uAC;0?KIh@Y%!k$U!ygO0hu#x@N4!*QTt z+w?>|2U==cC{NoU-%#guL^(uEGih}l)j$s0Kv2PqO$|CCvN}0Fd`^euB4K~^Jd(Aj zomUbsZEI7^{|+5=O<2CT0$g^$x7^fl_#y;Rn;mj_o!;V&9BaeTIYQ61#cRMTPtnj| zU8+?6QPuoicVd&q35^?BdZ$#jcG5<^V1w$j5AnOZ`mT_=IHaMARk%q5?l~*r#|Lux zPYa$~k+{sy+;Qlj7|yb$%w=%Y9Dg!EYu|x5!uEEGZk=zYOQ~e9mqxuy`<;Ky?>i)! zUB%mk57m>kJ-LoSpWMppJ|RqQ@3r@B6x9{rx>W-5T0k{8g5%5x%uHLUIrA7s2 zZss5bI=(1H_xFbTanXXYXC5H$W2yo7ufhwSBW7$t{Av@FFJL9td^qey96{xpJiC3(o$7vX?e>^LG87XIvy5*+hZq;v#3S1CN z(%~w*eerpVn4zrlR@d3(=0UZ3k&d@#mVab|@ovt^+2wM6L`?kSc$*FQ7ekqa?9Z;U zbrxnDYi@2nVBYvAXfOEQUch8Gvt9;rVuztZ(4LWH`(ErZ)q8WL{|U*F5)Q>$l&6(m zJxaoW&-4E#)Hy3Gff?DzFL4dYfYdZW54yDG8B5NWsGBEH|urBe6Cw~eb5FTGdVCm$ZKTz#gFK(CLstP?_Mc23@V zceotC4skFXSvU9$C|xB$w+n2L4F_k%VZhJwEq63)C+&MB|IBU6l4R-^HP(1=qHd?2 z1%T#XSDz4x%v@yF;k@;*5q>L8!t}Z1mfJlFvHfev&wxBRmyTmW1IYWebS%ZHlwCv7qU9KvSMbmMbZetv(Og5T!)Z?dSN8%%|xsYRfqOCh}WK!)vmuz>~O(s z0t5bWHdbUr^RSXrw%>;Q`Vp2Y*LzKzm+Eau9);xgs!xM|*cTo&c?OL%XW+Ti;jeH{ z(llZx)#?8^2^bu26@j$r=x0AISs=akIYCA)V>57dGr4V6CHPOj9q&GIk=gt}h2CWz zB8C~e)~(rV?|U4H4E^~|S0FNA5qjVcfZt?JiS*MH=OiplFFwEvIh9)-S(& zRZf=qZelz6S-NYhd0aa?~{u6D`AL0|&Zjh^s0ge3gmog-%)M|WS z`!3q#?$a7^iYv~?W0#bR0oH>8<>ACI($;-cjLNAwpT(w(LF;Eam_}1@(3g zbu162&7qk|0+f}Ntv$1fmH|jJOYhYWfp2g0Zyy`%npdM2cZ9YOYm+w>WsS2L9Sve! zr53j!gBzofij*U>lVJy#LBMRD{i6%jx1p(^FPEYKk0AU|a-!K{rKSg=XCSVpEwcVu zZ&!MP2DET`^4Xoc3>n7s)~M>~q@+r}UX|rCeA~4;(tnq5{>1G_$r&$e;Z(6OMwoe#N73V$$16g1lOmdP|z6=fhKM^>5N_J_Rt3$2c*_AfoY*F>X6%>;VyMk(j z#uL~5Z6h8l2Q&@o548+J#PH_-2#4<+`5c>_HJ?M z*7;Qny;b({tq~1A^nRa_5rV(%ya!_R?g|SyO)$3^nK=iS>=T@p?44)@#%$D2(|_I& z3qd|#$SbK6E*cA!KU_C0=I=Y`!Ph2gw%RdeY&F`{H0(KB_u=fW(R&g~rL!HUTf__s z%eD!2-4Eb{AJu6A^wkNJMYDuXNY*O`5$X;4dwV`vGx zs@;3q0jL&lhPhXy` z_Ljw`!+qeG-UQ^dTY7Ul_sS!`51)O&hTB@%d1pZh6J$}MM=?kV;%gq$EABd$e_&r? zCwAix-uJfc3B}gq&cfng<~vh$urq4iG1ffJ+fIt(jo=@B01F*oYwn4nFByuWX+96O zo6U7INAqYlOa#ZCqj9GP$5b3|q|f3$K2v=udLz9FevPt z`*n#zo}-INuD%h1+u273z?CiV)HZkoWo~mrd)Atf0y6XnjpKyLU%PgC`37^J{~!H@ zVN4@oxL+&3f4FAz`P@-!A>;t9T3R zjm6!t7hmp(6sf|TtHY`TJVd#1=7Q3js*i#n7<2M^ded4-Go`|#5q&&Fcjw)|^fbL9 zfRqAxOkPi;ny2!daI%0Sd0?18xd8`2u_$E1JhbKc7cy|YkI99a$K9d3(Ssh(tdgV) ztpU359d25(Iu|Dv_zxMCfMVbVY=Ze0ZdgatxvF#j?%szKY3e}i7YZ+No4cig=LT$7 zobY&5oA&0+27sLT-Lxw`e;;n_>^L^@gIN$Bj#JK6y+cBvKnu5JCp@<)T$z`Px^xxa zDLaJjAyCWukk#qjg*R7LU012qghwyXV|piUU^$@D1M#j3D-Ber)T9udYoKJ{{b zf$Q><862_6H^#uC6oRVz9G|sxtPY9QB=p?1#^s)lkZ4i)+Ww19%=#Nf@N3cAaJ&P- zZOIQ0ACZ}L15oRn<*Tp*u?FoqZ9bFoVZ5ZSQu^K(nBRA^QB&NoD7%>{a2TD?Bx|uM zXHu25qYLcfm2C!R_0`Y9(AnsmeKqseMBR=5V6>HkfAA`(1b){R?ipH0=&yNBajsdB zE&DnOHfOgSpI)8*EIh11=`Ri~PT(6a^!oSTUs(l68IMF}qgOk3QvOAt!@42ha=Ap^ z5RZhYiz!73Txf0%_;qoh!d;rw!dR8C7LBwxgO-g&ML z#g^LK_Vv{TN@~rB%&f)Q`V1qv+zSUNsS(w{DX1>#Zj%OTg)&MouH6j8PV{kRw!-J& zULJG!BVi3jhUHjuSNWnqQ=V7}>=1>it$276wr^eAy~vE8#mHm5!*n9RUAlw8o6BI= zm+lSz%v;GYqoUe~^rC!l$c?vy=wjz|F~X-)n7utBs(dnT@~%b;GE~(schbOV+zOWh zdgt||7qxbs-tvEXEt35d6{;xe>Tmw)9MoYfVm_Rx-)ROjTtX{UxcpTXpJWy74Tw(< zj$56B0+lZdUSV^l(gW@WSJ$F|zapWJc|(%VRvMHSXa29`#S8(khCcsyRv|XEn6Vn5 zAUz1a?+GZ#$(>#$=!9wX@mz?uI{*wOfSUx=;r#CYe`g~~*2>7b#E6NXwE)ttoxF{@ zxXz|-;=R(F^X6TgOy=EEn_3A}f~RCzVC;>8?*GLB*w+!|lvz7_DYKCdL;?H`jY zPGh@WTXZyezR^D}`Gs)&GG0*w5a7?jEo)iybJoGzBpXWn{T7cV^QNG9k<&cny{oW~ ztBZfwI_uj3<5-a>{H|@i^}$Vn2NNTzk3!f|vKACP!Bc@yoPDvFN+HU1Ogyt2UqqLnP))!vUJi;0dRiD`C#j5a_Wh7O$-@K4>(*E@>$x4CHj ztMJZe@Ue8JF~0}=`|gpwT>%EWEQwi~yd&~?*%6cggABfL^G_Umr+DP{c#G4=5fXm*?fUJ{(Okq9uMV0`b1x;x}g`M zr!m6h%K$jtO_Hhd$1u7)_r;J{zkP#pPS8lXCJTzkc;b*V^kO(Ah%G_qCg*tq+N#jF zOnAyC@z8ZF*0c{edc7ixRc z>=jS%gGKQ7n@!;d1D!k7<5V$I|L=#9*k&@K3RwSQ+ zq?-DnDX3)Ls{3vjKd#I*{w9XPplU9}E5$wMnZie!^clv$$;*b_k85F`btQiFo0x^F zRXWwPJ?_w}OCySZk#&tiAj;i4e{L`cWtV>k>o#JjP3~V4Y07_eoErTnN=o?uB%%Z|+vLL(? z+&P}etzS!lI4Qv*-W~D=Z;kh*+s@+cs-}XzVb2)58s`(y60x6k)i5`?>crkS&I>98 zXkcy|>!2U~=p`xV{AkEOCFi)oC>jP)sq(bjU_`%uxn<0;bWe-WCIMt;H#J{MQhcSO zVzWSWPy1hRoxn;^U1X3Vw}tSvtsna_b8M)k$`&U9wMnh{Iws9wVz@okSc4CSRO`KT z*4z%Qxj{!BtT%2br0I+})onWr zjlX4zmX2iAjc9qh@@)MD@RFK%_C=D zkBhfcHaeP=j`(qg2?w*urm4 z0JN`5f}Wag8L(1s);fEd5LUQt?2=8@jpf1wDpSI&kE5A}OP%(s5j4xXPa;y&afga0 zk<6!KGhmnu{#H=c3jZgCkP~8(Or^c(Nn;YiLM3bjUpevK$ngBjRJW%n*fQ76Y$(UY zIuszK7zp|q@5aM)ZfY|ojpA*#>i;rNaj?8^5Hb1tb{}7RT=mPA4EKAuYm*7}YzE|M z{-Jahb%~j;;oA>Xs7*b3i^2Q_&!$Mku#JiYp~$_S-KZ~aJ5@b(_vvMN*;Ms~UE*Zwhh3zrX6H1@;YpWiEc zDU1rOTEKy9&Ppe;%gBGoSI~&G9kOxxdJ|mM1}a?)Q=IIUB-^K+3_N>rQugIMNNcSGmt+^er-^)@U$f5_esLjV>jfi@oyC1 zS{lk%<1$HXSvJSdvs-1(NKG>m*_#qw{ru1Sug^qxeLpqdC_Lx>?84UW?0ae~aSQLw z7W^aP+3gP87Lg>n;C#wTz4NP0Zk`Q`5j>-Dk43%P^uCw&^$SNFjEdy<-j&Keec~SX z+wBE6ZLY*bElt>VZ}C#$S%)~L@dWqCXsepv-1cvGseFI!mUnv++%$RD%g0`x^`ZTO z=BD?He_9px))sAE0jln&&0siOqIUReWT$Up+VP{NW|x+3^;`?w<{2~5_xs(mWp7Sr zly!Loyub8HW8KZ7^Rr}h-kSJiUz)Y!7w;_K*hH)1ru7V=kA)V!ds~y+^iXQ!CA@HoVIN*A5-&Q=Mt=UY{3Q!)5V1;pWVIVAoLl`OKXU&(GJJ@%;Il=G63k zUEf}xmpa1)Tr@K${n@S8iO zV1Py7Qy1g!U(-3mSiy0=9hl#M0d(iXbARzOpNqd8++-Z@`ul4-ZyF=#hA_V=4D0** z)=Vw}iy!^)^|=^0-2ijL{{|HYtpoqN69yn1xTf(j%u|~a5FnoTjp2djAx_p(!8Cq` rc}jBvXnqjNs0AY=1U}f!diJ0F=i-I#ArAZML7w(>^>bP0l+XkKd=jpe diff --git a/ifrs17/Images/SpecificationsCSM.PNG b/ifrs17/Images/SpecificationsCSM.PNG deleted file mode 100644 index a04d351d21e730028ab328c8311e70b0f77f19fa..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 40913 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 diff --git a/ifrs17/Images/SpecificationsImportActuals.PNG b/ifrs17/Images/SpecificationsImportActuals.PNG deleted file mode 100644 index 7f3d5d05a460fba884f58baaeeb41c84a4617c0b..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12211 zcmc(FcT`i^_iwBtVn;!wS%4@4QBZ^k1S!%3O0OA3KtMnw0i-&L1?eClNI)bIIwHM= zQIt@W5;_4g5D=3PFk%QT;oXFB%J(<(d%w5ddh7j>b=S?k_ndw9+2yl8`$U++b$9PP zvJ(UX?bg@Rz6t_uMuR|`cI?;={3DiZVg_6``Cir41eJ7(Qh=MSu9u82fk0)k{A<^? z0rz~j^=y1WAVDeaZ@a z?T51m`F0(=d`sH6d&Ebi1x|SB6=z#@TIi9*ueWydCv8gl_S5E_x7woDTdO3mR%yRY zzA2L+Yx7EqaQ|k+ikAMflc~9$29i<i@ac)sN-44-gatQh0#e3|ut);^5rd);$D1?sfPQbQ5qndQlI|y}j`hWh-#G zH+vLN1PBx-h7sUi-}LH1y&D*pHFq2fk2}7ZjVVLU5vw6;#C38A z*3k1qx-p{1{_@{_TZHQ_j|{!l-Ubj9kQndaubFwwcDbwErWbSG^~4_Pbe!%wS-@8QbRGAK&7AC*MbW{ixU# z9yC`AzBN*DN_FYC2iLkX)UK^_*b`qTnkS~(5+^>UDrRTeTGkE}j(@s9QXPR43(@v} z3bPQeH#bswdKB4fd<`EXb|UrGgR0&|cU^k^n46+MAs?48oa41?$FUp9%fI~uJ1k%G z+x@S})eY0PhPUihJtI@zuz;Rdbrs2s4O=76^z~O&%{9)4%&X9zRpXe&*&*sHU$SQ^ zoR$eGxN{?!q{|&Lu{1}Y4~J&@M66(5rSfEP@_1vAE?&B%6rY8!M$raF=+BmvSL(M!pl1X{qLc8^%4rh4aJb%6dEQmHpR5Etq4+&}V)~`vqp(fvi zzRrFfI>5wVr!R#pVJgnc>$&dW=jYGfyIJj9>j?{e#|jC$$try(fv@-yl<$}n20kjO zZkbE$BTM47Td5}<(~3SCx;oT0q3prc2fCs0MYQ_K)%lJjH+}5nYEEV-T1}cc*tKKu z)8W%qI5^adcqApuaORgSKfNoi9zT*1x#8Bq;!$A4I^O7wL^ne1H!4YHzf9| zWaG&ds3)d(-aCEA3bA9Py4}(adI;w0!Mv zTd|5TX11IjxMDkZzvH9{6z|LzQ_qJ|cMJzYj4dsN8YKuL1vIVnB#dIr2us5JO;qB0 z9|rS<0oE(XE>-O^OmWsVO0G(NT=zv)i*p_!-z1Sni!#t)n}&_t`?1At$I%I5b_4V& z=>9j;Nfug_pQ9g7;Y3sUl>xjs51z^t(^ zQ<@B^a08Tc5)Enis)-%`AeslGTFLxH==|r04UW)&y$o`Dqd;$Nr%tjizy;ZI0RjUx z^J&8sCeIAp8-{Fi<I>qg@#|d=k=L-0&q=hsh!QgZ$ZPg$_*_dM9G|Nt2$yZpnmX^ZFc}<5( zcyet+f2O=k{o;xQMe0>(e%Ps_KejK;0K2uL{hf`y8h|Eu|Y2htpD-2Jc)2!8-#DSV!#!x2d(H=3Vxm?o2 zl^jmapGuZNKOMVnC8-^XPO46Vw@n*VCy*gOOMua#mP#4hW{;!EuS^o{LV|YTKH?>` zAnz?d$0CTprs)y#$yw{$%@wGbE5iqW81R!%xyz}BiAspvC1PXQ>(rxn+scPKaut07 zO>(z(bR8{l@I-*0phBvLa846RqqaoyIE;GY)NB0b?8VA35`?sR zxr=dS?!~{#wj^%jWh6dXE;a`XPG!+X~k zn1Zyyieq3t!){Ytr}jDPgv&Y)Qg-r^SVe~^W`RiJ_$m9%T34PEyQ7a? z$>%6-q8Mq+M|9t#VA&<9U5At0&^igiDW{~LRKYz1%|CDJU!;)p6X6K|kvEatbj8!c ziuMwv7h9M^i8F-ucjadOtP2&0tGJurJJ0wnRbz#9Auof^8NGHs9xecnU8J)l46&gs z?@gv-0TK=xzbhr7^TK#Qwr$!TJ=aH5!3qYG4QHqFJN4HOj91ucQGy$)LDe1I9%T*PU1(JuE6>ZJE~#01GZi?6 zwnSi6Cd_I+Jy)%BrYHqBg`0{mPmd7>R%*n8j$4a7B4I;YG~E>3q7vawqfR&Zx%$14 zEc_G+r*%xI)nXDMk24j>F2{9(BgeG6`7zqvRsHj*EhU}}Mef7ZA|1tQcMmojVi#w& z^-)(-2_=7-owNIMvYg#z@vPSUQ=9H=IlWLq5M(BXJy6k+j7a1tbVDHlNAv_VbvhoU z=#X+DRu#8Qb~R_55fr#`B7>6N7wg8u6ueEk-kWQD&Bv$A)*TPneHY`Na_F1F-T!IQ zlIXPHw9hkV?!4sWd`$j5=xeshDoRp}4%PJ^wTOy`-{ip{V1)_DrvQeL6NMu4Y-RYF zhHS%4l<{W{1ui@F6Mue{tF*c-HWTv3h?i!@>ugRnrtm zvF@MWv=VAxzuxCnJDvR6n}jR4QFXJadOVPpC*k>*fm;cu_J}I)Q}P}c{l{F&m02FG zsTl1)e%Cc%DqgoBq2VTM1d$>P-}1+rg)zRVimshe9Fguu*0{(XaaHRixKL#fDTEch zn9Vlc@_SqZ28-+T9WHn6`clPOq!XJNWPBmPD^IKv>(|dY_orCfDXJ2mG=G4&>{5l1 zrm(O|>D``KdVkEwi-FnPpZ+?zDj1%=qf2$csAeW3=p6tFMa6@^zU?u}x$*6H$ao^Y z&qS`!o@U_ka<&3$orGKUYQc;#EHU7}G0}{GhIi~+wLJZYgo+zdrG|kx~Bk$ z4WewlS8`i?(>(%kb1!lm2>Ebf2k6-zf(^)C7WDFTx-RG?5?I1-*EfM2CR8_ravmTB zK|=hXFFR-UgHDQJ%0V^OAPpee z-!23FkEhC)m6v~1SW-v5g%mF%UAQ%L#&$2r^Z+mlPz`lI3Yu^9M{=HI-vQktXh8Wj zg!n-B%+I|L=Eu4~V?|Z2_Jcqte*#1U3ap!ks>C)~FzDG%U`aq_Rq>(APoaYkB*k3^ zpcseO!*CasO)qZ%i`0N_dda`2@Av2ZLfP^bZ>bymhQC`i+1SBbRkyG3amR60N8Sl! zKDKLqH|GhcKTsUq72nCZ&mA&#FFGChDv+F`_Fo=wcknZK!(Kp?k3VruWi6xSKdH5~=mhUIWY;u=qC=7#Nn zFp3gf^Z95J*Xfe3a`#;N%0%_MHe%^cy!T3gvfmgY{6waMfa7xC2X5uH9FfB;z^;^o zfK3Cw1kzLVg>gNXXLV#mN}XrhcQgN4zEf&?GXb6H0q14a*FL@eS{WN|RT>bajH7&e zUE}1W% zrLPFvevaSmOgOz>#j@wMQaUf}X*?Vg z0@UPFXc3@TddYTc8VM8n*Wvs0vDc615hrlC>k6lO`gUPGB}ms(>_?yoaUjgKyeQ4w zsSB%Cl2xyOmf}A=_Bu>QumM29+xoap1-;sr3cz+95^a%$X{x&$s+-dvTg8iJfX~Q2c*ZZ|l#pru z_L|YRM5uH=WE$a%my5hO+KWz?DrYvAY&KL5W)A*vy)P3L_=S=)mZ`ae~XnH`%{NBs!Iyb*h z&ux1dDq6cTHt~JoVnM>^e-$pjzOjV(8;AWo!JyE4Go?c^8HEawOyvm7A26vO>!dUN zWP_Q_6P3DNg@1qsAV>qT!e;v^A#<*}?l%KQi!!=u21W~>t~SXHsufLH5)2X@bF8kb zf?*WVJ^s$2UY?caf-9z1sQ%%{xncjG6r~>zhpnodV#xVP(3`2p&~%l>4|^Y()#J?m zsD}PcDe1_SJ3;F?W4430a{9{yQY-9c6D%s74ipe6p}D>7@tx=3FaS@n-ytjwonLYC zGmUw<=AV{9o_-_mS3gR!t%d}~I%S$ydrF6B=&e@LrTcrKg%?g~C3Gg*4Lr^ytxvn> ziv_XfcGCum`Gp*iJ;P3oe)N&oo_4-h(%(;RLF@s~TO;I(cm11{9f4_4PWXJ6*h!d| zVM&0Vl3mYM7FC@mx+xUs9d~j=OXBoqmPLoZ&Nqwvlu?{ah`;R^F!3;(e41ik?(%8a z+4;z1{@<3;wZf$7g3&hdcP=@6I@_afi+2WUCyTb=1R3RpHE1f+DYItO-owD=yuw4U7%7+^B!$(P*@C?2HrIhm(%bYhVMuC`9E zQUyf>I@~2ZFy#mUigWC%i>uEyd7|F|c)AnE$^FHvw6Mt-$bx{C;N1} zl0`tls2W}^_z8k=L%9xAX-N@{ZXTOTIXdG z0LpNslMiNR>u2sXdF$xwDXm2{h4qu9H+;eAd`>Syk6AD8b(RBxb89i1VD{2x2XG!^ z(J_!FU*Xa=$>;SR7D&`(r%NXIiOTu~TMWWKa%v)$hA8hniNvZ$bUS(pGMF9s z!6~E+*=UW~2~Rm&=48rRyHGI>W07b4RRt}(4)7Pp#EzIvGC9hHj$;8W`0BaZpJO|) z{J-x;Z0KCqI~pvc4k$JQLut!_W2iw3sj&byw!XQiYu%>uT&h>;f#*Acq-tphr5|_x zq9cwt-1yt!0#_mX{@CdoqdF=jg;37sd{pTAX@{E@uyI`>AgTkRtEsOCFzdsD-?g-g zV^emB2(ZOF5=P3Lib?Dxn-_kwAup;VM6{Y5Mq$O}A@7}}sNyC&^Y8aM8_hD{f$Gcn zY!cho=H~DK9&ddUU8Pu21ogS-qjs^1vs4g6?|8zpVLh*akl->uR$|XCx$QFXbLBa; zS#~-H)qRM$(7NJpVVLN)zVny-Uyz@jDluk4a$#@FBa@r-`W;49Q9>jip|5py;>4!1 z1SI^$Gk)s17HxcU$1AmQYx7C`t%N+X6w-*@#ub9}WDrjm4sE!e6_HO2&GEE6ZgIOV zDuRg`Ju46@OO+%_JP5d@vsPzn7draBrtIc7+b6Nr1NhQvANmC;l+mL!p!7VQS*IL+ zfmD>7`yeBGF-d>r#%iCkuS;#y?jKgGH&YWC+rIX&JyKT;MI%QR?jNjFe_s~q5}Z}( zm$YwqEU+Gg7rKoYqy}U?g`|ah8sZG*wxIsWKSeZ|DZ4V@f=!fKU(wtq(rifajm77{^n3 zf=uq3xW)qDukNv^$sRQ0YK> z)Ya?wUvJdSoo#WF>`RVLggsIcbnGNEgfBRT&XUU_dg_uSPjdx>N<#<88MHY|JykY1mIpg~)JowqT>Iu0>(2u@&7GopJ^;6ch!E-}&f zNd9%GUD(-5=!%<=v7NUO6@LyuGk(H}K5wqwM8lGm#09f5q2l76R#sjL&Sm7A%v(j& zk;qjF@ro)V03H}~{+Pw>Tqcwe`}TTQ+hLIx*0bSat`a6=jPq+sBabVm8D0Eh9wM%! z!GKvZGyiup5M}GWx>(1aD7B+3j#dn6r!S56ZD;z%uj}uu%OslG=6`|{Tu;R+Cmi)H)F}`>@h^};>r)(NVJi7^b+Hvc z6Ef`yR2>_I$$wyJz@H>3eb{%gp%ak890irdhwJIzVUzLP66>EZyNe#-lpt;i(VXu< z%1>_BWJ3WYVrlqkBR>3B>;nj^KSOa9-vMCEsy`STUg@IeDvYr=6$TLf&OHDs>^m#$ z4sbNrCkiFRLxf!PH^}aPm0Fvk%3h1PJw^3@tf-49Ft8M2l3QI#VveNM2L%|Q_Wrl! zYEurv*2hT?AJP`sR#^x8_A;@%|NU)q%0YY+qwV&cj{bfE^(DKIOX2)8%zKn}%y0&P z(?>!ATp3whX#QrYJ39M+_X#$D+#NYFG((brkJo0&r0yQcTr6b!Z`!Eu{z*yl=*drJ z;O2LO5PmSOwnU~aadH-d}XiKGUFd2NAj$2$pTTqbyy75OayG$UPw;cgwg^y1oths5qudq&mm z;NIzLKKPc~)cpBJgDlwoPSGH@d_rnZN_`V=(R*CQr6+Y0d-9YO9ZwZDC&O;Y00}x;A zn9do1aN5}9$8dP~u49?&UxM5__)_s204eeRm07~Psi`^a7|i%k-gEao#6u0Fq0dv{ zW(^S~fJ=ggy}zOYa6dUfNq$fM00@+?%54GjVc&$TE*5MDX{Z2izl_`p(h!;4V28|q zXNTk%x4`A;AX6EhZ-ctGy`bMn762IlY#j*b&)5B2j{bOOvqszRvsvN3C6%55*e0Eg z4T_(aQ~SUttRXnRoCMH^pB1_d57z=QQSnt`?_2NiuT)Dwvmvou&3a#(+6f@~CvZ6Q z3VKKf=-bctEQ?ZR<)Z9?7$nRk5qVtDk;^3j7Zmk_3kuqO!U~AWmw#|UjgR6_1B}jz zA6$@QbL%01quT$2iYnchhR0rVsi?s-cK}m!;qsR}D#~L+J}!gFqoU6LkEhp5^7KbY zaC`9!ciNgbRuhCKPVZ}0gxrj0Ij4R7N`3U3&#W-kEj6~ImG0eJs~0Sbve|i^6Ctd} zT(YIpF02Q(4z3I-@-QQohLF;F$V^m7#W-~pKcPqo@N5WWtDyQJc41@ZGoh~N97;hvish&vw{O^GpJpl4UHM;Z=9oWNv@kY zO3BbCI7K+SC!7qtQefwOmQrNrdX^#z4ix0ed0){MngnI^E&4Q?PgoXpJ)N(Hu-pP= z!P_aKU6cpM*1nJI6JLL@Pkd>5U&e~bv9&30EoG#~4!mFZ*AY&RK`CUt?_1WV4w}V0 z2VpzTJ=mYuuh`(hscDa{tr~61gtcQI%OPU@4t-5 zlw&DISbhe&>}7X8-L$>i;Ha3qSVMCG(_&Jl%*#t;dQA#n$e>X)k!_Ts8NAiw*K{kb zA@FI~Fxy&op=eHTU%L6vMj-cy09i}swB(!=JIjJ8iI z6_Ze_Z|rCXjMXgJ@|&V*(H9*Ds>1u*<2o%Sf6Lt`&WYZa5ls5VNZk$`!cbd-q!2TY z|1gX!SAeQi(1#vMJPR>1)@h^m>1X8Vqep>ec(KO-q3dZ&^$=I;Q5W6wtL~`yPK)1$ zoA|EH5Ve$pgDlQC_mzyV=Ch6Xe%N)lBA_7PSOYuo^unuycyABqvZ>`I&yY1G)HmrX z6~g)-SYz$MB57|czFC8e73c#sDW;J4r!aA!Nqnjd+J{OV+)mjw5lud(%F*qpe&_nO z*KqajWNZqH82?MGy)e(2ctTG~$)q4#80EPrT9OaJCS|EH1%;AD&Cm3CB8wO9yD2ts z)Y94|DdsIq5z5EbHdoDnsmXmA>)IA)PAod&8W8lREnCEE?*RUMAF0^|K%JaIPbCXJw&umtg#J{? zXU5d1#A=^uu6a5=b-lX=Npd_ZGoxdnPpWhn%YKk7m(eboq(z)dOT! zpiF4)pjTNbvSH0XXeAV1hC8p8ETE`O2@W>i@e|Hk?%@5E>`s4qBBo<&Zaf49* z^LYXi_eLrl-DD%>Id*jw?=DxDjMO( z3nNy}7*ZkbNPj{$ZSQ@?x&`#Td6&|%2!G&COi!ZjT&NzWiF8^kehfLeGjItz6 zZtG3K)4tauW{BTc88pw~l){p@A)C|#hDk}wfjHPJ_`b^Meyg+{n5r^?Y)^!4@UHMr zF)Kq(J#|arcHlhY*oW6bDk^|;T|AA%u3sZy-nOdfD1V@n+T%XtQ!S^lQBrp7+2I~5)gAtVT~ zy4(;V>s25TnQm$$>)<0%o=iLsMz zMI0iRP5VRztr_PiGOhEPWFlA5n+f`@;Q*_u8_W1KO}aSQh42d{+%+uE=$$YkpB4VK z^{r}lsZl|aakeSt+}kqL%2ZDvFbXuAMk0w(tCoX+O=3kM+phT{nZwOu1UbLk)9jD)E^rA zqJ|d0J*eA~Hc>G@Z=?c=eaPaDeiAs{l@zpJ;SvK3DrQ|j7@08O@gkrF-ci-%b5$wd z8>hxD2`szWpR`Qxi%GfZfoExjETB{i=7|eKWpAn`LstFhJ}qF&i}DPgZ*;&$s)|BZ z*m*dK(%j#T#P>UeId9J2i=7J|I1F*fGFYPK=)JO7{D-{TAN3Gx^5tgdVCp?BDqP-e+DZ6{B>_9FOhB7!H1a73K#Z7 z zGk``Oerpa(iPi<=r!C%E(Bbz8?*40 zeoXb7UBBkFJOmZ7Sr7aXI8pmYHhAhV-?@TD7n_EOm#&vg17*k=pqc|P4L49fAuLnJ zj;Vh4IM%R8F8Dd=3akpkoM~0Fxa1r6R}r}6LY+dm!+e3Dr7%;A?Y4=)x3HVQrv`M4 zf%qeXzRp_J3YdH2el00r&Z&calkacOWznvJDX@m}FfEHSP8A4lC+nE z5dGFOdbH}wALTKgsp1+Cvg>Y(IS^OP2?BKgziM*W(*=$t?zGIcX+fRTY4Fmk3XXR&Xt!;o&W|MH&CB0u&P zXb7(@QTJ7`-FKL*FDE<+JrS;mEjYCM3a`|U8R-C>_~}ng#C0;#)epZjDcwE6fbE*# zAa+jVuLJiSrEskmTFO-?!Uq>27J(tl*yO!qbq$V80J7)MIY+}Y)Gd!rBkfA$EfLgDvDy*dt5{PSOeV~~r2T*aW%fiou`tzM>_ ox%0PE;r~}h%K!V16_2fjnV)nRz3RMsoja$#4qUrL^XL2j3jj;*0{{R3 diff --git a/ifrs17/Images/SpecificationsImportCashflows.PNG b/ifrs17/Images/SpecificationsImportCashflows.PNG deleted file mode 100644 index bcb093c83f1aeed76336d9853ce6074735e120e8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 38471 zcmcG$bzGC}`#(I8TR}kwsDR{DKuSWoWhznvA|)LPlG3>m>X25XL@5P{(b6?hLK=}C zFr`M<7_kx0HH_Q)^SQsz>xtj@4;ALF^E%I?kN5Guu28L8$~4E%9S4CxG%7c*-3Eb< zP=G+>PbiN9pSYS|<^%pAbGxmq1S;ranFD^Iu(_&n6$C1dKCx@@7w|jP!<&X~AkbM( z(jPLF+ZR_sptw<$Ygg}hn=bA7ZCFqHU_;h5OS;$%l_yZItvRh;?mmB=7x9+rN~`KX z$J%=1eXc8NY<{mdB9dJOY+3w@;vTM>XG&+V%-vU43&#D^3(69 zq5^gb0&$%{9R6$m(VX(f2h{%?AEr>k-^^S1T*>YYTu_ec__^Hvy5NE9z^$cz zO{3ELl)ERS=9Q~FcvSFN$BWO&dkoz4$jUXA1uJEru%H}|irKAMuI7X7w42?M!1&|% zznJ}1rsIcyyWi*hwbYI>O<|tvn2xESrI`PG-j_RrS<5~VS`5B`7+>9z{Qh{O%c~w| zFiaycD#UkXuTgWi(Z#WL{9u2JU0>hP5!1cf(aln!={s06F2;=Ol39^0VE>wWu#?)| zjB_l_UpLsgz`pa@1+R*?3XqD6a_LTydq31jkUq(Z>DM<)cI0l7BvfZsDeKN5bA>2c z-g<3&oaiYqsp(CJhRkFxq{I6#_YzFR7f>of6wIn)Q|4_8*YgmX$zn z{0sk%uLn)ToBG`2(1)k%{7`P#u8n+W7@yq1E)LgwUmG=VHYw^+27(r)_i3DbS8Lj6 zx7}y>Hm5*y49A#$xwHdp5R;;&*ey?79G1r@cY(L9(IYqOH3P)1!aj3k8^41rzZb8n z;tLwA+2Y0N%k9GLb*4=`%`njdkEUoMqS`B7IIxL#kNT?*M6-WF-ZJB~pu8>Zz4~nt z+E6j(iLT8s5shm8TDcGm8PfVU4YhIhtE%R!SB%HfX{p`LkD8*t%ZEd7=r22mv@)G~ z`N%jX^;OLjcBMV@9d*zYHuGRlUWTi4&`hP(Kb?v_~}S8DbEM>-w?|rZJs^ z)KN?!z4`J3%1#m0usG3s&@``E!K$g4jj0!!U24_WC)-Zvxn=$#+j)Uoa`-;?UKQ@n zir&RFo~+j*nE7aFd(nQkszZCcd!Mq@v0`yH0BNO?8)pbh?YaAsb6@17s-=~Q*?q^i zyRZ45cXyf)H*Qt8IT#ndqq&-+pf=KZ%?J8c(m?LTQhTI!MPbZ42g-t~nI!jvy{+yF z!qrK8He@g)J4n7ZUE$dhx}sYx>3iP$t|UDAqQ{Fzy}mqWHT=yC0%Hm^WGQz;FDyXP@Lft zZANlG+H(2Ir&!*QWgZi*o0JZ<^Wb z*+lA@u(Q@g@?Oo)T7RqIN%dwz!?Y#2?daF*Y+zez>&*|j@&E(>@yP|hEOz^D7_5hOnCmzvR_n{z`%)h6uJjBS5cA044NFH zCQB;GWh8Hn@#Ng7y4XKYd_2%5iin$@YT@Ht-!DIZh2CYk`n)-2_wD21S0{D8A~?2~ z$khfIc)B{Q2jzBP!UU)k>=rUYo;=y{>Vxfq-Uwce9$B*qo-;>;P9)COf@bb*Z7l@E?N}LRcq60Zh{Ad#hhqv3 zVe`FY60nEIbA~jtXn+*1hUTVI{OUCQY z+Zax8=HzROS!6@UrqW7Hr3<`e<3*{OJ{E@b$fph&I9QhGNIQk2*d+@53LNuv&PntF z7ShOsq4Cg@1xW}M3?_kaHW&vtS=Lh<&*sUzw-Wwz|M*F$&e)gfTYy zfL)|DRvKxk@WK-d!nk7eN(bQ;CNV$yf~>77bLlaU(^j(3opHo5iTgvyQKk zy4mkWJfMK6f34S3Drj+^>MRaoI}ADqKp~B+rpD)nQDz8-Hg(a&o`&Xr?^>$>&3+ zjfqW(GX~;bZ*vU9BBO+xA#WzXy7;PMGr60;_ITF=+Q}5Ne|5Oe*a;o{PBZ;My&5)i zo?j;G(8(y%xx~&ui@a9GH}Hi4u=+A--(;z^MtYlG`(V=}@pUPE*KvLR$R92v3Ix&U z;H-nCzoZj5sLV`N6Yrcgd$t$u<)A;`!c8Uar74>t%uFs5N+WYN;C2F`NOEX|NgjS9 z;$`Fldfp|@<$^|2?gMvO;drIuA`#Zq?AF*Jdv9be951NIA8pc(H1BvA9J|ibPGpm`b6O^dB^jLv`vq@)tZ+bup zJC0*IR(|e?cThbyLklyT#UavQCns3E1wojxa?v z4YmrK^2%B4QC+#HBV`I~bGWTSBJv|x5%%8&9au@jju-K*aDTqAS52@^6k~@drw*FQ z+0i5W*AkRuZ`E$L9Y%NF}cO(jvd>*hIdomjC-~Rs^l$ znbwdn?pyy|lmC#nD8B4%%Kw8ST-8xfpLx&@b{IYN;_Ck>81t3!x;W=ghK*6IGWSt( z7lu!Tj;wsSDMGdI#>cK+_XF7B5}+PPUcw&Z9r^$Y55~KBi!GZO+n)@OZ@3xo5_&*7 z2X{@&lVajytrtmQ5HP9JlJ?(T^|u!*cSL(GmdR&rpV;>JvJ2RRdKdVPM#OGmH1E~- zOWVjsC?HZTk2?PnJG*(hK}MROPAR*7g{gA7EnQ-nr?v)DTrQAdaoU7^lu!QbwJJetTgOu4basGnG`(E?q1F1*bCJ z;p*p1@zS8}Cgx(@mRGLhbPQ!@uHV_K;nTK>%uQ*3ZtFP+^Ll6hw@Nn%gZNho9y#`R zdFzzygK9)5;?0|^wN-A?Q(5;nUhGP@BNsajC|h@s?;Lsh60b0RYM@eZAXK*%Oc^(* zvD{)#xp7e^Ge2t{V-hNDe+O?YzUb|W#V4v?{X3La?yk3g{YN4{bN9q(9OQGIkc3Kq z<24Wek6{o=Rb8n0J+AOf&K}cw9Rthz1?X~tO)k{skMq}c<)Q~d`_Dtou}K)4doEFH zjGR}Fu5I(1-f+@zVEN?SB6X9Ko{mT>&VEqw>=i0~rwLY{-+X!L%6y)7zuR!n?ud|u ziOx^aia}RYfi2!aQ>z6P{bxOrKP#lYIX0yqHgvpmOCbeiT-z8XWKW1y3z9n5!aW8 zEalMg{NiW%kS~lF90xP866@Cww=%`DA2=p(ioI7FEZA4zDas zW!6XM+E3A4!qb{n>b5jT2@;g>Wf*SCbC?lZR5?u?aZ@*kbS}Y8&6cS${+D#QSgR~Y zb~6i==Xiz+8q9#@;@Vo?N9p3W{9+57KC4W?MDfs$t?hXG3|q8d%9Zn*%oT1}x0CkR zGc9fDp8L)hq6A&-xm|^UaznTKo(1miri31M^M2*^f_$@2qf!~L;?#S;V(k~O?BdC_ zLHq)7(`q^<Mc2w>%6S*X$K({mp^txnhmB1rj63YyvfHtc4OEQtf#t6 zm_N0*$QFe5tP$apo|m1ZRQDRicvw?uiL`q0IuTcs#d3WwpJ>vU6nJ|pVzTO)jHjc~ zVt>WF_imL=+)pL&oFjL^bxL%LQVhIoU)TRAQ2GH1I8(>9;Sq`kra*dR(<)yHsO9E;n;JjQtYCAcU08KnTCO;SGuBi( zZc9ydJxQz-uu3)<_8lhpEV6v5?=8OOZn|wfL|9#N_m{7C(Rf^TWx`W7RjtueX>v#E zF15c|dox2-37yA4_Iwrp=?Y#q1I}hd)5t(i*I&?RwY#46-oN629p&TkIMl&D5o@%U zX2xlXJ@%Ei?i>&fgeW$Hlhg{R{e*Q*-p0lnRs~pe*4biXE;tf}Et7l0QJvk*@1-a? zwe<=_@HudQ*LwyBdWDyPSem;Krxqa^keX)KB_FSJPd+7grQ&*o$*A})i|QKklXP(j zzBB*%%mcUfWGksV820F>D{QH4{k`3m&#}tfeTfhA1fjkoEK)$P110)v%LW4(7 zsl}=#=K#jCyHoqS4iKl9cxjWOl3?O#==&|`*bL`b+L~xVvsuWmUn^6`QCup@^$n)5XLHKGo|HKilo*_N+b!mYunPk4mgp%X6F+MTcb%~#xfQy7LAi(lP46EQSYSB@+G(yBM&|P)66-m zG#`VPO%3~cjz%J?#UiDe9up&mGM%5EcK>zQYLL=uH3aM%vTtujyj#6gj-KIMdgCHG zF0FqwVjY_Q(KqUoWda)$9)V0>Wuul9pq=z94RNSAmt>t3OfCS=!02$#?7n|7Rbz7ineML#o zlDGKW6^{Yi+=ZW+<_SbHC4?RB?a9~u4@feVpnIV46PL3xE%c7NQG&d#n|M2~S@kzC z2^2vj@O8WnwNOygn}FJ#9v%#m$M@;r&9g*ixaHtGh%?SHMY7=uLwQM<0b zs}0A#O4P4K4hs%pfa>kN*LK|O3I?T6x8BD0{-W7|z0veYp)XL&e9ucBL8g}ftb}+9 z84jV~KM#}L3^YVv-$u(PIo06@-1qQ<-SVgNi~>*BvJK%D+OD*qTfVr@a$OoK?{i0NCtmRCcINP}4bkiE{C z|GbC+0fLC?{{Q!V2l#lQ!hk8nVxg}ABPd5 zSULeTPe}l@J^8K#(i6R8Tby;CGpEY6ulA{j1Yx^HAq9}j+?CXwj>Rh!RWM+b(Rw@O zDTGllj;5h6c;ptbz$qJbQ$a12IZ729wJMc^xZWJ~}Zf&q)5c0mBBOW~IJLmhz$I(czugsmZ3k zIiCU{P9oAkn%~B*=G6pAR-8hBTvscOfuP5rT7lfF%Nzq^im%bfpdhJj^pU{yN03V& z=)Jwb3r-weOKzLPHr?=I`VXJ}7Z&F@VjctW-d$_4i9W?HFIz~a6Y^gNJ1IgI=GX_s z}P$o#W8B!w|6=z=NdhfCxiwEonJ$s#YA3OnOIFPZ+aA6tAT>+w@H zsrwsQRnnjq3whx|Y>@E)C94Oi!fh6bRUvRt;Scb+@2wWAWK};=Vl){!d7e+O z%i0w5-v}6;UkS&tb_V}m1n}7-P$7O`s+ji?%+hVYwd>)#_BvJLSVe&O*;Fnqg^+TB z-`eW{>BG_4Pdx+jb~UF&G{sUkWF71sNF+b}NOi?zE%Sg_2^&1<-?SoLmfTu299B_S zPwg&0s7T#6i|UubZQYX56P(Y2@2;>R6YLkJTX51ls6FRi)V=~-Ue3Q=;{B4V@AAG; z@5(+p0Op{+&=Li`oyx1Qmb@Zake}04JTD2ujObMnib^g;BBkeb(7KbAHyMK~ymyf7 zuV81t;g2~dCWwXuY4uzd&u^>zd$&P!Hfrity$@9KfzGYXl`6Nty>+lX&PPD?sfPUA z<+)8~IDSZY`r>4|FMPcCRO_a$oL*~;-%DD)ul{*;Dl_eyuV{_>ym;`Z(GOr*|Pe7PD31kW-&NnQrTxes9Ka2_V|R_=*-e!kE$5j9s% zK0eM?pra_r*LPwQIWIyc-_XrD#O3^O10?}gt@R+G;pX?|y9>B%)#G-yTUiWDUN9X+ z3hG8qp4S)y*A}m=ZS-dC`}j`V+jOf{U!8nl9Emy!MBR%yq)18z1WX}{PnLFw58Pj> zBX8W>_dHi4&0+YlnqQ@hXK;YehEiR=p?Od{Z6p6c~DmGuivI_PRVf$VQ!$_3BDqhkE;rBQcl79vE<<5xZD+fB!wKczkD87%)pa zX|ho>7stw;>WqK%@5_Gy&+-OxzOBx`anOQ164TGa*{a<>;tR|ZsxoBSHWQjx@5TpW z32kLxjF*mw7cS5Tm{b+H)`Zb&gs;f74H{+SoC{_*-WqmaJ#pY$-!FKqn>hG>CyyLR zK0x9H0^0|$;z{a;qQp0lXN%$xomy#*;riP#EMYyyN5m$)rf*gm6kT}PDS7-}0i*N?uO`m^&r@h|H=er zQW7L_@9c+E$5+lYCtx2cmz_EO(_l|fH>^?zY34D&+Mj8zCjfu53)a`H6vk(##9^a! z-8%clfGLNF=zTla7A>);a8UqE>BWw}GObz2-5DtAsTD;@|I3;Wse{H{qES%r%Ga&1 z3b`f>q-SWLLW0RR0izxiFle?u85h;x=B7_ot0LTlev)x$hD^bO>?1EtcRNst&NTF$ znz+2<|0#_R;5;YFH~w{_@E4nY&}Ta8t7;`^SJicWcGuSGgiT`oUNON{;r{El5^T4Z zJs~-EEDXT-;aeQ5O(whX!OqTr-Qw_j?qoP&ZZ6}+E$Oohz%U{+Sq90y7B1=k3Hy~# zKSd04_rH}|0x2@OyAj}oLhUuRo#kAYe{K@HYKKDMo7GkZ_=L^e?{TQY9z^Z81vhV* z9Xu%EI|f%T!#6irV;W=C<^{y7rpC-%o^pM9cTxPq3 z8#iv;1tztJaKCB&;)VRZ&AjceU9>0^(MNiXbvDo5;lixWcSC| z(1nkO+SF4jF(W%7I`r(a%)yW%u_D-)?O038?0U?~65E^j7_Nw1yA`6gx@w?mLgXYH$Kb6_Kwq070-1%`d^zI0?>V=1X0{H5On zL75A6zC;2FYTnI2KndJOK_4=qphahY$p-K+N;OH&R0H0*QrFh4eBa`F3u5iA_vU$v zFqLff!3v|e0-CF_(XY}Oy+4)lbHO7ovTu!6J~!Y#7nqAs+=l-)rD4G{W;>hMeCgRu z4!@Kl?DOnx|M$m}uomzfZ@HiKdmjzi)La`_QS4A>VUQl|F;iKh94^0q6_J)P`ij%z zi!2g8PWFfWALf5j{RxaAIZpQ7EG51vaQV}@KLS?rsYfIh|@+D#EJN;E< z0Ojp>mH+o5z`VnG#b@oxfn~jzx+$SUuxrNf%pW~MAPZx##i8zi(X8ZlRY2VDlw(R5 z^}`zVfB2(Q`1{_S;M)CfG;>V~XmQNBvq=dv`p5ot)jrayO=ihJ9s8`uU$pSQO1Tq< zQO%apG+<-K{oABMTvYA$Vr_<*X!MbT{jA|bX5yAn^zg@8jY6UH{$qN4vM82#H9OCa93kit&+&wixZOs#r)RfD19 zUu&pC72Sh!j1O&j`_Abc$kwfwy~qAS5&s8a&;)to%Jh31P~K*~KzWNL0dXhcbFlX= zga1_n{^&ux!xK=1;*H*_1HUBt!!%+7z6(MRxS zz4JSEc@ItL_1^bJaZw#`gT)ZdF*&|Lc)#EG3jsFBvBFIKiXS-H@0>*b+uAHBb6uw5 z7{1zj`HR*0H@%$eNx&!&^Mc?@+oWJCy}F|L(h<2E$9FK6moo1~_B+fnzJ(}`U1B(R z?dqtFYinXlPbXntzYp+fh(sPuU;7Dl{qHuv08{n7Oy5X8T4&HWPz1D%Xk zfU6VGIP}OVkkCbvntq}uM`xqncgy>2N-$))Qj>wGX#i2mxj-cjp)1gs3pUw{?FyM` zjptI*APB@rYTbM%5Kf197g;r@Dd)F&5QzFP?q&Tz!TzUDTMFn7F&b*XhJIi)99^I> zD}Aa;X%GlXDpaO&ejP({r4~o}_|e}VQ(x{Hbd=lU5G7;XZ$7wS6xDO%_zfyP{hyJU zx)&@Ppsgxs90^vkUF^k4A%Ampa<}u@6sd8`+hI`1I)1pz?^e>1;3jpfM#u{!5FOlsqM_4I8Z)- z1KAl={cd~#(sj0&1?3Hz-$!srf>eGBKB3j!mVZLY_RT+*9l8bu?G*#;)BEJXkNuv1bol4BK8$J^F3f2@miK* zm)G-bJJ?lVv!}lYvt1t1^RrL*y3bvh+POA`!ke)#KpiJ!Ine=x2Pk*rDr>jfM)DQ>slFfZ^yHa+^}2cFk9tggd&nJU&_7Z<^D z8QNV-9;06!wP(nzzAve|KABYf+-G&~GiX~}L?4b)xM5~`8j;qq(4Dohk)=~jWY2K_ z6p+{pJFr*vQ+U~1ucqTWHxp|LvqSctirz0=f+ety75WYy98*T;)Da#~{h@USx$jjB z3MwkwS|7k4VhsiXcC;>4tqE<Fr z3IGixg|mjt6!M)Z*Tk*rQ#+WBQ|=%^A|SoXO?;H%3<0Aj0K^P87M)d!Q&64TH@i8v zBQWVTRkjlqmR&zGc7RhRY6l2>_-$`G;uP_VH;z1PDp4t%NR^}4Up^K zCnf`=V_ZzdEczQwvIk929kgIdvO=Ma4p#Q!L5~$rJ>T++DdRWJ^X=fzi9>Mbqw3>5 z2ItMBxdNzf*9MylZ&t_&oCY#s3Q8!`=l}_5FiUyzE5*F>-WcIPek9=0Z}<2V3wT{$ zY%L8Fb;Gt0l!FHj41X*Kgeg?*1eSGQ==vp$I?zz42S9PDi31bSrN93$g zHP=_%&A$qlA4ovuniFe_d#w1(E>Sla$!@d*=HhjGB%rA_&7!YR-agIcT<~uneP>6> zFKiS)n|n*WAZ~TXE1)bNc|2bBRbyAOOf(;EGAG*hrsc;(H4fNEp5fhz?U+=X*J{hG z4y+-VXh?Q+GJE;0lu_T0MtN40@tl)VFUg9$`qe7F+?2l>zj4ctg}c7S^!8T(w%CkC z3r-V?tk#$EZY>`VhS`p&UnjBIeJ8b4y$;^Kt=MvJIASz8ii?hps^O9~`V|Ot#3-t) z1w!WU2vg){S&#I<<938gF%|DKzP#@MXV<4j16*lLkLPQ*%f->SP~o+sN1$4)G76{P zSDtl|yDn-M6J4=Xv9InDDG_v;CP>p;U}tM3u*JyvP78NGS3vZhG=igzdkkQ#FCpzI zJ3zw*VXrU)2P5S>Bge}50^o|kw9oBE;PTZqP1;*N!*TPk*MzZs{%iHnvU*LF0TbV9HtELiLF4v_>B`x*<`Pt%V zGh@y0LNf)V)xreLBfQm8Ue~*xOvok9ig=2I7*l*cOgx_5d6>n)3=rRp@gUe+=i(J> zT!mG|WGQ?}_1bjzshfb+DxY-boK}eM)v@V5A$?=g&cD;@I#;!8JLD&x9^5qBB*@hY zV?tK0Y|I0x~CA}F1<+MaV-`jHm=#>S%{oO!-!~gI= zL38eTfDC3fRC(OXosCcAOPtZkA7EKxE~Kc@!SD@IT6ivu%53zk@ESc3j>dzZ0Z%W0ha5js8ZTWx9os!URnde!9N6rF|anNV#jn z?mC&tcI(tumf7I!UL%nVB7`l{~tW z=9ur{BsY1Nin_tB1RZ#>4$T@6^1YDu1Yw2k01HwQGge-(ug7ySG=awL5PtY#>hGakWakLuKKl>SIq zqe3;~apm>YuL>VSvTrT>7a24&B2(s-{iP6T)$VZ|aOP(ToMZ7*&0g&qo(mBf@~}7T z)AT!+0U$JT(%GU-rRDW2o!Yx}*zZ;lff~DYaR3P&t;6pUJFqj%N3H_QemjxkIOH## zmH^Xw2cMm(yO-8VV5%QVF+X;<4(!f?>P<$AUdz+H?EL-&hs*G;{lr?~RjPWPiD+HN zd_n4~9D*gOy+p1?$Qd4Hr``(8PU|;}(JH<#)=jzXA zWdppay|aPxpJlFz7AB#Bgwo@X$9|eXH6-wU0~iRo5^gE?ZqPsjZ{!2idzk|#)o$2> zdSM|FYwYMBfEWmv=LdQK!}BzNCRvZVkcmDZ?ldcs$beyg019NHR0z-jz{m_r0_KcU zn2e37m$=BFH#-kf&ivUs+tN{!%HiZ9G5%}Gz+WCI{lQmE(2A8_J*@{Ju1*j(U&NN}_IRhr2^=RiFd z8OaTfQ8yd~Frl=Wd`S|FD0c<4W;EvB^r7Iis8XcStKXdnP^2YMKtT(EkRe5Y6f3(e zXhd8hBfb+p5bL#HtIG%Ax-)+^;(s6H4D{iaLLPoe&I14yX9cw-?o-wWOn=$Y`+I%{ z@JfNlw2FYLm)BfWg!E0~4!q54&WJCVA zR^y;B*3{3pzL&nw9Q4CA+Ff_^d1+BY&{d-K|E>7~Ez~Nr2u^ z6zo}BAhVGBsk~tu%H`M2qTvP9Lo4*6>s%D65Cirf6Vsj$NKfLs3Z_Riz+9DXYh5Kn zlOLA6ox#4fur7>9QvhfKKlRg5e{VK-=LT-JYCMHFcmsoItf0>SY2(0FzJL>>fK{#l z2wz{J<~&^M6P;RXk>6LCj3YANLJ&}dY*?|SeX;0u|J_VR%^I)47BrjR@ZATI{yvME zMBN!IXK8-%BC%OxUVr`G+Mw#Bf9=cCa=W(xM^Pbx8fCW5AFiWwC=+1{f&G&~MJU`2 zdE-2vbs36<^v3DM_uV&GZx-)AQrJGySK@zLoUNEDJHaVLnO&ET7yW*&^+?UJgDBV5B5lo`IdMz;hn0N&$%XwfdL;>nK zexGvuK1Bo#z+&w2v5WzDpK&jNBE&(J0(ejgc!EjJw6TXKh>hsR5yemuS&iT*cLv5s zN9};;J1Qn-2ht%rxPf<}c`P9JPEylcw>2(4Ta74#AHMMf%cyXkUM+4!NBQUGf!4oH`-M*+`T^-Ow4@ah<)m&1WuDP~7u%5iFULVudB2*pGf>Q%3s zS&}m~b*CB*Nd`QSOtAPw-O$Gv1JOEf-u(hPt^Zu_cA03BZ)Va(@hw=G*u`Hb5)W?b+*@ZfYBJJ4<){S~Oc zfS+>9C-s^rNMUA~NKXfn0pP?2kYDfaGFMaU=5({un zGN94^64L zqH2Y6Byw#K1OvTq#%C)wPiEa$p`mdD!}s z+C*nLm0e{Xxz!U!T;JcsM%9XAv}u39jPr$m9p3#pQ*iN{Mng?iY+)eb-Q{6dwYb~8oOx{->W8(wK1<_6bJX-2yk4f*_eg**L+tP zwc9#%n=r2DhyO|k_zj?;Gm=? z4qCr-lg|!DovAT7nET=wr?76XypRJwc6i7mS17VxySDLHJ&#pvu~u$PESJ+W3u{g4 zm&j3o!U(V!O)j<2__kfi5j_(HFFEnN4rETo8R#m2-BXi|0FSW)5Dg%!BO(-QII{TJ zZR-{~f9SggO!=E@vIF?gn6k2|FWg?@Df?S!UFsm`EJATtVj*~__`$xf!&+2vh4)L# zQJ8FpY}3%Wa`|`0i;Mok*P-AFWI+}ivg6`Jv5Gi1rV!&iNf7DB53y*hNuJ?mwQ;)j z@s-vKh4_1<h^g~V7${$AtG^W(af!bvuvR^ z4)V-WWWkF4g>zE}J1Y8lTN&%5U3N4hva-vQ&469LxLm4HO4qR4K-qDxvcAB=@gmeQ zucJBIt*cYHc&){$c-^fB&W`SN(Ir)Bhp5p>z}Y!~L6Gwebx-~r5r2_)Er|IR5lwX= znm9uxJ=M}XGcP_?3ivCWcapfSkKkb7WB=4kU^;uDe{ixoJ6SW>ZGiy`95~M=C+hpc zxhioN2ik5GR_G#M`B!1$<`;!GFQ=d8ecxCYYYPN4 zR~Msg__a}|umb9WyZ zwfM@5_5f<)Qu}X*QbWWDrY;V7QZ2oI+^G;XMJMpR-AyI=>E29p=ut(Y8`VrTbt{-L zUW>SWm%ZGXHaAOJepx;x(~Yx0fAlhE7jHXjY8z)jL{)Vad~)b~m&~C4MX!|RHPsf~ zzkp-_@EPrXxF{oedZTh^q(x|yrYFDQX0+xiBa$ z5xLOVTzHJ1%pu8@xI?*lHBvoooqn@y{W=sazBJVj|9RQ6Cr`V zK**&8o?B?;{#<-Y%}z}vFUEX9c`r9#GxmC(6;%c2_o|H1HuaJ6eHx&C+TM)MZlN%l zYA)Z|u_`Y&P2oi-CSHwE6$a**LyCuh=dm9l)r2v)I7Y4QyEjlj0^kmSXZ}h8TFp+a zK_Wm=efpO#ALbEn8BhDD*qVN-@jor^k8uC{>oknyeTA+IB{!?&d)(t>lzW~YqM|^6 z`jkXs;PnI^;=P9f3;0!B`Ip0zXneMA|HuDx_Q~Ws^wQ5jz(^ffhhg0fB5u2@4>ll7T>q;XtM&O$&gJ z?*d&7iGK?G*mItdoJ3|N2e`0j8^9paQ~>z6l#~tu-YW28+I1iulLi#P&jO@W1yEFh zAOAluE&7>MAOVz8A9WFm&26A8PFXqzVx&9V0-|bj#NOrxhw3!2!6Szo6skTB?hGsd zvq(NPH$4I}m;7-Aj^FbG(&0{QA96zjAwTv;RipZ$pA5t(a=2)Gku%E#Y1Y6*O5Y!y zjeUhaX*hTVycL$8qluE}86?g-7+*Y!#zzri+)OYZsg|%y#ur&zweJV=jC9+n57C zXQVx$hkbXm*mrPoRG7JaGe==*(A$H!jwAM^rn=?HE)OP-lvjsO5e0uxPk-#KN2~PG zaC{ePw%Z18ebSYvp;`{3OGR3hTr>*xaY9XX-gH8>62fo*e-O6VLfFKseFQrIl;~f( zT}OOqixooG%=xyAw^_#UA6c!(5c;jAt4Dy6<|Uz`(9n*p_|=0q5Vi}l4)G%^04TZ#o}aqF)kLep*e4%&3ip~N@Rx8r~-J2Dbq3J=4n z$$;4KYx{j!kX5T~dS18>$b4g`;AP4Ca3 z<0UAxt1B?|&s(@hrJB69-8?R)rm3lpF5!-IF&$y9urvDt&h99nYji&I5gbVJz`CLW zz#=-WZXy&z-FJDvTt_H+z*1wD!jE!ro6u@0IZ^pL=w}wbh7=(w#8H(PU{-4K^JJi> z)D7UN%~$>(^QR2&?GK#iyJF}A)ZsD0MW@cG>6wzQde&i`y)p_1hEKqd|IjQ!V5YZ_ zXL)r_#I>z`qcLfOVjJg-E`b*ye00A8#PLgRpr;Z2;Mhay7J99C7)3KtjlHqfr!4KB z2VOv9P1#q`5r$%=f`Zt7iV$?(N(^}Q0lMmW*#f_-pyERTXvmL3l`Q4;7#?e{y4S%Sas0K%fFZzS?J-`8f08WY)upyj3?ptD`gJmi10CJ(>z?p11_La)2l17>L5|_V zOu^EjwKM6}rp;W8;NW+%#0Q{j{Q-ksDMf9~xGKq*p%XO_Ph)BpxO)PiAyL%^#r>StA{5gZ3z(FlQG zF~Ff3qNQY05i~`onA$fV@S;slulw|i0B6dLfXmiw(kh#VcUaTCxM^YqkhINfrmR&=0b@{Sw|V_h7Mdv-Q`ul)XVMrbR${_AiIw(!k1 z+)}p8k*K=R!@wB4_T$+Mz=2*lQ1V-dxrSEvui^QH%dY8oSWaZ`$$uGuBduUbw6yUT z=K~H5Y*{d<6*QrwD!cQ|H4_h*S^Pz!xNq$xvNG}gZPz=Y$urC?z2&LVGtAg*>3zwG z*N!X~n(t&s7Sb2XTgqIBvS{2v4~2zbHustno9p`rHfhLy>SEf4AIMC@*3h)az1&V! z*W|cHKgLL?t-3bWmo3p7lx-35Lv+A_|o#T5R49;qh>DF=K9BbVarZ1JY{UJ|;Yi)vb{o`TzzSRkIg64JecJGz|5YAsI+K zNkfbx(^~7EybDlk1JCr4l~HuHa~I1)PM?E%L?rg)7U1c%UltaTe)pbwVemvn$shktzMG&Ta1UXigY51FWmEQRBt1# z#Wv5p7&5+Xf6tD2%V&b+EN4hKU2ku_LBS3`FjjPa!17jg(Y1xGr9#rjRXCKYoO`f^ zce@JBBAaQo32@@yRO%bPxI9b&O%rx+o4sq{TjC8p)zi zzoTJS=4cSSMBj5=B|oDDF=B){zggGt*ynAoj=E+B9WZp|Noi9|At79N_65LI zRM=cbNrmsojPFD(?r-f46tWp*`LWl?8C{N}ezK%bXXb@cM=WiH*2hf)G5_ce$sFT{ zuR)9Wzn3*?Ha33MdZ~FCrj*;L0o$gy741fqTo$^$e^H^nd~c{er8L3-L#JzH=r1e% zZYULS#rji`NEm$Ac+nCwvO+w)Ch33PDa;L*jWSS}z_QVMW4gLKXK1mL3$~_kvwr++ z7_dcO?AV0g{`G+U^1b_v6EfSIUG;TFW+JBtyqFPbeKu!+(AT+c;|;jU&^4&g#n@RM zmnZ!^OsDwR&y9m4;(!(Q%U^F_Mq##c6cn%qRb!Vg(tlf+0*?0yOv2C))54Mk)j}fu zCx|&!`NZ7w;V}KP2oS_dZZI{{p?9*P>@t8g9T$|&hwQu6Fi+mJfa+J+XQ(DtAv|GPc{frn2+zc~}N zT?<7xH}z(m8G0SB>N&Nd4*sv+zC0ev_I+EWCrTwMvZfl!8i^948j_{7ShGwaOAH~q zG1Y^Tn6ic#vS!UTV{4|eOp+x#gDLwq_OZ+u-fO6y=lQ2yoX2sTH6n1s0>CL@77&>65DUx8E3&LNDiFt`m$l2JF5jKad<4~fA%TN-pJa98 zI1hq%U_bZsbn7|><8I1mH<0%Bmp)-#3*65h?LUAb9|jdXC#hS< zer@ky?1u~N0?$u3&>Pv7)p}6jF9=AYghw#Cmn$ONDNC)7e_MSeTz2MGt61P|zKyB2 zp9T`Tdc7$pq1|xa$M*z$spq??%WY%*=NdIJB0!?CG!Cmmh<%x$HaKapdfUmh)7 zFU|py$M<{vhSF^)t>%m(z%lzNaY3 z4;A!c5<=3M#J=AV`?uEJA7PEXFQL9es@i1lL_t$}{?z`!x zrRHg~QYlKGPh~}liTuAcOw>%TL4Jxi%WMj5sP;GW{O%_=OnbzFB;mPyfe~2OwBYgnX&qo%Gfg zXankVP_zU6#3iz#%poRUG~ElxUcg*H0sb?@Y1DJ5e>hd?TACIIMA$XLP}k~eqkIXVOz?oeVFzI@ z;lXIzw)rq>SH2}t_S9iYPpK>3#!X(ezHl4?`#H7y8DakWDy#LbSOpDS2V#NcO^8*{9&|n zyRl6@aG^L-emvA?aq=xgI%#;2blHpk?fObkSLx2~(1Zucor$cg1RGy$E>%ApxWi)(hiQFA}wdnBvG;KFp`TRhju z=Qqf@46aIPjz1G)zRh%?YksY60JQ}@v2 z-U3W)fa}pi<~}@1;ynKHr{?cqaW^#Oc{ujPZ2=&#giRu>f z%R~n@WqoeO4HaRrYJ+_4%q)ap;b6xFqtd}}uHt!wuW(onre=YvY~VQYRHRc9OmbA= zwZ>vExcXkYPd;Hg!)%%2<~6udZatp^(pnbpJ8Xt*{t!j|8MjE!@gP#N8Zk_WoUT$E zS0trJ<}y-Qtc`HWLl7FxC0pCMRD3466)^(zQcY-3c9_5Z6)VFFuK9y*`;`8uR-a!w zp72al*&0=WM`cMES8xy-qq7)q&Kg{?;;FvwigTt27ze7#9E(e)4z2SjnV+-quWl70 zF0)e_>otbfl%J8H*7uyyQZ?>EKAAQ9cIyITA=Glm^p!?I?|Z;Cs!ZvAe~_5a5-ydP zN(j;SocewfJODqIZS+|lhVo{KG=&$}im7&wV5+1_pVdYHTc|B9mJ_-RThcXt?KEH1 zJ$vec5p~i?k4&3KBl$PhI1rfX77BMFRh^wi7pV@r zUBFYBRde07*h}hD9-=C=zR|=DX`1~$UiG>-8o?2{l21K@#WC8W_pO^h&vaI+WZrfs z6cv+Fsp@+d44hdBpPc@Ls?J!G)-xDddABn*eb@v55CG2T%mWacNx@zA7tsl=`f#d0 z#4IpOS37Lg^2fvqG1F4hek}iKZ8pSOe2J-xx4nwR?xWlk_9KAWS7*1qKwJGj60dkLGTLH4 zT74qD`03`WY6ZCB18qQK)Jcw8r|+YcU-O!BvIMdSmXn?e9|5IJQdBumWj4;&2NKs_ zqk1sYewjJ8dt>=cyPiSnfqH}!?vQ!xjvH53=5ap-qWI{t!<4%KRKYv@OqCH^2;}XR z9vh@BLTf&M5t1odP}iV-RLF$A{)Fg(i?Z()Y2^O2vbAMuXM^T?XR@q|bI@$F`}3S6 z?}Mu66yn0u?+JXHVJa+4?k~PyT>vgd3mzGSEsS{Y1&c_})N%Az7JF>Fe zH5<3Ol0q$TIhW@j*=2-xf=|)0#f=aZ{eh=}>2GT$6AndSrxCV4bbdlt4iX~eGy`7nT z$8+as%@;0fpO4aD8VI@2ti*xYd|tlag9{lE)HPEiXQH8}zGEy8)}rvY4=i_IXW>YQx_nn?Kb6O8A0ed<%{_~#r%pgf;Q=PUmZ+_STEf3ztQ4?(5MJon{ zz$)yo9T%`bWdGeE($_=t=r-&N-}B!4wt2Gv35$q3^w`bm09Pz#(=+V%0dUfy8>KFgn#Fp~M;}HRK8NSf)^8BNn-RMo;t8(;pV#S*&uF-B^?phaSgamM0bhOxEr* z{~Vl8;{WD!ve?|34frnl3^$#VjD_Zn%vK8Qpig{!P`wYU@p)!f;@9z=SU44IgC?G(&$ zVYRH;bI)n@jU~Moc>c9ly-fXvr4ooPPz|`ujR>vt0WhQ08`v9tXx9F`HZ>}V)iH89 z0$pnwdCcKDN904=z}T+(O0i1sihB+dH^4(eGcEF%V0a~3N<$WdjQ~cJzAj#cZ7k8_*}WnFYN1s;~J;OSV;3{H1(^ zd{k&T;*H2?SZ0tz%gCEh+$aLd_y zN?O67_N3uP9AV2=6@bI2v~YI%(Z#H9ZSI?CypK%_QjUH8;>%^F2AFO%*&A>uwBufDikl4Yjj=k|5H zqhCB5RU5}!Or;ET80Wy__J*mp>1O<-H` zX`akvxvVTDKgr~c`}l9-;9O=DoZ5X#kmY!-VAc3;(1<<&ooE5?_K?M^3DW0!L!w=+{p&yLJFfW%Zwr4n5LyLY<*QPFTIa`O z(!0A#f-_=2Dl zuvKk@^c4e`R3{bR+KLo@`GlIb<%xHz#(P*2x2HL>WhZD*w1dK?N$;$(A|^FUp_Y$L zAnbM3*9J0Wgtr}4gkx-pXFGjE)bsykKuIe#1GC^|ii7eXcCUiUuXu+q<;(-$Qcs#? zn;#*{FT`Ti0Tbdx(Ieu3J#=OJM&jnt z5iGBV6K#gpUKz-;Ud%68J4SwzQ(oONKHRRqv5F^IH8xT@9>*0Ur6rQE7MeovFz=Qe zUpl4ecRb!>o@hOAnn@4wzQYY1T)FNBy@0&>B$m97GGF^vOw_|b7xYHr5f&mY&P%e_NF{&xCE)YUV1dQen^%{>#)?P? zjyuoXqS%4FQxWQZmzmG%{!9`L2{>}HUn_>jSWJ-E5Kw_QxN|@39s9p-%wilLN#Dws z49OmTwEDWWkCR!N(<^fSrhMNEQE~J@(Ahd@OvjCc-F;gk$?r5Lgv!Pyb7C5>-nEa zUS-n1CP+*f)lAzqyN&_F^x&y8V#uj9bc(Ji-KqJ|IX}OH=X!T85IfeqX+62!~k^Zx=um{&?uvdwpK4!)ssd?OY5RgAjW5y&EC zAnlmpHDrMf-ALhj8e)d9frh~8nI&Ha}_N=h~T zm*x5OLCeq|>|(9DhpxIW*8B5LPdqkt$g0W@;{C$Ws`BK4&~#U!4ZfH!i+5{%aYM;JW_4#Y@O*75 z7Zd{6H_3C(@`YBJu}|qHms8xr^%{@B66ZwgFTw-Q4~)Og);`g$^hZ1zE40?rY6P;m z_{xs(BB@pV=b8C=-qOr>iYdAS2tN!Qz7|!W)?SO&Es#7kcQ=e`UmKMt(V9-FqyFH& zL4Gn`b*x^@`(>u)D|B*=NvqACxbh^{)1qw??>=+NhxGH0m_tIdUIz;aChHcZijSn{ z$sAJp>uv&vU z01b{rIk;Io_w_N^^@C*lx-(ZxU?L%S-#K>>co(B>8%nE8kt?UK!!y$hI`e2xjlQbj zbtm$~|GBssfcWxF%l057Kd{?qE`zmJEDU;KF6eC&R9o%}mW<;bS8Ok~(wTqGZmJx` zr5}D$n0O}ouI!B)8Qu_i58+d7#Ry8_z_pk~M&g)lgH8o66)4aEueHsHFx+xhsqOlu+6vG8b8J?e=NGXa|U?}rT_Myx9Bu$l;kC2 zms=M#U$k9+JUBrIV@vyl3$C)N7bBdF@U+W~N_-3Og-dPVP|&D{4@iF+j)KuG=EepF z!@n3AT9RgI#7|l>!7=_m7ttSOYDfbUZmA22px6 z)|<;I+6XD<0yzqdcM1@u#{iFzoen`%=XNLU|Y{$`{E}f zj*t5{9!l}Ei*jFQ)Q(!J!3MaI@TvL>g0MuZKH3bmf_(-Zpvd~E5hl0Vqc03=QvS!& z2FNG>cN^4yytDnsAG{fSXVoC%?mzB3AUNFz6W#}~xgbkn*#&sDcvnYJyE;M}E@rY7 zc2e-y#(T#h@I3jP6IqpffUmJo>!LwGrlyf_twT^|P#OTgWfG+_tMbvjUpPIv6HDCO zge=+8esdjwsnqeedN`z$DuN~x1f%87kpM`W`WL_aN*gTNqqHU-H2g+__1TqhFl~NW z(@XNKYreCxGqT0=9Sw><8dXu|U8NZa9|u5MZTU_9sIg-6y?B7z2oeW9#1pk&-9@NCmk>_|r7JJM!Gq}NNkrr$ct&Xc;^Zp)yeYdSQ)t z(=A}UN-kMT;4IJoA-egG_ke%>V3IxT;Xw%=-0`+Q<^D}X1tPeNLnn-3!I8mnhPk_y z%u7p>er)RcH(5CUF9fImI#B%o$g29ky(plAP4)Ox{)_$}ly^o0wk4ey^?*|I3WnGa zZ*IQ^F+bqi4L(2B@Jbbs>;Q4(e~e`JAM^M424{X$j#U7UOwmJI2{{Zv!`liTdX}b> z(Qv<&uWV`vG9LLC4Ug}V;TD&`?|{u0)3KrP-Vpyx7tTQ*WXy#fnlP#RyjrqIHlSSZb>v$U`I>>>zv`~qDgE&0wg!|vU7d2_uDG0Zq`|aP#e_yn18KUk{oM4YI&@oj zD=Iq~yWanvpgcibdJCe};Q^v_8^MaGNH!1?YrDx$!mco;4hf&jHIG=NdugsO+xSg& zt`U~FRlRzkWb83&OkA*Gypbl<0JA!|Qq3@gqv}YDfW44WGeE~Rd?Y34j+o;VRygs}n(AAtb_DoUpHnO08J# z4V{QK0$DiKUq9{BIA|EA4^K-96`669`UbaV>z}>%)rcrI>I}cicS@0`r7XYMkBqUR z>nTpvfuggu^;Sm|l+loiP9v|@X*6$FRE^8^89iU-Go7^1x+^cu(A>u|?Y#+lx{vNs z=4TIvH8pKoCT7<2=uE@D$upa2lKhAo?J^wp$xK#&T1|3ELt7K)#dJ7Y%pymw$nNYqhjbSL^I3 zWW9yUALMeGI2xUzy`~_b{Yjg>P)|G>a0uGXiTk--RCOuyq9>v&@+{c09ome>@_X^A z#P)`1T!A{c_R#kqip|0l&m-{+>U7#PerCL)=xl2`t(})I3ph|R_xHy?9*Wqa0n?<9 z#fZy3$j>+ZoM`OgR8iR7EK6ZgY{9D+^jR&<5-Ydtcwtiai9=YAp;S{Be&W&>>e!Gf zZ#>EAj}LvwrCP74!UN-#i$r8;sr)_(6|5JHcbQ>;1(KH zGBH!r@v3{dj-CM7{+nq;59!>*H{O`9XI2Kup{h$=&&mQ5gTNYmnKYVQ%q>C10JLz* zhc@(J9IpIojn+2}hy)szb~+*NH^6IVU~F5*`5Jg56#9QE1ikTak-J~2_$+=ME(HZ+ zuiAS65q+ojO{{h8&uqMMwC$}M*=n5xnByNJqJ#M9G>!`ucWWg=r-$gzU1w{3r0o{1 zKcfOa#l2nb+DT5AiFR?dJ7S>V0h|r;pV6c3z65^niZ<6KxUBtY*O3qnEYg!?QFrV1 zD|^gP!L@$9zDc`bw+;V@FhT>q;q?{&!ei@Gp3>hI*x#uv;y8!6T(X>&Dl}HCNMO+| zOGz+uZPOqq)iGD%S-+pKZB;CMqE~wDVZpM=C-$j$5 z7K4|fJ>810A;%;wl4GcLfFA> z*Ouuvxf=CTm?)lk0ghHnQTMRks#7Qf2J?lZ5aX>!*Rv+RSkGc?D@yPQva+u3C zgPmmYaP7|w+$_*-8-AJy*QXRJ_&H!sMt`{i%r7u;LPUiy#S5jtZhk3$W(behQwnvn zOeGrRD##tgPC2hLy)%1OJGI9=q`it><{dEOslOm>+y445#=#YE(GjGvoEec*&Govt zp#{cAk=#)qV(+Tp`bgx=8kX0`=B!q2@}fzBF-UzZ_{axjAcJe9M=s5;-0xnTvm{oL zxq8lE^*T6>7-2%i)$FTn)p(98sEpG(uR9BsS-ugHN;m>Kjnu(@u-NFDELhYt(syC2*(a>%?dwtNc7YRd?>m!PeMuw zYS(78;ufZ7NYSEe16$6L*_S*m8hNJEc!t9A=mB&(zcA7nug_E|0G|BqGoYsD&lM!9 z3cE(+lq@F;!yaCn2OnE*y6e+S(d8H!f0%UE&e82B>m^jIui(Z-x5@aaG}}tf&U4h@ zYXvz559@BUYQFGCpFiwW>XIkm%`lQS<^rO%V2OQk*CU z9OT3SBWAg0w{CjYv@v7HXZOiYSs%X>wFy}U>aHyUKs(N4XS8r0KWqBHB&hA%IwBEo z`KB}|@ciJ^*ivWgD+`N_Z~nCCwNhemn$^!Si*Fm~{`U+>>-%tw9}5eQ3`b0;`6G$p zy3mzQM5sA^DQ_w6kJz|jpkoIsb`cZ!A>nx>>m>)cw4K8_Y zx@Fzn?c%dqf=tVRCr7DAS@a_j+r1m(vS7n|kKh-0$_>`HoV=4KBu*2#9&te6>!Y9)$!MH+L-90YbR z2nM!zmUu08y)Ki~H*zGqFt;A#RLq(pt4Ja3pYtY1Nz?;ekIKJrt=D>X#c=`tDS>!lO zrFpQ65@Vrdq_`dSd$7DnZw5b)Mp9?Od(M&?K=%F4$$aF(m?E0&^}fvRrw22)A)T|z0w5vMd3g%sW2uHRs& z$2J2a%sqLifJFbCk7f4*SXeH71Wo>c1X8S*X^262udE;L&3{wQ@?EINJFNS}4IpU% zcd%2Si|lZ$i&OehmgZ{7BY6_wIiSQny-#JmN!(HeK&cy5MvCCKZAB!`9z18(tkN8q> z7oIL5P-j$--vPsDrm07ssPy}Imw|ESf!%dU)2C-TPm#0|AwdXQI!~9@qq+ncf z>wezH^)KW3uUoTCnt78Hy57_A6?U-is@HlVM4D!+pa+>I$%Tr_@wxaB`h3ohq*A2g z$kH&=V{;>sWKQ8cDe8qp44NJg=C0kJeBtC9k$2!rIPuChM_3Iv@64;`ajQ?ui}~`0YLAx=ANWpKnnC_h~n>lUW$&xSRo*7hQ?D` z0gGLTtEqSwa1?P0mpSN`F@n4`J$P)d#+rZ^>t}EVJe96P_7OP~p{es1zd&l&dOhfC zC>iY<1_HJgzuYqogh}JE*_a*yUlhO}=jp44iNk>BKgYDvE}8wtJhOTG^taY)x@Ixk zmIGe)NrAxIY+CGP>6s$OsY7+z$g#|TFL6L&dA8Y0WGKwJ-0U*BfqO}FO$b$PrZHVb z!mSKO@Y}oufgEQ4l}jgPql18fd1k)O%~P!XON2Qi+SPg!*KRc&J91fqnzx7TS4aSK zPHYskFss31#~?q@e6)z7dLBr)5L&Z;5*0Mwf+PgI-dNY^9+H%T*1G{{tym{MG|Ur0 zS2M?Po?vfeTzq#3-6L>}DmH(o=3@$_=ZQZfGUQAGA@h5kHj{L_k{{jd1fR3@ri3Vt zKp079ZKY#delc?^?;Hn`+6%a2YB$a$hl+3p)8tnDP6>PW?BCehfogZ&$y*dTZUUTH zH$J*~et~@Oi8RMYJzzon);1H^qW%aKYd+wizpnp1?OW%B-^9LOtN82q0^DKO9dKR3 z9M9e~GarL;GaEtq;k?)Dx4jorJBA@yk2Wdy8)@doxdg0EH!~A(w4jhq9;!xZ`SNKs z=06$3Os!=1HfGrKmVayh(uXV%iuQ&}(;8go!xl@Hu_L$|?*|Ijz{q8Tfn3SV`I%D! zZUQbdGyG#{cjcFBd3h*BZg=N9KcBp8m=EJ}K~X-1~s1TW*CtiWWW6i@}oT z9FD@ZGokp3whn^w^dn>PFS_^dasSS%=i|xR1iz1!g;r}xHt?9~x1rsp_vZ`8I;1^q z+oNd?AQIY)34hMx2*-sO;*v1byKxYKs4MIq!drH2z(LeE7*;;j3uXwPo2_ z&Sk{k;zYj^5z&E3QD z;RVPUfVSD+Y}0y_DF+6+=+_>7UZAhc!wVanw~{ro`O~Ij3-#oZ!~c{A)7@1g%{{*# z0vP1c=!8aD)`1PKd?L@D_fIQU-}C&v-^<2h``;+}{oC#TmuD`M_wg?25|-16fI}eO zAW0NBsOnUDI;o5G_VMuxTE=aHB+jH{;1vlc90>A4vD4i?UEm#8@ z;1?rpJm#7{c|ON`sp%bQ@#$u-g_irTjE%*kQy3o8S9V}l{k*9k_TEtXMZ?+a>ug9{ zw2S`AWct`~Z*D1x{GeX99rmuwB?uRW@bMrMUeX0^Zb9kb4P|5Sh zZT8KaYQ}dv_GgcPz63L*bSl-*kE__J|254Vq{iYWinUmk((XyLZZ~%Kx4d;^D|4t zVjI{?r4rT_j~1Fd6sq_h^}v&y2q z$AJDR=AJWMMH5T-umoEBpYvgkp5xs+Y?u?yl#0nZa()5rl7RE*0z*#v#~r~)c0eSsn`B!M@d++O5LRF~o7JzJQLM;jDn!16k;iTx4)d2!AIPwoAV$4AEKkq4Hl zog?IF4Cs~vT1ss-!$()tT5+fC60+nVFwO(U)@;fK9qq31r$>Pndi=|wt?;QlEXROB^I63cYMi;e-_69cbf(RHm$j zJ2l_}ALVk{n*S83%l!HyUq!YWp~>wj#+7foY>=;B_w+=P3F4buS`a0uqIQ zwHb-1XB6ht>8&aI!%&5!h?Up|{E6KnIUW(}iD5377b8X4SABQ%krg7s9nI#bJXA{f zx@ky(C*tZ9yKA+_bkO9PMti(6~^S3pWfCS!SS(0 zQTg>0WAY@1n`x)GNqfeErUtqkuIwq-w(^ou)}L-#@8lpG$dQASb2MnVrj;IG`ANVsEN|R zKJY$ygb<(bKGnRy>|*0}K(IfzDDVJCZ5pst-@-kyaI=<;*b8)WdB-XziqvXoyEF$d zoikD&i#%cigy>ZTnIcV#WimT00E#pRa^2`y5F@%yoMjXRw@f_Q)40okm@sm8>s3|8 zLKoJYe}V4@9A@x?`sb4toNjqa`=$ykKm^=7&^IEyP$ej?|BN%rH=XcIgfr6ynQh6j zvE4r`Yu(TBacSB|sh3)7&+K<^Neu0Br8B#yE>4qGWe`!lCQMP)W~kW0`N0J2BOu#x zdkgFUG-S$;BA56l*2VLme<*WWl!X2M(+`{vfWsKDSO6n`EK;(*OEGoC5#<7qH}?bG zWUcN$Vn-P8jJ31B_t(D-XUaAAiVSqF2Ow4tvNA!&MYJg_}6w`80>LvjHk3b z3EhxQCbMiFVsh%R8CO+CA+hi7X~rnJLW0pOgIDY=v|q~i*6mv|@*V-2YHV3r9%{(G z(3_@;TX$k~mbYl2ruSMij4;i)dDF^{d-%?^-;7y&o8aU#1~-+T=s?c~=%W0vx=5py zBX1q;8btZ?T1Uw1vzX69B)KaeIlnp{>h`b&&(qiK7W#e(49id>G_3t*G)A2}aXa&kO^9>p$dTC2BxtY~wS~;p7DK3V2cR+7l&)M3&w(UlX8Bjn&bFPAUFYV@EE2QW4TyEL z&-E&bBd=Fwjber=B>UA&!=2!~T_{d&%v&i=F87#Ds8(1iPF^(a0IDPng8M?+O1sO( zEd|K@VzDz~Ekoz#0&xEIa3sPJ=KkG9b}TLg-d@FnSv@kgdEopu#fOT#@b!_vk&ykJ z*V`M$PyE0ZsJqVI(j&-^WB}U~FYdcIDXEtI9L$#T)?~?JuHU&P{6)t?+0N%&IvD$49q!e2(F^KWhBO(O#-+*}0)Kf6}+W5{FQI!i#Qp z&iN9t`@&VN0;#j`YEHGGzIsD0r|IlCD~{DCt~tu0-QV^b#oHb~Mna2>CNM)d6`wk$ z443JtyQx)PxXb3E`SvOM8!V;zMgi+}qcGcA^Bx7@+IH&)`EFFK)|%FW9ov50b!iXj z6+=PHF@9Nhzw(GPGN)J*)PbvIkn27?Qu%5nu4TP@(MWl+=a#|<*w#X|E}hpb(9M1i zbir+D>a}iTg1#Zi?u*nnVY->FcSX&RO$T;6iM!036g4)UKayl)9`!189rUFdfmb2u597Qq+tZha}7!tLs`HjDc z8>Rh7?H7d4Hvu>Gk2)7}6R6+PMBdG=a9sFaAK|#h$V-bBA}Px79*pg%w^`NCAqB89 zkGv!q*kKE~45GNiouG0^q*mua1iyHpf77^{1s6#kd1&jozA#Ax1mD(5E_Xsrsk1ht zrj(70|H5a%R`#-AtoSaQUYZ)}dco8X$s`6LV{gyy!@P8q$aj;#gYyf!_on-((%a)M z!7k1>ua0k)I9fQX26bx9be1Qpo9c4;j0)^E5#VlFGrC`$mC_dN0AsqQ6(%)STrxOb ztz^-KJsxu6Yik!@ruogl^Xoo^FJY86w3wo~<0^QA1}830@IJm#>bUR5oC8jDWv{S3 zrnuN$L8G|C5_!C9Jmag*6NdZaXzI5jk4PU{0i|m18%%Cv-L@XU0fc)@p)MY;dA?NZGB=tx(x)$ zd2m=TA?Lb-jMjXp(w_O|?4mkA8NOb4^6+nn1m$QJ`eG3^xX+F~vn37mf~ z)^!e%^Ob)qyhA(f14m#q1@K2)3cUL`2luOTyk`P~jeRuFvUy#+ESc|*a@^ksd06s< z{@h*7l&61O0G1`rgd{obW0rBbpaw7)2G`YTK#)>ga?sURGkTnMkuTBvZ;j{Y4RmN& z8kHW}CIM{j{ihoTiG`L6gEfWoYPULgb-rbk19?{l ztuAc+7?!?vgETPm?O}Ns#SA=nCPc%84a2Q9v15Mo6v#X z?k(K_)@Y!bny3jCDFh_?hX#38Z2nl}RvUzcYLqYEJ#OwM(XmR-q6^Ob*9&vgd(g843 zrj64D&<1xS&^iHnHTX`G&}n9b^|poY(N3CAIx2AFYpQ$A@7HCM(+P~vf6ISuKXE3` zisRDQibXg+&H`Tuv0OkDTIWZdr7JZtmL_|}Ur%R$F+djI^r6l#8=$V3ADH=xcJ`jX z@sxA?A~564!_R1S`}D%ba#i0eAn8Tg&D-ETkqLb(m%C9*eGg`8r_&Aht{zT3s$u=p zN#mSux#xziC+^pmF;N*eFa{TMRnIdjh4#AM%WtMrd{oO_7e%akx2BZzR#4X|>jeAe z_ZU))Q0XXk;p-J2Yic=@UHAT4+Xg5pb&>5fm_O(P3@Q(x(*tN5Qv<$p^XLEF2kyTH zh5p-UlA{5Z2qd`tu&H_G^F7b=oZnx+^Etos%F{Q@8!CQ zy>c0(yk2d+f`Wpw<;C;%3JO1x6ciN8*R7GC0ru~^E&sC$VGla1P}Z?)LVoaLz!{q} z3JMjN4GX`nmLLCg^P(Fe5B-vBHt^YUAO1KroVov9BSA7{{Ol?b1#1%{O85P|DRm!_X|Rg z9`;@(m)+M_dWYSwLEn#F4;jm+`2EtWQ=o@+D?F1fkQSv(N3lOHjd_Gmr((laq#g9fUt)hf^z_%{ z!nQ5?vCuG_h3D|b8f5;UB!VGnD5sy_*X4|`S>psKvQDF&3q*f@;=SNrXC_R$bCjti zDs4-?p*O!GS+BP5_v(dp*E1mg}S z{n}gL@>Q4bJ#YS{tD8oIy3~EY0fSxXJ5*1(QSpvhKd~wtFHiA5-obedum&7(M;-TZ z3HD~lh+LGSZjWf6Qy~%_Q())fhVMDQ*cKt(d5y<%onzz6#$K&V>R$`&z4net1EoSp z$4SeWr8Ij7k{S4 z13;Rqcq0uhTd@1Re@rK@g()W716*>*(65Dh`&#?W`yVcrH%sfB=%qRct3vn1Q{Ir1Q+k+oO$00+&;zkuHq7B$@of28xRrIk()ri) z>k3HNlyWt2F5W_$Jv`{Hy-a$I!hsJ}6%e%-lYezyz8jfqew~}DC?A*J^0)S{1;uu8 zYY2sje8H>}v~IILn^55(ix}~V6=6sL{p)bHkjnUz*Md~zYf#ChOGJaO0{GhmEG*)v zY|NV5`|JVn{^?--VBb&0l0qMl#F!xn1+27e!)LHK2N3=$SS!%;9yUFtm6HQYd1KHIC? z|D~$U4)IxrQPBP^kgKd${D`p1ugkw(IoRE_z`o)cu3d_^C3tg~)BPan z+&*mEg!W@kO?0N7Knv#w9&<$7Yv_+xqMy&R(+z2!ZY%c(e^aRZf4MjP@5bM+bNv4$ zvwUA!P*Bj~lc)tcd})-iY@(oW=j>eEO!nf}%L*uCLPiD{uJ|lx@sZK;tk&XT1%*%6 z<9$o4fC$N?_ea^1SSwOk6eU$rP6 zL{6q-{TO2l*{ds@^M3BCeB9~PD`%BfhGlB5 zj4NI_d-vr-SH?ZNzjC)VE5k0Utc-J9Is1BL*z1Y^b(0{ff8skP4lC>>Q1Pr?rMc&5G9*inf<2o-Q^dD6XvsK{Ju?3A{l=2IHcH+ME6rrT22!Pj zi;q4Ezc62o?W=8#`V+h)A|aeP2!@wiy^EpCW$#}&w`Ybg8*Wc6N9Zzlh(ZnF_$Te= zP?ta^a@WvSayFu_8Z`6MKXoy5cX`}4iVwT@=a%(@RfG2K7bbAD!hn8v&s?_ASs#Sz z>i2nuc4NQN$6ZUywT1g38{?br0!u7f*rIL5jdpd3dlF$!VOT%OQ{=JdOE>iHV3qc& z?)AjEHA06rpv0}&D8JZ(8qa}&LIX!oF_-m}z+*Q*<}0~*4kU#NT!#VwG(MzaEq;%P zPPDc{XOJ-zMQU1MRFJ>XXo$_o3 zu!iX4vabYDPzjb5);J8*Wov$fNh}kJ1~@R-jmr1}8AO?0z_vl{Z#osYjaafpTGNL0v@1aT4#-^GZ1BQw3(Joa($}zQ7Ev4m$+hKVTC%T@*P>kNOm| zqyiVv7s%p=%d=I-W(8y+dgSdg|4B$*I3i+sUIo1@>!!_dmljE*Sw|g1d6qy)&f1^QB|2tV>?wR6$uv7${fG=Czyg)4AK}Vo(i+obR|SLS zhtt7E?=QYTT-lD_Q?vi7cd3=!94h>ePiDoKJ$l%(uzpTB)|GMS7a<$-h;n<^zBZOo z9vL$~s`i5D#;);0gP4(!qrt;W#)7Li)}}JsOmJlk$ld5Lpzq)miarOCd(glDt`>Pz zG93%O^b_4d&0h^pba6B=q&FvqxpJJw``w2*lLg@DI#CkzsGqxXQ2Y;{+5>!fzSN_b z;&~I_Bl)ZB+m5K()^HDHOo021v<=GJ2K4k@`3=VsN5ylVffzP)17ET|y2t?6-W&%$ zq+Klr^NOdV&18FpCB%X`ov#XwH4_|4F2&j+tm5K|I~<3guWyHCuWlzAk3{xGx3z5> z?><%OxhMMk8rw9Zl1C1K20dF;SL19Swc3+aaX+!1wp7>D#p2MY z!j6s0jxwBH50Y1b=ueMSZTIci*vsJyTn%=LJKk!({hhf0!Nv_gO^SUw$_G)rPHjvc zHKakdAkl3ASFpjD+`Z4ElP~UT8lTaJwBrYk5<7|_FDv@b-A-%{Mm1Ihl#ew0hR=q8 zWiLZ*nZP)4;rQ^Oc4P~BZ};x4d6>t)1)&Ylb9zk%cjXe-=CQ})Q`DY?hRxEk0LPrR zDLq{%txB_^>EfoEhVj|>r!9`k4~RTx^o9U9_mA#@+uFVfBkDj{2=Z}P_%Vv!-rDJ8 zvWj>zxm}`$I2@lZzhO4&cP1b;7B`{oP-Sq~?{wMd6mJaodJzA%TU}RsRyl*n!}hn_ zt~ZLpK0SCGY9O#-$2~}#(9^dfe0~an1;$F*9cncViJw`ch?nT_Jzfyc4Egx`dRz-aYqS&9Z!(oy^kHYjlXuZX zY62ko*BR4Ey(89iZ}V%c)k27W%S)WuSGmrM6WVk7NgmNP00dPx48$a%Y7$*JnY&>7{FDo@+?wCvfCcbv*>>EcY81VEvO!LN$E{ZDZfciE`lve_oiuME z^w*{M%#fWOE?rj&v%MaNoIXDs-I@%^l6%$L5cqvogGe*{#Bov(XgaUvZdhrT;{?#T z$f$6E9Y;OXNm5NIY+|3_#67@g`-3GsM}Ve&AW_$jZi>4;k4vVh#MS9C`twe~ zVpZ*$x+Z?)#4xlC_3M-u`nG&7uk8%>w!K*0SEVSfk(#iT9#MoZoxMSH@AwCXtF5U+ z1^QJ@zgA{)c8}H7CPQE_UIcjd_AWgSi;;-_>m_h4q+oaDi%v#fLrXR#Nq7hvUKp6w zW`@ee+vU;FsrkRUwlQl;;rINwgg)>;f zDC!Jz(Ox+{@k4EGq}7cqt;BgUz{6^$x2g=^1HGRx{ga*fzG7s{Tmy|Pnr`>A6KqB* z6Jo#IxEeH+FbIOJ5<2G{EP=moUbmAHme;U;)&LF5fLWZiVHhFEBvSXCO}JXNGg<)h zQByrlfX#_rvra8$`ge7M9bo9ex7~yDV`UyZ2bv(0FkF^-QQKOS|E7RU*1y*Fs#M;@e($G9C*@PPYjzKwhnH4#zS>EV7t&NMDH|pe@_zo9fE@iK3 zC#D@){Sok*Rio5cdh1I3L+jFeBIl~tlPj=OYFt@R21x#;hg|VO^eg74q)A*%zXdg{ z<~%@*?RWi!dt!Fr4CHl4;cvwVl6Z5YFJr-%8l=qWJ|%tu18f$6ln-aAV&QjKMjJW9 zP%AR&y1}dMp4pes8wzEwSX;mY9tK;W;D-xiYHf7_HuEU?&a}unHm2v3hd{5F0|InkDhh z0JcYXGH;6`+vQYXC-bz)Dj+k0u{dVzMd3r}w^N^9X-E_KpILMQ86jKsL8r+JEs3Qr&Ip_?C z2v{a~8kWYBxyc2hQJ2R4fu~dkVq)TS3j%+&%Ftl#EVhU)YdNk;p`&p>H;t{|^dOqKItmUr@r9pB$Ufo|903^~&A6IN?c0lOBpSa!7xR3E z;JDhf8bCAk%W#`MK4zDXm_A=F_d4ZX=%bU(hPYaPS4Zt<^4w>;(5J=q;w%xPw#y~j z_p2_N4n!q1orzprm)WF`S_v-!%_RH{Yu}u2)?e%coUM2VeHp^Lh>sOb6>XFk)Z&jN z^FDmX|M+5f!BpQ?z)Vt00Gka$8TBkC{(hs4bG|IPd`#UF84>W~H$|94m?=&wNn!7& z1lMdkxpo3CeI%6Dqp+!_OkTKz6WUJY8m#3<#1)T<+oPKs>YTONyr9GLU5(Jp5%8@% zqql}*R*3xIpk}P3AJ;PDj{%=nR+^y zq%G-of9;{TyxDDExzG!`jbMcXGDezNq78KES<+fp3EO>2utgs;OVmxA7>cy{NVFfj6Q~>v ztRxN!<)0CXuHPaL>95+p&+x?o-d>X@dw(p*GfW?Os&`5SCPK!|x@cP=$9DD{NneS8 z_-Z2q;1lS|sBc`$)YH;4ve?JmBATk*jMow!Y~zt9`wknI=gRfRt{be{4;_|ncL(YA z#2;%K6}7=m*j!i|(w!kS)E3xE)~twn)otZq16}3y8A^ap9Sfiz=JVM@s_KQ}dNqZb zvW*m0ZbVjv4q5-__%J3zZtdl0gq5#XP2Z@cT-+P-FnjUR#8(AISYIWcS1A+I6X-UO z5EMj?&~Wo-0J+H=Ik$*P5HO!ZZS(PEQgc9fdB8Aq*i4?t$c5eO{yOuGXx-{%w|zYc zKaPO=CtVHH^mXHRsvm`zG8e20|G+=5NS#bJPr6Q6<=FGbi^#|BX=BBBo265(02-ZS zQdG8o0+@82KX7dbe5+<^GqlKHwSg_k+kj#(n1066Se$iHMgGVrsM z+UCQaHL{~eZ z$PFm#lmcX5l?%V0GiNeNi@I0Vq2l_2AHqJ1xi%pcZYWAV}S+KtC%!Yej~ zx>|ZK5TWuiI7IGJk9m6s#(`qD#8{^>Ye&VKay|vJC@H{SxOcXo*rH}LyC#=qYzFUO z&m#M3?I;YX5n;w1cPFpS{;8cfkchgWd$r@edq~(J98Jv|+}qE?Ctm3>(6v#+X_B4e z)7xoGXPZ+i?(2ozXH7lh$i;7g2`ggU(<0eO+|fQ2hNqh2JlieHf#X96V^MH&sC6AH z6eAyqov1(icROwam^Fb*B#eHwkqBm`aZGkh!w%?D={-5Oihrb9D*q1B@+RDaN)jur zxm#YAt14)~*1R1KTQT>8QB+)#qrpw_No%Zty_-91A71vRA8*XXHfZxRT=X4heTuA@ zMjvatRV%cyY(IuqOV|oW*LI8!o7u&`F2L+#%TT_LShND2k2f9t50>|mrzL+wiN4K< zIzZnZ`aUZRc1jeV0T8Ee|C*rYk>>#BY#l<_ReeljAuL>2z$O~=hnL*tS&F#*9KeKc z8p5nA<OBESpK5N?%ZnB+2zVv+{OiJ%9P`TO1Gh#YS0mAM0^TgH<4_x{LeH{g?Q7A``>; zMyh>~J{MJUe7)h_Sz@J0ksGEMen0RzwdRBxN$M0|(Q)TR7{9?;A5Mv4vv-f>VV$C~ z{Dt~65An;;mFO|g|6;(-;-j>C&lRfKx@4&V+UhmcUm@g$suF7KS9vH?upok;#Yx4T zlef~37`aCqrq2dueaoxz>-?E9((RbWQsd+^A1UdLAMn3A*%)%l!=0Rw0-2#}N)eTk zA}pIR2!xcsn40?P0+RFeVgRBW7J!%VnAb;w56e+8kZP*T zjkBd#H_viI13@M`tOVt^fo1BU9*Q<774KQzL>*UpxmU=R1rU!JYYkCc*~uK4<|DQ&@3)963({tMWIAEu;|NPTZW`~&kfH4ppKy43B+&fHxDEs49q zX@W6JWYAOk*{;c5d38n8kCwG~Bi4I?^muN9_nH>x zQPr6PoN06SKRA;}5^Mgv0xB}tcTf=p?ou^^!QbxvD{c%gR8`mF`z)Q2;G>8{DKAwi zod|!S5r(oXX1FojwdCP&HvC39=R7^QQRw!)Xs)=<~KtB=so-v~Vpyw>74J{x*+8NaGiuWeg!9nl}8 zwkeFVp&NFZi+%@VpFCfN#Dev0OnRQX#38sxpKkZ1Mm(zd_>=kM&$sx zk|BfM8fTe}KR36RIkU*p9TeY%{I zMcQZpJRqVut{G!Ffnt?JvQ9VPouS9LU+kh_S|$$H=n8$;F8hUZEHq$%W^wxN7JIJW zX$X+;(=Xx%RhDWZvg~0$R`nO39#}dYO;mM8ngu?C#9d1MY~NHA)_!6Rtp>;V2F2pN zKX&aDW_LD(&gLqS-O5_3+rnWMVLjI0 z0iT}#dCxg$id-ul#dheWXn}>O`Fu}Aaa`HxfEDW{!Evju;4kZ!8uyfLzRthX)4tiw z7VQIVQ6R2yqSn;<4I<6Mr){R5bOM=o8UjQ$D44FmO<>j0G(Ox0=rA*Gjrv)Re5cnW zuD8ehh*>}E7e3My^I&+Xb6^(?85Cx99*tNsbTv^dK8L>8lS|dL=k}_8*zL6{jBWHw zd`@OgKef~JsK}0a%dyH|AlIMObhM6krGX(wDQ}m=eh6%*RlTuB3%|p&%`C04gH6eu zbt@Ni?U$KQp|<)zS!F*~fd2vKEIY^_bc%k#Hb3jr z99%O4-bwjT^`LQp1vvYWC~z2iVb7gIESdQX3KM%S@dWIf@=A|@9PZuf(XAF5hIKVK z3_{+1)H}Z9iLVb(T*PIg9k$A(ltWLJdZn4ZOWyo^KiV)KGCpO?-~hcO{DQZ{-1+gHugxaWrua zIHMmElwEr3)x+@R7a|>*9$8`muO<$aGB$o|SrOBiS512eXObb70S_D<8k^tuLlr^_ zK@Z^ec;+9puzXXn^)4kK;_7v zLk0$Su5K)(KFrIhkFZ!p?k|JKA82;Ddeq0yH({JS+*@LCUrKg%K48`sXZ_M}7xZP$ z;$2FYSj(%&-Twi<`%6`Jhtgn%#O;kdxr1B^d30W1`o-mzD1j=IJm* zunp^(bQR>4ppl+Ppv4V6%isnn|3uQl0qy}?d}wPPkROgeomZJEW#jufqRG;oMEdpN zL+<7?ebDz40mSEQ;$a#)EfZ6KvPBom0-k)Hmm|mj%2wq6ZOYzlwMGc`NB+5A-hCcn z284d?B>$r?&B+DUZ~d!zO)?~ry))%K=cD8?iLQJ@UeH0Y>e;3dRMFpWS@8@`Au7@* z=s9SsOzFALEX5&b=xZA^GduLxpgnWfug&BhZk9Ft`}fG(-4DEeqdY0wJtLf+kFR^E zX)|f?AfZKa8GU>IcemRVeo%are7}KFKW4<+9&T8{*krPgdrH)o_1((Oju-USkFTEv z&SZ1b!Q)-;fak{3BWC`&yyt2EcOw5ABw~olSuCK8EV}Tu3dVq^(FN%ruVdtR!|U%E zUC}(}Rps_ZDxd8U9+t;JEZQ!$n9rw{9urO2MoC?$=K{9z*r(;UTrud(WWA zex>>062|n82-xe%wJK+;{?NRD**(+qbp^zM11g6Y`!u8xFTA!c_r6M;&#ir+v}G}~ z9}nLvd5+%)Yn53CLQEkqCxE51>1dVkqaGHcPUU5%=)%Gi{9R$n-6si)J>P&tIeqc{nd`N^dE=W$(EVls zlDl;PZ@JJ6o;-EQTPk66-%HAj;r)w3o5GbCzLT$g$K`XZ}U31X-KH2v$hE8AhTf1HpE~e zBbsUI+lot-IXK$kL6@43CUa=zC5IY}lt7t5SJXsNy~&Hd$!Eg|VsT%Xzgd(2v_Xr| zi5`215zDI|0IB6P;b&{gtf4UK<-A(Xi0p=;xNGoBr~}EoVWwt3-_^q#fQj&w+%Srq zsWE(?P}XG61zDty9UQPlE`NGyxNp<}UmU#bKXmNie^HlKRXqz!Hx?Bv)(m1fHJQ?(?Ywtz`f2oT%t;erFS2 zS9~D+$FQ8+j6SogLG)CW>l+&)UTJA;($#R@bzptH6@|{;BWMoJ#{WXf+2>+*asKK4Y^N&8^rVrrVMoxdX7mZ;1Iz}L z_n4VbEz3`X8Kb@UX(fGQ2hz{m$5f0w=OB@EYeg3Ht zbWGI{HPiokP-c;HpRLw@J&Sym|&Ww6jK5*sw6mBhI*_j%qh&fzF$Dv;rjcB0<}274b6o-p;@ zQu-=4vis9h_7MizFJwCZRcQBam|f9TRRyLKR}Wxke@n!6qo46N24zL0SLt1ymlkIQ zbWTzP=Soz%!NcRi@SlkHB#9eGH#*Ng6`XJkO>N)8DVQn9gHQT-&!W0kZ-p|#n4vYv zew7+@O!UT~t@vm|ocPC0Nn@P|{q@cEeQW8UtR0q%oyf7CJ9Aadz_KBPTak_ru{KA@ zVvSal{b65&R=KTB0M+SP1z}~P@Wm8%3%Z2QzhsOqF;AM-7%FNFAfuw%zSx6hoB{#9 z+X7Kp!$>OA75S9Q(Z&+(tyWrq@|rj7xSU;8FqSZSLWHyg3oScJ#h~RcdnV?mxGLe( zg!b_pf0_tpUKUU&%&{(NuqvG>!_E%3j!k!oT=}x%DBxS-RANe#;UW39#L=Zu*MR>9 zImwEh3u&iYEFN{2M!2dj3a+Pq6=vE-tTs~g&E^m@(y8aB*Jb$ejgz?SwQf_yM7MUkz4usrFS6`Sg5s!J^$7X!f${$BNYjl;%yMgo`b%wMkR)1pe;1u|abrZKvbXvW z;&SWCfT(OAuc89|A@>zQ z%KZo$=zU`X6V2P~Cc#R-i!h}KYMWEgCCXcYry7y%1l7^YOnX+fAi#wb0Pr6g3-h{S z%%J4Rz(QTid8e4!(ql-fC?W(M=}a(NJi<3mAMcx}c25&bh;zrPtQ^cPl_I9}<;9$U zx*jrj1B!FbeMO{vOxcrZEo?PVq=g=waZekS5Hq=P@jD$;V{%N>ErEAg ziho`#3&<}B(TXESXXH~Sb{B^9u*S{}uUKk31?G^ec~j#?$eY+Ps+x7uM*a}B3+cHP znbY^Of6KZsG>hg~hFar}ReVH56K2hr@owGsye7bnyX&YX8`r+~y!-wcu^w~EcxS6# zQA2{X-x6}IG?TU_m;;V1i*$iyv9f zdGww)*TsWI<^IA=7G<|xt>}p1vqf(E?g`XIeT%&WJ5*T!6O*`-s!H7Gx-$p6aL2II z8jP4|+tu%~Jc_cp2g`GKlw_IRDAK(?3M9J*@kT;mA4}Z@IWt+)z)uJ(WWHGJ)?H(V z)0Ug&-i#q_0_1tX6YH%R$Itp`(W@G#0%|*@kPZPtP9}hZG&V!9hv_1!TZ*hST-#SW zD;Vp-_eGR3JX=sjRt{*nS>h$nr0M9cnbZPGRj3(OI?Yu-#BG5&4%mAlvm$8h3iqZ3erHUG3ubobA2i{S9kagEje)6pBJBN!5d{5)KQ034rMSv zLwVU8@@1(T2PAWW53>Bs|2= zoSdpMBu6?{NmR)+_VgJ;5H*xvb?VKa+Uw}GS)P-2bL(b-Q`uFh*Ms4dkmH;WR`*_C zg!ty)8`&MW&DXIm;po-01?-goZ2S+QoW2q(;T@1)_L(YiS@fAHWsQ!**-dKCP6ck8 zi|;mQ7HNJabIhJM^u;7F`^ll`{;laJ;X^r~{0ee8wEj75+&1Z&n~jw6|YJyKSdiQ zpFbp9c!948HF)K5cHSN)n4CL$V2*sSmx<@2R%beuo!j?1&PYrK*2Uc)02n`ZtH;zH zkW8yVw$-bMsOk`iMt+TSFeat#dIw>TF_a;Slj}>zu)vLmo0Pnmi9*wXVNnVFsVV*r&FD^PcoY-mY)_u8i<27RF$GJO z5G!_$XWr}QL5BqMZsh$Gl8{)}WoDApWNNaN=k7R4!Sm%U z%YwRW`R3!V7$dJUtSjgZVC*+fK4tJT{huppidnr@{r8wXT^ifVchkZ>6!QbRw5RMs zJiliRl*=2x)W5Ge6g{o>fUi(wvLL%agUy{P+|c0{@k%qbr0^cUgB)_e(QF#FMwle^ zJ7+aP00)+OEe`iE4z3;jYk{m?&}??c`V&WHr!>n`n~e?`O1w~ZlEhS*PYMI+sNJ%- zy=2m%DDm^3g8rC3tT?SP6E%psf-YXPr+|ORB(6ynH_VPwG9=f{J{ITHpgDT(9}OkJ z8muOdrj)V6LMzR*VuUG~y6@lC2Ng9Z-WZr1=^flG`gCjc{BakRNJcKGU%rK8wK6%4 zy(Eg;kP z&#>TVC-+N%bsd+r5r>tH(M~{20k52wHT&BU+CB_yD)fSy?L6wB&0czRza-+ZV@E8f zI6Hn&E72!35}h-v>fn<)UnF(x@SCgYsF1rIXJjSU)FXA~#iAc|>irF}+GcmK8#e$? zvZMZ}zaP@s-78o%?KXE2HK%F6>FJx8F2InA_FIn3B4$o|_QR5!WXS8g_V&!#mk-sS zF!Qx|age*6Fs5uabK^zt<3@mxU z7oU9CKdy9O%;ub>u(;xIpiOJ}?b;EIMX#=%-6{6yJT6@S?Vt;q7-q=e*Ef}!29;+7 zSR(tIw?M&Yd*ek9Wd{z$Ki_!;mErBW@(ORxo)GKr2>R)wil){fax`9Lr%Adi@XN%e z+_!NmHYOoV#hBKyHy5~q<2{y0WX$i=n?5##9hiGwOc1-ETNUvt-dO(4tkldH5J!8e z3w1zpk3BT9#5_Z7eUmO8*j%EVS}vON1ZeXoK$XH0y5 z@x${IH(zzIY;?RdZ$O`S0xj-fL}YQpdbXAF+&J6?uYAkrQr4K^>$$4&_Bash>m=yJ zL);zL+GzNhL@|!c;)U9_?ZRd>q5R#z+!kmPVUd1Y2*2#B+TwG^Ir&4Pc-$;SR+vm@On=;0zM03C zjee^}J?ylq2<`g$KO54n*F_WBeS@3lZ(mxom`6M1n_QBtTo8eR`95-Ld2LVa0#O}{ zx`k83NqE4!zWkl>S_lE&-GF4V&yhsa9Ti1x)ejeBJjx5FXgMui`cHx$L9bD0D*jsW zySsm8bIQHiA7FcYS~;*!lM@5%h0q|+zTTvNfy009GbrE5UyJ!6 zz>c1k$Zr3oDD>Vk-q*jyQJCQacxHa>BvG^ju>skN?%5-(S;{)mBHJgS3Ho6{kQssI zD?)|NKfHF*Gi3FDcAd2X)}Shcek525TRQR7S}`g@Pf&5IbI~j>ku7~v_t0dN+NHVq zgr}cIxI_@ zb$f2@q^RnLC7tNqHEb>b0mH~6gz$W`aFuwmO#r#j1Yu>5KJn@Se_~o?1~le$3M`Qt zwEn+#hTiEPrY`3_Gxt+G4S&U?WsG7pc>@R5j|%(Gk#L|El($?GZJ58^nY(wqvJhPIq zs3Qb=`NHH5zaj1qRD5s1I*tE9i)U^FLM`0aOLZ5w1YbQmN4YOn;`hiO4lRR)gD=ci z-cVk0I?BCk7x@7u#k&j2=?_dISwL6nK*_H;&AHny|bF^1}!H{ z8A|2o;;~%Dk#D8%e|ELdP6(?2k45cU*=@+}9P=YNc3_6HOQ-gf!Gn&y-^-aR<`q3g zjN*V+k!C~hpn*!2($OyIZ>WRwA1VhqZ+M5Hl!+DIo|87PX5QmpPSbHOSRZp+mmSGWtX70;W>lwafTk#rqa-w#nf~-%KSYt1eaR3=^sDnv3_z zs?(YGb}AQ_WB-kAWxw&T3@s5IF}E{3Mb4yse`kKCcRKt2(DcLte<*&-9sl?u$$Wc; zR*s1Kkx-agHU?XkQe_;wxbmiXW8YEQlkI33#bInou+6;DV z8N}OTq5-}7Z+3UnG+h_}?jIcyU4^@_9y40`^`O2RNvj;`IhXa1-B4)WnFPs~KR>vv z*TGBWlRo61NcDz5d;CuMyo-W4`VpszcdXEM_#QK0BK*yaMw1&7i{=?e?)7=uigLO$ zvu@_6=jO`yv(J6k+)b>!6Qf-L>e6oh>YyJy8 z?zIZHy_FGaYc2_tj;Pyb-FjagQIGZwlJBnVPmt#6_l;3Lo-FOCWEiIX>DEp>G-I3? zrM|=L@8seA5f#k`7XNHL{2zv()6&_3;kEQmSRWmAAOmw*Ef$VcQOct?<365|r%Gkl zbEUb}hTAN7SgsNnCEz!o>>yN48qm}3I3uiP&3=!n{Iu&^W0`%o%Jj}AwOF&?G|&7y z`ylYJItKe~j-qqmrwdB*XAVcIU*dvckM8+xJv>k~k*Z~x;z%oVL9|W1pxjCw9g^g$ z|0T~lE;OiRcctpVYL4%rgyG-1sZUiW7W$7#>kO`vMg-NhE@|S2e3xb6l3l%(@Oky5 z;QB^K(lE503<%|eG}2@z_5Bxf+*x{eh9k82g6n3Eq}k%5sR-JfQ-6O9D(YR&x1P3Q z$E>{3wD+I&dwDGPofT$EGr-vU_G{}ly6UWcN3OM?_EoY5X9w(6KS|w{lZI4QcVX{O z>P}q*HQsX0^2-V9V7Key^dL}(@&)`M_qG&{Go)Y3-CW%g7Yd^$V#NgMRCQU@G_4;| zPi5mwPdt9W(;j;^4fE!>FkG-U(QPQOh0}fpntEY^S{%v9urcy1{YXENG95XA_Z32I zwWj~BRh?{;x0n+DnI-K#iVGunKH2 zs7TFQYAh)jU=1=&^y#f+0s5n%sL5VaqQ^N`IpNeaDFYR&z0#Rby+k3_hOw(4e0^>gsKHq#lCKb2>r)C z43!iSNPpm#lyb9teA?`?iT^5BO!*#i>%Y@+4iYuq9*h&@$&4C;I^Oe#9D7Ie@-pDA+Ne;@%iFLc0`s13K??j;`EFf zKZd1hpJj?Q*>RBWM=X`OJ}YPGy;@L%Oop{v35sufvL$~Ot4NZ*=k%GQZ=yRd{MM&O7NYuZdRy(Vm{A@Y3;swPU~gMc8;dXurL>cQv)+n8Wj)1FxJHPZ zEPpQUD<&~MCjDCV$F^J99*3=vMPUUs({b`|Ga<pE@JF#8l>szMqj5S*d9jOzJ1vPdW zt(>VuGq~7U314)7BeLYVqKuFXbE* zGY0i{4?qrEI34afD-}&EBN@BF$x21l(1lS8>O%axFwnb89;*}OAl?MC;$h=2cj036 zwLtzhsXp%j(S9%>3b!w|WXw0Gl$K`hQ@33O^tG;g9$ zeEkw_=lN7|nYfo71vw*0`!~_jN@i2|Ra(Ez`-VI2I>v7gd~0#itc`=H6SnQP^HSF# zXT$FV(v7;^2XPau>-@$MnAF`b&-zYBrZ*SdSJ<8EUv;!#}wH zrwmL!&niO?lWvbBz5FT)egE@W6HMsx`y=Ph>-pg?NbA&`!NT~F-gBcC!8ro;YeDr1 zmLEOzQ-g;cYX#+z9k+h^d2se^KuDex&@R3Ca_&=mOf1zKb=tIEzJx`!(uv5vz*Ir; zEYKKA)$HmYM*Gg=Zdz4!{^v|3%QJ!0u^lG+zKz8Ic*oZjlJ{Fjq8PNr;IRa-=bR-3 z66_QWlSf3-=G~p5GN9_-6E!KIGk2ES-Z-z7sv>L64*C2)?7ewd(rNoQY&m7C*0gFa zmF=dMYc6PJX=SFSWiCiF?vh$6xgc6uV@)cVTW+Y4yTFtSiUL}VmK(W2qG*i)3IV19 z38K$eo9UkB{@w5M9Pe?w&+#75^ZU;O;S1+=p4Yj2uJbxSE}c<3E1HfaP(^%AJ8@d; zFAcw2Z32~i%ewyTOY_f^E&n|N7wz<6>$jA~A2E5DIJ+BtIxz6;f$@vkLBBMpBka43 z@T##iWJB@9#SYI?{&cjFRc+!N2g=w1e>(NYx);MS`Tx0ceVgrT`94Ya;g`R}sZ?gf7AO2WP#Db6ZhV zH%tH7L%9_Ui-{?_`EjuScm>($%w5SNn+jayQcvB-G!Pmeaua33b)<$k4l|O_L6E z?Yrq1mm2mEM8LjpNW*G@>>pG??{}-#-|l{H+h{x2*ut-+%tew&ivg zw)nlrN}KhCv5sew71<<1{0-=QrYLM<;2&Tteb2s$#EEp*N_JwK3lY;fNq$armzo%uD4i zZAt?Qn&a)X9+zzu#80+0P~Ic>T@!vjJUiSBs(3Yr34$qM7;X6}d`5bK{LeE=iWd6A z@RXF-aID2b_Z~8n%a(SABRQMInbPY%YX4>X>-s2>0#eCw&DJ>t0)BGpr>8)7glQg| ze3p9iq$PJ}X^r`ePqx0sSwXS>rylc%uCwdWfVyC6f$0`&E@X0cC?C_S>AmO3VAzH> zm1f;GrSukL_< zevL|N*?l#SA}JeoW5IY9{D=sFdyFEXt9Z5(&*H>cHfEw){8Qt%1%hJLD;5f)T)gn` z4%xBiivM9JNfX*ap%WXJH;dAgGzT6&-?i_8U1GS#yD9sXY9qiEYHQ?BPYaF&Mi*pQ zaOJ)Pn7&jO-tvT&$?ZNfR)$T*Aq~!ItT<>V#3&zIGyWVmaBmWIX-Ko-YGiouCl76~6X1;!eHhy?IN9tRd!UuPR zzMN35-?w1V9UU3Z75I19_%IgS9Rw?iMt9LS39EKBfMr0?k!nAeR9(s!x?$szQSoTf znIOABG^iw^xItIK5sA+Fx+Kz?p%>a*nfi_*E5uY(Se%v#3q4&}djS&OEtI|914Ci+ z4gYJ9@Y-EK;U|BNxHnbQrr=N{xJWH=Ih(kZ=ElUw-cdYm5jA_fM8GYwO)QPMcEJR% zU2#2Z3j>an94Fl+kbxb%>KHL-^V4JT+qMT%4h3sJzLZbeKXr`{!qnM@Noyg!Wt0mv zV|*!ybWukW(Ee|*5HHOo2r1DP0F`(M=EQC5K)Z(pT#q-%)bb>H2OCZ2N!U`?i9>9Q zarH_4fqjqYZw+Z4;*wrk>lKsH5fD4NKepTpZy58-WtGNw@+zS{tRW8w9&=a6KaK`B zY|Uf^b8|kLh7R-)p*%MwL851TmY@~IO^3HYClI^m;9d|e>G}@0ZvSO=umfGNdXjl% zzeyy~4w@Q#8Kp3w9c~*8M>1vA7x|5BM<$qdx_t~({<*wBz4T$fG16%qo`#4(fu;+k zrF8<6Z7R+geS{m-KY?_V9o>Vj$q*p@H~y`EoqAKtJZkF5G1IH#Sr4XW-#&erBrmV# z$N2!|IhMTiz;pzUyGI^~h*8gTNo-d)*#mmOC)yJIO#6}PR>#|++4~+b^_~Pptcpae ziLF$PC?i9s9_!)gy@tGo)N~z!tbX&c2wosrcYyW=u^Dh3*QA83kiCDdvmw4_e?IO| z0t|C^(u?YRll~(dGz2^0Z4l&HX;_~caC(D64&TG;H)Ocm72evegU7m7~Ho}vN3(BOe(A{;M z@sU~^#6-W45?=NBqKS6AZM|aGT``_1E$T*3aR}q6i>An9AaMhKH4ane9YJKgt1c)X zeqeN38;Q?!OB0`@vY`xt!J7$~MZX}%e)iRATb32g5MP_bw`Ee`17VhbEjSKnw`AN& z>eTL4pVoJb@aMxj#^}>#fAq|p29{s{TeT52Sy;^-0SXZAx_uR@s}4Zad)3xa`>M^YVFtA`fk0hf0jOHyzdAMlXrG6e9w| z8kH8;*aXAGeC_R>EMsN%GpC2ysM@A^7{n+05bpZ=UxH)qUu}b}E{0j9h)dskRmsv_ z>PB=cI+#I3zQ5YgqdCvlg$!Ch?mWR^IFW8C%j4;GRWb>t(J0R2nd+qc7^R`dc73+( zhJ!%7qJ_bO;P&8!n*FiC2Hkn_5UwbfR%L-~^0$HVW^vO8%j4q;&nr%Vd3OO>Pi;%YNyh2fy|MlkdGNII9J_$#oK=)(GLq;%ZmM`hKD5QxBlW4$sC zWqj26EBHq73sGA=MeK$pHx)F#_nHDd+-J?t?it!OQb5=ANPu;~u~Z%xM$vr}o&gIK zaB{{abv}wN$t*)=ooOUEH&T6W^zWKOtc zUAKMvVtY1(F+An=Q?TV1)QmuahTihR{nv{GSEN~}K1f$|U$ddt^YgONmJ0*)UFPd| z4HU_>@M!O?Xp9s`sfxq;J$t|%O%e;{%@X}Xo>;qS^BW5%%8fEm-WSYrs!ii^cMU{T z4=09<^y}h_rh>x%OwdqW!&8P`k%@iIhj38Cw-Iq*oN(2sv1A0edX}6%70C-u?eNRJ zK+D=|vXd*S6T`%+VP=|RI)*v4^xjjYJ(sik2k^f36^k*5#~e`&?6=H5OUU%g$6XBX zVP=&a#cM!Z z-Xly^eFzJ^Vp8UO1nk>)rK9?11Kh#l2j^8D^xAkox?V&&#E1|EyQM8{pqstQpDv;V z2G92JJ_q%_yIIb9g1rxNAJRXsfe`|t4hJ|?)z;bq9jMG3hfvO4zGnjo7CFd6_@j@w zL;6aO&iT?9PTU>f(cMe^%&>5~=?Q7QO3}gG6oPFQ)stL0(*%nv0&p&&Wz|72Wf`rK zm`fJa(DJFNaJOKtyV?U>rI+w`%Jw1wUZve1II^iuXT78BEi&9fDnZ<9fq4bWnnI9= zz8&K9D<~0Cu=TdK3%irLwZ6IYbXIIRpPu9C3VQtR@Sw`4v*@^DPeHHM>1C(YZ)nvz zR8%%vJW4QPNDt*6v+r+irQyxBY^HO<5cxLK1uY}@`ZEp7O$m|O3P}UUCq6!l2nA4x z1ul_9BbD{SdWhu)kA~EE%B9HV@KPG_J(n?rK!cu9sp`?)bq}YRvN~p0;2T&{gpc~L z0wbX|k6Ss7fii^Je_oe@#5QUOWxx~&Q&U8ZO<;XcaE7iuHfL0L2v^W{2n`>NW*CF} zPy-{^^9dz$(UuLN!Z3_< zN{-fY6|bQt7wQ%d4W@iq{{%~1_nPy?6RUq;wQKQ1$5*-&ycr{5b+h&m70(`9mvK?~)x>CibTL z2Qu>7!Y_)O(zzG=Y9lYkuTPXMK;AzQ=_lt!^rhIPHcDt;=$MAgbJUY@b_YD8mVreHN|<* zPRyoTiiVEc^=9wY1%u)rp; z@~EW>Qt}AVFD9VE+}kw2AsNM^XkDI(3Z!6Dx&^Q^wM*iY0FK2Ca& zE^z)3YqHIj)e;(UkSw}OpHz+Fb7Q&gk$+qJa-75snl&Y1%f@Qy)muY!nMPb##{_KQ zG+Nq=s1!@b2{rxQ%EHsqb5rWQM53#3u*$IA|DssR2-K;Zi^Hx0h2QCGGCnDugAuru z6q8i80`wBF(rA;;xt!1sN4ZdtZBpw~+`LJ=|A8){2`+liHyj%cih3*j*I8$xey)eb z%y!5&yI+p0=f%oReX#Ctj+~Gy_~p^`J@fIW)Z0J4QJ`Z%XMzce$){#P`;gYO3xFT= zViKTavj%&FJ##K5*<1s5j-S<=ubbg5bZ^kXJGXs&udP)1waczt8+rj2A-K_N1xASK zha;15D+}|VFF?7Kb>{37!4*86%ae0A0uNGf+&*II&1Rc(#w*q4iRVv9Us%IoyIlHS1WE)yENQp~F>IytQ={L;e6fgB7oL&zQwaVS zLdafU<4JOZP>A5k3gFGtUh)igqv9ra2&VWt{9uLvTS^eYkP)=vo;VF~*02&Y`Uk)j zq-C<=&d?JNmDXb6T@+s@@lD(Va|K`JRPyw6i0qiCEa(u<%?60i?Ee;UY5>QI`qzovHJflP`Noq93TlTqMWubHoudkA zI&ahaQHmyt*X~H(2~SyS5!J^pa1y3IE_;3!aUuRWC?gy)eQm!iv_adc znDo&!unEX^euM4oydDu=b>q1X(+PxrR&hT0CAX;d;!qA8(-3!l_L>(?cVc|x)OhNj z)f7oR%4}RT4V_sh7UUh)n#j%|BTX;ZQM~MewZIfZ5M?_19cYv>f8a5WwpVN&t!{;^ zp*$^afINyXO=(Z&3>fz0Z)%Dpgx}{@vQlx8WLhno;e}co(i1tlwl-;~g8gG)#3c`v zGy$A>21G~n{>P1;2OL0*k9@m1=^cV#6o&0QeDw*(YjaJ_V1bI6 zw!W&5kx5lRvyANYk@!o0+RYyF{lhjYnB0y5*}(=~aE^EgMbsRa@%VaA>ItcbXi(xb zYD3fbmiOJ@_e7&>fCdw^>UP?59W*ki_-gw7^aN%MBaE;P@6JB` zw_ngS4`)RNhn_~m!cB@@qctJ|HKzjt1*Z*Vmk=64imxaj@En?yjJ169?PRk@-F!Ue zKlKE(4#y~;lnQ>l-|Z51#j`_#(amsudw7O8qH;ZdQ7JKJ<6S$Ve-v7koRPhw9S8t+ zk-Bz3JP<5qLyz6Z>?^Lh)T+VjBiS{0;_~%j3{1gj@`8f*kcR04n2qJt_mxd-hy-)^p3O+@Akk!o;GzF-I zA)1iXd6GNW8N8{w3lntm%*e~#;t$#q3r;~-Z4BZ}2wAJzFC>{yvwip%`W-a|+|3t8 zEM4vUt~DUX16i25Z0DOJZfE2DKz~?t;PF1!28?rRelfDv20H^)g&%Ts+}Rz|!HZa# zD(+ODe(ifl!WPX8*n}G14(Sm)EtuoM9u<(;$~UZ|1B5*TMKz}T&d^S&L?gd-B29h- zCO2>=mb%}+2kY4x@{@D*u0h%|H({BylaBD$H?P6ybYmHw&v#oqDL_>roiLRQz~HIKQN;I`#y-pCSOs=-3Fog z|ATaklMbpQwK_5E)Iat9l@8!<3jedYmgu1^LmZm9{6Bfv|L0>9Mi*&~ZcbnLYrexj z^|eCon)cEyiho}d{~TaW#N@lL;~Jv3Esc%ITAcUr9g9J8?Zo2vhHu;m!@Y}N*!IK! z8ao2TKScJ)xM|xDfcZ`r`kO6&$q!3UL$wb}wk>?g9o4Uw(|Li9{S@Ehr4VJaL_GmL zFgZIySwP{fHUP{HN-=fbi_{BIhr-vs4_cg15P*|!rp=Pbvc%DqmU6BiaxElWI#-Tz z5A~T*9e-ze0eRLot`ENS>Gh!nJm3qFUs(XYFyxM~){Y9zM&aHaa)sun>{E@)~TB`{#<@4@UqFi4Tzg zO$$IOar5XR+sYB;<=X+8h{;BPE(YL@Xnwp%wDWk~vULCx1n|8})DTxX7b#uN{UQfE z_t0Dj@FGAZafG$VOS8{f4tUy@IAeey1z?NVzQp>Iw(BM!`5N+$uS60_i{w`~-)v}> zlRJKQbp2PQv@Wu>eD{L^dAG7k|Z_4Hc3Bvcy$hu37Ev;9O$dcw!tgFjjF%Q71pFvfm24dx@ov z{Wj5JW*0D^MrY@fYj^emZK6xubw%N;fbM_jy#uO6Z~o$}8&?JX8dur9#x~$NFbHJn z^QMWwUxZ)oz1Wy@_%AZM?#0Jpcm4O{{?A@JD2X(cfdf3QT(j9nw>v<3V0iMY`E|KQ zzF*`9ygBsw@ZU{_RcUr@k@~Bd7qu0z#EA79?`j&jJ@%L$P+KC9dw;|H!QadYGs{u* zTzvjDGt?=dxfg8x)pDt^Fa@2(*Xz|NyZ>ftP!d6Y+v4lPDgGM)`=)JhI(8!ME->MQ zaSLdE1_(7B{I7Kgk>6wEtRb5g;3w?~P%_9X(Xtk9Cs5cr()h z-RH!fmvi=`XJ6~7jP||@3oXNe)r+15DM7odA%{jWEmU@n__1lX(`|CnaFc9evUXZ zZvLP~cX3`)+>(`>ekyDL%$f4b?SmSbwAW#V?sczUq+@_@xB4nO7gX2{kbA=ng5D4~xrS?4je0-dDByVfVA_1>^`oOtA`lnV6l?TWF@7}9 zb{k_5uxc=!u)`7y>46Hj^g#G+dT}&oT4%0-Z5D$ESvdkmF zr#6Fmszfj-pN&_Mx0CL&KPuc$v-0M*KhB|zB5%V=AJF%AAq5&}Nv)_GJsXiL$)Qyb z_eO~wX`W;4hGozk-?S=!N{;$qA8sN%vtyR`x^~+V??OeBpTipV7MxllYC2n|MkiVT zMN(l~gpu})(uPYo8F+TlDj`SzWtHP!t+KUe=e2`!WiZY|zMyeuB=;7$#hO*wg1dbm zoA-FIl&&P)CC|@sU1nE;TjAixio#=|w)txZ@+WEwcK1z7+^=L;b)|KdoWsFz!bWuW zP%r)0Ak}`PM(~6+23_Kx!|96?QW!%!pJ30df1M?=R#B6XGQl}W&uThN=W=Auw7d7o+hTs61hEEJeZ4D$}0S5EUEoCbaZ>_?C7=ubiTfM&^=g94^ zUAHRec%85rwJbT|j*6V_ijZsvT8gNAZfQVwz(eiL7_E{go_F~@ZAbh8D z35|fCX}rLWJa}yj3ok&C$?a`Mc^{Qd7RXRmNM@ZV}v^8?f^tQ6l5_HW-6KnUOu_^!1J&+1eaP+`2Xa3^`4)QO+dFR`QV z*G5+?3qg$e+L5(j!T9Zm45PaAJR}c;E3i2z=0%8FBwpe9`HVq=hF%nf^z_UVLiM>v z&=RAdYmhbpw_Cu4+uv!Yehw+_p6ykwN`+R70e$I>_M%Wd?8D?60xScUUB@<=q=OFT zIW+mH4&3P{_{Jon?9h6!0**WOIu8n7I0px0qgO9p;UO<2lWGxfJz)w!pb6MezgaFq zK~%gmvf~z5!wg{UJm5==+w?@Q+94X0fWaK@%FhOkV7PQA_HOo>{<@$7z2K8#r>f%U z3pXFPV9I`Jb|;(ZEl_JQGEcf~c8MYOR;d3UJ_Op)HZOMLkQpr5M!HLyhIoTdes!RX z(r|5uiNaaR90@fGRsLyHfEKJtvySS)<%+mlz2Fd9^c$H=HXs>BBn311Md?oPw~X} z41S-IEQ;1SJ4jb3f_39b=UAVIsm&JRxpd~K;!us_ORtxJ3fY+5@^XSnskZ+vJr zq(8bt&!cQit*6VnEpvA01ysNVP3xg4ZgIT0GO?9Cr3NFWCV>v>jY3djI;ta*yP3b zUF)&@>EKw`O(2@7t@@ai5uq9V(Huv(hvf^y-Ryn1Q1B4lL9pvtvC^8jbew+O zNfrzOy&@o+xFqkPbY;qpNWNsHDp#lLgy}p_t})T;TVv=JJd z`>{Y2k{XcUSyGGpgm+ zg<=G+*(-s>PhP3EGap-6SVH;a>;+jdA|G=6*NN*8!}_|X%${KQA|JFB-|-UmaO z8YsDwv2)ZoC<**kE=pbk22mzuNM2AYa~!=nc$OC`DyrKR^c!CQjmtL8Hp^wlZl6paNopMJrh9PGxh-HEqRj7|y9Q^-yte7}3?XG8zz{CB zR%^S&8S-oJt6iTeZS3xHF96u+d|30wFwD%p{!1@|seo}^4R#=xP@aq=pz&+Dh(4lK z#)Jn-z8WyEncBK6l-WSU7CXv(Ogt6jDGn@Aro5yJiv7pjp2A)Nz`*Ph_%KnJz^X92 z2HIh}7?G}Y+yW&KC7-K0vs$dy&m1y*=n)gXw<8;a_|b6k!l;XdyzL6mnwoUiKoZFy z60ahF-j))V!S;59tPbkxHNPLUy}$YMX>x5`j`(mXv9Li%=Ty?M@Z+;V2q-|nty|uG zZd6n@*oD zndMFSsyhL~XM4&g2Wu}ZI(Wi=p~;x~k)>_sq4?=Zj=UjxIpF=e9{jreSEqS5gx(rb zL;!E<#>b`<7C&=Lt*Fq9`{~^dN7v_{eyr7nT9vRWu~sXQwo)(~wif*UP~A*XigU}= z5`Xu|_#4tA>vuYdtpUcml@qP0{c>j0?8^kwuiZzKnK&DYiVhyO@L=!QQ$3D!mC&1o z0E_$XsrIE>G**>yiLC*#;E`WN&!@VF0qd->)yF&+4LdR5D47k{om(NTDapl{bz!Fc}+~#hBs0J6i0sMph_ftTUYv&{hE~K1a9yHL+m3*lg^a{MI^nxPW!C$te>LDDD@EkBKo}(V0P;w*z_Oe z0ol{VA)%M*GoNADtXX;_3y8&+1h}(m&@5ZZJf@_eRWC-=kDxO*!jx8HfC~X`KyH}- z?}eESLjFwRxDI5mJZIgZQ&hLULx$G|DCawlhhWs5xzjriS4;YfO!_=*O^_$79On|}?@)zq-yO-r@VCr2GTo;AhOM>FGm1?ph8`7mvNzYuNkJ8R&h~lX;Addt7HJKs zOsGcI_Us_LfDsq0%B~=1TE8n!2*}UPq}fJz)BD(pJbg@Pq;6Hl7GSe-IzE98KBuTy zmt3qfk4&Ok&o&~;Evkgza8?|y_M-Ss9DfS5ma-e8`!5A2E>%GP4Uypge+W>)Z03Kr zoM!=4;p})d0INFwpnDBN`H!T3N6P#^@>+!cs{?gEOIn5(@zUDtrI-2qlTlme5k3GcyMC!Nz>kI%AHm~Z$NdJk}!2mue;OnmZ zz@j4l2{@VpQ=)+X9a$dEwfHCKn7?sx*1OzxfKf@~f0KAIAoASW0yta=F`hs!u_qtO z$y#8M=O2WU<{aWn?BgTi<^{5ML!V)RldyTTrK}t;PGnWu#YfCD;-#BH+e&34#R6uw zI0LmpWeCb{rwk)wr*WZuKk59JYc~9HSn`f6${pc1Y>c0^l%4Z9ZlqVfl;?yR3)7HX=|;TXnh@}U{!V>saiHNYpYvZV zs6w7~peO0uG{RwiA@pEILaUX5tp4#jC z8{_rvxy7VewfN3Al_t}k8^66B4RE-=l71fX`*n0@+N@{abEFZj5g*;HmuZ+elKFBt zhce=iov!fA@@g55vHZ>uimg?b;5h8;dj-ocH-arCJxE1+Y;~^3{5Ek^M={v%?R+ChcjX?7YG$6BH%C2^e8iXJXY31^fqM9-$;@?)OcCm zAAR9BQY}O?9pcNijWgI^;V`PzB@5euCX@R=?2JHOfB&pJZ)kuL;tDgtJeoF$(JD`& z%tmO7Z&S6}bP{eDh%nNVftq>+?;2ZCSp<~kTn{$LeC?=yg)?sgn48pvAvog=5aXVSm5xISX^wuBO>~u-Io!W#o zopu*FFFRWoxXG&jitVlB+Zjz*0Ry`{w-eWdwQF%+c|!4V1gPV{i{-N-UTL_v_u&ih$vVRUCh&tpC94%LRlx<961 z&_z2F&p*u@JZ*e)*!XDbu46u7`|6sg&a}8|bjL6x_#U8R|%1rh0fboi0uyEjttyPiqAuYHp!YW6a zK?7#f5?g(PHqeWr`E+Wn(++g=wL5H|lZHPJmjZkvu(9d6ft{B=P2^6#<669FHpAs+ zL!0h!Hh|q}wn$r^E_0KS*52N9*206h#&fi`NPuSd zYv^5!zdl5e3qqK6pwqgwm-x9QDp@cu8-1%D5PFK1_-Z!gha>yA-0}83iXlOhv}aU@ z6=7$GRH6tZ6*=sRU%(ofw++Z!9@2(gvvm(S4{kcysFTsbB^Xs$M>pze=EWQA-@>K= zSk3#m8-Xt-YEeC~4<-}6A{BUr^(^Cka{Id5_Suo06eP^aW(_N+p&IPy{?{uCN z=obkp&oJYtwMTU-XB0~#eQls0XAClkSc$~Fde(3;#WA&8f{B3iBH(#M)QLq*dBhO9 zGHc%WcgUO;1XKf%KyLd2VQndkn0VuEsaBXIdD48grAb~hSJhB1;;q4&b&VEfAz){@ zEEI5+$)j|25G4uRkA@wkjO zpz8&J;n(5sE(v*Y-|DE);l?f52dyOH*uu-2A84%DCN z|7D2V3wGr_Sbl!RMIDdwWrgxsrz_)OLc-8n*MXwuVJom~)o>Zkc6(P5Hkm%T9pBk_ zIX7)%keR*CiiZR5!`!{>^1RxP5_B?Ikp?27^du~j)^$O{?~i#{pdBJ&!9WQeo4p^m zpK**PdH@LB?eEx|p)o+D`uz@!cmXNxp3VuW`U7n4JuK>Vf9xbP+6a!fWkGV0n1DD> z2fTxgw`uPUS~oR9**!2!oA@kh?LX3ly-R5V*trX1P}`Z^rTwA#YKN`YBT#U}vHFIA zwjZ~24qmz7F`K%H<|+>mQU#>%o5~rzlbV{=k{ZWnwIcFA-?+)GSoTEvwpMVIst3^Q z`XtBdKUtZ?_y0>Y^Zg!eaXtk}*d5{z)Xz(YapY_|81`f}AoHQ(82Tjb+G`(q_ ztgV$jSu$r%pL^~W@hw^B&s%6oi&yb;vO*Ejfl z-I1J7akxR`dED4`@HSK$##=)ee6WjV3y)+0w!5=w2e-HW4*MY4PePYXNCpytdsUG1 zeS{jrIVUn9Qp|S}?_zh2ZOo=cp$K~5Ms$tlbT!+}q=H--c`!KGqV7@21^?SABfz!k zOSG8P_%ZVSEY<9npkVUW@5+W=tJPf>Bj3l+VyDsyRCC-}pIDi92WF*HpC2oKLUg z3aEae@%fAH2@@zgP|}4`c}-YQ3HLHSy9uU>=DvW1s7X^1yCc96t;0QrH%7U0z)`Cu zvXa~Q+9G9YcD|nwXaTT*l%lqr1%`qJlk15(!O1;ypBQMqHGd-|>vdCWaHMaDENO7M zN_9XG6Rvi5y>%*$#?tJWcZS2j{h3@`$s?{twta>3gi2(0gCkMJpCRVsUQ5rzi9@&w zS8jSqE=S}ZDIUOlU$m)x)wF)tjc~j1Yl1814s3Y4%n~=SlR?AR^?Z=Cskc|y^bX*Tj0Zb_DLeJJTf1|CgmBS&m7$#6jYXQ$lR(491CpO4)$oS9D0DTlRKMLI zt{8?e4!jyM>zO#YJq+hseWBg~eFI!)=kd~)E2{xEv+$$(n`eGrXaY1layDsD0xSwn z#(LhaIYX3iV)Pd1v3nR68>2BJ(i}6eE1}IgEP7!4p~|OMC|<5ih|0P_j1p@jIsN12Okd@7B%QA-wfs`V8_?vQJQ_lX3$egxR+Ek2dsrW<|tC_s= zcewbzW6qEYbFi`XtTPJ8nPVXl(vHB2>JnvPi?oJIb_AIiW5fH~G{tYXUM-C97NXQ^ z-6ljCB$}a6cUoltGXppGP76%4y!%%!Tngk5skT|hjd^07nTK{m5`~Iw=UJl=m zOib9lBFNDG7J7N5lW8;bx?F)xm;TS28dTEcS}A`79k*EieF%}?wwOsSmh-3`3N8%t z3^%6>6Div#=P6GtdLk2kDxq9FXMQZD;CF!Tn*F!#oQdYUi|{f~&|}y(8o&3*c*yG4 zS2xT$74tO>LIHGW{l5TUMshqXrRxQ1UW<)f zKjv=)<|;M(8!Ge>vRLO*mYTo<-ntc;S?8txO$Yy1wq%)Vj*9UMlew0%zIb5i=1LI0I<^uIOEb>CC0GHsf#Uih4~_|}oc?o|K) z;q~8W++s89VoTuv6l}aXJL0hL22WO+f1$K+JXcYU25`;(ml)#X-^H>)%W09@6C5~( zIUUaq4~_dHbS}e)H#mD2GCzp-UTCyj&<~anzf2m-e!)Yd>f(rY*d|@u0LuVK?3e=i znLXsh^lW3i08i4^wU}>=Ya8NXo#EKbTjBq}jIKOc#Ebxdl?zgh4L0<9zc-F+3jtt+ zsb95JR-?2OB>wMh7dT1`f7&;SPXzbPc5{^Vlm1pw1j zI51=*-lZd6bKk;|=Ol<^{6ZHF$tokwc{89IzxU=E?8eP19jy!@`i_yb3Z&J0kxoNo zCVrlUpExn9i!iWfhI>|c0B=73CG_*h*e`^(s<`@4LdmR0O!a~3wFumNzn)40=R$sW z<@Kaiu=p0+*{6UrJT5i0II5Qx3znW>K1ZrNnAf?)G7f@7gG$xFCSxXj?+6jX{p{MI zj%?THI(}g7M2uDr`!L)mFQ?jbQ!S>z)|)3P24Z!Fvxb2Y8{i}X;Y8u&#X%e}%cRy1 z#Qg9YgAsy1ICMn6!A24tJZA^3ko63>4Td8R+0QiGsjryeaN-uC^4(X76aDO3S+OZ5+_F5gBxz{GA_1F-#aGmr^LualImnG+9 z!W!c~0MlC5OF+NmO}~Q8`e#s%#@OExp{Lc9{j*TvCVFR2@;mr(?SfOHfhb%cDjjRl zhyXjs6D(W|Y*FD9hm@DIa|O%qg)|AhoQVXKtS_(p92Pnv_GlFt!U%1Ln&PX^XX(QQ zPNf6zmvD~=X;1jrvmoSb4&6~X*-ki=-njewv?O5(LtRWuMyy+$x5>>C64Y`xD+kaD zjpQp->N)JI)}vaGZBeUfX*9h9E^i-Ojiby%8by|Eml8g#o70OY%^p>;`+XL=gQTNZ z*uP!%J#D9v{T%GPM=ff90a=nmZWZW8vsQ(lH1<-v`X6#Zba=F^ycTR-t?*Ky#jKsFyoqAB-A^UzVlqpK-vq4g8_(y4b!#rQms*^}! zp?iTCHA&wgC?)I%3WPaLg7kcuMzno+;cU70l+2CYP2Fm-4Ff~fy1DABF8)!%qwL?3oo%?LOm76x?)^Vp&2k1?N)9_)rzDSEiSHP zN1)6_7anoz7>ihu5Y+g{s;FZeApg_mR!m6f#jfeDWx5{N2TnV5oYxoqO7ru%ZE|{R zG$K&ra5CKICZUtcU0kS!P#7t*bITaQ(H?ouL+_%gd|;r(o!*l~(xni=F~)g+`u)`V ze}oODuuu4S^$ELt39}l?Ff~*bO+}}|`lBHYW9Y@{Nd5ev*kt>_1VJ={HhLFE^d(hT zAoUC0cqKHkEXqCov5+nQC~y=PtKY?wF~NtM6)UM|?$4X+wTZk7*WV5d=mK~J{lI~9 z)F~gyk89+>ei$5dVhi4h9SD@J!AZ9nDcaD!f!Z3S%vN4B7XHe&Zn4CT?%HQ>s0OCJ zPTFjA)J*dy-g=duWMX6Hfv>ii6yAZ_j!Euds$U;*LR6qLH;#k`)_>d)syU|Z2A9WJ z3xn)0ww5V6O%vjFC7ho2wEqJ=7TFM@l*}=YLB{9~rBA89eJ4ZkH`Z#-Re!eFbT+HJ z-Zvkm{Jmhi{wCP_s+A9y1e?gYyrw%Tp&J|bf$*nfNfOd4cL=Rlix0^!?Sb{wKJ&Hc zyuc`_gf1z_fTB|^BrF0MYnl*Xrc0tcVg(!BY;K>)PsZ1hRy(9S1gE7$-8vQ>a;I+a?HurRZa*6VO`h zQ!O?!l>QKZX0NxMC3OAV)+b$91HmTVUQE6~2>}DS0#W|&@h$3KTQ6z(>*D6H&GikP zDCFLh<>2D`O-5_hq}7_AkNge4LTor1H{RRWz`3>%v|-V3gX_=v_wIp0#|m9ru6jY} z3U*^6a~kLmJrCRt;G=%>ry#+3WebvMpR23meZp!`e7HFEl(+S((2iBepD3uUcGCv{ z2g6Ge-RVLGT?3@Gq}&A%38`ksyQIFki(>&Zsf{VMv*(7DYF)dw;|pkqIMtHU*aqE{ zBuKp{zQ7hnz!Jq}uO$Ww*=^9mqcP`cR4aI!G=x$;HTVxSV)$aXmR6tto#s7 zd>OhUV&(0GV*u*0-2PdntyOMc2EN1jI;3%@gV5xFdiJIaCn*56SOo^Z^lNkfjZkNV zC9A00Nw4(p{{Sod%T|T-)aD^?mF!i(e79d#YcTaC0# zHYtMc78lT*06>lKJgKd^?KQ_SdZ60(lO4kItQ`Ra_nCWASy?h*iX1_|SeeP8j&z!% zY%%zPi<)EAPnw?CHU6WzwchbpbvyF1C3|_PHtqKV*E$OANBwh_FT~1guD@fTy!qbX zu?-|08>^q5??on@UJ*0U^pKCrlB%_e$CKPjMK&(nfS{xLj%pMOUU@v_6vFuk zG+|d)Mo`eZ^o_N=V#El0n!wlrj2ZHhclYa0n^o zyNzzz!ldc%UjK40L8>FJnvNdHC?W2dA+~bn{s(z)9+zbLK8)5(%Q#J|(_)KMrc9Pv zZn-l}j;5w&ikgZvshOfUinxQVQ-sADO zRC7{#VGq+tnE*+G2gguuIo)?#@z+!Q;~%HksIX`y&Yq~fX=c|N*pSB8U-|v`__?i! zdCBg0^_8Ko^tW;j+N1d~W05Ng;-byprdk&UQ<AS&cc=4X?G@as+N2R#?p(gmc)gyW}fV--7ytk>dFI} z*+pS1V+@XwDfcBN@sHZ3xBgAr4*hoMSAVGJH9LJ|K*iqBUH1*GXzxq)Swg1TNYydJ zvnE~6KJK<_jgA3wfw)_RS6v!y5X1M^+B0r2rv}tR`oS`%J^{EiZgok8J_gQ1zw%8HeJtAE9>;A#T zn+4=Zzm;uuzcxl04+@y1EVAp{9pL0-e1pUV7E6ogbvA$Woi$|qr$C`R-C&D9C zL$hP@PL19FN?YPK$S08wEng0cI;@yu;PJ8kSs=t==kkIHkxhRpO6$D5>NkxI`0_{2 z`y%s;{EpDZ6lFKR6=N#O)_zNbu{5BWIJW?^k(GgLu21!D`JXHOjwB#e=2|OB{r}{R zwl8W$%7cq98h1|rvJv}%-1v3O8Z46{g(_kQ-+rnzP`gMrQJeTJHK&#?k`FG+Lo62G zZLB@=bW1f|#MOykAcy3md7w7%KjrxVxXIK9LQnq@H+5NbKi@D65cm)JE8YGG z3&dct5}~|@CYk3gxAFSs%;N@g<$59fPL?)C2O@QgpKlFWAk{7e=M2X}$Gv2n>kFnMf2E* z>gs!~04E*(bJo^s|4)2rTuIL#@{r*l2#r9?u-cKS-I`H?PRZWcfOI8wwQtc%DqfSk zyv&0HwzVF&e26;HN!Th3At5qq>O15QVrOs7uE(wXtLyh|(nnOL0NEcK<}d8fbK?T@ zP5GVo{a{kHOLURfd~01^Y-fl~&#_&8ZG35?K1#|QxO=tXZvw2)>NgKy78QZwrz8P| zy}efkUjt(qR`~zTB_IFe-K%u8=@Htwb@x0!H2&=<_J0C7+6C1T-{=YAIb}gM9GH`L z4vu$%mfIlb$wEJeQPAZGOwPVh+$JVYdm-fH1Y@#n`XO#79TMotnk!X@$v(zbAbdnm z{>;w2E|@U&ICR;lvbosN`n47?H3!H>Xr`!~VR-Y(mrBvBjud{m|Aq@~)t#_`33U7p zUh(X^8d*ra61R0)>)}lNqGKFy(rc%v0~F9ACm|-SS&?})vD$YBebAM#%neDwLITu7 zpqD19Aw^eWCmAiQMS?5_Ha~JhG;(!7ZSsWo_O~_TJtw$#(^)ySFQcpCp|uosf+x=A zA|y$CRrV0D14Z&4%)N_?2$_>e(_UVJC*-O}tr=_7RprhLC({K6Gf*g04z^$p3OIykFj9z{(q{A2}Tl)wudV`{%Ig{cJat zwHNx`P0ThtEHkzyALH46bGqf|A=u?2w(D|^o7_#cfWH2n0o!!#(=iKPE2guZ+`f?5 zg|g7!Zj5ZdK1se{d&7Q3nuJpUr)rJpQ!}`6FfKyHsey;}kA=~1U5Vkjy)Cf|k99=2 zw?uKI7PH!-F2J*UvA{>at3J)^WFcgRH-LeS*J@}7eK_qUZY)j%$L&S*3}My)KifTZ zql%U|V`LBSC-dCkl{}vYLab*Ld6F|9(*~pmPZrCBxj?=P&GCh3if&y_u566SIo9yl z!c>UJ-7NgujnB$;pTsK;i8MC)ap=x*+?DHxNA@~hhAr_cn!l+yeMx{I*RE^cbLXIA zWHsVt;T|5KxI@`*K|j2-_BCEzMAowhaV1_ik%#xdE)@b(JC%~uTB5wrZ7B0VnYJ^3 zODykP52rZDpv@(tg&EV|zWeInmqb+Q)}-&{#k1TPW@r6te$lv?k+cEEH zma68+Gm{&F8@^=m!Q>_!Mff&s@huZ*+2u(GIdi+(nvr{jP!*B zgb&a(zV2TTv+obYpqH-*&Q+{Q-4GM_p!=N^QMv!~OaY_N>PqP8C+CQ8<_Vl;jVAH=JBF22b z{sE?X=iW!_$k$~9X-x|y0kJ=tGxxsXjK}mV@3EE{Gqiy$1&26Tu(a>uS9|)go5*S( z!KEqbYO+Lb6`)uGPA!?k7SLJ`?;6|bKh_e;uW8qRhdI*_`q&Za&o?jg?`J}|Q}yT6 zjwP8>c8&D}|GCoK#P`>O)6q)WY5C<^b%Q7rjJad{M>!RClsL!&5Nq|z#SF6WkRYQb zQUz}J6dW3JEdACbbRcD7Xf9}Q#P!1y{?@h0=-0NzXs*Z{b;L)I@#EVd=fk4!e~H|F zvUUy4jdg~_;Gge~%urFmI0!q%Z=wn1w zbH0G_6qL}FGw4(CN^f}E-^A?MPhysSi*E4cXVw)<+M6aP+xd3EMsJGz5YnA0o3un| zyO?2dW%QnWUPVS>2t2WGMr07S;lgXoBcP3G)CLh|Y!}RJkONx%^Ownz8m%YiJjNWw zFRhNl>}X6Y=UINk$CjlIan*v&z%k#Zdzw*$ z6JMQ)5cPzouz(^;H)Qw5(w>Y1GODHIC--!wkqPRez94@t4>N;KYv-ST2D%&B!Z5`s zG4XyE%+v<9{?!6}x%HEALq3mO$ZD)o^NQcz7%t+8@(p)eCVkf8bcb4Z22Ohn28NeT zG8MiZjR zBWC}|3)Ip5v$DQ)^S5b^RugtWCebjzU$tXL8uF@B_c5ZC?1w2;l_@yfGpm5i>8$bM z+m(SszOOHlX)vlGJ0)kN9e}(|qXc+MkTvBcl@uOTt7=STTKjKyF!7Te9JUo@S3wr6 zzjBK&v@kUI#Dxl2^a>6QO>~-aSRK|G*#oQ5X;g6zVO9{zv%XROhMC5ay#6JT9=Yes zBL*3CM=Oko)5A}g>~Oyu0wla?VM-8l$7&`$COslyiBf@X9_{<=fqW=Or&`PT>MU86 z7rz~3_g*0B$ex#8#NCVIYsd`xHV$~^#aPQCg9(dPL~)QeNc1}|j&UyBkzggXVyh8D z!^X1r0El}45cA}xRYC$!wC7pUu7t%J4ut!~T=EK)@U%Oi9 zbZ+9D!!Lo`??zToa#S7m49jVR3&yx9!a_V}$FTcSlAO(s14+aN- zT<YGV^rz_idw5ucAVwqZ_jscX6GB<5sHJj7a=gR-cO5bpYyY$$X2lj zCVBw2s)AV8U+?lDUY?H0H1t=Ob|(ST8Pc1h zR4W&V;rs#f?YJR}hycmoA~g3tCV#axrUBzmk9_%T2Hv~%@WJusp|{7MewF^3|A16H zICZOvP_fbOa{lMXSBEn>PP+{5v_|ONarCk4HhzCPRvTYWAe&xNMi1<{rs;@@Jq|Q2 zTtgw;My`kJt&KK6dq1{-SMhzD&lG~T5ltHN)Lnmw{4`59V6>aM8@655Z3<6enG>dN z9@cvi&G(3gcgKWP2j&_GysqZS!`WGm5<9qg?RkB0GoJNqFf3^DhQw0bgl5HDXTM&& z@GPDxi328A4LCn)dv^xHaZL_Q07Q8BX?$i`{G&!%Er}oQLA|HGz)+4>w0S%coTUmyOi3H9yS+q>zl~04&J|U9ARrOxYRAq(qdSEmdS9%i zez`L+>&kwh<<+W#Ki^4s@a%PQd}idP;W+GlD~SJ{u|)=%F&lG!q;OsGmRigkk>22r zlVM(2$8b%@J+^lzy)n`o>U3w4dFAV}%xPyGu1D}wQxcBBpk>^bHQSe@js z4KEPzoMV*8*i#Etk>w8z`HRIH2~T4n6{Hwgl-wHeWZ?tmNsQSx94URG(8m=6aCTSg*&J)8xkr14YLUEKLM=IMoL?D|P(Nh6RXPxWkh#Tz zTLM+*p4NA8BOwe6sj2|b+*LLG9)6%I7K346MagBc_t*frZT4B7Fq7=h{}Ld6!TH@w9!mLT zceK|Ln(F_pH#!Clw!n5~?^-4u?GbYRvZ-xjiiR}*o0q%%=VX%c=hEujW%H1YA6o?_ z{D8BDxvW3Bl!Mcbh8@sc+=``Q}+6c_nK&;QMu_2i@omzv_mW6sMV09G!k{udb_ zr1-g~%X6(Dna)xz@a}&|7y&)!WRVrYqwsUgccSH4?lK5?_qpti%1RW!A87scuQ8_o z2E|tYnfv~Kk*Re>ed+e{WWnH~s8+tQPrtX}81}=7kRsM{Tf00mgtq{a4?|*8)_gep z;jlu|{cE{hUpq)vyVyjNyxsz%Tc7x4TrY|D#h3NwYds{|?XFg+1=A(kay^?rI2$k5 z)9D=YNF-?Wsr7+yftO|uM+g07RlBtgzXd+08ZOj@%s&ai$}rY$f{vd{yQ+i3w-Voe z*opcD-OXRFT$T%CW97?B^5ypJ0kjtg+2L4&4zs`@+{JBy=G~IG^2M=1X)QL^eq3g) zUlEmVX82cw{{&cJ@QcU``EY5zIOYnS3R?T1DqwbTKJS|0gC))~-&)ZpD!L=T8nLL+ zs+Z--&;f~-cAI-X^X|K08#}e@+KSk>fk@0k3miME2ANR{?yLNByRwPriHcxZHNs;4 zmyIa^+7JEosk+j z**}d={V4%bGlB>_0dndzSWS&V_{^0afMskRStMIqS+y2J&I^DU&G)*0lHQ4Sfoth> z$7i4{L^OV`G~bNqDR-*WE)e!#ux_P9xa3ORW(5;nI|WZCU7}fUsrS1LP%>?xBTf)H z$BOlRKR7{pALQo@p9u!Rg^e*TZC1Au(@ZpYE#e+=;pw+hr^=39q126UlY7AI4l{b& zE%CKk(!=Rdth1+-?s+2y#O>oF+Pby@fE(9T5hUqjC*{m`24UeY8Eevy>Yei66%d0x z*dP3bs6$d*U!u<{5}nNgx7v8aWnUCcZWYD!ZzrH&Eex^1ejKPD04Dk-uO90$`=cn+ zUm z+gx+ur5dYrIFu3Z?ISsn*gR_C4n!af(HnxcjqWZSl)jC2sh4-m&pmBo0KG=MQM+}& zyw>G15D=)x-}1+By}*L>P|VvKLDoR0c)`kix&?1*Aeg`BU4&O;54fCTy-?lTSN@?_ z|Cm8=ID~Nu28Knd4qAJJh#F)sSV68T`G>Sxk1%;c5wt#q_oU646w)0@>q>G9_nVQH zR4cW(po;aVU;R6d1VaHq3LG_DPQCiX*1&0Z@4>y{Syvf5-}rADU(p#5aE`gxb80eX zY`Zo-_;#PedMgA$5Od6R?R^7x^zyZtitHMbZ%7)K2F07uRZ?TNQD=dA(3(-{e3tZn zG$JO)k(9u)_f>gE@7Pi9wcU82N)R!*+r^5joPS?`F6cpKwptRKReW~B9L_S9e7mQZ zzvb1>oSGfg9X@^v-xWr`Lx=F6OegH-{)F$zDM46taebDI|v&*bfn~X$ePP4`a5fr?u3Ah zF7B#Md0?1E{wi_lEUr7 z5$}&)_&L}Lb$Bmx=De&>x$7&>? zy}LZ`NG4?N#?qVqi4BA__;T&yVAaCZ^3pQN{LOdm->iUrcRBB>^IEvU$*p;Ne|}QD z0gk#HA9%!pHN7XsQi$upzqjJI2EGFtn#kIa#SUTL`c*Y&O_3IQq6 zI#l49Kx=~RtQ)|kc3<`czYuiZ#llHiD9^7!Kf$xRYDfq*uP0(_meo|DSFrztbSDy_ zA7YqLhEoM98!iM8OtRs#kA>HBx1VqNStW@zp;>IUm6eO>M#G$eFmcptSk{;WkTC;H zQlA317}%NgAAJZ>B4+pOF5Q{DUvz)-<@ zYu2laZNA#`YFG!jt`lOR4jn$FBWjf$W%W&woCe>|ibzw3Vel6rkXzcYa8&w8^C!?D z9W~6V#K|8sJEAI0OlPzXxBrmL44=JIQB!4@RY0XqHjj#s4rT+|!6ftX>4q(6@|#>e zcU}6t`!GsjpDh5y{vyX4Xjcd8%Jej(&e8Pl-l(NhbE)UTu0bwZBq#6Pmz-oK-#S*z9g#;kBc=8;*A*+h7`yLe)3 zpCX4QFWSSin0(4xSPvvGQpFFzty+4zzzrS26Szoh1^QusHx5jl1j?ZGX+*`XrugZ$ zQxWs6n|5hPYh)MM-+ZAjy-Dbt3F$LB#~;w&S=y7lgF8*l$5lhq$6il$pL^>kjyoLc zm}@fQ14VQ%h(%7IYy~eG?11lFzSySO%sVzTv!1NQP16pntt)JQq_>IVEvaX3vBQk_ zon_Sg#NH{d)~)Tx2+4@{0;;3q>%ztQ5hPFyr_!=j)Uaz z*S~Wgz1n9|_}&Tl3c5(Q^v;#v+7T6CLW3H5~YV3;>F0NA%P5 z6s6Il!i6Ydry1HPeoxmHgkKfzF2zpxVRwX|*_aas$lVIocg#5(GGlzUE3W#!Tf23} zSm;zH+})6tXs-?$$brx$0)kRGbcP%vlc2>SIXiCNX!fm==Pup(cXW^!R z1)>iJ`1D~H(4`U(~o$BaQ8-PTB9g_v&%U zOV*shEbdCH??GJBm+zt*EqeBPOfUvkry;GQ13k*~q^MH{%L5kB#V03oiZ{^G5DyJn z#oaZnx|z2fT4JuvOvJ3Ohvv2vJD$yDw;MMegH3u(@bvwzvC;i#4!KxtR}lov;@C8~ zSb$9(>b8G@17e8XtUibkmcmNn^QD9D7W*-}=j}4}-Kz(*!Ni3rI+ReQ zZ8oNDU(r@ouJ0Jg4j^{LTEgWRt&zq4su(X=-^KRly0NcGdY6!3pgqT!qVscj%%?yG zH8&1*;abw+wMf{JG!S@>`qgJ!AGg#sev4^(;B>z^_rm2XCq&1R40z}qAX3?qcggs3 zUy<_&DdY>K`$u8R!Oe+R{FuDGZiNscW#{^~N~+`5wKXEG^kk=>Yo1*gSeFSuyn4jr z>Q_q!8?i5eX)Ri_#mTQJVgo{8kPW zQ@Nh>eTM(F$tkIuaNoOF%iwPPchQseJpc|kNgt}IWFDDoTr{e?Bs#=8T(Wu^HzZ!~DnsudN- z?s+!;MT96aG+>wHsHh_;Jk<+8y9LzKH|4^P0n-@;+Am%Xj_S zq~*K6p5i|`t^D&V0p}lRm$DA%!2Boi{6|ZdeSg(Bza@YC6IpxQm&g5=C)h6!0V{s{ zNbj?;ZK;1nRb%AxC?q!aq9TGb{;42n^WV>pMSg^Eu)md z&8x87_<5n?<$(rIJU|$XB0J{~rTRZXwclFeTvs%1|I6`LPzh+;^S>19RVTw2*Fr>N zpM&O~-`|M&u!}ucJcELW@F6uH;Mj8e*fj)9+|&7EkR^7mbYQ;Ramh187;nCoF;{)j zF(3pTfNRTGV%IK5#8Gk%K~RvHckxvF8w)^>*uQak6#~WAi=V6(X$>U|@ z34Z+2iNWPZg5-9&|8f&+lJWf=(z#YqNRRG8i8$fL9 zayqyACmUbuR^&zrArbqTFk#VvEPCi&wlfvMBEz7?5^q?4!P7p$ zRt9#9S9Q&?rP*UkACUA^<(iCmKF}_zAl8&jV@RM@N{<8OTi+*l)XzJsDC<9M*wTPi zH!Bw9sZM}lc8ug<#Lc$1B?)zIc46zjYSOyIIuW*Rg|?%?5aUstte9y_<$MOfJ|w!s`Rr1Q^ZE+%xTywhZY~2WFkd+YwpPvg%6vEz zJyNd5YTb-+7(BW!G_71Vv0WWI!|1gF6N+OOU~MmZy22dpR*g`@p`Zjh?k@EJtwys+ z>&OAx3h#|gS}Q8dn3wpsYJ9@%K+DrYrZPwuVmv%U=cE%);6rL>DY;qKinX-yU`LZR zkd#Nco(+#zUBa2CQ!EBX4_wmd>?=@?JX6an*jO^zSw4L*GibmHUDOuEA?ESe0N!8TUm`oals)>`^9B}o{F&8OIw>3XjcV+mCGz@@+5C= zlEIQ(sY^?x&rOC-xHgeH&A0{hCr;+(;p%qO20RFU*4|5F_!Ch9sQ5sL@r4Sk7LIM3 zYX{13!7OCmsnPcJ&M@~d^vr>Xd=k~A)s^D7<#EaGtKr$DxsRs3gi|A@Y>=1t(N}+n z0qFmnTeQZ@ZEg?VQ_5CmY9D;S7?xH{-OLJ#K3~vuy>ACtMSDA&t8^P%-()A6yTw9) zh^7wT7AM?g$ttRI*oC>#R~{>sNb<@il|yu>+QJs))69Yh#4bkuF&=amU()(9r#sXsxK+zWRnIwJ;02wm)9>x}_zYP2 zRXITVt&zpp2%DeGVUdDdL9eC{#H|G#H*NN61oM4js3+R7!qG+ByB2!o5MkYvGrMjI zM&_?$X3}u7*O)$$b3PeD%V%gjx)mHcSVQ)GKd4C#tfm!<^SIvI`4Q|nJ$P(#<-m<@ zp@(VzB!}i-s^;>Iuh9OkpOR` zl;nyb&qPP}@LbR?{QRDls5np76)@3|AiEbnt6LnSN_Pr$f z@=?2Bwdt>XrjoxGRmM4d5qO`dT@>@oD|z5VUId00OELvHfhh0O`Mq;AU|!MPg*f7S zHC8fPlL`KEbkCqPvu#@Xxc4{A`hKrbKd~2M&6B zPvzNd3THT)piHaHz$?ov3h42V$cI#OY4`ix7D?~6c;*0^Wi*p4io&Di9NRZ&xe7Bz1^1HOk{cD2VCPd8g zJOTBgr_kcZ&mJ5qsHIlfIm}DbL+P}x(0Xndr8SlzoDr8g9`fSr3&cItw13JsK0=Z#)yz zpiXT9A~$a?cFGR_^DyM#J*NXc+qh(2${c;k^&NJGF55JhD!? zv@y6*SrhUu6(3K`^AKR(pEWm6MZb;X^oLDEKpWiYOmG^*dvWvLqN(ClHmqDH*5=;; zpDlHf@27e-1XTJAA}ZNG`$=4y3uA-Fdt^o1r{EHlTN@rr!nNdi=!}$++kL4z)Z_8~ z#gA!|uh}75l<-}njbX(MDw)4g%gwZ;g)ebO0NH$ zxkqjXiS)EHLI*v^3O=u{;ui!~V%kF=FDUNJ_(&Q2W~ zfOHW1iBCOPze36%X_ilqQ=hV2L)^63Cfm!42W>1_P?Z*;sG-ndi5J6Z;{X&^HO_Ss z7Vry@)ykn*qSF|wynWw4HEk?ln_;xNhTzI8?Z+Ntaa>}ssX5)4?~^cKHRU4n@vKZ> zx`OC6X79rG+d<5YJ1sPVX?tSAk`y^bX9NA z@TDdF9z36-$=Feow}{G~rpd)xTiQce%>$BQy^lC@GdE07EXey28{>?w;|`D+-ePI6 zV=ivDURB&8XP1KEY|iOJg!+3GQcqCl*mxh|q` zxmvYw(f0#kz|qXwuw0E$5Ok_OCwkfSpY}>6nD$ut>!X?YmTgQu~Um`=Cy$H-b|DwQ*G9l?5RzY=7)_k-ahRskfDl&&%EnLK1ArI zQ$6|KXa)HkOQ7hQW`QZCgxw4C7u=rLBM&m#^JN`qa_QTV=71AtT_#JY3a) z3r~tV`40S__6AQo}M~A2=^hQQjQd*uPD;d#w&5^vo3B?5 z3*^MyH-gbYCmDC#$Gekj?F{L#J`4Duw6ZUkeQ3m>c%~1R-Z1-cP-LPkv-HCVX0Yw) zquX`>#xLc@=(ZJJguv(M@BL3A10D#`{nif|!KOK@?qtOkCK0aH#fUXLn00y%Z3de= zLmQOv*s+@4Nj2I&$DJd--%O4)*?gsf^JEjVC0esxM{=}5xL5?eyELG`2fYbh8E2M8 z*j;bo214Y>tm1hI)E?j;-$F)WSX*%~dB^L^A`m%}?R?X)oW|<%$_*1WD2y&RaX1vp zBXtHBT9C)2E*g}lrAbg@_@Oceq!_^tCQ5@I+k3{;E|`RwT2Cg)&B{2^ieb8O*wlNV zu8GT?_Tt7K>R~b|_a1Rg;x*Mom6IQgleiM8+9Za7oig?2OU-ljkwL>LJ7)5GMy-M+by||^;5$$def{Ls3XbwY zYOC@A74Q#CygTxKIm$S=0K-c-S0G8rJ@R43YynSr6YyOY3rd_q!u>h%0u=Rov`fQd zztR#cj$b^2N~KnAdsgLHu*58_`OgC*M_ zQRvr95l`1614q4mobD)+x!!NT`wtGI+~K@n@s&z6oS1bs2`e4RGbVNZQ(Fx5CJ*qf z)m1-8C#83w!~8vQ2k0Wj{Y!314@Uc)*W7iJuFDHP7xg9%Ouufp*NVUQ?WuAdT&E_Y)pkAU z+b|8C^tiu}M{)QXrSmQw%Mii_PZg$mLeI3Masp8 zZaL{`qivD?#fl>ves?E7t=X2%DTAfn2IRzZqu=dU+pu+;H*Yot4o<6$HUQm9=B zZ<@3$EiK=3?2u={bbxj%694f0570Jk-du{(r~55);Y;~mOY~JMqQJjMFMf-q6FBPb>02#6x|8k8tmT=Ouo+1F$VTBL zX%6q?igx8{R@(>RQv*Yzsr_mI3cc(U_~9M@J^TS60XMM0`Xr|T-^5B)5H9-9)T#49s;35>LK>f?ioSmzL$vj~ zdoygy1hk3Nn_kt%A5p#_t&V9%=+N_pTb)0%S29WKaNL8lK)y|5N$00+f(J##{K&IR zN^LQCST%Uvek}Cg032<;7-ko5dbtZzTGbpaFUEU1cyYlEcfX!7nX(J+u~zGMRljajU69o1PDT@vKDVa1@dPrS9Wnj5_?$UwPDIaAN#CH@Ri}3+gqE z_k(PZHsFidb*a-fYT#;u4U&tSFB;I?H;O6D?#n{I&?+B&sMe&b%U8LcA~dPVdhL+GB5PNhqH0SQYL0j_-plsu z`cxpMgesc>)L%p?%Z2RCKeOpV&M6j=y;M$qR z3NB&5DuKB8HI#}gNqz;70VzlRCu(&yWn`bc715-%>~CrQ3m1GRZ2wpq;9wuP(>LlD z(-(la-wcpyxxCQNx=%LFxX5(;FIFNwKApiybuhG1r_V?=1D+P}i~B}}1I>;B3kP+n zU<;FvvGpH-OvCpfj1e@NrzGc%38xk~Yba3x-?NlOK1BRgZ>*)qJn%ML<)f+?ar# z;tvbO2v|^FIuB=H(YMXAroILYxX3CTz!ivp zN?L`s`6qOMbjSaL>lNw%FsA;-Rto*`|MarNmHg#d$np*NSKh$#o3G~9f1xgzXe-gGZ4{m$U0ibp_F>#ARsh(fDvZdYD0l=GXk1yuF^;pop+R4M;@ zCbR)?EX^EOT#CH%>#B;iZt|2?d~oW4mHh-TFwgWiJpia{%evV= zt3SmmQH1}dn*r{19ENW|7T;yme!Olw3!nn{nNdPWyo?QBT;xHPXLNuctT6gq!8I#Z zfE9=UMuWyFOoSCHvK15nZnkC>);2Jgb&G;-fLK=eCqN>x&9BRW{>MH%xX>0^Gyk?7 zE9Sx#%lx?J({c_9k^##t{JNaN!T=tg!a@P|a^Tm!C?e{>UhoPY06uK-Klb4oS-%iF z-IcpE*YYt_dg!bFH$eLvUgCtYgR`U1c2TChCR!FOs2ir?t~9vtx3 z^L1}yV)(gB6S+0O6i(ow{K^RHCI|z=MIWh+`b6yy=WBq(;&^rXE9XzV@$IKQy&5f` zMFoCj6NME5tdad~Tnzss%iAgbJH-4IX_plfW^=cA4lapl(VsqH`RgaH{qb$T@p(+l z?SgW}mfE-vN7L6_R7io3kAKuEz|Q;iiBiG=`%nlc#iR3X^GT#aFe#p4b+gYtn%oMx zWLb61dM{us|N3Nn0OX%S7%86VEvkSV{Pdyy`@LVN-BI`qAD=qA|CPUNaWq8U6M~th zQZT_RkbK;_mNOQzEDnjMFY@8b(teW#w|J3TBzs9pS(a{x0Lj*ZW=o%43g4&Zun*Ou zM~hlZ44T`xG_+ArzR*7?@7KXDj({@!fXHcnnDlKL-b2ERU*hFX-WDO^Ckwo=6k(Y) z&J75Z#Ls}^&!npuNMJ6qiDW3iKuZC1m@8&8tvK0qQXavAn%(dmlUqS=NIiIltb9L{ z@@j-n@p_Mf7)A|#I;NBX7n64t$s7331^qs{4Xc^6_}sLpXzHaHdnb118^+4j>JhfJ zGVE=?@YjJ|J%}&%?{E9W6T{$<1Ls?eN>A$+c!Fm~Ed#^8Zn5++X2Q}+nX8e?^uY4^${B0R=)us;W@PPK zx9k>TkRKAC9DJx$W7d#fZE`FWW0-D!CZjyT&kEY#=gl+L=rx(eZU%h0Py7uzYrj`> zWR-#AdGq6?{gwsycQ@#I;*Xf;Y-+KpRC-1#PhmQPqIENHj+)0ewFIf)0w}^q6q5n7 zvzTso79kp*habpZd@X;p`8q3+Gu-I97N|GP0o2hXA?c_Zy#%w0=t;WoKQ<`R?qeC}JNZdsTo zf<0%fuikB(y{4twhsF{f3^^=u>aN{4g${cGOeA{~rHu2jMu9Eosz^`UPO;nszfLWV; zn&RBnhIAIsBz*U@8Zh(uCcA#BJUOx(AW8-Dnf-zZkXLQ|#u0`xvDQUO#zml(vGP6D z8N&-{P?aK|o7`uxD(~<%=Ei>hT7bDmJ_?*+@a*G9n)oEVdr_047YJ;ixeLrTGMRf_0qE!yv+^XP3Q^%@VUu_WFVVg_C0fU9^$ETFxIsluE7bi!~RYeGxY2cyh z-Svp$z@~Oj6l5>nK{*-~M5fPZANU>!4``_KL-)7!^6aHKLQn@6g)0tQNB-vGcmnvvEYV zT`fh`N1g6UGQp_n`59-=Jj?}aa2UmGz?yxpzxWWy`F(qoR%1nfx|;kMG}7Y6!fv;* zCDIn%4o#J9%K2)+y{2tZiBfZTJk#I~We@e>5-jJ$F5x-|@LNCQ%iEJ09%1St3UkB4 zG(nzT8Oj;`m`)X1zsZ0TAO}Vm9fq$gQYX8JUJ<_o5rm9|T8&}ZwhsUe!1)^(6$&u2 zSM_Gip_L2fzrG2%k{2^l?%8zH-9d&^E;pNQ!_#{QdN&kZyU9wbU`2}48cbunO(m1f z4PUpv8(($IwA1nE#3R%W78lhEbL)sh(o%02YFwQ$R10pDy>7bQ8!wPWahL$(%^5D4 zYPXCXxW`V-J=yGN(ihcMh3j34TMUH-IU}vHnuxjz4B$k}-$JRdlFARViuhi#wuBe& z^H}kR@3SLDy;G+bn~909ZTyNx1Y|u+%WT$1#Z>25uk>pCnjQXrMUDm}6qDT@wf}2c zlWcm%-C`Hs=jg+`_;vk{b<#s)izAxNGH*9zfP?ZJ&-7N;JO#+oG22IXa}(h24K?vK zQRi)uBD~a0a>8L|^dmrOJVP3aZ*q&TAKK1#waM<)kYF4Pxrhghi1X1be3GMkeR&~h zSd4viXcw+Qb`$d;;#Ik8Lpm+RL11y7Q!|?qqacj5jq@aX{OP1!&JFFAb05zTf24yE zWL8_I>ErXlkSOzzQOb{7)-8Ne(TlzY4;#l4JP3{4CTj&ik8Ogp!yAID4yWVBaOYns zg<)9`jVq5z6D51V!J)%@G8$%PQj|Qo-h)kUpb$cdMW9=TMh_FO4*Sf$J@;SBx6xD#kb`eUC%6i^XXr__;px}6m9#MjM769Nr9sG-9kZL;DJ9MB zBDaj8RARB+C~$Jjer36`tdlPF!NUh!180<34L0`KU%X0)%>Fj|tagacXX=o*4{TtZ zn%JFc=?POw=-9z%-R&(9-5-iMeA9)=kt7VJ4v^XlvaqmtXyC9aErp(|NzG~ICRD%X z{j4W$O+npfPasYvmmlX<-mhpdd{tg=`R$@=iMxe{pz2h8Oc3_FZ@~UDUFV@Q8shIc z)+NAF{3ub=XbTE*9pGZj=ya5wDnDYkr(PRFW9awVJD{L!PAfLr2V}&C}+;ouO>~M2Ct$IL=`6E#-;8RMnQT zgpr#}Un6q+RI9QOkO`Y%?oyi`GIwX55Bi{*n8V zv*tNpGc9};vOl~;fF;#1q1QEbwfrLV(JQ`CKsd^h#3^UK^C3L&r*=e3cpW8G?VC#ntD zt@ofuEjkE@hK`~^lHx?RYjE^O8(?W`aH=P|9$i+MK8w!Iy=E4s(-ejEgI=g}V_v;^ zlO_4+IZWe2JCB&WyM=epRNfe>+i8Do@$pr{o12d2bu-a3HE9B{{4Q4Z#;faatnNB9K+WaSPv96Rfy9i)D#+wTf-;muFDrzb>Jf&AN zESRim&SXM9(d)39b>E%b`6hIoe6$AW!Ti=bcl5TSO|bbpHB_w6i-UxxRU3B+bE0y& zGYgBhY3+`;i*V>E-V%G9V^02XQfh%GJuc^>{rt>+IRR4cz4!fohbB7m;JS{uqT=zaIJB4N~^Nm z%Yxi8MTK?}H7OYGs^0WcI87=j8JX&~G(>i((4xb`R4CWAP@ZD)QQ+>+fQtsGgl7HV zsvJmFN1C1&$-My0*`T8QP*>H5DKR$QH;X@}OU8)``$J*xU)rjtGG?aTiRHGU5DvCD zZo8Vvh`|{Wg=06SFrq7vExk_yG5Lb!?7JpmT5dcDDAr%l5;fIap`FzdOi%k@ZCNMz zonXUn>`y+8-m)E>rt9EJw0Xe1cDP5){AfFVXwmnKA7MNa-_P-8+gBAUrD>$*;meGg zrlf+`BmKHPER`0Vx0*O50l`5Ecj7&^wbYe!(VhStyjcC{B1A>t{oMgq$$9rKy%8R@ z*({?>$~0F#MjXtz&G#`ket2K`z*(SUEr@@MR}xrEN^OLt+B6)?dXUfn17HdCpWDjQ zMb`QSIa4i)5mYdZ2Lp{)BJS3EE&_5sn?keZ9)%+?geFlo^5x&vVYWL=40RRmi83hl(C_&)6G zr0Ue4{@vjD@8F4l+T;HhF$NM|URf(MwT!#WlvA^ywR?xF|Bv>*JRIu&`&$uhlC+3W zS*8eytb-QCAQCfV?ItA}%Vg{ZN!f)&Wyw;Q!9+2ZVOoX>MQDud8L|wjXcQ4fR+w%5b< zNgmd6MFtgKBg=>TxFP8U><3i>6zrpmaX71!VC8?mTm7VUm-Aog{8xAWA6eFA!lpb9j+4<4ozrIj z6DwPsWDI6}U(6sZbW&>OYO$+hSX2d9KXRvxYmI*aM=&Wxc9s7f$K<04Q85M(9vMCC z-#&FfhI^*TI}XJDDz26!PU1BNz>R=;iwzucYp4*oU3;tB{XTtyN{uyU6o zMn0j7%5d~6T#E`KzJM#GFJ)^lWgA0|#9>fW6%;iJsAhSR(Jm6^(TV)+ySG2?Hw2KV zPZP%R+F=c6PJU+>ejLpoDt@rbk}&U2n1{$G_ARyJYPttRgEa3nm>)N)lKU6z0TRd& zR$5f>;q6dzUv4CN$0* z4bbopeJdaPx_PC0Y~hJ58ffY43GzeLQ)GH^ub~{4m8VszIK%gSitio#@fQ2qkKS>6 zIHm;I_-k?DK$Mw-Pz+?H(=H|ryhFT#iTa(a5?wzH4(S`#uT&NEhIy9ghAQz60N0|^ z;XI+_Q!j)^pzuqNRG-cwWZTr~xoBgb>O^axY@X$vRB)-JiRql-@dPhMnYi=NQ-gWy z8`r+#fp1l$tsFklUk1b!#xXv}o>IOSs=Q0>zf`gExG%;xnqpAC_diIec1S2%%~!(S z9<-x%g_yKU*ZK={830}aO1+H+7Pp*uH2;i1 z)p*IUm=11-U@cI}KcAZ2GhvX~LWGxOW%TN#lE=8X(lvJ*RNKv{g}aYG(|yP7%`)mt z&X5M-mD8Ai`x?5a@$}Pr;t+IKJ*P~PV(+(G61Z6fg6`Dnw3lsq#xVh*573FJVB`9H z%@qkN@;#%3eEI8P79KM_4x2c@b!;~`2b~p?!xS6VxjEGqht};g0w2xKArwY9h$WMa zzsq3;Edvsbm`CfMAw&sK2SLhkne%cyS10Dd^=t#7%H$5Tk}hWqm&p;JSk zq{HO7y5-nVjbh4kS*7D`UcSNKyv#UpMIyb|B;Gtn6cJi!zpTouIon|u;hVR^6MQ$3 z8z%CXuKg?)uV!(F zU6~$t8@$$+5UmA~S1KC;ASgp?Cz~R#r+b4M2dRfVe0r4fF4>!_K z=euL^)}9j`&i?0zt}?~;nFp^c0G=n(irgkLwfKmQag$$!6R(1IjMgdpR($D-BS}bK zA5gaXMi*vITkM-%JMBBg8iNMtw1Kj}!l4>}@F@2MU2anm=w;36B1dvI-6$N%dFpbD z~K6C6{HM`dU9CY^|A%;QbDgxE6iKueF$j+fVy*(eF{h6s}c~bOF|)F!3jCWUnq#?DQRU{?@5IfVf=45z=1+YNoy<(wx7@X)}jTBl*e?9>lWTkP+S*W z&FX;WcFMc@Lg^iEN`Z5;k-cjZk`fT>HtuL$q_6B-&?1>NSEm)pYq`&%qH_Q)8o|&l zyZq?OB!eGFd1+U-G;uT++aIR~%=@%fw_$Vh(L?8rouHftHN$obs4P_*^g4+ZksMjE z&sUrJHhonF4l{FZP@OC#OX;hSH3CE7o_(H)4FLtt$zyF^`;(X)W@tNd)1!>eU4Jfc z?<1nMaDo-R@g{@rtT4Wn2r5w$eUJTaDVCu}A1I`dKwn}=@+DdNt`Q60Y>Ui;%&B{R zmYmHYReyxajKGE|j{?CD8s_034qd=b@RkK5QVQuiZ?tA36)qR_VFn8?+N*>7XLRqJ zlxnFQgFrGN_DL7bZEQtBkqT-BEKFd!(^ziov&YArHIhvH!Syp<>UUR)Gxg-K8J%t? z_nXzpQWvCu3wE-^3Utd3>1+*vvFB{7@CZe9+M1qB}UhKAJn9eg)09#=$PQ>$q@G0k2hlzrONOekiZag6-=*bGm8o%$qQVs}6EHV#y3~NG z@sZc3pg;5i*qz2FIIjgqYzc4<)`!wL4zQ8Oxj5?y(PyP!=UnQ|MS7~cdus!PJ6|Vk zHP)%30qG!6n7Ciw`-u`{rbfrmC%>?wT5a^JS6+-vU%`=ASpRrGI+%OPnVks90GUuW5J=g|!hEvYByl-Xr;PTFMJ|zcgAfWKz$_$b0TZ!0$4=Z*j{Y~*_{2nI z5m%a?FR1vcgq-=40kyb@X925b%JVo-=LyhAthL6Nm|G&-{-Y==K^8>*Aa1N%UZ}5>-}h4CkWxZ7 zI$iLV|8(i6Ocpu-Rr#?|tisFF^%WSjU1sHuK61O3oA~hXEg)K~vfR$O;Pg-J@DGmX zxsSSTz{$yL559PRsaojxX4yE$lkZ#mJTB$|1=l=s&xIclm2XUCS2Dd1j5wvO&T$x` zYn%^$+YsB8t2O1d^k`Wkq0vCZ_yAZaNd(?@^A|IkqQOuf$LjdbIF`y0n*4=a`s75ME92IY4-Y5S81AfX=K%HZlhvW`GxmnTy$2vP0LgqkJh7pLx> zcJie)ej=V5v(Q#P%hAchW!Gjq3v!>C5$uvnZCtTk@yWt;`2m%Y$}-*Vd;WC_W+YoH zaV_l=t+FbvZWMy$q*jt##&VXGT=(681EMO(<=DLLbTs{!U9!>Dd~=gOCtv>Qj0}8a zL|W){O}f}iiEdfuvRX z*mqs$%9bRlB{u$Ie_#vwGcvm8Tq{O9F*BosrjCE!zCHdQo#pbNK@Uzm1*6 z?HSne+60Kmv3q4^)syVD)wa8&*vUYz@xe1_49a#hY$=MWcMT85L2s7kTMd^X+3Q{5 zep+|N|Hy_i=y&n)(vt(!k8t`!VR9j|I0!Ryy%JfJ+xc8$AL{IJ?IH88xf?M{*!OGB zaC?9DdM?M5F+Tf4*0I~cceFPiIr*Z^+j20j2M(9V(^Y+TS-~Sm($sn7piPw*_;KR$ zDo~A;j2J*i2T-{2RfE>;zZ$g*SsYtWrr{qR9o?Dnpnc&rlbD-4t3Ju910l_%P%E<3 zp^Cz{@P;jlrElu*uXIjQ7?UUamZJti#KY=y3rgPLCg)>MsUp4`4cVKjxgYOZ!KjF2 z(OBQS#w@B(?!Xzi3r~9x%W7HMY{Wgj8y$E4UQy5#Hz$n6#a;VZnU<1rGdqvER-JL5 zRoQ)Oej>2P}Q3Rklwccx!XKa1L`YF-~HRy3WoVqy)xlv!6+*%IfGtVVumI8yE|e!B0$?!X_yJG3DuaYcoo$ zM|F{vV*u~aba6p*NS8Qvwr=2mb8wYI_AdSWEgA`;dPLIu>gsl=PoKw>L|LZ<-j?&t zLeq;+i2WV_keZe{U?=!XO&zJl*t%c64c{~koyY@Cc)cYKZ1l;+$CrJPukKr7~j zumkzW&c|B_Hq9 zmp}rUipR7@f*%FyIMZfebfuQA_o>R&RxVBohd5kM-`VgUh|s1G)yw+(FYtx^S(3p5M-2Xc0N>zfJ#LAYc>>h4RA!o_mU&*;)pJ6fi} zCbQI;OL58mL8zl;kmDv3<$W@;WmVqsz*D>nLjY-kFx@VG?=h-T?uiDtk7rtS2roj){EFA3iV zMB7#V8_ys~Tqzl@moDiyPJ6kU&f9G1Ri@;7sb%hF=x(1uv`K!^(Sqd%nz4pTJP_Ec zDe2R#m5(k1Omxvs;}exNfpH_blkq8=YdYuCH;|eP)*k6oj|N^tpKp-9{}4SE8L{Z zXgwG_{D!P(05n$^iiGwa2vqqI?*t;_UH;SJ?yld=|NWx zL3=sXlSZfdI~Eu$S7Gv#uIFIPnN7QGn>`tL2ll$AZBjRUpR8^HXRggk{q)rd5zRmVk1$qOmF`RYT1^5i~=Sa*LI@Re4;2E zJ~sEYCc3T49O^!mw1N|R3H}l$~H^jEr zM><~=w{}ay??R~?z~B2^6yQQSg*vP`#=ZY3snU zESg|)SsaKOq#y`$m;yUGQxRz5t+!XZELo0kf}7ZM_B!yfKGg3Pdnq8_x~wE*Ua^B* z2%l|htaM0Zbl5Lr6wCt78o@uI%$fo(#W+~oXpPY&!{HVuAvX}gX}*3xZJ^RZQ{VJ9hhdi({X;Dh$YP(2f+)i2tL;=(Id5| zW84E5Z7RZf0z86@{Dwkc$=%Z>lQz1yW>sOpozg8PVCzBvdYacB2g%KLE^bBzQe1*W zg^z5>LYDYD$hZv?@5R)MQ*tRQhTT%4XAOmhxZ)dpg_H8@4ooI5C_Qp-HDK52eT)!& zG(S`Zp59$aOHlZ_TL4kqV_D<~ZIz+U5gCbHc5pgU0rI@8Dh^@aGSn=X@$oOhdl}uo z{e?6T&KM2U%YW*B!l$qlRDV0T-hZd~K&~a^hJa>4EMRaOVfPqX(m=d~$@( znmIfvbPy1Vx?v-#tG31LtIkEECSPr`LKPfJ5WC=--(20?ZCA6y-cEJ@%Kp8?6k+26J5Ar) z^NwW;^JqbsWajxP8qzyX?G3+O?!4_Vt{qu_$SpBh7#lZHuuC<*+?H@1qt&IM>?Y7P z3irI}E7lr;?lz+5s$YZWBA0HgNF+U^@xBL3Mfoh_jX}lsZ>6QG?bEbirG2Db6HP-e z*Mnh}iPuvge)*?lH5cRORPXz7!4*&JWCWj!I7x7@tezS5dLNz)=fx9Ss1_pZi>+F` z(=LO6U^e(c6$zYei*CW!QUMYDMvY!a%;Sg6WV@cB?>pHyy zJx79RudLV|cEok+s@xW-TuWB88KUKoF1IvF#eDhmK|QqW ze!h{b#87FtSl4s)*&R0y+!0ZWC9~Ne=Ypv~Mg?e-;@1eP=xwpGk&wtoNyMl>cQJ}2 zd*u36Pj+G5K9za7?v6_<<&$5p*5T!tx}q&oEYXHS#Yw!^;2{h=34=S#Nu>f$|U8;TtOz1qF)u$6$aMd+Fl zrq~*sgneT1e?Me+9-GT>@Ie($>=Hyx#CEMK4voEZB1;f7iI{eh7gdeTv-_+qzIGhs z34rKZwCY;u81Tu@c5Z|9mD?%xBKlxdu(oCwlYaR(3*SSH;Fc7!Cg#L)iwaqLhMth6 za7anrdsRJ_&uswABRB;88WKOw?SdvPe<+8GlV(Od3U&Y&C{TwmtV23LMU! z@C2^0GCH-4UQ53cOKzU%dGg}is~}3^{AlqLB{{6}wu#2TJOs4lU=~oFG&q=QQr+tf z##%nt8k@^jaO}P}HY$}YO^YaR^r8fZlVot6-{S#l#8%{8K%9jQ=OxO+W|tbV0b~}l z7?1i^p0nILBvaPzYp3SrBW%}Kx%XC8ERnOchcr;KxNz8?)Lv=_zt#0@S)tdoLJVLP zv$d32N=7>RV)wqoy2Hnr7oumJ9q!qQ0{4Bjv^-Qg|ToF4~bbalZs&z&)reSh|Bw&?9*6Pk((h#5_zxWs~3b_ZBvw%rtsH%;C7ge-RDRQ*o ztlW)b9VJHJ%NDC*Qb?}+RMrgvq}Wh>TZ-ne2}qpTl=ENhq>Mm8i&BBD`Vv!m?M!u$Qm)2_r))YG5@inKWbh75Kp7V2Qf9Wv;UD zglXgFc5lGoyvc%d6)h)^%v5irDf|`JkE7qH?YJuqK3-5V#u3kss?iLtD_m@1vo6v# z>-n9~hvvpa&j>M)9^#TDRU$0mAarAnFjiG9o1x!ZWKgh$lAL%LHSkn;-pAUkdNkM3 z)!>{V5ef?&oGUk?YiB&^&|b6%OE9-gZcbY|4=ewU*!XEVe<@G@)E2jw$=!(7V)eV| zpsE=kD4R)+`6C0+)xdiQ`^QHcD!Yco1&)(xD1((~BMHlt?`i&o7qUnOXVL z1_5!ZZXe2h8ci{u`0{qk8G6;2xEQ8jYDrpQkYNB@Zdsa4b!CPC_h;Cp%Q4hwTI@u) zUv&#|h<1jBVk&e19v-bQev3*gsRUh-T~nhoEPe7t;A+a|q^cY5U8Pe~l`A_Qug+b0 z%Xx}5TaxmA`bv&puDQ>ry#g1FVEJ0SFtdAoAKOa0flqtkPIDgN<8n;upRU|W$m9J zq{n{S@Q6|y64_853qIx9Dub&JJ(}-Dnn(?AosP!kk8nFpDwZA+iDWBT3An=qkYwirO3PsTKU{7qx0y%=>9;c1Mf?6yR1?>!piYv zNH2}%%(DINS)PuL3yALV{j4e{RiWe>>9d&a1b!Y^r*aZA_(d1U5v!a5qW#F)DZM>w zQo|;voZVwX(;CM3-3S6*nh`@>#s|!N4kq#lt&Z3o=pGL|@WSu<=g^~tv|Uao+GO|j zaD1f8nTHzC4JOtz)}NO?7$%?%9mq0xP+qjsnaXf+osZYbRH-(Ts#*1`l0N-18Q-G5 zpP``jSTMg%>rr8uS6&}@lA(p>vOLfXRXx2I$5f7sy^PNY2;3~@fQ-=rrm|cgSEQu% zbq8?8iDwiJZ(lbl4zb!FnG1${SXHp~ih0T9S;`5x6~OTWdnq#27VoW_sCOl+DY9u$D0R#0&20KSW)DiFu|8^y z+2aF_x4XxBT%CNZ)h~&*OSZ_)0Wc(Q4CQ;#h4ZwlI`yT6aOnrZ(;YWtB5>sP9XOJk za;5f+aIhBaa!gOEV3eB_TFWi5nYkB;O9U}45~fMaa`&stvY$yd!rBRIx+VBp_ZRFs zEXoB9HRL-#7tM)Xn0>&5>M=DEy+5u7G>=XxKXR?e{u=}!!j91g<>`-8HGdSLE%c=5s<^xy&Cz6^Ak&dZ9*c} z9I+9SSG_oT0`$#(AkQ9CxJTVJ$(&HGy}|{vmKyLeq776;(FPD-8R-f7i$_7MLZ;f~ zcCutZGy|M(je2JWpJ(pIZkTt};?9JdxgEn2m~}VCx0QBLE@?eqBSp!A+*2k$Trpec zIMbtf5MB@cw#Yskk8fNLy6lFh zX)o+DFqEJ;5b%_+10_VF*%%ke#6ljVUaTmGCxJWtSoF@T*1*Sz_l|lIm4|abv5=b< z{q+=GT?!P1m%B;nq(7vSyZD!zx<-d>zYoo1_dyAy;OQ?w_UGBk)L6_RIN0l}ew8Bc zNQ#3;Lv-ULpEXptT}9%>KCXcsKwz&UIp4<|3{VHKrhg4S?zti7h@8o~JiJBCp$dFv zKuHQ`A~>bX-o;(!l@Y+6^A+fvJSEWk&6&=PQu;;TjKG7G>mU&{=yB@nJllIrAq=H8 z<#>zWYq8R(Jkbdf+&!%)wc~Vv@4Uv8PDi0<(C6U`;D& zH0J_2gHbP$k*%6;x@<3oh6B2-rL7Q>12@x6dOhv?fpX8iYNn%}wV#G5!zEAiIwl(Vi+#oS>o>ZT@vU_RxnhThR0$jQLOoIadzxT>} zdh6JABE9p5uaWy=PsLVHblEN))IKv99X~2k2@VG)aZEFAXo%fI)p>8bC0rULYmShY zV%;f&E{>(ue)*G<;W&SgUA>CewlY=-G}3de=J^)^DU>?Tebyt;(Ei5GVN%btgww5! zvoGI99O?>uCI8UWrl=1XY%}hJXf(bL;k`&zP-Q?R`|)zF`@|v$W7MhZYaGd+CI>0- zaa*}&tunWedcWI`55Okk@nHWSu@v9{H7eR9v+wjJeGuzudujv`#U|@djpU={Zam|9 zl&I?u2=Vg+BEr`#n`mPAY76LHC8*9?H*8Koz!ZI!H4tK-oY$&F7In)Fbn4mzlozn2 z`e*=xSCPgZ&kvoy4KOdyEjEZn3BawWY70KUF5s{7i(Aiq1|%LPSnFSP)L!zx*3SZj zlzJ2>n$!AKI)4?`sF{L25C+C4HsUt|fzu=VO&sHZ`>;~DyO^QpnXxyd^hZ6OS1nKs zsL%G!inTyh-;^^Dg{c%g&`w&CF9rt5z!MRRVHigc;*yZ09I_&@^zh=oDR74ELcAyaR% znrI2!K#*9>mV@%<8$nWT;8SLoNLwU$_fnHP%p*>aho|+AOeI^BHus8b~>Fj}GXUX+b zi{N%ISvun@dG!SOsWHLja~XLF=(nI_Ow$hOVU_w>(;)A`+ya|5pyPmmvCyC@B#9^FEvHTr zmiwZpQZ4A&%I8FG#2zD9?S}St6j(5cpB?L}x2DVOFWdTy3>FT?xje9LMa0;EQ4xej zXTz^5Z(rF`cav!z52Aex4?*4JtR$21ODs9s*dVCTbcNFY;Ur2*U@g}r@W}e)%xun-ca`d>FMB0JswEo6;nB1tE z9?|u_T%Ocog$rqGQ%j~;rEp+EgP-x9P^9-xMMx1=PzA(dh{180p3p}8lOwjn=VN?h3>#uc~UpK?PG`J`^B!` zw8HU~{~l?qLbD>rZ1l8~9`Lw{0yY&9*XeJQq=aZSFjgBvI$uYTJ|U5z3b;dAB^A{@ z-VWeSQ4v#A!bjtL#$dbUKfvsV01{|^!2N%Z@C`=(VmJ;{=K*~Z-L;o=Myn3IsY zK1kl>B0BCXJOR?$AO-gMK))u0)5zM8+PRNLnOlsInbGsNZeJ!Fv#QV78~m&(ctEOnBalKy1+-(KXkDDF(8QFT{B+> z$njh2d{;`su;+4O`g+!l?pZ>lY5mVUSpZ?>Wf7MP(q;t&vpWnx!3AhI0 z*5K0r)Inf0u;mor--7w?a(?Qs_^)*Sr@F%gMgcWn?yc|NoqR^dEXI`6Sl{q_HPQaTKi&Pg{HTv09%s z#s1-S*ZM%MwO{n^T_1MF{$Z+YeO49wIT#nVHY1Du%z>9(pR&b%?uW0>sA4~JxNTdT liMICqfA@;#0gT%3d>d8s%gUu_PV7H~oHNoXI& IFRS17 Calculation Engine - an Overview

" ] }, - { - "cell_type": "markdown", - "source": [ - "Version of 01 Sep 2022" - ] - }, { "cell_type": "markdown", "source": [ @@ -78,13 +72,11 @@ "cell_type": "markdown", "source": [ "", - "\n# Data Model, Data Input, Data Import", + "\n# Data Model, Data Import", "\n", "\nThe IFRS 17 calculations are based on a well-defined **data model**. The data input files are set up according to the data model, and the data import and all the ensuing calculations up to the final report generation respect the data model.", "\n", - "\nInput files as listed below are used to provide the necessary information on the business to be modeled. These files are part of the IFRS 17 Calculation Engine and can be used as templates for users intending to model their own business and adapt some files accordingly. ", - "\n", - "\nThe IFRS 17 calculations start by importing the data input files, and the more complex logic of the IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." + "\nThe IFRS 17 calculations start by importing data input files, and the more complex logic of the IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." ] }, { @@ -102,58 +94,6 @@ "\nMany abbreviations and acronyms used later in the documentation and the code are the **system names**, where the corresponding display names can be found together with the attributes." ] }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Reporting nodes, dimensions and partitions", - "\n", - "\nSee folders *Files* (DimensionsAndPartitions) and *Files/300.ReportingNodes* (ReportingNodes).", - "\n- **ReportingNodes**: List of business units, often per country, with system name and display name, currency and \"G\" for the whole group", - "\n- **DimensionsAndPartitions**: The many dimensions (21) required to characterize all of the data and results, with system names and display names. This information is quite stable, but some information related to partitions refers to the reporting nodes " - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Groups of insurance and reinsurance contracts", - "\n", - "\nSee folder Files/700.DataNodes. The information is about data nodes, that is Groups of Insurance Contracts (GICs) and Groups of Reinsurance Contracts (GRICs) and portfolios of these.", - "\n- **DataNodes**: List of all GICs and GRICs, each with several attributes and the portfolios to which they belong; an additional attribute of GRICs being the reinsurance partner", - "\n- **DataNodeParameters** *\\_* *\\_* *\\_*: List of those GICs and GRICs that are actually used for the given reporting node/year/month combination with few attributes; if needed, more such files may be added for other reporting node/year/month combinations", - "\n- **DataNodeStates** *\\_* *\\_* *\\_*: Switching data nodes on and off, the normal state is (\"Active\") for all the GICs and GRICs of the reporting node/year/month combination; if needed, more such files may be added for other reporting node/year/month combinations" - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Parameters from financial markets", - "\n", - "\nSee folder Files/800.Parameters.", - "\n- **YieldCurve**: List of all yield curves to be used, for different currencies and as-of dates (year/month), using a yearly grid of interest rate maturities extending as far as needed", - "\n- **ExchangeRate**: List of exchange rates to be used, for different currencies and as-of dates (year/month), with a type (Spot/Average); defined as the value of 1 foreign unit expressed in the group currency of the insurance company ", - "\n- **CreditDefaultRate**: For relevant year/month combinations, each with a full list of all credit ratings in S&P notation with their default rate (= probabilty of default within 1 year)", - "\n- **PartnerRating**: For each reinsurance partner of a relevant GRIC, the rating in S&P notation with the as-of date (year/month)" - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Data input: Groups of insurance and reinsurance contracts", - "\n", - "\nSee folder Files/900.TransactionalData.", - "\n- **Actuals** *\\_* *\\_* *\\_*: List of all actual amounts for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types and other attributes; we need at least two such files for the two dates of the Analysis of Change", - "\n- **Openings** *\\_* *\\_* *\\_*: List of the opening amounts for some GICs that are used by the given reporting node. The year/month combination corresponds to the beginning of the planned Analysis of Change period, so only one such file is required. The entries are by EstimateType and AmountType.", - "\n- **NominalCashflows** *\\_* *\\_* *\\_*: List of all projected cash flows for those GICs and GRICs that are used by the given reporting node/year/month combination, for different amount types, AoC types, novelty types and other attributes, where the cash flow amounts are given in a regular sequence extending as far as needed; we need at least two such files for the two dates of the Analysis of Change", - "\n", - "\nThe structure of the [Actuals](./InputFormatDescription#actual), [Openings](./InputFormatDescription#opening) and [NominalCashflows](./InputFormatDescription#cashflow) files is explained in a special [notebook](./InputFormatDescription).", - "\n", - "\nThe less usual option of having discounted instead of nominal cash flows in the input is also supported." - ] - }, { "cell_type": "markdown", "source": [ @@ -213,9 +153,7 @@ "\n", "\nSome reports of ReportScopes just present existing data from the database, namely the imported data and the results already calculated using the methods of [ImportScopes](#model-calc).", "\n", - "\nSome other reports related to **[Financial Performance](./Report/ReportScopes#financial-performance)** (profit & loss) require further calculations provided by ReportScopes. An IFRS 17 financial performance report has at least four sections: Insurance Revenue, Insurance Service Expense, Insurance Finance Income/Expense and Other Comprehensive Income. Formulas are provided [here](./Report/ReportScopes#financial-performance).", - "\n", - "\nWhile the ReportScopes notebook provides the calculation formulas for different reports, the production of reports is done by a notebook such as **[Reports](./Report/Reports#report-production)** which imports ReportScopes." + "\nSome other reports related to **[Financial Performance](./Report/ReportScopes#financial-performance)** (profit & loss) require further calculations provided by ReportScopes. An IFRS 17 financial performance report has at least four sections: Insurance Revenue, Insurance Service Expense, Insurance Finance Income/Expense and Other Comprehensive Income. Formulas are provided [here](./Report/ReportScopes#financial-performance)." ] }, { diff --git a/ifrs17/README.md b/ifrs17/README.md index 5173f5ae..4447c0c3 100644 --- a/ifrs17/README.md +++ b/ifrs17/README.md @@ -1 +1,31 @@ -# IFRS17CalculationEngine \ No newline at end of file +![Systemorph_logo.png](https://portal.systemorph.cloud/api/project/ifrs17ce/env/dev/file/download?path=Images/Systemorph_logo.png) + + +**IFRS17 Calculation Engine** + +Systemorph's IFRS 17 Calculation Engine is a tool to conduct all the essential IFRS 17 calculations given some key figures, future cashflows and actual amounts, for groups of insurance contracts and other basic information. The result is a set of reports needed for IFRS 17 accounting and management information. + +# Get started + +Systemorph portal allows Users to create their own projects powered by the Vertex 10 technology. + +## Overview + +![BigPicture.png](https://portal.systemorph.cloud/api/project/ifrs17ce/env/dev/file/download?path=Images/BigPicture.png) + + +If you want to know more about the Calculation Engine than just its standard technical use, you are recommended to look at [OverviewCalculationEngine](OverviewCalculationEngine). +You will be introduced to +- [DataModel](./DataModel/DataStructure) with links to detailed description of individual data types, dimensions and partitions employed +- [Calculation](./Import/ImportScopeCalculation) with in detail description using mathematical formulas and links to supporting material +- [Reports](./Report/ReportScopes) for data analysis and drill down to the lowest data granularity. With links to discover the calculation of the [Financial Performance](./Report/ReportScopes#ifrs-17-financial-performance) + + +## Got Questions + +For support around the IFRS17 CalculationEngine you can personally reach out to one of our IFRS17 experts: +- [Dr. Andrea Muolo]() +- [Dr. Davide Colleoni](https://www.linkedin.com/in/davidecolleoni/) +- [Mrs. Sara Busato]() + +If you are interested in adapting the IFRS17 CalculationEngine to your data and would like to start a collaboration with us, you can contact [Wolfgang Maehr]() \ No newline at end of file From c24a5587e700589abeadb492e0f55df2f05ace7c Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Tue, 11 Oct 2022 15:27:02 +0200 Subject: [PATCH 18/38] include changes on factory --- ifrs17/Import/Importers.ipynb | 64 +++++++++++++++++++---------------- 1 file changed, 34 insertions(+), 30 deletions(-) diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 319f9b9e..d8902a79 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -266,36 +266,32 @@ { "cell_type": "code", "source": [ - "// TODO: think of a better Factory to instantiate DataNode/State/Parameter simultaneously while avoiding public contructors (see Factory Patterns)", - "\n// ATTENTION: this Factory method provides default states and parameters so that it is not mandatory to import them (=> simpler calculation engine). ", - "\n// This method weakness is that these defaults aren't always replaced with the imported values, e,g, when Month > DefaultDataNodeActivationMonth.", - "\n// Therefore they will remain in the DataSource (hopefully without producing any harm).", - "\npublic async Task DataNodeFactoryAsync ()", + "public async Task DataNodeFactoryAsync (string file, string tab, ImportArgs args)", "\n{", - "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", - "\n var existingGroupOfContracts = await DataSource.Query().Where(x => x.Partition == partition).ToArrayAsync();", - "\n var importedGroupOfContracts = await Workspace.Query().ToArrayAsync();", - "\n var listOfPartitionsWithPeriod = new List();", - "\n ", - "\n foreach (var groupOfContract in importedGroupOfContracts)", - "\n {", - "\n var name = groupOfContract.SystemName;", - "\n if(!existingGroupOfContracts.Any(x => x.SystemName == name))", - "\n {", - "\n var state = new DataNodeState { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", - "\n var parameter = new SingleDataNodeParameter { DataNode = name, Year = groupOfContract.AnnualCohort, Partition = partition };", - "\n await Workspace.UpdateAsync(state);", - "\n if(groupOfContract is GroupOfInsuranceContract) await Workspace.UpdateAsync(parameter);", - "\n }", - "\n }", - "\n ", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n await CommitToDatabase(partition);", - "\n //Hot fix: Disabling default as using Annual Cohort breakes Opening importer logic. ", - "\n //await CommitToDatabase(partition, snapshot: false);", - "\n //await CommitToDatabase(partition, snapshot: false);", + "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == args.ReportingNode && p.Scenario == null).ToArrayAsync()).SingleOrDefault();", + "\n if(partition == null) { ApplicationMessage.Log(Error.ParsedPartitionNotFound); return; }", + "\n", + "\n var extension = System.IO.Path.GetExtension(file);", + "\n var stream = await Project.FileStorage.ReadAsync(file);", + "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[tab];", + "\n ", + "\n var dataNodesImported = target.Rows.Select(x => x.Field(nameof(RawVariable.DataNode))).ToHashSet();", + "\n var dataNodesDefined = await DataSource.Query().Where(x => dataNodesImported.Contains(x.SystemName)).ToArrayAsync();", + "\n var dataNodeStatesDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync();", + "\n var dataNodeParametersDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync(); ", + "\n ", + "\n var dataNodeStatesUndefined = dataNodesImported.Where(x => x != null && !dataNodeStatesDefined.Contains(x)).ToHashSet();", + "\n var dataNodeSingleParametersUndefined = dataNodesImported.Where(x => x != null &&", + "\n !dataNodeParametersDefined.Contains(x) && ", + "\n dataNodesDefined.SingleOrDefault(y => y.SystemName == x) is GroupOfInsuranceContract).ToHashSet();", + "\n ", + "\n await DataSource.UpdateAsync( dataNodeStatesUndefined.Select(x => ", + "\n new DataNodeState {DataNode = x, Year = args.Year, Month = DefaultDataNodeActivationMonth, State = State.Active, Partition = partition.Id}).ToArray() );", + "\n ", + "\n await DataSource.UpdateAsync( dataNodeSingleParametersUndefined.Select(x => ", + "\n new SingleDataNodeParameter {DataNode = x, Year = args.Year, Month = DefaultDataNodeActivationMonth, PremiumAllocation = DefaultPremiumExperienceAdjustmentFactor, Partition = partition.Id}).ToArray() );", + "\n ", + "\n await DataSource.CommitAsync();", "\n}" ] }, @@ -492,7 +488,11 @@ "\n var log = await UploadDataNodesToWorkspaceAsync(fileName);", "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", "\n ", - "\n await DataNodeFactoryAsync(); ", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition);", + "\n await CommitToDatabase(partition); ", + "\n ", "\n return log;", "\n}" ] @@ -784,6 +784,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Cashflow};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.Cashflow, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(fileName, args);", @@ -886,6 +887,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Actual};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.Actual, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", "\n var parsingLog = await ParseActualsToWorkspaceAsync(fileName, args);", @@ -997,6 +999,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.SimpleValue};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.SimpleValue, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n Guid partitionId = new Guid();", @@ -1026,6 +1029,7 @@ "\n{", "\n Activity.Start();", "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Opening};", + "\n await DataNodeFactoryAsync(fileName, ImportFormats.Opening, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n Guid partitionId = new Guid();", From 92f6876be0aa8d3141f0864e7ef2abc620450971 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Thu, 13 Oct 2022 12:20:59 +0200 Subject: [PATCH 19/38] adapt to the split --- .../Test/AocConfigurationTest.ipynb | 58 ++++++++++++++++ ifrs17/Constants/Consts.ipynb | 1 + ifrs17/DataModel/DataStructure.ipynb | 20 +++--- ifrs17/Import/Importers.ipynb | 69 +++++++++++++++++-- ifrs17/Utils/ApplicationMessage.ipynb | 4 +- 5 files changed, 133 insertions(+), 19 deletions(-) create mode 100644 full-ifrs17-template/Test/AocConfigurationTest.ipynb diff --git a/full-ifrs17-template/Test/AocConfigurationTest.ipynb b/full-ifrs17-template/Test/AocConfigurationTest.ipynb new file mode 100644 index 00000000..23448027 --- /dev/null +++ b/full-ifrs17-template/Test/AocConfigurationTest.ipynb @@ -0,0 +1,58 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Test Aoc Configuration

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Workspace Initialization " + ] + }, + { + "cell_type": "code", + "source": [ + "Workspace.InitializeFrom(DataSource);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Test" + ] + }, + { + "cell_type": "code", + "source": [ + "var args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", + "\nvar partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", + "\n x.Month == args.Month && x.Scenario == args.Scenario);", + "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + ] + } + ] +} \ No newline at end of file diff --git a/ifrs17/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb index 79179ff2..be666faf 100644 --- a/ifrs17/Constants/Consts.ipynb +++ b/ifrs17/Constants/Consts.ipynb @@ -201,6 +201,7 @@ "\n public const string RCU = nameof(RCU);", "\n public const string CF = nameof(CF);", "\n public const string IA = nameof(IA);", + "\n public const string AU = nameof(AU);", "\n public const string YCU = nameof(YCU);", "\n public const string CRU = nameof(CRU);", "\n public const string WO = nameof(WO);", diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index 98114494..f5fcf571 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -43,16 +43,16 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Workspace,1.2.0\"", - "\n#r \"nuget:Systemorph.Scopes,1.2.4\"", - "\n#r \"nuget:Systemorph.Import,1.3.0\"", - "\n#r \"nuget:Systemorph.Test,1.2.4\"", - "\n#r \"nuget:Systemorph.Export,1.3.0\"", - "\n#r \"nuget:Systemorph.DataSetReader,1.3.0\"", - "\n#r \"nuget:Systemorph.DataSource,1.2.0\"", - "\n#r \"nuget:Systemorph.DataSource.Conversions,1.2.0\"", - "\n#r \"nuget:Systemorph.Reporting,1.2.4\"", - "\n#r \"nuget:Systemorph.DomainDesigner,1.3.0\"" + "#r \"nuget:Systemorph.Workspace,1.4.1\"", + "\n#r \"nuget:Systemorph.Scopes,1.4.0\"", + "\n#r \"nuget:Systemorph.Import,1.4.0\"", + "\n#r \"nuget:Systemorph.Test,1.4.0\"", + "\n#r \"nuget:Systemorph.Export,1.4.0\"", + "\n#r \"nuget:Systemorph.DataSetReader,1.4.0\"", + "\n#r \"nuget:Systemorph.DataSource,1.4.1\"", + "\n#r \"nuget:Systemorph.DataSource.Conversions,1.4.1\"", + "\n#r \"nuget:Systemorph.Reporting,1.4.0\"", + "\n#r \"nuget:Systemorph.DomainDesigner,1.4.0\"" ] }, { diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 34ab4202..482ed926 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -266,21 +266,20 @@ { "cell_type": "code", "source": [ - "public async Task DataNodeFactoryAsync (string file, string tab, ImportArgs args)", + "public async Task DataNodeFactoryAsync(string file, string tab, ImportArgs args)", "\n{", "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == args.ReportingNode && p.Scenario == null).ToArrayAsync()).SingleOrDefault();", "\n if(partition == null) { ApplicationMessage.Log(Error.ParsedPartitionNotFound); return; }", "\n", "\n var extension = System.IO.Path.GetExtension(file);", "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[tab];", - "\n ", + "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet.Tables[tab];", "\n", "\n var dataNodesImported = target.Rows.Select(x => x.Field(nameof(RawVariable.DataNode))).ToHashSet();", "\n var dataNodesDefined = await DataSource.Query().Where(x => dataNodesImported.Contains(x.SystemName)).ToArrayAsync();", "\n var dataNodeStatesDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync();", "\n var dataNodeParametersDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync(); ", - "\n ", + "\n", "\n var dataNodeStatesUndefined = dataNodesImported.Where(x => x != null && !dataNodeStatesDefined.Contains(x)).ToHashSet();", "\n var dataNodeSingleParametersUndefined = dataNodesImported.Where(x => x != null &&", "\n !dataNodeParametersDefined.Contains(x) && ", @@ -291,7 +290,7 @@ "\n", "\n await DataSource.UpdateAsync( dataNodeSingleParametersUndefined.Select(x => ", "\n new SingleDataNodeParameter {DataNode = x, Year = args.Year, Month = DefaultDataNodeActivationMonth, PremiumAllocation = DefaultPremiumExperienceAdjustmentFactor, Partition = partition.Id}).ToArray() );", - "\n ", + "\n", "\n await DataSource.CommitAsync();", "\n}" ] @@ -319,6 +318,63 @@ "\n}" ] }, + { + "cell_type": "markdown", + "source": [ + "### Analysis of Change Configuration" + ] + }, + { + "cell_type": "code", + "source": [ + "Import.DefineFormat(\"AocConfiguration\", async (options, dataSet) => {", + "\n Activity.Start();", + "\n var workspace = Workspace.CreateNew();", + "\n workspace.InitializeFrom(DataSource);", + "\n", + "\n var logConfig = await Import.FromDataSet(dataSet).WithType().WithTarget(workspace).ExecuteAsync();", + "\n if(logConfig.Errors.Any()) return logConfig.RepeatOnce(); ", + "\n", + "\n var aocTypes = await options.TargetDataSource.Query().OrderBy(x => x.Order).ToArrayAsync();", + "\n var orderByName = aocTypes.ToDictionary(x => x.SystemName, x => x.Order);", + "\n var distanceByNames = aocTypes.SelectMany(x => aocTypes.Select(y => (x.SystemName, y.SystemName, Array.IndexOf(aocTypes, x) - Array.IndexOf(aocTypes, y))))", + "\n .ToDictionary(x => (x.Item1, x.Item2), x => x.Item3);", + "\n", + "\n var aocConfigs = (await workspace.Query().ToArrayAsync())", + "\n .GroupBy(x => (x.AocType, x.Novelty))", + "\n .Select(y => y.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault())", + "\n .ToDictionary(x => (x.AocType, x.Novelty));", + "\n", + "\n foreach(var newAocType in orderByName.Keys.Where(x => !aocConfigs.Keys.Contains((x,Novelties.I))).ToArray()) {", + "\n if(orderByName[newAocType] < orderByName[AocTypes.RCU])", + "\n {", + "\n var config = aocConfigs[(AocTypes.MC, Novelties.I)];", + "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType, AocTypes.MC)] }); ", + "\n }", + "\n else if(orderByName[newAocType] < orderByName[AocTypes.CF] && orderByName[newAocType] > orderByName[AocTypes.RCU]) ", + "\n {", + "\n var config = aocConfigs[(AocTypes.RCU, Novelties.I)];", + "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType, AocTypes.RCU)] });", + "\n }", + "\n else if(orderByName[newAocType] < orderByName[AocTypes.YCU] && orderByName[newAocType] > orderByName[AocTypes.IA]) ", + "\n {", + "\n var config = aocConfigs[(AocTypes.AU, Novelties.I)];", + "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType,AocTypes.AU)] } );", + "\n }", + "\n else if(orderByName[newAocType] > orderByName[AocTypes.CRU])", + "\n {", + "\n var config = aocConfigs[(AocTypes.EV, Novelties.I)];", + "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType,AocTypes.EV)] } );", + "\n }", + "\n else", + "\n ApplicationMessage.Log(Error.Generic, $\"The AocType {newAocType} has been added in a wrong position.\");", + "\n };", + "\n", + "\n await workspace.CommitToTargetAsync(options.TargetDataSource);", + "\n return new[] {Activity.Finish(),logConfig}; ", + "\n});" + ] + }, { "cell_type": "markdown", "source": [ @@ -332,7 +388,7 @@ "\n{", "\n var extension = System.IO.Path.GetExtension(file);", "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[Main];", + "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet.Tables[Main];", "\n ", "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", @@ -492,7 +548,6 @@ "\n await CommitToDatabase(partition);", "\n await CommitToDatabase(partition);", "\n await CommitToDatabase(partition);", - "\n ", "\n return log;", "\n}" ] diff --git a/ifrs17/Utils/ApplicationMessage.ipynb b/ifrs17/Utils/ApplicationMessage.ipynb index 2bc8ec97..a03f0301 100644 --- a/ifrs17/Utils/ApplicationMessage.ipynb +++ b/ifrs17/Utils/ApplicationMessage.ipynb @@ -27,7 +27,7 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Activities,1.2.3\"" + "#r \"nuget:Systemorph.Activities,1.4.0\"" ] }, { @@ -53,10 +53,10 @@ "\n }", "\n ", "\n public static Object Log (Error e, params string[] s) { log.LogError(Get(e,s)); return null; }", - "\n ", "\n public static Object Log (Warning w, params string[] s) { log.LogWarning(Get(w,s)); return null; }", "\n ", "\n public static bool HasErrors () => activity.HasErrors();", + "\n public static bool HasWarnings () => activity.HasWarnings();", "\n}" ] }, From 005f28f278399110539464f0706d54222529d9e3 Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Fri, 14 Oct 2022 14:54:30 +0200 Subject: [PATCH 20/38] update packages and fix csm with bm --- .../BM_CH_2020_12_C.csv | 32 ++-- .../BM_CH_2020_12_DA.csv | 25 ++- .../BM_CH_2020_12_F.csv | 19 ++- .../IfrsVariableBenchmarks/BM_CH_2021_3_C.csv | 59 ++++--- .../BM_CH_2021_3_DA.csv | 33 ++-- .../IfrsVariableBenchmarks/BM_CH_2021_3_F.csv | 17 +- .../IfrsVariableBenchmarks/BM_CH_2021_3_L.csv | 7 +- .../BM_CH_2021_3_LR.csv | 4 +- ...ableBenchmarks_2020_12_CH__Contractual.csv | 82 +++++----- ...iableBenchmarks_2021_3_CH__Contractual.csv | 151 +++++++++--------- .../Test/IfrsVariablesTest.ipynb | 16 +- full-ifrs17-template/Test/QueriesTest.ipynb | 12 +- .../Test/SpecificationsImportCashflows.ipynb | 4 +- ifrs17/DataModel/DataStructure.ipynb | 20 +-- ifrs17/Import/ImportScopeCalculation.ipynb | 18 ++- ifrs17/Import/Importers.ipynb | 4 +- ifrs17/Utils/ApplicationMessage.ipynb | 2 +- 17 files changed, 257 insertions(+), 248 deletions(-) diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv index cf8c8f5f..061f2e7e 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_C.csv @@ -1,40 +1,40 @@ @@Main -Month,ReportingNode,Scenario,Year -12,CH,,2020 +ReportingNode,Year,Month,Scenario +CH,2020,12, @@C AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value -,,AM,DTR1.1,,C,C,24.228134693791258 +,,AM,DTR1.1,,C,C,46.24958203305145 ,,IA,DT1.3,,C,N,0.08233273235018213 ,,BOP,DT1.3,,C,N,139.90849210284577 -,,EOP,DT1.3,,C,C,82.02271122089925 -,,AM,DT1.3,,C,C,-42.968113614296705 +,,EOP,DT1.3,,C,C,42.9681136142967 +,,AM,DT1.3,,C,C,-82.02271122089925 ,,EA,DT1.3,,C,C,-15 ,,EA,DT1.1,,C,C,-15 -,,AM,DT1.1,,C,C,-42.968113614296705 -,,EOP,DT1.1,,C,C,82.02271122089925 +,,AM,DT1.1,,C,C,-82.02271122089925 +,,EOP,DT1.1,,C,C,42.9681136142967 ,,BOP,DT1.1,,C,N,139.90849210284577 ,,IA,DT1.1,,C,N,0.08233273235018213 ,,EA,DT2.1,,C,C,-15 -,,AM,DT2.1,,C,C,-42.968113614296705 -,,EOP,DT2.1,,C,C,82.02271122089925 +,,AM,DT2.1,,C,C,-82.02271122089925 +,,EOP,DT2.1,,C,C,42.9681136142967 ,,BOP,DT2.1,,C,N,139.90849210284577 ,,IA,DT2.1,,C,N,0.08233273235018213 -,,EOP,DTR1.1,,C,C,-46.24958203305145 +,,EOP,DTR1.1,,C,C,-24.22813469379126 ,,BOP,DTR1.1,,C,N,-70.43538016962212 ,,IA,DTR1.1,,C,N,-0.04233655722058882 -,,AM,DTR2.1,,C,C,24.228134693791258 -,,EOP,DTR2.1,,C,C,-46.24958203305145 +,,AM,DTR2.1,,C,C,46.24958203305145 +,,EOP,DTR2.1,,C,C,-24.22813469379126 ,,BOP,DTR2.1,,C,N,-70.43538016962212 ,,IA,DTR2.1,,C,N,-0.04233655722058882 ,,BOP,DT3.1,,C,I,72.2 ,,EA,DT3.1,,C,C,-15 -,,AM,DT3.1,,C,C,-67.83795828214956 -,,EOP,DT3.1,,C,C,129.49726655304642 +,,AM,DT3.1,,C,C,-129.49726655304642 +,,EOP,DT3.1,,C,C,67.83795828214957 ,,IA,DT3.1,,C,I,0.14440000000001615 ,,BOP,DT3.1,,C,N,139.90849210284577 ,,IA,DT3.1,,C,N,0.08233273235018213 ,,EA,DT4.1,,C,C,-15 -,,AM,DT4.1,,C,C,-42.968113614296705 -,,EOP,DT4.1,,C,C,82.02271122089925 +,,AM,DT4.1,,C,C,-82.02271122089925 +,,EOP,DT4.1,,C,C,42.9681136142967 ,,BOP,DT4.1,,C,N,139.90849210284577 ,,IA,DT4.1,,C,N,0.08233273235018213 \ No newline at end of file diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv index 0b2eb99d..900aadb2 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_DA.csv @@ -1,21 +1,20 @@ -$$Default @@Main -Month,ReportingNode,Scenario,Year -12,CH,,2020 +ReportingNode,Year,Month,Scenario +CH,2020,12, @@DA AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value -,,EOP,DT1.3,,DA,C,-9.843447868559382 -,,AM,DT1.3,,DA,C,5.156552131440618 +,,EOP,DT1.3,,DA,C,-5.156552131440618 +,,AM,DT1.3,,DA,C,9.843447868559382 ,,CF,DT1.3,,DA,C,-15 ,,CF,DT1.1,,DA,C,-15 -,,AM,DT1.1,,DA,C,5.156552131440618 -,,EOP,DT1.1,,DA,C,-9.843447868559382 +,,AM,DT1.1,,DA,C,9.843447868559382 +,,EOP,DT1.1,,DA,C,-5.156552131440618 ,,CF,DT2.1,,DA,C,-15 -,,AM,DT2.1,,DA,C,5.156552131440618 -,,EOP,DT2.1,,DA,C,-9.843447868559382 +,,AM,DT2.1,,DA,C,9.843447868559382 +,,EOP,DT2.1,,DA,C,-5.156552131440618 ,,CF,DT3.1,,DA,C,-15 -,,AM,DT3.1,,DA,C,5.156552131440618 -,,EOP,DT3.1,,DA,C,-9.843447868559382 +,,AM,DT3.1,,DA,C,9.843447868559382 +,,EOP,DT3.1,,DA,C,-5.156552131440618 ,,CF,DT4.1,,DA,C,-15 -,,AM,DT4.1,,DA,C,5.156552131440618 -,,EOP,DT4.1,,DA,C,-9.843447868559382 \ No newline at end of file +,,AM,DT4.1,,DA,C,9.843447868559382 +,,EOP,DT4.1,,DA,C,-5.156552131440618 \ No newline at end of file diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv index 91b1b7f4..8c0006b2 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2020_12_F.csv @@ -1,17 +1,16 @@ -$$Default @@Main -Month,ReportingNode,Scenario,Year -12,CH,,2020 +ReportingNode,Year,Month,Scenario +CH,2020,12, @@F AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value -,,AM,DT1.1,L,F,C,0.3437701420960412 +,,AM,DT1.1,L,F,C,0.6562298579039588 ,,AM,DT1.2,L,F,C,1 -,,AM,DT1.3,L,F,C,0.3437701420960412 -,,AM,DT2.1,L,F,C,0.3437701420960412 +,,AM,DT1.3,L,F,C,0.6562298579039588 +,,AM,DT2.1,L,F,C,0.6562298579039588 ,,AM,DT2.2,L,F,C,1 -,,AM,DTR1.1,L,F,C,0.3437701420960412 +,,AM,DTR1.1,L,F,C,0.6562298579039588 ,,AM,DTR1.2,L,F,C,1 -,,AM,DTR2.1,L,F,C,0.3437701420960412 +,,AM,DTR2.1,L,F,C,0.6562298579039588 ,,AM,DTR2.2,L,F,C,1 -,,AM,DT3.1,L,F,C,0.3437701420960412 -,,AM,DT4.1,L,F,C,0.3437701420960412 \ No newline at end of file +,,AM,DT3.1,L,F,C,0.6562298579039588 +,,AM,DT4.1,L,F,C,0.6562298579039588 \ No newline at end of file diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv index 965e5e6f..fdf3a318 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_C.csv @@ -1,55 +1,54 @@ @@Main -Month,ReportingNode,Scenario,Year -3,CH,,2021 +ReportingNode,Year,Month,Scenario +CH,2021,3, @@C AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value ,,CL,DT2.1,,C,C,-87.43135554903122 -,,IA,DT2.1,,C,I,0.09388697662967685 +,,IA,DT2.1,,C,I,0.07437430623754743 ,,MC,DT2.1,,C,I,105.89201388261736 -,,EOP,DT2.1,,C,C,18.374757965777995 -,,AM,DT2.1,,C,C,-38.60249856533708 +,,EOP,DT2.1,,C,C,12.129509556366447 +,,AM,DT2.1,,C,C,-5.773636697753954 ,,EA,DT2.1,,C,C,-43.599999999999994 -,,BOP,DT2.1,,C,I,82.02271122089925 +,,BOP,DT2.1,,C,I,42.9681136142967 ,,CL,DT1.3,,C,C,-87.43135554903122 -,,BOP,DT1.1,,C,I,82.02271122089925 +,,BOP,DT1.1,,C,I,42.9681136142967 ,,EA,DT1.1,,C,C,-43.599999999999994 -,,AM,DT1.1,,C,C,-38.60249856533708 -,,EOP,DT1.1,,C,C,18.374757965777995 +,,AM,DT1.1,,C,C,-5.773636697753954 +,,EOP,DT1.1,,C,C,12.129509556366447 ,,MC,DT1.1,,C,I,105.89201388261736 -,,IA,DT1.1,,C,I,0.09388697662967685 +,,IA,DT1.1,,C,I,0.07437430623754743 ,,CL,DT1.1,,C,C,-87.43135554903122 -,,BOP,DT1.3,,C,I,82.02271122089925 +,,BOP,DT1.3,,C,I,42.9681136142967 ,,EA,DT1.3,,C,C,-50 -,,AM,DT1.3,,C,C,-34.26645281902704 -,,EOP,DT1.3,,C,C,16.31080371208803 +,,AM,DT1.3,,C,C,-3.7096824440639895 +,,EOP,DT1.3,,C,C,7.793463810056405 ,,MC,DT1.3,,C,I,105.89201388261736 -,,IA,DT1.3,,C,I,0.09388697662967685 -,,BOP,DTR1.1,,C,I,-46.24958203305145 -,,AM,DTR1.1,,C,C,38.316584766326955 -,,EOP,DTR1.1,,C,C,-18.238663229656325 +,,IA,DT1.3,,C,I,0.07437430623754743 +,,BOP,DTR1.1,,C,I,-24.22813469379126 +,,AM,DTR1.1,,C,C,11.133355649364928 +,,EOP,DTR1.1,,C,C,-23.389442532110124 ,,MC,DTR1.1,,C,I,-52.92295262051829 -,,IA,DTR1.1,,C,I,-0.04954912095471157 +,,IA,DTR1.1,,C,I,-0.03854664570667637 ,,CRU,DTR1.1,,C,I,-0.5933128558860402 ,,CL,DTR1.1,,C,C,43.26014863442721 -,,BOP,DTR2.1,,C,I,-46.24958203305145 -,,AM,DTR2.1,,C,C,38.316584766326955 -,,EOP,DTR2.1,,C,C,-18.238663229656325 +,,BOP,DTR2.1,,C,I,-24.22813469379126 +,,AM,DTR2.1,,C,C,11.133355649364928 +,,EOP,DTR2.1,,C,C,-23.389442532110124 ,,MC,DTR2.1,,C,I,-52.92295262051829 -,,IA,DTR2.1,,C,I,-0.04954912095471157 +,,IA,DTR2.1,,C,I,-0.03854664570667637 ,,CRU,DTR2.1,,C,I,-0.5933128558860402 ,,CL,DTR2.1,,C,C,43.26014863442721 -,,BOP,DT3.1,,C,I,129.49726655304642 -,,EA,DT3.1,,C,C,-43.599999999999994 -,,AM,DT3.1,,C,C,-51.96181825867143 +,,BOP,DT3.1,,C,I,67.83795828214957 +,,EA,DT3.1,,C,C,-33.87170342894083 ,,MC,DT3.1,,C,I,105.89201388261736 -,,IA,DT3.1,,C,I,0.11760647207910604 +,,IA,DT3.1,,C,I,0.08679991324534386 ,,CL,DT3.1,,C,C,-139.94506864907146 -,,BOP,DT4.1,,C,I,82.02271122089925 +,,BOP,DT4.1,,C,I,42.9681136142967 ,,EA,DT4.1,,C,C,-51.599999999999994 -,,AM,DT4.1,,C,C,-96.83022811966929 -,,EOP,DT4.1,,C,C,46.091109943532146 +,,AM,DT4.1,,C,C,-33.48998867550812 +,,EOP,DT4.1,,C,C,70.35723911069866 ,,MC,DT4.1,,C,I,105.89201388261736 -,,IA,DT4.1,,C,I,0.09388697662967685 +,,IA,DT4.1,,C,I,0.07437430623754743 ,,BOP,DT4.1,,C,N,8.004653973154419 ,,IA,DT4.1,,C,N,0.0003356307173485902 ,,EV,DT4.1,,C,N,-1.4922636208166304 \ No newline at end of file diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv index 437c7cf1..be7fcf90 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_DA.csv @@ -1,25 +1,24 @@ -$$Default @@Main -Month,ReportingNode,Scenario,Year -3,CH,,2021 +ReportingNode,Year,Month,Scenario +CH,2021,3, @@DA AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value -,,EOP,DT2.1,,DA,C,-8.011834360099684 -,,AM,DT2.1,,DA,C,16.831613508459697 -,,BOP,DT2.1,,DA,I,-9.843447868559382 +,,EOP,DT2.1,,DA,C,-13.656208145282752 +,,AM,DT2.1,,DA,C,6.500343986157867 +,,BOP,DT2.1,,DA,I,-5.156552131440618 ,,CF,DT2.1,,DA,C,-15 ,,CF,DT1.1,,DA,C,-15 -,,BOP,DT1.1,,DA,I,-9.843447868559382 -,,AM,DT1.1,,DA,C,16.831613508459697 -,,EOP,DT1.1,,DA,C,-8.011834360099684 +,,BOP,DT1.1,,DA,I,-5.156552131440618 +,,AM,DT1.1,,DA,C,6.500343986157867 +,,EOP,DT1.1,,DA,C,-13.656208145282752 ,,CF,DT1.3,,DA,C,-15 -,,BOP,DT1.3,,DA,I,-9.843447868559382 -,,AM,DT1.3,,DA,C,16.831613508459697 -,,EOP,DT1.3,,DA,C,-8.011834360099684 +,,BOP,DT1.3,,DA,I,-5.156552131440618 +,,AM,DT1.3,,DA,C,6.500343986157867 +,,EOP,DT1.3,,DA,C,-13.656208145282752 ,,CF,DT3.1,,DA,C,-15 -,,BOP,DT3.1,,DA,I,-9.843447868559382 -,,AM,DT3.1,,DA,C,24.84344786855938 +,,BOP,DT3.1,,DA,I,-5.156552131440618 +,,AM,DT3.1,,DA,C,20.15655213144062 ,,CF,DT4.1,,DA,C,-15 -,,BOP,DT4.1,,DA,I,-9.843447868559382 -,,AM,DT4.1,,DA,C,16.831613508459697 -,,EOP,DT4.1,,DA,C,-8.011834360099684 \ No newline at end of file +,,BOP,DT4.1,,DA,I,-5.156552131440618 +,,AM,DT4.1,,DA,C,6.500343986157867 +,,EOP,DT4.1,,DA,C,-13.656208145282752 \ No newline at end of file diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv index c443cf93..f7419efa 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_F.csv @@ -1,17 +1,16 @@ -$$Default @@Main -Month,ReportingNode,Scenario,Year -3,CH,,2021 +ReportingNode,Year,Month,Scenario +CH,2021,3, @@F AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value -,,AM,DT1.1,L,F,C,0.6775071478609433 +,,AM,DT1.1,L,F,C,0.32249285213905665 ,,AM,DT1.2,L,F,C,1 -,,AM,DT1.3,L,F,C,0.6775071478609433 -,,AM,DT2.1,L,F,C,0.6775071478609433 +,,AM,DT1.3,L,F,C,0.32249285213905665 +,,AM,DT2.1,L,F,C,0.32249285213905665 ,,AM,DT2.2,L,F,C,1 -,,AM,DTR1.1,L,F,C,0.6775071478609433 +,,AM,DTR1.1,L,F,C,0.32249285213905665 ,,AM,DTR1.2,L,F,C,1 -,,AM,DTR2.1,L,F,C,0.6775071478609433 +,,AM,DTR2.1,L,F,C,0.32249285213905665 ,,AM,DTR2.2,L,F,C,1 ,,AM,DT3.1,L,F,C,1 -,,AM,DT4.1,L,F,C,0.6775071478609433 \ No newline at end of file +,,AM,DT4.1,L,F,C,0.32249285213905665 \ No newline at end of file diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv index b4ae0c7e..9a6831e3 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_L.csv @@ -1,7 +1,6 @@ -$$Default @@Main -Month,ReportingNode,Scenario,Year -3,CH,,2021 +ReportingNode,Year,Month,Scenario +CH,2021,3, @@L AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value ,,CL,DT2.1,,L,C,-87.43135554903122 @@ -16,6 +15,8 @@ AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Valu ,,BOP,DT1.3,,L,N,31.958738976731105 ,,IA,DT1.3,,L,N,0.016300537999407044 ,,EV,DT1.3,,L,N,55.45631603430072 +,,EA,DT3.1,,L,C,9.728296571059161 +,,AM,DT3.1,,L,C,-9.728296571059161 ,,BOP,DT3.1,,L,N,31.958738976731105 ,,IA,DT3.1,,L,N,0.016300537999407044 ,,EV,DT3.1,,L,N,55.45631603430072 diff --git a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv index 93205b6d..0596dea4 100644 --- a/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv +++ b/full-ifrs17-template/Test/Data/IfrsVariableBenchmarks/BM_CH_2021_3_LR.csv @@ -1,6 +1,6 @@ @@Main -Month,ReportingNode,Scenario,Year -3,CH,,2021 +ReportingNode,Year,Month,Scenario +CH,2021,3, @@LR AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value ,,BOP,DTR1.1,,LR,N,-15.684995728561214 diff --git a/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv b/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv index 8b78df02..80bfedb2 100644 --- a/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv +++ b/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2020_12_CH__Contractual.csv @@ -34,19 +34,19 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,399.6339294988556,OCI1 0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-299.675549694236,OCI1 0,PR,2020,USD,L,BEPA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,320,IR6 -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-82.02271122089925,AM 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,139.90849210284577,BOP 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,EA -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,42.9681136142967,EOP 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.08233273235018213,IA 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.08233273235018213,IFIE1 -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,82.02271122089925,IR3 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-124.90849210284577,IR5 -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,9.843447868559382,AM 0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-9.843447868559382,EOP -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,IR4 -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.156552131440618,EOP +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,9.843447868559382,IR4 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-9.843447868559382,ISE6 0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,C,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,L,RA,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF @@ -119,19 +119,19 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,399.6339294988556,OCI1 0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-299.675549694236,OCI1 0,PR,2020,USD,L,BEPA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,400,IR6 -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-82.02271122089925,AM 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,139.90849210284577,BOP 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,EA -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,42.9681136142967,EOP 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,0.08233273235018213,IA 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.08233273235018213,IFIE1 -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,82.02271122089925,IR3 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-124.90849210284577,IR5 -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,9.843447868559382,AM 0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-9.843447868559382,EOP -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.156552131440618,IR4 -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.156552131440618,EOP +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,9.843447868559382,IR4 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-9.843447868559382,ISE6 0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,C,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,L,RA,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,-30,CF @@ -176,19 +176,19 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,OCI1 0,PR,2020,USD,L,BEPA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,320,IR6 -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-82.02271122089925,AM 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,139.90849210284577,BOP 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-15,EA -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,42.9681136142967,EOP 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,0.08233273235018213,IA 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.08233273235018213,IFIE1 -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,82.02271122089925,IR3 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-124.90849210284577,IR5 -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,9.843447868559382,AM 0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-9.843447868559382,EOP -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,5.156552131440618,IR4 -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5.156552131440618,EOP +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,9.843447868559382,IR4 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-9.843447868559382,ISE6 0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,C,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,L,RA,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,-30,CF @@ -260,21 +260,21 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,399.6339294988556,OCI1 0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-299.675549694236,OCI1 0,PR,2020,USD,L,BEPA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,320,IR6 -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-67.83795828214956,AM +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-129.49726655304642,AM 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,72.2,BOP 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,139.90849210284577,BOP 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-15,EA -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,129.49726655304642,EOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,67.83795828214956,EOP 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.14440000000001615,IA 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.08233273235018213,IA 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.22673273235019828,IFIE1 -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,67.83795828214956,IR3 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,129.49726655304642,IR3 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-124.90849210284577,IR5 -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,9.843447868559382,AM 0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-9.843447868559382,EOP -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,5.156552131440618,IR4 -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-5.156552131440618,EOP +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,9.843447868559382,IR4 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-9.843447868559382,ISE6 0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,1.5,BOP 0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,1.5,EOP 0,,2020,USD,L,RA,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,59.8752944598663,BOP @@ -323,19 +323,19 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,399.6339294988556,OCI1 0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-299.675549694236,OCI1 0,PR,2020,USD,L,BEPA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,320,IR6 -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-42.968113614296705,AM +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-82.02271122089925,AM 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,139.90849210284577,BOP 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-15,EA -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,82.02271122089925,EOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,42.9681136142967,EOP 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.08233273235018213,IA 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.08233273235018213,IFIE1 -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,42.968113614296705,IR3 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,82.02271122089925,IR3 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-124.90849210284577,IR5 -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,5.156552131440618,AM +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,9.843447868559382,AM 0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-9.843447868559382,EOP -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,5.156552131440618,IR4 -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5.156552131440618,ISE6 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-5.156552131440618,EOP +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,9.843447868559382,IR4 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-9.843447868559382,ISE6 0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,59.8752944598663,BOP 0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-30,CF @@ -388,13 +388,13 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-199.8169647494278,OCI1 0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,149.837774847118,OCI1 0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-0.11527160395201003,OCI1 -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,24.228134693791258,AM +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,46.24958203305145,AM 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-70.43538016962212,BOP -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-46.249582033051446,EOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-24.228134693791258,EOP 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-0.04233655722058882,IA 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.04233655722058882,IFIE1 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,70.43538016962212,ISE10 -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-24.228134693791258,ISE7 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-46.24958203305145,ISE7 0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.93764722993315,BOP 0,,2020,USD,C,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-29.93764722993315,BOP 0,,2020,USD,L,RA,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,15,CF @@ -482,13 +482,13 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0,OCI1 -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,24.228134693791258,AM +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,46.24958203305145,AM 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-70.43538016962212,BOP -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-46.249582033051446,EOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-24.228134693791258,EOP 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-0.04233655722058882,IA 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.04233655722058882,IFIE1 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,70.43538016962212,ISE10 -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-24.228134693791258,ISE7 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-46.24958203305145,ISE7 0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.93764722993315,BOP 0,,2020,USD,C,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-29.93764722993315,BOP 0,,2020,USD,L,RA,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,15,CF diff --git a/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv b/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv index f9cba291..bef760f1 100644 --- a/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv +++ b/full-ifrs17-template/Test/Data/ReportVariableBenchmarks/ReportVariableBenchmarks_2021_3_CH__Contractual.csv @@ -76,22 +76,22 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.3283233358608868,YCU 0,NIC,2020,USD,C,BE,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.22380254636726704,YCU 0,PR,2020,USD,L,BEPA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,96,IR6 -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-38.60249856533708,AM -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,82.02271122089925,BOP -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-5.773636697753954,AM +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,42.9681136142967,BOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903121,CL 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-43.599999999999994,EA -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,18.374757965778002,EOP -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.09388697662967685,IA -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09388697662967685,IFIE1 -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,38.60249856533708,IR3 -0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,25.139341666413856,IR5 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,12.129509556366443,EOP +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.07437430623754743,IA +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.07437430623754743,IFIE1 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,5.773636697753954,IR3 +0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,25.13934166641384,IR5 0,,2020,USD,,C,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,105.89201388261736,MC -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,AM -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,6.500343986157867,AM +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-5.156552131440618,BOP 0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.011834360099684,EOP -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,IR4 -0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-13.656208145282752,EOP +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,6.500343986157867,IR4 +0,,2020,USD,,DA,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-6.500343986157867,ISE6 0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,31.958738976731105,BOP 0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903124,CL 0,,2020,USD,,L,CHF,DT1.1,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0,EOP @@ -251,22 +251,22 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.3283233358608868,YCU 0,NIC,2020,USD,C,BE,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-0.22380254636726704,YCU 0,PR,2020,USD,L,BEPA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,120,IR6 -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-34.26645281902704,AM -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,82.02271122089925,BOP -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-3.7096824440639895,AM +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,42.9681136142967,BOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903121,CL 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-50,EA -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.31080371208803,EOP -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.09388697662967685,IA -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.09388697662967685,IFIE1 -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,34.26645281902704,IR3 -0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,31.53934166641386,IR5 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,7.793463810056409,EOP +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,0.07437430623754743,IA +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-0.07437430623754743,IFIE1 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,3.7096824440639895,IR3 +0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,31.539341666413847,IR5 0,,2020,USD,,C,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,105.89201388261736,MC -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,AM -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,6.500343986157867,AM +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,I,Default,,DT1,0,CH,,BBA,-5.156552131440618,BOP 0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-8.011834360099684,EOP -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,16.831613508459697,IR4 -0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-13.656208145282752,EOP +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,6.500343986157867,IR4 +0,,2020,USD,,DA,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-6.500343986157867,ISE6 0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,N,Default,,DT1,0,CH,,BBA,31.958738976731105,BOP 0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,-87.43135554903122,CL 0,,2020,USD,,L,CHF,DT1.3,P,False,LRC,ANN,C,Default,,DT1,0,CH,,BBA,0,EOP @@ -375,22 +375,22 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.3283233358608868,YCU 0,NIC,2020,USD,C,BE,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-0.22380254636726704,YCU 0,PR,2020,USD,L,BEPA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,96,IR6 -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-38.60249856533708,AM -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,82.02271122089925,BOP -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-5.773636697753954,AM +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,42.9681136142967,BOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-87.43135554903121,CL 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-43.599999999999994,EA -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,18.374757965778002,EOP -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.09388697662967685,IA -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.09388697662967685,IFIE1 -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,38.60249856533708,IR3 -0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,25.139341666413856,IR5 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,12.129509556366443,EOP +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,0.07437430623754743,IA +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-0.07437430623754743,IFIE1 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,5.773636697753954,IR3 +0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,25.13934166641384,IR5 0,,2020,USD,,C,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,105.89201388261736,MC -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,16.831613508459697,AM -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,6.500343986157867,AM +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,I,,,DT2,0,CH,,BBA,-5.156552131440618,BOP 0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-8.011834360099686,EOP -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,16.831613508459697,IR4 -0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-13.65620814528275,EOP +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,6.500343986157867,IR4 +0,,2020,USD,,DA,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-6.500343986157867,ISE6 0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,N,,,DT2,0,CH,,BBA,31.958738976731105,BOP 0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,-87.43135554903122,CL 0,,2020,USD,,L,CHF,DT2.1,P,False,LRC,ANN,C,,,DT2,0,CH,,BBA,0,EOP @@ -554,29 +554,30 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.3283233358608868,YCU 0,NIC,2020,USD,C,BE,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-0.22380254636726704,YCU 0,PR,2020,USD,L,BEPA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,96,IR6 -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-51.96181825867143,AM -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,129.49726655304642,BOP +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,67.83795828214957,BOP 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-139.94506864907146,CL -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-43.599999999999994,EA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-33.87170342894083,EA 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.11760647207910604,IA -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.11760647207910604,IFIE1 -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,51.96181825867143,IR3 -0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,77.65305476645409,IR5 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,0.08679991324534386,IA +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.08679991324534386,IFIE1 +0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,67.92475819539493,IR5 0,,2020,USD,,C,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,105.89201388261736,MC -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,24.84344786855938,AM -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,20.15655213144062,AM +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,-5.156552131440618,BOP 0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-15,CF 0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,24.84344786855938,IR4 -0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-24.84344786855938,ISE6 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,20.15655213144062,IR4 +0,,2020,USD,,DA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-20.15655213144062,ISE6 +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-9.728296571059161,AM 0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,31.958738976731105,BOP 0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-87.43135554903122,CL +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,9.728296571059161,EA 0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0,EOP 0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,55.45631603430072,EV 0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,N,Default,,DT3,0,CH,,BBA,0.016300537999407044,IA 0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-0.016300537999407044,IFIE1 -0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,0.016300537999399012,ISE11 +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,-9.71199603305977,ISE11 +0,,2020,USD,,L,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,9.728296571059161,ISE9 0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,I,Default,,DT3,0,CH,,BBA,1.5,BOP 0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,3,CF 0,PR,2020,USD,,OA,CHF,DT3.1,P,False,LRC,ANN,C,Default,,DT3,0,CH,,BBA,2.5,EOP @@ -684,24 +685,24 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.3283233358608868,YCU 0,NIC,2020,USD,C,BE,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-0.22380254636726704,YCU 0,PR,2020,USD,L,BEPA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,104,IR6 -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-96.83022811966929,AM -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,82.02271122089925,BOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-33.48998867550812,AM +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,42.9681136142967,BOP 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,8.004653973154419,BOP 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-51.599999999999994,EA -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,46.09110994353215,EOP +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,70.35723911069861,EOP 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,-1.4922636208166304,EV -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.09388697662967685,IA +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,0.07437430623754743,IA 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,N,Default,,DT4,0,CH,,BBA,0.0003356307173485902,IA -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.09422260734702544,IFIE1 -0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,96.83022811966929,IR3 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-0.07470993695489601,IFIE1 +0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,33.48998867550812,IR3 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-60.80440423495516,IR5 0,,2020,USD,,C,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,105.89201388261736,MC -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,16.831613508459697,AM -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-9.843447868559382,BOP +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,6.500343986157867,AM +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-5.156552131440618,BOP 0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-15,CF -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-8.011834360099684,EOP -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,16.831613508459697,IR4 -0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-16.831613508459697,ISE6 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-13.656208145282752,EOP +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,6.500343986157867,IR4 +0,,2020,USD,,DA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-6.500343986157867,ISE6 0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,3,CF 0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,1,EOP 0,PR,2020,USD,,OA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,3,IR1 @@ -730,8 +731,8 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,,2020,USD,L,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,-7.486276372201601,OCI1 0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,C,Default,,DT4,0,CH,,BBA,7.5142516904975025,OCI1 0,,2020,USD,C,RA,CHF,DT4.1,P,False,LRC,ANN,I,Default,,DT4,0,CH,,BBA,-0.02238025463672244,YCU -0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-45,CF 0,NIC,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,35,CF +0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-45,CF 0,PR,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-45,ISE1 0,NIC,2020,USD,,A,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,35,ISE2 0,PR,2020,USD,,AA,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,2,CF @@ -808,15 +809,15 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.1641616679304434,YCU 0,NIC,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,0.11190127318363352,YCU 0,CDR,2020,USD,C,BE,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-8.349412781047394E-05,YCU -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,38.316584766326955,AM -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-46.24958203305145,BOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,11.133355649364928,AM +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-24.22813469379126,BOP 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,43.26014863442721,CL 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.5933128558860402,CRU -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-18.238663229656325,EOP -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.04954912095471157,IA -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.6428619768407517,IFIE1 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-23.389442532110124,EOP +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-0.03854664570667637,IA +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,0.6318595015927165,IFIE1 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,9.662803986091077,ISE10 -0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-38.316584766326955,ISE7 +0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,-11.133355649364928,ISE7 0,,2020,USD,,C,CHF,DTR1.1,P,True,LRC,ANN,I,Default,PT1,DTR1,0,CH,,BBA,-52.92295262051829,MC 0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,N,Default,PT1,DTR1,0,CH,,BBA,-15.684995728561214,BOP 0,,2020,USD,,LR,CHF,DTR1.1,P,True,LRC,ANN,C,Default,PT1,DTR1,0,CH,,BBA,43.26014863442721,CL @@ -999,15 +1000,15 @@ AccidentYear,AmountType,AnnualCohort,ContractualCurrency,EconomicBasis,EstimateT 0,PR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.1641616679304434,YCU 0,NIC,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,0.11190127318363352,YCU 0,CDR,2020,USD,C,BE,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-8.349412781047394E-05,YCU -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,38.316584766326955,AM -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-46.24958203305145,BOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,11.133355649364928,AM +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-24.22813469379126,BOP 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,43.26014863442721,CL 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.5933128558860402,CRU -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-18.238663229656325,EOP -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.04954912095471157,IA -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.6428619768407517,IFIE1 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-23.389442532110124,EOP +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-0.03854664570667637,IA +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,0.6318595015927165,IFIE1 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,9.662803986091077,ISE10 -0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-38.316584766326955,ISE7 +0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,-11.133355649364928,ISE7 0,,2020,USD,,C,CHF,DTR2.1,P,True,LRC,ANN,I,,PT1,DTR2,0,CH,,BBA,-52.92295262051829,MC 0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,N,,PT1,DTR2,0,CH,,BBA,-15.684995728561214,BOP 0,,2020,USD,,LR,CHF,DTR2.1,P,True,LRC,ANN,C,,PT1,DTR2,0,CH,,BBA,43.26014863442721,CL diff --git a/full-ifrs17-template/Test/IfrsVariablesTest.ipynb b/full-ifrs17-template/Test/IfrsVariablesTest.ipynb index 1a40358a..98187848 100644 --- a/full-ifrs17-template/Test/IfrsVariablesTest.ipynb +++ b/full-ifrs17-template/Test/IfrsVariablesTest.ipynb @@ -211,9 +211,13 @@ { "cell_type": "code", "source": [ - "var errorList = new List();", - "\n", - "\nforeach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", + "var errorList = new List();" + ] + }, + { + "cell_type": "code", + "source": [ + "foreach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", "\n{", "\n var reportingNode = g.Key.ReportingNode;", "\n var year = g.Key.Year;", @@ -235,7 +239,7 @@ "\n var extension = System.IO.Path.GetExtension(bmfile.FileName);", "\n var stream = await Project.FileStorage.ReadAsync(bmfile.FileName);", "\n //Read Bm csv", - "\n var bmDataTable = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync());", + "\n var bmDataTable = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet;", "\n", "\n var mainTab = bmDataTable.Tables[Main].Rows.First();", "\n if(!ValidateMainTab(mainTab, reportingNode, year, month))", @@ -247,8 +251,10 @@ "\n //Get the computed Data", "\n var computedVariables = computedVariablesByEstimateType.TryGetValue(bmTableName, out var ret) ? ret : Enumerable.Empty();", "\n ", + "\n if(!computedVariables.Any()) ", + "\n errorList.Add(new BenchmarkTestResult(\"No variables are computed for EstimateType: \" + bmTableName, 0, 0));", "\n //CompareAgainstBm", - "\n if (bmVariables.Any() || computedVariables.Any()) //TODO we are adding duplicates here", + "\n if (bmVariables.Any() && computedVariables.Any()) //TODO we are adding duplicates here", "\n errorList = errorList.Concat(CompareAgainstBm(errorList, bmVariables, computedVariables)).ToList();", "\n }", "\n}", diff --git a/full-ifrs17-template/Test/QueriesTest.ipynb b/full-ifrs17-template/Test/QueriesTest.ipynb index ab6ca4d9..8fdabb4a 100644 --- a/full-ifrs17-template/Test/QueriesTest.ipynb +++ b/full-ifrs17-template/Test/QueriesTest.ipynb @@ -20,7 +20,7 @@ { "cell_type": "code", "source": [ - "#!import \"../CalculationEngine\"" + "#!import \"//ifrs17ce/dev/CalculationEngine\"" ] }, { @@ -168,12 +168,13 @@ "source": [ "public async Task CheckLoadDataNodeStateAsync(Args args, IEnumerable testData, bool isExpectedToBeActive)", "\n{", + "\n await Workspace.Partition.SetAsync(args);", "\n await Workspace.UpdateAsync(testData);", "\n var isActive = (await Workspace.LoadDataNodeStateAsync(args)).Keys.Contains(gic);", "\n ", "\n isActive.Should().Be(isExpectedToBeActive);", "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n Workspace.Reset(x => x.ResetCurrentPartitions());", "\n}" ] }, @@ -210,6 +211,7 @@ "\n double expectedCurrentFirstYcValue,", "\n double expectedLockedFirstYcValue)", "\n{", + "\n await Workspace.Partition.SetAsync(args);", "\n await Workspace.UpdateAsync(testData);", "\n await Workspace.UpdateAsync(new ReportingNode[]{new ReportingNode{Currency=\"EUR\",SystemName=\"CH\"}});", "\n ", @@ -217,8 +219,7 @@ "\n var eurLockedYieldCurve = (await LoadLockedInYieldCurveAsync(Workspace, args, dataNodes));", "\n var eurCurrentYieldCurve = (await LoadCurrentYieldCurveAsync(Workspace, args, dataNodes));", "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n Workspace.Reset(x => x.ResetCurrentPartitions());", "\n ", "\n var errors = new List();", "\n var currentPrevPeriod = eurCurrentYieldCurve[\"EUR\"][PreviousPeriod].Values.First();", @@ -271,6 +272,7 @@ "\n int? currentYear = null)", "\n{", "\n currentYear = currentYear ?? previousYear;", + "\n await Workspace.Partition.SetAsync(args);", "\n await Workspace.UpdateAsync(testData);", "\n ", "\n var interDataNodeParameters = await LoadInterDataNodeParametersAsync(Workspace, args);", @@ -345,7 +347,7 @@ "\n }", "\n }", "\n ", - "\n await Workspace.DeleteAsync(Workspace.Query().ToArray());", + "\n Workspace.Reset(x => x.ResetCurrentPartitions());", "\n ", "\n if(errors.Any()) ApplicationMessage.Log(Error.Generic, string.Join(\"\\n\", errors));", "\n}" diff --git a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb index 7831cbde..4be8de77 100644 --- a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb @@ -1824,7 +1824,7 @@ "\nwhile the AMF related to the current period is", "\n", "\n$$", - "\n\\text{AMF} = \\prod _{t = \\text{S}}^{\\text{S}+\\text{TS}} \\text{AMF}^{\\text{Monthly}}_t ~.", + "\n\\text{AMF} = 1 - \\prod _{t = \\text{S}}^{\\text{S}+\\text{TS}-1} \\text{AMF}^{\\text{Monthly}}_t ~.", "\n$$", "\n", "\nwhere the shift S and Time Step TS for the [current period](#year-and-period) are" @@ -1949,7 +1949,7 @@ { "cell_type": "code", "source": [ - "var expectedCurrentPeriodAmortizationFactor = expectedMonthlyAmortizationFactor.Skip(shift).Take(timeStep).Aggregate(1d, (x, y) => x * y);" + "var expectedCurrentPeriodAmortizationFactor = 1d - expectedMonthlyAmortizationFactor.Skip(shift).Take(timeStep).Aggregate(1d, (x, y) => x * y);" ] }, { diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index 98114494..f5fcf571 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -43,16 +43,16 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Workspace,1.2.0\"", - "\n#r \"nuget:Systemorph.Scopes,1.2.4\"", - "\n#r \"nuget:Systemorph.Import,1.3.0\"", - "\n#r \"nuget:Systemorph.Test,1.2.4\"", - "\n#r \"nuget:Systemorph.Export,1.3.0\"", - "\n#r \"nuget:Systemorph.DataSetReader,1.3.0\"", - "\n#r \"nuget:Systemorph.DataSource,1.2.0\"", - "\n#r \"nuget:Systemorph.DataSource.Conversions,1.2.0\"", - "\n#r \"nuget:Systemorph.Reporting,1.2.4\"", - "\n#r \"nuget:Systemorph.DomainDesigner,1.3.0\"" + "#r \"nuget:Systemorph.Workspace,1.4.1\"", + "\n#r \"nuget:Systemorph.Scopes,1.4.0\"", + "\n#r \"nuget:Systemorph.Import,1.4.0\"", + "\n#r \"nuget:Systemorph.Test,1.4.0\"", + "\n#r \"nuget:Systemorph.Export,1.4.0\"", + "\n#r \"nuget:Systemorph.DataSetReader,1.4.0\"", + "\n#r \"nuget:Systemorph.DataSource,1.4.1\"", + "\n#r \"nuget:Systemorph.DataSource.Conversions,1.4.1\"", + "\n#r \"nuget:Systemorph.Reporting,1.4.0\"", + "\n#r \"nuget:Systemorph.DomainDesigner,1.4.0\"" ] }, { diff --git a/ifrs17/Import/ImportScopeCalculation.ipynb b/ifrs17/Import/ImportScopeCalculation.ipynb index 803483c1..ee63b100 100644 --- a/ifrs17/Import/ImportScopeCalculation.ipynb +++ b/ifrs17/Import/ImportScopeCalculation.ipynb @@ -1055,10 +1055,12 @@ "For a certain projection period - defined by the Shift, $S$, and the Time-Step, $TS$, parameters - the Amortization Factor is then given by the product of the corresponding monthly amortization factors:", "\n", "\n$$", - "\nAF = \\prod _{i = S}^{TS} \\text{Monthly }AF_i ~.", + "\nAF = 1 - \\prod _{i = S}^{S + TS - 1} \\text{Monthly }AF_i ~.", "\n$$", "\n", - "\nEach GIC will have his own AF." + "\nEach GIC will have his own AF.", + "\n", + "\nIn order to run off the business of a given Group of Contract one should provide a cashflow of 0s for the AocStep with AocType CL and Novelty C. When computing the AF this results in the product of the monthly amortization factors of the period to be 1. In this case, the computed AF does not follow the formula above but is 1 allowing for the full release of the Technical Margin in the AM AocStep." ] }, { @@ -1073,15 +1075,17 @@ "\n ", "\n private int shift => GetStorage().GetShift(0);//Identity.ProjectionPeriod", "\n private int timeStep => GetStorage().GetTimeStep(0);//Identity.ProjectionPeriod", - "\n ", - "\n [NotVisible] string EconomicBasis => GetContext();", - "\n ", - "\n string EstimateType => EstimateTypes.F;", - "\n double Value => GetScope(Identity)", + "\n private double amortizedFactor => GetScope(Identity)", "\n .MonthlyAmortizationFactors", "\n .Skip(shift)", "\n .Take(timeStep)", "\n .Aggregate(1d, (x, y) => x * y);", + "\n [NotVisible] string EconomicBasis => GetContext();", + "\n ", + "\n string EstimateType => EstimateTypes.F;", + "\n double Value => Math.Abs(amortizedFactor - 1d) > Precision", + "\n ? 1d - amortizedFactor", + "\n : 1d;", "\n}", "\n", "\npublic interface AmfFromIfrsVariable : CurrentPeriodAmortizationFactor", diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 34ab4202..4b2d2a5a 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -273,7 +273,7 @@ "\n", "\n var extension = System.IO.Path.GetExtension(file);", "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[tab];", + "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet.Tables[tab];", "\n ", "\n", "\n var dataNodesImported = target.Rows.Select(x => x.Field(nameof(RawVariable.DataNode))).ToHashSet();", @@ -332,7 +332,7 @@ "\n{", "\n var extension = System.IO.Path.GetExtension(file);", "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).Tables[Main];", + "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet.Tables[Main];", "\n ", "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", diff --git a/ifrs17/Utils/ApplicationMessage.ipynb b/ifrs17/Utils/ApplicationMessage.ipynb index 2bc8ec97..d5b26c8b 100644 --- a/ifrs17/Utils/ApplicationMessage.ipynb +++ b/ifrs17/Utils/ApplicationMessage.ipynb @@ -27,7 +27,7 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Activities,1.2.3\"" + "#r \"nuget:Systemorph.Activities,1.4.0\"" ] }, { From 49a3b6f5498f8b55c020eae81a729cc7e70059c4 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Fri, 14 Oct 2022 17:14:16 +0200 Subject: [PATCH 21/38] approaching --- .../Test/AocConfigurationTest.ipynb | 155 +++++++++++++++++- ifrs17/Constants/Consts.ipynb | 2 + ifrs17/Import/Importers.ipynb | 16 +- 3 files changed, 164 insertions(+), 9 deletions(-) diff --git a/full-ifrs17-template/Test/AocConfigurationTest.ipynb b/full-ifrs17-template/Test/AocConfigurationTest.ipynb index 23448027..e790f4de 100644 --- a/full-ifrs17-template/Test/AocConfigurationTest.ipynb +++ b/full-ifrs17-template/Test/AocConfigurationTest.ipynb @@ -39,6 +39,66 @@ "Workspace.InitializeFrom(DataSource);" ] }, + { + "cell_type": "markdown", + "source": [ + "# Canonical Aoc Types" + ] + }, + { + "cell_type": "code", + "source": [ + "string canonicalAocTypes = ", + "\n@\"@@AocType,,,,,,,,,,,", + "\nSystemName,DisplayName,Parent,Order,,,,,,,,", + "\nBOP,Opening Balance,,10,,,,,,,,", + "\nMC,Model Correction,,20,,,,,,,,", + "\nPC,Portfolio Changes,,30,,,,,,,,", + "\nRCU,Reinsurance Coverage Update,PC,40,,,,,,,,", + "\nCF,Cash flow,,50,,,,,,,,", + "\nIA,Interest Accretion,,60,,,,,,,,", + "\nAU,Assumption Update,,70,,,,,,,,", + "\nFAU,Financial Assumption Update,,80,,,,,,,,", + "\nYCU,Yield Curve Update,FAU,90,,,,,,,,", + "\nCRU,Credit Risk Update,FAU,100,,,,,,,,", + "\nEV,Experience Variance,,110,,,,,,,,", + "\nWO,Write-Off,,120,,,,,,,,", + "\nCL,Combined Liabilities,,130,,,,,,,,", + "\nEA,Experience Adjustment,,140,,,,,,,,", + "\nAM,Amortization,,150,,,,,,,,", + "\nFX,FX Impact,,160,,,,,,,,", + "\nEOP,Closing Balance,,170,,,,,,,,\";" + ] + }, + { + "cell_type": "code", + "source": [ + "string canonicalAocConfig = ", + "\n@\"@@AocConfiguration,,,,,,,,,,,", + "\nAocType,Novelty,DataType,InputSource,FxPeriod,YcPeriod,CdrPeriod,ValuationPeriod,RcPeriod,Order,Year,Month", + "\nBOP,I,Optional,7,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,10,1900,1", + "\nMC,I,Optional,4,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,20,1900,1", + "\nRCU,I,Calculated,4,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,BeginningOfPeriod,EndOfPeriod,30,1900,1", + "\nCF,I,Calculated,4,Average,NotApplicable,BeginningOfPeriod,Delta,EndOfPeriod,40,1900,1", + "\nIA,I,Calculated,5,Average,BeginningOfPeriod,BeginningOfPeriod,Delta,EndOfPeriod,50,1900,1", + "\nAU,I,Optional,4,EndOfPeriod,BeginningOfPeriod,BeginningOfPeriod,EndOfPeriod,EndOfPeriod,60,1900,1", + "\nYCU,I,CalculatedTelescopic,4,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,EndOfPeriod,70,1900,1", + "\nCRU,I,CalculatedTelescopic,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,80,1900,1", + "\nEV,I,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,90,1900,1", + "\nBOP,N,Optional,4,Average,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,100,1900,1", + "\nCF,N,Calculated,4,Average,NotApplicable,EndOfPeriod,Delta,EndOfPeriod,110,1900,1", + "\nIA,N,Calculated,4,Average,EndOfPeriod,EndOfPeriod,Delta,EndOfPeriod,120,1900,1", + "\nAU,N,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,130,1900,1", + "\nEV,N,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,140,1900,1", + "\nCF,C,Optional,2,Average,NotApplicable,NotApplicable,NotApplicable,NotApplicable,160,1900,1", + "\nWO,C,Optional,2,Average,NotApplicable,NotApplicable,NotApplicable,NotApplicable,170,1900,1", + "\nCL,C,Mandatory,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,180,1900,1", + "\nEA,C,Calculated,4,EndOfPeriod,NotApplicable,NotApplicable,NotApplicable,EndOfPeriod,190,1900,1", + "\nAM,C,Calculated,6,EndOfPeriod,NotApplicable,NotApplicable,NotApplicable,EndOfPeriod,200,1900,1", + "\nFX,C,Calculated,0,NotApplicable,NotApplicable,NotApplicable,NotApplicable,NotApplicable,210,1900,1", + "\nEOP,C,Calculated,6,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,220,1900,1\";" + ] + }, { "cell_type": "markdown", "source": [ @@ -48,10 +108,97 @@ { "cell_type": "code", "source": [ - "var args = new ImportArgs(\"CH\", 2021, 3, Periodicity.Quarterly, null, ImportFormats.Cashflow);", - "\nvar partition = Workspace.Query().FirstOrDefault(x => x.ReportingNode == args.ReportingNode && x.Year == args.Year && ", - "\n x.Month == args.Month && x.Scenario == args.Scenario);", - "\nif(partition == null) ApplicationMessage.Log(Error.PartitionNotFound);" + "public async Task CheckAocConfigurationDefault(AocType[] newAocTypes)", + "\n{", + "\n await DataSource.DeleteAsync( await DataSource.Query().ToArrayAsync() );", + "\n await DataSource.DeleteAsync( await DataSource.Query().ToArrayAsync() );", + "\n await DataSource.CommitAsync();", + "\n", + "\n var aocTypeLog = await Import.FromString(canonicalAocTypes).WithType().WithTarget(DataSource).ExecuteAsync();", + "\n aocTypeLog.Errors.Any().Should().Be(false);", + "\n", + "\n await DataSource.UpdateAsync(newAocTypes);", + "\n await DataSource.CommitAsync();", + "\n", + "\n var aocConfigLog = await Import.FromString(canonicalAocConfig).WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync();", + "\n aocConfigLog.Errors.Any().Should().Be(false);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## NewAoc < RCU" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 25} } );", + "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.MC && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 21, DataType = DataType.Optional};", + "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## RCU < NewAoc < CF" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 45} } );", + "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.RCU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 31, DataType = DataType.Optional};", + "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## IA < NewAoc < YCU" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 82} } );", + "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.AU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 62, DataType = DataType.Optional};", + "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## NewAoc > CRU" + ] + }, + { + "cell_type": "code", + "source": [ + "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 106} } );", + "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 91};", + "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "code", + "source": [ + "DataSource.Query().Where(x => x.AocType == \"A1\")" + ] + }, + { + "cell_type": "code", + "source": [ + "" ] } ] diff --git a/ifrs17/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb index be666faf..423a41b4 100644 --- a/ifrs17/Constants/Consts.ipynb +++ b/ifrs17/Constants/Consts.ipynb @@ -198,10 +198,12 @@ "public static class AocTypes{", "\n public const string BOP = nameof(BOP);", "\n public const string MC = nameof(MC);", + "\n public const string PC = nameof(PC);", "\n public const string RCU = nameof(RCU);", "\n public const string CF = nameof(CF);", "\n public const string IA = nameof(IA);", "\n public const string AU = nameof(AU);", + "\n public const string FAU = nameof(FAU);", "\n public const string YCU = nameof(YCU);", "\n public const string CRU = nameof(CRU);", "\n public const string WO = nameof(WO);", diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 482ed926..6ed5728a 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -332,20 +332,26 @@ "\n var workspace = Workspace.CreateNew();", "\n workspace.InitializeFrom(DataSource);", "\n", + "\n var aocTypes = await options.TargetDataSource.Query().OrderBy(x => x.Order).ToArrayAsync();", + "\n var aocTypesMandatory = typeof(AocTypes).GetFields().Select(x => (string)x.Name);", + "\n if(aocTypesMandatory.Where(x => !aocTypes.Select(x => x.SystemName).Contains(x)).Any()) {", + "\n ApplicationMessage.Log(Error.Generic, $\"Not all mandatory AocTypes have been imported.\"); // TODO: create new Error in Validations", + "\n return Activity.Finish().RepeatOnce();", + "\n }", + "\n ", "\n var logConfig = await Import.FromDataSet(dataSet).WithType().WithTarget(workspace).ExecuteAsync();", "\n if(logConfig.Errors.Any()) return logConfig.RepeatOnce(); ", "\n", - "\n var aocTypes = await options.TargetDataSource.Query().OrderBy(x => x.Order).ToArrayAsync();", "\n var orderByName = aocTypes.ToDictionary(x => x.SystemName, x => x.Order);", - "\n var distanceByNames = aocTypes.SelectMany(x => aocTypes.Select(y => (x.SystemName, y.SystemName, Array.IndexOf(aocTypes, x) - Array.IndexOf(aocTypes, y))))", + "\n var distanceByNames = aocTypes.SelectMany(x => aocTypes.Select(y => (x.SystemName, y.SystemName, Math.Abs(Array.IndexOf(aocTypes, x) - Array.IndexOf(aocTypes, y)))))", "\n .ToDictionary(x => (x.Item1, x.Item2), x => x.Item3);", - "\n", "\n var aocConfigs = (await workspace.Query().ToArrayAsync())", "\n .GroupBy(x => (x.AocType, x.Novelty))", "\n .Select(y => y.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault())", "\n .ToDictionary(x => (x.AocType, x.Novelty));", + "\n var newAocTypes = orderByName.Keys.Where(x => !aocConfigs.Keys.Contains((x, Novelties.I)) && !aocTypesMandatory.Contains(x)).ToArray();", "\n", - "\n foreach(var newAocType in orderByName.Keys.Where(x => !aocConfigs.Keys.Contains((x,Novelties.I))).ToArray()) {", + "\n foreach(var newAocType in newAocTypes) {", "\n if(orderByName[newAocType] < orderByName[AocTypes.RCU])", "\n {", "\n var config = aocConfigs[(AocTypes.MC, Novelties.I)];", @@ -367,7 +373,7 @@ "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType,AocTypes.EV)] } );", "\n }", "\n else", - "\n ApplicationMessage.Log(Error.Generic, $\"The AocType {newAocType} has been added in a wrong position.\");", + "\n ApplicationMessage.Log(Error.Generic, $\"The AocType {newAocType} has been added in a wrong position.\"); // TODO: create new Error in Validations", "\n };", "\n", "\n await workspace.CommitToTargetAsync(options.TargetDataSource);", From 59e5ca0f9660650fc9d09b6786c44324a9856738 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Sun, 16 Oct 2022 17:58:08 +0200 Subject: [PATCH 22/38] better --- .../Test/AocConfigurationTest.ipynb | 70 ++++++++++++++----- ifrs17/Import/Importers.ipynb | 25 ++++--- 2 files changed, 66 insertions(+), 29 deletions(-) diff --git a/full-ifrs17-template/Test/AocConfigurationTest.ipynb b/full-ifrs17-template/Test/AocConfigurationTest.ipynb index e790f4de..e2fcbdc7 100644 --- a/full-ifrs17-template/Test/AocConfigurationTest.ipynb +++ b/full-ifrs17-template/Test/AocConfigurationTest.ipynb @@ -42,7 +42,7 @@ { "cell_type": "markdown", "source": [ - "# Canonical Aoc Types" + "# Canonical Aoc Types and Configurations" ] }, { @@ -85,7 +85,7 @@ "\nYCU,I,CalculatedTelescopic,4,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,EndOfPeriod,70,1900,1", "\nCRU,I,CalculatedTelescopic,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,80,1900,1", "\nEV,I,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,90,1900,1", - "\nBOP,N,Optional,4,Average,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,100,1900,1", + "\nBOP,N,Optional,4,Average,EndOfPeriod,EndOfPeriod,BeginningOfPeriod,EndOfPeriod,95,1900,1", "\nCF,N,Calculated,4,Average,NotApplicable,EndOfPeriod,Delta,EndOfPeriod,110,1900,1", "\nIA,N,Calculated,4,Average,EndOfPeriod,EndOfPeriod,Delta,EndOfPeriod,120,1900,1", "\nAU,N,Optional,4,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,EndOfPeriod,130,1900,1", @@ -108,7 +108,7 @@ { "cell_type": "code", "source": [ - "public async Task CheckAocConfigurationDefault(AocType[] newAocTypes)", + "public async Task CheckAocConfigurationDefault(AocType[] newAocTypes)", "\n{", "\n await DataSource.DeleteAsync( await DataSource.Query().ToArrayAsync() );", "\n await DataSource.DeleteAsync( await DataSource.Query().ToArrayAsync() );", @@ -120,8 +120,7 @@ "\n await DataSource.UpdateAsync(newAocTypes);", "\n await DataSource.CommitAsync();", "\n", - "\n var aocConfigLog = await Import.FromString(canonicalAocConfig).WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync();", - "\n aocConfigLog.Errors.Any().Should().Be(false);", + "\n return await Import.FromString(canonicalAocConfig).WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync();", "\n}" ] }, @@ -134,9 +133,15 @@ { "cell_type": "code", "source": [ - "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 25} } );", - "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", - "\n x.AocType == AocTypes.MC && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 21, DataType = DataType.Optional};", + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 25} } );", + "\naocConfigLog.Errors.Any().Should().Be(false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.MC && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 21, DataType = DataType.Optional};", "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] @@ -150,9 +155,15 @@ { "cell_type": "code", "source": [ - "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 45} } );", - "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", - "\n x.AocType == AocTypes.RCU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 31, DataType = DataType.Optional};", + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 45} } );", + "\naocConfigLog.Errors.Any().Should().Be(false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.RCU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 31, DataType = DataType.Optional};", "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] @@ -166,9 +177,15 @@ { "cell_type": "code", "source": [ - "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 82} } );", - "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", - "\n x.AocType == AocTypes.AU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 62, DataType = DataType.Optional};", + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 82} } );", + "\naocConfigLog.Errors.Any().Should().Be(false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.AU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 61, DataType = DataType.Optional};", "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] @@ -182,17 +199,34 @@ { "cell_type": "code", "source": [ - "await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 106} } );", - "\nvar newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", - "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 91};", + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 106} } );", + "\naocConfigLog.Errors.Any().Should().Be(false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 91};", "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] }, + { + "cell_type": "markdown", + "source": [ + "## Two or more Aoc Config with same Order" + ] + }, { "cell_type": "code", "source": [ - "DataSource.Query().Where(x => x.AocType == \"A1\")" + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 101},", + "\n new AocType{SystemName = \"A2\", DisplayName = \"a1\", Order = 102},", + "\n new AocType{SystemName = \"A3\", DisplayName = \"a1\", Order = 103},", + "\n new AocType{SystemName = \"A4\", DisplayName = \"a1\", Order = 104},", + "\n new AocType{SystemName = \"A5\", DisplayName = \"a1\", Order = 105} } );", + "\n(aocConfigLog.Errors.First().ToString() == \"ActivityMessageNotification { Message = Two or more Aoc Configurations have the same Order. }\").Should().Be(true);" ] }, { diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 17f63d2f..f103e57d 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -343,39 +343,42 @@ "\n if(logConfig.Errors.Any()) return logConfig.RepeatOnce(); ", "\n", "\n var orderByName = aocTypes.ToDictionary(x => x.SystemName, x => x.Order);", - "\n var distanceByNames = aocTypes.SelectMany(x => aocTypes.Select(y => (x.SystemName, y.SystemName, Math.Abs(Array.IndexOf(aocTypes, x) - Array.IndexOf(aocTypes, y)))))", - "\n .ToDictionary(x => (x.Item1, x.Item2), x => x.Item3);", "\n var aocConfigs = (await workspace.Query().ToArrayAsync())", "\n .GroupBy(x => (x.AocType, x.Novelty))", "\n .Select(y => y.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault())", "\n .ToDictionary(x => (x.AocType, x.Novelty));", + "\n var aocOrder = aocConfigs.ToDictionary(x => x.Key, x => x.Value.Order);", "\n var newAocTypes = orderByName.Keys.Where(x => !aocConfigs.Keys.Contains((x, Novelties.I)) && !aocTypesMandatory.Contains(x)).ToArray();", "\n", "\n foreach(var newAocType in newAocTypes) {", "\n if(orderByName[newAocType] < orderByName[AocTypes.RCU])", "\n {", - "\n var config = aocConfigs[(AocTypes.MC, Novelties.I)];", - "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType, AocTypes.MC)] }); ", + "\n var step = (AocTypes.MC, Novelties.I);", + "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] }); ", "\n }", "\n else if(orderByName[newAocType] < orderByName[AocTypes.CF] && orderByName[newAocType] > orderByName[AocTypes.RCU]) ", "\n {", - "\n var config = aocConfigs[(AocTypes.RCU, Novelties.I)];", - "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType, AocTypes.RCU)] });", + "\n var step = (AocTypes.RCU, Novelties.I);", + "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] });", "\n }", "\n else if(orderByName[newAocType] < orderByName[AocTypes.YCU] && orderByName[newAocType] > orderByName[AocTypes.IA]) ", "\n {", - "\n var config = aocConfigs[(AocTypes.AU, Novelties.I)];", - "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType,AocTypes.AU)] } );", + "\n var step = (AocTypes.AU, Novelties.I);", + "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] } );", "\n }", "\n else if(orderByName[newAocType] > orderByName[AocTypes.CRU])", "\n {", - "\n var config = aocConfigs[(AocTypes.EV, Novelties.I)];", - "\n await workspace.UpdateAsync( config with { AocType = newAocType, DataType = DataType.Optional, Order = config.Order + distanceByNames[(newAocType,AocTypes.EV)] } );", + "\n var step = (AocTypes.EV, Novelties.I);", + "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] } );", "\n }", "\n else", "\n ApplicationMessage.Log(Error.Generic, $\"The AocType {newAocType} has been added in a wrong position.\"); // TODO: create new Error in Validations", "\n };", "\n", + "\n var aocConfigsFinal = await workspace.Query().ToArrayAsync();", + "\n if(aocConfigsFinal.GroupBy(x => x.Order).Any(x => x.Count() > 1))", + "\n ApplicationMessage.Log(Error.Generic, $\"Two or more Aoc Configurations have the same Order.\"); // TODO: create new Error in Validations", + "\n", "\n await workspace.CommitToTargetAsync(options.TargetDataSource);", "\n return new[] {Activity.Finish(),logConfig}; ", "\n});" @@ -1123,4 +1126,4 @@ ] } ] -} +} \ No newline at end of file From efd06dc5afb922abf7e2f912699f978ca1dad7f7 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Mon, 17 Oct 2022 23:19:02 +0200 Subject: [PATCH 23/38] implement feedback --- .../Test/AocConfigurationTest.ipynb | 135 +++++++++++++++--- full-ifrs17-template/Test/QueriesTest.ipynb | 2 +- ifrs17/Constants/Validations.ipynb | 6 +- ifrs17/Import/Importers.ipynb | 63 ++++++-- ifrs17/Test/Tests.ipynb | 37 +++++ 5 files changed, 205 insertions(+), 38 deletions(-) create mode 100644 ifrs17/Test/Tests.ipynb diff --git a/full-ifrs17-template/Test/AocConfigurationTest.ipynb b/full-ifrs17-template/Test/AocConfigurationTest.ipynb index e2fcbdc7..501b0574 100644 --- a/full-ifrs17-template/Test/AocConfigurationTest.ipynb +++ b/full-ifrs17-template/Test/AocConfigurationTest.ipynb @@ -24,7 +24,7 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + "#!import \"../CalculationEngine\"" ] }, { @@ -36,7 +36,25 @@ { "cell_type": "code", "source": [ - "Workspace.InitializeFrom(DataSource);" + "string novelties = ", + "\n@\"@@Novelty", + "\nSystemName,DisplayName,Parent,Order", + "\nI,In Force,,1", + "\nN,New Business,,10", + "\nC,Combined,,20\";" + ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromString(novelties).WithType().WithTarget(DataSource).ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "var workspace = Workspace.CreateNew();", + "\nworkspace.InitializeFrom(DataSource);" ] }, { @@ -110,17 +128,17 @@ "source": [ "public async Task CheckAocConfigurationDefault(AocType[] newAocTypes)", "\n{", - "\n await DataSource.DeleteAsync( await DataSource.Query().ToArrayAsync() );", - "\n await DataSource.DeleteAsync( await DataSource.Query().ToArrayAsync() );", - "\n await DataSource.CommitAsync();", + "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", + "\n await workspace.DeleteAsync( await workspace.Query().ToArrayAsync() );", + "\n await workspace.CommitAsync();", "\n", - "\n var aocTypeLog = await Import.FromString(canonicalAocTypes).WithType().WithTarget(DataSource).ExecuteAsync();", + "\n var aocTypeLog = await Import.FromString(canonicalAocTypes).WithType().WithTarget(workspace).ExecuteAsync();", "\n aocTypeLog.Errors.Any().Should().Be(false);", "\n", - "\n await DataSource.UpdateAsync(newAocTypes);", - "\n await DataSource.CommitAsync();", + "\n await workspace.UpdateAsync(newAocTypes);", + "\n await workspace.CommitAsync();", "\n", - "\n return await Import.FromString(canonicalAocConfig).WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync();", + "\n return await Import.FromString(canonicalAocConfig).WithFormat(\"AocConfiguration\").WithTarget(workspace).ExecuteAsync();", "\n}" ] }, @@ -140,9 +158,9 @@ { "cell_type": "code", "source": [ - "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", "\n x.AocType == AocTypes.MC && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 21, DataType = DataType.Optional};", - "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] }, @@ -162,9 +180,9 @@ { "cell_type": "code", "source": [ - "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", "\n x.AocType == AocTypes.RCU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 31, DataType = DataType.Optional};", - "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] }, @@ -184,16 +202,25 @@ { "cell_type": "code", "source": [ - "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", "\n x.AocType == AocTypes.AU && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 61, DataType = DataType.Optional};", - "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.AU && x.Novelty == Novelties.N) with {AocType = \"A1\", Order = 131, DataType = DataType.Optional};", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] }, { "cell_type": "markdown", "source": [ - "## NewAoc > CRU" + "## CRU < NewAoc < EV" ] }, { @@ -206,9 +233,71 @@ { "cell_type": "code", "source": [ - "var newConfigExpected = (await DataSource.Query().ToArrayAsync()).First(x => ", + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 81};", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.N) with {AocType = \"A1\", Order = 131};", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## EV < NewAoc < WO" + ] + }, + { + "cell_type": "code", + "source": [ + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 116} } );", + "\naocConfigLog.Errors.Any().Should().Be(false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.I) with {AocType = \"A1\", Order = 91};", - "\nvar newConfigCalculated = await DataSource.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.EV && x.Novelty == Novelties.N) with {AocType = \"A1\", Order = 141};", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", + "\nnewConfigCalculated.Count().Should().Be(1);" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## WO < NewAoc < CL" + ] + }, + { + "cell_type": "code", + "source": [ + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 125} } );", + "\naocConfigLog.Errors.Any().Should().Be(false);" + ] + }, + { + "cell_type": "code", + "source": [ + "var newConfigExpected = (await workspace.Query().ToArrayAsync()).First(x => ", + "\n x.AocType == AocTypes.WO && x.Novelty == Novelties.C) with {AocType = \"A1\", Order = 171};", + "\nvar newConfigCalculated = await workspace.Query().Where(x => x == newConfigExpected).ToArrayAsync();", "\nnewConfigCalculated.Count().Should().Be(1);" ] }, @@ -221,11 +310,11 @@ { "cell_type": "code", "source": [ - "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 101},", - "\n new AocType{SystemName = \"A2\", DisplayName = \"a1\", Order = 102},", - "\n new AocType{SystemName = \"A3\", DisplayName = \"a1\", Order = 103},", - "\n new AocType{SystemName = \"A4\", DisplayName = \"a1\", Order = 104},", - "\n new AocType{SystemName = \"A5\", DisplayName = \"a1\", Order = 105} } );", + "var aocConfigLog = await CheckAocConfigurationDefault( new[]{ new AocType{SystemName = \"A1\", DisplayName = \"a1\", Order = 111},", + "\n new AocType{SystemName = \"A2\", DisplayName = \"a1\", Order = 112},", + "\n new AocType{SystemName = \"A3\", DisplayName = \"a1\", Order = 113},", + "\n new AocType{SystemName = \"A4\", DisplayName = \"a1\", Order = 114},", + "\n new AocType{SystemName = \"A5\", DisplayName = \"a1\", Order = 115} } );", "\n(aocConfigLog.Errors.First().ToString() == \"ActivityMessageNotification { Message = Two or more Aoc Configurations have the same Order. }\").Should().Be(true);" ] }, diff --git a/full-ifrs17-template/Test/QueriesTest.ipynb b/full-ifrs17-template/Test/QueriesTest.ipynb index 8fdabb4a..07990aa7 100644 --- a/full-ifrs17-template/Test/QueriesTest.ipynb +++ b/full-ifrs17-template/Test/QueriesTest.ipynb @@ -20,7 +20,7 @@ { "cell_type": "code", "source": [ - "#!import \"//ifrs17ce/dev/CalculationEngine\"" + "#!import \"../CalculationEngine\"" ] }, { diff --git a/ifrs17/Constants/Validations.ipynb b/ifrs17/Constants/Validations.ipynb index 56dec561..afd2e82e 100644 --- a/ifrs17/Constants/Validations.ipynb +++ b/ifrs17/Constants/Validations.ipynb @@ -53,7 +53,8 @@ "source": [ "public enum Error { ", "\n // Import", - "\n NoMainTab, IncompleteMainTab, ParsingScientificNotation, ValueTypeNotFound, ValueTypeNotValid, AocTypeNotValid,", + "\n NoMainTab, IncompleteMainTab, ParsingScientificNotation, ValueTypeNotFound, ValueTypeNotValid, ", + "\n AocTypeNotValid, AocTypeCompulsoryNotFound, AocTypePositionNotSupported, AocConfigurationOrderNotUnique,", "\n // Partition", "\n PartitionNotFound, ParsedPartitionNotFound, PartititionNameNotFound, PartitionTypeNotFound,", "\n // Dimensions", @@ -95,6 +96,9 @@ "\n (Error.ValueTypeNotFound , _) => $\"Value Type not found.\",", "\n (Error.ValueTypeNotValid , 1) => $\"The Value Type {s[0]} is invalid.\",", "\n (Error.AocTypeNotValid , 1) => $\"The parsed AocType {s[0]} is invalid.\",", + "\n (Error.AocTypeCompulsoryNotFound , _) => $\"Not all compulsory AocTypes have been imported.\",", + "\n (Error.AocTypePositionNotSupported , 1) => $\"The position of the AocType {s[0]} is not supported.\",", + "\n (Error.AocConfigurationOrderNotUnique , _) => $\"Two or more Aoc Configurations have the same Order.\",", "\n // Partition", "\n (Error.PartitionNotFound , _) => $\"Partition do not found.\",", "\n (Error.ParsedPartitionNotFound , 1) => $\"Parsed partition not available: ReportingNode {s[0]}.\",", diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index f103e57d..f2963181 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -324,18 +324,38 @@ "### Analysis of Change Configuration" ] }, + { + "cell_type": "markdown", + "source": [ + "The Analysis of Change configuration is parsed from the input file and complemented with defaults to allow for an easy insertion of new AOC steps. ", + "\n", + "\nAfter having checked that the AocTypes loaded in the target DataSource are including all the compulsory ones, default configurations are generated on the basis of the AocTypes ordering. ", + "\n", + "\nThe following categories have been identified based on the *Order* of the novel AOC step:", + "\n", + "\n| Category | Default added with same configuration of |", + "\n| --------------------- | ----------------------------------------------------- |", + "\n| Order < RCU | MC with Novelty I |", + "\n| RCU < Order < CF | RCU with Novelty I |", + "\n| IA < Order < YCU | AU with both Novelty I and N |", + "\n| CRU < Order < WO | EV with Novelty I and N |", + "\n| WO < Order < CL | WO with Novelty C (only for Import Source = Actual) |", + "\n", + "\nThe new Aoc Configurations are created with the same order of the Aoc Types. " + ] + }, { "cell_type": "code", "source": [ "Import.DefineFormat(\"AocConfiguration\", async (options, dataSet) => {", "\n Activity.Start();", "\n var workspace = Workspace.CreateNew();", - "\n workspace.InitializeFrom(DataSource);", + "\n workspace.InitializeFrom(options.TargetDataSource);", "\n", "\n var aocTypes = await options.TargetDataSource.Query().OrderBy(x => x.Order).ToArrayAsync();", - "\n var aocTypesMandatory = typeof(AocTypes).GetFields().Select(x => (string)x.Name);", - "\n if(aocTypesMandatory.Where(x => !aocTypes.Select(x => x.SystemName).Contains(x)).Any()) {", - "\n ApplicationMessage.Log(Error.Generic, $\"Not all mandatory AocTypes have been imported.\"); // TODO: create new Error in Validations", + "\n var aocTypesCompulsory = typeof(AocTypes).GetFields().Select(x => (string)x.Name);", + "\n if(aocTypesCompulsory.Where(x => !aocTypes.Select(x => x.SystemName).Contains(x)).Any()) {", + "\n ApplicationMessage.Log(Error.AocTypeCompulsoryNotFound);", "\n return Activity.Finish().RepeatOnce();", "\n }", "\n ", @@ -348,7 +368,11 @@ "\n .Select(y => y.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault())", "\n .ToDictionary(x => (x.AocType, x.Novelty));", "\n var aocOrder = aocConfigs.ToDictionary(x => x.Key, x => x.Value.Order);", - "\n var newAocTypes = orderByName.Keys.Where(x => !aocConfigs.Keys.Contains((x, Novelties.I)) && !aocTypesMandatory.Contains(x)).ToArray();", + "\n var newAocTypes = orderByName.Keys.Where(x => !aocConfigs.Keys.Contains((x, Novelties.I)) && ", + "\n !aocConfigs.Keys.Contains((x, Novelties.N)) && ", + "\n !aocConfigs.Keys.Contains((x, Novelties.C)) && ", + "\n !aocTypes.Any(y => y.Parent == x) &&", + "\n !aocTypesCompulsory.Contains(x)).ToArray();", "\n", "\n foreach(var newAocType in newAocTypes) {", "\n if(orderByName[newAocType] < orderByName[AocTypes.RCU])", @@ -356,28 +380,41 @@ "\n var step = (AocTypes.MC, Novelties.I);", "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] }); ", "\n }", - "\n else if(orderByName[newAocType] < orderByName[AocTypes.CF] && orderByName[newAocType] > orderByName[AocTypes.RCU]) ", + "\n else if(orderByName[newAocType] > orderByName[AocTypes.RCU] && orderByName[newAocType] < orderByName[AocTypes.CF]) ", "\n {", "\n var step = (AocTypes.RCU, Novelties.I);", "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] });", "\n }", - "\n else if(orderByName[newAocType] < orderByName[AocTypes.YCU] && orderByName[newAocType] > orderByName[AocTypes.IA]) ", + "\n else if(orderByName[newAocType] > orderByName[AocTypes.IA] && orderByName[newAocType] < orderByName[AocTypes.YCU]) ", "\n {", - "\n var step = (AocTypes.AU, Novelties.I);", - "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] } );", + "\n foreach (var novelty in new[]{Novelties.I, Novelties.N}) {", + "\n var step = (AocTypes.AU, novelty);", + "\n var order = orderByName[newAocType] < orderByName[AocTypes.AU]? ++aocOrder[(AocTypes.IA, novelty)] : ++aocOrder[(AocTypes.AU, novelty)];", + "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = order } );", + "\n }", + "\n }", + "\n else if(orderByName[newAocType] > orderByName[AocTypes.CRU] && orderByName[newAocType] < orderByName[AocTypes.WO])", + "\n {", + "\n var stepI = (AocTypes.EV, Novelties.I);", + "\n var orderI = orderByName[newAocType] < orderByName[AocTypes.EV]? ++aocOrder[(AocTypes.CRU, Novelties.I)] : ++aocOrder[(AocTypes.EV, Novelties.I)];", + "\n await workspace.UpdateAsync( aocConfigs[stepI] with { AocType = newAocType, DataType = DataType.Optional, Order = orderI } );", + "\n", + "\n var stepN = (AocTypes.EV, Novelties.N);", + "\n var orderN = orderByName[newAocType] < orderByName[AocTypes.EV]? ++aocOrder[(AocTypes.AU, Novelties.N)] : ++aocOrder[(AocTypes.EV, Novelties.N)];", + "\n await workspace.UpdateAsync( aocConfigs[stepN] with { AocType = newAocType, DataType = DataType.Optional, Order = orderN } );", "\n }", - "\n else if(orderByName[newAocType] > orderByName[AocTypes.CRU])", + "\n else if(orderByName[newAocType] > orderByName[AocTypes.WO] && orderByName[newAocType] < orderByName[AocTypes.CL])", "\n {", - "\n var step = (AocTypes.EV, Novelties.I);", + "\n var step = (AocTypes.WO, Novelties.C);", "\n await workspace.UpdateAsync( aocConfigs[step] with { AocType = newAocType, DataType = DataType.Optional, Order = ++aocOrder[step] } );", "\n }", "\n else", - "\n ApplicationMessage.Log(Error.Generic, $\"The AocType {newAocType} has been added in a wrong position.\"); // TODO: create new Error in Validations", + "\n ApplicationMessage.Log(Error.AocTypePositionNotSupported);", "\n };", "\n", "\n var aocConfigsFinal = await workspace.Query().ToArrayAsync();", "\n if(aocConfigsFinal.GroupBy(x => x.Order).Any(x => x.Count() > 1))", - "\n ApplicationMessage.Log(Error.Generic, $\"Two or more Aoc Configurations have the same Order.\"); // TODO: create new Error in Validations", + "\n ApplicationMessage.Log(Error.AocConfigurationOrderNotUnique);", "\n", "\n await workspace.CommitToTargetAsync(options.TargetDataSource);", "\n return new[] {Activity.Finish(),logConfig}; ", diff --git a/ifrs17/Test/Tests.ipynb b/ifrs17/Test/Tests.ipynb new file mode 100644 index 00000000..e49d0f33 --- /dev/null +++ b/ifrs17/Test/Tests.ipynb @@ -0,0 +1,37 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Tests

" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"AocConfigurationTest\"" + ] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"QueriesTest\"" + ] + } + ] +} \ No newline at end of file From 886ec6822538a1e109a9c44e9db5f85386a9e933 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Mon, 17 Oct 2022 23:30:21 +0200 Subject: [PATCH 24/38] final feedback --- .../Initialization/InitSystemorphBaseToMemory.ipynb | 7 ++++++- full-ifrs17-template/Test/Tests.ipynb | 6 ------ .../Test/AocConfigurationTest.ipynb | 0 {full-ifrs17-template => ifrs17}/Test/QueriesTest.ipynb | 0 4 files changed, 6 insertions(+), 7 deletions(-) rename {full-ifrs17-template => ifrs17}/Test/AocConfigurationTest.ipynb (100%) rename {full-ifrs17-template => ifrs17}/Test/QueriesTest.ipynb (100%) diff --git a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb index 293cb431..aa07078f 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb @@ -77,7 +77,6 @@ "\n .WithType()", "\n .WithType()", "\n .WithType()", - "\n .WithType()", "\n .WithType()", "\n .WithType()", "\n .WithType()", @@ -96,6 +95,12 @@ "\n .WithTarget(DataSource)", "\n .ExecuteAsync()" ] + }, + { + "cell_type": "code", + "source": [ + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\").WithFormat("AocConfiguration").WithTarget(DataSource).ExecuteAsync()" + ] }, { "cell_type": "code", diff --git a/full-ifrs17-template/Test/Tests.ipynb b/full-ifrs17-template/Test/Tests.ipynb index 40b15ba1..47f5ea85 100644 --- a/full-ifrs17-template/Test/Tests.ipynb +++ b/full-ifrs17-template/Test/Tests.ipynb @@ -41,12 +41,6 @@ "#!eval-notebook \"ReportStorageTest\"" ] }, - { - "cell_type": "code", - "source": [ - "#!eval-notebook \"QueriesTest\"" - ] - }, { "cell_type": "code", "source": [ diff --git a/full-ifrs17-template/Test/AocConfigurationTest.ipynb b/ifrs17/Test/AocConfigurationTest.ipynb similarity index 100% rename from full-ifrs17-template/Test/AocConfigurationTest.ipynb rename to ifrs17/Test/AocConfigurationTest.ipynb diff --git a/full-ifrs17-template/Test/QueriesTest.ipynb b/ifrs17/Test/QueriesTest.ipynb similarity index 100% rename from full-ifrs17-template/Test/QueriesTest.ipynb rename to ifrs17/Test/QueriesTest.ipynb From 7b8850bdbfbfc2082806c29104689f992ebced8a Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Tue, 18 Oct 2022 00:36:54 +0200 Subject: [PATCH 25/38] fix --- .../Initialization/InitSystemorphBaseToMemory.ipynb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb index aa07078f..523544b7 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb @@ -96,10 +96,10 @@ "\n .ExecuteAsync()" ] }, - { + { "cell_type": "code", "source": [ - "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\").WithFormat("AocConfiguration").WithTarget(DataSource).ExecuteAsync()" + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\").WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync()" ] }, { @@ -191,4 +191,4 @@ ] } ] -} \ No newline at end of file +} From 34a97cfd6ae623aa108cabd41c4c7a6a8ad94b93 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Tue, 18 Oct 2022 00:52:20 +0200 Subject: [PATCH 26/38] const version ce --- full-ifrs17-template/Constants/Consts.ipynb | 28 +++++++++++++++++++ .../InitSystemorphBaseToMemory.ipynb | 7 +++-- 2 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 full-ifrs17-template/Constants/Consts.ipynb diff --git a/full-ifrs17-template/Constants/Consts.ipynb b/full-ifrs17-template/Constants/Consts.ipynb new file mode 100644 index 00000000..f39ab144 --- /dev/null +++ b/full-ifrs17-template/Constants/Consts.ipynb @@ -0,0 +1,28 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "var projectName = \"ifrs17ce\";", + "\nvar environmentName = \"dev\";", + "\nvar notebookName = \"CalculationEngine\";", + "\nvar calculationEngine = $\"#!import \\\"//{projectName}/{environmentName}/{notebookName}\\\"\";" + ] + } + ] +} \ No newline at end of file diff --git a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb index 523544b7..cf90dac4 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb @@ -29,7 +29,8 @@ { "cell_type": "code", "source": [ - "#!import \"//ifrs17ce/dev/CalculationEngine\"" + "#!import \"../Constants/Consts\"", + "\n#!eval calculationEngine" ] }, { @@ -96,7 +97,7 @@ "\n .ExecuteAsync()" ] }, - { + { "cell_type": "code", "source": [ "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\").WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync()" @@ -191,4 +192,4 @@ ] } ] -} +} \ No newline at end of file From 016fac738cf144e49066d979735cbded6cd252fd Mon Sep 17 00:00:00 2001 From: Davide Colleoni <103409906+dcolleoni@users.noreply.github.com> Date: Thu, 20 Oct 2022 13:36:13 +0200 Subject: [PATCH 27/38] Update links (#51) * working on links * read me * remove redundant code * clean up * AocConfiguration ImportFormat * remove reference to init from Overview --- full-ifrs17-template/Export/MapTemplate.ipynb | 12 - .../InitSystemorphBaseToMemory.ipynb | 2 +- .../InputFormatDescription.ipynb | 28 +- full-ifrs17-template/README.md | 19 +- .../SpecificationsFinancialPerformance.ipynb | 4 +- .../Test/SpecificationsImportActuals.ipynb | 4 +- .../Test/SpecificationsImportCashflows.ipynb | 12 +- .../Test/SpecificationsTechnicalMargin.ipynb | 14 +- ifrs17/Constants/Consts.ipynb | 1 + ifrs17/Import/ImportScopeCalculation.ipynb | 78 +--- ifrs17/Import/Importers.ipynb | 2 +- ifrs17/OverviewCalculationEngine.ipynb | 4 +- ifrs17/README.md | 8 +- ifrs17/Report/Reports.ipynb | 410 ------------------ 14 files changed, 61 insertions(+), 537 deletions(-) delete mode 100644 ifrs17/Report/Reports.ipynb diff --git a/full-ifrs17-template/Export/MapTemplate.ipynb b/full-ifrs17-template/Export/MapTemplate.ipynb index 4aa026ea..af901570 100644 --- a/full-ifrs17-template/Export/MapTemplate.ipynb +++ b/full-ifrs17-template/Export/MapTemplate.ipynb @@ -56,18 +56,6 @@ "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" ] }, - { - "cell_type": "markdown", - "source": [ - "# Import dependencies" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"../Export/ExportConfiguration\"" - ] - }, { "cell_type": "markdown", "source": [ diff --git a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb index cf90dac4..1dc82a4e 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb @@ -100,7 +100,7 @@ { "cell_type": "code", "source": [ - "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\").WithFormat(\"AocConfiguration\").WithTarget(DataSource).ExecuteAsync()" + "await Import.FromFile(\"../Files/DimensionsAndPartitions.csv\").WithFormat(ImportFormats.AocConfiguration).WithTarget(DataSource).ExecuteAsync()" ] }, { diff --git a/full-ifrs17-template/InputFormatDescription.ipynb b/full-ifrs17-template/InputFormatDescription.ipynb index 2e81506f..9dd70de5 100644 --- a/full-ifrs17-template/InputFormatDescription.ipynb +++ b/full-ifrs17-template/InputFormatDescription.ipynb @@ -36,16 +36,16 @@ "source": [ "A cashflow file is named **NominalCashflows** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Cashflow**.", "\n", - "\nThe **Main** section contains information such as: Reporting Node, Year, Month and Scenario for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partitions) to which the data belongs.", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month and Scenario for which the data is being imported. This information is used to define the [partition](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#partitions) to which the data belongs.", "\n", "\nThe **Cashflow** section contains the cash flow data. Several pieces of information are required to characterize a cash flow correctly:", - "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", - "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", - "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", - "\n- [Novelty](./DataModel/DataStructure#novelty) : entered with its SystemName,", + "\n- [DataNode](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [AmountType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#amount-type) : entered with its SystemName,", + "\n- [AocType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#aoc-type) : entered with its SystemName,", + "\n- [Novelty](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#novelty) : entered with its SystemName,", "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims.", "\n", - "\nAll valid combinations of AocType and Novelty can be found in [AocConfiguration](./DataModel/DataStructure#aoc-configuration) with DataType Optional or Mandatory.", + "\nAll valid combinations of AocType and Novelty can be found in [AocConfiguration](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#aoc-configuration) with DataType Optional or Mandatory.", "\n
The cash flow is entered in the columns named ValuesN where N goes from 0 to the lenght of cash flow. The Value0 corresponds to January of the Year entered in the **Main** section for every combination of AocType and Novelty. " ] }, @@ -64,12 +64,12 @@ "source": [ "An Actuals file is named **Actuals** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Actual**.", "\n", - "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#partition) to which the data belong.", "\n", "\nThe **Actual** section contains the actuals data. Several pieces of information are required to to characterize an Actuals amount correctly:", - "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", - "\n- [AocType](./DataModel/DataStructure#aoc-type) : entered with its SystemName,", - "\n- [ValueType](./DataModel/DataStructure#amount-type) : corresponds to AmountType SystemName extended with the ExternalId,", + "\n- [DataNode](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [AocType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#aoc-type) : entered with its SystemName,", + "\n- [ValueType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#amount-type) : corresponds to AmountType SystemName extended with the ExternalId,", "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." ] }, @@ -88,12 +88,12 @@ "source": [ "An Openings file is named **Openings** *\\_* *\\_* *\\_* and is composed of two sections: **Main** and **Opening**. In an AoC for one period, we only need one file with the year/month combination of the beginning of the period. Some GICs do not need any entries in Openings.", "\n", - "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](./DataModel/DataStructure#partition) to which the data belong.", + "\nThe **Main** section contains information such as: Reporting Node, Year, Month for which the data is being imported. This information is used to define the [partition](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#partition) to which the data belong.", "\n", "\nThe **Opening** section contains values at opening of an analysis. Several pieces of information are required to to characterize an Opening amount correctly:", - "\n- [DataNode](./DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", - "\n- [EstimateType](./DataModel/DataStructure#estimate-type) : entered with its SystemName,", - "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", + "\n- [DataNode](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#group-of-contracts) : lowest granularity of the Data Node, it is entered with its SystemName,", + "\n- [EstimateType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#estimate-type) : entered with its SystemName,", + "\n- [AmountType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#amount-type) : entered with its SystemName,", "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." ] } diff --git a/full-ifrs17-template/README.md b/full-ifrs17-template/README.md index 5c22a397..682bf0c1 100644 --- a/full-ifrs17-template/README.md +++ b/full-ifrs17-template/README.md @@ -1,21 +1,24 @@ -![Systemorph_logo.png](https://portal.systemorph.cloud/api/project/userclone/env/dev/file/download?path=Images/Systemorph_logo.png) +![Systemorph_logo.png](https://portal.systemorph.cloud/api/project/full-ifrs17-template1/env/dev/file/download?path=Images/Systemorph_logo.png) **Full IFRS 17 Template** Systemorph's IFRS 17 [Calculation Engine](https://portal.systemorph.cloud/api/project/ifrs17ce/env/dev/) is a tool to conduct all the essential IFRS 17 calculations given some key figures. + Systemorph's *Full IFRS 17 Template* uses our IFRS 17 Calculation Engine to import several use-cases and show the results. # Get Started -Interact with this *Full IFRS 17 Template* after having cloned the project. +Interact with this *Full IFRS 17 Template* after having cloned the project # Supporting Material -Check out the [video]() (this is a youtube link to Marketing) +Check out the [video]() (this is a youtube link or the video is embedded) + +Check out our IFRS 17 initiative [here](landing page) # Report -Check out the IFRS 17 reports [here](./Report/Reports) +Check out the IFRS 17 reports computed for our use-cases [here](./Report/Reports) # Testing @@ -27,9 +30,7 @@ If you want a step by step guide into the calculation logic, please go to the "S # Got Questions -For support around the IFRS17 CalculationEngine you can personally reach out to one of our IFRS17 experts: -- [Dr. Andrea Muolo]() -- [Dr. Davide Colleoni](https://www.linkedin.com/in/davidecolleoni/) -- [Mrs. Sara Busato]() +For support around the IFRS 17 CalculationEngine get in contact with our Community: -If you are interested in adapting the IFRS17 CalculationEngine to your data and would like to start a collaboration with us, you can contact [Wolfgang Maehr]() \ No newline at end of file +- [Community]() -link to the community page- +- [Evangelists]() -link to Evangelists page- \ No newline at end of file diff --git a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb index 3cfaff8e..8be275bc 100644 --- a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb +++ b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb @@ -218,7 +218,7 @@ { "cell_type": "markdown", "source": [ - "The Fulfillment Cashflow (FCF) corresponds to the sum of the Best Estimate [Present Value](../Import/ImportScopeCalculation#current-and-locked) (PV) and the [Risk Adjustment](../Import/ImportScopeCalculation#risk-adjustment) (RA), both summed over Amounty Types, and both discounted with the Locked-In curve in the BBA valuation approach:", + "The Fulfillment Cashflow (FCF) corresponds to the sum of the Best Estimate [Present Value](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation#current-and-locked) (PV) and the [Risk Adjustment](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation#risk-adjustment) (RA), both summed over Amounty Types, and both discounted with the Locked-In curve in the BBA valuation approach:", "\n", "\n$$", "\n\\text{FCF}(\\text{AoC}) = \\text{PV Locked}(\\text{AoC})", @@ -1136,7 +1136,7 @@ "source": [ "Based on the results calculated in Section 3, we check here the consistency of the [Financial Performance Report](#report). ", "\n", - "\nFiner granular reconciliations can be performed by following the datails of how each report contributes to the Financial Performance Report. Please, refer to the [Report documentation](../Report/ReportScopes#financial-performance) for all the details. " + "\nFiner granular reconciliations can be performed by following the datails of how each report contributes to the Financial Performance Report. Please, refer to the [Report documentation](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#financial-performance) for all the details. " ] }, { diff --git a/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb b/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb index 7785ed4a..8993aa5c 100644 --- a/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportActuals.ipynb @@ -84,7 +84,7 @@ { "cell_type": "markdown", "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + "[Setup IFRS17 Calculation Engine](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation):" ] }, { @@ -155,7 +155,7 @@ "\n3. Amortization (AM) ", "\n4. End of Period (EOP) ", "\n", - "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](../DataModel/DataStructure#estimate-type):", + "\nWe consider 4 types of Actual values, which are distinguished through their [Estimate Type](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#estimate-type):", "\n- Actuals (A)", "\n- Advance Actuals (AA)", "\n- Overdue Actuals (OA)", diff --git a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb index 4be8de77..5034a6ac 100644 --- a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb @@ -91,7 +91,7 @@ { "cell_type": "markdown", "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + "[Setup IFRS17 Calculation Engine](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation):" ] }, { @@ -160,7 +160,7 @@ { "cell_type": "markdown", "source": [ - "Here the correct Yield Curve is chosen among those imported from Initialization/Systemorph/Data.csv according to the [current period](#year-and-period) and the Aoc Step according the [Aoc Configuration](../DataModel/DataStructure#aoc-configuration). In the following we retrieve the desired identity." + "Here the correct Yield Curve is chosen among those imported from Initialization/Systemorph/Data.csv according to the [current period](#year-and-period) and the Aoc Step according the [Aoc Configuration](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#aoc-configuration). In the following we retrieve the desired identity." ] }, { @@ -603,7 +603,7 @@ "\n\\text{CDC}_t^{\\text{Amount Type}=\\text{CDR}} = \\sum_{\\tau=t} \\big( \\text{Valid Discount}_{\\frac{t}{12}} \\big)^{\\tau-t+1} \\cdot \\text{Nominal}_\\tau^{\\text{Claim}} \\cdot \\big( e^{-\\gamma(\\tau-t)} -1 \\big)", "\n$$", "\n", - "\nwhere $\\gamma$ is the assumed non-performance probability of the reinsurer to be provided as an [input parameter](../DataModel/DataStructure#credit-default-rate).", + "\nwhere $\\gamma$ is the assumed non-performance probability of the reinsurer to be provided as an [input parameter](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#credit-default-rate).", "\n", "\nThis rate is constant for the whole projection period, that is, $\\gamma$ is not a function of $t$. ", "\nIt effectively amounts to a constant increase in the continuous discount rate by $\\gamma$. " @@ -716,7 +716,7 @@ { "cell_type": "markdown", "source": [ - "Secondly, the correct credit risk rate (parameter $\\gamma$ in the [formula above](#non-performance-risk-adjustment)) is retrieved from the list of imported [Partner Rating](../DataModel/DataStructure) and [Credit Default Rates](../DataModel/DataStructure) relative to the target [Data Node](#year-and-period)'s Partner" + "Secondly, the correct credit risk rate (parameter $\\gamma$ in the [formula above](#non-performance-risk-adjustment)) is retrieved from the list of imported [Partner Rating](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure) and [Credit Default Rates](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure) relative to the target [Data Node](#year-and-period)'s Partner" ] }, { @@ -780,7 +780,7 @@ { "cell_type": "markdown", "source": [ - "For an implementation of these formulas refer to the [ImportScopeCalculation notebook](../Import/ImportScopeCalculation). " + "For an implementation of these formulas refer to the [ImportScopeCalculation notebook](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation). " ] }, { @@ -804,7 +804,7 @@ { "cell_type": "markdown", "source": [ - "The Present Value Base (PVB) values are valid for all [Economic Basis](../DataModel/DataStructure#economic-basis) and depends on the corresponding [AoCType](../DataModel/DataStructure#aoc-type):", + "The Present Value Base (PVB) values are valid for all [Economic Basis](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#economic-basis) and depends on the corresponding [AoCType](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#aoc-type):", "\n", "\n$$", "\n\\text{PVB}_t \\big(\\text{AoC}\\big) = ", diff --git a/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb index 26e2d8f3..43191eec 100644 --- a/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb +++ b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb @@ -83,7 +83,7 @@ { "cell_type": "markdown", "source": [ - "[Setup IFRS17 Calculation Engine](../Import/ImportScopeCalculation):" + "[Setup IFRS17 Calculation Engine](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation):" ] }, { @@ -189,7 +189,7 @@ "cell_type": "markdown", "source": [ "Projected Present Values (PPVs) are calculated for each Amount Type (AT) either with the *locked-in* (L) and with the *current* (C) Yield Curves. While the former is the latest available as per end of the DataNode's inception year, the latter is the latest available as per the current period. ", - "\nPPVs for both Economic Basis L and C have been defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", + "\nPPVs for both Economic Basis L and C have been defined [here](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", "\n", "\nAccording to the BBA methodology, the CSM calculation uses the PV with locked-in Yield Curve simply defined as", "\n", @@ -228,7 +228,7 @@ { "cell_type": "markdown", "source": [ - "Aggregated values are also available as the sum over all [Amount Types](../DataModel/DataStructure#amount-type):", + "Aggregated values are also available as the sum over all [Amount Types](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#amount-type):", "\n", "\n$$", "\n\\text{PV Locked Value}(\\text{AoC}) = \\sum_{\\text{AT}} \\text{PV Locked}(\\text{AoC}, \\text{AT})", @@ -270,7 +270,7 @@ { "cell_type": "markdown", "source": [ - "The CSM calculation also uses locked-in Risk Adjustment (RA Locked) which is retrieved from the corresponding Present Value with [Calculation Type](../DataModel/DataStructure#calculation-type) being RA defined [here](../Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", + "The CSM calculation also uses locked-in Risk Adjustment (RA Locked) which is retrieved from the corresponding Present Value with [Calculation Type](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#calculation-type) being RA defined [here](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation#present-value) and tested [here](SpecificationsImportCashflows#present-values). ", "\n", "\nRisk Adjustment values can be written as", "\n", @@ -278,7 +278,7 @@ "\n\\text{RA Locked Value}(\\text{AoC}) = \\text{PV}(\\text{AoC})|_{\\substack{ \\text{Calculation Type = RA} \\\\ \\text{Economic Base = L} }}", "\n$$", "\n", - "\nwhere the imported Cashflows for the RA Calculation Type are already aggregated over all [Amount Types](../DataModel/DataStructure#amount-type)." + "\nwhere the imported Cashflows for the RA Calculation Type are already aggregated over all [Amount Types](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/DataModel/DataStructure#amount-type)." ] }, { @@ -376,7 +376,7 @@ "\n\\right.", "\n$$", "\n", - "\nwhere AMF is the Amortization Factor that is defined [here](../Import/ImportScopeCalculation#amortization-factor) and tested [here](SpecificationsImportCashflows#amortization-factor), with YC being the [Yield Curve](#yield-curves) and TS is the Time-Step, ", + "\nwhere AMF is the Amortization Factor that is defined [here](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation#amortization-factor) and tested [here](SpecificationsImportCashflows#amortization-factor), with YC being the [Yield Curve](#yield-curves) and TS is the Time-Step, ", "\nand the Premiums, Attributable Expense and Commissions and Investment Claims terms are given by:", "\n", "\n$$", @@ -392,7 +392,7 @@ "\n\\end{array}", "\n$$", "\n", - "\nThe AoC Type **CF** is implicit for all formulas, PV is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **OA** and **AA** (see details [here](../Import/ImportScopeCalculation#actual-base))." + "\nThe AoC Type **CF** is implicit for all formulas, PV is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **OA** and **AA** (see details [here](https://portal.stage.systemorph.cloud/project/ifrs17ce/env/dev/Import/ImportScopeCalculation#actual-base))." ] }, { diff --git a/ifrs17/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb index 423a41b4..8c67e92e 100644 --- a/ifrs17/Constants/Consts.ipynb +++ b/ifrs17/Constants/Consts.ipynb @@ -141,6 +141,7 @@ "\n public const string DataNodeParameter = nameof(DataNodeParameter);", "\n public const string SimpleValue = nameof(SimpleValue);", "\n public const string Opening = nameof(Opening);", + "\n public const string AocConfiguration = nameof(AocConfiguration);", "\n}" ] }, diff --git a/ifrs17/Import/ImportScopeCalculation.ipynb b/ifrs17/Import/ImportScopeCalculation.ipynb index ee63b100..c5709d0a 100644 --- a/ifrs17/Import/ImportScopeCalculation.ipynb +++ b/ifrs17/Import/ImportScopeCalculation.ipynb @@ -21,9 +21,13 @@ "cell_type": "markdown", "source": [ "", - "\n

Import Scopes (IFRS17 Methodology Business Logic)

", - "\n", - "\nThis notebook contains the logic used to perform calculations upon import of data (actuals and cashflows). This is also called 'Data Loading' and the concept of Scope is used here to define the logic and provide the means of executing the logic." + "\n

Import Scopes (IFRS17 Methodology Business Logic)

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This notebook contains the logic used to perform calculations upon import of data (actuals and cashflows). This is also called 'Data Loading' and the concept of Scope is used here to define the logic and provide the means of executing the logic." ] }, { @@ -378,9 +382,7 @@ { "cell_type": "markdown", "source": [ - "The exact structure being return depends on the **order** of the AoC Steps (which is set by the [AoC Type](../DataModel/DataStructure#aoc-type)), and on which AoC steps exist.", - "\n", - "\nFor an example of the usage of the AocStep scope see [here](../Test/AocStructureTest)." + "The exact structure being return depends on the **order** of the AoC Steps (which is set by the [AoC Type](../DataModel/DataStructure#aoc-type)), and on which AoC steps exist." ] }, { @@ -443,12 +445,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "For an example of these calculations see [here](../Test/SpecificationsImportCashflows#interest-and-discount-rates)." - ] - }, { "cell_type": "markdown", "source": [ @@ -505,12 +501,6 @@ "For a given month $i$ they are denoted as $\\rm{Nominal}_i$." ] }, - { - "cell_type": "markdown", - "source": [ - "For an example of nominal cashflow values see [here](../Test/SpecificationsImportCashflows#nominal-cashflow)." - ] - }, { "cell_type": "markdown", "source": [ @@ -574,12 +564,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "For example calculations for Cumulated Discounted Cashflows see [here](../Test/SpecificationsImportCashflows#cumulated-discounted-cashflow)." - ] - }, { "cell_type": "markdown", "source": [ @@ -620,12 +604,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "Examples of Telescoping Difference calculations for different AoC steps start [here](../Test/SpecificationsImportCashflows#modelcorrections)." - ] - }, { "cell_type": "markdown", "source": [ @@ -672,12 +650,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "An example of Projected Present Value calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." - ] - }, { "cell_type": "markdown", "source": [ @@ -750,12 +722,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "An example of the Interest Accretion calculations can be found [here](../Test/SpecificationsImportCashflows#interest-accretion)." - ] - }, { "cell_type": "markdown", "source": [ @@ -841,12 +807,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "An example of the Present Value Base calculations can be found [here](../Test/SpecificationsImportCashflows#present-value)." - ] - }, { "cell_type": "markdown", "source": [ @@ -926,7 +886,7 @@ "", "\n## Risk Adjustment", "\n", - "\nRisk Adjustment values ($\\rm{RA}$) are accessible from the [PV Base](#present-value-base) data and have [Calculation Type](../DataModel/DataStructure#calculation-type) $RA$. In particular, the Locked-In and Current values are given by:", + "\nRisk Adjustment values ($\\rm{RA}$) are accessible from the [PresentValue](#present-value-base) data and have [Estimate Type](../DataModel/DataStructure#estimate-type) $RA$. In particular, the Locked-In and Current values are given by:", "\n", "\n$$", "\n\\text{RA Locked}(\\text{AoC step}) = \\text{PV}(\\text{AoC step})|_{\\text{Calculation Type = RA},~ \\text{Economic Basis = L}}", @@ -990,7 +950,7 @@ "\nThe coverage unit (CU) of a GIC is introduced in the standard as the quantity of the service provided in that GIC. The service is", "\nmeasured by considering the quantity of benefits provided as well as the expected coverage period of the GIC.", "\n", - "\nThe cashflows of coverage units are retrieved from the discounted cashflows with [Calculation Type](../DataModel/DataStructure#calculation-type) CU." + "\nThe cashflows of coverage units are retrieved from the discounted cashflows with [EstimateType](../DataModel/DataStructure#estimate-type) CU." ] }, { @@ -1165,12 +1125,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "An example of Actual Base figures can be found [here](../Test/SpecificationsImportActuals#base-actual)." - ] - }, { "cell_type": "markdown", "source": [ @@ -1207,7 +1161,7 @@ "", "\n### Advance Actuals", "\n", - "\n**Advance Actuals** are those cashflows with due date inside the reporting period but which occured *before* the reporting period - They include:", + "\nAdvance Actuals are cash flows with due date inside the reporting period but occured *before* the reporting period - They include:", "\n- Receivable Claims", "\n- Receivable Expenses", "\n- Payable Premiums", @@ -1242,7 +1196,7 @@ "", "\n### Overdue Actuals", "\n", - "\n**Overdue Actuals** are those cashflows with due date inside the reporting period but which occur *after* the reporting period - They contain:", + "\nOverdue Actuals are cash flows with due date inside the reporting period but occur *after* the reporting period - They contain:", "\n- Payable Claims", "\n- Payable Expenses", "\n- Receivable Premiums", @@ -1341,12 +1295,6 @@ "\n}" ] }, - { - "cell_type": "markdown", - "source": [ - "An example of Deferrable Actual figures can be found [here](../Test/SpecificationsImportActuals#deferrable-actual)." - ] - }, { "cell_type": "markdown", "source": [ @@ -1480,7 +1428,7 @@ "\n\\big(PV_{\\text{Novelty = I}} + PV_{\\text{Novelty = N}} \\big) - \\big( \\text{Actual}_{\\text{Novelty=C}} + \\text{Advance Actual}_{\\text{Novelty=C}}+ \\text{Overdue Actual}_{\\text{Novelty=C}} \\big) ~,", "\n$$", "\n", - "\nwhere the AoC Step **CF** is implicit for all formulas, $PV$ is the [present value](#present-value) with Calculation Type **BE**, and Actuals have Estimate Types **A**, **AA**, and **OA** (see details [here](#actual-values))." + "\nwhere the AoC Step **CF** is implicit for all formulas, $PV$ is the [present value](#present-value) with Estimate Type **BE**, and Actuals have Estimate Types **A**, **AA**, and **OA** (see details [here](#actual-values))." ] }, { diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index f2963181..cd3fe8a0 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -347,7 +347,7 @@ { "cell_type": "code", "source": [ - "Import.DefineFormat(\"AocConfiguration\", async (options, dataSet) => {", + "Import.DefineFormat(ImportFormats.AocConfiguration, async (options, dataSet) => {", "\n Activity.Start();", "\n var workspace = Workspace.CreateNew();", "\n workspace.InitializeFrom(options.TargetDataSource);", diff --git a/ifrs17/OverviewCalculationEngine.ipynb b/ifrs17/OverviewCalculationEngine.ipynb index 108756ef..3045ed95 100644 --- a/ifrs17/OverviewCalculationEngine.ipynb +++ b/ifrs17/OverviewCalculationEngine.ipynb @@ -104,9 +104,7 @@ "\n", "\nHowever, the import as such is conducted by other notebooks which use the methods of ImportStorage and ImportScopeCalculation in a chain of notebook imports:", "\n", - "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) --> [InitSystemorphBaseToMemory](./Initialization/InitSystemorphBaseToMemory#init-base-to-memory) --> [InitSystemorphToMemory](./Initialization/InitSystemorphToMemory#init-base-to-memory).", - "\n", - "\nThe latter two notebooks initialize and store the imported and derived data in memory for further usage. To store the data in a physical database, [InitSystemorphToDatabase](./Initialization/InitSystemorphToDatabase#init-to-database) can be employed.", + "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) ", "\n", "\nThe calculations of ImportScopeCalculation cover a large part of the IFRS 17 methodology and are explained in the section below." ] diff --git a/ifrs17/README.md b/ifrs17/README.md index 4447c0c3..9891b004 100644 --- a/ifrs17/README.md +++ b/ifrs17/README.md @@ -23,9 +23,7 @@ You will be introduced to ## Got Questions -For support around the IFRS17 CalculationEngine you can personally reach out to one of our IFRS17 experts: -- [Dr. Andrea Muolo]() -- [Dr. Davide Colleoni](https://www.linkedin.com/in/davidecolleoni/) -- [Mrs. Sara Busato]() +For support around the IFRS 17 CalculationEngine get in contact with our Community: -If you are interested in adapting the IFRS17 CalculationEngine to your data and would like to start a collaboration with us, you can contact [Wolfgang Maehr]() \ No newline at end of file +- [Community]() -link to the community page- +- [Evangelists]() -link to Evangelists page- \ No newline at end of file diff --git a/ifrs17/Report/Reports.ipynb b/ifrs17/Report/Reports.ipynb deleted file mode 100644 index 91d3d680..00000000 --- a/ifrs17/Report/Reports.ipynb +++ /dev/null @@ -1,410 +0,0 @@ -{ - "metadata": { - "authors": [], - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False" - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "

Reports

", - "\n", - "\n" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Infrastructure and Configuration" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Initialize data" - ] - }, - { - "cell_type": "code", - "source": [ - "/* DataSource is configured and connected to real database */", - "\n//#!eval-notebook \"../Database/Configure\"" - ] - }, - { - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ] - }, - { - "cell_type": "code", - "source": [ - "Workspace.InitializeFrom(DataSource);" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Imports and Configurations" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"ReportScopes\"" - ] - }, - { - "cell_type": "code", - "source": [ - "var reportStorage = new ReportStorage(Workspace, Report);", - "\nawait reportStorage.InitializeReportIndependentCacheAsync();", - "\nvar mostRecentPartition = (await Workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last();", - "\nvar reportingNodeRoot = (await Workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName;", - "\nawait reportStorage.InitializeAsync((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);", - "\nvar identities = reportStorage.GetIdentities((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Calling Scope" - ] - }, - { - "cell_type": "code", - "source": [ - "var universe = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Report Settings and Storage Update" - ] - }, - { - "cell_type": "code", - "source": [ - "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", - "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", - "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", - "\n ;", - "\n", - "\nawait reportStorage.InitializeAsync(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);", - "\nidentities = reportStorage.GetIdentities(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Data Constellation", - "\n", - "\nWe have " - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Present Value", - "\n", - "\nPresent values of the best estimate of future cashflows are shown here in an Analysis of Change report.", - "\n", - "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", - "\nThe figures displayed in the report are automatically aggregated to meet the granularity desired by the user.", - "\n", - "\nCurrently, the data is sliced by :", - "\n- CurrencyType", - "\n- LiabilityType", - "\n- EconomicBasis", - "\n", - "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", - "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data." - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedBestEstimate + universe.GetScopes(identities).Aggregate().CurrentBestEstimate)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\", \"EconomicBasis\") //\"GroupOfContract\"", - "\n .ReportGridOptions()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Risk Adjustment" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedRiskAdjustment + universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"EconomicBasis\", \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Written", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"AmountType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 450)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Advance, Overdue Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Advance + universe.GetScopes(identities).Aggregate().Overdue)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions(reportHeight: 400)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Deferrable Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Deferrals", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 400)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Fulfilment Cashflow" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Fcf ", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")//, \"EstimateType\")//, \"AmountType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Actuarial Experience Adjustment" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().ActuarialExperienceAdjustment", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"AmountType\" )//\"LiabilityType\", \"EstimateType\")", - "\n .ReportGridOptions(reportHeight: 300, headerColumnWidth: 300)", - "\n .ToReport() " - ] - }, - { - "cell_type": "markdown", - "source": [ - "# LRC Technical Margin" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().LrcTechnicalMargin", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 600)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Contractual Service Margin / Loss Component / Loss Recovery Component" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Csm + universe.GetScopes(identities).Aggregate().Lc + universe.GetScopes(identities).Aggregate().Loreco)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# LRC Actuarial" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LrcActuarial)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"LiabilityType\",\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# LRC" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lrc)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType),\"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions(300)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# LIC Actuarial" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LicActuarial)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# LIC" - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lic)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions(300)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Financial Performance", - "\n", - "\nUse the expand and collapse buttons in the report rows to change the granularity of the figures displayed." - ] - }, - { - "cell_type": "code", - "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().FinancialPerformance", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", - "\n .ToReport()" - ] - }, - { - "cell_type": "code", - "source": [ - "" - ] - } - ] -} \ No newline at end of file From 546ae04f956bc8dd4b3d431b47dfe152b3f4c5be Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Fri, 21 Oct 2022 18:51:41 +0200 Subject: [PATCH 28/38] removal arithmetics --- full-ifrs17-template/Constants/Consts.ipynb | 3 ++- .../SpecificationsFinancialPerformance.ipynb | 11 +++------- .../Test/SpecificationsImportCashflows.ipynb | 20 +++++++++--------- ifrs17/DataModel/DataStructure.ipynb | 21 ++++++++++--------- ifrs17/Import/ImportScopeCalculation.ipynb | 21 ++++++++++--------- ifrs17/Import/Importers.ipynb | 6 +++--- ifrs17/Report/ReportScopes.ipynb | 17 +++++++-------- ifrs17/Report/ReportStorage.ipynb | 8 +++---- ifrs17/Utils/ApplicationMessage.ipynb | 13 ++++++------ 9 files changed, 59 insertions(+), 61 deletions(-) diff --git a/full-ifrs17-template/Constants/Consts.ipynb b/full-ifrs17-template/Constants/Consts.ipynb index f39ab144..8dc84f8d 100644 --- a/full-ifrs17-template/Constants/Consts.ipynb +++ b/full-ifrs17-template/Constants/Consts.ipynb @@ -21,7 +21,8 @@ "var projectName = \"ifrs17ce\";", "\nvar environmentName = \"dev\";", "\nvar notebookName = \"CalculationEngine\";", - "\nvar calculationEngine = $\"#!import \\\"//{projectName}/{environmentName}/{notebookName}\\\"\";" + "\nvar calculationEngine = $\"#!import \\\"//{projectName}/{environmentName}/{notebookName}\\\"\";", + "\ncalculationEngine = $\"#!import \\\"../../ifrs17/CalculationEngine\\\"\";" ] } ] diff --git a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb index 8be275bc..6900ca96 100644 --- a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb +++ b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb @@ -133,13 +133,8 @@ { "cell_type": "code", "source": [ - "var identities = reportStorage.GetIdentities(period, reportingNode, null, currencyType);" - ] - }, - { - "cell_type": "code", - "source": [ - "identities" + "var identities = reportStorage.GetIdentities(period, reportingNode, null, currencyType);", + "\nidentities" ] }, { @@ -197,7 +192,7 @@ "\n .WithQuerySource(DataSource)", "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", "\n .SliceColumnsBy(CurrencyGrouper(currencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", + "\n .WithGridOptions( o => o.WithColumns(cols => cols.Modify(\"\", c => c.WithWidth(850))) with {GroupDefaultExpanded = 3, Height = 600})", "\n .ToReport() with { Height = 600 }" ] }, diff --git a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb index 5034a6ac..12b9fc30 100644 --- a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb @@ -268,14 +268,14 @@ { "cell_type": "code", "source": [ - "var expectedInterest = yearlyYieldCurve.Select( yc => (1 + yc)^( 1.0 / 12.0) );", + "var expectedInterest = yearlyYieldCurve.Select( yc => Math.Pow(1 + yc, 1.0 / 12.0) );", "\nexpectedInterest" ] }, { "cell_type": "code", "source": [ - "from yc in yearlyYieldCurve select (1 + yc)^( 1.0 / 12.0 ) " + "from yc in yearlyYieldCurve select Math.Pow(1 + yc, 1.0 / 12.0)" ] }, { @@ -299,7 +299,7 @@ { "cell_type": "code", "source": [ - "var expectedDiscount = yearlyYieldCurve.Select( yc => (1 + yc)^( -1.0 / 12.0) );", + "var expectedDiscount = yearlyYieldCurve.Select( yc => Math.Pow(1 + yc, -1.0 / 12.0) );", "\nexpectedDiscount" ] }, @@ -710,7 +710,7 @@ { "cell_type": "code", "source": [ - "var nominalClaims = nominalICO.Values + nominalNIC.Values + nominalALE.Values + nominalULE.Values;" + "var nominalClaims = Sum( Sum(nominalICO.Values, nominalNIC.Values), Sum(nominalALE.Values, nominalULE.Values) );" ] }, { @@ -1015,7 +1015,7 @@ { "cell_type": "code", "source": [ - "var expectedPresentValueMC_PR = discountedMC_PR.Values - discountedBoP_PR.Values;" + "var expectedPresentValueMC_PR = Subtract(discountedMC_PR.Values, discountedBoP_PR.Values);" ] }, { @@ -1097,7 +1097,7 @@ { "cell_type": "code", "source": [ - "var expectedPresentValueCF_PR = -1.0 * cfNominalReference_PR.Values;" + "var expectedPresentValueCF_PR = Multiply(-1.0, cfNominalReference_PR.Values);" ] }, { @@ -1428,7 +1428,7 @@ { "cell_type": "code", "source": [ - "var expectedPresentValueYCU_PR = ycReferenceDiscountedEop - discountedYcParent.Values;" + "var expectedPresentValueYCU_PR = Subtract(ycReferenceDiscountedEop, discountedYcParent.Values);" ] }, { @@ -1579,7 +1579,7 @@ { "cell_type": "code", "source": [ - "var expectedPresentValueCRU = cruExpectedDiscountedCDR - discountedCruParent.Values;" + "var expectedPresentValueCRU = Subtract(cruExpectedDiscountedCDR, discountedCruParent.Values);" ] }, { @@ -1648,8 +1648,8 @@ { "cell_type": "code", "source": [ - "var expectedPresentValueCL_PR = Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values -", - "\n clParents.Select(aocStep => Test.GetScope((idCL with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, \"PR\", \"BE\", (int?)null)).Values).Aggregate();" + "var expectedPresentValueCL_PR = Subtract(Test.GetScope((idCL, \"PR\", \"BE\", (int?)null)).Values,", + "\n clParents.Select(aocStep => Test.GetScope((idCL with {AocType = aocStep.AocType, Novelty = aocStep.Novelty}, \"PR\", \"BE\", (int?)null)).Values).Aggregate());" ] }, { diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index f5fcf571..1b74b293 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -43,16 +43,17 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Workspace,1.4.1\"", - "\n#r \"nuget:Systemorph.Scopes,1.4.0\"", - "\n#r \"nuget:Systemorph.Import,1.4.0\"", - "\n#r \"nuget:Systemorph.Test,1.4.0\"", - "\n#r \"nuget:Systemorph.Export,1.4.0\"", - "\n#r \"nuget:Systemorph.DataSetReader,1.4.0\"", - "\n#r \"nuget:Systemorph.DataSource,1.4.1\"", - "\n#r \"nuget:Systemorph.DataSource.Conversions,1.4.1\"", - "\n#r \"nuget:Systemorph.Reporting,1.4.0\"", - "\n#r \"nuget:Systemorph.DomainDesigner,1.4.0\"" + "#r \"nuget:Systemorph.Arithmetics,1.5.1\"", + "\n#r \"nuget:Systemorph.Workspace,1.5.0\"", + "\n#r \"nuget:Systemorph.Scopes,1.5.1\"", + "\n#r \"nuget:Systemorph.Import,1.5.0\"", + "\n#r \"nuget:Systemorph.Test,1.5.1\"", + "\n#r \"nuget:Systemorph.Export,1.5.0\"", + "\n#r \"nuget:Systemorph.DataSetReader,1.5.0\"", + "\n#r \"nuget:Systemorph.DataSource,1.5.0\"", + "\n#r \"nuget:Systemorph.DataSource.Conversions,1.5.0\"", + "\n#r \"nuget:Systemorph.Reporting,1.5.1\"", + "\n#r \"nuget:Systemorph.DomainDesigner,1.5.0\"" ] }, { diff --git a/ifrs17/Import/ImportScopeCalculation.ipynb b/ifrs17/Import/ImportScopeCalculation.ipynb index c5709d0a..f172092b 100644 --- a/ifrs17/Import/ImportScopeCalculation.ipynb +++ b/ifrs17/Import/ImportScopeCalculation.ipynb @@ -441,7 +441,7 @@ "\n ", "\n double[] Interest => YearlyYieldCurve.Select(rate => Math.Pow(1d + rate, 1d / 12d) + Perturbation).ToArray(); ", "\n ", - "\n double[] Discount => Interest^(-1);", + "\n double[] Discount => Interest.Select(x => Math.Pow(x, -1)).ToArray();", "\n}" ] }, @@ -484,7 +484,7 @@ "\n ret[i] = Math.Exp(-nonPerformanceRiskRate) * ret.ElementAtOrDefault(i + 1) + NominalClaimsCashflow[i] - NominalClaimsCashflow.ElementAtOrDefault(i + 1);", "\n return ret; } } ", "\n ", - "\n double[] NominalCashflow.Values => PvCdrDecumulated - NominalClaimsCashflow;", + "\n double[] NominalCashflow.Values => Subtract(PvCdrDecumulated, NominalClaimsCashflow);", "\n}", "\n", "\npublic interface AllClaimsCashflow : NominalCashflow", @@ -600,7 +600,7 @@ "\n .Where(cf => cf.Count() > 0)", "\n .Aggregate();", "\n ", - "\n double[] Values => CurrentValues - PreviousValues;", + "\n double[] Values => Subtract(CurrentValues, PreviousValues);", "\n}" ] }, @@ -702,7 +702,7 @@ "\npublic interface IWithInterestAccretionForCreditRisk : IScope<(ImportIdentity Id, string AmountType, string EstimateType, int? AccidentYear), ImportStorage>", "\n{", "\n private double[] nominalClaimsCashflow => GetScope(Identity).Values;", - "\n private double[] nominalValuesCreditRisk => -1 * GetScope(Identity with {Id = Identity.Id with {AocType = AocTypes.CF}}).Values;", + "\n private double[] nominalValuesCreditRisk => Multiply(-1, GetScope(Identity with {Id = Identity.Id with {AocType = AocTypes.CF}}).Values);", "\n private double[] monthlyInterestFactor => GetScope(Identity.Id).Interest;", "\n private double nonPerformanceRiskRate => GetStorage().GetNonPerformanceRiskRate(Identity.Id);", "\n ", @@ -717,7 +717,7 @@ "\n effectCreditRisk[i] = interestOnClaimsCashflow[i] - interestOnClaimsCashflowCreditRisk[i];", "\n }", "\n ", - "\n return effectCreditRisk - nominalValuesCreditRisk;", + "\n return Subtract(effectCreditRisk, nominalValuesCreditRisk);", "\n }", "\n}" ] @@ -785,7 +785,7 @@ "\npublic interface CashflowAocStep : PresentValue", "\n{", "\n [NotVisible]", - "\n double[] PresentValue.Values => -1d * GetScope(Identity).Values;", + "\n double[] PresentValue.Values => Multiply(-1d, GetScope(Identity).Values);", "\n}", "\n", "\npublic interface PresentValueWithInterestAccretion : PresentValue, IWithInterestAccretion", @@ -1337,7 +1337,9 @@ "\n string EstimateType => EstimateTypes.BEPA;", "\n string EconomicBasis => EconomicBases.L;", "\n ", - "\n PresentValue[] ByAmountType => GetStorage().GetPremiums().Select(pr => GetStorage().GetPremiumAllocationFactor(Identity) * GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis))).ToArray(); ", + "\n PresentValue[] ByAmountType => GetStorage().GetPremiums().Select(pr => ", + "\n Multiply( GetStorage().GetPremiumAllocationFactor(Identity), ", + "\n GetScope((Identity, pr, EstimateTypes.BE, (int?)null), o => o.WithContext(EconomicBasis)) ) ).ToArray(); ", "\n}", "\n", "\npublic interface DefaultValueBeExperienceAdjustmentForPremium : BeExperienceAdjustmentForPremium", @@ -1356,9 +1358,8 @@ "\n .WithApplicability(x => x.Identity.AocType != AocTypes.CF));", "\n ", "\n public ActualBase[] ByAmountTypeAndEstimateType => GetStorage().GetPremiums().SelectMany(pr => ", - "\n GetStorage().ExperienceAdjustEstimateTypeMapping.Keys", - "\n .Select(et => GetStorage().GetPremiumAllocationFactor(Identity) * ", - "\n GetScope((Identity, pr, et, (int?)null)))).ToArray(); ", + "\n GetStorage().ExperienceAdjustEstimateTypeMapping.Keys.Select(et => ", + "\n Multiply(GetStorage().GetPremiumAllocationFactor(Identity), GetScope((Identity, pr, et, (int?)null))) ) ).ToArray();", "\n}", "\n", "\npublic interface DefaultValueActualExperienceAdjustmentForPremium : ActualExperienceAdjustmentForPremium", diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index cd3fe8a0..d0f1071f 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -356,11 +356,11 @@ "\n var aocTypesCompulsory = typeof(AocTypes).GetFields().Select(x => (string)x.Name);", "\n if(aocTypesCompulsory.Where(x => !aocTypes.Select(x => x.SystemName).Contains(x)).Any()) {", "\n ApplicationMessage.Log(Error.AocTypeCompulsoryNotFound);", - "\n return Activity.Finish().RepeatOnce();", + "\n return Activity.Finish();", "\n }", "\n ", "\n var logConfig = await Import.FromDataSet(dataSet).WithType().WithTarget(workspace).ExecuteAsync();", - "\n if(logConfig.Errors.Any()) return logConfig.RepeatOnce(); ", + "\n if(logConfig.Errors.Any()) return Activity.Finish().Merge(logConfig); ", "\n", "\n var orderByName = aocTypes.ToDictionary(x => x.SystemName, x => x.Order);", "\n var aocConfigs = (await workspace.Query().ToArrayAsync())", @@ -417,7 +417,7 @@ "\n ApplicationMessage.Log(Error.AocConfigurationOrderNotUnique);", "\n", "\n await workspace.CommitToTargetAsync(options.TargetDataSource);", - "\n return new[] {Activity.Finish(),logConfig}; ", + "\n return Activity.Finish().Merge(logConfig); ", "\n});" ] }, diff --git a/ifrs17/Report/ReportScopes.ipynb b/ifrs17/Report/ReportScopes.ipynb index ae87b53d..649caa08 100644 --- a/ifrs17/Report/ReportScopes.ipynb +++ b/ifrs17/Report/ReportScopes.ipynb @@ -140,12 +140,11 @@ "\n builder.ForScope(s => s.WithApplicability(x => x.GetStorage().EstimateTypesWithoutAoc.Contains(x.Identity.EstimateType)));", "\n ", "\n protected IDataCube Data => GetScope((Identity.ReportIdentity, Identity.EstimateType)).Data", - "\n .SelectToDataCube(x => GetScope((Identity.ReportIdentity.ContractualCurrency, ", - "\n Identity.ReportIdentity.FunctionalCurrency, ", - "\n GetStorage().GetFxPeriod(GetStorage().Args.Period, x.VariableType, x.Novelty),", - "\n (Identity.ReportIdentity.Year, Identity.ReportIdentity.Month),", - "\n Identity.CurrencyType", - "\n )).Fx * x);", + "\n .SelectToDataCube(x => Multiply( GetScope((Identity.ReportIdentity.ContractualCurrency, ", + "\n Identity.ReportIdentity.FunctionalCurrency, ", + "\n GetStorage().GetFxPeriod(GetStorage().Args.Period, x.VariableType, x.Novelty),", + "\n (Identity.ReportIdentity.Year, Identity.ReportIdentity.Month),", + "\n Identity.CurrencyType)).Fx, x ));", "\n ", "\n private IDataCube Eops => Data.Filter((\"VariableType\", AocTypes.EOP));", "\n private IDataCube NotEops => Data.Filter((\"VariableType\", \"!EOP\")); // TODO negation must be hardcoded (also to avoid string concatenation)", @@ -767,11 +766,11 @@ "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.NIC))", "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE2\" });", "\n ", - "\n private IEnumerable ClaimsIco => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO));", + "\n private ReportVariable[] ClaimsIco => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO)).ToArray();", "\n ", "\n IDataCube ClaimsIcoToIr => ClaimsIco.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR2\" });", - "\n IDataCube ClaimsIcoToIse => (-1 * ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", + "\n IDataCube ClaimsIcoToIse => Multiply(-1, ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", "\n ", "\n IDataCube Expenses => WrittenAndAccruals", "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AE))", diff --git a/ifrs17/Report/ReportStorage.ipynb b/ifrs17/Report/ReportStorage.ipynb index 655f0888..0c61fe1a 100644 --- a/ifrs17/Report/ReportStorage.ipynb +++ b/ifrs17/Report/ReportStorage.ipynb @@ -94,12 +94,12 @@ "public class ReportStorage {", "\n protected readonly IWorkspace workspace;", "\n private readonly Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchicalDimensionCache;", - "\n private readonly Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory;", + "\n private readonly Systemorph.Vertex.Pivot.Builder.Interfaces.IPivotFactory reportFactory;", "\n ", "\n // Current Storage Settings", "\n public ((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args {get; private set;}", "\n ", - "\n // Cache for Aux Data ", + "\n // Cache for Aux Data", "\n private Dictionary<(int year, int month), Dictionary>> exchangeRatesByCurrencyByFxTypeAndPeriod = new(); // Fx Rates", "\n private Dictionary<(int year, int month), Dictionary> fxPeriodsByAocStepAndPeriod = new(); // FxParameter", "\n ", @@ -109,7 +109,7 @@ "\n private Dictionary<((int year, int month) period, string reportingNode, string scenario), Dictionary>>> variablesDictionary = new();", "\n ", "\n // Constructor", - "\n public ReportStorage(IWorkspace workspace, Systemorph.Vertex.Pivot.Reporting.IReportFactory reportFactory) {", + "\n public ReportStorage(IWorkspace workspace, Systemorph.Vertex.Pivot.Builder.Interfaces.IPivotFactory reportFactory) {", "\n this.workspace = workspace;", "\n this.hierarchicalDimensionCache = workspace.ToHierarchicalDimensionCache();", "\n this.reportFactory = reportFactory;", @@ -182,7 +182,7 @@ "\n ", "\n // Other getters", "\n public IWorkspace Workspace => workspace;", - "\n public Systemorph.Vertex.Pivot.Reporting.IReportFactory Report => reportFactory;", + "\n public Systemorph.Vertex.Pivot.Builder.Interfaces.IPivotFactory Report => reportFactory;", "\n", "\n public Systemorph.Vertex.Hierarchies.IHierarchy GetHierarchy() where T : class, IHierarchicalDimension => hierarchicalDimensionCache.Get();", "\n ", diff --git a/ifrs17/Utils/ApplicationMessage.ipynb b/ifrs17/Utils/ApplicationMessage.ipynb index a03f0301..f2253bd6 100644 --- a/ifrs17/Utils/ApplicationMessage.ipynb +++ b/ifrs17/Utils/ApplicationMessage.ipynb @@ -27,7 +27,7 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Activities,1.4.0\"" + "#r \"nuget:Systemorph.Activities,1.5.1\"" ] }, { @@ -41,7 +41,7 @@ "source": [ "using Microsoft.Extensions.Logging;", "\n", - "\npublic class ApplicationMessage {", + "\npublic static class ApplicationMessage {", "\n private static ILogger log;", "\n ", "\n private static IActivityVariable activity;", @@ -87,13 +87,14 @@ "cell_type": "code", "source": [ "public static ActivityLog Merge (this ActivityLog a, ActivityLog b) {", + "\n var errors = a.Errors.Concat(b.Errors).ToList();", "\n return a with { ", + "\n Status = a.Status == ActivityLogStatus.Failed || b.Status == ActivityLogStatus.Failed ? ActivityLogStatus.Failed : ActivityLogStatus.Succeeded,", "\n StartDateTime = a.StartDateTime < b.StartDateTime ? a.StartDateTime : b.StartDateTime,", "\n FinishDateTime = a.FinishDateTime > b.FinishDateTime ? a.FinishDateTime : b.FinishDateTime,", - "\n Errors = a.Errors.Concat(b.Errors).ToList(),", - "\n Warnings = a.Warnings.Concat(b.Warnings).ToList(),", - "\n Infos = a.Infos.Concat(b.Infos).ToList(),", - "\n Status = a.Status == ActivityLogStatus.Failed || b.Status == ActivityLogStatus.Failed ? ActivityLogStatus.Failed : ActivityLogStatus.Succeeded", + "\n Errors = errors,", + "\n Warnings = errors.Any() ? new List() : a.Warnings.Concat(b.Warnings).ToList(),", + "\n Infos = errors.Any() ? new List() : a.Infos.Concat(b.Infos).ToList(),", "\n };", "\n}", "\n", From 95ccbb2ad66e7a9d89c927bfc72556832c95576d Mon Sep 17 00:00:00 2001 From: Daniel Trzesniak Date: Mon, 24 Oct 2022 10:08:30 +0200 Subject: [PATCH 29/38] Simple value test data (#54) * Adding data files * Fix input * Fix input * change to importers test * Fix to sign * Int convention --- .../DataNodeStates_CH_2020_12.csv | 1 + .../Files/700.DataNodes/DataNodes_CH.csv | 12 ++--- .../SimpleValue_CH_2020_12.csv | 44 +++++++++++++++++++ .../InitSystemorphToMemory.ipynb | 6 +++ ifrs17/Import/Importers.ipynb | 22 ++++++---- 5 files changed, 71 insertions(+), 14 deletions(-) create mode 100644 full-ifrs17-template/Files/900.TransactionalData/SimpleValue_CH_2020_12.csv diff --git a/full-ifrs17-template/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv b/full-ifrs17-template/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv index 78802935..14a81d65 100644 --- a/full-ifrs17-template/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv +++ b/full-ifrs17-template/Files/700.DataNodes/DataNodeStates_CH_2020_12.csv @@ -13,6 +13,7 @@ DT2.1,Active, DT2.2,Active, DT3.1,Active, DT4.1,Active, +DT5.1,Active, DTR1.1,Active, DTR1.2,Active, DTR2.1,Active, diff --git a/full-ifrs17-template/Files/700.DataNodes/DataNodes_CH.csv b/full-ifrs17-template/Files/700.DataNodes/DataNodes_CH.csv index 54f5657f..8862c011 100644 --- a/full-ifrs17-template/Files/700.DataNodes/DataNodes_CH.csv +++ b/full-ifrs17-template/Files/700.DataNodes/DataNodes_CH.csv @@ -1,15 +1,16 @@ @@Main,,,,,, ReportingNode,,,,,, CH,,,,,, -,,,,,, + @@InsurancePortfolio,,,,,, SystemName,DisplayName,ContractualCurrency,LineOfBusiness,ValuationApproach,OciType, -DT,DT complex CF,USD,ANN,BBA,Default, +DT,DT Complex CF,USD,ANN,BBA,Default, DT1,DT1 OCI,USD,ANN,BBA,Default, DT2,DT2 NOCI,USD,ANN,BBA,, DT3,DT3 RunOff,USD,ANN,BBA,Default, DT4,DT4 OCI,USD,ANN,BBA,Default, -,,,,,, +DT5,DT5 Simple Import,USD,ANN,BBA,Default + @@GroupOfInsuranceContract,,,,,, SystemName,DisplayName,InsurancePortfolio,AnnualCohort,LiabilityType,Profitability, GicComplex,Gic test discounting,DT,2020,LRC,P, @@ -20,13 +21,14 @@ DT2.1,DT2.1 NOCI LRC PA 0.8,DT2,2020,LRC,P, DT2.2,DT2.2 NOCI LIC,DT2,2020,LIC,P, DT3.1,DT3.1 Runoff - PA 0.8,DT3,2020,LRC,P, DT4.1,DT4.1 CSM PA 0.8,DT4,2020,LRC,P, -,,,,,, +DT5.1,DT5.1 Simple Import on DT 4.1,DT5,2020,LRC,P, + @@ReinsurancePortfolio,,,,,, SystemName,DisplayName,ContractualCurrency,LineOfBusiness,ValuationApproach,OciType, DTR,DTR complex CF,USD,ANN,BBA,, DTR1,DTR1 OCI,USD,ANN,BBA,Default, DTR2,DTR2 NOCI,USD,ANN,BBA,, -,,,,,, + @@GroupOfReinsuranceContract,,,,,, SystemName,DisplayName,ReinsurancePortfolio,AnnualCohort,LiabilityType,Profitability,Partner GricComplex,Gric test for discounting,DTR,2020,LRC,P,PT1 diff --git a/full-ifrs17-template/Files/900.TransactionalData/SimpleValue_CH_2020_12.csv b/full-ifrs17-template/Files/900.TransactionalData/SimpleValue_CH_2020_12.csv new file mode 100644 index 00000000..4d80bce3 --- /dev/null +++ b/full-ifrs17-template/Files/900.TransactionalData/SimpleValue_CH_2020_12.csv @@ -0,0 +1,44 @@ +@@Main +Month,ReportingNode,Scenario,Year +12,CH,,2020 +@@SimpleValue +AccidentYear,AmountType,AocType,DataNode,EconomicBasis,EstimateType,Novelty,Value +,PR,BOP,DT5.1,L,BE,N,-798.536731161375 +,NIC,BOP,DT5.1,L,BE,N,598.7529445986629 +,PR,BOP,DT5.1,C,BE,N,-798.536731161375 +,NIC,BOP,DT5.1,C,BE,N,598.7529445986629 +,,BOP,DT5.1,C,RA,N,59.8752944598663 +,,BOP,DT5.1,L,RA,N,59.8752944598663 +,,AM,DT5.1,L,F,C,0.6562298579039588 +,PR,EOP,DT5.1,L,BE,C,-399.63392949885525 +,NIC,EOP,DT5.1,L,BE,C,299.67554969423594 +,PR,EOP,DT5.1,C,BE,C,-399.63392949885525 +,NIC,EOP,DT5.1,C,BE,C,299.67554969423594 +,,EOP,DT5.1,C,RA,C,29.967554969423595 +,,EOP,DT5.1,L,RA,C,29.967554969423595 +,PR,IA,DT5.1,L,BE,N,-1.0971983374806105 +,NIC,IA,DT5.1,L,BE,N,0.9226050955731167 +,PR,IA,DT5.1,C,BE,N,-1.0971983374806105 +,NIC,IA,DT5.1,C,BE,N,0.9226050955731167 +,,IA,DT5.1,C,RA,N,0.09226050955731169 +,,IA,DT5.1,L,RA,N,0.09226050955731169 +,PR,CF,DT5.1,L,BE,N,400 +,NIC,CF,DT5.1,L,BE,N,-300 +,PR,CF,DT5.1,C,BE,N,400 +,NIC,CF,DT5.1,C,BE,N,-300 +,,CF,DT5.1,C,RA,N,-30 +,,CF,DT5.1,L,RA,N,-30 +,PR,CF,DT5.1,L,BEPA,N,320 +,PR,CF,DT5.1,,A,C,400 +,NIC,CF,DT5.1,,A,C,-280 +,ACA,CF,DT5.1,,A,C,-10 +,AEA,CF,DT5.1,,A,C,-5 +,PR,CF,DT5.1,,APA,C,320 +,,CF,DT5.1,,DA,C,-15 +,,EA,DT5.1,,C,C,-15 +,,AM,DT5.1,,DA,C,9.843447868559382 +,,AM,DT5.1,,C,C,-82.02271122089925 +,,EOP,DT5.1,,DA,C,-5.156552131440618 +,,EOP,DT5.1,,C,C,42.9681136142967 +,,BOP,DT5.1,,C,N,139.90849210284577 +,,IA,DT5.1,,C,N,0.08233273235018213 \ No newline at end of file diff --git a/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb index 884cc8fd..af8c5cf1 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb @@ -79,6 +79,12 @@ "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" ] }, + { + "cell_type": "code", + "source": [ + "await UploadSimpleValueAsync(\"../Files/900.TransactionalData/SimpleValue_CH_2020_12.csv\")" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index cd3fe8a0..0a85ee43 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -1065,21 +1065,25 @@ "\n EstimateType = estimateType,", "\n EconomicBasis = economicBasis,", "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Value = GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", + "\n Value = //GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", + "\n 1 // TODO, we need to adjust the inputs to have the correct sign, so that the default GetSign returns 1.", "\n * datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()", "\n };", "\n return iv;", - "\n }, importFormat", + "\n }, importFormat // This should indicate the table name, not the input format", "\n ).WithTarget(Workspace).ExecuteAsync();", "\n ", - "\n HashSet availableEstimateTypes = parsingStorage.TechnicalMarginEstimateTypes;", - "\n var multipleOp = await Workspace.Query().Where(iv => availableEstimateTypes.Contains(iv.EstimateType))", - "\n .GroupBy(iv => iv.DataNode)", - "\n .Where(g => g.Count() > 1).ToArrayAsync();", - "\n //.Select(g => ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, g.Key));", + "\n // Checking if there are inconsistencies in the TechnicalMarginEstimateTypes --> double entries in the steps where we expect to have unique values", + "\n var invalidVariables = await Workspace.Query()", + "\n .Where(iv => parsingStorage.TechnicalMarginEstimateTypes.Contains(iv.EstimateType))", + "\n .Where(iv => iv.AocType == AocTypes.BOP || iv.AocType == AocTypes.EOP || iv.AocType == AocTypes.AM || iv.AocType == AocTypes.EA)", + "\n .GroupBy(iv => new {iv.DataNode, iv.AocType, iv.Novelty})", + "\n .Where(g => g.Count() > 1)", + "\n .Select(g => g.Key)", + "\n .ToArrayAsync();", "\n ", - "\n foreach (var op in multipleOp)", - "\n ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, op.Key);", + "\n foreach (var iv in invalidVariables)", + "\n ApplicationMessage.Log(Error.MultipleTechnicalMarginOpening, $\"{iv.DataNode},{iv.AocType},{iv.Novelty}\");", "\n ", "\n await ValidateForDataNodeStateActiveAsync(parsingStorage.DataNodeDataBySystemName);", "\n targetPartitionByReportingNodeAndPeriodId = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id;", From 03c35bf3bd44834592e5a34ce9c95594bb0ddeb1 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Tue, 25 Oct 2022 16:38:28 +0200 Subject: [PATCH 30/38] reset consts --- full-ifrs17-template/Constants/Consts.ipynb | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/full-ifrs17-template/Constants/Consts.ipynb b/full-ifrs17-template/Constants/Consts.ipynb index 8dc84f8d..1ef5ee81 100644 --- a/full-ifrs17-template/Constants/Consts.ipynb +++ b/full-ifrs17-template/Constants/Consts.ipynb @@ -21,9 +21,8 @@ "var projectName = \"ifrs17ce\";", "\nvar environmentName = \"dev\";", "\nvar notebookName = \"CalculationEngine\";", - "\nvar calculationEngine = $\"#!import \\\"//{projectName}/{environmentName}/{notebookName}\\\"\";", - "\ncalculationEngine = $\"#!import \\\"../../ifrs17/CalculationEngine\\\"\";" + "\nvar calculationEngine = $\"#!import \\\"//{projectName}/{environmentName}/{notebookName}\\\"\";" ] } ] -} \ No newline at end of file +} From b8d6e886af0c70910b09a663fa0f39fcd83b2045 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Wed, 26 Oct 2022 08:29:26 +0200 Subject: [PATCH 31/38] implement feedback part 1 --- .../Test/SpecificationsFinancialPerformance.ipynb | 4 ++-- ifrs17/Report/ReportScopes.ipynb | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb index 6900ca96..7016fa12 100644 --- a/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb +++ b/full-ifrs17-template/Test/SpecificationsFinancialPerformance.ipynb @@ -192,8 +192,8 @@ "\n .WithQuerySource(DataSource)", "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", "\n .SliceColumnsBy(CurrencyGrouper(currencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .WithGridOptions( o => o.WithColumns(cols => cols.Modify(\"\", c => c.WithWidth(850))) with {GroupDefaultExpanded = 3, Height = 600})", - "\n .ToReport() with { Height = 600 }" + "\n .WithGridOptions( o => o.WithDefaultColumn( c => c.WithWidth(260) ) with {GroupDefaultExpanded = 3, Height = 900, OnGridReady = null} )", + "\n .ToReport()" ] }, { diff --git a/ifrs17/Report/ReportScopes.ipynb b/ifrs17/Report/ReportScopes.ipynb index 649caa08..d9344d3c 100644 --- a/ifrs17/Report/ReportScopes.ipynb +++ b/ifrs17/Report/ReportScopes.ipynb @@ -766,11 +766,11 @@ "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.NIC))", "\n .SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE2\" });", "\n ", - "\n private ReportVariable[] ClaimsIco => WrittenAndAccruals", - "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO)).ToArray();", + "\n private IDataCube ClaimsIco => WrittenAndAccruals", + "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.ICO)).ToDataCube();", "\n ", "\n IDataCube ClaimsIcoToIr => ClaimsIco.SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"IR2\" });", - "\n IDataCube ClaimsIcoToIse => Multiply(-1, ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", + "\n IDataCube ClaimsIcoToIse => (-1 * ClaimsIco).SelectToDataCube(v => v with { Novelty = Novelties.C, VariableType = \"ISE5\" });", "\n ", "\n IDataCube Expenses => WrittenAndAccruals", "\n .Where(x => GetStorage().GetHierarchy().Ancestors(x.AmountType, includeSelf: true).Any(x => x.SystemName == AmountTypes.AE))", From 3a07d9ade2f7b3f3c2b4a823dc18fa1c0affec17 Mon Sep 17 00:00:00 2001 From: UMueller1 <108468853+UMueller1@users.noreply.github.com> Date: Wed, 26 Oct 2022 09:05:36 +0200 Subject: [PATCH 32/38] Overview texts (#53) * Overview (Template), revised text * Reports of template with small adjustments * Overview IFRS17, some adjustments --- .../OverviewIFRS17Template.ipynb | 19 ++++++++++++++----- full-ifrs17-template/Report/Reports.ipynb | 14 ++++++++++---- ifrs17/OverviewCalculationEngine.ipynb | 14 ++++++++------ 3 files changed, 32 insertions(+), 15 deletions(-) diff --git a/full-ifrs17-template/OverviewIFRS17Template.ipynb b/full-ifrs17-template/OverviewIFRS17Template.ipynb index 7145abb7..026e24e4 100644 --- a/full-ifrs17-template/OverviewIFRS17Template.ipynb +++ b/full-ifrs17-template/OverviewIFRS17Template.ipynb @@ -28,7 +28,9 @@ "source": [ "# Introduction", "\n", - "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\nSystemorph's IFRS 17 Calculation Engine is a tool and a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts for **groups of insurance contracts** and other relevant parameters (Yield Curve, FX rates, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\n", + "\nSystemorph's Full IFRS 17 Template provides a complete example of input data and uses the Calculation Engine for the production of IFRS 17 results. Users can adapt this template to their own needs by changing the input data and calculating their own results.", "\n", "\nThis notebook provides an **overview** of Systemorph's Full IFRS 17 Template with brief introductions to all the main steps." ] @@ -41,6 +43,8 @@ "\n", "\nIFRS 17 is a new accounting standard for insurance contracts. The previous standard IFRS 4, which is based on nominal accounting, is replaced by the economic accounting standard IFRS 17.", "\n", + "\nExplanatory **videos** on **IFRS 17** and a **demo application** can be found on Systemorph's website. Some key points are repeated here briefly.", + "\n", "\nIFRS 17 deals with insurance contracts which are on the liability side of the balance sheet. Other accounting standards deal with other parts of the business, primarily IFRS 9 for invested assets.", "\n", "\nInsurance policies need to be allocated to homogeneous groups of insurance contracts (GICs) according to high-level principles established by the IFRS 17 standard, such as contract type, line of business, annual cohort etc. Insurers have some degree of freedom to optmize those GICs, as long as they respect the high-level principles.", @@ -60,8 +64,7 @@ "\n - Contractual Service Margin (CSM) and Loss Component (LC)", "\n - Liability for Remaining Coverage (LRC)", "\n - Liability for Incurred Claims (LIC)", - "\n - Financial Performance", - "\n - Accounting Events" + "\n - Financial Performance" ] }, { @@ -119,7 +122,7 @@ "\n", "\nThe structure of the [Actuals](./InputFormatDescription#actual), [Openings](./InputFormatDescription#opening) and [NominalCashflows](./InputFormatDescription#cashflow) files is explained in a special [notebook](./InputFormatDescription).", "\n", - "\nThe less usual option of having discounted instead of nominal cash flows in the input is also supported." + "\nThe less usual option of having discounted instead of nominal cash flows in the input is supported, but not a subject of this notebook in its current state." ] }, { @@ -128,7 +131,13 @@ "", "\n# Reports", "\n", - "\nThe production of reports is done by a notebook such as **[Reports](./Report/Reports#report-production)**." + "\nAll the reports are produced by running a notebook such as **[Reports](./Report/Reports#report-production)**. Some information on the reporting functionality can also be found there and in the final Reports section of [OverviewIFRS17](../IFRS17/OverviewIFRS17#reports)." + ] + }, + { + "cell_type": "markdown", + "source": [ + "" ] } ] diff --git a/full-ifrs17-template/Report/Reports.ipynb b/full-ifrs17-template/Report/Reports.ipynb index 1dc742bd..4caa201d 100644 --- a/full-ifrs17-template/Report/Reports.ipynb +++ b/full-ifrs17-template/Report/Reports.ipynb @@ -25,6 +25,12 @@ "\n" ] }, + { + "cell_type": "markdown", + "source": [ + "This is the notebook to be run for the production of all the reports." + ] + }, { "cell_type": "markdown", "source": [ @@ -110,8 +116,8 @@ "source": [ "# Use cases", "\n", - "\nFor demostration purposes we import data for 7 *Group of Insurance Contract* (GIC) and 4 *Group of Reinsurance Contract* (GRIC). ", - "\n
Data set consists in cashflows, actuals, and parameters.", + "\nFor demonstration purposes we import data for 7 *Group of Insurance Contract* (GIC) and 4 *Group of Reinsurance Contract* (GRIC). ", + "\n
The data set consists of cashflows, actuals, and parameters.", "\n", "\n" ] @@ -121,11 +127,11 @@ "source": [ "# Present Value", "\n", - "\nPresent values of the best estimate of future cashflows are shown here in an Analysis of Change report.", + "\nPresent values of the best-estimate future cashflows are shown here in an Analysis of Change report.", "\n", "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", - "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data.", + "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the order of the inputs corresponds to the order of the columns shown in the report to expand the data.", "\n", "\nAggregated values are displayed when the data has a finer granularity than the one selected by the report slice options." ] diff --git a/ifrs17/OverviewCalculationEngine.ipynb b/ifrs17/OverviewCalculationEngine.ipynb index 3045ed95..866c5502 100644 --- a/ifrs17/OverviewCalculationEngine.ipynb +++ b/ifrs17/OverviewCalculationEngine.ipynb @@ -20,7 +20,7 @@ { "cell_type": "markdown", "source": [ - "

IFRS17 Calculation Engine - an Overview

" + "

IFRS 17 Calculation Engine - an Overview

" ] }, { @@ -28,7 +28,7 @@ "source": [ "# Introduction", "\n", - "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\nSystemorph's IFRS 17 Calculation Engine is a tool and a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts for **groups of insurance contracts** and other relevant parameters (Yield Curve, FX rates, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", "\n", "\nThis notebook provides an **overview** of Systemorph's IFRS 17 Calculation Engine with brief introductions to all the main steps.", "\n", @@ -76,7 +76,7 @@ "\n", "\nThe IFRS 17 calculations are based on a well-defined **data model**. The data input files are set up according to the data model, and the data import and all the ensuing calculations up to the final report generation respect the data model.", "\n", - "\nThe IFRS 17 calculations start by importing data input files, and the more complex logic of the IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." + "\nThe IFRS 17 calculations start by importing data input files, and the more complex IFRS 17 Business Logic is defined in the [ImportScopes](./Import/ImportScopeCalculation#import-scope-calculation) notebook. This basis will later be used to calculate and generate different reports." ] }, { @@ -91,7 +91,7 @@ "\n", "\nThe [input files](#data-input-dim-nodes) ReportingNodes and especially DimensionsAndPartitions provide an overview of data structures actually used. Some dimensions are hierarchical, so some entries have parent entries.", "\n", - "\nMany abbreviations and acronyms used later in the documentation and the code are the **system names**, where the corresponding display names can be found together with the attributes." + "\nMany abbreviations and acronyms used later in the documentation and the code are the **system names**, where the corresponding display names can be found in the corresponding input files together with the attributes." ] }, { @@ -104,7 +104,9 @@ "\n", "\nHowever, the import as such is conducted by other notebooks which use the methods of ImportStorage and ImportScopeCalculation in a chain of notebook imports:", "\n", - "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) ", + "\nImportStorage --> ImportScopeCalculation --> [Importers](./Import/Importers#importers) --> [InitSystemorphBaseToMemory](./Initialization/InitSystemorphBaseToMemory#init-base-to-memory) --> [InitSystemorphToMemory](./Initialization/InitSystemorphToMemory#init-base-to-memory).", + "\n", + "\nThe latter two notebooks initialize and store the imported and derived data in memory for further usage. To store the data in a physical database, [InitSystemorphToDatabase](./Initialization/InitSystemorphToDatabase#init-to-database) can be employed.", "\n", "\nThe calculations of ImportScopeCalculation cover a large part of the IFRS 17 methodology and are explained in the section below." ] @@ -115,7 +117,7 @@ "", "\n# IFRS 17 Model Calculations", "\n", - "\nThe notebook **[ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation)** has all the calculations to be executed upon data import. The methods used are explained there with formulas. The centerpiece is the Analysis of Change (AoC) of the insurance business over one period (here: quarter). The formulas often use acronyms (system names) as explained in the [section](#data-input-dim-nodes) on *DimensionsAndPartitions*.", + "\nThe notebook **[ImportScopeCalculation](./Import/ImportScopeCalculation#import-scope-calculation)** has all the calculations to be executed upon data import. The methods used are explained there with formulas. The centerpiece is the Analysis of Change (AoC) of the insurance business over one period (here: quarter). The formulas often use acronyms (system names) as listed in the input file *DimensionsAndPartitions*.", "\n", "\nThe main concepts and parts of ImportScopeCalculation are listed here, with links.", "\n- Structure and sequence of the **[Analysis of Change (AoC)](./Import/ImportScopeCalculation#aoc-step-structure)** steps for the given period", From 2312bcbf71f6124d6c3b3729de9bf072b813980f Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Wed, 26 Oct 2022 14:38:27 +0200 Subject: [PATCH 33/38] finalized + hot fixes --- .../Test/IfrsVariablesTest.ipynb | 37 +++++++------------ ifrs17/Import/Importers.ipynb | 3 +- ifrs17/Utils/Extensions.ipynb | 18 ++++----- ifrs17/Utils/TestHelper.ipynb | 15 ++++---- 4 files changed, 32 insertions(+), 41 deletions(-) diff --git a/full-ifrs17-template/Test/IfrsVariablesTest.ipynb b/full-ifrs17-template/Test/IfrsVariablesTest.ipynb index 98187848..50a59c01 100644 --- a/full-ifrs17-template/Test/IfrsVariablesTest.ipynb +++ b/full-ifrs17-template/Test/IfrsVariablesTest.ipynb @@ -142,21 +142,11 @@ "\n var expectedNotComputed = expected.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(computed.Select(x => x.ToIdentityString()));", "\n var computedNotExpected = computed.Where(x => Math.Abs(x.Value) > BenchmarkPrecision).Select(x => x.ToIdentityString()).Except(expected.Select(x => x.ToIdentityString()));", "\n if (expectedNotComputed.Any())", - "\n {", "\n foreach (var error in expectedNotComputed)", - "\n {", - "\n var message = error.ToIdentityString();", - "\n errors.Add(new BenchmarkTestResult(\"Extra expected variable for: \"+ message));", - "\n }", - "\n }", + "\n errors.Add(new BenchmarkTestResult(\"Extra expected variable for: \" + error));", "\n if (computedNotExpected.Any())", - "\n {", "\n foreach (var error in computedNotExpected)", - "\n {", - "\n var message = error.ToIdentityString();", - "\n errors.Add(new BenchmarkTestResult(\"Extra computed variable for: \"+ message));", - "\n }", - "\n }", + "\n errors.Add(new BenchmarkTestResult(\"Extra computed variable for: \" + error));", "\n ", "\n var misMatchedVariables = expected.Concat(computed).AggregateOver().Where(x => Math.Abs(x.Value) > BenchmarkPrecision);", "\n if (misMatchedVariables.Any())", @@ -211,13 +201,8 @@ { "cell_type": "code", "source": [ - "var errorList = new List();" - ] - }, - { - "cell_type": "code", - "source": [ - "foreach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", + "var errorList = new List();", + "\nforeach (var g in bmFiles.GroupBy(x => (ReportingNode: x.ReportingNode, Year: x.Year, Month: x.Month)))", "\n{", "\n var reportingNode = g.Key.ReportingNode;", "\n var year = g.Key.Year;", @@ -244,13 +229,13 @@ "\n var mainTab = bmDataTable.Tables[Main].Rows.First();", "\n if(!ValidateMainTab(mainTab, reportingNode, year, month))", "\n throw new Exception(\"Metadata and main tab of the Benchmark are different.\");", - "\n ", + "\n", "\n var bmTableName = bmDataTable.Tables.Single(x => x.TableName != Main).TableName;", "\n var bmVariables = bmDataTable.Tables[bmTableName].Rows.Select(x => CreateVariable(x, partition));", - "\n ", + "\n", "\n //Get the computed Data", "\n var computedVariables = computedVariablesByEstimateType.TryGetValue(bmTableName, out var ret) ? ret : Enumerable.Empty();", - "\n ", + "\n", "\n if(!computedVariables.Any()) ", "\n errorList.Add(new BenchmarkTestResult(\"No variables are computed for EstimateType: \" + bmTableName, 0, 0));", "\n //CompareAgainstBm", @@ -264,7 +249,13 @@ { "cell_type": "code", "source": [ - "errorList.Count().Should().Be(0)" + "errorList.Count().Should().Be(0);" + ] + }, + { + "cell_type": "code", + "source": [ + "errorList" ] }, { diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index d0f1071f..4b9945ad 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -970,7 +970,8 @@ "\n AmountType = amountType,", "\n EstimateType = estimateType,", "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Value = Multiply(GetSign((aocType, amountType, estimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache), datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()),", + "\n Value = GetSign((aocType, amountType, estimateType, dataNodeData.IsReinsurance), parsingStorage.HierarchyCache) ", + "\n * datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble(),", "\n };", "\n return item;", "\n }, ImportFormats.Actual", diff --git a/ifrs17/Utils/Extensions.ipynb b/ifrs17/Utils/Extensions.ipynb index 9e0adcb9..0eb9c443 100644 --- a/ifrs17/Utils/Extensions.ipynb +++ b/ifrs17/Utils/Extensions.ipynb @@ -123,17 +123,15 @@ "cell_type": "code", "source": [ "using System.Text;", - "\npublic static string ToIdentityString(this T v)", - "\n where T : class", + "\npublic static string ToIdentityString(this T v) where T : class", "\n{", - "\n StringBuilder sb = new StringBuilder();", - "\n var propertyInfos = v.GetType()", - "\n .GetProperties()", - "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", - "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", - "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", - "\n", - "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", + "\n StringBuilder sb = new StringBuilder();", + "\n var propertyInfos = v.GetType()", + "\n .GetProperties()", + "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", + "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", + "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \")).ToArray();", + "\n return propertyInfos.Count() == 0? v.ToString() : propertyInfos.Select(p => p.ToString()).ToArray().Last();", "\n}" ] }, diff --git a/ifrs17/Utils/TestHelper.ipynb b/ifrs17/Utils/TestHelper.ipynb index a627b204..9a46850e 100644 --- a/ifrs17/Utils/TestHelper.ipynb +++ b/ifrs17/Utils/TestHelper.ipynb @@ -98,14 +98,15 @@ { "cell_type": "code", "source": [ - "public static ReportBuilder WithGridOptionsForIfrsVariable", - "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", + "public static Systemorph.Vertex.Pivot.Reporting.Builder.ReportBuilder WithGridOptionsForIfrsVariable", + "\n(this Systemorph.Vertex.Pivot.Builder.PivotBuilder reportBuilder, int reportHeight = 650)", "\n{", - "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", - "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", - "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", - "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", - "\n );", + "\n return reportBuilder.WithGridOptions(go => ", + "\n go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", + "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", + "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", + "\n );", "\n}" ] } From 22bd497fc54df91c6cba7008bf0b1d5f682766ad Mon Sep 17 00:00:00 2001 From: Davide Colleoni Date: Wed, 26 Oct 2022 16:17:15 +0200 Subject: [PATCH 34/38] ReportGridOptions --- ifrs17/Report/ReportConfigurationAndUtils.ipynb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ifrs17/Report/ReportConfigurationAndUtils.ipynb b/ifrs17/Report/ReportConfigurationAndUtils.ipynb index d482e339..39128784 100644 --- a/ifrs17/Report/ReportConfigurationAndUtils.ipynb +++ b/ifrs17/Report/ReportConfigurationAndUtils.ipynb @@ -32,11 +32,12 @@ { "cell_type": "code", "source": [ - "using Systemorph.Vertex.Pivot.Reporting.Builder;", + "using Systemorph.Vertex.Pivot.Builder;", + "\nusing Systemorph.Vertex.Pivot.Reporting.Builder;", "\nusing System.Collections.Immutable;", "\n", "\npublic static DataCubeReportBuilder, TVariable, TVariable ,TVariable> ReportGridOptions(", - "\n this DataCubeReportBuilder, TVariable, TVariable, TVariable> reportBuilder,", + "\n this DataCubePivotBuilder, TVariable, TVariable, TVariable> reportBuilder,", "\n int reportHeight = 700,", "\n int valueColumnWidth = 250,", "\n int headerColumnWidth = 250,", From 5a143ffa97822de1e778c5cac6d2fb9bcd334d42 Mon Sep 17 00:00:00 2001 From: Andrea Muolo Date: Thu, 27 Oct 2022 11:48:42 +0200 Subject: [PATCH 35/38] final fixes and feedback implementations --- .../Initialization/InitSystemorphToMemory.ipynb | 2 +- full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb | 6 +++--- ifrs17/DataModel/DataStructure.ipynb | 8 ++++---- ifrs17/Import/Importers.ipynb | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb index af8c5cf1..c9eb277e 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb @@ -82,7 +82,7 @@ { "cell_type": "code", "source": [ - "await UploadSimpleValueAsync(\"../Files/900.TransactionalData/SimpleValue_CH_2020_12.csv\")" + "//await UploadSimpleValueAsync(\"../Files/900.TransactionalData/SimpleValue_CH_2020_12.csv\") TODO: missing benchmarks" ] }, { diff --git a/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb index f82db019..e0b58e97 100644 --- a/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb +++ b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb @@ -150,7 +150,7 @@ "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", - "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar tables = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet;", "\nvar mainCols = new[]{nameof(PartitionByReportingNode.ReportingNode)};", "\nvar portfolioCols = new[]{nameof(Portfolio.SystemName),nameof(Portfolio.DisplayName),nameof(Portfolio.ContractualCurrency),", "\n nameof(Portfolio.LineOfBusiness),nameof(Portfolio.OciType),nameof(Portfolio.ValuationApproach)};", @@ -236,7 +236,7 @@ "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", - "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar tables = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet;", "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", "\n nameof(PartitionByReportingNodeAndPeriod.Year),", "\n nameof(PartitionByReportingNodeAndPeriod.Month)};", @@ -316,7 +316,7 @@ "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", - "\nvar tables = await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync();", + "\nvar tables = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet;", "\nvar mainCols = new[]{nameof(PartitionByReportingNodeAndPeriod.ReportingNode),", "\n nameof(PartitionByReportingNodeAndPeriod.Year),", "\n nameof(PartitionByReportingNodeAndPeriod.Month),", diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index 1b74b293..78851b13 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -43,16 +43,16 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Arithmetics,1.5.1\"", + "#r \"nuget:Systemorph.Arithmetics,1.5.4\"", "\n#r \"nuget:Systemorph.Workspace,1.5.0\"", - "\n#r \"nuget:Systemorph.Scopes,1.5.1\"", + "\n#r \"nuget:Systemorph.Scopes,1.5.2\"", "\n#r \"nuget:Systemorph.Import,1.5.0\"", - "\n#r \"nuget:Systemorph.Test,1.5.1\"", + "\n#r \"nuget:Systemorph.Test,1.5.2\"", "\n#r \"nuget:Systemorph.Export,1.5.0\"", "\n#r \"nuget:Systemorph.DataSetReader,1.5.0\"", "\n#r \"nuget:Systemorph.DataSource,1.5.0\"", "\n#r \"nuget:Systemorph.DataSource.Conversions,1.5.0\"", - "\n#r \"nuget:Systemorph.Reporting,1.5.1\"", + "\n#r \"nuget:Systemorph.Reporting,1.5.2\"", "\n#r \"nuget:Systemorph.DomainDesigner,1.5.0\"" ] }, diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 5553680f..6be43097 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -1066,8 +1066,8 @@ "\n EstimateType = estimateType,", "\n EconomicBasis = economicBasis,", "\n Partition = parsingStorage.TargetPartitionByReportingNodeAndPeriod.Id,", - "\n Value = //GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", - "\n 1 // TODO, we need to adjust the inputs to have the correct sign, so that the default GetSign returns 1.", + "\n Value = GetSign((aocStep.AocType, amountType, estimateType, parsingStorage.IsDataNodeReinsurance(dataNode)), parsingStorage.HierarchyCache)", + "\n //1 // TODO, we need to adjust the inputs to have the correct sign, so that the default GetSign returns 1.", "\n * datarow.Field(nameof(IfrsVariable.Value)).CheckStringForExponentialAndConvertToDouble()", "\n };", "\n return iv;", From a864f0f29d14b17b62fc49bd55dbbeb8878257e1 Mon Sep 17 00:00:00 2001 From: Davide Colleoni <103409906+dcolleoni@users.noreply.github.com> Date: Mon, 31 Oct 2022 14:39:03 +0100 Subject: [PATCH 36/38] Interactive reports (#58) * Ifrs17ReportScopes * wip * latest * add other reports * start with pv * filter does not work * clean up * clean up reports * clean up * typo * move it ce * remove partition set * adjust reporting * test readme with relative path for image * back to absolute path - bug in the portal - * wip * settle with identities * some more docs * adding rn and period selector --- .../Files/DimensionsAndPartitions.csv | 3 - full-ifrs17-template/Report/Reports.ipynb | 302 ++++++----------- .../Test/SpecificationsSetup.ipynb | 2 +- .../Test/SpecificationsTechnicalMargin.ipynb | 10 +- ifrs17/CalculationEngine.ipynb | 8 +- ifrs17/DataModel/DataStructure.ipynb | 9 - ifrs17/Import/ImportScopeCalculation.ipynb | 4 +- .../Report/ReportConfigurationAndUtils.ipynb | 7 +- ifrs17/Report/ReportMutableScopes.ipynb | 311 ++++++++++++++++++ ifrs17/Report/ReportScopes.ipynb | 10 +- 10 files changed, 442 insertions(+), 224 deletions(-) create mode 100644 ifrs17/Report/ReportMutableScopes.ipynb diff --git a/full-ifrs17-template/Files/DimensionsAndPartitions.csv b/full-ifrs17-template/Files/DimensionsAndPartitions.csv index bcfe9d1d..4f648680 100644 --- a/full-ifrs17-template/Files/DimensionsAndPartitions.csv +++ b/full-ifrs17-template/Files/DimensionsAndPartitions.csv @@ -228,9 +228,6 @@ CH,00000000-0000-0000-0000-000000000001,,,,,,,,,, ReportingNode,Year,Month,Id,,,,,,,, CH,2020,12,10000000-0000-0000-0000-000000000000,,,,,,,, CH,2021,3,20000000-0000-0000-0000-000000000000,,,,,,,, -CH,2021,9,30000000-0000-0000-0000-000000000000,,,,,,,, -CH,2021,12,35000000-0000-0000-0000-000000000000,,,,,,,, -CH,2022,3,40000000-0000-0000-0000-000000000000,,,,,,,, ,,,,,,,,,,, @@ProjectionConfiguration,,,,,,,,,,, SystemName,DisplayName,Shift,TimeStep,,,,,,,, diff --git a/full-ifrs17-template/Report/Reports.ipynb b/full-ifrs17-template/Report/Reports.ipynb index 4caa201d..23a3804b 100644 --- a/full-ifrs17-template/Report/Reports.ipynb +++ b/full-ifrs17-template/Report/Reports.ipynb @@ -28,26 +28,18 @@ { "cell_type": "markdown", "source": [ - "This is the notebook to be run for the production of all the reports." - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Infrastructure and Configuration" + "For demonstration purposes we import here data for 7 *Group of Insurance Contract* (GIC) and 4 *Group of Reinsurance Contract* (GRIC) - the import is triggered in the [Set up data and configuration](#set-up-data-and-configuration).", + "\n
The imported data set consists of cashflows, actuals, and parameters for two consecutive periods (Year 2020-Quarter 4 and Year 2021-Quarter 1)", + "\n
Input files can be found in the **File** directory. You are invited to change them or upload your own. ", + "\n
For simplicity, we import the same transactional data for all GICs and GRICs. Each *Group of Contracts* produces different figures due to differences in parameters such as *Liability Type*, *Oci type* or *Premium allocation factor* to Contractual Service Margin.", + "\n", + "\nFollow the instructions below for a guided interaction with the reports." ] }, { "cell_type": "markdown", "source": [ - "## Initialize data" - ] - }, - { - "cell_type": "code", - "source": [ - "/* DataSource is configured and connected to real database */", - "\n//#!eval-notebook \"../Database/Configure\"" + "# Set up data and configuration" ] }, { @@ -59,77 +51,18 @@ { "cell_type": "code", "source": [ - "Workspace.InitializeFrom(DataSource);" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Imports and Configurations" - ] - }, - { - "cell_type": "code", - "source": [ - "var reportStorage = new ReportStorage(Workspace, Report);", - "\nawait reportStorage.InitializeReportIndependentCacheAsync();", - "\nvar mostRecentPartition = (await Workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last();", - "\nvar reportingNodeRoot = (await Workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName;", - "\nawait reportStorage.InitializeAsync((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);", - "\nvar identities = reportStorage.GetIdentities((mostRecentPartition.Year, mostRecentPartition.Month), reportingNodeRoot, null, CurrencyType.Contractual);" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Calling Scope" - ] - }, - { - "cell_type": "code", - "source": [ - "var universe = Scopes.ForSingleton().WithStorage(reportStorage).ToScope();" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Report Settings and Storage Update" - ] - }, - { - "cell_type": "code", - "source": [ - "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", - "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", - "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", - "\n ;", - "\n", - "\nawait reportStorage.InitializeAsync(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);", - "\nidentities = reportStorage.GetIdentities(Args.Period, Args.ReportingNode, Args.Scenario, Args.CurrencyType);" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Use cases", - "\n", - "\nFor demonstration purposes we import data for 7 *Group of Insurance Contract* (GIC) and 4 *Group of Reinsurance Contract* (GRIC). ", - "\n
The data set consists of cashflows, actuals, and parameters.", - "\n", - "\n" + "Workspace.InitializeFrom(DataSource);", + "\nifrs17Report.Reset(Workspace)" ] }, { "cell_type": "markdown", "source": [ - "# Present Value", + "# Best Estimate", "\n", - "\nPresent values of the best-estimate future cashflows are shown here in an Analysis of Change report.", + "\nPresent values of the [best-estimate](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#best-estimate) future cashflows are shown here in an Analysis of Change report.", "\n", - "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", + "\nThe granularity of the reported figures can be modified by changing the Column Slices options.", "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the order of the inputs corresponds to the order of the columns shown in the report to expand the data.", "\n", @@ -139,166 +72,157 @@ { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedBestEstimate + universe.GetScopes(identities).Aggregate().CurrentBestEstimate)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\", \"EconomicBasis\") //\"GroupOfContract\"", - "\n .ReportGridOptions()", - "\n .ToReport()" + "var pvReport = ifrs17Report.PresentValues;", + "\npvReport.ReportingNode = \"CH\";", + "\npvReport.ReportingPeriod = (2021, 3);", + "\npvReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\npvReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.2\"),(\"LiabilityType\", \"LIC\") }", + "\n(await pvReport.ToReportAsync) with {Height = 720}" ] }, { "cell_type": "markdown", "source": [ - "# Risk Adjustment" + "# Risk Adjustment", + "\n", + "\nPresent values of the [risk adjustment](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#risk-adjustment) future cashflows are shown here.", + "\n", + "\nFilters can be applied to report to isolate a sub-set of the data. They can be used in conjuction to the Slice options. For example, filtering **EconomicBasis** Locked-in together with a slice on the **GroupOfContract** allows to analyse the risk adjustment figures computed with the yield curve at inception for all Group of Contracts." ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LockedRiskAdjustment + universe.GetScopes(identities).Aggregate().CurrentRiskAdjustment)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"EconomicBasis\", \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions()", - "\n .ToReport()" + "var raReport = ifrs17Report.RiskAdjustments;", + "\nraReport.ColumnSlices = new string[]{};//\"GroupOfContract\"", + "\nraReport.DataFilter = null;//new [] {(\"GroupOfContract\", \"DT1.2\")};", + "\n(await raReport.ToReportAsync) with {Height = 800}" ] }, { "cell_type": "markdown", "source": [ - "# Actuals" + "# Written Actuals", + "\n", + "\n[Written Actuals](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#written-accrual-deferral) are shown here. ", + "\n", + "\nIn this case, the analysis of change view is replaced with a default slice by the **AmountTypes**. Only the amount type with non zero value are displayed. " ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Written", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"AmountType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 450)", - "\n .ToReport()" + "var writtenActualReport = ifrs17Report.WrittenActuals;", + "\nwrittenActualReport.ColumnSlices = new string[]{};//\"GroupOfContract\"", + "\nwrittenActualReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await writtenActualReport.ToReportAsync) with {Height = 400}" ] }, { "cell_type": "markdown", "source": [ - "## Advance, Overdue Actuals" + "## Advance, Overdue Actuals", + "\n", + "\nActuals payed in [Advance](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#written-accrual-deferral)", + "\nor [Overdue](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#written-accrual-deferral) are shown here together in a simplified Analysis of Change. " ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Advance + universe.GetScopes(identities).Aggregate().Overdue)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions(reportHeight: 400)", - "\n .ToReport()" + "var accrualActualReport = ifrs17Report.AccrualActuals;", + "\naccrualActualReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\naccrualActualReport.DataFilter = null;//new [] {(\"GroupOfContract\", \"DT2.1\")};", + "\n(await accrualActualReport.ToReportAsync) with {Height = 400}" ] }, { "cell_type": "markdown", "source": [ - "## Deferrable Actuals" + "## Deferrable Actuals", + "\n", + "\n[Deferrable Actuals](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#written-accrual-deferral) are shown here. Amortization of the deferrable amount is computed using the Coverage Unit pattern. " ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Deferrals", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 400)", - "\n .ToReport()" + "var deferrableActualReport = ifrs17Report.DeferralActuals;", + "\ndeferrableActualReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\ndeferrableActualReport.DataFilter = null;//new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await deferrableActualReport.ToReportAsync) with {Height = 400}" ] }, { "cell_type": "markdown", "source": [ - "# Fulfilment Cashflow" + "# Fulfilment Cashflow", + "\n", + "\nPresent Value of the [Fulfilment Cashflow](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#fulfillment-cashflows) are shown here. ", + "\n
The individual contributions from Best Estimate and Risk Adjustment can be visualized slicing by **EstimateType**" ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().Fcf ", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")//, \"EstimateType\")//, \"AmountType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" + "var fulfillmentCashflowsReport = ifrs17Report.FulfillmentCashflows;", + "\nfulfillmentCashflowsReport.ColumnSlices = new string[]{};//\"EstimateType\"", + "\nfulfillmentCashflowsReport.DataFilter = null;// new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await fulfillmentCashflowsReport.ToReportAsync) with {Height = 750}" ] }, { "cell_type": "markdown", "source": [ - "# Actuarial Experience Adjustment" + "# Actuarial Experience Adjustment", + "\n", + "\nA comparison between [Written Actual](#written-actual) and the Releases of the [Best Estimate](#present-value) is reported in the [Actuarial Experience Adjustment](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#experience-adjustment)." ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().ActuarialExperienceAdjustment", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"AmountType\" )//\"LiabilityType\", \"EstimateType\")", - "\n .ReportGridOptions(reportHeight: 300, headerColumnWidth: 300)", - "\n .ToReport() " + "var experienceAdjustmentsReport = ifrs17Report.ExperienceAdjustments;", + "\nexperienceAdjustmentsReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\nexperienceAdjustmentsReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await experienceAdjustmentsReport.ToReportAsync) with {Height = 300}" ] }, { "cell_type": "markdown", "source": [ - "# LRC Technical Margin" + "# LRC Technical Margin", + "\n", + "\nIn the [Technical Margin](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#technical-margin) report we present a unified view on the figures that are allocated to either Contractual Service Margin or to Loss Component. ", + "\n
The Analysis of Change is expanded with few more steps such as **Experience Adjustment** and **Amortization**." ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().LrcTechnicalMargin", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 600)", - "\n .ToReport()" + "var technicalMarginsReport = ifrs17Report.TechnicalMargins;", + "\ntechnicalMarginsReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\ntechnicalMarginsReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await technicalMarginsReport.ToReportAsync) with {Height = 600}" ] }, { "cell_type": "markdown", "source": [ - "# Contractual Service Margin / Loss Component / Loss Recovery Component" + "# Contractual Service Margin / Loss Component / Loss Recovery Component", + "\n", + "\nThe Contractual Service Margin (CSM) / Loss Component (LC) / Loss Recovery Component (LR) [report](https://portal.systemorph.cloud/project/ifrs17ce/env/dev/Report/ReportScopes#technical-margin) are here shown side by side as the allocation to profit or loss is done at each step of the Analysis of Change. ", + "\n", + "\nA default slice by EstimateType - which distinguish between CSM, LC and LR contributions - is automatically enforced. " ] }, { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Csm + universe.GetScopes(identities).Aggregate().Lc + universe.GetScopes(identities).Aggregate().Loreco)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" + "var allocatedTechnicalMarginsReport = ifrs17Report.AllocatedTechnicalMargins;", + "\nallocatedTechnicalMarginsReport.ColumnSlices = new string[]{\"GroupOfContract\", \"EstimateType\"};//\"GroupOfContract\", \"AmountType\"", + "\nallocatedTechnicalMarginsReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await allocatedTechnicalMarginsReport.ToReportAsync) with {Height = 700}" ] }, { @@ -310,14 +234,10 @@ { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LrcActuarial)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"LiabilityType\",\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" + "var actuarialLrcReport = ifrs17Report.ActuarialLrc;", + "\nactuarialLrcReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\nactuarialLrcReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await actuarialLrcReport.ToReportAsync) with {Height = 750}" ] }, { @@ -329,14 +249,10 @@ { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lrc)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType),\"GroupOfContract\", \"EstimateType\")", - "\n .ReportGridOptions(300)", - "\n .ToReport()" + "var lrcReport = ifrs17Report.Lrc;", + "\nlrcReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\nlrcReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await lrcReport.ToReportAsync) with {Height = 250}" ] }, { @@ -348,14 +264,10 @@ { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().LicActuarial)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions()", - "\n .ToReport()" + "var actuarialLicReport = ifrs17Report.ActuarialLic;", + "\nactuarialLicReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\nactuarialLicReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await actuarialLicReport.ToReportAsync) with {Height = 750}" ] }, { @@ -367,14 +279,10 @@ { "cell_type": "code", "source": [ - "Report.ForDataCube((universe.GetScopes(identities).Aggregate().Lic)", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), /*\"GroupOfContract\",*/ \"EstimateType\")", - "\n .ReportGridOptions(300)", - "\n .ToReport()" + "var licReport = ifrs17Report.Lic;", + "\nlicReport.ColumnSlices = new string[]{};//\"GroupOfContract\", \"AmountType\"", + "\nlicReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await licReport.ToReportAsync) with {Height = 250}" ] }, { @@ -388,14 +296,10 @@ { "cell_type": "code", "source": [ - "Report.ForDataCube(universe.GetScopes(identities).Aggregate().FinancialPerformance", - "\n //.Filter((\"GroupOfContract\", \"DT1.1\"))", - "\n )", - "\n .WithQuerySource(DataSource)", - "\n .SliceRowsBy(\"VariableType\", \"EstimateType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\")", - "\n .ReportGridOptions(reportHeight: 900, headerColumnWidth: 500, groupDefaultExpanded: 3)", - "\n .ToReport()" + "var financialPerformanceReport = ifrs17Report.FinancialPerformance;", + "\nfinancialPerformanceReport.ColumnSlices = new string[]{};//\"GroupOfContract\"", + "\nfinancialPerformanceReport.DataFilter = null; //new [] {(\"GroupOfContract\", \"DT1.1\")};", + "\n(await financialPerformanceReport.ToReportAsync) with { Height = 900, GroupDefaultExpanded = 3}" ] }, { diff --git a/full-ifrs17-template/Test/SpecificationsSetup.ipynb b/full-ifrs17-template/Test/SpecificationsSetup.ipynb index 335f1ca3..b9f1e2f4 100644 --- a/full-ifrs17-template/Test/SpecificationsSetup.ipynb +++ b/full-ifrs17-template/Test/SpecificationsSetup.ipynb @@ -90,7 +90,7 @@ "\n Value = scope.Value,", "\n Partition = scope.GetStorage().TargetPartition };", "\n", - "\npublic static IfrsVariable FromCsmToIfrsVariable(this ContractualServiceMaring scope)", + "\npublic static IfrsVariable FromCsmToIfrsVariable(this ContractualServiceMargin scope)", "\n => new IfrsVariable{ EstimateType = scope.EstimateType, ", "\n DataNode = scope.Identity.DataNode, ", "\n AocType = scope.Identity.AocType, ", diff --git a/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb index 43191eec..f8cc0f73 100644 --- a/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb +++ b/full-ifrs17-template/Test/SpecificationsTechnicalMargin.ipynb @@ -1121,7 +1121,7 @@ { "cell_type": "code", "source": [ - "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", + "var computedCSM_BoP_I = Test.GetScope(id_BoP_I).Value;", "\nvar computedLC_BoP_I = Test.GetScope(id_BoP_I).Value;" ] }, @@ -1196,7 +1196,7 @@ { "cell_type": "code", "source": [ - "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", + "var computedCSM_MC_I = Test.GetScope(id_MC_I).Value;", "\nvar computedLC_MC_I = Test.GetScope(id_MC_I).Value;" ] }, @@ -1447,7 +1447,7 @@ { "cell_type": "code", "source": [ - "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", + "var computedCSM_CL_C = Test.GetScope(id_CL_C).Value;", "\nvar computedLC_CL_C = Test.GetScope(id_CL_C).Value;" ] }, @@ -1644,7 +1644,7 @@ { "cell_type": "code", "source": [ - "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", + "var computedCSM_EoP_C = Test.GetScope(id_EoP_C).Value;", "\nvar computedLC_EoP_C = Test.GetScope(id_EoP_C).Value;" ] }, @@ -1694,7 +1694,7 @@ { "cell_type": "code", "source": [ - "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", + "var csm = allIdentitiesWoLic.SelectMany(id => Test.GetScope(id).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => x.FromCsmToIfrsVariable())).ToArray();" ] diff --git a/ifrs17/CalculationEngine.ipynb b/ifrs17/CalculationEngine.ipynb index d6a34d5e..0936fa66 100644 --- a/ifrs17/CalculationEngine.ipynb +++ b/ifrs17/CalculationEngine.ipynb @@ -19,12 +19,18 @@ "cell_type": "code", "source": [ "#!import \"DataModel/DataStructure\"", - "\n#!import \"Report/ReportScopes\"", + "\n#!import \"Report/ReportMutableScopes\"", "\n#!import \"Import/Importers\"", "\n#!import \"Export/ExportConfiguration\"", "\n#!import \"Utils/TestHelper\"", "\n#!import \"Utils/ImportCalculationMethods\"" ] + }, + { + "cell_type": "code", + "source": [ + "var ifrs17Report = new Ifrs17Reports(Workspace, Scopes, Report);" + ] } ] } \ No newline at end of file diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index 78851b13..4c88153d 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -1056,15 +1056,6 @@ "\n- OCI Type" ] }, - { - "cell_type": "markdown", - "source": [ - "TODOs:", - "\n
    ", - "\n
  • Remove Scenario from Partition and include it as simple property (see Year, Month). Introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", - "\n
" - ] - }, { "cell_type": "code", "source": [ diff --git a/ifrs17/Import/ImportScopeCalculation.ipynb b/ifrs17/Import/ImportScopeCalculation.ipynb index f172092b..629d2d40 100644 --- a/ifrs17/Import/ImportScopeCalculation.ipynb +++ b/ifrs17/Import/ImportScopeCalculation.ipynb @@ -1784,7 +1784,7 @@ { "cell_type": "code", "source": [ - "public interface ContractualServiceMaring : IScope", + "public interface ContractualServiceMargin : IScope", "\n{", "\n [NotVisible]string EstimateType => EstimateTypes.C;", "\n ", @@ -1951,7 +1951,7 @@ "\n ", "\n IEnumerable Csms => GetStorage().DataNodeDataBySystemName[Identity.DataNode].LiabilityType == LiabilityTypes.LIC", "\n ? Enumerable.Empty()", - "\n : GetScope(Identity).RepeatOnce()", + "\n : GetScope(Identity).RepeatOnce()", "\n .Where(x => Math.Abs(x.Value) >= Precision)", "\n .Select(x => new IfrsVariable{ EstimateType = x.EstimateType,", "\n DataNode = x.Identity.DataNode,", diff --git a/ifrs17/Report/ReportConfigurationAndUtils.ipynb b/ifrs17/Report/ReportConfigurationAndUtils.ipynb index 39128784..e380125c 100644 --- a/ifrs17/Report/ReportConfigurationAndUtils.ipynb +++ b/ifrs17/Report/ReportConfigurationAndUtils.ipynb @@ -102,7 +102,6 @@ "source": [ "public static async Task> QueryReportVariablesAsync(this IWorkspace workspace, (int Year, int Month, string ReportingNode, string Scenario) args ) {", "\n ", - "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario });", "\n await workspace.Partition.SetAsync(new { ReportingNode = args.ReportingNode, Scenario = args.Scenario, Year = args.Year, Month = args.Month });", "\n ", "\n return await workspace.Query()", @@ -146,6 +145,12 @@ "\n .ToArrayAsync();", "\n}" ] + }, + { + "cell_type": "code", + "source": [ + "" + ] } ] } \ No newline at end of file diff --git a/ifrs17/Report/ReportMutableScopes.ipynb b/ifrs17/Report/ReportMutableScopes.ipynb new file mode 100644 index 00000000..2cd03b41 --- /dev/null +++ b/ifrs17/Report/ReportMutableScopes.ipynb @@ -0,0 +1,311 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "", + "\n

Report Mutable Scopes

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This notebook contains the set up of mutable scopes used to achieve high interactivity with reports." + ] + }, + { + "cell_type": "markdown", + "source": [ + "# References", + "\nLibraries and other notebooks which are needed for this notebook are imported below." + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"ReportScopes\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Mutable Scope" + ] + }, + { + "cell_type": "markdown", + "source": [ + "The IIfrs17Report mutable scope is created with applicabilities to control how the data for each individual report is retrieved from the [report scopes](./ReportScopes)" + ] + }, + { + "cell_type": "code", + "source": [ + "public interface ReportUniverse : IMutableScopeWithStorage{}" + ] + }, + { + "cell_type": "code", + "source": [ + "[InitializeScope(nameof(InitAsync))]", + "\npublic interface IIfrs17Report : IMutableScope {", + "\n // Infrastructure", + "\n protected IWorkspace workspace => GetStorage().Workspace;", + "\n protected Systemorph.Vertex.Pivot.Builder.Interfaces.IPivotFactory report => GetStorage().Report;", + "\n", + "\n static ApplicabilityBuilder ScopeApplicabilityBuilder(ApplicabilityBuilder builder) =>", + "\n builder.ForScope(s => s.WithApplicability(x => x.Identity == nameof(PvReport))", + "\n .WithApplicability(x => x.Identity == nameof(RaReport))", + "\n .WithApplicability(x => x.Identity == nameof(WrittenReport))", + "\n .WithApplicability(x => x.Identity == nameof(AccrualReport))", + "\n .WithApplicability(x => x.Identity == nameof(DeferralReport))", + "\n .WithApplicability(x => x.Identity == nameof(FcfReport))", + "\n .WithApplicability(x => x.Identity == nameof(ExpAdjReport))", + "\n .WithApplicability(x => x.Identity == nameof(TmReport))", + "\n .WithApplicability(x => x.Identity == nameof(CsmReport))", + "\n .WithApplicability(x => x.Identity == nameof(ActLrcReport))", + "\n .WithApplicability(x => x.Identity == nameof(LrcReport))", + "\n .WithApplicability(x => x.Identity == nameof(ActLicReport))", + "\n .WithApplicability(x => x.Identity == nameof(LicReport))", + "\n .WithApplicability(x => x.Identity == nameof(FpReport))", + "\n );", + "\n", + "\n // Basic mutable properties", + "\n (int Year, int Month) ReportingPeriod { get; set; }", + "\n int Year => ReportingPeriod.Year;", + "\n int Month => ReportingPeriod.Month;", + "\n string ReportingNode { get; set; }", + "\n string Scenario { get; set; }", + "\n CurrencyType CurrencyType { get; set; }", + "\n ", + "\n ((int Year, int Month) ReportingPeriod, string ReportingNode, string Scenario, CurrencyType) ShowSettings => (ReportingPeriod, ReportingNode, Scenario, CurrencyType);", + "\n ", + "\n // Slice and Dice", + "\n IEnumerable RowSlices { get; set; }", + "\n protected string[] defaultRowSlices => new string[] { };", + "\n protected string[] rowSlices => RowSlices is null ? defaultRowSlices : defaultRowSlices.Concat(RowSlices).ToArray();", + "\n", + "\n IEnumerable ColumnSlices { get; set; }", + "\n protected string[] defaultColumnSlices => new string[] { };", + "\n protected string[] columnSlices => ColumnSlices is null ? defaultColumnSlices : defaultColumnSlices.Where(cs => !ColumnSlices.Contains(cs)).Concat(ColumnSlices).ToArray(); //I can't put a slice before defaultSlices !!!", + "\n protected HashSet<(ReportIdentity, CurrencyType)> GetIdentities() => GetStorage().GetIdentities(ReportingPeriod, ReportingNode, Scenario, CurrencyType);", + "\n ", + "\n // Filter", + "\n IEnumerable<(string filterName, string filterValue)> DataFilter { get; set; }", + "\n protected (string filterName, object filterValue)[] dataFilter => (DataFilter is null ? Enumerable.Empty<(string, object)>() : DataFilter.Select(x => (x.filterName, (object)x.filterValue))).ToArray();", + "\n", + "\n // Scope Initialization", + "\n async Task InitAsync() {", + "\n var mostRecentPartition = (await workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last(); ", + "\n ", + "\n ReportingPeriod = (mostRecentPartition.Year, mostRecentPartition.Month);", + "\n ReportingNode = (await workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName; // TODO: change once user permissions are available", + "\n Scenario = null;", + "\n CurrencyType = CurrencyType.Contractual;", + "\n await GetStorage().InitializeReportIndependentCacheAsync();", + "\n }", + "\n public IDataCube GetDataCube() => default;", + "\n protected int headerColumnWidthValue => 250;", + "\n private async Task GetReportTaskAsync() {", + "\n await GetStorage().InitializeAsync(ReportingPeriod, ReportingNode, Scenario, CurrencyType);", + "\n ", + "\n return report.ForDataCube(GetDataCube())", + "\n .WithQuerySource(workspace)", + "\n .SliceRowsBy(rowSlices)", + "\n .SliceColumnsBy(columnSlices)", + "\n .ReportGridOptions(headerColumnWidth: headerColumnWidthValue)", + "\n .ToReport();", + "\n }", + "\n", + "\n Task ToReportAsync => GetReportTaskAsync();", + "\n}", + "\n", + "\npublic interface PvReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] { \"Novelty\", \"VariableType\" };", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"LiabilityType\", \"EconomicBasis\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? (GetScopes(GetIdentities()).Aggregate().LockedBestEstimate + GetScopes(GetIdentities()).Aggregate().CurrentBestEstimate)", + "\n : (GetScopes(GetIdentities()).Aggregate().LockedBestEstimate + GetScopes(GetIdentities()).Aggregate().CurrentBestEstimate).Filter(dataFilter);", + "\n}", + "\n", + "\npublic interface RaReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] { \"Novelty\", \"VariableType\" };", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"LiabilityType\", \"EconomicBasis\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().LockedRiskAdjustment + ", + "\n GetScopes(GetIdentities()).Aggregate().CurrentRiskAdjustment", + "\n : GetScopes(GetIdentities()).Aggregate().LockedRiskAdjustment.Filter(dataFilter) + ", + "\n GetScopes(GetIdentities()).Aggregate().CurrentRiskAdjustment.Filter(dataFilter);", + "\n}", + "\n", + "\npublic interface WrittenReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"AmountType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"LiabilityType\"};", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Written", + "\n : GetScopes(GetIdentities()).Aggregate().Written.Filter(dataFilter);", + "\n}", + "\n", + "\npublic interface AccrualReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"EstimateType\"};", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Advance + ", + "\n GetScopes(GetIdentities()).Aggregate().Overdue", + "\n : GetScopes(GetIdentities()).Aggregate().Advance.Filter(dataFilter) + ", + "\n GetScopes(GetIdentities()).Aggregate().Overdue.Filter(dataFilter);", + "\n}", + "\n", + "\npublic interface DeferralReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"LiabilityType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Deferrals", + "\n : GetScopes(GetIdentities()).Aggregate().Deferrals.Filter(dataFilter);", + "\n}", + "\n", + "\npublic interface FcfReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] { \"Novelty\",\"VariableType\" };", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"LiabilityType\", \"EconomicBasis\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Fcf", + "\n : GetScopes(GetIdentities()).Aggregate().Fcf.Filter(dataFilter);", + "\n}", + "\n", + "\npublic interface ExpAdjReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"EstimateType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"AmountType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().ActuarialExperienceAdjustment", + "\n : GetScopes(GetIdentities()).Aggregate().ActuarialExperienceAdjustment.Filter(dataFilter);", + "\n}", + "\npublic interface TmReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"Novelty\", \"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType) };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().LrcTechnicalMargin", + "\n : GetScopes(GetIdentities()).Aggregate().LrcTechnicalMargin.Filter(dataFilter);", + "\n}", + "\npublic interface CsmReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"Novelty\", \"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"EstimateType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Csm + ", + "\n GetScopes(GetIdentities()).Aggregate().Lc + ", + "\n GetScopes(GetIdentities()).Aggregate().Loreco", + "\n : GetScopes(GetIdentities()).Aggregate().Csm.Filter(dataFilter) + ", + "\n GetScopes(GetIdentities()).Aggregate().Lc.Filter(dataFilter) + ", + "\n GetScopes(GetIdentities()).Aggregate().Loreco.Filter(dataFilter);", + "\n}", + "\npublic interface ActLrcReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"Novelty\",\"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"EstimateType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().LrcActuarial", + "\n : GetScopes(GetIdentities()).Aggregate().LrcActuarial.Filter(dataFilter);", + "\n}", + "\npublic interface LrcReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"EstimateType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Lrc", + "\n : GetScopes(GetIdentities()).Aggregate().Lrc.Filter(dataFilter);", + "\n}", + "\npublic interface ActLicReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"Novelty\",\"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"EstimateType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().LicActuarial", + "\n : GetScopes(GetIdentities()).Aggregate().LicActuarial.Filter(dataFilter);", + "\n}", + "\npublic interface LicReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"VariableType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType), \"EstimateType\" };", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().Lic", + "\n : GetScopes(GetIdentities()).Aggregate().Lic.Filter(dataFilter);", + "\n}", + "\npublic interface FpReport : IIfrs17Report {", + "\n string[] IIfrs17Report.defaultRowSlices => new string[] {\"VariableType\", \"EstimateType\"};", + "\n string[] IIfrs17Report.defaultColumnSlices => new string[] { CurrencyGrouper(CurrencyType),\"LiabilityType\" };", + "\n int IIfrs17Report.headerColumnWidthValue => 500;", + "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", + "\n ? GetScopes(GetIdentities()).Aggregate().FinancialPerformance", + "\n : GetScopes(GetIdentities()).Aggregate().FinancialPerformance.Filter(dataFilter);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# IFRS 17 Reports" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This class is used to trigger the calculation of the reports and it is exposed to the end-user in the reports." + ] + }, + { + "cell_type": "code", + "source": [ + "public class Ifrs17Reports ", + "\n{", + "\n private Systemorph.Vertex.Scopes.Proxy.IScopeFactory scopes;", + "\n private Systemorph.Vertex.Pivot.Builder.Interfaces.IPivotFactory report;", + "\n private ReportStorage Storage;", + "\n private ReportUniverse reportUniverse;", + "\n ", + "\n //reset", + "\n public void Reset(IWorkspace workspace) => Storage = new ReportStorage(workspace, report);", + "\n", + "\n //constructor", + "\n public Ifrs17Reports (IWorkspace workspace, Systemorph.Vertex.Scopes.Proxy.IScopeFactory scopes, Systemorph.Vertex.Pivot.Builder.Interfaces.IPivotFactory report)", + "\n {", + "\n this.scopes = scopes; ", + "\n this.report = report; ", + "\n Storage = new ReportStorage(workspace, report);", + "\n reportUniverse = scopes.ForSingleton().WithStorage(Storage).ToScope();", + "\n }", + "\n", + "\n public IIfrs17Report PresentValues => reportUniverse.GetScope(nameof(PvReport));", + "\n public IIfrs17Report RiskAdjustments => reportUniverse.GetScope(nameof(RaReport));", + "\n public IIfrs17Report WrittenActuals => reportUniverse.GetScope(nameof(WrittenReport));", + "\n public IIfrs17Report AccrualActuals => reportUniverse.GetScope(nameof(AccrualReport));", + "\n public IIfrs17Report DeferralActuals => reportUniverse.GetScope(nameof(DeferralReport));", + "\n public IIfrs17Report FulfillmentCashflows => reportUniverse.GetScope(nameof(FcfReport));", + "\n public IIfrs17Report ExperienceAdjustments => reportUniverse.GetScope(nameof(ExpAdjReport));", + "\n public IIfrs17Report TechnicalMargins => reportUniverse.GetScope(nameof(TmReport));", + "\n public IIfrs17Report AllocatedTechnicalMargins => reportUniverse.GetScope(nameof(CsmReport));", + "\n public IIfrs17Report ActuarialLrc => reportUniverse.GetScope(nameof(ActLrcReport));", + "\n public IIfrs17Report Lrc => reportUniverse.GetScope(nameof(LrcReport));", + "\n public IIfrs17Report ActuarialLic => reportUniverse.GetScope(nameof(ActLicReport));", + "\n public IIfrs17Report Lic => reportUniverse.GetScope(nameof(LicReport));", + "\n public IIfrs17Report FinancialPerformance => reportUniverse.GetScope(nameof(FpReport));", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/ifrs17/Report/ReportScopes.ipynb b/ifrs17/Report/ReportScopes.ipynb index d9344d3c..f6a51b88 100644 --- a/ifrs17/Report/ReportScopes.ipynb +++ b/ifrs17/Report/ReportScopes.ipynb @@ -21,9 +21,13 @@ "cell_type": "markdown", "source": [ "", - "\n

Report Scopes (IFRS17 Methodology Business Logic)

", - "\n", - "\nThis notebook contains the logic used to perform calculations upon reporting of data." + "\n

Report Scopes (IFRS17 Methodology Business Logic)

" + ] + }, + { + "cell_type": "markdown", + "source": [ + "This notebook contains the logic used to perform calculations upon reporting of data." ] }, { From ca009dfa93f3966fec4aab052866c8e339000c6f Mon Sep 17 00:00:00 2001 From: nnikolopoulos <114566025+nnikolopoulos@users.noreply.github.com> Date: Wed, 2 Nov 2022 21:50:07 +0100 Subject: [PATCH 37/38] New format design in importers (#62) * Define new ImportFormats * Apply import w format in DN, DNS, DP, CF * Apply import w format in A, SV and O * Correct Import statements * Replace abs link with var link * Adjust naming convention * Adjust new import format in full-template --- full-ifrs17-template/Database/Configure.ipynb | 3 +- .../InitSystemorphBaseToMemory.ipynb | 14 +- .../InitSystemorphToDatabase.ipynb | 24 ++-- .../InitSystemorphToMemory.ipynb | 10 +- .../Test/MapTemplateAndImportTest.ipynb | 3 +- .../Test/SpecificationsImportCashflows.ipynb | 2 +- ifrs17/Constants/Consts.ipynb | 2 + ifrs17/Import/Importers.ipynb | 132 +++++++----------- 8 files changed, 82 insertions(+), 108 deletions(-) diff --git a/full-ifrs17-template/Database/Configure.ipynb b/full-ifrs17-template/Database/Configure.ipynb index b332a43c..cbe56388 100644 --- a/full-ifrs17-template/Database/Configure.ipynb +++ b/full-ifrs17-template/Database/Configure.ipynb @@ -27,7 +27,8 @@ { "cell_type": "code", "source": [ - "#!import \"//ifrs17ce/dev/CalculationEngine\"" + "#!import \"../Constants/Consts\"", + "\n#!eval calculationEngine" ] }, { diff --git a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb index 1dc82a4e..e910c089 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphBaseToMemory.ipynb @@ -128,25 +128,25 @@ { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/YieldCurve.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/ExchangeRate.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/PartnerRating.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/CreditDefaultRate.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { @@ -158,19 +158,19 @@ { "cell_type": "code", "source": [ - "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" + "await Import.FromFile(\"../Files/700.DataNodes/DataNodes_CH.csv\").WithFormat(ImportFormats.DataNode).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\").WithFormat(ImportFormats.DataNodeState).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\").WithFormat(ImportFormats.DataNodeParameter).WithTarget(DataSource).ExecuteAsync()" ] }, { diff --git a/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb index 9b7b5ab5..cc45633d 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb @@ -106,25 +106,25 @@ { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/YieldCurve.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/YieldCurve.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/ExchangeRate.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/ExchangeRate.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/PartnerRating.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/PartnerRating.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDimensionsAsync(\"../Files/800.Parameters/CreditDefaultRate.csv\")" + "await Import.FromFile(\"../Files/800.Parameters/CreditDefaultRate.csv\").WithType().SnapshotMode().WithTarget(DataSource).ExecuteAsync()" ] }, { @@ -136,19 +136,19 @@ { "cell_type": "code", "source": [ - "await UploadDataNodesAsync(\"../Files/700.DataNodes/DataNodes_CH.csv\")" + "await Import.FromFile(\"../Files/700.DataNodes/DataNodes_CH.csv\").WithFormat(ImportFormats.DataNode).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDataNodeStateAsync(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/700.DataNodes/DataNodeStates_CH_2020_12.csv\").WithFormat(ImportFormats.DataNodeState).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadDataNodeParameterAsync(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/700.DataNodes/DataNodeParameters_CH_2020_12.csv\").WithFormat(ImportFormats.DataNodeParameter).WithTarget(DataSource).ExecuteAsync()" ] }, { @@ -160,31 +160,31 @@ { "cell_type": "code", "source": [ - "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\").WithFormat(ImportFormats.Opening).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\").WithFormat(ImportFormats.Cashflow).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\").WithFormat(ImportFormats.Actual).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\").WithFormat(ImportFormats.Cashflow).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\").WithFormat(ImportFormats.Actual).WithTarget(DataSource).ExecuteAsync()" ] }, { diff --git a/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb index c9eb277e..1685c887 100644 --- a/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb +++ b/full-ifrs17-template/Initialization/InitSystemorphToMemory.ipynb @@ -52,31 +52,31 @@ { "cell_type": "code", "source": [ - "await UploadOpeningAsync(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/Openings_CH_2020_12.csv\").WithFormat(ImportFormats.Opening).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/NominalCashflows_CH_2020_12.csv\").WithFormat(ImportFormats.Cashflow).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/Actuals_CH_2020_12.csv\").WithFormat(ImportFormats.Actual).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadCashflowsAsync(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/NominalCashflows_CH_2021_3.csv\").WithFormat(ImportFormats.Cashflow).WithTarget(DataSource).ExecuteAsync()" ] }, { "cell_type": "code", "source": [ - "await UploadActualAsync(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\")" + "await Import.FromFile(\"../Files/900.TransactionalData/Actuals_CH_2021_3.csv\").WithFormat(ImportFormats.Actual).WithTarget(DataSource).ExecuteAsync()" ] }, { diff --git a/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb index e0b58e97..69f8137a 100644 --- a/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb +++ b/full-ifrs17-template/Test/MapTemplateAndImportTest.ipynb @@ -443,8 +443,7 @@ "source": [ "public async Task CheckErrors(string inputFileName, List errorBms)", "\n{", - "\n var partitionId = new Guid();", - "\n var log = await UploadDataNodeParameterToWorkspaceAsync(inputFileName, partitionId);", + "\n var log = await Import.FromFile(inputFileName).WithFormat(ImportFormats.DataNodeParameter).WithTarget(Workspace).ExecuteAsync();", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n errorBms.Intersect(log.Errors.Select(x => x.ToString().Substring(0,x.ToString().Length-2).Substring(40)).ToArray()).Count().Should().Be(errorBms.Count());", "\n}" diff --git a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb index 12b9fc30..d75b5206 100644 --- a/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb +++ b/full-ifrs17-template/Test/SpecificationsImportCashflows.ipynb @@ -116,7 +116,7 @@ "cell_type": "code", "source": [ "var groupOfContract = \"GricComplex\";", - "\nawait UploadCashflowsAsync(\"Data/CashflowComplex.csv\")" + "\nawait Import.FromFile(\"Data/CashflowComplex.csv\").WithFormat(ImportFormats.Cashflow).WithTarget(DataSource).ExecuteAsync()" ] }, { diff --git a/ifrs17/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb index 8c67e92e..d5dafed5 100644 --- a/ifrs17/Constants/Consts.ipynb +++ b/ifrs17/Constants/Consts.ipynb @@ -138,7 +138,9 @@ "public static class ImportFormats{", "\n public const string Cashflow = nameof(Cashflow);", "\n public const string Actual = nameof(Actual);", + "\n public const string DataNode = nameof(DataNode);", "\n public const string DataNodeParameter = nameof(DataNodeParameter);", + "\n public const string DataNodeState = nameof(DataNodeState);", "\n public const string SimpleValue = nameof(SimpleValue);", "\n public const string Opening = nameof(Opening);", "\n public const string AocConfiguration = nameof(AocConfiguration);", diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 6be43097..8a499aa5 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -266,16 +266,14 @@ { "cell_type": "code", "source": [ - "public async Task DataNodeFactoryAsync(string file, string tab, ImportArgs args)", + "public async Task DataNodeFactoryAsync(IDataSet dataSet, string tableName, ImportArgs args)", "\n{", "\n var partition = (await DataSource.Query().Where(p => p.ReportingNode == args.ReportingNode && p.Scenario == null).ToArrayAsync()).SingleOrDefault();", "\n if(partition == null) { ApplicationMessage.Log(Error.ParsedPartitionNotFound); return; }", "\n", - "\n var extension = System.IO.Path.GetExtension(file);", - "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var target = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet.Tables[tab];", + "\n var table = dataSet.Tables[tableName];", "\n", - "\n var dataNodesImported = target.Rows.Select(x => x.Field(nameof(RawVariable.DataNode))).ToHashSet();", + "\n var dataNodesImported = table.Rows.Select(x => x.Field(nameof(RawVariable.DataNode))).ToHashSet();", "\n var dataNodesDefined = await DataSource.Query().Where(x => dataNodesImported.Contains(x.SystemName)).ToArrayAsync();", "\n var dataNodeStatesDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync();", "\n var dataNodeParametersDefined = await DataSource.Query().Select(x => x.DataNode).ToArrayAsync(); ", @@ -304,24 +302,7 @@ { "cell_type": "markdown", "source": [ - "## Parse and Upload: Dimensions" - ] - }, - { - "cell_type": "code", - "source": [ - "public async Task UploadDimensionsAsync (string fileName) where T: class ", - "\n{", - "\n await CleanDatabaseAsync();", - "\n var importLog = await Import.FromFile(fileName).WithType().WithTarget(DataSource).ExecuteAsync();", - "\n return importLog;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "### Analysis of Change Configuration" + "## Analysis of Change Configuration" ] }, { @@ -430,11 +411,9 @@ { "cell_type": "code", "source": [ - "public async Task GetArgsFromMainAsync(string file)", + "public async Task GetArgsFromMainAsync(IDataSet dataSet)", "\n{", - "\n var extension = System.IO.Path.GetExtension(file);", - "\n var stream = await Project.FileStorage.ReadAsync(file);", - "\n var mainTab = (await DataSetReader.ReadFromStream(stream).WithContentType(extension).ExecuteAsync()).DataSet.Tables[Main];", + "\n var mainTab = dataSet.Tables[Main];", "\n ", "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", @@ -471,7 +450,7 @@ { "cell_type": "markdown", "source": [ - "### Parse and Upload: Data Nodes" + "## Parse and Upload: Data Nodes" ] }, { @@ -483,7 +462,7 @@ { "cell_type": "code", "source": [ - "public async Task UploadDataNodesToWorkspaceAsync(string fileName)", + "public async Task UploadDataNodesToWorkspaceAsync(IDataSet dataSet)", "\n{", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n Workspace.Initialize(x => x.FromSource(DataSource)", @@ -493,7 +472,7 @@ "\n .DisableInitialization());", "\n ", "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(fileName);", + "\n var args = await GetArgsFromMainAsync(dataSet);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var storage = new ParsingStorage(args, DataSource, Workspace);", @@ -501,7 +480,7 @@ "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var errors = new List();", - "\n var importLogPortfolios = await Import.FromFile(fileName)", + "\n var importLogPortfolios = await Import.FromDataSet(dataSet)", "\n .WithType((dataset, datarow) => new InsurancePortfolio {", "\n SystemName = datarow.Field(nameof(DataNode.SystemName)),", "\n DisplayName = datarow.Field(nameof(DataNode.DisplayName)),", @@ -526,7 +505,7 @@ "\n .ExecuteAsync();", "\n ", "\n var portfolios = await Workspace.Query().ToDictionaryAsync(x => x.SystemName);", - "\n var importLogGroupOfContracts = await Import.FromFile(fileName)", + "\n var importLogGroupOfContracts = await Import.FromDataSet(dataSet)", "\n .WithType((dataset, datarow) => {", "\n var gicSystemName = datarow.Field(nameof(DataNode.SystemName));", "\n var pf = datarow.Field(nameof(InsurancePortfolio));", @@ -586,16 +565,15 @@ { "cell_type": "code", "source": [ - "public async Task UploadDataNodesAsync(string fileName)", - "\n{", - "\n var log = await UploadDataNodesToWorkspaceAsync(fileName);", + "Import.DefineFormat(ImportFormats.DataNode, async (options, dataSet) => {", + "\n var log = await UploadDataNodesToWorkspaceAsync(dataSet);", "\n var partition = (Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", "\n await CommitToDatabase(partition);", "\n await CommitToDatabase(partition);", "\n await CommitToDatabase(partition);", "\n await CommitToDatabase(partition);", "\n return log;", - "\n}" + "\n});" ] }, { @@ -628,7 +606,7 @@ { "cell_type": "code", "source": [ - "public async Task UploadDataNodeStateToWorkspaceAsync(string fileName)", + "public async Task UploadDataNodeStateToWorkspaceAsync(IDataSet dataSet)", "\n{", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n Workspace.Initialize(x => x.FromSource(DataSource)", @@ -639,14 +617,14 @@ "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", "\n ", "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(fileName);", + "\n var args = await GetArgsFromMainAsync(dataSet);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var storage = new ParsingStorage(args, DataSource, Workspace);", "\n await storage.InitializeAsync();", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", - "\n var importLog = await Import.FromFile(fileName).WithType(", + "\n var importLog = await Import.FromDataSet(dataSet).WithType(", "\n (dataset, datarow) => new DataNodeState {", "\n DataNode = datarow.Field(nameof(DataNodeState.DataNode)),", "\n State = (State)Enum.Parse(typeof(State), datarow.Field(nameof(DataNodeState.State))),", @@ -664,12 +642,11 @@ { "cell_type": "code", "source": [ - "public async Task UploadDataNodeStateAsync(string fileName)", - "\n{", - "\n var log = await UploadDataNodeStateToWorkspaceAsync(fileName);", + "Import.DefineFormat(ImportFormats.DataNodeState, async (options, dataSet) => {", + "\n var log = await UploadDataNodeStateToWorkspaceAsync(dataSet);", "\n await CommitToDatabase((Guid)Workspace.Partition.GetCurrent(nameof(PartitionByReportingNode)), snapshot: false); ", "\n return log;", - "\n}" + "\n});" ] }, { @@ -681,7 +658,7 @@ { "cell_type": "code", "source": [ - "public async Task UploadDataNodeParameterToWorkspaceAsync(string fileName, Guid targetPartitionByReportingNodeId)", + "public async Task UploadDataNodeParameterToWorkspaceAsync(IDataSet dataSet, Guid targetPartitionByReportingNodeId)", "\n{", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n Workspace.Initialize(x => x.FromSource(DataSource)", @@ -692,7 +669,7 @@ "\n await Workspace.DeleteAsync(await Workspace.Query().ToArrayAsync() );", "\n ", "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(fileName) with {ImportFormat = ImportFormats.DataNodeParameter};", + "\n var args = await GetArgsFromMainAsync(dataSet) with {ImportFormat = ImportFormats.DataNodeParameter};", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", "\n var storage = new ParsingStorage(args, DataSource, Workspace);", @@ -702,7 +679,7 @@ "\n var singleDataNode = new List();", "\n var interDataNode = new List<(string,string)>();", "\n ", - "\n var importLog = await Import.FromFile(fileName)", + "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType( (dataset, datarow) => {", "\n", "\n //read and validate DataNodes", @@ -769,16 +746,15 @@ { "cell_type": "code", "source": [ - "public async Task UploadDataNodeParameterAsync(string fileName)", - "\n{", + "Import.DefineFormat(ImportFormats.DataNodeParameter, async (options, dataSet) => {", "\n Guid partitionId = new Guid();", - "\n var log = await UploadDataNodeParameterToWorkspaceAsync(fileName, partitionId);", + "\n var log = await UploadDataNodeParameterToWorkspaceAsync(dataSet, partitionId);", "\n ", "\n await CommitToDatabase(partitionId, snapshot: false);", "\n await CommitToDatabase(partitionId, snapshot: false); ", "\n ", "\n return log;", - "\n}" + "\n});" ] }, { @@ -813,7 +789,7 @@ { "cell_type": "code", "source": [ - "public async Task ParseCashflowsToWorkspaceAsync(string fileName, ImportArgs args)", + "public async Task ParseCashflowsToWorkspaceAsync(IDataSet dataSet, ImportArgs args)", "\n{", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n Workspace.Initialize(x => x.FromSource(DataSource)", @@ -825,7 +801,7 @@ "\n await parsingStorage.InitializeAsync();", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", - "\n var importLog = await Import.FromFile(fileName)", + "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType ( (dataset, datarow) => {", "\n var aocType = datarow.Field(nameof(RawVariable.AocType));", "\n var novelty = datarow.Field(nameof(RawVariable.Novelty));", @@ -881,14 +857,13 @@ { "cell_type": "code", "source": [ - "public async Task UploadCashflowsAsync(string fileName)", - "\n{", + "Import.DefineFormat(ImportFormats.Cashflow, async (options, dataSet) => {", "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Cashflow};", - "\n await DataNodeFactoryAsync(fileName, ImportFormats.Cashflow, args);", + "\n var args = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.Cashflow};", + "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Cashflow, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", - "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(fileName, args);", + "\n var parsingLog = await ParseCashflowsToWorkspaceAsync(dataSet, args);", "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", "\n ", "\n var storage = new ImportStorage(args, DataSource, Workspace);", @@ -910,7 +885,7 @@ "\n filter : x => storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", "\n", "\n return Activity.Finish().Merge(parsingLog); ", - "\n}" + "\n});" ] }, { @@ -922,7 +897,7 @@ { "cell_type": "code", "source": [ - "public async Task ParseActualsToWorkspaceAsync(string fileName, ImportArgs args)", + "public async Task ParseActualsToWorkspaceAsync(IDataSet dataSet, ImportArgs args)", "\n{", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n Workspace.Initialize(x => x.FromSource(DataSource)", @@ -934,7 +909,7 @@ "\n await parsingStorage.InitializeAsync();", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", - "\n var importLog = await Import.FromFile(fileName)", + "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType ( (dataset, datarow) => {", "\n var dataNode = datarow.Field(nameof(DataNode));", "\n if(!parsingStorage.DataNodeDataBySystemName.TryGetValue(dataNode, out var dataNodeData)) {", @@ -985,14 +960,13 @@ { "cell_type": "code", "source": [ - "public async Task UploadActualAsync(string fileName)", - "\n{", + "Import.DefineFormat(ImportFormats.Actual, async (options, dataSet) => {", "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Actual};", - "\n await DataNodeFactoryAsync(fileName, ImportFormats.Actual, args);", + "\n var args = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.Actual};", + "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Actual, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", - "\n var parsingLog = await ParseActualsToWorkspaceAsync(fileName, args);", + "\n var parsingLog = await ParseActualsToWorkspaceAsync(dataSet, args);", "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", "\n", "\n var storage = new ImportStorage(args, DataSource, Workspace);", @@ -1011,7 +985,7 @@ "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", "\n", "\n return Activity.Finish().Merge(parsingLog);", - "\n}" + "\n});" ] }, { @@ -1029,7 +1003,7 @@ { "cell_type": "code", "source": [ - "public async Task ParseSimpleValueToWorkspaceAsync(string fileName, ImportArgs args, Guid targetPartitionByReportingNodeAndPeriodId)", + "public async Task ParseSimpleValueToWorkspaceAsync(IDataSet dataSet, ImportArgs args, Guid targetPartitionByReportingNodeAndPeriodId)", "\n{", "\n Workspace.Reset(x => x.ResetInitializationRules().ResetCurrentPartitions());", "\n Workspace.Initialize(x => x.FromSource(DataSource)", @@ -1042,7 +1016,7 @@ "\n await parsingStorage.InitializeAsync();", "\n if(Activity.HasErrors()) return Activity.Finish(); ", "\n", - "\n var importLog = await Import.FromFile(fileName)", + "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType ( (dataset, datarow) => {", "\n var dataNode = parsingStorage.ValidateDataNode(datarow.Field(nameof(DataNode)));", "\n var amountType = parsingStorage.ValidateAmountType(datarow.Field(nameof(IfrsVariable.AmountType)));", @@ -1101,15 +1075,14 @@ { "cell_type": "code", "source": [ - "public async Task UploadSimpleValueAsync(string fileName)", - "\n{", + "Import.DefineFormat(ImportFormats.SimpleValue, async (options, dataSet) => {", "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.SimpleValue};", - "\n await DataNodeFactoryAsync(fileName, ImportFormats.SimpleValue, args);", + "\n var args = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.SimpleValue};", + "\n await DataNodeFactoryAsync(dataSet, ImportFormats.SimpleValue, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n Guid partitionId = new Guid();", - "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", + "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(dataSet, args, partitionId);", "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", "\n ", "\n Workspace.Query().Select(v => new {v.DataNode, v.AccidentYear}).Distinct();", @@ -1119,7 +1092,7 @@ "\n filter : x => Workspace.Query().Select(v => v.DataNode).Distinct().Contains(x.DataNode));", "\n ", "\n return Activity.Finish().Merge(parsingLog);", - "\n}" + "\n});" ] }, { @@ -1131,15 +1104,14 @@ { "cell_type": "code", "source": [ - "public async Task UploadOpeningAsync(string fileName)", - "\n{", + "Import.DefineFormat(ImportFormats.Opening, async (options, dataSet) => {", "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(fileName)) with {ImportFormat = ImportFormats.Opening};", - "\n await DataNodeFactoryAsync(fileName, ImportFormats.Opening, args);", + "\n var args = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.Opening};", + "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Opening, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n Guid partitionId = new Guid();", - "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(fileName, args, partitionId);", + "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(dataSet, args, partitionId);", "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", "\n ", "\n var storage = new ImportStorage(args, DataSource, Workspace);", @@ -1158,7 +1130,7 @@ "\n storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode ));", "\n", "\n return Activity.Finish().Merge(parsingLog);", - "\n}" + "\n});" ] }, { From 7a4f4641d0efe2d2ad3c7a4a6f2453e4898ccee3 Mon Sep 17 00:00:00 2001 From: Davide Colleoni <103409906+dcolleoni@users.noreply.github.com> Date: Thu, 3 Nov 2022 18:23:48 +0100 Subject: [PATCH 38/38] Package update (#65) * update packages * add anchors --- ifrs17/DataModel/DataStructure.ipynb | 23 ++++++++++++----------- ifrs17/Report/ReportScopes.ipynb | 6 ++++-- ifrs17/Utils/ApplicationMessage.ipynb | 2 +- 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index 4c88153d..2c3fac39 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -43,17 +43,18 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Arithmetics,1.5.4\"", - "\n#r \"nuget:Systemorph.Workspace,1.5.0\"", - "\n#r \"nuget:Systemorph.Scopes,1.5.2\"", - "\n#r \"nuget:Systemorph.Import,1.5.0\"", - "\n#r \"nuget:Systemorph.Test,1.5.2\"", - "\n#r \"nuget:Systemorph.Export,1.5.0\"", - "\n#r \"nuget:Systemorph.DataSetReader,1.5.0\"", - "\n#r \"nuget:Systemorph.DataSource,1.5.0\"", - "\n#r \"nuget:Systemorph.DataSource.Conversions,1.5.0\"", - "\n#r \"nuget:Systemorph.Reporting,1.5.2\"", - "\n#r \"nuget:Systemorph.DomainDesigner,1.5.0\"" + "#r \"nuget:Systemorph.Arithmetics,1.5.5\"", + "\n#r \"nuget:Systemorph.Workspace,1.5.3\"", + "\n#r \"nuget:Systemorph.Scopes,1.5.5\"", + "\n#r \"nuget:Systemorph.Import,1.5.1\"", + "\n#r \"nuget:Systemorph.Test,1.5.5\"", + "\n#r \"nuget:Systemorph.Export,1.5.1\"", + "\n#r \"nuget:Systemorph.DataSetReader,1.5.1\"", + "\n#r \"nuget:Systemorph.DataSource,1.5.3\"", + "\n#r \"nuget:Systemorph.DataSource.Conversions,1.5.3\"", + "\n#r \"nuget:Systemorph.Reporting,1.5.5\"", + "\n#r \"nuget:Systemorph.DomainDesigner,1.5.1\"", + "\n#r \"nuget:Systemorph.SharePoint,1.5.6\"" ] }, { diff --git a/ifrs17/Report/ReportScopes.ipynb b/ifrs17/Report/ReportScopes.ipynb index f6a51b88..b6fd584d 100644 --- a/ifrs17/Report/ReportScopes.ipynb +++ b/ifrs17/Report/ReportScopes.ipynb @@ -379,7 +379,8 @@ { "cell_type": "markdown", "source": [ - "## LIC (Liability for Incurred Claims)", + "", + "\n## LIC (Liability for Incurred Claims)", "\n", "\nLiability of Incurred Claims (LIC) report includes the contributions from [Lic Actuarial](#lic-actuarial) (Fullfilment Cashflow), [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." ] @@ -427,7 +428,8 @@ { "cell_type": "markdown", "source": [ - "## LRC (Liability for Remaining Coverage)", + "", + "\n## LRC (Liability for Remaining Coverage)", "\n", "\nLiability for Remaining Coverage (LRC) report includes all the contributions from [LRC Actuarial](#lrc-actuarial) (Fulfillment Cashflow, Contructual Sevice Margin, Loss Component, Loss Recovery Component) and, [Advance](#written-accrual-deferral) Actual, and [Overdue](#written-accrual-deferral) Actual." ] diff --git a/ifrs17/Utils/ApplicationMessage.ipynb b/ifrs17/Utils/ApplicationMessage.ipynb index f2253bd6..e55e688c 100644 --- a/ifrs17/Utils/ApplicationMessage.ipynb +++ b/ifrs17/Utils/ApplicationMessage.ipynb @@ -27,7 +27,7 @@ { "cell_type": "code", "source": [ - "#r \"nuget:Systemorph.Activities,1.5.1\"" + "#r \"nuget:Systemorph.Activities,1.5.5\"" ] }, {