0

I create a single dataset which contains the OHLC data and the volume data in a DefaultOHLC dataset. The only problem is that when the volume is plotted, it overlaps a lot of the OHLC data. As this is a single data series, I can't figure out how to address the volume data specifically to scale it down. I'd like to keep it below the yellow line on the image. How can I do this ?

enter image description here

public class DefaultChart {

    private String title;
    private DefaultOHLCDataset ohlcData;
    private CandlestickRenderer renderer;
    private JFreeChart chart;
    private XYPlot plot;
    private DateAxis dateAxis;
    private NumberAxis numberAxis;

    public DefaultChart(String tile, List<Candlestick> candles) {
        this.title = tile;
        ohlcData = (DefaultOHLCDataset) getDataSet(candles);
        dateAxis = new DateAxis(StringConstants.time_axis_label);
        numberAxis = new NumberAxis(StringConstants.value_axis_label);
        renderer = new CandlestickRenderer();
    }

    public void createChart() {
        chart = ChartFactory.createCandlestickChart(title, StringConstants.time_axis_label, StringConstants.value_axis_label, ohlcData, true);
    }

    /**
     * Prepare to display result
     */
    public void displayChart() {
        // Chart panel
        ChartPanel panel = new ChartPanel(chart);
        panel.setFillZoomRectangle(true);
        panel.setMouseWheelEnabled(true);
        panel.setPreferredSize(new java.awt.Dimension(1000, 700));

        // Application frame
        ApplicationFrame frame = new ApplicationFrame("Candlestick chart");
        UIUtils.positionFrameOnScreen(frame, 0.3, 0.3);
        frame.setContentPane(panel);
        frame.pack();
        frame.setVisible(true);
    }

    /**
     * Candlestick rendering
     */
    public void candleStickRendering() {
        renderer.setAutoWidthMethod(CandlestickRenderer.WIDTHMETHOD_SMALLEST);
        renderer.setDrawVolume(true);

        //How to scale to volume data?
        plot = chart.getXYPlot();
        plot.setRenderer(renderer);
        plot.setRangeGridlinePaint(Color.lightGray);
        plot.setBackgroundPaint(Color.white);
        plot.setDatasetRenderingOrder(DatasetRenderingOrder.FORWARD);

        setValueAxis();
        setTimeAxis();
    }

    public long getLastCandleTimeStamp() {
       return ohlcData.getXDate(0,ohlcData.getItemCount(0)-1).getTime();
    }

    public void setValueAxis() {
        NumberAxis numberAxis = (NumberAxis) plot.getRangeAxis();
        numberAxis.setAutoRangeIncludesZero(false);

        Font bold = numberAxis.getLabelFont().deriveFont(Font.BOLD);
        numberAxis.setLabelFont(bold);
    }

    public void setTimeAxis() {
        DateAxis dateAxis = (DateAxis) plot.getDomainAxis();
        dateAxis.setLowerMargin(0);//align left side
        dateAxis.setUpperMargin(0.125);
        dateAxis.setTickLabelsVisible(true);
        Font bold = dateAxis.getLabelFont().deriveFont(Font.BOLD);
        dateAxis.setLabelFont(bold);
    }

    private static double convertToDouble(String value) {
        return Double.parseDouble(value);
    }

    protected AbstractXYDataset getDataSet(List<Candlestick>candlesticks) {
        //This is the dataset we are going to create
        DefaultOHLCDataset result = null;
        //This is the data needed for the dataset
        OHLCDataItem[] data;

        //This is where we go get the data, replace with your own data source
        data = getData(candlesticks);

        //Create a dataset, an Open, High, Low, Close dataset
        result = new DefaultOHLCDataset("OHLCV", data);

        return result;
    }

    protected OHLCDataItem[] getData(List<Candlestick> candlesticks) {
        List<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();

        for (Candlestick c : candlesticks) {
            Date date = new Date(c.getOpenTime());
            double open = convertToDouble(c.getOpen());
            double high = convertToDouble(c.getHigh());
            double low = convertToDouble(c.getLow());
            double close = convertToDouble(c.getClose());
            double volume = convertToDouble(c.getVolume());

            OHLCDataItem item = new OHLCDataItem(date, open, high, low, close, volume);
            dataItems.add(item);
        }
        //Convert the list into an array
        OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);

        return data;
    }

    public static void main(String[] args) throws ParseException {
        String Ticker = "BTCUSDT";
        String TimeFrame = "4H";
        String Title = Ticker + " " + TimeFrame;

        FetchCandleSticks fetch = new FetchCandleSticks();
        List<Candlestick> candles = fetch.getFourHourlyCandles("BTCUSDT", TimeStamps.monthAgo());

        DefaultChart chart = new DefaultChart(Ticker, candles);
        chart.createChart();
        chart.candleStickRendering();
        chart.displayChart();
    }
}
Mark Rotteveel
  • 100,966
  • 191
  • 140
  • 197
leroyv
  • 63
  • 5
  • You could _scale_ the volume; alternatively, you could configure the `OHLCDataset` _not_ to `drawVolume` and plot volume against a second axis. – trashgod Nov 12 '21 at 23:27
  • how would i scale the volume in my current case? i cant find any options to interact with the volume. Only thing i can find is the setvisible option for the volume. thank you in advance – leroyv Nov 13 '21 at 10:41
  • 1
    It looks like the renderer will rescale it anyway; I'd guess you'll have to suppress the volume display and use a second axis, for [example](https://stackoverflow.com/q/13358758/230513). If you go that way, please [edit] your question to include a [mre] that shows your revised approach with data. – trashgod Nov 13 '21 at 20:32

0 Answers0