diff --git a/PresentValueSeries/CF_CH_2021_12.xlsx b/PresentValueSeries/CF_CH_2021_12.xlsx index bdc502b9..a7156d0c 100644 Binary files a/PresentValueSeries/CF_CH_2021_12.xlsx and b/PresentValueSeries/CF_CH_2021_12.xlsx differ diff --git a/PresentValueSeries/CF_DE_2021_12.xlsx b/PresentValueSeries/CF_DE_2021_12.xlsx index 72fb2aff..5d1be035 100644 Binary files a/PresentValueSeries/CF_DE_2021_12.xlsx and b/PresentValueSeries/CF_DE_2021_12.xlsx differ diff --git a/PresentValueSeries/CF_DE_2022_12.xlsx b/PresentValueSeries/CF_DE_2022_12.xlsx index fe5e13b8..cbcadc97 100644 Binary files a/PresentValueSeries/CF_DE_2022_12.xlsx and b/PresentValueSeries/CF_DE_2022_12.xlsx differ diff --git a/PresentValueSeries/Cashflows.xlsx b/PresentValueSeries/Cashflows.xlsx index 1b1ffd52..acc96124 100644 Binary files a/PresentValueSeries/Cashflows.xlsx and b/PresentValueSeries/Cashflows.xlsx differ diff --git a/ifrs17-template/Files/Parameters/YieldCurve.csv b/ifrs17-template/Files/Parameters/YieldCurve.csv deleted file mode 100644 index 54460671..00000000 --- a/ifrs17-template/Files/Parameters/YieldCurve.csv +++ /dev/null @@ -1,14 +0,0 @@ -@@YieldCurve,,,,,, -Currency,Year,Month,Values0,Values1,Values2,Values3 -EUR,2020,3,0.008685495,0.008685495,0.018498471,0.019966839 -CHF,2019,12,0,0,0.015,0.02 -CHF,2020,12,0.01,0.02,0.025,0.025 -CHF,2021,6,0.03,0.03,0.035,0.035 -CHF,2021,12,0.025,0.025,0.035,0.035 -USD,2021,3,0.005,0.005,0.005,0.005 -USD,2020,12,0.002,0.002,0.002,0.002 -USD,2020,3,0.002,0.002,0.002,0.002 -USD,2020,1,0.002,0.002,0.002,0.002 -GBP,2020,3,0.01,0.015,0.02,0.02 -GBP,2021,3,0.015,0.02,0.02,0.025 -XTSHY,2019,12,0.85,0.85,0.85,0.85 diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2019_12.csv b/ifrs17-template/Files/Parameters/YieldCurve_2019_12.csv new file mode 100644 index 00000000..657f3e7e --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2019_12.csv @@ -0,0 +1,7 @@ +@@Main +Year,Month +2019,12 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +CHF,0,0,0.015,0.02 +XTSHY,0.85,0.85,0.85,0.85 \ No newline at end of file diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2020_1.csv b/ifrs17-template/Files/Parameters/YieldCurve_2020_1.csv new file mode 100644 index 00000000..c94e347e --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2020_1.csv @@ -0,0 +1,7 @@ +@@Main +Year,Month +2020,12 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +USD,0.002,0.002,0.002,0.002 + diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2020_12.csv b/ifrs17-template/Files/Parameters/YieldCurve_2020_12.csv new file mode 100644 index 00000000..48e9669d --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2020_12.csv @@ -0,0 +1,8 @@ +@@Main +Year,Month +2020,1 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +USD,0.002,0.002,0.002,0.002 +CHF,0.01,0.02,0.025,0.025 + diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2020_3.csv b/ifrs17-template/Files/Parameters/YieldCurve_2020_3.csv new file mode 100644 index 00000000..266e8682 --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2020_3.csv @@ -0,0 +1,8 @@ +@@Main +Year,Month +2020,3 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +EUR,0.008685495,0.008685495,0.018498471,0.019966839 +USD,0.002,0.002,0.002,0.002 +GBP,0.01,0.015,0.02,0.02 diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2021_12.csv b/ifrs17-template/Files/Parameters/YieldCurve_2021_12.csv new file mode 100644 index 00000000..ef5b7414 --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2021_12.csv @@ -0,0 +1,6 @@ +@@Main +Year,Month +2021,12 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +CHF,0.025,0.025,0.035,0.035 diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2021_3.csv b/ifrs17-template/Files/Parameters/YieldCurve_2021_3.csv new file mode 100644 index 00000000..5386ae88 --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2021_3.csv @@ -0,0 +1,7 @@ +@@Main +Year,Month +2021,3 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +USD,0.005,0.005,0.005,0.005 +GBP,0.015,0.02,0.02,0.025 diff --git a/ifrs17-template/Files/Parameters/YieldCurve_2021_6.csv b/ifrs17-template/Files/Parameters/YieldCurve_2021_6.csv new file mode 100644 index 00000000..65e212d4 --- /dev/null +++ b/ifrs17-template/Files/Parameters/YieldCurve_2021_6.csv @@ -0,0 +1,6 @@ +@@Main +Year,Month +2021,6 +@@YieldCurve +Currency,Values0,Values1,Values2,Values3 +CHF,0.03,0.03,0.035,0.035 diff --git a/ifrs17-template/Initialization/InitSystemorphRefDataToMemory.ipynb b/ifrs17-template/Initialization/InitSystemorphRefDataToMemory.ipynb index ad4e7b83..f4c5b6f8 100644 --- a/ifrs17-template/Initialization/InitSystemorphRefDataToMemory.ipynb +++ b/ifrs17-template/Initialization/InitSystemorphRefDataToMemory.ipynb @@ -154,7 +154,14 @@ { "cell_type": "code", "source": [ - "await Import.FromFile(\"../Files/Parameters/YieldCurve.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" + "var log = await Import.FromFile(\"../Files/Parameters/YieldCurve_2019_12.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync();", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2020_1.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2020_3.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2020_12.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2021_3.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2021_6.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2021_12.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog" ], "metadata": {}, "execution_count": 0, @@ -204,15 +211,6 @@ "metadata": {}, "execution_count": 0, "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "" - ], - "metadata": {}, - "execution_count": 0, - "outputs": [] } ] } \ No newline at end of file diff --git a/ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb b/ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb index 65138c29..a8aea982 100644 --- a/ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb +++ b/ifrs17-template/Initialization/InitSystemorphToDatabase.ipynb @@ -123,7 +123,14 @@ { "cell_type": "code", "source": [ - "await Import.FromFile(\"../Files/Parameters/YieldCurve.csv\").WithType().WithTarget(DataSource).ExecuteAsync()" + "var log = await Import.FromFile(\"../Files/Parameters/YieldCurve_2019_12.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync();", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2020_1.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2020_3.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2020_12.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2021_3.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2021_6.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog.Merge(await Import.FromFile(\"../Files/Parameters/YieldCurve_2021_12.csv\").WithFormat(ImportFormats.YieldCurve).WithTarget(DataSource).ExecuteAsync());", + "\nlog" ], "metadata": {}, "execution_count": 0, diff --git a/ifrs17/Constants/Consts.ipynb b/ifrs17/Constants/Consts.ipynb index ceb279db..08842d5a 100644 --- a/ifrs17/Constants/Consts.ipynb +++ b/ifrs17/Constants/Consts.ipynb @@ -63,6 +63,15 @@ "execution_count": 0, "outputs": [] }, + { + "cell_type": "code", + "source": [ + "public const double YieldCurvePrecision = 1E-8;" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "markdown", "source": [ @@ -198,6 +207,7 @@ "\n public const string Opening = nameof(Opening); // Importer for Opening Balances (BOP Inforce of CSM/LC)", "\n public const string SimpleValue = nameof(SimpleValue); // Importer for Simple Values (pre-calculated direct import)", "\n", + "\n public const string YieldCurve = nameof(YieldCurve); // Importer for Yield Curve", "\n public const string DataNode = nameof(DataNode); // Importer for Data Node", "\n public const string DataNodeState = nameof(DataNodeState); // Importer for Data Node State", "\n public const string DataNodeParameter = nameof(DataNodeParameter); // Importer for Data Node Parameters", diff --git a/ifrs17/DataModel/DataStructure.ipynb b/ifrs17/DataModel/DataStructure.ipynb index a9275444..2521b257 100644 --- a/ifrs17/DataModel/DataStructure.ipynb +++ b/ifrs17/DataModel/DataStructure.ipynb @@ -189,31 +189,6 @@ "execution_count": 0, "outputs": [] }, - { - "cell_type": "markdown", - "source": [ - "The interface IHierarchy is used for modelling dimensions which have an hierarchical structure, such as [Amount Type](#amount-type)." - ], - "metadata": {}, - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "code", - "source": [ - "public interface IHierarchy", - "\n{", - "\n public string Name { get; init; }", - "\n ", - "\n public string Parent { get; init; }", - "\n ", - "\n public string Child { get; init; }", - "\n}" - ], - "metadata": {}, - "execution_count": 0, - "outputs": [] - }, { "cell_type": "markdown", "source": [ diff --git a/ifrs17/Import/Importers.ipynb b/ifrs17/Import/Importers.ipynb index 01482d48..638f6679 100644 --- a/ifrs17/Import/Importers.ipynb +++ b/ifrs17/Import/Importers.ipynb @@ -239,7 +239,7 @@ { "cell_type": "markdown", "source": [ - "## Clean the Database" + "## Clean the Target QuerySource" ], "metadata": {}, "execution_count": 0, @@ -248,10 +248,10 @@ { "cell_type": "code", "source": [ - "async public Task CleanDatabaseAsync (Expression> filter = null) where T : class", + "public static async Task CleanAsync (this IDataSource dataSource, Expression> filter = null) where T : class", "\n{", - "\n var loadData = await DataSource.Query().Where(filter?? (Expression>)(x => true)).ToListAsync();", - "\n await DataSource.DeleteAsync(loadData);", + "\n var loadData = await dataSource.Query().Where(filter?? (Expression>)(x => true)).ToListAsync();", + "\n await dataSource.DeleteAsync(loadData);", "\n}" ], "metadata": {}, @@ -261,7 +261,9 @@ { "cell_type": "markdown", "source": [ - "## Update the Database" + "## Update the Target DataSource", + "\n", + "\nSource and target data space are of type IDataSource to allow update and commit to a Workspace or to a DataSource." ], "metadata": {}, "execution_count": 0, @@ -270,17 +272,17 @@ { "cell_type": "code", "source": [ - "public async Task CommitToDatabase (IWorkspace workspace, Guid partitionId = new Guid(), bool snapshot = true, Expression> filter = null) ", + "public static async Task CommitToAsync (this IDataSource source, IDataSource target, Guid partitionId = default, bool snapshot = true, Expression> filter = null) ", "\nwhere TData : class, IPartitioned", "\nwhere TPartition : IfrsPartition", "\n{", "\n if(partitionId != new Guid()) {", - "\n await workspace.Partition.SetAsync(partitionId);", - "\n await DataSource.Partition.SetAsync(partitionId);", + "\n await target.Partition.SetAsync(partitionId);", + "\n await source.Partition.SetAsync(partitionId);", "\n }", - "\n if(snapshot) await CleanDatabaseAsync(filter);", - "\n await DataSource.UpdateAsync( await workspace.Query().ToArrayAsync() );", - "\n await DataSource.CommitAsync();", + "\n if(snapshot) await CleanAsync(target, filter);", + "\n await target.UpdateAsync( await source.Query().ToArrayAsync() );", + "\n await target.CommitAsync();", "\n}" ], "metadata": {}, @@ -299,9 +301,11 @@ { "cell_type": "markdown", "source": [ - "## Parse Main Tab and return Args", + "## Parse the Main Tab", + "\n", + "\nThe main table of our custom import formats contains the information which are required to identify the data partition depending on the ImportFormat. These information are temporarily stored in [Args](../DataModel/DataStructure#args) and used in the next methods.", "\n", - "\nThe main table of our custom import formats contains the information which are required to identify the data partition. These information are temporarily stored in [Args](../DataModel/DataStructure#args) and used in the next methods." + "\nGetArgsFromMain performes basic valiadations on the existance of the main tab. Then reads the reporting node, year, month, and scenario and return an ImportArgs with the results. If any of these information a default value is returned and will be validated in the following methods. " ], "metadata": {}, "execution_count": 0, @@ -310,50 +314,82 @@ { "cell_type": "code", "source": [ - "public async Task GetArgsFromMainAsync(IDataSet dataSet)", - "\n{", + "public ImportArgs GetArgsFromMain(IDataSet dataSet) {", "\n var mainTab = dataSet.Tables[Main];", "\n if(mainTab == null) ApplicationMessage.Log(Error.NoMainTab);", - "\n if(mainTab.Rows.Count() == 0) ApplicationMessage.Log(Error.IncompleteMainTab);", - "\n if(mainTab.Columns.FirstOrDefault(x => x.ColumnName == nameof(ReportingNode)) == null) ApplicationMessage.Log(Error.ReportingNodeInMainNotFound);", + "\n if(!mainTab.Rows.Any()) ApplicationMessage.Log(Error.IncompleteMainTab);", "\n if(ApplicationMessage.HasErrors()) return null;", - "\n ", + "\n", "\n var main = mainTab.Rows.First();", - "\n var reportingNode = (string)main[nameof(ReportingNode)];", - "\n var scenario = mainTab.Columns.Where(x => x.ColumnName == nameof(Scenario)).Count()>0? (string)main[nameof(Scenario)] : default(string);", - "\n ", + "\n var reportingNode = mainTab.Columns.Any(x => x.ColumnName == nameof(Args.ReportingNode)) ? (string)main[nameof(ReportingNode)] : default(string);", + "\n var scenario = mainTab.Columns.Any(x => x.ColumnName == nameof(Args.Scenario)) ? (string)main[nameof(Scenario)] : default(string);", + "\n var year = mainTab.Columns.Any(x => x.ColumnName == nameof(Args.Year)) ? (int)Convert.ChangeType(main[nameof(Args.Year)], typeof(int)) : default(int);", + "\n var month = mainTab.Columns.Any(x => x.ColumnName == nameof(Args.Month)) ? (int)Convert.ChangeType(main[nameof(Args.Month)], typeof(int)) : default(int);", + "\n", + "\n return new ImportArgs(reportingNode, year, month, default(Periodicity), scenario, default(string));", + "\n}" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "A validation method which checks year and month. Log errors if any is missing. " + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "public static void ValidateArgsForPeriod(this ImportArgs args) {", + "\n if(args.Year == default(int)) ApplicationMessage.Log(Error.YearInMainNotFound);", + "\n if(args.Month == default(int)) ApplicationMessage.Log(Error.MonthInMainNotFound);", + "\n}" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "## Get Args and commit Partition", + "\n", + "\nThis is the main method to get Args which reference a specific data partition. All validations are triggered after parsing and if the partition is not already existing in the DataSource it is created and committed. " + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "public async Task GetArgsAndCommitPartitionAsync(IDataSet dataSet)", + "\n{", + "\n var args = GetArgsFromMain(dataSet);", "\n if(ApplicationMessage.HasErrors()) return null;", + "\n if(args.ReportingNode == default(string)) { ApplicationMessage.Log(Error.ReportingNodeInMainNotFound); return null; }", "\n", - "\n ImportArgs args;", "\n switch(typeof(IPartition).Name) {", "\n case nameof(PartitionByReportingNode) : {", - "\n args = new ImportArgs( reportingNode,", - "\n default(int),", - "\n default(int),", - "\n default(Periodicity),", - "\n scenario,", - "\n default(string));", "\n await DataSource.UpdateAsync( new[] { new PartitionByReportingNode { ", "\n Id = (Guid)(await DataSource.Partition.GetKeyForInstanceAsync(args)),", - "\n ReportingNode = reportingNode } } );", + "\n ReportingNode = args.ReportingNode } } );", "\n break;", "\n }", "\n case nameof(PartitionByReportingNodeAndPeriod) : {", - "\n if(mainTab.Columns.Where(x => x.ColumnName == nameof(PartitionByReportingNodeAndPeriod.Year)).Count()!=1) ApplicationMessage.Log(Error.YearInMainNotFound);", - "\n if(mainTab.Columns.Where(x => x.ColumnName == nameof(PartitionByReportingNodeAndPeriod.Month)).Count()!=1) ApplicationMessage.Log(Error.MonthInMainNotFound);", + "\n args.ValidateArgsForPeriod();", "\n if(ApplicationMessage.HasErrors()) return null;", - "\n args = new ImportArgs( reportingNode, ", - "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Year)], typeof(int)),", - "\n (int)Convert.ChangeType(main[nameof(PartitionByReportingNodeAndPeriod.Month)], typeof(int)),", - "\n default(Periodicity),", - "\n scenario,", - "\n default(string) );", "\n await DataSource.UpdateAsync( new[]{ new PartitionByReportingNodeAndPeriod { ", "\n Id = (Guid)(await DataSource.Partition.GetKeyForInstanceAsync(args)),", "\n Year = args.Year,", "\n Month = args.Month,", - "\n ReportingNode = reportingNode, ", - "\n Scenario = scenario } } );", + "\n ReportingNode = args.ReportingNode, ", + "\n Scenario = args.Scenario } } );", "\n break;", "\n }", "\n default : {", @@ -435,7 +471,12 @@ { "cell_type": "markdown", "source": [ - "## Get Target Args" + "## Calculate IFRS Variables", + "\n", + "\nThe following methods are used in the different importers to compute the [IfrsVariables](../DataModel/DataStructure#ifrs-variable).", + "\n", + "\nGetAllArgsAsync retrieves the partitions or Args that require computation. They are the union of the primary args (the one read from the main tab of the imported file) with the secondary args (senarios which depends on the best estimate data).", + "\nComputeAsync computes the IfrsVariables for a given partition (identified by its ImportArgs) and stores the results in a disposable workspace. This then serves as DataSource in the calculation of the secondary partitions (identified by the secondary args)." ], "metadata": {}, "execution_count": 0, @@ -444,28 +485,20 @@ { "cell_type": "code", "source": [ - "public async Task GetTargetArgsAsync(ImportArgs mainArgs)", + "public async Task GetAllArgsAsync(ImportArgs primaryArgs)", "\n{", - "\n var scenarioArgs = await DataSource.Query() ", - "\n .Where(x => x.ReportingNode == mainArgs.ReportingNode && x.Year == mainArgs.Year && x.Month == mainArgs.Month && x.Scenario != null)", + "\n if (primaryArgs.Scenario != null)", + "\n return primaryArgs.RepeatOnce().ToArray();", + "\n", + "\n var secondaryArgs = await DataSource.Query() ", + "\n .Where(x => x.ReportingNode == primaryArgs.ReportingNode && x.Year == primaryArgs.Year && x.Month == primaryArgs.Month && x.Scenario != null)", "\n .Select(x => new ImportArgs(x.ReportingNode, x.Year, x.Month, default(Periodicity), x.Scenario, ImportFormats.Cashflow)).ToArrayAsync();", - "\n var isMultipleArg = mainArgs.Scenario == null && scenarioArgs.Any();", - "\n var targetArgs = isMultipleArg", - "\n ? mainArgs.RepeatOnce().Concat(scenarioArgs)", - "\n : mainArgs.RepeatOnce();", - "\n", - "\n if (isMultipleArg) ApplicationMessage.Log(Warning.ScenarioReCalculations, String.Join(\", \", scenarioArgs.Select(x => x.Scenario)));", - "\n return targetArgs.ToArray();", - "\n} " - ], - "metadata": {}, - "execution_count": 0, - "outputs": [] - }, - { - "cell_type": "markdown", - "source": [ - "## Calculate and Upload IFRS Variables" + "\n ", + "\n if (secondaryArgs.Any())", + "\n ApplicationMessage.Log(Warning.ScenarioReCalculations, String.Join(\", \", secondaryArgs.Select(x => x.Scenario)));", + "\n ", + "\n return primaryArgs.RepeatOnce().Concat(secondaryArgs).ToArray();", + "\n}" ], "metadata": {}, "execution_count": 0, @@ -474,10 +507,10 @@ { "cell_type": "code", "source": [ - "public async Task CalculateAndUploadVariablesAsync(ImportArgs args, IWorkspace workspace, bool saveRawVariables)", + "public async Task ComputeAsync(ImportArgs args, IWorkspace workspace, IWorkspace workspaceToCompute, bool saveRawVariables)", "\n{", "\n Activity.Start();", - "\n var storage = new ImportStorage(args, DataSource, workspace);", + "\n var storage = new ImportStorage(args, workspaceToCompute, workspace);", "\n await storage.InitializeAsync();", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", @@ -492,14 +525,13 @@ "\n ivs.Where(iv => Math.Abs(iv.Value) < Precision).Intersect(bestEstimateIvs, EqualityComparer.Instance).Select(iv => iv with {Value = 0.0}).ToArray());", "\n }", "\n", - "\n", "\n await workspace.UpdateAsync(ivs.Where(x => storage.DefaultPartition != storage.TargetPartition || Math.Abs(x.Value) >= Precision));", - "\n await CommitToDatabase(workspace, storage.TargetPartition, snapshot : true, ", + "\n await workspace.CommitToAsync(workspaceToCompute, storage.TargetPartition, snapshot : true, ", "\n filter : x => storage.EstimateTypesByImportFormat[args.ImportFormat].Contains(x.EstimateType) ", "\n && storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", "\n if(saveRawVariables) {", "\n if(args.Scenario == null) await workspace.DeleteAsync(await workspace.Query().Where(rv => rv.Values.Sum(x => Math.Abs(x)) < Precision).ToArrayAsync());", - "\n await CommitToDatabase(workspace, storage.TargetPartition, snapshot : true, ", + "\n await workspace.CommitToAsync(workspaceToCompute, storage.TargetPartition, snapshot : true, ", "\n filter : x => storage.DataNodesByImportScope[ImportScope.Primary].Contains(x.DataNode));", "\n }", "\n return Activity.Finish();", @@ -622,6 +654,69 @@ "execution_count": 0, "outputs": [] }, + { + "cell_type": "markdown", + "source": [ + "# Yield Curves ", + "\n", + "\n[Yield curves](../DataModel/DataStructure#yield-curve) are imported for a specific year, month, and scenario (not required if best estimate). This informations are collected in the main section of the file. ", + "\n", + "\nYield curves to be imported are compared against those already present in the DataSource and only the new ones are stored." + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "Import.DefineFormat(ImportFormats.YieldCurve, async (options, dataSet) => {", + "\n Activity.Start();", + "\n var args = GetArgsFromMain(dataSet) with {ImportFormat = ImportFormats.YieldCurve};", + "\n args.ValidateArgsForPeriod();", + "\n if(ApplicationMessage.HasErrors()) return Activity.Finish();", + "\n", + "\n var workspace = Workspace.CreateNew();", + "\n workspace.Initialize(x => x.FromSource(DataSource).DisableInitialization().DisableInitialization());", + "\n", + "\n var committedYieldCurves = await DataSource.Query().ToArrayAsync();", + "\n var hasNameColumn = dataSet.Tables[ImportFormats.YieldCurve].Columns.Any(x => x.ColumnName == nameof(YieldCurve.Name));", + "\n var importLog = await Import.FromDataSet(dataSet).WithType((dataset, datarow) => { ", + "\n var yieldCurve = new YieldCurve {", + "\n Currency = datarow.Field(nameof(YieldCurve.Currency)),", + "\n Year = args.Year,", + "\n Month = args.Month, ", + "\n Scenario = args.Scenario,", + "\n Values = datarow.Table.Columns.Where(c => c.ColumnName.StartsWith(nameof(YieldCurve.Values))).OrderBy(c => c.ColumnName.Length).ThenBy(c => c.ColumnName)", + "\n .Select(x => datarow.Field(x.ColumnName).CheckStringForExponentialAndConvertToDouble()).ToArray(),", + "\n Name = hasNameColumn", + "\n ? datarow.Field(nameof(YieldCurve.Name))", + "\n : default(string)", + "\n };", + "\n return committedYieldCurves.Contains(yieldCurve, YieldCurveComparer.Instance())", + "\n ? null", + "\n : yieldCurve;", + "\n }", + "\n ).WithTarget(workspace).ExecuteAsync(); ", + "\n ", + "\n if(importLog.Errors.Any()) return Activity.Finish().Merge(importLog); ", + "\n ", + "\n var toCommitYieldCurves = await workspace.Query().ToArrayAsync();", + "\n if (!toCommitYieldCurves.Any()){", + "\n ApplicationMessage.Log(Warning.VariablesAlreadyImported); ", + "\n return Activity.Finish().Merge(importLog);", + "\n }", + "\n ", + "\n await DataSource.UpdateAsync(toCommitYieldCurves);", + "\n await DataSource.CommitAsync();", + "\n ", + "\n return Activity.Finish().Merge(importLog);", + "\n});" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, { "cell_type": "markdown", "source": [ @@ -655,7 +750,7 @@ "\n .DisableInitialization());", "\n ", "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(dataSet);", + "\n var args = await GetArgsAndCommitPartitionAsync(dataSet);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var storage = new ParsingStorage(args, DataSource, workspace);", @@ -756,10 +851,10 @@ "\n var workspace = Workspace.CreateNew();", "\n var log = await UploadDataNodesToWorkspaceAsync(dataSet, workspace);", "\n var partition = (Guid)workspace.Partition.GetCurrent(nameof(PartitionByReportingNode));", - "\n await CommitToDatabase(workspace, partition);", - "\n await CommitToDatabase(workspace, partition);", - "\n await CommitToDatabase(workspace, partition);", - "\n await CommitToDatabase(workspace, partition);", + "\n await workspace.CommitToAsync(DataSource, partition);", + "\n await workspace.CommitToAsync(DataSource, partition);", + "\n await workspace.CommitToAsync(DataSource, partition);", + "\n await workspace.CommitToAsync(DataSource, partition);", "\n return log;", "\n});" ], @@ -811,7 +906,7 @@ "\n .DisableInitialization()", "\n .DisableInitialization());", "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(dataSet);", + "\n var args = await GetArgsAndCommitPartitionAsync(dataSet) with {ImportFormat = ImportFormats.DataNodeState};", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var storage = new ParsingStorage(args, DataSource, workspace);", @@ -842,7 +937,7 @@ "Import.DefineFormat(ImportFormats.DataNodeState, async (options, dataSet) => {", "\n var workspace = Workspace.CreateNew();", "\n var log = await UploadDataNodeStateToWorkspaceAsync(dataSet, workspace);", - "\n await CommitToDatabase(workspace, (Guid)workspace.Partition.GetCurrent(nameof(PartitionByReportingNode)), snapshot: false); ", + "\n await workspace.CommitToAsync(DataSource, (Guid)workspace.Partition.GetCurrent(nameof(PartitionByReportingNode)), snapshot: false); ", "\n return log;", "\n});" ], @@ -870,7 +965,7 @@ "\n .DisableInitialization()", "\n .DisableInitialization());", "\n Activity.Start();", - "\n var args = await GetArgsFromMainAsync(dataSet) with {ImportFormat = ImportFormats.DataNodeParameter};", + "\n var args = await GetArgsAndCommitPartitionAsync(dataSet) with {ImportFormat = ImportFormats.DataNodeParameter};", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", "\n var storage = new ParsingStorage(args, DataSource, workspace);", @@ -954,8 +1049,8 @@ "\n Guid partitionId = new Guid();", "\n var workspace = Workspace.CreateNew();", "\n var log = await UploadDataNodeParameterToWorkspaceAsync(dataSet, partitionId, workspace);", - "\n await CommitToDatabase(workspace, partitionId, snapshot: false);", - "\n await CommitToDatabase(workspace, partitionId, snapshot: false); ", + "\n await workspace.CommitToAsync(DataSource, partitionId, snapshot: false);", + "\n await workspace.CommitToAsync(DataSource, partitionId, snapshot: false); ", "\n ", "\n return log;", "\n});" @@ -992,8 +1087,7 @@ "\n await parsingStorage.InitializeAsync();", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", - "\n var hasAccidentYearColumn = dataSet.Tables[ImportFormats.Cashflow].Columns.Where(x => x.ColumnName == nameof(RawVariable.AccidentYear)).Count() > 0; ", - "\n ", + "\n var hasAccidentYearColumn = dataSet.Tables[ImportFormats.Cashflow].Columns.Any(x => x.ColumnName == nameof(RawVariable.AccidentYear));", "\n var importLog = await Import.FromDataSet(dataSet)", "\n .WithType ( (dataset, datarow) => {", "\n var aocType = datarow.Field(nameof(RawVariable.AocType));", @@ -1057,21 +1151,24 @@ "source": [ "Import.DefineFormat(ImportFormats.Cashflow, async (options, dataSet) => {", "\n Activity.Start();", - "\n var mainArgs = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.Cashflow};", + "\n var primaryArgs = await GetArgsAndCommitPartitionAsync(dataSet) with {ImportFormat = ImportFormats.Cashflow};", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", - "\n var targetArgs = await GetTargetArgsAsync(mainArgs);", - "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Cashflow, mainArgs);", + "\n var allArgs = await GetAllArgsAsync(primaryArgs);", + "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Cashflow, primaryArgs);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", "\n var workspace = Workspace.CreateNew();", - "\n var log = await ParseCashflowsToWorkspaceAsync(dataSet, mainArgs, workspace);", + "\n var log = await ParseCashflowsToWorkspaceAsync(dataSet, primaryArgs, workspace);", "\n if(log.Errors.Any()) return Activity.Finish().Merge(log);", "\n", - "\n foreach (var args in targetArgs) {", - "\n log = log.Merge(await CalculateAndUploadVariablesAsync(args, workspace, args == mainArgs));", + "\n var workspaceToCompute = Workspace.CreateNew();", + "\n workspaceToCompute.Initialize(x => x.FromSource(DataSource));", + "\n foreach (var args in allArgs) {", + "\n log = log.Merge(await ComputeAsync(args, workspace, workspaceToCompute, args == primaryArgs));", "\n if(log.Errors.Any()) return Activity.Finish().Merge(log);", "\n }", + "\n await workspaceToCompute.CommitToTargetAsync(DataSource);", "\n return Activity.Finish().Merge(log); ", "\n});" ], @@ -1155,21 +1252,24 @@ "source": [ "Import.DefineFormat(ImportFormats.Actual, async (options, dataSet) => {", "\n Activity.Start();", - "\n var mainArgs = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.Actual};", + "\n var primaryArgs = await GetArgsAndCommitPartitionAsync(dataSet) with {ImportFormat = ImportFormats.Actual};", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", - "\n var targetArgs = await GetTargetArgsAsync(mainArgs);", - "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Actual, mainArgs);", + "\n var allArgs = await GetAllArgsAsync(primaryArgs);", + "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Actual, primaryArgs);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", "\n var workspace = Workspace.CreateNew();", - "\n var log = await ParseActualsToWorkspaceAsync(dataSet, mainArgs, workspace);", + "\n var log = await ParseActualsToWorkspaceAsync(dataSet, primaryArgs, workspace);", "\n if(log.Errors.Any()) return Activity.Finish().Merge(log);", "\n", - "\n foreach (var args in targetArgs) {", - "\n log = log.Merge(await CalculateAndUploadVariablesAsync(args, workspace, false)); ", + "\n var workspaceToCompute = Workspace.CreateNew();", + "\n workspaceToCompute.Initialize(x => x.FromSource(DataSource));", + "\n foreach (var args in allArgs) {", + "\n log = log.Merge(await ComputeAsync(args, workspace, workspaceToCompute, false)); ", "\n if(log.Errors.Any()) return Activity.Finish().Merge(log);", "\n }", + "\n if (!log.Errors.Any()) await workspaceToCompute.CommitToTargetAsync(DataSource);", "\n return Activity.Finish().Merge(log);", "\n});" ], @@ -1261,7 +1361,8 @@ "source": [ "Import.DefineFormat(ImportFormats.SimpleValue, async (options, dataSet) => {", "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.SimpleValue};", + "\n var args = await GetArgsAndCommitPartitionAsync(dataSet) with {ImportFormat = ImportFormats.SimpleValue};", + "\n if(Activity.HasErrors()) return Activity.Finish();", "\n await DataNodeFactoryAsync(dataSet, ImportFormats.SimpleValue, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n ", @@ -1272,7 +1373,7 @@ "\n ", "\n workspace.Query().Select(v => new {v.DataNode, v.AccidentYear}).Distinct();", "\n ", - "\n await CommitToDatabase(workspace, partitionId, snapshot : true,", + "\n await workspace.CommitToAsync(DataSource, partitionId, snapshot : true,", "\n filter : x => workspace.Query().Select(v => v.DataNode).Distinct().Contains(x.DataNode));", "\n", "\n return Activity.Finish().Merge(parsingLog);", @@ -1298,7 +1399,8 @@ "source": [ "Import.DefineFormat(ImportFormats.Opening, async (options, dataSet) => {", "\n Activity.Start();", - "\n var args = (await GetArgsFromMainAsync(dataSet)) with {ImportFormat = ImportFormats.Opening};", + "\n var args = await GetArgsAndCommitPartitionAsync(dataSet) with {ImportFormat = ImportFormats.Opening};", + "\n if(Activity.HasErrors()) return Activity.Finish();", "\n await DataNodeFactoryAsync(dataSet, ImportFormats.Opening, args);", "\n if(Activity.HasErrors()) return Activity.Finish();", "\n", @@ -1307,8 +1409,11 @@ "\n var parsingLog = await ParseSimpleValueToWorkspaceAsync(dataSet, args, partitionId, workspace);", "\n if(parsingLog.Errors.Any()) return Activity.Finish().Merge(parsingLog);", "\n", - "\n var calculationLog = await CalculateAndUploadVariablesAsync(args, workspace, false); ", + "\n var workspaceToCompute = Workspace.CreateNew();", + "\n workspaceToCompute.Initialize(x => x.FromSource(DataSource));", + "\n var calculationLog = await ComputeAsync(args, workspace, workspaceToCompute, false); ", "\n if(calculationLog.Errors.Any()) return Activity.Finish().Merge(calculationLog);", + "\n await workspaceToCompute.CommitToAsync(DataSource, partitionId);", "\n return Activity.Finish().Merge(parsingLog).Merge(calculationLog);", "\n});" ], diff --git a/ifrs17/Test/EqualityComparerTest.ipynb b/ifrs17/Test/EqualityComparerTest.ipynb new file mode 100644 index 00000000..444f18b3 --- /dev/null +++ b/ifrs17/Test/EqualityComparerTest.ipynb @@ -0,0 +1,151 @@ +{ + "metadata": { + "authors": [], + "kernelspec": { + "display_name": "Formula Framework", + "language": "C#", + "name": "C#" + }, + "language_info": { + "file_extension": ".cs", + "mimetype": "text/plain", + "name": "C#" + } + }, + "nbformat": 4, + "nbformat_minor": 5, + "cells": [ + { + "cell_type": "markdown", + "source": [ + "

Equality Comparers Test

" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "markdown", + "source": [ + "# Yield Curve" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "#!import \"../Utils/EqualityComparers\"", + "\n#!import \"../Utils/TestHelper\"" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "using FluentAssertions;" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var comparer = YieldCurveComparer.Instance(); " + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "var yc = new YieldCurve() {Currency = \"EUR\", ", + "\n Year = 2000,", + "\n Month = 1,", + "\n Name = default, ", + "\n Scenario = default, ", + "\n Values = new double[]{0.001, 0.002, 0.003, 0.004}};" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc,yc).Should().BeTrue()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc,null).Should().BeFalse()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc,yc with { Month = 19}).Should().BeFalse()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc,yc with { Year = 2001}).Should().BeFalse()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc, yc with {Year = 2001, Values = new[] { 0.002, 0.003, 0.004 } }).Should().BeTrue()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc,yc with { Year = 1999}).Should().BeFalse()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "comparer.Equals(yc,yc with { Year = 1999, Values = new[] { 0.001, 0.001, 0.002, 0.003, 0.004 } }).Should().BeTrue()" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] + } + ] +} \ No newline at end of file diff --git a/ifrs17/Test/Tests.ipynb b/ifrs17/Test/Tests.ipynb index ef37f404..7a5e9882 100644 --- a/ifrs17/Test/Tests.ipynb +++ b/ifrs17/Test/Tests.ipynb @@ -50,6 +50,15 @@ "metadata": {}, "execution_count": 0, "outputs": [] + }, + { + "cell_type": "code", + "source": [ + "#!eval-notebook \"EqualityComparerTest\"" + ], + "metadata": {}, + "execution_count": 0, + "outputs": [] } ] } \ No newline at end of file diff --git a/ifrs17/Utils/EqualityComparers.ipynb b/ifrs17/Utils/EqualityComparers.ipynb index 243e73f9..488dc6a8 100644 --- a/ifrs17/Utils/EqualityComparers.ipynb +++ b/ifrs17/Utils/EqualityComparers.ipynb @@ -115,14 +115,25 @@ "\n{", "\n private YieldCurveComparer(){}", "\n", - "\n\tpublic bool Equals(YieldCurve x, YieldCurve y) => ", - "\n x.Year == y.Year && x.Month == y.Month && x.Scenario == y.Scenario && x.Currency == y.Currency && x.Id == y.Id && x.Values.SequenceEqual(y.Values, Precision);", + "\n public bool Equals(YieldCurve x, YieldCurve y)", + "\n {", + "\n if (x == null && y == null)", + "\n return true; ", + "\n if (x == null || y == null)", + "\n return false; ", + "\n if (!(x.Month == y.Month && x.Scenario == y.Scenario && x.Currency == y.Currency && x.Id == y.Id && x.Name == y.Name))", + "\n return false; ", + "\n if (x.Year == y.Year)", + "\n return x.Values.SequenceEqual(y.Values, YieldCurvePrecision); ", + "\n return x.Year > y.Year", + "\n ? x.Values.SequenceEqual(y.Values.Skip(x.Year - y.Year).ToArray(), YieldCurvePrecision)", + "\n : x.Values.Skip(y.Year - x.Year).ToArray().SequenceEqual(y.Values, YieldCurvePrecision);", + "\n }", "\n\t", - "\n\tpublic int GetHashCode (YieldCurve x) => 0;", + "\n public int GetHashCode (YieldCurve x) => 0;", "\n", "\n public static YieldCurveComparer Instance() => new YieldCurveComparer();", - "\n}", - "\n" + "\n}" ], "metadata": {}, "execution_count": 0,