Latest Entries »

Wednesday, March 23, 2011

Android Candlestick Chart with Google Chart API

Good morning. Today I would like to share with other how to create CandleStick Chart with little support of Google Chart API.

Browsing around the web I hadn't found any good open source library for charting in android which directly support Candlestick Chart so I decided to use online solution based on HTTP GET/POST.

So let's start our sourvey.

First we need to take a look closer to Google Chart API. For this tutorial I will use simple basic text format to put series data inside HTTP GET request to get image I want to.
There is one thing which sadden me.
Basic text-formatted data lets you specify floating point values from 0—100, inclusive, as numbers. Values below zero are marked as missing; values above 100 are truncated to 100.

Preparing Chart Data

In most cases our data is larger than 100 and it would be stupid to have truncated all data. For this reason we need to do some scaling. Scaling will make all data suitable for requirements.
/**
     * This method transform any Double[] series to suitable series accepted by
     * Google Chart API
     */
    public static ArrayList<integer[]> transformChartSeries(ArrayList<double[]> input) {
        ArrayList<integer[]> scaledInput = new ArrayList<integer[]>();
        //Getting scale between minimum and maximum value from input series
        double scaleRatio = getScaleRatio(Min(input), Max(input));
        for (int i = 0; i &lt; input.size(); i++) {
            scaledInput.add(scale(input.get(i), scaleRatio));
            displayArray(scaledInput.get(i));
        }
        return scaledInput;
    }

    private static double Max(ArrayList<double[]> arr) {
        ArrayList<double> tmp = new ArrayList<double>();
        for (int i = 0; i &lt; arr.size(); i++) {
            tmp.add(Max(arr.get(i)));
        }
        return Collections.max(tmp);
    }

    private static double Max(Double[] input) {
        return Collections.max(Arrays.asList(input));
    }

    private static double Min(ArrayList<double[]> arr) {
        ArrayList<double> tmp = new ArrayList<double>();
        for (int i = 0; i &lt; arr.size(); i++) {
            tmp.add(Min(arr.get(i)));
        }
        return Collections.min(tmp);
    }

    private static double Min(Double[] input) {
        return Collections.min(Arrays.asList(input));
    }

    private static double getScaleRatio(double min, double max) {
        double ratio = 0;
        //Dividing value. You can manipulate this parameter to get 
        //smaller or bigger chart.
        int div = 80;
        ratio = (max - min) / div;
        return ratio;
    }
    private static Integer[] scale(Double[] input, double ratio) {
        Integer[] scaledData = new Integer[input.length];
        for (int i = 0; i &lt; input.length; i++) {
            scaledData[i] = new Integer((int) Math.round(input[i] / ratio));
        }
        return scaledData;
    }

Preparing Chart

Now when we finished data transformation we can create CandleStick Chart with Google Chart API :-) We will use cht=lc (Line Chart) as scaffolding for CandleStick Chart. Whole trick with line chart is that we will hide series data with chd:t0 parameter and next we will display CandleSticks with chm=F (CandleStick Markers). In chm=F link you have full documentation of markers.
public Intent execute(Context context) {
        Double[] _1st = CandleStickChart.generateRandomArray(seriesCount);
        Double[] _2nd = CandleStickChart.incrementArray(_1st, 1000d);
        Double[] _3rd = CandleStickChart.incrementArray(_1st, 2000d);
        Double[] _4th = CandleStickChart.incrementArray(_1st, 3000d);
        ArrayList<double[]> series = new ArrayList<double[]>();
        series.add(_1st);
        series.add(_2nd);
        series.add(_3rd);
        series.add(_4th);

        String abc = createCandleStickChart(series);
        Uri uri = Uri.parse(abc);
        Intent intent = new Intent(Intent.ACTION_VIEW, uri);
        return intent;
        // TODO Auto-generated method stub
    }

private String createCandleStickChart(ArrayList<double[]> dataSeries) {
        ArrayList<integer[]> chd = transformChartSeries(dataSeries);
        StringBuilder sbChart = new StringBuilder();
        //Four series data
        StringBuilder sb1 = new StringBuilder("-1,");
        StringBuilder sb2 = new StringBuilder("-1,");
        StringBuilder sb3 = new StringBuilder("-1,");
        StringBuilder sb4 = new StringBuilder("-1,");
        //Axis Labels
        StringBuilder axis = new StringBuilder("&amp;chl=");
        for (int i = 0; i &lt; chd.get(0).length; i++) {
            sb1.append((chd.get(0)[i]) + ",");
            sb2.append((chd.get(1)[i]) + ",");
            sb3.append((chd.get(2)[i]) + ",");
            sb4.append((chd.get(3)[i]) + ",");
            axis.append(i + "|");
        }

        sb1.append("-1|");
        sb2.append("-1|");
        sb3.append("-1|");
        sb4.append("-1");
        sbChart.append("https://chart.googleapis.com/chart?");//API URL
        sbChart.append("chs=800x200&amp;");//Chart Size
        sbChart.append("cht=lc&amp;chm=F,0000FF,0,,10&amp;");//CandleStick marker
        sbChart.append("chxt=y&amp;");//Visible axis: Left y-axis
        sbChart.append("chd=t0:");//Chart Data t0 - all series are hidden
        String chdd = sbChart.toString() + sb1.toString() + sb2.toString() + sb3.toString() + sb4.toString() + axis.toString();
        System.out.println(chdd);
     
     return chdd;
 }

Final result

Code above use Intent.ACTION_VIEW to open WebActivity for display generated image from Google Chart API

Source Code

You can download Charting Demo application from
here

1 comments:

Unknown said...

Great post..Candlestick is a concept we could all learn a little more about. The Law of Charts is a trading concept that identifies the human actions & reactions underlying the real market & enables to consistently identify. watch here

Post a Comment