Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 359
  • Last Modified:

OHLCSeriesCollection

We have class which get data from two different independent sources:
1. avg[0] arrive with irregular interval and has own timestamp avg_ts[0];
2. outY[0] arrive from timer with standard interval 1 sec, but it has not time stamp, so it's timestamp is a system time.
First dataset works perfect and draw candlestick chart well.
The question is how to create second dataset with the same rules and place them into one chart plot with different Y axises because they are completely incomparable:
CC avg[0]    = 1.380455
interval: 60000
CC avg[0]    = 1.3804349999999999
interval: 60000
CC outY[0]    = -0.15570024
CC avg[0]    = 1.380445
interval: 60000
CC outY[0]    = -0.15570024
CC outY[0]    = -0.1556916
CC avg[0]    = 1.380445
interval: 60000
CC outY[0]    = -0.1556916
CC avg[0]    = 1.3804349999999999
interval: 60000
CC outY[0]    = -0.15569852

Open in new window

public class ChartCommanderEURUSD {

    List<Date> datesArrayList = new ArrayList<Date>();
    ArrayList pricesArrayList;
    long interval;
    java.util.Date dates;
    java.util.Date[] myDates;
    double[] prices;
    double[] myPrices;
    ApplicationFrame af;
    CandlestickRenderer csr;
    double open;
    double high;
    double low;
    double close;

    private static ChartCommanderEURUSD instance = new ChartCommanderEURUSD();

    public static ChartCommanderEURUSD getInstance() {
        return instance;
    }

    public ChartCommanderEURUSD() {

        datesArrayList = new ArrayList();
        pricesArrayList = new ArrayList();
        interval = 60000L;
        af = new ApplicationFrame("Chart");
        csr = new CandlestickRenderer();
    }

    public void chartEURUSD(double[] avg, java.util.Date[] avg_ts,
                            double[] outY) {

        if (avg[0] != 0) {
            System.out.println("CC avg[0]    = " + avg[0]);
            //            System.out.println("CC avg_ts[0]    = " + avg_ts[0]);

            datesArrayList.add(avg_ts[0]);
            pricesArrayList.add(new Double(avg[0]));
            java.util.Date[] myDates =
                new java.util.Date[datesArrayList.size()];
            for (int j = 0; j < myDates.length; j++) {
                myDates[j] = (java.util.Date)datesArrayList.get(j);
            }
            double[] myPrices = new double[pricesArrayList.size()];
            for (int j = 0; j < myPrices.length; j++) {
                myPrices[j] = ((Double)pricesArrayList.get(j)).doubleValue();
            }

            //            System.out.println("Dates: ");
            for (int j = 0; j < myDates.length; j++) {
                //                System.out.println(myDates[j].toString());
            }
            //            System.out.println("Prices: ");

            for (int j = 0; j < myPrices.length; j++) {
                //                System.out.println(myPrices[j]);
            }
            System.out.println("interval: " + interval);

            DefaultHighLowDataset dataset =
                OHLCData(myDates, myPrices, myDates[0], interval);


            JFreeChart chart = createChart(dataset);

            ChartPanel chartPanel = new ChartPanel(chart);

            af.setContentPane(chartPanel);
            af.setSize(700, 400);
            af.move(200, 800);

            af.setVisible(true);
            chartPanel.repaint();

            //            lineEURUSD.doEvent_avg(avg);
        }
        if (outY[0] != 0) {
            System.out.println("CC outY[0]    = " + outY[0]);

            //            lineEURUSD.doEvent_outY(outY);
        }
    }

    public DefaultHighLowDataset OHLCData(java.util.Date[] dates,
                                          double[] prices,
                                          java.util.Date startDate,
                                          long interval) {


        java.util.Date[] finalDates;
        double[] highs;
        double[] opens;
        double[] closes;
        double[] lows;
        double[] volumes;

        ArrayList anchors = new ArrayList();
        HashMap h = new HashMap();

        long start = startDate.getTime();

        for (int j = 0; j < dates.length; j++) {
            long cur = dates[j].getTime();
            long num = ((cur - start) / interval);
            Long anchor = new Long(start + num * interval + interval / 2);
            if (h.get(anchor) == null) {
                Moment mm = new Moment(dates[j], prices[j]);
                h.put(anchor, mm);
                anchors.add(anchor);
            } else {
                Moment mm = (Moment)h.get(anchor);
                mm.update(dates[j], prices[j]);
                h.put(anchor, mm);
            }

        }

        Collections.sort(anchors);

        finalDates = new java.util.Date[anchors.size()];
        opens = new double[anchors.size()];
        highs = new double[anchors.size()];
        lows = new double[anchors.size()];
        closes = new double[anchors.size()];
        volumes = new double[anchors.size()];


        for (int j = 0; j < anchors.size(); j++) {
            Long ttime = (Long)anchors.get(j);
            Moment mm = (Moment)h.get(ttime);
            finalDates[j] = new java.util.Date(ttime.longValue());
            opens[j] = mm.getOpen();
            closes[j] = mm.getClose();
            highs[j] = mm.getHigh();
            lows[j] = mm.getLow();
            volumes[j] = 0.0;

        }

        DefaultHighLowDataset dataset =
            new DefaultHighLowDataset("Series 1", finalDates, highs, lows,
                                      opens, closes, volumes);

        return dataset;
    }

    private double width;

    private JFreeChart createChart(final DefaultHighLowDataset dataset) {
        final JFreeChart chart =
            ChartFactory.createCandlestickChart("Candlestick Demo", "Time",
                                                "Price", dataset, false);
        width = 10;
        NumberAxis yaxis = (NumberAxis)chart.getXYPlot().getRangeAxis();
        yaxis.setAutoRangeIncludesZero(false);
        csr.setCandleWidth(width);
        chart.getXYPlot().setRenderer(csr);

        return chart;
    }
}

Open in new window

0
gbcbr
Asked:
gbcbr
  • 14
  • 10
3 Solutions
 
gbcbrAuthor Commented:
To create priceArrayList from outY[0] is not a problem it will be exactly similar like for avg[0],
we can't use avg_ts[0] for date ArrayList because of irregularity of it.
So, we need to create this array from system time.
0
 
for_yanCommented:
Still try to put them both - they are not that different in scale of numbers.
With time there should be no great issue - just run

java.util.Date now = new java.util.Date()
datesArrayList2.add(now);

at every moment new outY arrives and store this
date in the ArrayList
0
 
gbcbrAuthor Commented:
OK, this finished, but how now to add dataset2.
I think is reasonable to move ChartPanel parameters to the end of the method
0
VIDEO: THE CONCERTO CLOUD FOR HEALTHCARE

Modern healthcare requires a modern cloud. View this brief video to understand how the Concerto Cloud for Healthcare can help your organization.

 
gbcbrAuthor Commented:
Now it looks like this
public class ChartCommanderEURUSD {

    List<Date> datesArrayList = new ArrayList<Date>();
    ArrayList pricesArrayList;
    List<Date> datesArrayList2 = new ArrayList<Date>();
    ArrayList pricesArrayList2;
    long interval;
    java.util.Date dates;
    java.util.Date[] myDates;
    java.util.Date[] myDates2;
    java.util.Date now;
    double[] prices;
    double[] myPrices;
    double[] myPrices2;
    ApplicationFrame af;
    CandlestickRenderer csr;
    double open;
    double high;
    double low;
    double close;

    private static ChartCommanderEURUSD instance = new ChartCommanderEURUSD();

    public static ChartCommanderEURUSD getInstance() {
        return instance;
    }

    public ChartCommanderEURUSD() {

        datesArrayList = new ArrayList();
        pricesArrayList = new ArrayList();
        datesArrayList2 = new ArrayList();
        pricesArrayList2 = new ArrayList();
        now = new java.util.Date();
        interval = 60000L;
        af = new ApplicationFrame("Chart");
        csr = new CandlestickRenderer();
    }

    public void chartEURUSD(double[] avg, java.util.Date[] avg_ts,
                            double[] outY) {

        if (avg[0] != 0) {
            System.out.println("CC avg[0]    = " + avg[0]);
            //            System.out.println("CC avg_ts[0]    = " + avg_ts[0]);

            datesArrayList.add(avg_ts[0]);
            
            pricesArrayList.add(new Double(avg[0]));
            
            java.util.Date[] myDates =
                new java.util.Date[datesArrayList.size()];
            
            for (int j = 0; j < myDates.length; j++) {
                myDates[j] = (java.util.Date)datesArrayList.get(j);
            }
            
            double[] myPrices = new double[pricesArrayList.size()];
            for (int j = 0; j < myPrices.length; j++) {
                myPrices[j] = ((Double)pricesArrayList.get(j)).doubleValue();
            }

            //            System.out.println("Dates: ");
            for (int j = 0; j < myDates.length; j++) {
                //                System.out.println(myDates[j].toString());
            }
            //            System.out.println("Prices: ");

            for (int j = 0; j < myPrices.length; j++) {
                //                System.out.println(myPrices[j]);
            }
            System.out.println("interval: " + interval);

            DefaultHighLowDataset dataset =
                OHLCData(myDates, myPrices, myDates[0], interval);


            JFreeChart chart = createChart(dataset);

            //            lineEURUSD.doEvent_avg(avg);
        }
        if (outY[0] != 0) {
            System.out.println("CC outY[0]    = " + outY[0]);
            
            datesArrayList2.add(now);
            
            pricesArrayList2.add(new Double(outY[0]));
            
            java.util.Date[] myDates2 =
                new java.util.Date[datesArrayList2.size()];
            
            for (int j = 0; j < myDates2.length; j++) {
                myDates2[j] = (java.util.Date)datesArrayList2.get(j);
            }
            
            double[] myPrices2 = new double[pricesArrayList2.size()];
            for (int j = 0; j < myPrices2.length; j++) {
                myPrices2[j] = ((Double)pricesArrayList2.get(j)).doubleValue();
            }

            //            System.out.println("Dates: ");
            for (int j = 0; j < myDates2.length; j++) {
                //                System.out.println(myDates[j].toString());
            }
            //            System.out.println("Prices: ");

            for (int j = 0; j < myPrices2.length; j++) {
                //                System.out.println(myPrices[j]);
            }
            System.out.println("interval: " + interval);

            DefaultHighLowDataset dataset2 =
                OHLCData(myDates2, myPrices2, myDates2[0], interval);

            JFreeChart chart = createChart(dataset);

            ChartPanel chartPanel = new ChartPanel(chart);

            af.setContentPane(chartPanel);
            af.setSize(800, 500);
            //            af.move(200, 800);
            af.setLocation(1200, 800);
            af.setVisible(true);
            chartPanel.repaint();

            //            lineEURUSD.doEvent_outY(outY);
        }
    }

    public DefaultHighLowDataset OHLCData(java.util.Date[] dates,
                                          double[] prices,
                                          java.util.Date startDate,
                                          long interval) {
        java.util.Date[] finalDates;
        double[] highs;
        double[] opens;
        double[] closes;
        double[] lows;
        double[] volumes;

        ArrayList anchors = new ArrayList();
        HashMap h = new HashMap();

        long start = startDate.getTime();

        for (int j = 0; j < dates.length; j++) {
            long cur = dates[j].getTime();
            long num = ((cur - start) / interval);
            Long anchor = new Long(start + num * interval + interval / 2);
            if (h.get(anchor) == null) {
                Moment mm = new Moment(dates[j], prices[j]);
                h.put(anchor, mm);
                anchors.add(anchor);
            } else {
                Moment mm = (Moment)h.get(anchor);
                mm.update(dates[j], prices[j]);
                h.put(anchor, mm);
            }
        }

        Collections.sort(anchors);

        finalDates = new java.util.Date[anchors.size()];
        opens = new double[anchors.size()];
        highs = new double[anchors.size()];
        lows = new double[anchors.size()];
        closes = new double[anchors.size()];
        volumes = new double[anchors.size()];

        for (int j = 0; j < anchors.size(); j++) {
            Long ttime = (Long)anchors.get(j);
            Moment mm = (Moment)h.get(ttime);
            finalDates[j] = new java.util.Date(ttime.longValue());
            opens[j] = mm.getOpen();
            closes[j] = mm.getClose();
            highs[j] = mm.getHigh();
            lows[j] = mm.getLow();
            volumes[j] = 0.0;
        }

        DefaultHighLowDataset dataset =
            new DefaultHighLowDataset("Series 1", finalDates, highs, lows,
                                      opens, closes, volumes);
        return dataset;
    }

    private JFreeChart createChart(final DefaultHighLowDataset dataset,final DefaultHighLowDataset dataset2) {
        final JFreeChart chart =
            ChartFactory.createCandlestickChart("Candlestick Demo", "Time","Price", dataset, false);

        NumberAxis yaxis = (NumberAxis)chart.getXYPlot().getRangeAxis();
        yaxis.setAutoRangeIncludesZero(false);
      
        csr.setCandleWidth(10);
        chart.getXYPlot().setRenderer(csr);

        return chart;
    }
    
    
}

Open in new window

But I can't manage where to put
JFreeChart chart = createChart(dataset, dataset2);
0
 
for_yanCommented:
I guess you cannot create with two adatasets but you can add the soecond one
Let me see...
0
 
gbcbrAuthor Commented:
I'm already create public DefaultHighLowDataset OHLCData2( and return dataset 2, but I'm confused with chartPanel and charts creation
0
 
gbcbrAuthor Commented:
In line chart I have:
private JFreeChart createChart(XYDataset dataset) {

        JFreeChart chart =
            ChartFactory.createTimeSeriesChart("EUR/USD - 3", // title
                "Time", // x-axis label
                "inX[0]", // y-axis label
                dataset, // data
                true, // create legend?
                true, // generate tooltips?
                false) // generate URLs?
        ;
        XYPlot plot = (XYPlot)chart.getPlot();
        XYDataset dataset2 = createDataset2();
        plot.setDataset(0, dataset);
        plot.setDataset(1, dataset2);
        DateAxis axis = (DateAxis)plot.getDomainAxis();
        axis.setDateFormatOverride(new SimpleDateFormat("hh:mm:ss"));
        XYItemRenderer r = plot.getRenderer();
        XYItemRenderer renderer2 = new XYLineAndShapeRenderer();
        r.setSeriesPaint(0, Color.blue);
        r.setSeriesPaint(1, Color.red);
        renderer2.setSeriesPaint(0, Color.red);
        plot.setRenderer(1, renderer2);
        plot.setBackgroundPaint(Color.lightGray);
        plot.setDomainGridlinePaint(Color.white);
        plot.setRangeGridlinePaint(Color.white);
        plot.setAxisOffset(new RectangleInsets(1.0, 1.0, 1.0, 1.0));
        NumberAxis axis2 = new NumberAxis("outX[0]");
        axis2.setAutoRangeIncludesZero(false);
        axis2.setLabelPaint(Color.red);
        axis2.setTickLabelPaint(Color.green);
        plot.setRangeAxis(1, axis2);
        plot.setRangeAxisLocation(1, AxisLocation.BOTTOM_OR_RIGHT);
        plot.mapDatasetToRangeAxis(1, 1);

        return chart;
    }

    private XYDataset createDataset() {

        TimeSeriesCollection dataset = new TimeSeriesCollection();

        dataset.addSeries(s1);

        return dataset;
    }

    private XYDataset createDataset2() {

        TimeSeriesCollection dataset2 = new TimeSeriesCollection();

        dataset2.addSeries(s2);

        return dataset2;
    }

    public JPanel createDemoPanel() {
        JFreeChart chart = createChart(createDataset());
        ChartPanel panel = new ChartPanel(chart);
        panel.setFillZoomRectangle(true);
        panel.setMouseWheelEnabled(true);
     
        return panel;
    }
    ChartPanel chartPanel = (ChartPanel)createDemoPanel();

}

Open in new window

But there all methods separated, but here we create dataset and jpanel on one method, ok with one dataset it works perfect, but when we add second dataset everything in mess.
0
 
for_yanCommented:
Did you try to replace this method below and then
also modify the place where you call it and provide
sceond dataset as additional argument:

 private JFreeChart createChart(final DefaultHighLowDataset dataset1, final DefaultHighLowDataset dataset2) {
        final JFreeChart chart =
            ChartFactory.createCandlestickChart("Candlestick Demo", "Time",
                                                "Price", dataset1, false);
        width = 10;
   chart.setDataset(1, dataset2);
        NumberAxis yaxis = (NumberAxis)chart.getXYPlot().getRangeAxis();
        yaxis.setAutoRangeIncludesZero(false);
        csr.setCandleWidth(width);
        chart.getXYPlot().setRenderer(csr);

        return chart;
    }

Open in new window

0
 
gbcbrAuthor Commented:
I make it like this  
private JFreeChart createChart(final DefaultHighLowDataset dataset) {
        final JFreeChart chart =
            ChartFactory.createCandlestickChart("Candlestick EUR/USD", "Time","Price", dataset, false);
        XYPlot plot = (XYPlot)chart.getPlot();
        XYDataset dataset2 = OHLCData2(myDates2, myPrices2, myDates2[0], interval);
        plot.setDataset(0, dataset);
        plot.setDataset(1, dataset2);
        NumberAxis yaxis = (NumberAxis)chart.getXYPlot().getRangeAxis();
        yaxis.setAutoRangeIncludesZero(false);
      
        csr.setCandleWidth(10);
        chart.getXYPlot().setRenderer(csr);

        return chart;
    }

Open in new window

but NPE at
XYDataset dataset2 = OHLCData2(myDates2, myPrices2, myDates2[0], interval);
How I can get dataset2 from
public DefaultHighLowDataset OHLCData2(....){
...............
return dataset2
}
0
 
for_yanCommented:
No, you can't do that - you should create both datset1 and dataset2 in one place
side by side with each other then you call this createChart with two parameters - and the with one dataset you create chart
only for the sceon dataset you use setDataset method.
But creation should be outside
0
 
gbcbrAuthor Commented:
How I can set in plot.setDataset(1, dataset2); if it's here:
public void chartEURUSD(double[] avg, java.util.Date[] avg_ts,
                            double[] outY) {

        if (avg[0] != 0) {
            System.out.println("CC avg[0]    = " + avg[0]);
           ............................

            DefaultHighLowDataset dataset =
                OHLCData(myDates, myPrices, myDates[0], interval);


            JFreeChart chart = createChart(dataset);
            ChartPanel chartPanel = new ChartPanel(chart);

            af.setContentPane(chartPanel);
            af.setSize(800, 500);
            af.setLocation(1200, 800);
            af.setVisible(true);
            chartPanel.repaint();

            //            lineEURUSD.doEvent_avg(avg);
        }
        if (outY[0] != 0) {
            System.out.println("CC outY[0]    = " + outY[0]);
            
            datesArrayList2.add(now);
            
            pricesArrayList2.add(new Double(outY[0]));
            
            java.util.Date[] myDates2 =
                new java.util.Date[datesArrayList2.size()];
            
            for (int j = 0; j < myDates2.length; j++) {
                myDates2[j] = (java.util.Date)datesArrayList2.get(j);
            }
            
            double[] myPrices2 = new double[pricesArrayList2.size()];
            for (int j = 0; j < myPrices2.length; j++) {
                myPrices2[j] = ((Double)pricesArrayList2.get(j)).doubleValue();
            }

            //            System.out.println("Dates: ");
            for (int j = 0; j < myDates2.length; j++) {
                //                System.out.println(myDates[j].toString());
            }
            //            System.out.println("Prices: ");

            for (int j = 0; j < myPrices2.length; j++) {
                //                System.out.println(myPrices[j]);
            }
            System.out.println("interval: " + interval);

            DefaultHighLowDataset dataset2 =
                OHLCData2(myDates2, myPrices2, myDates2[0], interval);
.......................

    private JFreeChart createChart(final DefaultHighLowDataset dataset) {
        final JFreeChart chart =
            ChartFactory.createCandlestickChart("Candlestick EUR/USD", "Time","Price", dataset, false);
        XYPlot plot = (XYPlot)chart.getPlot();
        plot.setDataset(0, dataset);
        plot.setDataset(1, dataset2);

Open in new window

0
 
for_yanCommented:

Before this line you create both of your datasets:
  JFreeChart chart = createChart(dataset);

Then you replace

  JFreeChart chart = createChart(dataset);

with

JFreeChart chart = createChart(dataset1, dataset2);

Then you replace the method createChart itself
by the method I posted above.
(be careful grab the method I posted, not the one which you changed).


0
 
gbcbrAuthor Commented:
>> Before this line
before which line?
plot.setDataset(1, dataset2); ?
0
 
gbcbrAuthor Commented:
When I try to join them, one of datasets invisible
 
DefaultHighLowDataset dataset =
                OHLCData(myDates, myPrices, myDates[0], interval);


            JFreeChart chart = createChart(dataset, dataset2);
            ChartPanel chartPanel = new ChartPanel(chart);

            af.setContentPane(chartPanel);
            af.setSize(800, 500);
            af.setLocation(1600, 800);
            af.setVisible(true);
            chartPanel.repaint();

Open in new window

when it's inside of any 'if' operator.
When I move this ChartPanel creation out of them, at the bottom of method, both of them invisible.
I told you from very beginning that I can't find solution for this.
I don't understand how to join these two datasets in
JFreeChart chart = createChart(dataset, dataset2);
0
 
for_yanCommented:
Well, you are ambiguous.

Did you do exactly as I wrote ?- in this code I see how you create only one dataset,
did you create the second one also? Where is that line?
Did you modify the createChart - creating it with dataset1 and then setting the second
one with id = 1 ?

If you did it, then try setting the second one with id = 2 .
Do all this and write unambifguously.

With all that I'm not 100% sure, that JFreeChart would
support the chrt with two different candlesticks sets.
In my mind I don't recall ever seeing such kind of graph - it may not
be a common task. They definitely should
support line graph overlaid on top of highLowDataset -
like say moving average over stock candles,
about two different set of candles - I'm not so sure.

Waht is the source of these tasks -is it some class assignement (then they know it can be done),
is it some real business necessity (then we don't know if that can be accomplished).



With all that I am not quite sure that
0
 
gbcbrAuthor Commented:
>>Did you do exactly as I wrote ?- in this code I see how you create only one dataset,
>>did you create the second one also? Where is that line?
>>Did you modify the createChart - creating it with dataset1 and then setting the second
>>one with id = 1 ?

>>If you did it, then try setting the second one with id = 2 .
>>Do all this and write unambifguously.

I'm already post it two times
I can't make
JFreeChart chart = createChart(dataset, dataset2);

At the moment I try to make two separate chartplots, because I 'm also suppose that these candles will lay on each other and I'll net get desired result.
Better I'll locate them one above the other and compare them in this way
0
 
for_yanCommented:
Yes, that seems like a good idea; I see no reason why it should not allow to do two separate chartplots.

0
 
gbcbrAuthor Commented:
I even split this class to make everything absolutely clear and don't make changes in your code for preparation second dataset.
0
 
for_yanCommented:
Good.
0
 
gbcbrAuthor Commented:
Now I have another problem, these two charts eat whole memory
Exception in thread "AWT-EventQueue-0" java.lang.OutOfMemoryError: Java heap space

Open in new window

How to clean it?
0
 
for_yanCommented:
when you start java program start it with the command:

java -Xmx250M your_class_name your_arguments
0
 
gbcbrAuthor Commented:
I run it now from JDeveloper and I set -Xmx1024M, but it still not enough, I'll increase now up to 4096 and will see.
But it looks like garbage collector doesn't destroy unused elements.
0
 
for_yanCommented:
Well, if you really have may points coming quickly, then
we should probably think about replacing creation of the chart every time by
setting dataset. Still we need to create the datasets rather quickly - Ididn't think
you do have such huge amounts of data. Maybe you should not do 10 seconds candles.
At least in the stocks area never saw candles faster than 1 min  
0
 
gbcbrAuthor Commented:
I have 60000L, means 60 seconds, correct?
Anyway question solved, by another way, but solved.
Thank you
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

  • 14
  • 10
Tackle projects and never again get stuck behind a technical roadblock.
Join Now