Page 1 of 1

Candlestick chart with scrollbar

Posted: Sat Jan 17, 2009 12:11 am
by tapion
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;
    }

} 

Posted: Sun Feb 01, 2009 2:10 am
by tapion
omg no answers since 15 days :shock:

<Day>

Posted: Mon Feb 02, 2009 3:21 pm
by sawo01
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

Posted: Mon Feb 02, 2009 10:46 pm
by david.gilbert
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.

Posted: Mon Feb 02, 2009 11:59 pm
by tapion
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);
	}

} 

data source

Posted: Tue Feb 03, 2009 3:10 pm
by sawo01
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?

Re: data source

Posted: Tue Feb 03, 2009 6:51 pm
by skunk
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

Posted: Wed Feb 04, 2009 2:33 am
by tapion
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())); 

Posted: Thu Feb 05, 2009 4:59 pm
by david.gilbert
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.

Posted: Fri Feb 06, 2009 8:02 pm
by tapion
Oh ok. So what are the correct values for jscrollbar to see for example 100 days on the chart?
Thank you.

Re: Candlestick chart with scrollbar

Posted: Thu Mar 04, 2010 10:00 am
by tomi_100
this code doesn't work :(
program hang ;/
can someone look at it and fix it ;)

Re: Candlestick chart with scrollbar

Posted: Fri Jun 25, 2010 12:50 pm
by grigori
Realy hangs, any solutions?