Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added Widget for performance-based all time high #3037

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package name.abuchen.portfolio.math;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;

import java.time.LocalDate;
import java.util.Optional;
import java.util.OptionalDouble;

import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;

import name.abuchen.portfolio.snapshot.PerformanceIndex;

public class AllTimeHighPerformanceTest
{
private PerformanceIndex emptyIndex;
private PerformanceIndex oneEntryIndex;
private PerformanceIndex athAtTheEndIndex;
private PerformanceIndex athAtTheBeginnigIndex;
private PerformanceIndex athInTheMiddle;
private PerformanceIndex bankruptcy;
private PerformanceIndex worseThanBankruptcy; // Asset that looses more than 100%

@Before
public void setUp()
{
emptyIndex = Mockito.mock(PerformanceIndex.class);
when(emptyIndex.getAccumulatedPercentage()).thenReturn(new double[] {});
when(emptyIndex.getDates()).thenReturn(new LocalDate[] {});

oneEntryIndex = Mockito.mock(PerformanceIndex.class);
when(oneEntryIndex.getAccumulatedPercentage()).thenReturn(new double[] { 0d });
when(oneEntryIndex.getDates()).thenReturn(new LocalDate[] { LocalDate.of(2022, 11, 10) });

athAtTheEndIndex = Mockito.mock(PerformanceIndex.class);
when(athAtTheEndIndex.getAccumulatedPercentage()).thenReturn(new double[] { 0d, -.1d, -.1d, -.05d, .1d, .15d});
when(athAtTheEndIndex.getDates()).thenReturn(new LocalDate[] { LocalDate.of(2022, 11, 2),
LocalDate.of(2022, 11, 3), LocalDate.of(2022, 11, 4), LocalDate.of(2022, 11, 6),
LocalDate.of(2022, 11, 8), LocalDate.of(2022, 11, 11) });

athAtTheBeginnigIndex = Mockito.mock(PerformanceIndex.class);
when(athAtTheBeginnigIndex.getAccumulatedPercentage()).thenReturn(new double[] { 0d, -.1d, -.1d, -.05d, -.2d, -.15d});
when(athAtTheBeginnigIndex.getDates()).thenReturn(new LocalDate[] { LocalDate.of(2022, 11, 2),
LocalDate.of(2022, 11, 3), LocalDate.of(2022, 11, 4), LocalDate.of(2022, 11, 6),
LocalDate.of(2022, 11, 8), LocalDate.of(2022, 11, 11) });

athInTheMiddle = Mockito.mock(PerformanceIndex.class);
when(athInTheMiddle.getAccumulatedPercentage()).thenReturn(new double[] { 0d, -.1d, -.2d, 1d, .5d, 0d});
when(athInTheMiddle.getDates()).thenReturn(new LocalDate[] { LocalDate.of(2022, 11, 2),
LocalDate.of(2022, 11, 3), LocalDate.of(2022, 11, 4), LocalDate.of(2022, 11, 6),
LocalDate.of(2022, 11, 8), LocalDate.of(2022, 11, 11) });

bankruptcy = Mockito.mock(PerformanceIndex.class);
when(bankruptcy.getAccumulatedPercentage()).thenReturn(new double[] { 0d, .1d, .23d, -.9d, -1d, -1d});
when(bankruptcy.getDates()).thenReturn(new LocalDate[] { LocalDate.of(2022, 11, 2),
LocalDate.of(2022, 11, 3), LocalDate.of(2022, 11, 4), LocalDate.of(2022, 11, 6),
LocalDate.of(2022, 11, 8), LocalDate.of(2022, 11, 11) });

worseThanBankruptcy = Mockito.mock(PerformanceIndex.class);
when(worseThanBankruptcy.getAccumulatedPercentage()).thenReturn(new double[] { 0d, -.1d, -.23d, -.9d, -1d, -1.5d});
when(worseThanBankruptcy.getDates()).thenReturn(new LocalDate[] { LocalDate.of(2022, 11, 2),
LocalDate.of(2022, 11, 3), LocalDate.of(2022, 11, 4), LocalDate.of(2022, 11, 6),
LocalDate.of(2022, 11, 8), LocalDate.of(2022, 11, 11) });
}

@Test
public void testEmptyIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(emptyIndex);

assertTrue(ath.getDistance().isEmpty());
assertTrue(ath.getDate().isEmpty());
}

@Test
public void testOneEntryIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(oneEntryIndex);

assertApproximatelyEquals(OptionalDouble.of(0d), ath.getDistance());
assertEquals(Optional.of(LocalDate.of(2022, 11, 10)), ath.getDate());
}

@Test
public void testATHAtTheEndIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(athAtTheEndIndex);

assertApproximatelyEquals(OptionalDouble.of(0d), ath.getDistance());
assertEquals(Optional.of(LocalDate.of(2022, 11, 11)), ath.getDate());
}

@Test
public void testATHAtTheBeginningIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(athAtTheBeginnigIndex);

assertApproximatelyEquals(OptionalDouble.of(-.15d), ath.getDistance());
assertEquals(Optional.of(LocalDate.of(2022, 11, 2)), ath.getDate());
}

@Test
public void testATHInTheMiddleIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(athInTheMiddle);

assertApproximatelyEquals(OptionalDouble.of(-.5d), ath.getDistance());
assertEquals(Optional.of(LocalDate.of(2022, 11, 6)), ath.getDate());
}

@Test
public void testBankruptcyIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(bankruptcy);

assertApproximatelyEquals(OptionalDouble.of(-1d), ath.getDistance());
assertEquals(Optional.of(LocalDate.of(2022, 11, 4)), ath.getDate());
}

@Test
public void testWorseThanBankruptcyIndex()
{
AllTimeHighPerformance ath = new AllTimeHighPerformance(worseThanBankruptcy);

assertApproximatelyEquals(OptionalDouble.of(-1.5d), ath.getDistance());
assertEquals(Optional.of(LocalDate.of(2022, 11, 2)), ath.getDate());
}

private static void assertApproximatelyEquals(OptionalDouble double1, OptionalDouble double2)
{
assertTrue(double1.isPresent() == double2.isPresent());
assertEquals(double1.getAsDouble(), double2.getAsDouble(), 0.00001d);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
import name.abuchen.portfolio.util.Interval;

@SuppressWarnings("nls")
public class AllTimeHighTest
public class AllTimeHighPriceTest
{
private Security securityOnePrice;
private Security securityTenPrices;
Expand Down Expand Up @@ -57,7 +57,7 @@ private void buildPrices(Security security, Long[] prices)
public void testSecurityIsNull()
{
Interval interval = Interval.of(securityOnePrice.getPrices().get(0).getDate(), LocalDate.now());
AllTimeHigh ath = new AllTimeHigh(null, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(null, interval);

assertNull(ath.getDistance());
assertNull(ath.getValue());
Expand All @@ -68,7 +68,7 @@ public void testSecurityIsNull()
public void testSecurityHasOnlyOnePrice()
{
Interval interval = Interval.of(securityOnePrice.getPrices().get(0).getDate(), LocalDate.now());
AllTimeHigh ath = new AllTimeHigh(this.securityOnePrice, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securityOnePrice, interval);

assertNull(ath.getValue());
assertNull(ath.getDistance());
Expand All @@ -79,7 +79,7 @@ public void testSecurityHasOnlyOnePrice()
public void testAthValueFor10Prices()
{
Interval interval = Interval.of(securityTenPrices.getPrices().get(0).getDate(), LocalDate.now());
AllTimeHigh ath = new AllTimeHigh(this.securityTenPrices, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securityTenPrices, interval);

assertEquals(Long.valueOf(2133L), ath.getValue());
assertEquals(-0.47444, ath.getDistance(), 0.00001);
Expand All @@ -90,7 +90,7 @@ public void testAthValueFor10Prices()
public void testAthValueFor7PricesWithDateGaps()
{
Interval interval = Interval.of(this.securitySevenPricesWithGaps.getPrices().get(0).getDate(), LocalDate.now());
AllTimeHigh ath = new AllTimeHigh(this.securitySevenPricesWithGaps, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securitySevenPricesWithGaps, interval);

assertEquals(Long.valueOf(2062L), ath.getValue());
assertEquals(-0.24005, ath.getDistance(), 0.00001);
Expand All @@ -101,7 +101,7 @@ public void testAthValueFor7PricesWithDateGaps()
public void testAthValueFor10PricesForLargerInterval()
{
Interval interval = Interval.of(LocalDate.of(2021, 1, 1), LocalDate.of(2023, 12, 31));
AllTimeHigh ath = new AllTimeHigh(this.securityTenPrices, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securityTenPrices, interval);

assertEquals(Long.valueOf(2133L), ath.getValue());
assertEquals(-0.47444, ath.getDistance(), 0.00001);
Expand All @@ -112,7 +112,7 @@ public void testAthValueFor10PricesForLargerInterval()
public void testAthValueFor10PricesForLast2DaysInterval()
{
Interval interval = Interval.of(LocalDate.of(2022, 6, 10), LocalDate.of(2022, 6, 11));
AllTimeHigh ath = new AllTimeHigh(this.securityTenPrices, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securityTenPrices, interval);

assertEquals(Long.valueOf(1121L), ath.getValue());
assertEquals(0, ath.getDistance(), 0.00001);
Expand All @@ -123,7 +123,7 @@ public void testAthValueFor10PricesForLast2DaysInterval()
public void testAthValueFor10PricesFor5DaysInterval()
{
Interval interval = Interval.of(LocalDate.of(2022, 6, 7), LocalDate.of(2022, 6, 10));
AllTimeHigh ath = new AllTimeHigh(this.securityTenPrices, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securityTenPrices, interval);

assertEquals(Long.valueOf(1500L), ath.getValue());
assertEquals(-0.4, ath.getDistance(), 0.00001);
Expand All @@ -134,7 +134,7 @@ public void testAthValueFor10PricesFor5DaysInterval()
public void testAthValueFor10PricesForFirst3DaysInterval()
{
Interval interval = Interval.of(LocalDate.of(2022, 1, 31), LocalDate.of(2022, 6, 4));
AllTimeHigh ath = new AllTimeHigh(this.securityTenPrices, interval);
AllTimeHighPrice ath = new AllTimeHighPrice(this.securityTenPrices, interval);

assertEquals(Long.valueOf(699L), ath.getValue());
assertEquals(0, ath.getDistance(), 0.00001);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -595,6 +595,8 @@ public class Messages extends NLS
public static String LabelDefaultReferenceAccountName;
public static String LabelDelta;
public static String LabelDescription;
public static String LabelDistanceFromATHPrice;
public static String LabelDistanceFromATHPerformance;
public static String LabelDoImport;
public static String LabelDoNotImport;
public static String LabelEarnings;
Expand Down Expand Up @@ -1089,7 +1091,6 @@ public class Messages extends NLS
public static String SecurityFilterSharesHeldNotZero;
public static String SecurityListFilter;
public static String SecurityListFilterDateReached;
public static String SecurityListFilterDistanceFromAth;
public static String SecurityListFilterHideInactive;
public static String SecurityListFilterLimitPriceExceeded;
public static String SecurityListFilterOnlyExchangeRates;
Expand Down Expand Up @@ -1186,7 +1187,8 @@ public class Messages extends NLS
public static String TabAccountBalanceChart;
public static String TabTransactions;
public static String TitlePasswordDialog;
public static String TooltipAllTimeHigh;
public static String TooltipAllTimeHighPrice;
public static String TooltipAllTimeHighPerformance;
public static String TooltipAverageHoldingPeriod;
public static String TooltipDateOfExchangeRate;
public static String TooltipHintPressAlt;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -594,9 +594,9 @@ ColumnQuoteChange_Description = Percentage change of the quote within the given

ColumnQuoteChange_Option = \u0394 {0}

ColumnQuoteDistanceFromAthPercent = Distance from ATH
ColumnQuoteDistanceFromAthPercent = Distance from ATH (price)

ColumnQuoteDistanceFromAthPercent_Description = Percentage distance from the last All Time High (ATH) in the chosen period.
ColumnQuoteDistanceFromAthPercent_Description = Percentage distance from the last price-based All Time High (ATH) in the chosen period.

ColumnQuoteDistanceFromAthPercent_Option = \u0394 ATH {0} %

Expand Down Expand Up @@ -1202,6 +1202,10 @@ LabelDelta = Delta (for reporting period)

LabelDescription = Description

LabelDistanceFromATHPrice = Security: Distance from ATH (Price)

LabelDistanceFromATHPerformance = Distance from ATH (Performance)

LabelDividendPerShare = dividend payment per shares

LabelDividends = Dividends
Expand Down Expand Up @@ -2206,8 +2210,6 @@ SecurityListFilter = Filter securities

SecurityListFilterDateReached = Securities: Date reached

SecurityListFilterDistanceFromAth = Security: Distance from ATH

SecurityListFilterHideInactive = Only active instruments

SecurityListFilterLimitPriceExceeded = Securities: Limit price exceeded
Expand Down Expand Up @@ -2394,7 +2396,9 @@ TabTransactions = Transactions

TitlePasswordDialog = Assign password

TooltipAllTimeHigh = All-Time High (ATH) in the last {0} days: {2} ({1})\nCurrent security price: {3} ({4})
TooltipAllTimeHighPrice = Price-based All-Time High (ATH) in the last {0} days: {3} ({1} days ago, on {2})\nCurrent security price: {4} ({5})

TooltipAllTimeHighPerformance = Performance-based All-Time High (ATH) in the last {0} days: {1} days ago, on {2}

TooltipAverageHoldingPeriod = The average holding period is calculated as follows:\n\n* All trades are included that were in the portfolio at some point within the selected reporting period.\n\n* The holding period of each security results from the time of purchase and sale. Immediate sales are assumed for positions currently held.\n\n* The position weight is calculated from the purchase price of the position relative to the total number of all purchase prices.\n\n* Result "average holding period of all positions" is the sum of the products "holding period * percentage position weight" across all positions.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -584,9 +584,9 @@ ColumnQuoteChange_Description = Procentu\u00E1ln\u00ED zm\u011Bna kotace v dan\u

ColumnQuoteChange_Option = \u0394 {0}

ColumnQuoteDistanceFromAthPercent = Vzd\u00E1lenost od ATH
ColumnQuoteDistanceFromAthPercent = Vzd\u00E1lenost od ATH (cena)

ColumnQuoteDistanceFromAthPercent_Description = Procentu\u00E1ln\u00ED vzd\u00E1lenost od posledn\u00EDho All Time High (ATH) ve zvolen\u00E9m obdob\u00ED.
ColumnQuoteDistanceFromAthPercent_Description = Procentu\u00E1ln\u00ED vzd\u00E1lenost od posledn\u00EDho cenov\u00E9ho maxima (ATH) ve zvolen\u00E9m obdob\u00ED.

ColumnQuoteDistanceFromAthPercent_Option = \u0394 ATH {0} %

Expand Down Expand Up @@ -1188,6 +1188,10 @@ LabelDelta = Delta (za sledovan\u00E9 obdob\u00ED)

LabelDescription = Popis

LabelDistanceFromATHPrice = Zabezpe\u010Den\u00ED: Vzd\u00E1lenost od ATH (Cena)

LabelDistanceFromATHPerformance = Vzd\u00E1lenost od ATH (v\u00FDkon)

LabelDividendPerShare = v\u00FDplata dividendy na akcii

LabelDividends = Dividendy
Expand Down Expand Up @@ -2190,8 +2194,6 @@ SecurityListFilter = Filtrovat cenn\u00E9 pap\u00EDry

SecurityListFilterDateReached = Cenn\u00E9 pap\u00EDry: dosa\u017Een\u00FD datum

SecurityListFilterDistanceFromAth = Zabezpe\u010Den\u00ED: Vzd\u00E1lenost od ATH

SecurityListFilterHideInactive = Pouze aktivn\u00ED cenn\u00E9 pap\u00EDry

SecurityListFilterLimitPriceExceeded = P\u0159ekro\u010Den\u00ED limitn\u00ED ceny
Expand Down Expand Up @@ -2378,7 +2380,9 @@ TabTransactions = Transakce

TitlePasswordDialog = P\u0159i\u0159adit heslo

TooltipAllTimeHigh = All-Time High (ATH) za posledn\u00EDch {0} dn\u00ED: {2} ({1})\nAktu\u00E1ln\u00ED cena cenn\u00E9ho pap\u00EDru: {3} ({4})
TooltipAllTimeHighPrice = Cenov\u00E9 maximum (ATH) za posledn\u00EDch {0} dn\u00ED: {3} (p\u0159ed {1} dny, dne {2})\nAktu\u00E1ln\u00ED cena cenn\u00E9ho pap\u00EDru: {4} ({5})

TooltipAllTimeHighPerformance = V\u00FDkonnostn\u00ED maximum (ATH) za posledn\u00EDch {0} dn\u00ED: p\u0159ed {1} dny, dne {2}.

TooltipAverageHoldingPeriod = Pr\u016Fm\u011Brn\u00E1 doba dr\u017Een\u00ED se vypo\u010D\u00EDt\u00E1 takto:\n\n* Zahrnuty jsou v\u0161echny obchody, kter\u00E9 byly v portfoliu v ur\u010Dit\u00E9m okam\u017Eiku v r\u00E1mci zvolen\u00E9ho vykazovan\u00E9ho obdob\u00ED.\n\n* Doba dr\u017Eby ka\u017Ed\u00E9ho cenn\u00E9ho pap\u00EDru vypl\u00FDv\u00E1 z okam\u017Eiku n\u00E1kupu a prodeje. U aktu\u00E1ln\u011B dr\u017Een\u00FDch pozic se p\u0159edpokl\u00E1d\u00E1 okam\u017Eit\u00FD prodej.\n\n* V\u00E1ha pozice se vypo\u010D\u00EDt\u00E1 z n\u00E1kupn\u00ED ceny pozice vzhledem k celkov\u00E9mu po\u010Dtu v\u0161ech n\u00E1kupn\u00EDch cen.\n\n* V\u00FDsledek "pr\u016Fm\u011Brn\u00E1 doba dr\u017Een\u00ED v\u0161ech pozic" je sou\u010Dtem sou\u010Din\u016F "doba dr\u017Een\u00ED * procentn\u00ED v\u00E1ha pozice" ve v\u0161ech pozic\u00EDch.

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -581,9 +581,9 @@ ColumnQuoteChange_Description = Prozentuale Kurs\u00E4nderung bezogen auf den Ze

ColumnQuoteChange_Option = \u0394 {0}

ColumnQuoteDistanceFromAthPercent = Abstand vom ATH
ColumnQuoteDistanceFromAthPercent = Abstand vom ATH (Preis)

ColumnQuoteDistanceFromAthPercent_Description = Prozentualer Abstand zum letzten All Time High (ATH) in dem gew\u00E4hlten Zeitraum.
ColumnQuoteDistanceFromAthPercent_Description = Prozentualer Abstand zum letzten preis-basierten All Time High (ATH) in dem gew\u00E4hlten Zeitraum.

ColumnQuoteDistanceFromAthPercent_Option = \u0394 ATH {0} %

Expand Down Expand Up @@ -1187,6 +1187,10 @@ LabelDelta = Delta (im Berichtszeitraum)

LabelDescription = Beschreibung

LabelDistanceFromATHPrice = Wertpapier: Abstand vom ATH (Preis)

LabelDistanceFromATHPerformance = Abstand vom ATH (Performance)

LabelDividendPerShare = Dividende pro St\u00FCck

LabelDividends = Dividenden
Expand Down Expand Up @@ -2189,8 +2193,6 @@ SecurityListFilter = Wertpapiere filtern

SecurityListFilterDateReached = Wertpapiere: Termin erreicht

SecurityListFilterDistanceFromAth = Wertpapier: Abstand vom ATH

SecurityListFilterHideInactive = Nur aktive Instrumente

SecurityListFilterLimitPriceExceeded = Wertpapiere: Limit \u00FCberschritten
Expand Down Expand Up @@ -2377,7 +2379,9 @@ TabTransactions = Ums\u00E4tze

TitlePasswordDialog = Passwort vergeben

TooltipAllTimeHigh = All-Time-High (ATH) in den letzten {0} Tagen: {2} ({1})\nAktueller Kurs: {3} ({4})
TooltipAllTimeHighPrice = Preis-basiertes All-Time-High (ATH) in den letzten {0} Tagen: {3} (vor {1} Tagen, am {2})\nAktueller Kurs: {4} ({5})

TooltipAllTimeHighPerformance = Performance-basiertes All-Time-High (ATH) in den letzten {0} Tagen: Vor {1} Tagen, am {2}

TooltipAverageHoldingPeriod = Die mittlere Haltedauer errechnet sich wie folgt:\n\n* Es werden alle Trades einbezogen die irgendwann innerhalb des gew\u00E4hlten Berichtszeitraums im Depot waren.\n\n* Die Haltedauer jedes Wertpapiers ergibt sich aus Kauf- und Verkaufszeitpunkt. F\u00FCr aktuell gehaltene Positionen wird ein sofortiger Verkauf unterstellt.\n\n* Das Positionsgewicht errechnet sich aus Kaufpreis der Position relativ zu der Gesamtsumme aller Kaufpreise.\n\n* Ergebnis "mittlere Haltedauer aller Positionen" ergibt sich als Summe der Produkte "Haltedauer * prozentuales Positionsgewicht" \u00FCber alle Positionen.

Expand Down
Loading