fix amounts in trade statistics view

This commit is contained in:
woodser 2023-06-15 09:43:49 -04:00
parent 59c0496d34
commit b414ac942d
6 changed files with 32 additions and 40 deletions

View File

@ -28,12 +28,8 @@ import haveno.common.util.CollectionUtils;
import haveno.common.util.ExtraDataMapValidator; import haveno.common.util.ExtraDataMapValidator;
import haveno.common.util.JsonExclude; import haveno.common.util.JsonExclude;
import haveno.common.util.Utilities; import haveno.common.util.Utilities;
import haveno.core.locale.CurrencyUtil;
import haveno.core.monetary.CryptoMoney; import haveno.core.monetary.CryptoMoney;
import haveno.core.monetary.CryptoExchangeRate;
import haveno.core.monetary.Price; import haveno.core.monetary.Price;
import haveno.core.monetary.TraditionalMoney;
import haveno.core.monetary.TraditionalExchangeRate;
import haveno.core.monetary.Volume; import haveno.core.monetary.Volume;
import haveno.core.offer.Offer; import haveno.core.offer.Offer;
import haveno.core.offer.OfferPayload; import haveno.core.offer.OfferPayload;
@ -47,9 +43,10 @@ import haveno.network.p2p.storage.payload.PersistableNetworkPayload;
import haveno.network.p2p.storage.payload.ProcessOncePersistableNetworkPayload; import haveno.network.p2p.storage.payload.ProcessOncePersistableNetworkPayload;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.bitcoinj.core.Coin;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import java.math.BigInteger;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
import java.util.Arrays; import java.util.Arrays;
@ -370,19 +367,17 @@ public final class TradeStatistics3 implements ProcessOncePersistableNetworkPayl
return priceObj; return priceObj;
} }
public Coin getTradeAmount() { public BigInteger getTradeAmount() {
return Coin.valueOf(amount); return BigInteger.valueOf(amount);
} }
public Volume getTradeVolume() { public Volume getTradeVolume() {
Volume volume = this.volume;
if (volume == null) { if (volume == null) {
if (getTradePrice().getMonetary() instanceof CryptoMoney) { Price price = getTradePrice();
volume = new Volume(new CryptoExchangeRate((CryptoMoney) getTradePrice().getMonetary()).coinToCrypto(getTradeAmount())); this.volume = volume = price.getMonetary() instanceof CryptoMoney
} else { ? price.getVolumeByAmount(getTradeAmount())
Volume exactVolume = new Volume(new TraditionalExchangeRate((TraditionalMoney) getTradePrice().getMonetary()).coinToTraditionalMoney(getTradeAmount())); : VolumeUtil.getAdjustedVolume(price.getVolumeByAmount(getTradeAmount()), paymentMethod);
boolean isFiat = CurrencyUtil.isFiatCurrency(exactVolume.getCurrencyCode());
if (isFiat) volume = VolumeUtil.getRoundedFiatVolume(exactVolume);
}
} }
return volume; return volume;
} }

View File

@ -84,7 +84,7 @@ public class AveragePriceUtil {
for (TradeStatistics3 item : list) { for (TradeStatistics3 item : list) {
accumulatedVolume += item.getTradeVolume().getValue(); accumulatedVolume += item.getTradeVolume().getValue();
accumulatedAmount += item.getTradeAmount().getValue(); // Amount of BTC traded accumulatedAmount += item.getTradeAmount().longValueExact(); // Amount of XMR traded
} }
long averagePrice; long averagePrice;
double accumulatedAmountAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedAmount, CryptoMoney.SMALLEST_UNIT_EXPONENT); double accumulatedAmountAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedAmount, CryptoMoney.SMALLEST_UNIT_EXPONENT);
@ -110,7 +110,7 @@ public class AveragePriceUtil {
.orElse(usdBTCPrice); .orElse(usdBTCPrice);
var bsqAmount = MathUtils.scaleDownByPowerOf10((double) item.getTradeVolume().getValue(), var bsqAmount = MathUtils.scaleDownByPowerOf10((double) item.getTradeVolume().getValue(),
CryptoMoney.SMALLEST_UNIT_EXPONENT); CryptoMoney.SMALLEST_UNIT_EXPONENT);
var btcAmount = MathUtils.scaleDownByPowerOf10((double) item.getTradeAmount().getValue(), var btcAmount = MathUtils.scaleDownByPowerOf10((double) item.getTradeAmount().longValueExact(),
CryptoMoney.SMALLEST_UNIT_EXPONENT); CryptoMoney.SMALLEST_UNIT_EXPONENT);
usdBsqList.add(new Tuple2<>(usdBTCPrice * btcAmount, bsqAmount)); usdBsqList.add(new Tuple2<>(usdBTCPrice * btcAmount, bsqAmount));
} }

View File

@ -22,6 +22,7 @@ import haveno.common.util.Utilities;
import haveno.core.locale.CurrencyUtil; import haveno.core.locale.CurrencyUtil;
import haveno.core.locale.Res; import haveno.core.locale.Res;
import haveno.core.offer.OfferPayload; import haveno.core.offer.OfferPayload;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.statistics.TradeStatistics3; import haveno.core.trade.statistics.TradeStatistics3;
import haveno.core.trade.statistics.TradeStatistics3StorageService; import haveno.core.trade.statistics.TradeStatistics3StorageService;
import haveno.core.util.FormattingUtils; import haveno.core.util.FormattingUtils;
@ -189,7 +190,7 @@ public class MarketView extends ActivatableView<TabPane, Void> {
sb.append("Date: ").append(DisplayUtils.formatDateTime(tradeStatistics3.getDate())).append("\n") sb.append("Date: ").append(DisplayUtils.formatDateTime(tradeStatistics3.getDate())).append("\n")
.append("Market: ").append(CurrencyUtil.getCurrencyPair(tradeStatistics3.getCurrency())).append("\n") .append("Market: ").append(CurrencyUtil.getCurrencyPair(tradeStatistics3.getCurrency())).append("\n")
.append("Price: ").append(FormattingUtils.formatPrice(tradeStatistics3.getTradePrice())).append("\n") .append("Price: ").append(FormattingUtils.formatPrice(tradeStatistics3.getTradePrice())).append("\n")
.append("Amount: ").append(formatter.formatCoin(tradeStatistics3.getTradeAmount())).append("\n") .append("Amount: ").append(HavenoUtils.formatXmr(tradeStatistics3.getTradeAmount())).append("\n")
.append("Volume: ").append(VolumeUtil.formatVolume(tradeStatistics3.getTradeVolume())).append("\n") .append("Volume: ").append(VolumeUtil.formatVolume(tradeStatistics3.getTradeVolume())).append("\n")
.append("Payment method: ").append(Res.get(tradeStatistics3.getPaymentMethodId())).append("\n") .append("Payment method: ").append(Res.get(tradeStatistics3.getPaymentMethodId())).append("\n")
.append("ReferralID: ").append(tradeStatistics3.getExtraDataMap().get(OfferPayload.REFERRAL_ID)); .append("ReferralID: ").append(tradeStatistics3.getExtraDataMap().get(OfferPayload.REFERRAL_ID));

View File

@ -21,13 +21,13 @@ import com.google.common.annotations.VisibleForTesting;
import haveno.common.util.MathUtils; import haveno.common.util.MathUtils;
import haveno.core.locale.CurrencyUtil; import haveno.core.locale.CurrencyUtil;
import haveno.core.monetary.CryptoMoney; import haveno.core.monetary.CryptoMoney;
import haveno.core.monetary.TraditionalMoney;
import haveno.core.trade.statistics.TradeStatistics3; import haveno.core.trade.statistics.TradeStatistics3;
import haveno.desktop.main.market.trades.charts.CandleData; import haveno.desktop.main.market.trades.charts.CandleData;
import haveno.desktop.util.DisplayUtils; import haveno.desktop.util.DisplayUtils;
import javafx.scene.chart.XYChart; import javafx.scene.chart.XYChart;
import javafx.util.Pair; import javafx.util.Pair;
import lombok.Getter; import lombok.Getter;
import org.bitcoinj.core.Coin;
import java.time.LocalDateTime; import java.time.LocalDateTime;
import java.time.ZoneId; import java.time.ZoneId;
@ -211,14 +211,14 @@ public class ChartCalculations {
} }
private static long getAveragePrice(List<TradeStatistics3> tradeStatisticsList) { private static long getAveragePrice(List<TradeStatistics3> tradeStatisticsList) {
long accumulatedAmount = 0; long accumulatedAmount = 0; // TODO: use BigInteger
long accumulatedVolume = 0; long accumulatedVolume = 0;
for (TradeStatistics3 tradeStatistics : tradeStatisticsList) { for (TradeStatistics3 tradeStatistics : tradeStatisticsList) {
accumulatedAmount += tradeStatistics.getAmount(); accumulatedAmount += tradeStatistics.getAmount();
accumulatedVolume += tradeStatistics.getTradeVolume().getValue(); accumulatedVolume += tradeStatistics.getTradeVolume().getValue();
} }
double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, Coin.SMALLEST_UNIT_EXPONENT); double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, 4 + TraditionalMoney.SMALLEST_UNIT_EXPONENT);
return MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / accumulatedAmount); return MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / accumulatedAmount);
} }
@ -232,7 +232,7 @@ public class ChartCalculations {
long close = 0; long close = 0;
long high = 0; long high = 0;
long low = 0; long low = 0;
long accumulatedVolume = 0; long accumulatedVolume = 0; // TODO: use BigInteger
long accumulatedAmount = 0; long accumulatedAmount = 0;
long numTrades = set.size(); long numTrades = set.size();
List<Long> tradePrices = new ArrayList<>(); List<Long> tradePrices = new ArrayList<>();
@ -243,7 +243,7 @@ public class ChartCalculations {
high = (high != 0) ? Math.max(high, tradePriceAsLong) : tradePriceAsLong; high = (high != 0) ? Math.max(high, tradePriceAsLong) : tradePriceAsLong;
accumulatedVolume += item.getTradeVolume().getValue(); accumulatedVolume += item.getTradeVolume().getValue();
accumulatedAmount += item.getTradeAmount().getValue(); accumulatedAmount += item.getTradeAmount().longValueExact();
tradePrices.add(tradePriceAsLong); tradePrices.add(tradePriceAsLong);
} }
Collections.sort(tradePrices); Collections.sort(tradePrices);
@ -262,11 +262,11 @@ public class ChartCalculations {
boolean isBullish; boolean isBullish;
if (CurrencyUtil.isCryptoCurrency(currencyCode)) { if (CurrencyUtil.isCryptoCurrency(currencyCode)) {
isBullish = close < open; isBullish = close < open;
double accumulatedAmountAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedAmount, CryptoMoney.SMALLEST_UNIT_EXPONENT); double accumulatedAmountAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedAmount, 4 + CryptoMoney.SMALLEST_UNIT_EXPONENT);
averagePrice = MathUtils.roundDoubleToLong(accumulatedAmountAsDouble / accumulatedVolume); averagePrice = MathUtils.roundDoubleToLong(accumulatedAmountAsDouble / accumulatedVolume);
} else { } else {
isBullish = close > open; isBullish = close > open;
double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, Coin.SMALLEST_UNIT_EXPONENT); double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, 4 + TraditionalMoney.SMALLEST_UNIT_EXPONENT);
averagePrice = MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / accumulatedAmount); averagePrice = MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / accumulatedAmount);
} }
@ -277,10 +277,10 @@ public class ChartCalculations {
DisplayUtils.formatDate(dateFrom) + " - " + DisplayUtils.formatDate(dateTo); DisplayUtils.formatDate(dateFrom) + " - " + DisplayUtils.formatDate(dateTo);
// We do not need precision, so we scale down before multiplication otherwise we could get an overflow. // We do not need precision, so we scale down before multiplication otherwise we could get an overflow.
averageUsdPrice = (long) MathUtils.scaleDownByPowerOf10((double) averageUsdPrice, 4); averageUsdPrice = (long) MathUtils.scaleDownByPowerOf10((double) averageUsdPrice, TraditionalMoney.SMALLEST_UNIT_EXPONENT);
long volumeInUsd = averageUsdPrice * (long) MathUtils.scaleDownByPowerOf10((double) accumulatedAmount, 4); long volumeInUsd = averageUsdPrice * (long) MathUtils.scaleDownByPowerOf10((double) accumulatedAmount, 4);
// We store USD value without decimals as its only total volume, no precision is needed. // We store USD value without decimals as its only total volume, no precision is needed.
volumeInUsd = (long) MathUtils.scaleDownByPowerOf10((double) volumeInUsd, 4); volumeInUsd = (long) MathUtils.scaleDownByPowerOf10((double) volumeInUsd, TraditionalMoney.SMALLEST_UNIT_EXPONENT);
return new CandleData(tick, open, close, high, low, averagePrice, medianPrice, accumulatedAmount, accumulatedVolume, return new CandleData(tick, open, close, high, low, averagePrice, medianPrice, accumulatedAmount, accumulatedVolume,
numTrades, isBullish, dateString, volumeInUsd); numTrades, isBullish, dateString, volumeInUsd);
} }

View File

@ -19,10 +19,10 @@ package haveno.desktop.main.market.trades;
import haveno.core.locale.CurrencyUtil; import haveno.core.locale.CurrencyUtil;
import haveno.core.locale.Res; import haveno.core.locale.Res;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.statistics.TradeStatistics3; import haveno.core.trade.statistics.TradeStatistics3;
import haveno.core.util.FormattingUtils; import haveno.core.util.FormattingUtils;
import haveno.core.util.VolumeUtil; import haveno.core.util.VolumeUtil;
import haveno.core.util.coin.CoinFormatter;
import haveno.desktop.util.DisplayUtils; import haveno.desktop.util.DisplayUtils;
import lombok.experimental.Delegate; import lombok.experimental.Delegate;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
@ -30,7 +30,6 @@ import org.jetbrains.annotations.Nullable;
public class TradeStatistics3ListItem { public class TradeStatistics3ListItem {
@Delegate @Delegate
private final TradeStatistics3 tradeStatistics3; private final TradeStatistics3 tradeStatistics3;
private final CoinFormatter coinFormatter;
private final boolean showAllTradeCurrencies; private final boolean showAllTradeCurrencies;
private String dateString; private String dateString;
private String market; private String market;
@ -40,10 +39,8 @@ public class TradeStatistics3ListItem {
private String amountString; private String amountString;
public TradeStatistics3ListItem(@Nullable TradeStatistics3 tradeStatistics3, public TradeStatistics3ListItem(@Nullable TradeStatistics3 tradeStatistics3,
CoinFormatter coinFormatter,
boolean showAllTradeCurrencies) { boolean showAllTradeCurrencies) {
this.tradeStatistics3 = tradeStatistics3; this.tradeStatistics3 = tradeStatistics3;
this.coinFormatter = coinFormatter;
this.showAllTradeCurrencies = showAllTradeCurrencies; this.showAllTradeCurrencies = showAllTradeCurrencies;
} }
@ -87,7 +84,7 @@ public class TradeStatistics3ListItem {
public String getAmountString() { public String getAmountString() {
if (amountString == null) { if (amountString == null) {
amountString = tradeStatistics3 != null ? coinFormatter.formatCoin(tradeStatistics3.getTradeAmount(), 4) : ""; amountString = tradeStatistics3 != null ? HavenoUtils.formatXmr(getAmount(), false, 4) : "";
} }
return amountString; return amountString;
} }

View File

@ -26,6 +26,7 @@ import haveno.common.util.Tuple3;
import haveno.core.locale.CurrencyUtil; import haveno.core.locale.CurrencyUtil;
import haveno.core.locale.Res; import haveno.core.locale.Res;
import haveno.core.monetary.Price; import haveno.core.monetary.Price;
import haveno.core.trade.HavenoUtils;
import haveno.core.trade.statistics.TradeStatistics3; import haveno.core.trade.statistics.TradeStatistics3;
import haveno.core.user.CookieKey; import haveno.core.user.CookieKey;
import haveno.core.user.User; import haveno.core.user.User;
@ -78,7 +79,6 @@ import javafx.scene.text.Text;
import javafx.stage.Stage; import javafx.stage.Stage;
import javafx.util.Callback; import javafx.util.Callback;
import javafx.util.StringConverter; import javafx.util.StringConverter;
import org.bitcoinj.core.Coin;
import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription; import org.fxmisc.easybind.Subscription;
import org.fxmisc.easybind.monadic.MonadicBinding; import org.fxmisc.easybind.monadic.MonadicBinding;
@ -377,7 +377,6 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
CompletableFuture.supplyAsync(() -> { CompletableFuture.supplyAsync(() -> {
return model.tradeStatisticsByCurrency.stream() return model.tradeStatisticsByCurrency.stream()
.map(tradeStatistics -> new TradeStatistics3ListItem(tradeStatistics, .map(tradeStatistics -> new TradeStatistics3ListItem(tradeStatistics,
coinFormatter,
model.showAllTradeCurrenciesProperty.get())) model.showAllTradeCurrenciesProperty.get()))
.collect(Collectors.toCollection(FXCollections::observableArrayList)); .collect(Collectors.toCollection(FXCollections::observableArrayList));
}).whenComplete((listItems, throwable) -> { }).whenComplete((listItems, throwable) -> {
@ -438,7 +437,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
String details = showAllTradeCurrencies ? "all-markets" : model.getCurrencyCode(); String details = showAllTradeCurrencies ? "all-markets" : model.getCurrencyCode();
GUIUtil.exportCSV("trade-statistics-" + details + ".csv", headerConverter, contentConverter, GUIUtil.exportCSV("trade-statistics-" + details + ".csv", headerConverter, contentConverter,
new TradeStatistics3ListItem(null, coinFormatter, showAllTradeCurrencies), new TradeStatistics3ListItem(null, showAllTradeCurrencies),
sortedList, sortedList,
(Stage) root.getScene().getWindow()); (Stage) root.getScene().getWindow());
} }
@ -517,7 +516,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
volumeAxisX = new NumberAxis(0, MAX_TICKS + 1, 1); volumeAxisX = new NumberAxis(0, MAX_TICKS + 1, 1);
volumeAxisY = new NumberAxis(); volumeAxisY = new NumberAxis();
volumeChart = getVolumeChart(volumeAxisX, volumeAxisY, volumeSeries, "BTC"); volumeChart = getVolumeChart(volumeAxisX, volumeAxisY, volumeSeries, "XMR");
volumeInUsdAxisX = new NumberAxis(0, MAX_TICKS + 1, 1); volumeInUsdAxisX = new NumberAxis(0, MAX_TICKS + 1, 1);
NumberAxis volumeInUsdAxisY = new NumberAxis(); NumberAxis volumeInUsdAxisY = new NumberAxis();
@ -557,8 +556,8 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
axisY.setTickLabelFormatter(new StringConverter<>() { axisY.setTickLabelFormatter(new StringConverter<>() {
@Override @Override
public String toString(Number volume) { public String toString(Number volume) {
return currency.equals("BTC") ? return currency.equals("XMR") ?
coinFormatter.formatCoin(Coin.valueOf(MathUtils.doubleToLong((double) volume))) : HavenoUtils.formatXmr(MathUtils.doubleToLong((double) volume)) :
VolumeUtil.formatLargeFiatWithUnitPostFix((double) volume, "USD"); VolumeUtil.formatLargeFiatWithUnitPostFix((double) volume, "USD");
} }
@ -568,10 +567,10 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
} }
}); });
StringConverter<Number> btcStringConverter = new StringConverter<>() { StringConverter<Number> xmrStringConverter = new StringConverter<>() {
@Override @Override
public String toString(Number volume) { public String toString(Number volume) {
return coinFormatter.formatCoinWithCode(Coin.valueOf((long) volume)); return HavenoUtils.formatXmr((long) volume, true);
} }
@Override @Override
@ -579,7 +578,7 @@ public class TradesChartsView extends ActivatableViewAndModel<VBox, TradesCharts
return null; return null;
} }
}; };
VolumeChart volumeChart = new VolumeChart(axisX, axisY, btcStringConverter); VolumeChart volumeChart = new VolumeChart(axisX, axisY, xmrStringConverter);
volumeChart.setId("volume-chart"); volumeChart.setId("volume-chart");
volumeChart.setData(FXCollections.observableArrayList(List.of(series))); volumeChart.setData(FXCollections.observableArrayList(List.of(series)));
volumeChart.setMinHeight(138); volumeChart.setMinHeight(138);