diff --git a/Export/Export.ipynb b/Export/Export.ipynb new file mode 100644 index 00000000..e3fa8ad4 --- /dev/null +++ b/Export/Export.ipynb @@ -0,0 +1,206 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Main Tab" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Scenario, x => x.Delete()));" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", + "\n => builder.WithTable( config => config .AtBeginning() ", + "\n .WithName(Main) ", + "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", + "\n .WithColumn(x => x.Id, x => x.Delete()));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Porfolio" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", + "\n });" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Group of Contract" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", + "\n => builder.WithTable(config => { ", + "\n if(DependsOnType != default)", + "\n config = config.DependsOn(DependsOnType); ", + "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", + "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", + "\n return config .AtBeginning() ", + "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", + "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", + "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", + "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", + "\n .WithColumn(x => x.OciType, x => x.Delete())", + "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", + "\n });" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "using DocumentFormat.OpenXml.Spreadsheet;" + ] + }, + { + "cell_type": "code", + "source": [ + "public record HelperState { public string State {get; init;} }" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data.AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", + "\n{", + "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", + "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", + "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", + "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", + "\n .WithSource(source => helperState.AsQueryable()) );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node Parameter" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", + "\n => builder", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(x => x.Delete())", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n )", + "\n .WithTable(config => config ", + "\n .AtBeginning() ", + "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", + "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", + "\n .WithColumn(x => x.Partition, x => x.Delete())", + "\n .WithColumn(x => x.Month, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Year, x => x.Delete())", + "\n .WithColumn(x => x.Id, x => x.Delete())", + "\n );" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Export/MapTemplate.ipynb b/Export/MapTemplate.ipynb index 9d6cc89b..2f6034eb 100644 --- a/Export/MapTemplate.ipynb +++ b/Export/MapTemplate.ipynb @@ -38,34 +38,34 @@ { "cell_type": "markdown", "source": [ - "# Import dependencies" + "# Select Initialization" ] }, { - "cell_type": "code", + "cell_type": "markdown", "source": [ - "#!import \"../Utils/UtilityMethods\"" + "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." ] }, { - "cell_type": "markdown", + "cell_type": "code", "source": [ - "# Select Initialization" + "/* The DataSource is configured and connected to real database */", + "\n//#!eval-notebook \"../Database/Configure\"", + "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", + "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" ] }, { "cell_type": "markdown", "source": [ - "Choose to run the Map Template either with the set of Systemorph data in memory or with the data present in the Database. Uncomment the desired option." + "# Import dependencies" ] }, { "cell_type": "code", "source": [ - "/* The DataSource is configured and connected to real database */", - "\n//#!eval-notebook \"Database/Configure\"", - "\n/* The Systemorph set of dimensions + mockdata are dispatched to the unconfigured in-memory DataSource */", - "\n#!eval-notebook \"../Initialization/InitSystemorphBaseToMemory\"" + "#!import \"../Export/Export\"" ] }, { diff --git a/Import/ImportResultPreview.ipynb b/Import/ImportResultPreview.ipynb deleted file mode 100644 index ba23909b..00000000 --- a/Import/ImportResultPreview.ipynb +++ /dev/null @@ -1,250 +0,0 @@ -{ - "metadata": { - "authors": [], - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False" - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "cell_type": "markdown", - "source": [ - "# Temporary for debugging (initialize data and construct/initialize storage)" - ] - }, - { - "cell_type": "code", - "source": [ - "#!eval-notebook \"../Initialization/InitSystemorphToMemory\"" - ] - }, - { - "cell_type": "code", - "source": [ - "#!import \"../Test/SpecificationsSetup\"" - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\nGiven the current status of the implementation, in order to display Actual reports it is necessary to set Actual format in the Args while to display Cashflow it is necessary to set Cashflow format." - ] - }, - { - "cell_type": "code", - "source": [ - "var year = 2021 ;", - "\nvar month = 3 ;", - "\nvar reportingNode = \"CH\" ;", - "\nvar economicBasis = \"L\" ;" - ] - }, - { - "cell_type": "code", - "source": [ - "var UniversePreview = await StartCalculatorAsync(reportingNode, year, month, economicBasis, Periodicity.Quarterly, ImportFormats.Cashflow);" - ] - }, - { - "cell_type": "code", - "source": [ - "var importStorage = UniversePreview.GetStorage();" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Import Preview" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Present Value" - ] - }, - { - "cell_type": "code", - "source": [ - "var identities = UniversePreview.GetScopes(importStorage.DataNodesByImportScope[ImportScope.Primary]).SelectMany(s => s.Identities);" - ] - }, - { - "cell_type": "code", - "source": [ - "var pvs = UniversePreview.GetScopes(identities, o => o.WithStorage(importStorage)).SelectMany(x => x.PvCurrent.Concat(x.PvLocked));" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(pvs", - "\n //.Where(x => x.DataNode == \"DTR1.1\")", - "\n )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n //.GroupColumnsBy(x => x.AmountType)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n //VariableType", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n //.GroupColumnsBy(x => x.Novelty)", - "\n .WithGridOptionsForIfrsVariable(720)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Risk Adjustment" - ] - }, - { - "cell_type": "code", - "source": [ - "var ras = UniversePreview.GetScopes(identities).SelectMany(x => x.RaCurrent.Concat(x.RaLocked));" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(ras)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.EconomicBasis)", - "\n //.GroupRowsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n //VariableType", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n //.GroupColumnsBy(x => x.Novelty)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "var actuals = UniversePreview.GetScopes(identities).SelectMany(x => x.Actual);" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(actuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupRowsBy(x => x.AmountType)", - "\n //.GroupColumnsBy(x => x.DataNode)", - "\n .WithGridOptionsForIfrsVariable(550)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Advance, Overdue Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "var aoActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.AdvanceActual.Concat(x.OverdueActual));" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(aoActuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupColumnsBy(x => x.AmountType)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable(300)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Deferrable Actuals" - ] - }, - { - "cell_type": "code", - "source": [ - "var deferrableActuals = UniversePreview.GetScopes(identities).SelectMany(x => x.DeferrableActual);" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(deferrableActuals)", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable(350)", - "\n .ToReport()" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Csm Lc LoReCo" - ] - }, - { - "cell_type": "code", - "source": [ - "var csm = UniversePreview.GetScopes(identities).SelectMany(x => x.Csms);", - "\nvar loss = UniversePreview.GetScopes(identities).SelectMany(x => x.Loss);", - "\nvar csmLcLoReCo = Enumerable.Empty().Concat(csm).Concat(loss);" - ] - }, - { - "cell_type": "code", - "source": [ - "Report", - "\n .ForObjects(csmLcLoReCo", - "\n //.Where(x => x.DataNode == \"DT1.1\")", - "\n )", - "\n .WithQuerySource(Workspace)", - "\n .GroupColumnsBy(x => x.DataNode)", - "\n .GroupColumnsBy(x => x.EstimateType)", - "\n .GroupRowsBy(x => x.Novelty)", - "\n .GroupRowsBy(x => x.AocType)", - "\n .WithGridOptionsForIfrsVariable()", - "\n .ToReport()" - ] - }, - { - "cell_type": "code", - "source": [ - "" - ] - } - ] -} \ No newline at end of file diff --git a/Import/ImportScopeCalculation.ipynb b/Import/ImportScopeCalculation.ipynb index b9949cc3..4f8e78f5 100644 --- a/Import/ImportScopeCalculation.ipynb +++ b/Import/ImportScopeCalculation.ipynb @@ -404,7 +404,7 @@ "\n- For the **Locked-in** economic basis, the yield curve used is the latest available as per end of the DataNode's inception year;", "\n- Whereas for the **Current** economic base, the yield curve used is the latest available as per the current period.", "\n", - "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/UtilityMethods#yield-curve)." + "\nThe algorithm which retrieves the latest available yield curve is [here](../Utils/Queries#yield-curve)." ] }, { diff --git a/Import/ImportStorage.ipynb b/Import/ImportStorage.ipynb index ae040ef3..291e0e0b 100644 --- a/Import/ImportStorage.ipynb +++ b/Import/ImportStorage.ipynb @@ -32,6 +32,7 @@ "\n- [IfrsVariables](../DataModel/DataStructure)", "\n- [Projection Configuration](../DataModel/DataStructure)", "\n- [YieldCurve](../DataModel/DataStructure)", + "\n- [DataNodeParameters](../DataModel/DataStructure)", "\n- [AocType](../DataModel/DataStructure)", "\n- [AmountType](../DataModel/DataStructure)", "\n- [CalculationType](../DataModel/DataStructure)", @@ -43,7 +44,8 @@ { "cell_type": "code", "source": [ - "#!import \"../Utils/UtilityMethods\"" + "#!import \"../Utils/ImportCalculationMethods\"", + "\n#!import \"../Utils/Queries\"" ] }, { diff --git a/InputFormatDescription.ipynb b/InputFormatDescription.ipynb index 857d2cc9..bee76506 100644 --- a/InputFormatDescription.ipynb +++ b/InputFormatDescription.ipynb @@ -28,7 +28,7 @@ "\n# The Cashflows File Structure ", "\n", "\n", - "\n
" + "\n
" ] }, { @@ -56,7 +56,7 @@ "\n# The Actuals File Structure ", "\n", "\n", - "\n
" + "\n
" ] }, { @@ -80,7 +80,7 @@ "\n# The Openings File Structure ", "\n", "\n", - "\n
" + "\n
" ] }, { @@ -96,6 +96,12 @@ "\n- [AmountType](./DataModel/DataStructure#amount-type) : entered with its SystemName,", "\n- AccidentYear : relevant for Data Node with Liability Type: Liability for Incurred Claims." ] + }, + { + "cell_type": "markdown", + "source": [ + "" + ] } ] } \ No newline at end of file diff --git a/OverviewCalculationEngine.ipynb b/OverviewCalculationEngine.ipynb index a4ba1b36..d3d3e77b 100644 --- a/OverviewCalculationEngine.ipynb +++ b/OverviewCalculationEngine.ipynb @@ -34,7 +34,7 @@ "source": [ "# Introduction", "\n", - "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key inpute: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", + "\nThe Systemorph's IFRS 17 Calculation Engine is a solution to conduct all the essential IFRS 17 calculations based on some key input: modeled future **cashflows** and actual amounts, for a **groups of insurance contracts** and other relevant parameters (Yield Curve, Fx, etc...). The output is a set of calculated results (CSM, Loss Component, Financial Performance, etc...) that are needed for IFRS 17 reporting, analysis, accounting, steering and other management information.", "\n", "\nThis notebook provides an **overview** of Systemorph's IFRS 17 Calculation Engine with brief introductions to all the main steps.", "\n", diff --git a/Report/ReportConfigurationAndUtils.ipynb b/Report/ReportConfigurationAndUtils.ipynb index 575ece44..d482e339 100644 --- a/Report/ReportConfigurationAndUtils.ipynb +++ b/Report/ReportConfigurationAndUtils.ipynb @@ -26,7 +26,7 @@ { "cell_type": "code", "source": [ - "#!import \"../Utils/UtilityMethods\"" + "#!import \"../Utils/Queries\"" ] }, { @@ -51,6 +51,12 @@ "\n with { Height = reportHeight, GroupDefaultExpanded = groupDefaultExpanded, OnGridReady = null } );" ] }, + { + "cell_type": "markdown", + "source": [ + "# Currency methods" + ] + }, { "cell_type": "code", "source": [ @@ -60,6 +66,24 @@ "\n _ => string.Empty };" ] }, + { + "cell_type": "code", + "source": [ + "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", + "\n{", + "\n if(currency == groupCurrency)", + "\n return 1;", + "\n", + "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", + "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", + "\n", + "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", + "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", + "\n", + "\n return currencyToGroupFx;", + "\n}" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/Report/Reports.ipynb b/Report/Reports.ipynb index 36b8aa3e..91d3d680 100644 --- a/Report/Reports.ipynb +++ b/Report/Reports.ipynb @@ -103,7 +103,6 @@ "((int Year, int Month) Period, string ReportingNode, string Scenario, CurrencyType CurrencyType) Args =", "\n //((2020, 12), reportingNodeRoot, null,CurrencyType.Contractual)", "\n ((2021, 3), reportingNodeRoot, null,CurrencyType.Contractual)", - "\n //((2021, 12), reportingNodeRoot, null,CurrencyType.Contractual)", "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Functional)", "\n //((2021, 3), reportingNodeRoot, null,CurrencyType.Group)", "\n ;", @@ -115,7 +114,28 @@ { "cell_type": "markdown", "source": [ - "# Present Value" + "# Data Constellation", + "\n", + "\nWe have " + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Present Value", + "\n", + "\nPresent values of the best estimate of future cashflows are shown here in an Analysis of Change report.", + "\n", + "\nThe report view can be modified with the Slice options for the columns by changing the SliceColumnBy inputs in the next command cell.", + "\nThe figures displayed in the report are automatically aggregated to meet the granularity desired by the user.", + "\n", + "\nCurrently, the data is sliced by :", + "\n- CurrencyType", + "\n- LiabilityType", + "\n- EconomicBasis", + "\n", + "\nFor example one can add \"GroupOfContract\" to separate the contributions of the individual Group of Contracts.", + "\n
We suggest to add this slice between the \"LiabilityType\" and the \"EconomicBasis\" as the the order of the inputs corresponds to the order of the columns shown in the report to expand the data." ] }, { @@ -126,7 +146,7 @@ "\n )", "\n .WithQuerySource(DataSource)", "\n .SliceRowsBy(\"Novelty\",\"VariableType\")", - "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\",\"GroupOfContract\", \"EconomicBasis\")", + "\n .SliceColumnsBy(CurrencyGrouper(Args.CurrencyType), \"LiabilityType\", \"EconomicBasis\") //\"GroupOfContract\"", "\n .ReportGridOptions()", "\n .ToReport()" ] @@ -362,7 +382,9 @@ { "cell_type": "markdown", "source": [ - "# Financial Performance" + "# Financial Performance", + "\n", + "\nUse the expand and collapse buttons in the report rows to change the granularity of the figures displayed." ] }, { diff --git a/Test/MapTemplateAndImportTest.ipynb b/Test/MapTemplateAndImportTest.ipynb index cdb93e65..6dc5c63c 100644 --- a/Test/MapTemplateAndImportTest.ipynb +++ b/Test/MapTemplateAndImportTest.ipynb @@ -26,7 +26,8 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"../Utils/UtilityMethods\"" + "#!import \"../Export/Export\"", + "\n#!import \"../Utils/TestHelper\"" ] }, { @@ -132,8 +133,27 @@ "\n .MainTabConfigurationWoScenario(partition)", "\n.ExecuteAsync();", "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .PortfolioConfiguration()", + "\n .PortfolioConfiguration()", + "\n .GroupofContractConfiguration(typeof(ReinsurancePortfolio))", + "\n .GroupofContractConfiguration(typeof(InsurancePortfolio))", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "// Run this only after having imported the file exported in the above cell.", + "\n/*", "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", @@ -162,8 +182,7 @@ "\nUtils.EqualityComparer(rps, Workspace.Query().ToArray());", "\nUtils.EqualityComparer(gics, Workspace.Query().ToArray());", "\nUtils.EqualityComparer(grics, Workspace.Query().ToArray());", - "\n", - "\n" + "\n*/" ] }, { @@ -202,8 +221,25 @@ "\n .MainTabConfigurationWoScenario(partition)", "\n.ExecuteAsync();", "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .StateEnumConfiguration() ", + "\n .DataNodeStateConfiguration(dataNodeStates)", + "\n .MainTabConfigurationWoScenario(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "// Run this only after having imported the file exported in the above cell.", + "\n/*", "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", @@ -223,7 +259,8 @@ "\nawait UploadDataNodeStateToWorkspaceAsync(filename+\".xlsx\");", "\n", "\n// Workspace is empty because ValidateDataNodeStatesAsync removes the entry, since this is already present in the DataSource.", - "\nWorkspace.Query().ToArray().Should().BeEmpty();" + "\nWorkspace.Query().ToArray().Should().BeEmpty();", + "\n*/" ] }, { @@ -265,8 +302,24 @@ "\n .MainTabConfiguration(partition)", "\n.ExecuteAsync();", "\n", - "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);", - "\n//-----------------------------------------------------------------", + "\nexportResult.ActivityLog.Status.Should().Be(ActivityLogStatus.Succeeded);" + ] + }, + { + "cell_type": "code", + "source": [ + "await Export.ToExcel(filename)", + "\n .WithSource(Workspace)", + "\n .DataNodeParameterConfiguration(dataNodeParameters)", + "\n .MainTabConfiguration(partition)", + "\n.ExecuteAsync()" + ] + }, + { + "cell_type": "code", + "source": [ + "// Run this only after having imported the file exported in the above cell.", + "\n/*", "\n// check that exporter generates only the desired columns ", "\nvar extension = \".xlsx\";", "\nvar stream = await Project.FileStorage.ReadAsync(filename + extension);", @@ -292,7 +345,8 @@ "\nvar expectedSingleDataNodeParamBm = Workspace.Query().Where(x => x.Year == partition.Year && x.Month == partition.Month).ToArray();", "\nvar expectedInterDataNodeParamBm = Workspace.Query().ToArray();", "\nUtils.EqualityComparer(singleDataNodeParamBm, expectedSingleDataNodeParamBm);", - "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);" + "\nUtils.EqualityComparer(interDataNodeParamBm, expectedInterDataNodeParamBm);", + "\n*/" ] }, { diff --git a/Test/QueriesTest.ipynb b/Test/QueriesTest.ipynb index 3c102747..2eddc72f 100644 --- a/Test/QueriesTest.ipynb +++ b/Test/QueriesTest.ipynb @@ -20,7 +20,7 @@ { "cell_type": "code", "source": [ - "#!eval-notebook \"../Utils/UtilityMethods\"" + "#!eval-notebook \"../Utils/Queries\"" ] }, { diff --git a/Test/SpecificationsFinancialPerformance.ipynb b/Test/SpecificationsFinancialPerformance.ipynb index 44816ee6..219121be 100644 --- a/Test/SpecificationsFinancialPerformance.ipynb +++ b/Test/SpecificationsFinancialPerformance.ipynb @@ -240,6 +240,18 @@ "### Non Financial" ] }, + { + "cell_type": "markdown", + "source": [ + "Import `CheckEquality`" + ] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Utils/TestHelper\"" + ] + }, { "cell_type": "markdown", "source": [ diff --git a/Test/SpecificationsSetup.ipynb b/Test/SpecificationsSetup.ipynb index 15228d6f..f4d8ab6f 100644 --- a/Test/SpecificationsSetup.ipynb +++ b/Test/SpecificationsSetup.ipynb @@ -17,10 +17,17 @@ "nbformat": 4, "nbformat_minor": 5, "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Specifications Setup

" + ] + }, { "cell_type": "code", "source": [ - "#!import \"../Import/ImportScopeCalculation\"" + "#!import \"../Import/ImportScopeCalculation\"", + "\n#!import \"../Utils/TestHelper\"" ] }, { diff --git a/Test/Tests.ipynb b/Test/Tests.ipynb index ba71bfbc..40b15ba1 100644 --- a/Test/Tests.ipynb +++ b/Test/Tests.ipynb @@ -98,7 +98,7 @@ { "cell_type": "code", "source": [ - "//#!eval-notebook \"MapTemplateAndImportTest\"" + "#!eval-notebook \"MapTemplateAndImportTest\"" ] }, { diff --git a/Utils/Extensions.ipynb b/Utils/Extensions.ipynb new file mode 100644 index 00000000..9e0adcb9 --- /dev/null +++ b/Utils/Extensions.ipynb @@ -0,0 +1,147 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"", + "\n#!import \"ApplicationMessage\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Enumerable Extensions" + ] + }, + { + "cell_type": "code", + "source": [ + "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", + "\nstatic T GetElementOrDefault(this ICollection array, int index)", + "\n{ ", + "\n var count = array.Count;", + "\n if (array == null || count == 0)", + "\n return default(T);", + "\n", + "\n return index < 0", + "\n ? array.ElementAt(0) // should this case be removed?", + "\n : index < count", + "\n ? array.ElementAt(index)", + "\n : array.ElementAt(count -1);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" + ] + }, + { + "cell_type": "code", + "source": [ + "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# String Extensions" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Globalization;" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double CheckStringForExponentialAndConvertToDouble (this string s)", + "\n{ ", + "\n if (s == null) return default;", + "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", + "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Enum Extentions" + ] + }, + { + "cell_type": "code", + "source": [ + "public static bool Contains(this T value, T lookingForFlag) ", + "\n where T : struct", + "\n{", + "\n int intValue = (int) (object) value;", + "\n int intLookingForFlag = (int) (object) lookingForFlag;", + "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# ToIdentityString" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Text;", + "\npublic static string ToIdentityString(this T v)", + "\n where T : class", + "\n{", + "\n StringBuilder sb = new StringBuilder();", + "\n var propertyInfos = v.GetType()", + "\n .GetProperties()", + "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", + "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", + "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", + "\n", + "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/ImportCalculationMethods.ipynb b/Utils/ImportCalculationMethods.ipynb new file mode 100644 index 00000000..ec78d688 --- /dev/null +++ b/Utils/ImportCalculationMethods.ipynb @@ -0,0 +1,185 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"./Extensions\"" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Get Previous Identities" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", + "\n{", + "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", + "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", + "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", + "\n return identities.Where(id => id.AocType != AocTypes.BOP)", + "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", + "\n : previousStep[x.Novelty].RepeatOnce();", + "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", + "\n return ret;});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Get Reference AocStep for calculated steps" + ] + }, + { + "cell_type": "code", + "source": [ + "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", + "\n{", + "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", + "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", + "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", + "\n && aocStep.Novelty == identityAocStep.Novelty) ", + "\n ?? new AocStep(default, default);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Discount and Cumulate" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", + "\n{ ", + "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", + "\n ", + "\n var ret = new double[nominalValues.Length];", + "\n ", + "\n if(periodType == PeriodType.BeginningOfPeriod)", + "\n {", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n return ret;", + "\n }", + "\n ", + "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", + "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", + "\n ", + "\n return ret;", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", + "\n{ ", + "\n return Enumerable.Range(0, nominalValues.Length)", + "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", + "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", + "\n .Sum() )", + "\n .ToArray();", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Import Configuration " + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Data Nodes" + ] + }, + { + "cell_type": "code", + "source": [ + "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" + ] + }, + { + "cell_type": "code", + "source": [ + "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Change Sign Rules" + ] + }, + { + "cell_type": "code", + "source": [ + "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", + "\n return isActual;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## EstimateType And AmountType" + ] + }, + { + "cell_type": "code", + "source": [ + "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", + "\n{", + "\n return new Dictionary>(){", + "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", + "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", + "\n };", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Technical Margin EstimateType" + ] + }, + { + "cell_type": "code", + "source": [ + "public static HashSet GetTechnicalMarginEstimateType()", + "\n{", + "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", + "\n}" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/Queries.ipynb b/Utils/Queries.ipynb new file mode 100644 index 00000000..02105032 --- /dev/null +++ b/Utils/Queries.ipynb @@ -0,0 +1,320 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"./Extensions\"" + ] + }, + { + "cell_type": "code", + "source": [ + "using System.Linq.Expressions;" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Exchange Rates" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.Query()", + "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", + "\n x.Year == year && x.Month == month)", + "\n .ToArrayAsync())", + "\n .ToDictionaryGrouped(x => x.Currency,", + "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", + "\n {", + "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", + "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", + "\n },", + "\n y => y.FxToGroupCurrency));" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Current and Previous Parameters" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task LoadParameterAsync(", + "\n this IQuerySource querySource,", + "\n int year,", + "\n int month,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return await querySource.Query()", + "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", + "\n .Where(filterExpression?? (Expression>)(x => true))", + "\n .ToArrayAsync();", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadCurrentParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", + "\n .GroupBy(identityExpression)", + "\n .Select(y => y.OrderByDescending(x => x.Year)", + "\n .ThenByDescending(x => x.Month)", + "\n .FirstOrDefault())", + "\n .ToDictionary(identityExpression);", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentAndPreviousParameterAsync (", + "\n this IQuerySource querySource,", + "\n Args args,", + "\n Func identityExpression,", + "\n Expression> filterExpression = null ) ", + "\n where T : IWithYearAndMonth", + "\n{", + "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", + "\n ", + "\n var ret = new Dictionary>();", + "\n foreach(var p in parameters)", + "\n {", + "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", + "\n", + "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n ", + "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", + "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", + "\n }", + "\n return ret;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "", + "\n# Yield Curve" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Locked-in" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var lockedInYieldCurveByGoc = new Dictionary();", + "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", + "\n {", + "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", + "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", + "\n ", + "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", + "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", + "\n ", + "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", + "\n }", + "\n ", + "\n return lockedInYieldCurveByGoc;", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Current" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", + "\n IEnumerable dataNodes)", + "\n{", + "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", + "\n x => x.Currency,", + "\n x => contractualCurrenciesInScope.Contains(x.Currency)", + "\n ));", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node State" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", + "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", + "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Nodes" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", + "\n ", + "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", + "\n .ToDictionary(dn => dn.SystemName, dn => {", + "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", + "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", + "\n return new DataNodeData(){Year = dnPreviousState.Year, ", + "\n Month = dnPreviousState.Month,", + "\n State = dnCurrentState.State,", + "\n PreviousState = dnPreviousState.State,", + "\n DataNode = dn.SystemName,", + "\n ContractualCurrency = dn.ContractualCurrency,", + "\n FunctionalCurrency = dn.FunctionalCurrency,", + "\n LineOfBusiness = dn.LineOfBusiness,", + "\n ValuationApproach = dn.ValuationApproach,", + "\n OciType = dn.OciType,", + "\n Portfolio = dn.Portfolio,", + "\n AnnualCohort = dn.AnnualCohort,", + "\n LiabilityType = dn.LiabilityType,", + "\n Profitability = dn.Profitability,", + "\n Partner = dn.Partner,", + "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", + "\n };", + "\n }", + "\n );", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Data Node Parameters" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Single data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "## Inter data Node" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", + "\n{", + "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", + "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", + "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", + "\n ", + "\n return parameters.SelectMany(p => p", + "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", + "\n .Select(gg =>", + "\n {", + "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", + "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", + "\n return (key: p.Key,", + "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", + "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", + "\n })", + "\n )", + "\n .ToDictionaryGrouped(x => x.key,", + "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", + "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", + "\n}" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# Aoc Step Configuration" + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", + "\n => (await querySource.LoadParameterAsync(year, month))", + "\n .GroupBy(x => (x.AocType, x.Novelty), ", + "\n (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " + ] + }, + { + "cell_type": "code", + "source": [ + "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) ", + "\n => (await querySource.LoadAocStepConfigurationAsync(year, month))", + "\n .ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " + ] + }, + { + "cell_type": "code", + "source": [ + "" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/TestHelper.ipynb b/Utils/TestHelper.ipynb new file mode 100644 index 00000000..a627b204 --- /dev/null +++ b/Utils/TestHelper.ipynb @@ -0,0 +1,113 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + }, + "toc-autonumbering": "True", + "toc-showcode": "False" + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "code", + "source": [ + "#!import \"../DataModel/DataStructure\"" + ] + }, + { + "cell_type": "code", + "source": [ + "public static class Utils {", + "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", + "\n {", + "\n collection1.Length.Should().Be(collection2.Length);", + "\n var type = typeof(T);", + "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", + "\n if(properties.Count() == 0) {", + "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", + "\n isEqual.Should().Be(true);", + "\n }", + "\n foreach(var item1 in collection1) {", + "\n var item2 = collection2.Where(x => ", + "\n properties.All(prop => {", + "\n var propType = prop.PropertyType;", + "\n var val = prop.GetValue(item1);", + "\n var otherVal = prop.GetValue(x);", + "\n if(val == null && otherVal == null) return true;", + "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", + "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", + "\n })", + "\n );", + "\n item2.Count().Should().NotBe(0);", + "\n }", + "\n }", + "\n}" + ] + }, + { + "cell_type": "code", + "source": [ + "static var NumericalPrecisionEqualityChecker = 1.0E-10;", + "\n", + "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", + "\n{", + "\n if(arr1.Length != arr2.Length) return false;", + "\n for(int i = 0; i < arr1.Length; i++) {", + "\n double d1 = arr1[i];", + "\n double d2 = arr2[i];", + "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", + "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", + "\n }", + "\n return true;", + "\n}", + "\n", + "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", + "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", + "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", + "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", + "\n", + "\nstatic bool CheckEquality(this double? d1, double? d2) ", + "\n{", + "\n if(d1 == null && d2 == null) return true;", + "\n else return CheckEquality((double)d1, (double)d2);", + "\n}", + "\n" + ] + }, + { + "cell_type": "markdown", + "source": [ + "# IfrsVariable Report configuration" + ] + }, + { + "cell_type": "code", + "source": [ + "using Systemorph.Vertex.Pivot.Reporting.Builder;" + ] + }, + { + "cell_type": "code", + "source": [ + "public static ReportBuilder WithGridOptionsForIfrsVariable", + "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", + "\n{", + "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", + "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", + "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", + "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", + "\n );", + "\n}" + ] + } + ] +} \ No newline at end of file diff --git a/Utils/UtilityMethods.ipynb b/Utils/UtilityMethods.ipynb deleted file mode 100644 index 3436c3e7..00000000 --- a/Utils/UtilityMethods.ipynb +++ /dev/null @@ -1,899 +0,0 @@ -{ - "metadata": { - "authors": [], - "kernelspec": { - "display_name": "Formula Framework", - "language": "C#", - "name": "C#" - }, - "language_info": { - "file_extension": ".cs", - "mimetype": "text/plain", - "name": "C#" - }, - "toc-autonumbering": "True", - "toc-showcode": "False" - }, - "nbformat": 4, - "nbformat_minor": 5, - "cells": [ - { - "cell_type": "code", - "source": [ - "#!import \"../DataModel/DataStructure\"", - "\n#!import \"./ApplicationMessage\"" - ] - }, - { - "cell_type": "code", - "source": [ - "using System.Linq.Expressions;" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Math Functions" - ] - }, - { - "cell_type": "code", - "source": [ - "static double DivideOrDefault(double numerator, double denominator, double defaultValue = default) => Math.Abs(denominator) > double.Epsilon ? numerator / denominator : defaultValue;" - ] - }, - { - "cell_type": "code", - "source": [ - "// because the default(T) is something else than the first/last element. What about \"static T GetValidElement(this IList array, int index)\"? ", - "\nstatic T GetElementOrDefault(this ICollection array, int index)", - "\n{ ", - "\n var count = array.Count;", - "\n if (array == null || count == 0)", - "\n return default(T);", - "\n", - "\n return index < 0", - "\n ? array.ElementAt(0) // should this case be removed?", - "\n : index < count", - "\n ? array.ElementAt(index)", - "\n : array.ElementAt(count -1);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Enumerable Extensions" - ] - }, - { - "cell_type": "code", - "source": [ - "public static Dictionary ToDictionaryGrouped(this IEnumerable source, Func keySelector, Func, TResult> elementSelector) => source.GroupBy(keySelector).ToDictionary(g => g.Key, elementSelector);" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDataCube SelectToDataCube(this IEnumerable source, Func whereClause, Func selector) => source.Where(whereClause).Select(selector).ToDataCube();" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDataCube SelectToDataCube(this IEnumerable source, Func selector) => source.SelectToDataCube(x => true, selector);" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double[] Prune (this IEnumerable source, double precision = Precision) => source.Reverse().SkipWhile(x => Math.Abs(x) < precision).Reverse().ToArray();" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# String Extensions" - ] - }, - { - "cell_type": "code", - "source": [ - "using System.Globalization;" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double CheckStringForExponentialAndConvertToDouble (this string s)", - "\n{ ", - "\n if (s == null) return default;", - "\n if (double.TryParse(s, NumberStyles.Number, CultureInfo.InvariantCulture, out var doubleValue)) return doubleValue;", - "\n else { ApplicationMessage.Log(Error.ParsingScientificNotation, s); return 1; }", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Enum Extentions" - ] - }, - { - "cell_type": "code", - "source": [ - "public static bool Contains(this T value, T lookingForFlag) ", - "\n where T : struct", - "\n{", - "\n int intValue = (int) (object) value;", - "\n int intLookingForFlag = (int) (object) lookingForFlag;", - "\n return ((intValue & intLookingForFlag) == intLookingForFlag);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Queries" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## FX" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> GetExchangeRatesDictionaryAsync(this IQuerySource querySource, int year, int month)", - "\n => (await querySource.Query()", - "\n .Where(x => x.Year == year - 1 && x.Month == MonthInAYear && x.FxType == FxType.Spot ||", - "\n x.Year == year && x.Month == month)", - "\n .ToArrayAsync())", - "\n .ToDictionaryGrouped(x => x.Currency,", - "\n x => x.ToDictionary(y => (y.Year, y.Month, y.FxType) switch", - "\n {", - "\n (_, _, _) when y.Year == year - 1 && y.Month == MonthInAYear && y.FxType == FxType.Spot => FxPeriod.BeginningOfPeriod,", - "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Average => FxPeriod.Average,", - "\n (_, _, _) when y.Year == year && y.Month == month && y.FxType == FxType.Spot => FxPeriod.EndOfPeriod", - "\n },", - "\n y => y.FxToGroupCurrency));" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double GetCurrencyToGroupFx(Dictionary> exchangeRates, string currency, FxPeriod fxPeriod, string groupCurrency)", - "\n{", - "\n if(currency == groupCurrency)", - "\n return 1;", - "\n", - "\n if(!exchangeRates.TryGetValue(currency, out var currencyToGroup))", - "\n ApplicationMessage.Log(Error.ExchangeRateCurrency, currency);", - "\n", - "\n if(!currencyToGroup.TryGetValue(fxPeriod, out var currencyToGroupFx))", - "\n ApplicationMessage.Log(Error.ExchangeRateNotFound, currency, fxPeriod.ToString());", - "\n", - "\n return currencyToGroupFx;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Current and Previous Parameters" - ] - }, - { - "cell_type": "markdown", - "source": [ - "TODOs:", - "\n
    ", - "\n
  • DataNodes Query: After merging with the new import storage, define IsFirstPeriod property.
  • ", - "\n
  • Once Scenario is defined as a simple property (e.g. in DataNodeState), introduce concept of Priority in LoadCurrentAndPreviousParameterAsync query (see ParameterResultsEntityQueryExtensions in IfrsGeneric).
  • ", - "\n
" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task LoadParameterAsync(", - "\n this IQuerySource querySource,", - "\n int year,", - "\n int month,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n return await querySource.Query()", - "\n .Where(x => x.Year == year && x.Month <= month || x.Year < year)", - "\n .Where(filterExpression?? (Expression>)(x => true))", - "\n .ToArrayAsync();", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadCurrentParameterAsync (", - "\n this IQuerySource querySource,", - "\n Args args,", - "\n Func identityExpression,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n return (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression))", - "\n .GroupBy(identityExpression)", - "\n .Select(y => y.OrderByDescending(x => x.Year)", - "\n .ThenByDescending(x => x.Month)", - "\n .FirstOrDefault())", - "\n .ToDictionary(identityExpression);", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> LoadCurrentAndPreviousParameterAsync (", - "\n this IQuerySource querySource,", - "\n Args args,", - "\n Func identityExpression,", - "\n Expression> filterExpression = null ) ", - "\n where T : IWithYearAndMonth", - "\n{", - "\n var parameters = (await querySource.LoadParameterAsync(args.Year, args.Month, filterExpression)).GroupBy(identityExpression);", - "\n ", - "\n var ret = new Dictionary>();", - "\n foreach(var p in parameters)", - "\n {", - "\n var inner = ret.GetOrAdd(p.Key, _ => new Dictionary());", - "\n", - "\n var currentCandidate = p.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", - "\n var previousCandidate = p.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", - "\n ", - "\n inner.Add(CurrentPeriod, currentCandidate != null ? currentCandidate : previousCandidate);", - "\n inner.Add(PreviousPeriod, previousCandidate != null ? previousCandidate : currentCandidate);", - "\n }", - "\n return ret;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "", - "\n## Yield Curve" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadLockedInYieldCurveAsync(this IQuerySource querySource, Args args, ", - "\n IEnumerable dataNodes)", - "\n{", - "\n var lockedInYieldCurveByGoc = new Dictionary();", - "\n foreach (var dn in dataNodes.Where(x => x.ValuationApproach == ValuationApproaches.BBA))", - "\n {", - "\n var argsNew = args with {Year = dn.Year, Month = dn.Month};", - "\n var loadedYc = (await querySource.LoadCurrentParameterAsync(argsNew, x => x.Currency, x => x.Currency == dn.ContractualCurrency));", - "\n ", - "\n if(!loadedYc.TryGetValue(dn.ContractualCurrency, out var lockedYc))", - "\n ApplicationMessage.Log(Error.YieldCurveNotFound, dn.ContractualCurrency, argsNew.Year.ToString(), argsNew.Month.ToString());", - "\n ", - "\n lockedInYieldCurveByGoc[dn.DataNode] = lockedYc;", - "\n }", - "\n ", - "\n return lockedInYieldCurveByGoc;", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> LoadCurrentYieldCurveAsync(this IQuerySource querySource, Args args, ", - "\n IEnumerable dataNodes)", - "\n{", - "\n var contractualCurrenciesInScope = dataNodes.Select(dn => dn.ContractualCurrency).ToHashSet();", - "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, ", - "\n x => x.Currency,", - "\n x => contractualCurrenciesInScope.Contains(x.Currency)", - "\n ));", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node State" - ] - }, - { - "cell_type": "code", - "source": [ - "//TODO : remove this method and clean up in queriesTest. We need a new test for LoadDataNodes.", - "\npublic static async Task> LoadDataNodeStateAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n //This querySource is partitioned", - "\n return (await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode))", - "\n .Where(x => x.Value[CurrentPeriod].State != State.Inactive)", - "\n .ToDictionary(x => x.Key, x => x.Value[CurrentPeriod]);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Nodes" - ] - }, - { - "cell_type": "code", - "source": [ - "// TODO: the name of this method is strange, one expects DataNodes in return but instead obtains DataNodeData...", - "\npublic static async Task> LoadDataNodesAsync(this IQuerySource querySource, Args args) //How do we force the user to provide here a partitioned source? IWorkspace?", - "\n{", - "\n var dataNodeStates = await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", - "\n var activeDataNodes = dataNodeStates.Where(kvp => kvp.Value[CurrentPeriod].State != State.Inactive).Select(kvp => kvp.Key);", - "\n ", - "\n return (await querySource.Query().Where(dn => activeDataNodes.Contains(dn.SystemName)).ToArrayAsync())", - "\n .ToDictionary(dn => dn.SystemName, dn => {", - "\n var dnCurrentState = dataNodeStates[dn.SystemName][CurrentPeriod];", - "\n var dnPreviousState = dataNodeStates[dn.SystemName][PreviousPeriod];", - "\n return new DataNodeData(){Year = dnPreviousState.Year, ", - "\n Month = dnPreviousState.Month,", - "\n State = dnCurrentState.State,", - "\n PreviousState = dnPreviousState.State,", - "\n //from Group of Contract", - "\n DataNode = dn.SystemName,", - "\n ContractualCurrency = dn.ContractualCurrency,", - "\n FunctionalCurrency = dn.FunctionalCurrency,", - "\n LineOfBusiness = dn.LineOfBusiness,", - "\n ValuationApproach = dn.ValuationApproach,", - "\n OciType = dn.OciType,", - "\n Portfolio = dn.Portfolio,", - "\n AnnualCohort = dn.AnnualCohort,", - "\n LiabilityType = dn.LiabilityType,", - "\n Profitability = dn.Profitability,", - "\n Partner = dn.Partner,", - "\n IsReinsurance = dn.GetType() == typeof(GroupOfReinsuranceContract),", - "\n };", - "\n }", - "\n );", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node Parameters" - ] - }, - { - "cell_type": "markdown", - "source": [ - "### Single data Node" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>> LoadSingleDataNodeParametersAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n return await querySource.LoadCurrentAndPreviousParameterAsync(args, x => x.DataNode);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "### Inter data Node" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task>>> LoadInterDataNodeParametersAsync(this IQuerySource querySource, Args args)", - "\n{", - "\n var identityExpressions = new Func[]{x => x.DataNode, x => x.LinkedDataNode,};", - "\n var parameterArray = (await querySource.LoadParameterAsync(args.Year, args.Month));", - "\n var parameters = identityExpressions.SelectMany(ie => parameterArray.GroupBy(ie));", - "\n ", - "\n return parameters.SelectMany(p => p", - "\n .GroupBy(x => x.DataNode != p.Key ? x.DataNode : x.LinkedDataNode)", - "\n .Select(gg =>", - "\n {", - "\n var currentCandidate = gg.Where(x => x.Year == args.Year).OrderByDescending(x => x.Month).FirstOrDefault();", - "\n var previousCandidate = gg.Where(x => x.Year < args.Year).OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).FirstOrDefault();", - "\n return (key: p.Key,", - "\n currentPeriod: currentCandidate != null ? currentCandidate : previousCandidate,", - "\n previousPeriod: previousCandidate != null ? previousCandidate : currentCandidate);", - "\n })", - "\n )", - "\n .ToDictionaryGrouped(x => x.key,", - "\n x => new Dictionary>{ {CurrentPeriod, x.Select(y => y.currentPeriod).ToHashSet()},", - "\n {PreviousPeriod, x.Select(y => y.previousPeriod).ToHashSet()}});", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Aoc Step Configuration" - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadAocStepConfigurationAsync(this IQuerySource querySource, int year, int month)", - "\n => (await querySource.LoadParameterAsync(year, month)).GroupBy(x => (x.AocType, x.Novelty), (k, v) => v.OrderByDescending(x => x.Year).ThenByDescending(x => x.Month).First()); " - ] - }, - { - "cell_type": "code", - "source": [ - "public static async Task> LoadAocStepConfigurationAsDictionaryAsync(this IQuerySource querySource, int year, int month) => (await querySource.LoadAocStepConfigurationAsync(year, month)).ToDictionary(x => new AocStep(x.AocType, x.Novelty)); " - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Export Configurations" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Main Tab" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder MainTabConfigurationWoScenario(this IDocumentBuilder builder, T args) where T : IfrsPartition", - "\n => builder.WithTable( config => config .AtBeginning() ", - "\n .WithName(Main) ", - "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.Scenario, x => x.Delete()));" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder MainTabConfiguration(this IDocumentBuilder builder, T args) where T : IfrsPartition", - "\n => builder.WithTable( config => config .AtBeginning() ", - "\n .WithName(Main) ", - "\n .WithSource(source => args.RepeatOnce().AsQueryable()) ", - "\n .WithColumn(x => x.Id, x => x.Delete()));" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Dimensions" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder PortfolioConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : Portfolio", - "\n => builder.WithTable(config => { ", - "\n if(DependsOnType != default)", - "\n config = config.DependsOn(DependsOnType); ", - "\n return config .AtBeginning() ", - "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", - "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete());", - "\n });" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IDocumentBuilder GroupofContractConfiguration(this IDocumentBuilder builder, Type DependsOnType = default) where T : GroupOfContract", - "\n => builder.WithTable(config => { ", - "\n if(DependsOnType != default)", - "\n config = config.DependsOn(DependsOnType); ", - "\n if(typeof(T).Name == nameof(GroupOfInsuranceContract))", - "\n config = config.WithColumn(x => x.Partner, x => x.Delete());", - "\n return config .AtBeginning() ", - "\n .WithColumn(x => x.DisplayName, x => x.AtBeginning())", - "\n .WithColumn(x => x.SystemName, x => x.AtBeginning())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.ContractualCurrency, x => x.Delete())", - "\n .WithColumn(x => x.FunctionalCurrency, x => x.Delete())", - "\n .WithColumn(x => x.LineOfBusiness, x => x.Delete())", - "\n .WithColumn(x => x.OciType, x => x.Delete())", - "\n .WithColumn(x => x.ValuationApproach, x => x.Delete());", - "\n });" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node State" - ] - }, - { - "cell_type": "code", - "source": [ - "using DocumentFormat.OpenXml.Spreadsheet;" - ] - }, - { - "cell_type": "code", - "source": [ - "public record HelperState { public string State {get; init;} }" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder DataNodeStateConfiguration (this IExcelDocumentBuilder builder, DataNodeState[] data)", - "\n => builder", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data.AsQueryable())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.State, y => y.WithDataValidation(z => z.WithReferenceTo(t => t.State)))", - "\n );" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder StateEnumConfiguration (this IExcelDocumentBuilder builder)", - "\n{", - "\n var helperState = new[] {new HelperState {State = \"Active\"}, new HelperState {State = \"Inactive\"} }; ", - "\n return builder.WithTable( config => config .WithSheetVisibility(SheetStateValues.Hidden)", - "\n //.WithColumn(x => x.State, z => z.WithNamedRange(y => y.WithName(\"HelperState_State\")))", - "\n .WithColumn(x => x.State, z => z.WithDefaultNamedRange())", - "\n .WithSource(source => helperState.AsQueryable()) );", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Node Parameter" - ] - }, - { - "cell_type": "code", - "source": [ - "public static IExcelDocumentBuilder DataNodeParameterConfiguration (this IExcelDocumentBuilder builder, Dictionary data)", - "\n => builder", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(x => x.Delete())", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data[nameof(InterDataNodeParameter)].Cast().AsQueryable())", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n )", - "\n .WithTable(config => config ", - "\n .AtBeginning() ", - "\n .WithSource(source => data[nameof(SingleDataNodeParameter)].Cast().AsQueryable())", - "\n .WithColumn(x => x.DataNode, x => x.WithHeader(\"DataNode\"))", - "\n .WithColumn(x => x.Partition, x => x.Delete())", - "\n .WithColumn(x => x.Month, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Year, x => x.Delete())", - "\n .WithColumn(x => x.Id, x => x.Delete())", - "\n );" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Report Configurations" - ] - }, - { - "cell_type": "code", - "source": [ - "using Systemorph.Vertex.Pivot.Reporting.Builder;" - ] - }, - { - "cell_type": "code", - "source": [ - "public static ReportBuilder WithGridOptionsForIfrsVariable", - "\n(this ReportBuilder reportBuilder, int reportHeight = 650)", - "\n{", - "\n return reportBuilder.WithGridOptions(go => go.WithColumns(cols => cols.Modify(\"Value\", c => c.WithWidth(300)", - "\n .WithFormat(\"new Intl.NumberFormat('en',{ minimumFractionDigits:2, maximumFractionDigits:2 }).format(value)\")))", - "\n .WithRows(rows => rows.Where(r => !r.RowGroup.SystemName.EndsWith(\"NullGroup\")).ToList())", - "\n .WithAutoGroupColumn(c => c.WithWidth(250) with { Pinned = \"left\" }) with { Height = reportHeight, GroupDefaultExpanded = 2, OnGridReady = null }", - "\n );", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Utility Methods Class" - ] - }, - { - "cell_type": "markdown", - "source": [ - "This class contains:", - "\n- EqualityComparer" - ] - }, - { - "cell_type": "code", - "source": [ - "public static class Utils {", - "\n public static void EqualityComparer (T[] collection1, T[] collection2) ", - "\n {", - "\n collection1.Length.Should().Be(collection2.Length);", - "\n var type = typeof(T);", - "\n var properties = type.GetProperties().Where(p => p.Name != \"Id\").ToArray();", - "\n if(properties.Count() == 0) {", - "\n bool isEqual = Enumerable.SequenceEqual(collection1, collection2);", - "\n isEqual.Should().Be(true);", - "\n }", - "\n foreach(var item1 in collection1) {", - "\n var item2 = collection2.Where(x => ", - "\n properties.All(prop => {", - "\n var propType = prop.PropertyType;", - "\n var val = prop.GetValue(item1);", - "\n var otherVal = prop.GetValue(x);", - "\n if(val == null && otherVal == null) return true;", - "\n else if((val != null && otherVal == null) || (val == null && otherVal != null)) return false;", - "\n else return Convert.ChangeType(otherVal, propType).Equals( Convert.ChangeType(val, propType) );", - "\n })", - "\n );", - "\n item2.Count().Should().NotBe(0);", - "\n }", - "\n }", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "// TODO: find a better arrangement to these methods", - "\nstatic var NumericalPrecisionEqualityChecker = 1.0E-10;", - "\n", - "\nstatic bool CheckEquality(this double[] arr1, double[] arr2) ", - "\n{", - "\n if(arr1.Length != arr2.Length) return false;", - "\n for(int i = 0; i < arr1.Length; i++) {", - "\n double d1 = arr1[i];", - "\n double d2 = arr2[i];", - "\n if(Math.Abs(d1) < NumericalPrecisionEqualityChecker && Math.Abs(d1) < NumericalPrecisionEqualityChecker) continue;", - "\n if(Math.Abs( (d1 - d2) / d1 ) > NumericalPrecisionEqualityChecker) return false;", - "\n }", - "\n return true;", - "\n}", - "\n", - "\nstatic bool CheckEquality(this IEnumerable arr1, double[] arr2) => CheckEquality(arr1.ToArray(), arr2);", - "\nstatic bool CheckEquality(this double[] arr1, IEnumerable arr2) => CheckEquality(arr1, arr2.ToArray());", - "\nstatic bool CheckEquality(this IEnumerable arr1, IEnumerable arr2) => CheckEquality(arr1.ToArray(), arr2.ToArray());", - "\nstatic bool CheckEquality(this double d1, double d2) => CheckEquality(d1.RepeatOnce(), d2.RepeatOnce());", - "\n", - "\nstatic bool CheckEquality(this double? d1, double? d2) ", - "\n{", - "\n if(d1 == null && d2 == null) return true;", - "\n else return CheckEquality((double)d1, (double)d2);", - "\n}", - "\n" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## ToIdentityString" - ] - }, - { - "cell_type": "code", - "source": [ - "using System.Text;", - "\npublic static string ToIdentityString(this T v)", - "\n where T : class", - "\n{", - "\n StringBuilder sb = new StringBuilder();", - "\n var propertyInfos = v.GetType()", - "\n .GetProperties()", - "\n .Where(x => Attribute.IsDefined(x, typeof(IdentityPropertyAttribute)))", - "\n .OrderByDescending(x => x.PropertyType.Name).ThenByDescending(x => x.Name)", - "\n .Select(x => sb.Append(x.Name).Append(\":\").Append(v.GetType().GetProperty(x.Name)?.GetValue(v, null)).Append(\", \"));", - "\n", - "\nreturn propertyInfos.Select(p => p.ToString()).ToArray().Last();", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## GetPreviousIdentities" - ] - }, - { - "cell_type": "code", - "source": [ - "public static Dictionary> GetPreviousIdentities(IEnumerable identities)", - "\n{", - "\n var bopNovelties = identities.Where(id => id.AocType == AocTypes.BOP).Select(id => id.Novelty);", - "\n var previousStep = (new string[]{Novelties.N,Novelties.I,Novelties.C})", - "\n .ToDictionary(n => n, n => bopNovelties.Contains(n) ? new AocStep(AocTypes.BOP,n) : null);", - "\n return identities.Where(id => id.AocType != AocTypes.BOP)", - "\n .ToDictionary(x => x, x => {var ret = x.AocType == AocTypes.CL ? previousStep.Where(kvp => kvp.Value != null).Select(kvp => kvp.Value).ToArray() ", - "\n : previousStep[x.Novelty].RepeatOnce();", - "\n previousStep[x.Novelty] = new AocStep(x.AocType, x.Novelty);", - "\n return ret;});", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## GetReferenceAocStepForCalculated" - ] - }, - { - "cell_type": "code", - "source": [ - "public static AocStep GetReferenceAocStepForCalculated(this IEnumerable identities, Dictionary aocConfigurationByAocStep, AocStep identityAocStep)", - "\n{", - "\n return identities.LastOrDefault(aocStep => aocConfigurationByAocStep[aocStep].DataType != DataType.Calculated", - "\n && aocConfigurationByAocStep[aocStep].DataType != DataType.CalculatedTelescopic", - "\n && aocConfigurationByAocStep[aocStep].Order < aocConfigurationByAocStep[identityAocStep].Order", - "\n && aocStep.Novelty == identityAocStep.Novelty) ", - "\n ?? new AocStep(default, default);", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Change Sign Rules" - ] - }, - { - "cell_type": "code", - "source": [ - "public static int GetSign((string AocType, string AmountType, string EstimateType, bool IsReinsurance) variable, Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", - "\n{", - "\n var isActual = (new string[] { EstimateTypes.AA, EstimateTypes.OA, EstimateTypes.A }).Contains(variable.EstimateType) ? -1 : 1;", - "\n return isActual;", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# EstimateType And AmountType" - ] - }, - { - "cell_type": "code", - "source": [ - "public static Dictionary> GetAmountTypesByEstimateType(Systemorph.Vertex.Hierarchies.IHierarchicalDimensionCache hierarchyCache)", - "\n{", - "\n return new Dictionary>(){", - "\n {EstimateTypes.RA, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.C, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.L, new string[]{}.ToHashSet()},", - "\n {EstimateTypes.LR, new string[]{}.ToHashSet()},", - "\n };", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Technical Margin EstimateType" - ] - }, - { - "cell_type": "code", - "source": [ - "public static HashSet GetTechnicalMarginEstimateType()", - "\n{", - "\n return new []{EstimateTypes.C, EstimateTypes.L, EstimateTypes.LR, }.ToHashSet();", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Discount and Cumulate" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double[] ComputeDiscountAndCumulate(this double[] nominalValues, double[] monthlyDiscounting, PeriodType periodType) ", - "\n{ ", - "\n if(nominalValues == null) return Enumerable.Empty().ToArray();", - "\n ", - "\n var ret = new double[nominalValues.Length];", - "\n ", - "\n if(periodType == PeriodType.BeginningOfPeriod)", - "\n {", - "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", - "\n ret[i] = nominalValues[i] + GetElementOrDefault(ret, i + 1) * GetElementOrDefault(monthlyDiscounting, i/12);", - "\n return ret;", - "\n }", - "\n ", - "\n for (var i = nominalValues.Length - 1; i >= 0; i--)", - "\n ret[i] = ( nominalValues[i] + GetElementOrDefault(ret, i + 1) ) * GetElementOrDefault(monthlyDiscounting, i/12);", - "\n ", - "\n return ret;", - "\n}" - ] - }, - { - "cell_type": "code", - "source": [ - "public static double[] ComputeDiscountAndCumulateWithCreditDefaultRisk(this double[] nominalValues, double[] monthlyDiscounting, double nonPerformanceRiskRate) //Is it correct that NonPerformanceRiskRate is a double? Should it be an array that takes as input tau/t?", - "\n{ ", - "\n return Enumerable.Range(0, nominalValues.Length)", - "\n .Select( t => Enumerable.Range(t, nominalValues.Length-t)", - "\n .Select( tau => nominalValues[tau] * Math.Pow(GetElementOrDefault(monthlyDiscounting, t/12), tau-t+1) * (Math.Exp(-nonPerformanceRiskRate*(tau-t)) - 1) )", - "\n .Sum() )", - "\n .ToArray();", - "\n}" - ] - }, - { - "cell_type": "markdown", - "source": [ - "# Import Configuration" - ] - }, - { - "cell_type": "markdown", - "source": [ - "## Data Nodes" - ] - }, - { - "cell_type": "code", - "source": [ - "public GroupOfInsuranceContract ExtendGroupOfContract(GroupOfInsuranceContract gic, IDataRow datarow) => gic;" - ] - }, - { - "cell_type": "code", - "source": [ - "public GroupOfReinsuranceContract ExtendGroupOfContract(GroupOfReinsuranceContract gric, IDataRow datarow) => gric;" - ] - }, - { - "cell_type": "code", - "source": [ - "" - ] - } - ] -} \ No newline at end of file