Martin Ille
Martin Ille

Reputation: 7055

Is it possible to show hollow candle in Candlestick jfreechart?

Most of financial chart libraries use some rules for coloring the candles:

  1. if close >= open, then candle is hollow (not filled)
  2. if close < open, then candle is filled
  3. if previous close <= close, then candle is green
  4. if previous close > close, then candle is red

jFreeChart seems to have own rules for coloring and it's possible to change them. By default the chart looks something like this (some colors has been changed):

candlestick chart jfreechart

So as you see, it is possible to change the colors of candles, background, plot borders etc.

I'd like to implement rules 1 and 2 (above) to the chart. Is it possible?

The result should be like this:

jfreechart ohlc candlestick

This is my current CandlestickRenderer used in the example:

public class CandlestickRenderer extends org.jfree.chart.renderer.xy.CandlestickRenderer {

    public CandlestickRenderer() {
        setDrawVolume(false);
    }

    @Override
    public Paint getItemPaint(int series, int item) {
        OHLCDataset highLowData = (OHLCDataset)getPlot().getDataset(series);
        Number curClose = highLowData.getClose(series, item);
        Number prevClose = highLowData.getClose(series, item>0 ? item-1 : 0);
        if (prevClose.doubleValue() <=  curClose.doubleValue()) {
            return getUpPaint();
        }
        else {
            return getDownPaint();
        }
    }   
}

Update 1

It seems it can be done just by setting up paint to black and draw item pant unchanged with colors.

public class CandlestickRenderer extends org.jfree.chart.renderer.xy.CandlestickRenderer {

    public CandlestickRenderer() {
        setDrawVolume(false);
        setUseOutlinePaint(false);
        setUpPaint(Color.BLACK); // <-- rule 1. (plot is also black so it looks not filled)
    }

    @Override
    public Paint getItemPaint(int series, int item) {
        OHLCDataset highLowData = (OHLCDataset) getPlot().getDataset(series);
        Number curClose = highLowData.getClose(series, item);
        Number prevClose = highLowData.getClose(series, item>0 ? item-1 : 0);

        if (prevClose.doubleValue() <=  curClose.doubleValue()) {
            return Color.GREEN; // <-- rule 3.
        } else {
            return Color.RED; // <-- rule 4.
        }
    }

}

But the main question lasts:

This is the strange result now:

enter image description here

Upvotes: 4

Views: 948

Answers (1)

Martin Ille
Martin Ille

Reputation: 7055

I've done it. Here is the complete own renderer:

public class CandlestickRenderer extends org.jfree.chart.renderer.xy.CandlestickRenderer {

    private final Paint colorRaising = Color.GREEN;
    private final Paint colorFalling = Color.RED;
    private final Paint colorUnknown = Color.GRAY;
    private final Paint colorTransparent = Color.BLACK;

    public CandlestickRenderer() {
        setDrawVolume(false);
        setUpPaint(colorUnknown); // use unknown color if error
        setDownPaint(colorUnknown); // use unknown color if error
    }


    @Override
    public Paint getItemPaint(int series, int item) {
        OHLCDataset highLowData = (OHLCDataset) getPlot().getDataset(series);
        Number curClose = highLowData.getClose(series, item);
        Number prevClose = highLowData.getClose(series, item>0 ? item-1 : 0);

        if (prevClose.doubleValue() <=  curClose.doubleValue()) {
            return Color.GREEN;
        } else {
            return Color.RED;
        }
    }


    @Override
    public void drawItem(Graphics2D g2, XYItemRendererState state,
            Rectangle2D dataArea, PlotRenderingInfo info, XYPlot plot,
            ValueAxis domainAxis, ValueAxis rangeAxis, XYDataset dataset,
            int series, int item, CrosshairState crosshairState, int pass) {

        OHLCDataset highLowData = (OHLCDataset) dataset;
        double yOpen = highLowData.getOpenValue(series, item);
        double yClose = highLowData.getCloseValue(series, item);        

        // set color for filled candle
        if (yClose >= yOpen) {
            setUpPaint(colorRaising);
            setDownPaint(colorFalling);
        }

        // set color for hollow (not filled) candle
        else {
            setUpPaint(colorTransparent);
            setDownPaint(colorTransparent);
        }

        // call parent method
        super.drawItem(g2, state, dataArea, info, plot, domainAxis, rangeAxis, dataset, series, item, crosshairState, pass);
    }   

}

And resulting chart:

enter image description here

Don't hesitate to contact me if you'll want all the example code.

Upvotes: 3

Related Questions