Search in sources :

Example 1 with CandleData

use of bisq.desktop.main.market.trades.charts.CandleData in project bisq-desktop by bisq-network.

the class CandleStickChart method layoutPlotChildren.

// -------------- METHODS ------------------------------------------------------------------------------------------
/**
 * Called to update and layout the content for the plot
 */
@Override
protected void layoutPlotChildren() {
    // we have nothing to layout if no data is present
    if (getData() == null) {
        return;
    }
    // update candle positions
    for (int seriesIndex = 0; seriesIndex < getData().size(); seriesIndex++) {
        XYChart.Series<Number, Number> series = getData().get(seriesIndex);
        Iterator<XYChart.Data<Number, Number>> iter = getDisplayedDataIterator(series);
        Path seriesPath = null;
        if (series.getNode() instanceof Path) {
            seriesPath = (Path) series.getNode();
            seriesPath.getElements().clear();
        }
        while (iter.hasNext()) {
            XYChart.Data<Number, Number> item = iter.next();
            double x = getXAxis().getDisplayPosition(getCurrentDisplayedXValue(item));
            double y = getYAxis().getDisplayPosition(getCurrentDisplayedYValue(item));
            Node itemNode = item.getNode();
            CandleData candleData = (CandleData) item.getExtraValue();
            if (itemNode instanceof Candle && candleData != null) {
                Candle candle = (Candle) itemNode;
                double close = getYAxis().getDisplayPosition(candleData.close);
                double high = getYAxis().getDisplayPosition(candleData.high);
                double low = getYAxis().getDisplayPosition(candleData.low);
                // calculate candle width
                double candleWidth = -1;
                if (getXAxis() instanceof NumberAxis) {
                    NumberAxis xa = (NumberAxis) getXAxis();
                    // use 90% width between ticks
                    candleWidth = xa.getDisplayPosition(xa.getTickUnit()) * 0.90;
                }
                // update candle
                candle.update(close - y, high - y, low - y, candleWidth);
                candle.updateTooltip(candleData);
                // position the candle
                candle.setLayoutX(x);
                candle.setLayoutY(y);
            }
            if (seriesPath != null && candleData != null) {
                final double displayPosition = getYAxis().getDisplayPosition(candleData.average);
                if (seriesPath.getElements().isEmpty())
                    seriesPath.getElements().add(new MoveTo(x, displayPosition));
                else
                    seriesPath.getElements().add(new LineTo(x, displayPosition));
            }
        }
    }
}
Also used : Path(javafx.scene.shape.Path) NumberAxis(javafx.scene.chart.NumberAxis) LineTo(javafx.scene.shape.LineTo) CandleData(bisq.desktop.main.market.trades.charts.CandleData) Node(javafx.scene.Node) CandleData(bisq.desktop.main.market.trades.charts.CandleData) MoveTo(javafx.scene.shape.MoveTo) XYChart(javafx.scene.chart.XYChart)

Example 2 with CandleData

use of bisq.desktop.main.market.trades.charts.CandleData in project bisq-desktop by bisq-network.

the class TradesChartsViewModel method updateChartData.

private void updateChartData() {
    tradeStatisticsByCurrency.setAll(tradeStatisticsManager.getObservableTradeStatisticsSet().stream().filter(e -> showAllTradeCurrenciesProperty.get() || e.getCurrencyCode().equals(getCurrencyCode())).collect(Collectors.toList()));
    // Generate date range and create sets for all ticks
    itemsPerInterval = new HashMap<>();
    Date time = new Date();
    for (long i = maxTicks + 1; i >= 0; --i) {
        Set<TradeStatistics2> set = new HashSet<>();
        Pair<Date, Set<TradeStatistics2>> pair = new Pair<>((Date) time.clone(), set);
        itemsPerInterval.put(i, pair);
        time.setTime(time.getTime() - 1);
        time = roundToTick(time, tickUnit);
    }
    // Get all entries for the defined time interval
    tradeStatisticsByCurrency.stream().forEach(e -> {
        for (long i = maxTicks; i > 0; --i) {
            Pair<Date, Set<TradeStatistics2>> p = itemsPerInterval.get(i);
            if (e.getTradeDate().after(p.getKey())) {
                p.getValue().add(e);
                break;
            }
        }
    });
    // create CandleData for defined time interval
    List<CandleData> candleDataList = itemsPerInterval.entrySet().stream().filter(entry -> entry.getKey() >= 0 && !entry.getValue().getValue().isEmpty()).map(entry -> getCandleData(entry.getKey(), entry.getValue().getValue())).collect(Collectors.toList());
    candleDataList.sort((o1, o2) -> (o1.tick < o2.tick ? -1 : (o1.tick == o2.tick ? 0 : 1)));
    // noinspection Convert2Diamond
    priceItems.setAll(candleDataList.stream().map(e -> new XYChart.Data<Number, Number>(e.tick, e.open, e)).collect(Collectors.toList()));
    // noinspection Convert2Diamond
    volumeItems.setAll(candleDataList.stream().map(e -> new XYChart.Data<Number, Number>(e.tick, e.accumulatedAmount, e)).collect(Collectors.toList()));
}
Also used : Altcoin(bisq.core.monetary.Altcoin) GUIUtil(bisq.desktop.util.GUIUtil) TradeCurrency(bisq.core.locale.TradeCurrency) CurrencyListItem(bisq.desktop.util.CurrencyListItem) Coin(org.bitcoinj.core.Coin) Date(java.util.Date) CurrencyList(bisq.desktop.util.CurrencyList) Inject(com.google.inject.Inject) ZonedDateTime(java.time.ZonedDateTime) SetChangeListener(javafx.collections.SetChangeListener) LocalDateTime(java.time.LocalDateTime) FXCollections(javafx.collections.FXCollections) HashMap(java.util.HashMap) XYChart(javafx.scene.chart.XYChart) TradeStatisticsManager(bisq.core.trade.statistics.TradeStatisticsManager) BSFormatter(bisq.desktop.util.BSFormatter) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Map(java.util.Map) CurrencyUtil(bisq.core.locale.CurrencyUtil) Navigation(bisq.desktop.Navigation) ObjectProperty(javafx.beans.property.ObjectProperty) Pair(javafx.util.Pair) GlobalSettings(bisq.core.locale.GlobalSettings) Set(java.util.Set) TradeStatistics2(bisq.core.trade.statistics.TradeStatistics2) MathUtils(bisq.common.util.MathUtils) Collectors(java.util.stream.Collectors) ZoneId(java.time.ZoneId) ActivatableViewModel(bisq.desktop.common.model.ActivatableViewModel) MainView(bisq.desktop.main.MainView) BooleanProperty(javafx.beans.property.BooleanProperty) List(java.util.List) PriceFeedService(bisq.core.provider.price.PriceFeedService) SimpleBooleanProperty(javafx.beans.property.SimpleBooleanProperty) ChronoUnit(java.time.temporal.ChronoUnit) CryptoCurrency(bisq.core.locale.CryptoCurrency) PreferencesView(bisq.desktop.main.settings.preferences.PreferencesView) SimpleObjectProperty(javafx.beans.property.SimpleObjectProperty) CandleData(bisq.desktop.main.market.trades.charts.CandleData) Preferences(bisq.core.user.Preferences) Optional(java.util.Optional) VisibleForTesting(com.google.common.annotations.VisibleForTesting) ObservableList(javafx.collections.ObservableList) SettingsView(bisq.desktop.main.settings.SettingsView) HashSet(java.util.HashSet) Set(java.util.Set) CandleData(bisq.desktop.main.market.trades.charts.CandleData) TradeStatistics2(bisq.core.trade.statistics.TradeStatistics2) Date(java.util.Date) XYChart(javafx.scene.chart.XYChart) HashSet(java.util.HashSet) Pair(javafx.util.Pair)

Example 3 with CandleData

use of bisq.desktop.main.market.trades.charts.CandleData in project bisq-desktop by bisq-network.

the class TradesChartsViewModel method getCandleData.

@VisibleForTesting
CandleData getCandleData(long tick, Set<TradeStatistics2> set) {
    long open = 0;
    long close = 0;
    long high = 0;
    long low = 0;
    long accumulatedVolume = 0;
    long accumulatedAmount = 0;
    long numTrades = set.size();
    for (TradeStatistics2 item : set) {
        long tradePriceAsLong = item.getTradePrice().getValue();
        if (CurrencyUtil.isCryptoCurrency(getCurrencyCode())) {
            low = (low != 0) ? Math.max(low, tradePriceAsLong) : tradePriceAsLong;
            high = (high != 0) ? Math.min(high, tradePriceAsLong) : tradePriceAsLong;
        } else {
            low = (low != 0) ? Math.min(low, tradePriceAsLong) : tradePriceAsLong;
            high = (high != 0) ? Math.max(high, tradePriceAsLong) : tradePriceAsLong;
        }
        accumulatedVolume += (item.getTradeVolume() != null) ? item.getTradeVolume().getValue() : 0;
        accumulatedAmount += item.getTradeAmount().getValue();
    }
    List<TradeStatistics2> list = new ArrayList<>(set);
    list.sort((o1, o2) -> (o1.getTradeDate().getTime() < o2.getTradeDate().getTime() ? -1 : (o1.getTradeDate().getTime() == o2.getTradeDate().getTime() ? 0 : 1)));
    if (list.size() > 0) {
        open = list.get(0).getTradePrice().getValue();
        close = list.get(list.size() - 1).getTradePrice().getValue();
    }
    long averagePrice;
    boolean isBullish;
    if (CurrencyUtil.isCryptoCurrency(getCurrencyCode())) {
        isBullish = close < open;
        double accumulatedAmountAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedAmount, Altcoin.SMALLEST_UNIT_EXPONENT);
        averagePrice = MathUtils.roundDoubleToLong(accumulatedAmountAsDouble / (double) accumulatedVolume);
    } else {
        isBullish = close > open;
        double accumulatedVolumeAsDouble = MathUtils.scaleUpByPowerOf10((double) accumulatedVolume, Coin.SMALLEST_UNIT_EXPONENT);
        averagePrice = MathUtils.roundDoubleToLong(accumulatedVolumeAsDouble / (double) accumulatedAmount);
    }
    final Date dateFrom = new Date(getTimeFromTickIndex(tick));
    final Date dateTo = new Date(getTimeFromTickIndex(tick + 1));
    String dateString = tickUnit.ordinal() > TickUnit.DAY.ordinal() ? formatter.formatDateTimeSpan(dateFrom, dateTo) : formatter.formatDate(dateFrom) + " - " + formatter.formatDate(dateTo);
    return new CandleData(tick, open, close, high, low, averagePrice, accumulatedAmount, accumulatedVolume, numTrades, isBullish, dateString);
}
Also used : CandleData(bisq.desktop.main.market.trades.charts.CandleData) TradeStatistics2(bisq.core.trade.statistics.TradeStatistics2) ArrayList(java.util.ArrayList) Date(java.util.Date) VisibleForTesting(com.google.common.annotations.VisibleForTesting)

Example 4 with CandleData

use of bisq.desktop.main.market.trades.charts.CandleData in project bisq-desktop by bisq-network.

the class CandleStickChart method updateAxisRange.

/**
 * This is called when the range has been invalidated and we need to update it. If the axis are auto
 * ranging then we compile a list of all data that the given axis has to plot and call invalidateRange() on the
 * axis passing it that data.
 */
@Override
protected void updateAxisRange() {
    // For candle stick chart we need to override this method as we need to let the axis know that they need to be able
    // to cover the whole area occupied by the high to low range not just its center data value
    final Axis<Number> xa = getXAxis();
    final Axis<Number> ya = getYAxis();
    List<Number> xData = null;
    List<Number> yData = null;
    if (xa.isAutoRanging()) {
        xData = new ArrayList<>();
    }
    if (ya.isAutoRanging()) {
        yData = new ArrayList<>();
    }
    if (xData != null || yData != null) {
        for (XYChart.Series<Number, Number> series : getData()) {
            for (XYChart.Data<Number, Number> data : series.getData()) {
                if (xData != null) {
                    xData.add(data.getXValue());
                }
                if (yData != null) {
                    if (data.getExtraValue() instanceof CandleData) {
                        CandleData candleData = (CandleData) data.getExtraValue();
                        yData.add(candleData.high);
                        yData.add(candleData.low);
                    } else {
                        yData.add(data.getYValue());
                    }
                }
            }
        }
        if (xData != null) {
            xa.invalidateRange(xData);
        }
        if (yData != null) {
            ya.invalidateRange(yData);
        }
    }
}
Also used : CandleData(bisq.desktop.main.market.trades.charts.CandleData) XYChart(javafx.scene.chart.XYChart)

Example 5 with CandleData

use of bisq.desktop.main.market.trades.charts.CandleData in project bisq-desktop by bisq-network.

the class VolumeChart method layoutPlotChildren.

@Override
protected void layoutPlotChildren() {
    if (getData() == null) {
        return;
    }
    for (int seriesIndex = 0; seriesIndex < getData().size(); seriesIndex++) {
        XYChart.Series<Number, Number> series = getData().get(seriesIndex);
        Iterator<XYChart.Data<Number, Number>> iter = getDisplayedDataIterator(series);
        while (iter.hasNext()) {
            XYChart.Data<Number, Number> item = iter.next();
            double x = getXAxis().getDisplayPosition(getCurrentDisplayedXValue(item));
            double y = getYAxis().getDisplayPosition(getCurrentDisplayedYValue(item));
            Node itemNode = item.getNode();
            CandleData candleData = (CandleData) item.getExtraValue();
            if (itemNode instanceof VolumeBar && candleData != null) {
                VolumeBar volumeBar = (VolumeBar) itemNode;
                double candleWidth = -1;
                if (getXAxis() instanceof NumberAxis) {
                    NumberAxis xa = (NumberAxis) getXAxis();
                    // use 90% width between ticks
                    candleWidth = xa.getDisplayPosition(xa.getTickUnit()) * 0.90;
                }
                // 97 is visible chart data height if chart height is 140.
                // So we subtract 43 form the height to get the height for the bar to the bottom.
                // Did not find a way how to request the chart data height
                final double height = getHeight() - 43;
                // We want min 5px height to allow tooltips
                double upperYPos = Math.min(height - 5, y);
                volumeBar.update(height - upperYPos, candleWidth, candleData);
                volumeBar.setLayoutX(x);
                volumeBar.setLayoutY(upperYPos);
            }
        }
    }
}
Also used : NumberAxis(javafx.scene.chart.NumberAxis) CandleData(bisq.desktop.main.market.trades.charts.CandleData) Node(javafx.scene.Node) XYChart(javafx.scene.chart.XYChart) CandleData(bisq.desktop.main.market.trades.charts.CandleData)

Aggregations

CandleData (bisq.desktop.main.market.trades.charts.CandleData)6 XYChart (javafx.scene.chart.XYChart)4 TradeStatistics2 (bisq.core.trade.statistics.TradeStatistics2)3 Date (java.util.Date)3 VisibleForTesting (com.google.common.annotations.VisibleForTesting)2 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 MathUtils (bisq.common.util.MathUtils)1 CryptoCurrency (bisq.core.locale.CryptoCurrency)1 CurrencyUtil (bisq.core.locale.CurrencyUtil)1 FiatCurrency (bisq.core.locale.FiatCurrency)1 GlobalSettings (bisq.core.locale.GlobalSettings)1 TradeCurrency (bisq.core.locale.TradeCurrency)1 Altcoin (bisq.core.monetary.Altcoin)1 PriceFeedService (bisq.core.provider.price.PriceFeedService)1 TradeStatisticsManager (bisq.core.trade.statistics.TradeStatisticsManager)1 Preferences (bisq.core.user.Preferences)1 Navigation (bisq.desktop.Navigation)1 ActivatableViewModel (bisq.desktop.common.model.ActivatableViewModel)1 MainView (bisq.desktop.main.MainView)1