Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
612 views
in Technique[技术] by (71.8m points)

java - jfreechart crashes when using Yahoo Finance Quotes


QUESTION RESOLVED: solution is changing to JFreeChart v1.0.15


I have a very peculiar problem.

What I have set up is a file that sends a url request to the Yahoo Finance website and then uses the results to draw a JFreeChart in a JFrame.

What I just can't get my head around is the following:

For certain url requests, the JFrame crashes

It starts, but only shows a white screen. Whereas for other requests, my program works fine.

Example

For example:

This request:

"http://ichart.yahoo.com/table.csv?s=GOOG&a=0&b=1&c=2011&d=6&e=24&f=2013&g=d&ignore=.csv";

works fine.

But this request:

"http://ichart.yahoo.com/table.csv?s=GOOG&a=2&b=1&c=2012&d=6&e=24&f=2013&g=d&ignore=.csv";

causes an error.

How is this possible?

Note

I know the following:

  • JFrame crashes but JVM doesn't make note of it (doesn't notice that it crashes)
  • Downloading of the stock quotes (the information that JFreeChart uses) goes perfect in both cases
  • The code for downloading the data and displaying it in the JFreeChart comes from this site (the code posted by RoyW ? Sat May 10, 2008 7:52 am).
  • The amount of data coming in doesn't seem a problem because in request 1, there are more data points than in request 2
  • The way I download the data doesn't matter (I tried both reading directly from the url and I tried saving the .csv file to a folder and then reading from the folder)
  • The problem doesn't occur randomly: I've tried launching the JFrame (recompiling the code and then running it) multiple times but the 'wrong' quote crashes the JFrame everytime.

Extra information

Something that might have to do with it:

  • When I launch the graph with a correct quote and I drag the graph around, something weird happens. At a certain interval, it seems every weekend, the candlesticks get smaller and smaller untill they are only a stripe. Then when I drag across the weekend, they become thicker again until they are normal size again. This seems to happen for every weekend. Refer to the following pictures:

enter image description here enter image description here enter image description here

So it got me thinking that it might have something to do with trading days. But this doesn't make any sense either because 1/1/2011 (request 1) falls on a Saturday and 3/1/2012 (request 2) falls on a Thursday while request 1 was successful and request 2 failed.

I am absolutely clueless as to what I should do.

All help greatly appreciated.

Update

On request, here is the SSCCE with trashgod's suggestions (using JFreechart lib v1.0.14).

    import org.jfree.chart.*;
    import org.jfree.chart.axis.*;
    import org.jfree.chart.plot.XYPlot;
    import org.jfree.chart.renderer.xy.CandlestickRenderer;
    import org.jfree.data.xy.*;

    import javax.swing.*;
    import java.awt.*;
    import java.io.*;
    import java.net.URL;
    import java.text.*;
    import java.util.*;
    import java.util.List;

    public class CandlestickDemo2 extends JFrame {
        public CandlestickDemo2(String stockSymbol) {
            super("CandlestickDemo");
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

            DateAxis    domainAxis       = new DateAxis("Date");
            NumberAxis  rangeAxis        = new NumberAxis("Price");
            CandlestickRenderer renderer = new CandlestickRenderer();
            XYDataset   dataset          = getDataSet(stockSymbol);

            XYPlot mainPlot = new XYPlot(dataset, domainAxis, rangeAxis, renderer);

            //Do some setting up, see the API Doc
            renderer.setSeriesPaint(0, Color.BLACK);
            renderer.setDrawVolume(false);
            rangeAxis.setAutoRangeIncludesZero(false);
            domainAxis.setTimeline( SegmentedTimeline.newMondayThroughFridayTimeline() );

            //Now create the chart and chart panel
            JFreeChart chart = new JFreeChart(stockSymbol, null, mainPlot, false);
            ChartPanel chartPanel = new ChartPanel(chart, false);
            chartPanel.setPreferredSize(new Dimension(600, 300));

            this.add(chartPanel);
            this.pack();
        }
        protected AbstractXYDataset getDataSet(String stockSymbol) {
            //This is the dataset we are going to create
            DefaultOHLCDataset result = null;
            //This is the data needed for the dataset
            OHLCDataItem[] data;

            //This is where we go get the data, replace with your own data source
            data = getData(stockSymbol);

            //Create a dataset, an Open, High, Low, Close dataset
            result = new DefaultOHLCDataset(stockSymbol, data);

            return result;
        }
        //This method uses yahoo finance to get the OHLC data
        protected OHLCDataItem[] getData(String stockSymbol) {
            List<OHLCDataItem> dataItems = new ArrayList<OHLCDataItem>();
            try {
                String strUrl= "http://ichart.finance.yahoo.com/table.csv?s=GOOG&a=2&b=1&c=2012&d=6&e=24&f=2013&g=d&ignore=.csv";
                URL url = new URL(strUrl);
                BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()));
                DateFormat df = new SimpleDateFormat("y-M-d");

                String inputLine;
                in.readLine();
                while ((inputLine = in.readLine()) != null) {
                    StringTokenizer st = new StringTokenizer(inputLine, ",");

                    Date date       = df.parse( st.nextToken() );
                    double open     = Double.parseDouble( st.nextToken() );
                    double high     = Double.parseDouble( st.nextToken() );
                    double low      = Double.parseDouble( st.nextToken() );
                    double close    = Double.parseDouble( st.nextToken() );
                    double volume   = Double.parseDouble( st.nextToken() );
                    double adjClose = Double.parseDouble( st.nextToken() );

                    OHLCDataItem item = new OHLCDataItem(date, open, high, low, close, volume);
                    dataItems.add(item);
                }
                in.close();
            }
            catch (Exception e) {
                e.printStackTrace();
            }
            //Data from Yahoo is from newest to oldest. Reverse so it is oldest to newest
            Collections.reverse(dataItems);

            //Convert the list into an array
            OHLCDataItem[] data = dataItems.toArray(new OHLCDataItem[dataItems.size()]);

            return data;
        }

        public static void main(String[] args) {
            EventQueue.invokeLater(new Runnable() {
                @Override
                public void run() {
                    new CandlestickDemo2("GOOG").setVisible(true);
                }
            });
        }
    }

This generates a JFrame that displays nothing but a white screen. Try changing the strUrl to

 "http://ichart.finance.yahoo.com/table.csv?s=GOOG&a=0&b=1&c=2011&d=6&e=24&f=2013&g=d&ignore=.csv";

and you will notice that it works fine.

Update

Solved it! The problem was the JFreeChart version. Changing from v1.0.14 to v1.0.15 solved everything. Kudos to trashgod for (unknowingly) solving my issue by answering extensively and mentioning the library version used.

Does anybody know how I can help others that are having the same issue? Is there a portal somewhere where I can make note of this bug?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

CandlestickDemo works for me with v1.0.15 and either of your queries. I made two changes:

  • Construct the GUI on the event dispatch thread; failure to do so causes a data race with non-deterministic results:

    EventQueue.invokeLater(new Runnable() {
        @Override
        public void run() {
            new CandlestickDemo("GOOG").setVisible(true);
        }
    });
    
  • Omit the backing buffer, although it's probably irrelevant:

    ChartPanel chartPanel = new ChartPanel(chart, false);
    
  • Addendum: For reference, it looks like a call to ParamChecks.nullNotPermitted() was applied in r2692, replacing an explicit check, but the renderer was otherwise unchanged.

  • Addendum: Under v1.0.14, the example works correctly with the DefaultTimeline of DateAxis, which changed substantially in the interim.

  • Addendum: @David Gilbert notes that the relevant changes may be found in r2465.

image


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...