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

Add bsq price trend indicator #3226

Merged
Merged
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
2 changes: 1 addition & 1 deletion core/src/main/resources/i18n/displayStrings.properties
Original file line number Diff line number Diff line change
Expand Up @@ -2056,7 +2056,7 @@ dao.factsAndFigures.menuItem.transactions=BSQ Transactions
dao.factsAndFigures.dashboard.marketPrice=Market data
dao.factsAndFigures.dashboard.price=Latest BSQ/BTC trade price (in Bisq)
dao.factsAndFigures.dashboard.avgPrice90=90 days average BSQ/BTC trade price
dao.factsAndFigures.dashboard.medianPrice90=90 days median BSQ/BTC trade price
dao.factsAndFigures.dashboard.avgPrice30=30 days average BSQ/BTC trade price
dao.factsAndFigures.dashboard.marketCap=Market capitalisation (based on trade price)
dao.factsAndFigures.dashboard.availableAmount=Total available BSQ

Expand Down
12 changes: 11 additions & 1 deletion desktop/src/main/java/bisq/desktop/bisq.css
Original file line number Diff line number Diff line change
Expand Up @@ -1298,7 +1298,7 @@ textfield */
#address-text-field:hover {
-fx-text-fill: -bs-text-color;
}

/* Account setup */
#wizard-item-background-deactivated {
-fx-body-color: linear-gradient(to bottom, -bs-content-background-gray, -bs-color-gray-aaa);
Expand Down Expand Up @@ -1990,6 +1990,16 @@ textfield */
-fx-fill: -bs-rd-green;
}

.price-trend-up {
-fx-text-fill: -bs-color-primary;
-fx-padding: 2 0 0 0;
}

.price-trend-down {
-fx-text-fill: -bs-red;
-fx-padding: 2 0 0 0;
}

/********************************************************************************************************************
* *
* Notifications *
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ public class TextFieldWithIcon extends AnchorPane {
public static final Logger log = LoggerFactory.getLogger(TextFieldWithIcon.class);
@Getter
private final Label iconLabel;
@Getter
private final TextField textField;
private final Label dummyTextField;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

import bisq.desktop.common.view.ActivatableView;
import bisq.desktop.common.view.FxmlView;
import bisq.desktop.components.TextFieldWithIcon;
import bisq.desktop.util.FormBuilder;
import bisq.desktop.util.GUIUtil;

Expand All @@ -36,13 +37,14 @@
import bisq.core.util.BsqFormatter;

import bisq.common.util.MathUtils;
import bisq.common.util.Tuple2;
import bisq.common.util.Tuple3;

import org.bitcoinj.core.Coin;

import javax.inject.Inject;

import de.jensd.fx.fontawesome.AwesomeIcon;

import javafx.scene.chart.AreaChart;
import javafx.scene.chart.NumberAxis;
import javafx.scene.chart.XYChart;
Expand All @@ -57,6 +59,8 @@

import javafx.beans.value.ChangeListener;

import javafx.collections.ObservableList;

import javafx.util.StringConverter;

import java.time.LocalDate;
Expand All @@ -83,6 +87,7 @@

import static bisq.desktop.util.FormBuilder.addLabelWithSubText;
import static bisq.desktop.util.FormBuilder.addTopLabelReadOnlyTextField;
import static bisq.desktop.util.FormBuilder.addTopLabelTextFieldWithIcon;


@FxmlView
Expand All @@ -102,7 +107,8 @@ public class BsqDashboardView extends ActivatableView<GridPane, Void> implements
private AreaChart bsqPriceChart;
private XYChart.Series<Number, Number> seriesBSQPrice;

private TextField avgPrice90TextField, medianPrice90TextField, marketCapTextField, availableAmountTextField;
private TextField avgPrice90TextField, marketCapTextField, availableAmountTextField;
private TextFieldWithIcon avgPrice30TextField;
private Label marketPriceLabel;

private Coin availableAmount;
Expand Down Expand Up @@ -136,13 +142,13 @@ public void initialize() {

priceChangeListener = (observable, oldValue, newValue) -> {
updatePrice();
updateAverageAndMedianPrice();
updateAveragePriceFields();
};
}

private void createKPIs() {

Tuple3<Label, Label, VBox> marketPriceBox = addLabelWithSubText(root, gridRow++, "0.004000 BSQ/BTC", "Latest BSQ/BTC trade price (in Bisq)");
Tuple3<Label, Label, VBox> marketPriceBox = addLabelWithSubText(root, gridRow++, "", "");
marketPriceLabel = marketPriceBox.first;
marketPriceLabel.getStyleClass().add("dao-kpi-big");

Expand All @@ -151,15 +157,15 @@ private void createKPIs() {
avgPrice90TextField = addTopLabelReadOnlyTextField(root, ++gridRow,
Res.get("dao.factsAndFigures.dashboard.avgPrice90")).second;

medianPrice90TextField = addTopLabelReadOnlyTextField(root, gridRow, 1,
Res.get("dao.factsAndFigures.dashboard.medianPrice90")).second;
avgPrice30TextField = addTopLabelTextFieldWithIcon(root, gridRow, 1,
Res.get("dao.factsAndFigures.dashboard.avgPrice30"), -15).second;
AnchorPane.setRightAnchor(avgPrice30TextField.getIconLabel(), 10d);

marketCapTextField = addTopLabelReadOnlyTextField(root, ++gridRow,
Res.get("dao.factsAndFigures.dashboard.marketCap")).second;

availableAmountTextField = FormBuilder.addTopLabelReadOnlyTextField(root, gridRow, 1,
Res.get("dao.factsAndFigures.dashboard.availableAmount")).second;

}


Expand All @@ -171,7 +177,7 @@ protected void activate() {
updateWithBsqBlockChainData();
updatePrice();
updateChartData();
updateAverageAndMedianPrice();
updateAveragePriceFields();
}


Expand Down Expand Up @@ -243,7 +249,7 @@ public Number fromString(String string) {
bsqPriceChart.setLegendVisible(false);
bsqPriceChart.setAnimated(false);
bsqPriceChart.setId("charts-dao");
bsqPriceChart.setMinHeight(335);
bsqPriceChart.setMinHeight(320);
bsqPriceChart.setPrefHeight(bsqPriceChart.getMinHeight());
bsqPriceChart.setCreateSymbols(true);
bsqPriceChart.setPadding(new Insets(0));
Expand Down Expand Up @@ -329,27 +335,45 @@ private void updatePrice() {
}
}

private void updateAverageAndMedianPrice() {
Date past90 = getPastDate(90);
private void updateAveragePriceFields() {
long average90 = updateAveragePriceField(avgPrice90TextField, 90);
long average30 = updateAveragePriceField(avgPrice30TextField.getTextField(), 30);
boolean trendUp = average30 > average90;
boolean trendDown = average30 < average90;

Label iconLabel = avgPrice30TextField.getIconLabel();
ObservableList<String> styleClass = iconLabel.getStyleClass();
if (trendUp) {
avgPrice30TextField.setVisible(true);
avgPrice30TextField.setIcon(AwesomeIcon.CIRCLE_ARROW_UP);
styleClass.remove("price-trend-down");
styleClass.add("price-trend-up");
} else if (trendDown) {
avgPrice30TextField.setVisible(true);
avgPrice30TextField.setIcon(AwesomeIcon.CIRCLE_ARROW_DOWN);
styleClass.remove("price-trend-up");
styleClass.add("price-trend-down");
} else {
iconLabel.setVisible(false);
}
}

private long updateAveragePriceField(TextField textField, int days) {
Date past90 = getPastDate(days);
List<TradeStatistics2> bsqTradePast90Days = tradeStatisticsManager.getObservableTradeStatisticsSet().stream()
.filter(e -> e.getCurrencyCode().equals("BSQ"))
.filter(e -> e.getTradeDate().after(past90))
.collect(Collectors.toList());
Tuple2<Long, Long> averageAndMedian = getAverageAndMedian(bsqTradePast90Days);
long average = getAverage(bsqTradePast90Days);
Coin oneBsq = Coin.valueOf(100);

Price avgPrice = Price.valueOf("BSQ", averageAndMedian.first);
Price avgPrice = Price.valueOf("BSQ", average);
String avg = bsqFormatter.formatPrice(avgPrice);
String bsqInUsdAvg = GUIUtil.getBsqInUsd(avgPrice, oneBsq, priceFeedService, bsqFormatter);
avgPrice90TextField.setText(avg + " BSQ/BTC (" + "1 BSQ = " + bsqInUsdAvg + ")");

Price medianPrice = Price.valueOf("BSQ", averageAndMedian.second);
String median = bsqFormatter.formatPrice(medianPrice);
String bsqInUsdMedian = GUIUtil.getBsqInUsd(medianPrice, oneBsq, priceFeedService, bsqFormatter);
medianPrice90TextField.setText(median + " BSQ/BTC (" + "1 BSQ = " + bsqInUsdMedian + ")");
String bsqInUsdAvg = average > 0 ? GUIUtil.getBsqInUsd(avgPrice, oneBsq, priceFeedService, bsqFormatter) : Res.get("shared.na");
textField.setText(avg + " BSQ/BTC (" + "1 BSQ = " + bsqInUsdAvg + ")");
return average;
}

private Tuple2<Long, Long> getAverageAndMedian(List<TradeStatistics2> list) {
private long getAverage(List<TradeStatistics2> list) {
long accumulatedVolume = 0;
long accumulatedAmount = 0;
List<Long> tradePrices = new ArrayList<>(list.size());
Expand All @@ -366,11 +390,10 @@ private Tuple2<Long, Long> getAverageAndMedian(List<TradeStatistics2> list) {
long averagePrice;
Long[] prices = new Long[tradePrices.size()];
tradePrices.toArray(prices);
long medianPrice = MathUtils.getMedian(prices);
double accumulatedAmountAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedAmount, Altcoin.SMALLEST_UNIT_EXPONENT);
averagePrice = MathUtils.roundDoubleToLong(accumulatedAmountAsDouble / (double) accumulatedVolume);
averagePrice = accumulatedVolume > 0 ? MathUtils.roundDoubleToLong(accumulatedAmountAsDouble / (double) accumulatedVolume) : 0;

return new Tuple2<>(averagePrice, medianPrice);
return averagePrice;
}

private Date getPastDate(int days) {
Expand Down
Loading