Candlestick chart with scrollbar

Discussion about JFreeChart related to stockmarket charts.
Locked
tapion
Posts: 5
Joined: Fri Jan 16, 2009 11:58 pm

Candlestick chart with scrollbar

Post by tapion » Sat Jan 17, 2009 12:11 am

Hello.
I wrote this code for a candlestickChart with two plots on it(price and buy/sell signals) and I tried to add a scrollbar like an example that i saw on this forum. I have a serie with 1000 items, but on the chart i want to see about 100 items and move the chart thanks to a scrollbar. With this code i see the scrollbar and all 1000 values, instead of only 100 values, and moving the scrollbar the chart doesn't move. (sorry for my bad english)
Can someone help me? Thanks in advance


Code: Select all

package chart;
import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.SegmentedTimeline;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.data.xy.*;
import org.jfree.ui.RefineryUtilities;

import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.swing.JFrame;
import javax.swing.JScrollBar;

public class CandlestickChart extends JFrame {
	final int maxdays = 100;
	
    public CandlestickChart(LinkedList<day.Day> list, String title){
    	super(title + ": Chart + Buy/Sell signals");
    	this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        //Shared date axis
        DateAxis            domainAxis = new DateAxis("Date");
        domainAxis.setTickMarkPosition( DateTickMarkPosition.START );
        domainAxis.setTimeline( SegmentedTimeline.newMondayThroughFridayTimeline() );
        domainAxis.setDateFormatOverride(new SimpleDateFormat("dd-MM-yy"));

        //Build Candlestick Chart based on stock price OHLC
        OHLCDataset         priceDataset  = getPriceDataSet(title,list);
        NumberAxis          priceAxis     = new NumberAxis("Price");
        CandlestickRenderer priceRenderer = new CandlestickRenderer();
        XYPlot              pricePlot     = new XYPlot(priceDataset, domainAxis, priceAxis, priceRenderer);
        priceRenderer.setSeriesPaint(0, Color.BLACK);
        priceRenderer.setDrawVolume(true);
        priceAxis.setAutoRangeIncludesZero(false);
        
        OHLCDataset         signalDataset  = getSignalDataSet(title,list);
        NumberAxis signalAxis     = new NumberAxis("Signal");
        CandlestickRenderer signalRenderer = new CandlestickRenderer();
        XYPlot              signalPlot     = new XYPlot(signalDataset, domainAxis, signalAxis, signalRenderer);
        signalRenderer.setSeriesPaint(0, Color.BLACK);
        signalRenderer.setDrawVolume(false);
        signalAxis.setAutoRangeIncludesZero(true);
       
        //Build Combined Plot
        CombinedDomainXYPlot mainPlot = new CombinedDomainXYPlot(domainAxis);
        mainPlot.add(pricePlot,4);
        mainPlot.add(signalPlot,1);
        
        JFreeChart chart = new JFreeChart(title, null, mainPlot, false);
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setSize(600,600);
        chartPanel.setVisible(true);
        this.add(chartPanel);
        this.add(getScrollBar(domainAxis), BorderLayout.SOUTH);
        this.pack();
        RefineryUtilities.centerFrameOnScreen(this);
    }

	private OHLCDataset getPriceDataSet(String symbol, LinkedList<day.Day> list) {
        List<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
        int counter = 0;
        ListIterator<day.Day> it = list.listIterator(list.size());
        while(it.hasPrevious() && counter<maxdays){
        	day.Day day = it.previous();
        	OHLCDataItem item = new OHLCDataItem(day.id, day.open, day.max, day.min, day.close, day.vol);
            dataItems.add(item);
            counter++;
        }
        OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);
        return new DefaultOHLCDataset(symbol, data);
    }

    private OHLCDataset getSignalDataSet(String symbol, LinkedList<day.Day> list) {
        List<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
        int counter = 0;
        ListIterator<day.Day> it = list.listIterator(list.size());
        while(it.hasPrevious() && counter<maxdays){
        	day.Day day = it.previous();
        	if(day.signalType>0){
        		OHLCDataItem item = new OHLCDataItem(day.id, 0, day.signalType, 0, day.signalType, 0);
        		dataItems.add(item);
        	} else if(day.signalType<0){
        		OHLCDataItem item = new OHLCDataItem(day.id, 0, 0, day.signalType, day.signalType, 0);
        		dataItems.add(item);
        	}
        	counter++;
        }
        OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);
        return new DefaultOHLCDataset(symbol, data);
    }
    
    private JScrollBar getScrollBar(final DateAxis domainAxis){
        final double r1 = domainAxis.getLowerBound();
        final double r2 = domainAxis.getUpperBound();
        JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 100, 0, 400);
        scrollBar.addAdjustmentListener( new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent e) {
                double x = e.getValue() *60 *60 * 1000;
                domainAxis.setRange(r1+x, r2+x);
            }
        });
        return scrollBar;
    }

} 

tapion
Posts: 5
Joined: Fri Jan 16, 2009 11:58 pm

Post by tapion » Sun Feb 01, 2009 2:10 am

omg no answers since 15 days :shock:

sawo01
Posts: 4
Joined: Wed Jan 14, 2009 4:53 pm

<Day>

Post by sawo01 » Mon Feb 02, 2009 3:21 pm

It may my mistake, but I can't resolve the <Day> Could u tell me please, in which package can be found? Or if it is a custom class, please post it also.

Thx

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

Post by david.gilbert » Mon Feb 02, 2009 10:46 pm

tapion wrote:omg no answers since 15 days :shock:
Lots of people ask questions, only a few provide answers. Since there is not enough time to answer all questions, some don't get answered. That shouldn't shock you.

I actually took the time to copy and paste your code into NetBeans to see if I could spot the problem...but it doesn't compile so I wasn't able to try it out. Now I could go through it line by line trying to figure out what it is doing and what might be going wrong, but in the end I just moved on to something else more interesting.
David Gilbert
JFreeChart Project Leader

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

tapion
Posts: 5
Joined: Fri Jan 16, 2009 11:58 pm

Post by tapion » Mon Feb 02, 2009 11:59 pm

I'm sorry... Now here is the code with all the classes/initialized variables/main method... So you could compile the code and find out the problem. Thank you so much.

Code: Select all

import org.jfree.chart.ChartFrame;
import org.jfree.chart.ChartPanel;
import org.jfree.chart.JFreeChart;
import org.jfree.chart.axis.DateAxis;
import org.jfree.chart.axis.DateTickMarkPosition;
import org.jfree.chart.axis.NumberAxis;
import org.jfree.chart.axis.SegmentedTimeline;
import org.jfree.chart.plot.CombinedDomainXYPlot;
import org.jfree.chart.plot.XYPlot;
import org.jfree.chart.renderer.xy.CandlestickRenderer;
import org.jfree.data.xy.*;
import org.jfree.ui.RefineryUtilities;

import java.awt.*;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

import javax.swing.JFrame;
import javax.swing.JScrollBar;

public class CandlestickChart extends JFrame {
   final int maxdays = 100;
   
   private class Day {
		public Date id;
		public double open;
		public double max;
		public double min;
		public double close;
		public long vol;
		public int signalType;
		public String colour;
		public double body_inf;
		public double body_sup;
		
		public Day(String ids, double open, double max, double min, double close,long vol) throws ParseException {
			DateFormat df = new SimpleDateFormat("y-M-d");
			this.id=df.parse(ids);
			this.open=open;
			this.max=max;
			this.min=min;
			this.close=close;
			this.vol=vol;
			if(close>=open){
				this.colour="G";
				this.body_inf=this.open;
				this.body_sup=this.close;
			} else {
				this.colour="R";
				this.body_inf=this.close;
				this.body_sup=this.open;
			}
		}
	}
   
   LinkedList<Day> list = new LinkedList<Day>();
   
    public CandlestickChart(String title) throws IOException, NumberFormatException, ParseException{
       super(title + ": Chart + Buy/Sell signals");
       this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
       
       readData();
       
        //Shared date axis
        DateAxis            domainAxis = new DateAxis("Date");
        domainAxis.setTickMarkPosition( DateTickMarkPosition.START );
        domainAxis.setTimeline( SegmentedTimeline.newMondayThroughFridayTimeline() );
        domainAxis.setDateFormatOverride(new SimpleDateFormat("dd-MM-yy"));

        //Build Candlestick Chart based on stock price OHLC
        OHLCDataset         priceDataset  = getPriceDataSet(title);
        NumberAxis          priceAxis     = new NumberAxis("Price");
        CandlestickRenderer priceRenderer = new CandlestickRenderer();
        XYPlot              pricePlot     = new XYPlot(priceDataset, domainAxis, priceAxis, priceRenderer);
        priceRenderer.setSeriesPaint(0, Color.BLACK);
        priceRenderer.setDrawVolume(true);
        priceAxis.setAutoRangeIncludesZero(false);
       
        OHLCDataset         signalDataset  = getSignalDataSet(title);
        NumberAxis signalAxis     = new NumberAxis("Signal");
        CandlestickRenderer signalRenderer = new CandlestickRenderer();
        XYPlot              signalPlot     = new XYPlot(signalDataset, domainAxis, signalAxis, signalRenderer);
        signalRenderer.setSeriesPaint(0, Color.BLACK);
        signalRenderer.setDrawVolume(false);
        signalAxis.setAutoRangeIncludesZero(true);
       
        //Build Combined Plot
        CombinedDomainXYPlot mainPlot = new CombinedDomainXYPlot(domainAxis);
        mainPlot.add(pricePlot,4);
        mainPlot.add(signalPlot,1);
       
        JFreeChart chart = new JFreeChart(title, null, mainPlot, false);
        ChartPanel chartPanel = new ChartPanel(chart);
        chartPanel.setSize(600,600);
        chartPanel.setVisible(true);
        this.add(chartPanel);
        this.add(getScrollBar(domainAxis), BorderLayout.SOUTH);
        this.pack();
        RefineryUtilities.centerFrameOnScreen(this);
    }

    private OHLCDataset getPriceDataSet(String symbol) {
        ArrayList<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
        int counter = 0;
        ListIterator<Day> it = list.listIterator(list.size());
        while(it.hasPrevious() /*&& counter<maxdays*/){
           Day day = it.previous();
           OHLCDataItem item = new OHLCDataItem(day.id, day.open, day.max, day.min, day.close, day.vol);
            dataItems.add(item);
            counter++;
        }
        OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);
        return new DefaultOHLCDataset(symbol, data);
    }

    private OHLCDataset getSignalDataSet(String symbol) {
        ArrayList<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
        int counter = 0;
        ListIterator<Day> it = list.listIterator(list.size());
        while(it.hasPrevious() && counter<maxdays){
           Day day = it.previous();
           if(day.signalType>0){
              OHLCDataItem item = new OHLCDataItem(day.id, 0, day.signalType, 0, day.signalType, 0);
              dataItems.add(item);
           } else if(day.signalType<0){
              OHLCDataItem item = new OHLCDataItem(day.id, 0, 0, day.signalType, day.signalType, 0);
              dataItems.add(item);
           }
           counter++;
        }
        OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);
        return new DefaultOHLCDataset(symbol, data);
    }
   
    private JScrollBar getScrollBar(final DateAxis domainAxis){
        final double r1 = domainAxis.getLowerBound();
        final double r2 = domainAxis.getUpperBound();
        JScrollBar scrollBar = new JScrollBar(JScrollBar.HORIZONTAL, 0, 100, 0, 400);
        scrollBar.addAdjustmentListener( new AdjustmentListener() {
            public void adjustmentValueChanged(AdjustmentEvent e) {
                double x = e.getValue() *60 *60 * 1000;
                domainAxis.setRange(r1+x, r2+x);
            }
        });
        return scrollBar;
    }
    
    private void readData() throws IOException, NumberFormatException, ParseException {
    	URL url = new URL("http://ichart.yahoo.com/table.csv?s=F.MI&a=00&b=1&c=2003&d=01&e=2&f=2009&g=d&ignore=.csv");
    	BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
		in.readLine();
		String line;
		try {
			while ((line = in.readLine()) != null) {
				StringTokenizer st = new StringTokenizer(line, ",");
		        String id = st.nextToken().trim();
		        String open = st.nextToken().trim();
		        String max = st.nextToken().trim();
		        String min = st.nextToken().trim();
		        st.nextToken().trim();
		        String vol = st.nextToken().trim();
		        String cload = st.nextToken().trim();
		        addRecord(id, Double.parseDouble(open), Double.parseDouble(max),
		        		Double.parseDouble(min), Double.parseDouble(cload), Long.parseLong(vol));
		    }
		} catch (FileNotFoundException e) {
		} catch (IOException e) {}
		Collections.reverse(list);
		
	}

	private void addRecord(String id, double open,
			double max, double min, double close,
			long vol) throws ParseException {
		list.add(new Day(id,open,max,min,close,vol));
	}
	
	public static void main(String[] args) throws IOException, NumberFormatException, ParseException {
		new CandlestickChart("FIAT Chart").setVisible(true);
	}

} 

sawo01
Posts: 4
Joined: Wed Jan 14, 2009 4:53 pm

data source

Post by sawo01 » Tue Feb 03, 2009 3:10 pm

There is one more thing that I dont understand. From where do U get the data that U want to display? From database? From yahoo finance or do u have a tool that generates random data for dispaling?

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

Re: data source

Post by skunk » Tue Feb 03, 2009 6:51 pm

sawo01 wrote:From where do U get the data that U want to display? From database? From yahoo finance or do u have a tool that generates random data for dispaling?
Have you tried entering the URL from his sample into your favorite browser?
http://ichart.yahoo.com/table.csv?s=F.M ... gnore=.csv

tapion
Posts: 5
Joined: Fri Jan 16, 2009 11:58 pm

Post by tapion » Wed Feb 04, 2009 2:33 am

from yahoo finance...

Code: Select all

private void readData() throws IOException, NumberFormatException, ParseException {
       URL url = new URL("http://ichart.yahoo.com/table.csv?s=F.MI&a=00&b=1&c=2003&d=01&e=2&f=2009&g=d&ignore=.csv");
       BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream())); 

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

Post by david.gilbert » Thu Feb 05, 2009 4:59 pm

These two lines would be the problem:
tapion wrote:

Code: Select all

                double x = e.getValue() *60 *60 * 1000;
                domainAxis.setRange(r1+x, r2+x);

First, you are just translating the axis range sideways, not reducing it. Second, your scrollbar will return values in the range 0 to 300, which you then multiply by the number of milliseconds in 1 hour. At best, that's going to move your plot sideways by 300 hours, which given that you have a range of 6 months, isn't going to have a big effect.

And I say "at best", because the right side of the first expression is evaluated as an 'int', so you're likely to get integer overflow. I suggest you change the '1000' to '1000L' to ensure that the expression is evaluated as a long.

These are basic logic errors rather than anything specifically to do with JFreeChart.
David Gilbert
JFreeChart Project Leader

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

tapion
Posts: 5
Joined: Fri Jan 16, 2009 11:58 pm

Post by tapion » Fri Feb 06, 2009 8:02 pm

Oh ok. So what are the correct values for jscrollbar to see for example 100 days on the chart?
Thank you.

tomi_100
Posts: 1
Joined: Thu Mar 04, 2010 9:43 am
antibot: No, of course not.

Re: Candlestick chart with scrollbar

Post by tomi_100 » Thu Mar 04, 2010 10:00 am

this code doesn't work :(
program hang ;/
can someone look at it and fix it ;)

grigori
Posts: 1
Joined: Fri Jun 25, 2010 12:48 pm
antibot: No, of course not.

Re: Candlestick chart with scrollbar

Post by grigori » Fri Jun 25, 2010 12:50 pm

Realy hangs, any solutions?

Locked