Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -579,6 +579,11 @@ public class Messages extends NLS
public static String LabelBiggerSize;
public static String LabelBlueGrayOrange;
public static String LabelCapitalGains;
public static String LabelAccumulatedCapitalGains;
public static String LabelRealizedCapitalGains;
public static String LabelAccumulatedRealizedCapitalGains;
public static String LabelUnrealizedCapitalGains;
public static String LabelAccumulatedUnrealizedCapitalGains;
public static String LabelCapitalGainsMethod;
public static String LabelCategoryOtherMovements;
public static String LabelChartDetailChartDevelopment;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1150,6 +1150,16 @@ LabelBlueGrayOrange = Blue - Grey - Orange

LabelCapitalGains = Capital Gains

LabelAccumulatedCapitalGains = Accumulated Capital Gains

LabelRealizedCapitalGains = Realized Capital Gains

LabelAccumulatedRealizedCapitalGains = Accumulated Realized Capital Gains

LabelUnrealizedCapitalGains = Unrealized Capital Gains

LabelAccumulatedUnrealizedCapitalGains = Accumulated Unrealized Capital Gains

LabelCapitalGainsMethod = Acquisition cost method for Capital Gains

LabelCategoryOtherMovements = Other Movements
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ public enum ClientDataSeries
FEES_ACCUMULATED(Messages.LabelFeesAccumulated), //
TAXES(Messages.ColumnTaxes), //
TAXES_ACCUMULATED(Messages.LabelAccumulatedTaxes), //
CAPITAL_GAINS(Messages.LabelCapitalGains), //
CAPITAL_GAINS_ACCUMULATED(Messages.LabelAccumulatedCapitalGains), //
REALIZED_CAPITAL_GAINS(Messages.LabelRealizedCapitalGains), //
REALIZED_CAPITAL_GAINS_ACCUMULATED(Messages.LabelAccumulatedRealizedCapitalGains), //
UNREALIZED_CAPITAL_GAINS(Messages.LabelUnrealizedCapitalGains), //
UNREALIZED_CAPITAL_GAINS_ACCUMULATED(Messages.LabelAccumulatedUnrealizedCapitalGains), //

DELTA_PERCENTAGE(Messages.LabelAggregationDaily);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,37 @@ private void buildStatementOfAssetsDataSeries()
series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.FEES_ACCUMULATED,
Messages.LabelFeesAccumulated, Colors.GRAY.getRGB());
availableSeries.add(series);

// Capital Gains
series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.CAPITAL_GAINS,
Messages.LabelCapitalGains, Display.getDefault().getSystemColor(SWT.COLOR_GREEN).getRGB());
// series.setLineChart(false);
availableSeries.add(series);

series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.CAPITAL_GAINS_ACCUMULATED,
Messages.LabelAccumulatedCapitalGains, Display.getDefault().getSystemColor(SWT.COLOR_GREEN).getRGB());
// series.setLineChart(false);
availableSeries.add(series);

series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.REALIZED_CAPITAL_GAINS,
Messages.LabelRealizedCapitalGains, Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN).getRGB());
// series.setLineChart(false);
availableSeries.add(series);

series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.REALIZED_CAPITAL_GAINS_ACCUMULATED,
Messages.LabelAccumulatedRealizedCapitalGains, Display.getDefault().getSystemColor(SWT.COLOR_DARK_GREEN).getRGB());
// series.setLineChart(false);
availableSeries.add(series);

series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.UNREALIZED_CAPITAL_GAINS,
Messages.LabelUnrealizedCapitalGains, Display.getDefault().getSystemColor(SWT.COLOR_CYAN).getRGB());
// series.setLineChart(false);
availableSeries.add(series);

series = new DataSeries(DataSeries.Type.CLIENT, ClientDataSeries.UNREALIZED_CAPITAL_GAINS_ACCUMULATED,
Messages.LabelAccumulatedUnrealizedCapitalGains, Display.getDefault().getSystemColor(SWT.COLOR_CYAN).getRGB());
// series.setLineChart(false);
availableSeries.add(series);
}

private void buildPerformanceDataSeries(Client client, IPreferenceStore preferences, ColorWheel wheel)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,24 @@ private void addClient(DataSeries series, PerformanceIndex clientIndex)
case FEES_ACCUMULATED:
values = accumulateAndToDouble(clientIndex.getFees(), Values.Amount.divider());
break;
case CAPITAL_GAINS:
values = toDouble(clientIndex.getCapitalGains(), Values.Amount.divider());
break;
case CAPITAL_GAINS_ACCUMULATED:
values = accumulateAndToDouble(clientIndex.getCapitalGains(), Values.Amount.divider());
break;
case REALIZED_CAPITAL_GAINS:
values = toDouble(clientIndex.getRealizedCapitalGains(), Values.Amount.divider());
break;
case REALIZED_CAPITAL_GAINS_ACCUMULATED:
values = accumulateAndToDouble(clientIndex.getRealizedCapitalGains(), Values.Amount.divider());
break;
case UNREALIZED_CAPITAL_GAINS:
values = toDouble(clientIndex.getUnrealizedCapitalGains(), Values.Amount.divider());
break;
case UNREALIZED_CAPITAL_GAINS_ACCUMULATED:
values = accumulateAndToDouble(clientIndex.getUnrealizedCapitalGains(), Values.Amount.divider());
break;
default:
throw new IllegalArgumentException(String.valueOf(series.getInstance()));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@
import name.abuchen.portfolio.money.Values;
import name.abuchen.portfolio.util.Dates;
import name.abuchen.portfolio.util.Interval;
import name.abuchen.portfolio.snapshot.ClientPerformanceSnapshot.CategoryType;
import name.abuchen.portfolio.PortfolioLog;
import name.abuchen.portfolio.model.PortfolioTransaction;
import name.abuchen.portfolio.snapshot.security.DailyCapitalGainsCalculation;
import java.util.ArrayList;
import java.util.stream.Collectors;

/* package */class ClientIndex extends PerformanceIndex
{
Expand Down Expand Up @@ -59,6 +65,9 @@
buys = new long[size];
sells = new long[size];
fees = new long[size];
capitalGains = new long[size];
realizedCapitalGains = new long[size];
unrealizedCapitalGains = new long[size];

collectTransferalsAndTaxes(interval);

Expand Down Expand Up @@ -103,6 +112,9 @@
valuation = thisValuation;
index++;
}

// Calculate capital gains
calculateCapitalGains(interval);
}

protected void addValue(long[] array, String currencyCode, long value, Interval interval, LocalDate time)
Expand Down Expand Up @@ -210,4 +222,75 @@ private void collectTransferalsAndTaxes(Interval interval)

}
}

private void calculateCapitalGains(Interval interval)
{
// Use the new DailyCapitalGainsCalculation for accurate FIFO-based gains
DailyCapitalGainsCalculation dailyCalc = new DailyCapitalGainsCalculation(
getClient(), getCurrencyConverter(), interval);
dailyCalc.calculate();

// Distribute realized gains from the daily calculation
distributeRealizedGainsFromDailyCalculation(interval, dailyCalc);

// Distribute unrealized gains from the daily calculation
distributeUnrealizedGainsFromDailyCalculation(interval, dailyCalc);

// Calculate total capital gains (realized + unrealized)
calculateTotalCapitalGains(interval, dailyCalc);
}

private void distributeRealizedGainsFromDailyCalculation(Interval interval, DailyCapitalGainsCalculation dailyCalc)
{
// Get all dates that have realized gains
List<LocalDate> datesWithGains = dailyCalc.getDatesWithRealizedGains();

// Add the gains to the arrays on their specific dates
for (LocalDate date : datesWithGains)
{
Money gainsForDate = dailyCalc.getRealizedGains(date);
if (gainsForDate.getAmount() != 0)
{
addValue(realizedCapitalGains, gainsForDate.getCurrencyCode(),
gainsForDate.getAmount(), interval, date);
}
}
}

private void distributeUnrealizedGainsFromDailyCalculation(Interval interval, DailyCapitalGainsCalculation dailyCalc)
{
// Get all dates that have unrealized gains
List<LocalDate> datesWithUnrealizedGains = dailyCalc.getDatesWithUnrealizedGains();

// Add the unrealized gains to the arrays on their specific dates
for (LocalDate date : datesWithUnrealizedGains)
{
Money unrealizedGainsForDate = dailyCalc.getUnrealizedGains(date);
if (unrealizedGainsForDate.getAmount() != 0)
{
addValue(unrealizedCapitalGains, unrealizedGainsForDate.getCurrencyCode(),
unrealizedGainsForDate.getAmount(), interval, date);
}
}
}

private void calculateTotalCapitalGains(Interval interval, DailyCapitalGainsCalculation dailyCalc)
{
// Calculate total capital gains (realized + unrealized) for each day
int daysInInterval = (int) interval.getDays() + 1;
if (daysInInterval > 0)
{
for (int i = 0; i < daysInInterval; i++)
{
LocalDate date = interval.getStart().plusDays(i);
Money realizedGains = dailyCalc.getRealizedGains(date);
Money unrealizedGains = dailyCalc.getUnrealizedGains(date);
Money totalGains = realizedGains.add(unrealizedGains);

this.capitalGains[i] = totalGains.getAmount();
}
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public class PerformanceIndex
protected long[] interestCharge;
protected long[] buys;
protected long[] sells;
protected long[] capitalGains;
protected long[] realizedCapitalGains;
protected long[] unrealizedCapitalGains;
protected double[] accumulated;
protected double[] delta;

Expand Down Expand Up @@ -323,6 +326,21 @@ public long[] getSells()
return sells;
}

public long[] getCapitalGains()
{
return capitalGains;
}

public long[] getRealizedCapitalGains()
{
return realizedCapitalGains;
}

public long[] getUnrealizedCapitalGains()
{
return unrealizedCapitalGains;
}

/**
* Calculates the absolute invested capital, i.e. starting with the first
* transaction recorded for the client.
Expand Down
Loading
Loading