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));
}
}
}
}
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()));
}
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);
}
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);
}
}
}
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);
}
}
}
}
Aggregations