diff --git a/desktop/src/main/java/bisq/desktop/main/market/trades/ChartCalculations.java b/desktop/src/main/java/bisq/desktop/main/market/trades/ChartCalculations.java
new file mode 100644
index 0000000000..67f5aac09c
--- /dev/null
+++ b/desktop/src/main/java/bisq/desktop/main/market/trades/ChartCalculations.java
@@ -0,0 +1,68 @@
+/*
+ * This file is part of Bisq.
+ *
+ * Bisq is free software: you can redistribute it and/or modify it
+ * under the terms of the GNU Affero General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or (at
+ * your option) any later version.
+ *
+ * Bisq is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with Bisq. If not, see .
+ */
+
+package bisq.desktop.main.market.trades;
+
+import bisq.core.trade.statistics.TradeStatistics3;
+
+import bisq.common.util.MathUtils;
+
+import org.bitcoinj.core.Coin;
+
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.temporal.ChronoUnit;
+
+import java.util.Date;
+import java.util.List;
+
+public class ChartCalculations {
+ static final ZoneId ZONE_ID = ZoneId.systemDefault();
+
+ static long getAveragePrice(List tradeStatisticsList) {
+ long accumulatedAmount = 0;
+ long accumulatedVolume = 0;
+ for (TradeStatistics3 tradeStatistics : tradeStatisticsList) {
+ accumulatedAmount += tradeStatistics.getAmount();
+ accumulatedVolume += tradeStatistics.getTradeVolume().getValue();
+ }
+
+ double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, Coin.SMALLEST_UNIT_EXPONENT);
+ return MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / (double) accumulatedAmount);
+ }
+
+ static Date roundToTick(LocalDateTime localDate, TradesChartsViewModel.TickUnit tickUnit) {
+ switch (tickUnit) {
+ case YEAR:
+ return Date.from(localDate.withMonth(1).withDayOfYear(1).withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
+ case MONTH:
+ return Date.from(localDate.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
+ case WEEK:
+ int dayOfWeek = localDate.getDayOfWeek().getValue();
+ LocalDateTime firstDayOfWeek = ChronoUnit.DAYS.addTo(localDate, 1 - dayOfWeek);
+ return Date.from(firstDayOfWeek.withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
+ case DAY:
+ return Date.from(localDate.withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
+ case HOUR:
+ return Date.from(localDate.withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
+ case MINUTE_10:
+ return Date.from(localDate.withMinute(localDate.getMinute() - localDate.getMinute() % 10).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
+ default:
+ return Date.from(localDate.atZone(ZONE_ID).toInstant());
+ }
+ }
+}
diff --git a/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java b/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java
index b56073f48b..2852d103f9 100644
--- a/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java
+++ b/desktop/src/main/java/bisq/desktop/main/market/trades/TradesChartsViewModel.java
@@ -59,10 +59,6 @@ import javafx.collections.SetChangeListener;
import javafx.util.Pair;
-import java.time.LocalDateTime;
-import java.time.ZoneId;
-import java.time.temporal.ChronoUnit;
-
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -81,7 +77,6 @@ import javax.annotation.Nullable;
class TradesChartsViewModel extends ActivatableViewModel {
private static final int TAB_INDEX = 2;
- private static final ZoneId ZONE_ID = ZoneId.systemDefault();
///////////////////////////////////////////////////////////////////////////////////////////
@@ -116,7 +111,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
TickUnit tickUnit;
final int maxTicks = 90;
private int selectedTabIndex;
- final Map> usdPriceMapsPerTickUnit = new HashMap<>();
+ final Map> usdAveragePriceMapsPerTickUnit = new HashMap<>();
private boolean fillTradeCurrenciesOnActivateCalled;
///////////////////////////////////////////////////////////////////////////////////////////
@@ -156,16 +151,17 @@ class TradesChartsViewModel extends ActivatableViewModel {
fillTradeCurrencies();
fillTradeCurrenciesOnActivateCalled = true;
}
- buildUsdPricesPerDay();
- updateSelectedTradeStatistics(getCurrencyCode());
- updateChartData();
syncPriceFeedCurrency();
setMarketPriceFeedCurrency();
+ buildUsdPricesPerTickUnit(usdAveragePriceMapsPerTickUnit, tradeStatisticsManager.getObservableTradeStatisticsSet());
+ updateSelectedTradeStatistics(getCurrencyCode());
+ updateChartData();
}
@Override
protected void deactivate() {
tradeStatisticsManager.getObservableTradeStatisticsSet().removeListener(setChangeListener);
+ usdAveragePriceMapsPerTickUnit.clear();
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -252,18 +248,19 @@ class TradesChartsViewModel extends ActivatableViewModel {
priceFeedService.setCurrencyCode(selectedTradeCurrencyProperty.get().getCode());
}
- private void buildUsdPricesPerDay() {
- if (usdPriceMapsPerTickUnit.isEmpty()) {
+ private static void buildUsdPricesPerTickUnit(Map> usdAveragePriceMapsPerTickUnit,
+ Set tradeStatisticsSet) {
+ if (usdAveragePriceMapsPerTickUnit.isEmpty()) {
Map>> dateMapsPerTickUnit = new HashMap<>();
for (TickUnit tick : TickUnit.values()) {
dateMapsPerTickUnit.put(tick, new HashMap<>());
}
- tradeStatisticsManager.getObservableTradeStatisticsSet().stream()
+ tradeStatisticsSet.stream()
.filter(e -> e.getCurrency().equals("USD"))
.forEach(tradeStatistics -> {
for (TickUnit tick : TickUnit.values()) {
- long time = roundToTick(tradeStatistics.getLocalDateTime(), tick).getTime();
+ long time = ChartCalculations.roundToTick(tradeStatistics.getLocalDateTime(), tick).getTime();
Map> map = dateMapsPerTickUnit.get(tick);
map.putIfAbsent(time, new ArrayList<>());
map.get(time).add(tradeStatistics);
@@ -272,24 +269,12 @@ class TradesChartsViewModel extends ActivatableViewModel {
dateMapsPerTickUnit.forEach((tick, map) -> {
HashMap priceMap = new HashMap<>();
- map.forEach((date, tradeStatisticsList) -> priceMap.put(date, getAveragePrice(tradeStatisticsList)));
- usdPriceMapsPerTickUnit.put(tick, priceMap);
+ map.forEach((date, tradeStatisticsList) -> priceMap.put(date, ChartCalculations.getAveragePrice(tradeStatisticsList)));
+ usdAveragePriceMapsPerTickUnit.put(tick, priceMap);
});
}
}
- private long getAveragePrice(List tradeStatisticsList) {
- long accumulatedAmount = 0;
- long accumulatedVolume = 0;
- for (TradeStatistics3 tradeStatistics : tradeStatisticsList) {
- accumulatedAmount += tradeStatistics.getAmount();
- accumulatedVolume += tradeStatistics.getTradeVolume().getValue();
- }
-
- double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, Coin.SMALLEST_UNIT_EXPONENT);
- return MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / (double) accumulatedAmount);
- }
-
private void updateChartData() {
// Generate date range and create sets for all ticks
itemsPerInterval = new HashMap<>();
@@ -313,7 +298,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
}
});
- Map map = usdPriceMapsPerTickUnit.get(tickUnit);
+ Map usdAveragePriceMap = usdAveragePriceMapsPerTickUnit.get(tickUnit);
AtomicLong averageUsdPrice = new AtomicLong(0);
// create CandleData for defined time interval
@@ -322,8 +307,8 @@ class TradesChartsViewModel extends ActivatableViewModel {
.map(entry -> {
long tickStartDate = entry.getValue().getKey().getTime();
// If we don't have a price we take the previous one
- if (map.containsKey(tickStartDate)) {
- averageUsdPrice.set(map.get(tickStartDate));
+ if (usdAveragePriceMap.containsKey(tickStartDate)) {
+ averageUsdPrice.set(usdAveragePriceMap.get(tickStartDate));
}
return getCandleData(entry.getKey(), entry.getValue().getValue(), averageUsdPrice.get());
})
@@ -409,28 +394,7 @@ class TradesChartsViewModel extends ActivatableViewModel {
}
Date roundToTick(Date time, TickUnit tickUnit) {
- return roundToTick(time.toInstant().atZone(ZONE_ID).toLocalDateTime(), tickUnit);
- }
-
- Date roundToTick(LocalDateTime localDate, TickUnit tickUnit) {
- switch (tickUnit) {
- case YEAR:
- return Date.from(localDate.withMonth(1).withDayOfYear(1).withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
- case MONTH:
- return Date.from(localDate.withDayOfMonth(1).withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
- case WEEK:
- int dayOfWeek = localDate.getDayOfWeek().getValue();
- LocalDateTime firstDayOfWeek = ChronoUnit.DAYS.addTo(localDate, 1 - dayOfWeek);
- return Date.from(firstDayOfWeek.withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
- case DAY:
- return Date.from(localDate.withHour(0).withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
- case HOUR:
- return Date.from(localDate.withMinute(0).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
- case MINUTE_10:
- return Date.from(localDate.withMinute(localDate.getMinute() - localDate.getMinute() % 10).withSecond(0).withNano(0).atZone(ZONE_ID).toInstant());
- default:
- return Date.from(localDate.atZone(ZONE_ID).toInstant());
- }
+ return ChartCalculations.roundToTick(time.toInstant().atZone(ChartCalculations.ZONE_ID).toLocalDateTime(), tickUnit);
}
private long getTimeFromTick(long tick) {