From 404917ba45a1b9cdf27eee3931fdcfd93ce95e1a Mon Sep 17 00:00:00 2001 From: mierin12 Date: Fri, 6 Sep 2024 02:50:39 +0200 Subject: [PATCH 1/3] add total perf to statement of assets --- .../ui/views/StatementOfAssetsViewer.java | 75 ++++++++++++++++--- 1 file changed, 66 insertions(+), 9 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java index f7ee0397c3..62564a13bb 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java @@ -70,6 +70,7 @@ import name.abuchen.portfolio.snapshot.AssetPosition; import name.abuchen.portfolio.snapshot.ClientSnapshot; import name.abuchen.portfolio.snapshot.GroupByTaxonomy; +import name.abuchen.portfolio.snapshot.PerformanceIndex; import name.abuchen.portfolio.snapshot.ReportingPeriod; import name.abuchen.portfolio.snapshot.SecurityPosition; import name.abuchen.portfolio.snapshot.filter.ClientFilter; @@ -250,9 +251,21 @@ private final List flatten(GroupByTaxonomy groupByTaxonomy) if (calculated.contains(key)) return; + List warnings = new ArrayList<>(); + + // performance for sub totals (category) + elements.stream().filter(Element::isCategory).forEach(e -> e.setPerformanceForCategoryTotals(currencyCode,interval, + PerformanceIndex.forClassification(filteredClient, converter.with(currencyCode), + e.getCategory().getClassification(), interval, warnings))); + // performance for total + elements.stream().filter(Element::isGroupByTaxonomy) + .forEach(e -> e.setPerformanceForCategoryTotals(currencyCode, interval, + PerformanceIndex.forClient(filteredClient, converter.with(currencyCode), + interval, warnings))); + + // performance for securities var snapshot = LazySecurityPerformanceSnapshot.create(filteredClient, converter.with(currencyCode), interval); - Map map = snapshot.getRecords().stream() .collect(Collectors.toMap(LazySecurityPerformanceRecord::getSecurity, r -> r)); @@ -605,7 +618,8 @@ private void addPerformanceColumns(List options) Column column = new Column("ttwror", Messages.ColumnTTWROR, SWT.RIGHT, 80); //$NON-NLS-1$ labelProvider = new ReportingPeriodLabelProvider( - LazySecurityPerformanceRecord::getTrueTimeWeightedRateOfReturn); + LazySecurityPerformanceRecord::getTrueTimeWeightedRateOfReturn, true, + PerformanceIndex::getFinalAccumulatedPercentage); column.setOptions(new ReportingPeriodColumnOptions(Messages.ColumnTTWROR_Option, options)); column.setGroupLabel(Messages.GroupLabelPerformance); column.setDescription(Messages.LabelTTWROR); @@ -616,7 +630,8 @@ private void addPerformanceColumns(List options) column = new Column("ttwror_pa", Messages.ColumnTTWRORpa, SWT.RIGHT, 80); //$NON-NLS-1$ labelProvider = new ReportingPeriodLabelProvider( - LazySecurityPerformanceRecord::getTrueTimeWeightedRateOfReturnAnnualized); + LazySecurityPerformanceRecord::getTrueTimeWeightedRateOfReturnAnnualized, true, + PerformanceIndex::getFinalAccumulatedAnnualizedPercentage); column.setOptions(new ReportingPeriodColumnOptions(Messages.ColumnTTWRORpa_Option, options)); column.setGroupLabel(Messages.GroupLabelPerformance); column.setDescription(Messages.LabelTTWROR_Annualized); @@ -626,7 +641,8 @@ private void addPerformanceColumns(List options) support.addColumn(column); column = new Column("irr", Messages.ColumnIRR, SWT.RIGHT, 80); //$NON-NLS-1$ - labelProvider = new ReportingPeriodLabelProvider(LazySecurityPerformanceRecord::getIrr); + labelProvider = new ReportingPeriodLabelProvider(LazySecurityPerformanceRecord::getIrr, true, + PerformanceIndex::getPerformanceIRR); column.setOptions(new ReportingPeriodColumnOptions(Messages.ColumnIRRPerformanceOption, options)); column.setMenuLabel(Messages.ColumnIRR_MenuLabel); column.setGroupLabel(Messages.GroupLabelPerformance); @@ -1050,6 +1066,7 @@ public static class Element implements Adaptable private List children = new ArrayList<>(); private Map performance = new HashMap<>(); + private Map performanceForCategoryTotals = new HashMap<>(); private Element(GroupByTaxonomy groupByTaxonomy, AssetCategory category, int sortOrder) { @@ -1115,6 +1132,16 @@ public LazySecurityPerformanceRecord getPerformance(String currencyCode, Interva return performance.get(new CacheKey(currencyCode, period)); } + public void setPerformanceForCategoryTotals(String currencyCode, Interval period, PerformanceIndex index) + { + performanceForCategoryTotals.put(new CacheKey(currencyCode, period), index); + } + + public PerformanceIndex getPerformanceForCategoryTotals(String currencyCode, Interval period) + { + return performanceForCategoryTotals.get(new CacheKey(currencyCode, period)); + } + public boolean isGroupByTaxonomy() { return groupByTaxonomy != null && category == null && position == null; @@ -1242,6 +1269,7 @@ public int compare(Object o1, Object o2) { private Function> valueProvider; private Function, Object> collector; + private Function valueProviderTotal; public ElementValueProvider(Function> valueProvider, Function, Object> collector) @@ -1250,6 +1278,15 @@ public ElementValueProvider(Function this.collector = collector; } + public ElementValueProvider(Function> valueProvider, + Function, Object> collector, + Function valueProviderTotal) + { + this.valueProvider = valueProvider; + this.collector = collector; + this.valueProviderTotal = valueProviderTotal; + } + public Object getValue(Element element, String currencyCode, Interval interval) { if (element.isSecurity()) @@ -1297,17 +1334,31 @@ public Object getValue(Element element, String currencyCode, Interval interval) } else if (element.isCategory()) { + if (collector == null && valueProviderTotal != null) + { + // assumption: performance index has been calculated + // before by calculatePerformanceAndInjectIntoElements ! + PerformanceIndex index = element.getPerformanceForCategoryTotals(currencyCode, interval); + return valueProviderTotal.apply(index); + } if (collector == null) return null; - - return collectValue(element.getChildren(), currencyCode, interval); + else + return collectValue(element.getChildren(), currencyCode, interval); } else if (element.isGroupByTaxonomy()) { - if (collector == null) + if (collector == null && valueProviderTotal != null) + { + // assumption: performance index has been calculated + // before by calculatePerformanceAndInjectIntoElements ! + PerformanceIndex index = element.getPerformanceForCategoryTotals(currencyCode, interval); + return valueProviderTotal.apply(index); + } + else if (collector == null) return null; - - return collectValue(element.getChildren().flatMap(Element::getChildren), currencyCode, interval); + else + return collectValue(element.getChildren().flatMap(Element::getChildren), currencyCode, interval); } else { @@ -1341,6 +1392,12 @@ public ReportingPeriodLabelProvider(Function> valueProvider, + boolean showUpAndDownArrows, Function valueProviderTotal) + { + this(new ElementValueProvider(valueProvider, null, valueProviderTotal), null, showUpAndDownArrows); + } + public ReportingPeriodLabelProvider(ElementValueProvider valueProvider, boolean showUpAndDownArrows) { this(valueProvider, null, showUpAndDownArrows); From df217fc310e63697e1c0352263967fe91ad6cb41 Mon Sep 17 00:00:00 2001 From: mierin12 Date: Sat, 7 Sep 2024 22:23:27 +0200 Subject: [PATCH 2/3] fix java heap space issue --- .../ui/views/StatementOfAssetsViewer.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java index 62564a13bb..f5431d404b 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java @@ -243,7 +243,8 @@ private final List flatten(GroupByTaxonomy groupByTaxonomy) return answer; } - /* package */ final void calculatePerformanceAndInjectIntoElements(String currencyCode, Interval interval) + /* package */ final void calculatePerformanceAndInjectIntoElements(String currencyCode, Interval interval, + boolean calculateTotalsPerformance) { CacheKey key = new CacheKey(currencyCode, interval); @@ -251,18 +252,22 @@ private final List flatten(GroupByTaxonomy groupByTaxonomy) if (calculated.contains(key)) return; - List warnings = new ArrayList<>(); + // do not compute the performance index per default + if (calculateTotalsPerformance) + { + List warnings = new ArrayList<>(); - // performance for sub totals (category) - elements.stream().filter(Element::isCategory).forEach(e -> e.setPerformanceForCategoryTotals(currencyCode,interval, + // performance for sub totals (category) lines + elements.stream().filter(Element::isCategory).forEach(e -> e.setPerformanceForCategoryTotals( + currencyCode, interval, PerformanceIndex.forClassification(filteredClient, converter.with(currencyCode), e.getCategory().getClassification(), interval, warnings))); - // performance for total - elements.stream().filter(Element::isGroupByTaxonomy) + // performance for total lines + elements.stream().filter(Element::isGroupByTaxonomy) .forEach(e -> e.setPerformanceForCategoryTotals(currencyCode, interval, PerformanceIndex.forClient(filteredClient, converter.with(currencyCode), interval, warnings))); - + } // performance for securities var snapshot = LazySecurityPerformanceSnapshot.create(filteredClient, converter.with(currencyCode), interval); @@ -1378,6 +1383,7 @@ private final class ReportingPeriodLabelProvider extends OptionLabelProvider { private boolean showColorAndArrows; + private boolean calculateTotalsPerformance = false; private ElementValueProvider valueProvider; private Function currencyProvider; @@ -1396,6 +1402,7 @@ public ReportingPeriodLabelProvider(Function valueProviderTotal) { this(new ElementValueProvider(valueProvider, null, valueProviderTotal), null, showUpAndDownArrows); + this.calculateTotalsPerformance = true; } public ReportingPeriodLabelProvider(ElementValueProvider valueProvider, boolean showUpAndDownArrows) @@ -1435,7 +1442,7 @@ private Object getValue(Object e, ReportingPeriod option) String currencyCode = currencyProvider != null ? currencyProvider.apply(element) : model.getCurrencyConverter().getTermCurrency(); - model.calculatePerformanceAndInjectIntoElements(currencyCode, interval); + model.calculatePerformanceAndInjectIntoElements(currencyCode, interval, calculateTotalsPerformance); return valueProvider.getValue(element, currencyCode, interval); } From 7545f01b0a2b7885af5fab85632581c09f2dafbc Mon Sep 17 00:00:00 2001 From: mierin12 Date: Tue, 10 Sep 2024 00:51:55 +0200 Subject: [PATCH 3/3] make "without classification" returns nothing instead of wrong 0% --- .../ui/views/StatementOfAssetsViewer.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java index f5431d404b..945fffbab5 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/StatementOfAssetsViewer.java @@ -256,9 +256,12 @@ private final List flatten(GroupByTaxonomy groupByTaxonomy) if (calculateTotalsPerformance) { List warnings = new ArrayList<>(); - + // performance for sub totals (category) lines - elements.stream().filter(Element::isCategory).forEach(e -> e.setPerformanceForCategoryTotals( + elements.stream().filter(Element::isCategory) + .filter(e -> !Objects.equals(Classification.UNASSIGNED_ID, + e.getCategory().getClassification().getId())) + .forEach(e -> e.setPerformanceForCategoryTotals( currencyCode, interval, PerformanceIndex.forClassification(filteredClient, converter.with(currencyCode), e.getCategory().getClassification(), interval, warnings))); @@ -1339,14 +1342,14 @@ public Object getValue(Element element, String currencyCode, Interval interval) } else if (element.isCategory()) { - if (collector == null && valueProviderTotal != null) + if (collector == null && valueProviderTotal != null && !Objects.equals(Classification.UNASSIGNED_ID, + element.getCategory().getClassification().getId())) { - // assumption: performance index has been calculated - // before by calculatePerformanceAndInjectIntoElements ! + // assumption: performance index has been calculated before PerformanceIndex index = element.getPerformanceForCategoryTotals(currencyCode, interval); return valueProviderTotal.apply(index); } - if (collector == null) + else if (collector == null) return null; else return collectValue(element.getChildren(), currencyCode, interval); @@ -1355,8 +1358,7 @@ else if (element.isGroupByTaxonomy()) { if (collector == null && valueProviderTotal != null) { - // assumption: performance index has been calculated - // before by calculatePerformanceAndInjectIntoElements ! + // assumption: performance index has been calculated before PerformanceIndex index = element.getPerformanceForCategoryTotals(currencyCode, interval); return valueProviderTotal.apply(index); }