How to implement constant volume candlestick bars?

Discussion about JFreeChart related to stockmarket charts.
Locked
ptd26
Posts: 27
Joined: Sun Nov 08, 2009 10:12 am
antibot: No, of course not.

How to implement constant volume candlestick bars?

Post by ptd26 » Mon Jan 04, 2010 9:02 pm

I want to modify the candlestick renderer and OHLC dataset so that I can create constant volume candlestick bars. This will require that the x-axis is no longer linear with time. I know how to change the renderer and create a new dataset to represent constant volume bars. However, how do I change to a date time axis that does not have constant time spacing?

skunk
Posts: 1087
Joined: Thu Jun 02, 2005 10:14 pm
Location: Brisbane, Australia

Re: How to implement constant volume candlestick bars?

Post by skunk » Tue Jan 05, 2010 2:30 pm


ptd26
Posts: 27
Joined: Sun Nov 08, 2009 10:12 am
antibot: No, of course not.

Re: How to implement constant volume candlestick bars?

Post by ptd26 » Wed Mar 17, 2010 10:48 pm

Image

I appreciate the help from skunk below and in the spirit of open source development, I'm happy to share his code, slightly modified, which I used to setup constant volume bars in JFreeChart. It would be great if there was a constant volume bar (non-linear time axis support) built into the next release of JFreeChart. The code posted below which produces the plot shown works, but is very slow, even on a modern system.

Some of this code is specific to some other stuff I am doing and might need to be commented out in order to compile:

Code: Select all

public class Candlestick extends JPanel implements ChartChangeListener {
	private Dataset dataset; 
	private ConstVolumeOHLCDataset data; 
	private JFreeChart chart;
	private ChartPanel chartpanel;

	public Candlestick(Dataset dataset, Set<ChartCallback> charts)
	{
		this.setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
		this.setBackground(Color.BLACK);
		this.dataset = dataset;
		data = dataset.getCandlesticks();
		setupCandleStickChart();
		chart.addChangeListener(this);
	}

	private void setupCandleStickChart() {
		chart = ChartFactory.createCandlestickChart(
				null,
				null,
				null,
				data,
				false
		);	

		chartpanel = new ChartPanel(chart);
		XYPlot xyplot = chartpanel.getChart().getXYPlot();
		xyplot.setDomainCrosshairVisible(true);
		xyplot.setDomainCrosshairLockedOnData(false);
		xyplot.setRangeCrosshairVisible(true);
		xyplot.setRangeAxisLocation(AxisLocation.BOTTOM_OR_RIGHT);
		NumberAxis numaxis = (NumberAxis) chart.getXYPlot().getRangeAxis();
		numaxis.setAutoRangeIncludesZero(false);
	
		NumberAxis axis = new NumberAxis();
		xyplot.setDomainAxis(axis);
		axis.setStandardTickUnits(NumberAxis.createIntegerTickUnits());
		axis.setNumberFormatOverride(new TranslatingFormat(data));
		
		add(chartpanel);
	}
}

Code: Select all

package JFreeChartext;

import  org.jfree.data.xy.*;

public class ConstVolumeOHLCDataset extends DefaultOHLCDataset {

	public ConstVolumeOHLCDataset(Comparable key, OHLCDataItem[] data) {
		super(key, data);
		// TODO Auto-generated constructor stub
	}

    public double getXValue(int series, int item) {
        if ((item < 0) || (item >= getItemCount(series)))
            return Double.NaN;
        return item;
    }
    public double getDisplayXValue(int series, int item) {
        if ((item < 0) || (item >= getItemCount(series)))
            return Double.NaN;
        return super.getXValue(series, item);
    }
// These are commented out but you WILL need to implement them as soon as you
//  need to call setRange() and need to convert timevalues to data indexes
//
//    public int findFirstXValueGE(long timeval);
//    public int findLastXValueLE(long timeval);
}

Code: Select all

package JFreeChartext;

import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.FieldPosition;
import java.text.SimpleDateFormat;
import java.util.Date;

public class TranslatingFormat extends DecimalFormat {
    final ConstVolumeOHLCDataset constvoldataset;
    final DateFormat fmt = new SimpleDateFormat("HH:mm:ss");

    public TranslatingFormat(ConstVolumeOHLCDataset ds) {
    	assert(ds != null);
        constvoldataset = ds;
    }
    
    public StringBuffer format(double number, StringBuffer toAppendTo, FieldPosition pos) {
        if (Double.isNaN(number))
            return toAppendTo;
        double timeval = constvoldataset.getDisplayXValue(0, (int)number);
        if (Double.isNaN(timeval))
            return toAppendTo;
        return toAppendTo.append(fmt.format(new Date((long)timeval)));
    }
}

Astrophobos
Posts: 1
Joined: Tue Apr 20, 2010 2:47 am
antibot: No, of course not.
Contact:

Re: How to implement constant volume candlestick bars?

Post by Astrophobos » Tue Apr 20, 2010 2:51 am

ptd26, can you please explain what is going on when you call getCandlesticks on you dataset?

Thank you for sharing ptd26.

ptd26
Posts: 27
Joined: Sun Nov 08, 2009 10:12 am
antibot: No, of course not.

Re: How to implement constant volume candlestick bars?

Post by ptd26 » Mon May 03, 2010 8:14 am

getCandlesticks() simply returns a ConstVolumeOHLCDataset.

snid3ly
Posts: 23
Joined: Wed Aug 07, 2013 4:21 am
antibot: No, of course not.

Re: How to implement constant volume candlestick bars?

Post by snid3ly » Wed Aug 07, 2013 4:25 am

This thread is over 3 years old. Is there a newer/better way to implement constant volume candlestick bars now?

Thanks!

Locked