BUG: CombinedDomainXYPlot with CandlestickRenderer

Discussion about JFreeChart related to stockmarket charts.
Locked
Aquajock
Posts: 6
Joined: Fri Dec 07, 2012 12:03 am
antibot: No, of course not.

BUG: CombinedDomainXYPlot with CandlestickRenderer

Post by Aquajock » Fri Dec 07, 2012 12:08 am

Code: Select all

package chart;

import java.awt.EventQueue;
import java.util.Calendar;

import javax.swing.JFrame;
import javax.swing.WindowConstants;

import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.data.xy.DefaultOHLCDataset;
import org.jfree.data.xy.OHLCDataItem;

/**
 * This is an example of a CombinedDomainXYPlot that misbehaves with CandlestickRenderer.
 * Note that the datasets of the subplots are not set at instantiation.
 * Instead, they are set later using #setDataset(Dataset).
 * Running the code as shown results in the first plot being only partially rendered.
 * Swapping the lines labeled LOOK HERE results in the second plot being only partially rendered.
 * Adding more subplots results in the first plot whose dataset is set exhibiting this problem.
 * Telling me to set the dataset in the constructors doesn't solve the problem.
 * Built with JFreeChart 1.0.14.
 */
public class MultiPlotProblem implements Runnable
	{
// MAIN ///////////////////////////////////////////////////////////////////////
	
	static public void main(String[] avs){EventQueue.invokeLater(new MultiPlotProblem());}
	
// STATIC VARIABLES ///////////////////////////////////////////////////////////
	
	static final int	gknDays	= 365;
	static final double	gkdDay	= 2*Math.PI/gknDays;
	
// CONSTRUCTORS ///////////////////////////////////////////////////////////////
	
	public MultiPlotProblem() {super();}

// PUBLIC INSTANCE METHODS ////////////////////////////////////////////////////
	
	@Override
	public void run()
		{
	// make dataset
		Calendar oCalendar = Calendar.getInstance();
		oCalendar.set(Calendar.YEAR,2010);
		OHLCDataItem[] voOHLCDataItem = new OHLCDataItem[gknDays];
		int iC;
		int iH = 0;
		int iL = 0;
		int iO = 1000;
		for (int i = 0; i < gknDays; )
			{
			oCalendar.set(Calendar.DAY_OF_YEAR,++i);
			int iSin = (int)(Math.sin(gkdDay*i*2)*100);
			iC = iO+iSin;
			iH = Math.max(iC,iO)+Math.abs(iSin);
			iL = Math.min(iC,iO)-Math.abs(iSin);
			voOHLCDataItem[i-1] = new OHLCDataItem(oCalendar.getTime(),iO,iH,iL,iC,iH-iL);
			iO = iC;
			}
		DefaultOHLCDataset oDataset = new DefaultOHLCDataset("",voOHLCDataItem);
		
	// make combined plot
		XYPlot oPlot0 = new XYPlot(null,null,new NumberAxis(),new CandlestickRenderer());
		XYPlot oPlot1 = new XYPlot(null,null,new NumberAxis(),new CandlestickRenderer());
		CombinedDomainXYPlot oPlotCombined = new CombinedDomainXYPlot(new DateAxis());
		oPlotCombined.add(oPlot0);
		oPlotCombined.add(oPlot1);
		
	// make and show frame
		JFrame oJFrame = new JFrame();
		oJFrame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
		oJFrame.setContentPane(new ChartPanel(new JFreeChart(oPlotCombined)));
		oJFrame.setSize(700,500);
		oJFrame.setVisible(true);
		
	// set dataset
		oPlot0.setDataset(oDataset); // LOOK HERE
		oPlot1.setDataset(oDataset); // LOOK HERE
		}
	}

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: BUG: CombinedDomainXYPlot with CandlestickRenderer

Post by david.gilbert » Sat Jan 05, 2013 12:05 pm

Thanks for the example, I can reproduce the problem exactly as you described. It looks like an issue with the auto-range calculation on the y-axis, I will debug.
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

david.gilbert
JFreeChart Project Leader
Posts: 11734
Joined: Fri Mar 14, 2003 10:29 am
antibot: No, of course not.
Contact:

Re: BUG: CombinedDomainXYPlot with CandlestickRenderer

Post by david.gilbert » Sat Jan 05, 2013 1:23 pm

The issue is that when the first dataset is applied, the auto-range calculation is not triggered for the domain axis on the combined plot, and then the auto-range calculation for the y-axis of the subplot doesn't consider the full range of values. This is a bug, but I don't know the correct fix yet. A workaround is to call the method to set the dataset twice (just for the first one)...the second time around, the domain axis range is correct so the y-axis auto-range calculation works as it should:

Code: Select all

      oPlot0.setDataset(oDataset); // LOOK HERE
      oPlot0.setDataset(oDataset); // THIS LINE ADDED
      oPlot1.setDataset(oDataset); // LOOK HERE
David Gilbert
JFreeChart Project Leader

:idea: Read my blog
:idea: Support JFree via the Github sponsorship program

Aquajock
Posts: 6
Joined: Fri Dec 07, 2012 12:03 am
antibot: No, of course not.

Re: BUG: CombinedDomainXYPlot with CandlestickRenderer

Post by Aquajock » Tue Jan 08, 2013 1:08 am

Thank you. BTW Nice piece of work, this.

Locked