diff --git a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PerformanceView.java b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PerformanceView.java index 8c08f4a542..34f90a79a5 100644 --- a/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PerformanceView.java +++ b/name.abuchen.portfolio.ui/src/name/abuchen/portfolio/ui/views/PerformanceView.java @@ -3,6 +3,8 @@ import static name.abuchen.portfolio.ui.util.SWTHelper.clearLabel; import static name.abuchen.portfolio.ui.util.SWTHelper.placeBelow; +import java.io.File; +import java.io.IOException; import java.text.MessageFormat; import java.time.ZoneId; import java.time.format.DateTimeFormatter; @@ -19,6 +21,7 @@ import name.abuchen.portfolio.snapshot.ReportingPeriod; import name.abuchen.portfolio.ui.Messages; import name.abuchen.portfolio.ui.PortfolioPlugin; +import name.abuchen.portfolio.ui.util.AbstractCSVExporter; import name.abuchen.portfolio.ui.util.AbstractDropDown; import name.abuchen.portfolio.ui.util.Colors; import name.abuchen.portfolio.ui.util.Column; @@ -68,6 +71,8 @@ public class PerformanceView extends AbstractHistoricView { private static class OverviewTab implements DisposeListener { + private ClientPerformanceSnapshot snapshot; + private LocalResourceManager resourceManager = new LocalResourceManager(JFaceResources.getResources()); private Font kpiFont; @@ -93,6 +98,8 @@ private static class OverviewTab implements DisposeListener public void setInput(ClientPerformanceSnapshot snapshot) { + this.snapshot = snapshot; + PerformanceIndex index = snapshot.getPerformanceIndex(); if (index.getTotals().length > 1) @@ -293,6 +300,11 @@ public void widgetDisposed(DisposeEvent e) { resourceManager.dispose(); } + + public ClientPerformanceSnapshot getSnapshot() + { + return snapshot; + } } private OverviewTab overview; @@ -772,6 +784,32 @@ public void run() } }); + manager.add(new Action(MessageFormat.format(Messages.LabelExport, Messages.LabelVolatility)) + { + @Override + public void run() + { + new AbstractCSVExporter() + { + @Override + protected void writeToFile(File file) throws IOException + { + ClientPerformanceSnapshot snapshot = overview.getSnapshot(); + if (snapshot == null) + return; + + PerformanceIndex index = snapshot.getPerformanceIndex(); + index.exportVolatilityData(file); + } + + @Override + protected Control getControl() + { + return ExportDropDown.this.getToolBar(); + } + }.export(Messages.LabelVolatility + ".csv"); //$NON-NLS-1$ + } + }); } } diff --git a/name.abuchen.portfolio/src/name/abuchen/portfolio/snapshot/PerformanceIndex.java b/name.abuchen.portfolio/src/name/abuchen/portfolio/snapshot/PerformanceIndex.java index 02314abf8c..2d9c5deca7 100644 --- a/name.abuchen.portfolio/src/name/abuchen/portfolio/snapshot/PerformanceIndex.java +++ b/name.abuchen.portfolio/src/name/abuchen/portfolio/snapshot/PerformanceIndex.java @@ -8,6 +8,7 @@ import java.nio.charset.StandardCharsets; import java.util.Date; import java.util.List; +import java.util.function.Predicate; import name.abuchen.portfolio.Messages; import name.abuchen.portfolio.math.Risk.Drawdown; @@ -157,27 +158,32 @@ public Volatility getVolatility() { if (volatility == null) { - // Volatility calculation must only include values starting with the - // first data point. - int skip = 0; - for (int ii = 0; ii < totals.length; ii++) - { - if (totals[ii] != 0) - { - skip = ii; - break; - } - } - - // additionally skip first value as it is always 0 (as there is no - // previous period for the delta) TradeCalendar calendar = new TradeCalendar(); - volatility = new Volatility(dates, delta, skip + 1, date -> !calendar.isHoldiay(date)); + volatility = new Volatility(dates, delta, getVolatilitySkip(), date -> !calendar.isHoldiay(date)); } return volatility; } + /** + * Volatility calculation must only include values starting with the first + * data point. Additionally skip first value as it is always 0 (as there is + * no previous period for the delta) + */ + private int getVolatilitySkip() + { + int skip = 0; + for (int ii = 0; ii < totals.length; ii++) + { + if (totals[ii] != 0) + { + skip = ii; + break; + } + } + return skip + 1; + } + public long[] getTaxes() { return taxes; @@ -216,6 +222,17 @@ public DateTime getFirstDataPoint() } public void exportTo(File file) throws IOException + { + exportTo(file, 0, d -> true); + } + + public void exportVolatilityData(File file) throws IOException + { + TradeCalendar calendar = new TradeCalendar(); + exportTo(file, getVolatilitySkip(), date -> !calendar.isHoldiay(date)); + } + + private void exportTo(File file, int skip, Predicate filter) throws IOException { CSVStrategy strategy = new CSVStrategy(';', '"', CSVStrategy.COMMENTS_DISABLED, CSVStrategy.ESCAPE_DISABLED, false, false, false, false); @@ -231,8 +248,11 @@ public void exportTo(File file) throws IOException Messages.CSVColumn_DeltaInPercent, // Messages.CSVColumn_CumulatedPerformanceInPercent }); - for (int ii = 0; ii < totals.length; ii++) + for (int ii = skip; ii < totals.length; ii++) { + if (!filter.test(dates[ii])) + continue; + printer.print(Values.Date.format(dates[ii])); printer.print(Values.Amount.format(totals[ii])); printer.print(Values.Amount.format(transferals[ii]));