List of usage examples for org.jfree.data.xy DefaultHighLowDataset getLowValue
@Override public double getLowValue(int series, int item)
From source file:org.yccheok.jstock.gui.charting.ChartJDialog.java
/** * Zoom in to this chart with specific amount of time. * @param field the calendar field.//from ww w . j a va 2s. c om * @param amount the amount of date or time to be added to the field. */ private void _zoom(int field, int amount) { this.chartPanel.restoreAutoBounds(); final int itemCount = this.priceTimeSeries.getItemCount(); final Day day = (Day) this.priceTimeSeries.getDataItem(itemCount - 1).getPeriod(); // Candle stick takes up half day space. // Volume price chart's volume information takes up whole day space. final long end = day.getFirstMillisecond() + (this.getCurrentType() == Type.Candlestick ? (1000 * 60 * 60 * 12) : (1000 * 60 * 60 * 24 - 1)); final Calendar calendar = Calendar.getInstance(); // -1. Calendar's month is 0 based but JFreeChart's month is 1 based. calendar.set(day.getYear(), day.getMonth() - 1, day.getDayOfMonth(), 0, 0, 0); calendar.set(Calendar.MILLISECOND, 0); calendar.add(field, amount); // Candle stick takes up half day space. // Volume price chart's volume information does not take up any space. final long start = Math.max(0, calendar.getTimeInMillis() - (this.getCurrentType() == Type.Candlestick ? (1000 * 60 * 60 * 12) : 0)); final ValueAxis valueAxis = this.getPlot().getDomainAxis(); if (priceTimeSeries.getItemCount() > 0) { if (start < priceTimeSeries.getTimePeriod(0).getFirstMillisecond()) { // To prevent zoom-out too much. // This happens when user demands for 10 years zoom, where we // are only having 5 years data. return; } } valueAxis.setRange(start, end); double min = Double.MAX_VALUE; double max = Double.MIN_VALUE; double max_volume = Double.MIN_VALUE; final DefaultHighLowDataset defaultHighLowDataset = (DefaultHighLowDataset) this.priceOHLCDataset; for (int i = itemCount - 1; i >= 0; i--) { final TimeSeriesDataItem item = this.priceTimeSeries.getDataItem(i); final Day d = (Day) item.getPeriod(); if (d.getFirstMillisecond() < start) { break; } final double high = defaultHighLowDataset.getHighValue(0, i); final double low = defaultHighLowDataset.getLowValue(0, i); final double volume = defaultHighLowDataset.getVolumeValue(0, i); if (max < high) { max = high; } if (min > low) { min = low; } if (max_volume < volume) { max_volume = volume; } } if (min > max) { return; } final ValueAxis rangeAxis = this.getPlot().getRangeAxis(); final Range rangeAxisRange = rangeAxis.getRange(); // Increase each side by 1% double tolerance = 0.01 * (max - min); // The tolerance must within range [0.01, 1.0] tolerance = Math.min(Math.max(0.01, tolerance), 1.0); // The range must within the original chart range. min = Math.max(rangeAxisRange.getLowerBound(), min - tolerance); max = Math.min(rangeAxisRange.getUpperBound(), max + tolerance); this.getPlot().getRangeAxis().setRange(min, max); if (this.getPlot().getRangeAxisCount() > 1) { final double volumeUpperBound = this.getPlot().getRangeAxis(1).getRange().getUpperBound(); final double suggestedVolumneUpperBound = max_volume * 4; // To prevent over zoom-in. if (suggestedVolumneUpperBound < volumeUpperBound) { this.getPlot().getRangeAxis(1).setRange(0, suggestedVolumneUpperBound); } } }
From source file:org.yccheok.jstock.gui.charting.ChartJDialog.java
/** * Calculate and update high low value labels, according to current displayed * time range. This is a time consuming method, and shall be called by * user thread.// w w w . jav a2s .c o m */ private void _updateHighLowJLabels() { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ChartJDialog.this.jLabel2.setText(""); ChartJDialog.this.jLabel4.setText(""); } }); final ValueAxis valueAxis = this.getPlot().getDomainAxis(); final Range range = valueAxis.getRange(); final long lowerBound = (long) range.getLowerBound(); final long upperBound = (long) range.getUpperBound(); // Perform binary search, to located day in price time series, which // is equal or lesser than upperBound. int low = 0; int high = this.priceTimeSeries.getItemCount() - 1; long best_dist = Long.MAX_VALUE; int best_mid = -1; while (low <= high) { int mid = (low + high) >>> 1; final Day day = (Day) this.priceTimeSeries.getDataItem(mid).getPeriod(); long v = day.getFirstMillisecond(); if (v > upperBound) { high = mid - 1; } else if (v < upperBound) { low = mid + 1; long dist = upperBound - v; if (dist < best_dist) { best_dist = dist; best_mid = mid; } } else { best_dist = 0; best_mid = mid; break; } } if (best_mid < 0) { return; } double high_price = -Double.MAX_VALUE; double low_price = Double.MAX_VALUE; final DefaultHighLowDataset defaultHighLowDataset = (DefaultHighLowDataset) this.priceOHLCDataset; for (int i = best_mid; i >= 0; i--) { final TimeSeriesDataItem item = this.priceTimeSeries.getDataItem(i); final long time = ((Day) item.getPeriod()).getFirstMillisecond(); if (time < lowerBound) { break; } final double _high_price = defaultHighLowDataset.getHighValue(0, i); final double _low_price = defaultHighLowDataset.getLowValue(0, i); final double _last_price = defaultHighLowDataset.getCloseValue(0, i); high_price = Math.max(high_price, _high_price); // Prevent bad data. if (_low_price > 0) { low_price = Math.min(low_price, _low_price); } else { if (_high_price > 0) { low_price = Math.min(low_price, _high_price); } if (_last_price > 0) { low_price = Math.min(low_price, _last_price); } } } final double h = high_price; final double l = low_price; if (high_price >= low_price) { SwingUtilities.invokeLater(new Runnable() { @Override public void run() { ChartJDialog.this.jLabel2.setText(org.yccheok.jstock.gui.Utils.stockPriceDecimalFormat(h)); ChartJDialog.this.jLabel4.setText(org.yccheok.jstock.gui.Utils.stockPriceDecimalFormat(l)); } }); } }