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" - ], - "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