diff --git a/ifrs17-template/Test/Data/ExportReportVariables.ipynb b/ifrs17-template/Test/Data/ExportReportVariables.ipynb index bf06f205..71aa2cc1 100644 --- a/ifrs17-template/Test/Data/ExportReportVariables.ipynb +++ b/ifrs17-template/Test/Data/ExportReportVariables.ipynb @@ -144,8 +144,7 @@ "\n ((2020, 12), \"CH\", null, CurrencyType.Group), ", "\n ((2021, 3), \"CH\", null, CurrencyType.Contractual),", "\n ((2021, 3), \"CH\", null, CurrencyType.Functional),", - "\n ((2021, 3), \"CH\", null, CurrencyType.Group),", - "\n ((2020, 12), \"CH\", nameof(Scenarios.MTUP10pct), CurrencyType.Contractual)", + "\n ((2021, 3), \"CH\", null, CurrencyType.Group)", "\n};" ], "metadata": {}, diff --git a/ifrs17/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb index 23d90c66..6bb2ba8f 100644 --- a/ifrs17/Constants/Consts.ipynb +++ b/ifrs17/Constants/Consts.ipynb @@ -361,32 +361,6 @@ "execution_count": 0, "outputs": [] }, - { - "cell_type": "code", - "source": [ - "public static class Scenarios{", - "\n public const string YCUP1pct = nameof(YCUP1pct); // Yield Curve Up 1.0pct", - "\n public const string YCDW1pct = nameof(YCDW1pct); // Yield Curve Down 1.0pct", - "\n public const string SRUP1pct = nameof(SRUP1pct); // Spread Rate Up 1.0pct", - "\n public const string SRDW1pct = nameof(SRDW1pct); // Spread Rate Down 1.0pct", - "\n public const string EUP1pct = nameof(EUP1pct); // Equity Up 1.0pct", - "\n public const string EDW1pct = nameof(EDW1pct); // Equity Down 1.0pct", - "\n public const string FXUP1pct = nameof(FXUP1pct); // Exchange Rate Up 1.0pct", - "\n public const string FXDW1pct = nameof(FXDW1pct); // Exchange Rate Down 1.0pct", - "\n public const string MTUP10pct = nameof(MTUP10pct); // Mortality Up 10pct", - "\n public const string MTDW10pct = nameof(MTDW10pct); // Mortality Down 10pct", - "\n public const string LUP10pct = nameof(LUP10pct); // Longevity Up 10pct", - "\n public const string LDW10pct = nameof(LDW10pct); // Longevity Down 10pct", - "\n public const string DUP10pct = nameof(DUP10pct); // Disability Up 10pct", - "\n public const string DDW10pct = nameof(DDW10pct); // Disability Down 10pct", - "\n public const string LICUP10pct = nameof(LICUP10pct); // Lic Up 10pct", - "\n public const string LICDW10pct = nameof(LICDW10pct); // Lic Down 10pct", - "\n}" - ], - "metadata": {}, - "execution_count": 0, - "outputs": [] - }, { "cell_type": "markdown", "source": [ diff --git a/ifrs17/Report/ReportConfigurationAndUtils.ipynb b/ifrs17/Report/ReportConfigurationAndUtils.ipynb index aa805243..5d077303 100644 --- a/ifrs17/Report/ReportConfigurationAndUtils.ipynb +++ b/ifrs17/Report/ReportConfigurationAndUtils.ipynb @@ -172,11 +172,11 @@ "cell_type": "code", "source": [ "public static async Task> QueryReportVariablesAsync(this IWorkspace workspace, (int Year, int Month, string ReportingNode, string Scenario) args ) {", - "\n ReportVariable[] reportVariables = new ReportVariable[0];", - "\n if(args.Scenario != null) ", - "\n reportVariables = (await workspace.QueryReportVariablesSingleScenarioAsync((args.Year, args.Month, args.ReportingNode, null)));", - "\n return (await workspace.QueryReportVariablesSingleScenarioAsync((args.Year, args.Month, args.ReportingNode, args.Scenario)))", - "\n .Union(reportVariables.Select(x => x with {Scenario = args.Scenario}), EqualityComparer.Instance).ToArray();", + "\n var bestEstimate = (await workspace.QueryReportVariablesSingleScenarioAsync((args.Year, args.Month, args.ReportingNode, null)));", + "\n return (args.Scenario == null) ", + "\n ? bestEstimate", + "\n : (await workspace.QueryReportVariablesSingleScenarioAsync((args.Year, args.Month, args.ReportingNode, args.Scenario)))", + "\n .Union(bestEstimate.Select(x => x with {Scenario = args.Scenario}), EqualityComparer.Instance).ToArray();", "\n}" ], "metadata": {}, diff --git a/ifrs17/Report/ReportMutableScopes.ipynb b/ifrs17/Report/ReportMutableScopes.ipynb index 358bbe69..664a3c41 100644 --- a/ifrs17/Report/ReportMutableScopes.ipynb +++ b/ifrs17/Report/ReportMutableScopes.ipynb @@ -111,7 +111,8 @@ "\n int Year => ReportingPeriod.Year;", "\n int Month => ReportingPeriod.Month;", "\n string ReportingNode { get; set; }", - "\n string Scenario { get; set; }", + "\n string Scenario { get; set; } // TODO: Enable dropdown selection including All and Delta", + "\n string Comparison { get; set; } // TODO: only for scenario at the beginning, meant to enable general purpose comparisons ", "\n CurrencyType CurrencyType { get; set; }", "\n ", "\n ((int Year, int Month) ReportingPeriod, string ReportingNode, string Scenario, CurrencyType) ShowSettings => (ReportingPeriod, ReportingNode, Scenario, CurrencyType);", @@ -124,8 +125,15 @@ "\n protected string[] rowSlices => RowSlices is null ? defaultRowSlices : defaultRowSlices.Concat(RowSlices).Where(x => !forbiddenSlices.Contains(x)).ToArray();", "\n", "\n IEnumerable ColumnSlices { get; set; }", - "\n protected string[] defaultColumnSlices => new string[] { };", - "\n protected string[] columnSlices => ColumnSlices is null ? defaultColumnSlices : defaultColumnSlices.Where(cs => !ColumnSlices.Contains(cs)).Concat(ColumnSlices).Where(x => !forbiddenSlices.Contains(x)).ToArray();", + "\n protected string[] defaultColumnSlices => new string[] { };", + "\n protected string[] columnSlices { get{", + "\n var slices = ColumnSlices is null ? defaultColumnSlices : defaultColumnSlices.Where(cs => !ColumnSlices.Contains(cs)).Concat(ColumnSlices).Where(x => !forbiddenSlices.Contains(x)).ToArray();", + "\n return Scenario == \"All\" || Scenario == \"Delta\"", + "\n ? slices.Concat(nameof(Scenario).RepeatOnce()).ToArray() ", + "\n : Scenario is null ? slices : nameof(Scenario).RepeatOnce().Concat(slices).ToArray();", + "\n }}", + "\n", + "\n // Identities", "\n protected HashSet<(ReportIdentity, CurrencyType)> GetIdentities() => GetStorage().GetIdentities(ReportingPeriod, ReportingNode, Scenario, CurrencyType);", "\n ", "\n // Filter", @@ -135,27 +143,26 @@ "\n // Scope Initialization", "\n async Task InitAsync() {", "\n var mostRecentPartition = (await workspace.Query().Where(x => x.Scenario == null).OrderBy(x => x.Year).ThenBy(x => x.Month).ToArrayAsync()).Last(); ", - "\n ", "\n ReportingPeriod = (mostRecentPartition.Year, mostRecentPartition.Month);", "\n ReportingNode = (await workspace.Query().Where(x => x.Parent == null).ToArrayAsync()).First().SystemName; // TODO: change once user permissions are available", "\n Scenario = null;", "\n CurrencyType = CurrencyType.Contractual;", "\n await GetStorage().InitializeReportIndependentCacheAsync();", - "\n }", + "\n } ", + "\n", + "\n //Report", "\n public IDataCube GetDataCube() => default;", "\n protected int headerColumnWidthValue => 250;", + "\n public Task ToReportAsync => GetReportTaskAsync();", "\n private async Task GetReportTaskAsync() {", - "\n await GetStorage().InitializeAsync(ReportingPeriod, ReportingNode, Scenario, CurrencyType);", - "\n ", - "\n return await report.ForDataCube(GetDataCube())", + "\n await GetStorage().InitializeAsync(ReportingPeriod, ReportingNode, Scenario, CurrencyType); ", + "\n return await report.ForDataCube(GetScope((ReportingPeriod, ReportingNode, Scenario, CurrencyType, Identity, dataFilter)).Cube)", "\n .WithQuerySource(workspace)", "\n .SliceRowsBy(rowSlices)", "\n .SliceColumnsBy(columnSlices)", "\n .ReportGridOptions(headerColumnWidth: headerColumnWidthValue)", "\n .ExecuteAsync();", "\n }", - "\n", - "\n Task ToReportAsync => GetReportTaskAsync();", "\n}", "\n", "\npublic interface PvReport : IIfrs17Report {", @@ -279,7 +286,19 @@ "\n IDataCube IIfrs17Report.GetDataCube() => DataFilter == null ", "\n ? GetScopes(GetIdentities()).Aggregate().FinancialPerformance", "\n : GetScopes(GetIdentities()).Aggregate().FinancialPerformance.Filter(dataFilter);", - "\n}" + "\n}", + "\n", + "\npublic interface Data : IMutableScope<((int year, int month) period, string reportingNode, string scenario, CurrencyType currencyType, ", + "\n string reportType, (string filterName, object filterValue)[] dataFilter)> ", + "\n{", + "\n IDataCube Cube { get{", + "\n var dataCube = GetScope(Identity.reportType).GetDataCube();", + "\n // TODO: suggestion to place the filter here instead of having it in every applicability scope", + "\n if(Identity.scenario != \"Delta\") return dataCube;", + "\n var bestEstimateById = dataCube.Where(x => x.Scenario == null).ToDictionary(x => x.ToIdentityString());", + "\n return dataCube.Select(x => x.Scenario == null ? x : x with { Value = x.Value - (bestEstimateById.TryGetValue((x with {Scenario = null}).ToIdentityString(), out var be)? be.Value : 0.0) }).ToDataCube();", + "\n }}", + "\n} " ], "metadata": {}, "execution_count": 0, diff --git a/ifrs17/Report/ReportStorage.ipynb b/ifrs17/Report/ReportStorage.ipynb index 4effa761..e2f9e843 100644 --- a/ifrs17/Report/ReportStorage.ipynb +++ b/ifrs17/Report/ReportStorage.ipynb @@ -114,13 +114,15 @@ "\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 // 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 // Dimensions", "\n public HashSet EstimateTypesWithoutAoc {get; private set;}", + "\n public HashSet TargetScenarios {get; private set;}", "\n ", - "\n // Cache for Variables and Parameters", + "\n // Variables and Parameters", "\n private Dictionary<((int year, int month) period, string reportingNode, string scenario), Dictionary>>> variablesDictionary = new();", "\n ", "\n // Constructor", @@ -140,12 +142,11 @@ "\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 TargetScenarios = await GetScenariosAsync(scenario); ", "\n ", "\n // FX && Fx Parameters", "\n if(!exchangeRatesByCurrencyByFxTypeAndPeriod.TryGetValue(period, out var exchangeRatesByCurrencyByFxType) || !fxPeriodsByAocStepAndPeriod.TryGetValue(period, out var fxPeriodsByAocStep)) {", @@ -157,31 +158,34 @@ "\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 foreach(var scn in TargetScenarios) {", + "\n if(!variablesDictionary.TryGetValue((period, rn, scn), out var variablesByIdentity)) {", + "\n variablesByIdentity = (await workspace.QueryReportVariablesAsync((period.year, period.month, rn, scn)))", + "\n .ToDictionaryGrouped(x => new ReportIdentity {", + "\n Year = period.year,", + "\n Month = period.month,", + "\n ReportingNode = x.ReportingNode,", + "\n Scenario = scn,", + "\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 variablesDictionary.Add((period, rn, scn), variablesByIdentity);", + "\n }", "\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 => (!variablesDictionary.TryGetValue(((reportIdentity.Year, reportIdentity.Month), reportIdentity.ReportingNode, reportIdentity.Scenario), out var variablesByIdentity) || ", + "\n !variablesByIdentity.TryGetValue(reportIdentity, out var variablesByEstimateType))", "\n ? Enumerable.Empty().ToDataCube()", "\n : estimateTypes.Length switch {", "\n 0 => variablesByEstimateType.SelectMany(x => x.Value).ToDataCube(),", @@ -202,16 +206,15 @@ "\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 => GetLeaves(reportingNode).SelectMany(rn => TargetScenarios.SelectMany(scn =>", + "\n variablesDictionary.TryGetValue((period, rn, scn), out var inner) ? inner.Keys.Select(x => (x, currencyType)) : Enumerable.Empty<(ReportIdentity, CurrencyType)>())).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 / 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)];", @@ -221,6 +224,11 @@ "\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", + "\n public async Task> GetScenariosAsync(string scenario) => ", + "\n scenario == \"Delta\" || scenario == \"All\" ", + "\n ? (await workspace.Query().Select(x => x.Scenario).ToArrayAsync()).ToHashSet()", + "\n : scenario.RepeatOnce().ToHashSet();", "\n}" ], "metadata": {},