【问题标题】:JFreeChart : How to draw the moving average over a OHLC chartJFreeChart:如何在 OHLC 图表上绘制移动平均线
【发布时间】:2012-07-04 13:46:58
【问题描述】:

我试图在 OHLC 图表上叠加一条移动平均线,但它似乎不起作用。

我提供了两个关键功能的代码:

private static OHLCDataset createPriceDataset(String filename)
{   
    OHLCSeries s1 = new OHLCSeries(filename);

    try {
        BufferedReader in = new BufferedReader(new FileReader(filename));
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        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() );
            s1.add(new Day(date), open, high, low, close);
        }
        in.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }

    OHLCSeriesCollection dataset = new OHLCSeriesCollection();
    dataset.addSeries(s1);

    return dataset;
}



private static JFreeChart createCombinedChart()
{
    OHLCDataset data1 = createPriceDataset(filename);

    XYItemRenderer renderer1 = new HighLowRenderer();
    renderer1.setBaseToolTipGenerator(new StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT, new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0.00")));
    renderer1.setSeriesPaint(0, Color.blue);
    DateAxis domainAxis = new DateAxis("Date");
    NumberAxis rangeAxis = new NumberAxis("Price");
    rangeAxis.setNumberFormatOverride(new DecimalFormat("$0.00"));
    rangeAxis.setAutoRange(true);
    rangeAxis.setAutoRangeIncludesZero(false);
    XYPlot plot1 = new XYPlot(data1, domainAxis, rangeAxis, renderer1);
    plot1.setBackgroundPaint(Color.lightGray);
    plot1.setDomainGridlinePaint(Color.white);
    plot1.setRangeGridlinePaint(Color.white);
    plot1.setRangePannable(true);

    //Overlay the Long-Term Trend Indicator
    XYDataset dataset3 = MovingAverage.createMovingAverage(data1, "LT", 49.0, 49.0);
    plot1.setDataset(1, dataset3);
    plot1.setRenderer(1, new StandardXYItemRenderer());

    //add a second dataset (volume) and renderer
    IntervalXYDataset data2 = createVolumeDataset(filename);
    XYBarRenderer renderer2 = new XYBarRenderer();
    renderer2.setDrawBarOutline(false);
    renderer2.setBaseToolTipGenerator(new StandardXYToolTipGenerator(StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT, new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0,000.00")));
    renderer2.setSeriesPaint(0, Color.red);

    XYPlot plot2 = new XYPlot(data2, null, new NumberAxis("Volume"), renderer2);
    plot2.setBackgroundPaint(Color.lightGray);
    plot2.setDomainGridlinePaint(Color.white);
    plot2.setRangeGridlinePaint(Color.white);

    CombinedDomainXYPlot cplot = new CombinedDomainXYPlot(domainAxis);
    cplot.add(plot1, 3);
    cplot.add(plot2, 2);
    cplot.setGap(8.0);
    cplot.setDomainGridlinePaint(Color.white);
    cplot.setDomainGridlinesVisible(true);
    cplot.setDomainPannable(true);


    //return the new combined chart
    JFreeChart chart = new JFreeChart("Sun Microsystems (SUNW)", JFreeChart.DEFAULT_TITLE_FONT, cplot, false);

    ChartUtilities.applyCurrentTheme(chart);
    renderer2.setShadowVisible(false);
    renderer2.setBarPainter(new StandardXYBarPainter());

    return chart;
}

有什么想法吗?

谢谢。

【问题讨论】:

  • 我可以理解,它可以使用包含像 Def​​aultHighLowDataset 这样的卷的数据类实例来完成(正如我从示例中看到的那样),但我想知道它是否可以使用 OHLCSeriesCollection 来完成,因为要计算移动平均线你不需要数量。它只是基于价格的计算。

标签: jfreechart


【解决方案1】:

我添加了以下代码,它似乎可以工作。 如果有人不同意这个解决方案,请告诉我。 就是这样:

public class PriceVolumeChart2 extends ApplicationFrame{

final static String filename = "A.txt";
*static TimeSeries t1 = new TimeSeries("49-day moving average");*

/**
 * Default constructor
 */
public PriceVolumeChart2(String title)
{
    super(title);
    JPanel panel = createDemoPanel();
    panel.setPreferredSize(new Dimension(500, 270));
    setContentPane(panel);
}

//create price dataset
//hard-coded here
private static OHLCDataset createPriceDataset(String filename)
{
    //the following data is taken from http://finance.yahoo.com/
    //for demo purposes...

    OHLCSeries s1 = new OHLCSeries(filename);

    try {
        BufferedReader in = new BufferedReader(new FileReader(filename));
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        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() );
            s1.add(new Day(date), open, high, low, close);
            *t1.add(new Day(date), close);*
        }
        in.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }



    OHLCSeriesCollection dataset = new OHLCSeriesCollection();
    dataset.addSeries(s1);

    return dataset;
}


//create volume dataset
private static IntervalXYDataset createVolumeDataset(String filename)
{
    //create dataset 2...
    TimeSeries s1 = new TimeSeries("Volume");

    try {
        BufferedReader in = new BufferedReader(new FileReader(filename));
        DateFormat df = new SimpleDateFormat("yyyyMMdd");
        String inputLine;
        in.readLine();
        while ((inputLine = in.readLine()) != null) {
            StringTokenizer st = new StringTokenizer(inputLine, ",");
            Date date = df.parse( st.nextToken() );
            st.nextToken();
            st.nextToken();
            st.nextToken();
            st.nextToken();
            double volume   = Double.parseDouble( st.nextToken() );
            //double adjClose = Double.parseDouble( st.nextToken() );
            s1.add(new Day(date), volume);
        }
        in.close();
    }
    catch (Exception e) {
        e.printStackTrace();
    }

    return new TimeSeriesCollection(s1);
}

private static JFreeChart createCombinedChart()
{
    OHLCDataset data1 = createPriceDataset(filename);

    XYItemRenderer renderer1 = new HighLowRenderer();
    renderer1.setBaseToolTipGenerator(new StandardXYToolTipGenerator(
        StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
        new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0.00")));
    renderer1.setSeriesPaint(0, Color.blue);
    DateAxis domainAxis = new DateAxis("Date");
    NumberAxis rangeAxis = new NumberAxis("Price");
    rangeAxis.setNumberFormatOverride(new DecimalFormat("$0.00"));
    rangeAxis.setAutoRange(true);
    rangeAxis.setAutoRangeIncludesZero(false);
    XYPlot plot1 = new XYPlot(data1, domainAxis, rangeAxis, renderer1);
    plot1.setBackgroundPaint(Color.lightGray);
    plot1.setDomainGridlinePaint(Color.white);
    plot1.setRangeGridlinePaint(Color.white);
    plot1.setRangePannable(true);

    //Overlay the Long-Term Trend Indicator
    *TimeSeries dataset3 = MovingAverage.createMovingAverage(t1, "LT", 49, 49);
    TimeSeriesCollection collection = new TimeSeriesCollection();
    collection.addSeries(dataset3);
    plot1.setDataset(1, collection);*
    plot1.setRenderer(1, new StandardXYItemRenderer());

    //add a second dataset (volume) and renderer
    IntervalXYDataset data2 = createVolumeDataset(filename);
    XYBarRenderer renderer2 = new XYBarRenderer();
    renderer2.setDrawBarOutline(false);
    renderer2.setBaseToolTipGenerator(new StandardXYToolTipGenerator(
        StandardXYToolTipGenerator.DEFAULT_TOOL_TIP_FORMAT,
        new SimpleDateFormat("d-MMM-yyyy"), new DecimalFormat("0,000.00")));
    renderer2.setSeriesPaint(0, Color.red);

    XYPlot plot2 = new XYPlot(data2, null, new NumberAxis("Volume"), renderer2);
    plot2.setBackgroundPaint(Color.lightGray);
    plot2.setDomainGridlinePaint(Color.white);
    plot2.setRangeGridlinePaint(Color.white);

    CombinedDomainXYPlot cplot = new CombinedDomainXYPlot(domainAxis);
    cplot.add(plot1, 3);
    cplot.add(plot2, 2);
    cplot.setGap(8.0);
    cplot.setDomainGridlinePaint(Color.white);
    cplot.setDomainGridlinesVisible(true);
    cplot.setDomainPannable(true);


    //return the new combined chart
    JFreeChart chart = new JFreeChart("Sun Microsystems (SUNW)",
        JFreeChart.DEFAULT_TITLE_FONT, cplot, false);

    ChartUtilities.applyCurrentTheme(chart);
    renderer2.setShadowVisible(false);
    renderer2.setBarPainter(new StandardXYBarPainter());

    return chart;
}

//create a panel
public static JPanel createDemoPanel()
{
    JFreeChart chart = createCombinedChart();
    return new ChartPanel(chart);
}

public static void main(String[] args) {
    // TODO code application logic here
    PriceVolumeChart2 demo = new PriceVolumeChart2(
        "JFreeChart: CombinedXYPlotDemo1.java (base)");
    demo.pack();
    RefineryUtilities.centerFrameOnScreen(demo);
    demo.setVisible(true);
}

//Download data from web
}

样本数据:

20110103,41.56,42.14,41.41,41.88,3572300 20110104,41.99,42.1,41.18,41.49,3588800 20110105,41.28,41.73,41,41.4,3232700 20110106,41.37,41.84,41.21,41.48,3361400 20110107,41.52,41.8,41.04,41.62,2725900 20110110,41.41,42.72,41.3,42.22,3145800 20110111,42.52,43.31,42.38,42.94,3315400 20110112,43.2,43.41,42.96,43.13,2463100 20110113,42.88,43.23,42.87,42.97,1676400 20110114,42.79,43.37,42.76,43.26,2215600 20110117,43.26,43.26,43.26,43.26,0 20110118,43.33,44.45,43.32,44.35,2982300 20110119,44.16,44.29,42.27,42.43,4537200 20110120,41.95,42.58,41.46,42.29,4874700 20110121,42.5,43.26,42.03,42.11,3004500 20110124,42.18,42.79,42.07,42.77,2067400 20110125,42.77,43.52,42.28,42.69,3132700 20110126,42.82,42.97,42.04,42.57,3927300 20110127,42.77,43.09,42.37,42.45,3189600 20110128,42.5,42.52,40.88,40.98,3629800 20110131,41.21,41.83,40.89,41.83,3690900 20110201,42.07,42.7,41.93,42.05,3388200 20110202,41.75,41.91,40.82,41.23,3970700 20110203,40.93,41.18,40.23,40.99,3522700 20110204,41.19,43.13,40.94,42.99,5197700 20110207,43.45,44.66,43.37,44.44,4569800 20110208,44.65,44.71,43.83,44.17,3734500 20110209,44.01,44.17,43.16,43.43,3779300 20110210,43.22,44.01,42.57,44,3275700 20110211,43.77,45.15,43.65,45.02,4436000 20110214,45,45.42,44.72,44.79,3484400 20110215,44.79,45,42.64,42.65,7328000 20110216,42.91,43.6,42.7,43.57,4159800 20110217,43.38,44,43.02,43.92,2621800 20110218,43.78,44.29,43.65,43.92,4390200 20110221,43.92,43.92,43.92,43.92,0 20110222,43.21,43.75,42.39,42.49,4143600 20110223,42.59,42.75,39.94,40.45,7074200 20110224,40.34,41.55,40.18,41.15,4455700 20110225,41.16,42.41,41.13,42.36,4297500 20110228,42.43,42.65,41.36,42.08,3070200 20110301,41.98,42.49,40.65,40.68,4091300

新代码在星号内。

如果您认为有更优雅的解决方案,请告诉我。

【讨论】:

  • 示例中的任何数据?
  • 为了完整起见,您可能希望在答案中添加一个小子集。
  • 我不确定你的意思。你能解释一下吗?thnx。
猜你喜欢
  • 2017-12-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多