Thursday, September 8, 2011

Simple Charts in GWT using Google Charts API

I recently started to muck around with Google Charts API to generate financial charts. My aim is to be able to generate a price chart annotated with news and company announcement information, something like this (click to see it clear):


What I have got so far is a timeline chart in a GWT application. This simple application will chart the price information of a few stocks provided in a CSV file.

The code is here, and can be checked out using this command:
svn co http://tinywebgears-samples.googlecode.com/svn/trunk/simplecharts simplecharts
It is an Eclipse project you can use easily if you too use Eclipse.

The class responsible to generate this chart looks like this:

// ...

// Entry point class
public class SimpleCharts implements EntryPoint
{
// ...

// Entry point method
@Override
public void onModuleLoad()
{
// ...

// Load the visualization API, passing the onLoadCallback to be called when loading is done.
VisualizationUtils.loadVisualizationApi(onLoadCallback, AnnotatedTimeLine.PACKAGE);

// ...
}

// ...

private void makeChartDialog(Map<Date, Map<String, Double>> rawData)
{
AnnotatedTimeLine timeLine = new AnnotatedTimeLine(createDataTable(rawData), createOptions(), "600px", "400px");

chartDialogBox.setAnimationEnabled(true);

VerticalPanel vp = new VerticalPanel();
vp.addStyleName("dialogVPanel");

VerticalPanel vinp = new VerticalPanel();
vinp.addStyleName("dialogVInnerPanel");

vinp.add(timeLine);

vp.setHorizontalAlignment(VerticalPanel.ALIGN_LEFT);
vp.add(vinp);
vp.setHorizontalAlignment(VerticalPanel.ALIGN_RIGHT);
vp.add(closeButton);

chartDialogBox.setWidget(vp);

// Add a handler to close the DialogBox
closeButton.addClickHandler(new ClickHandler()
{
public void onClick(ClickEvent event)
{
chartDialogBox.hide();
}
});
}

private void paintChart(String stockCodeList)
{
String[] stockCodes = StringHelper.separateCodes(stockCodeList);
ausequitiesService.getPriceInfo(stockCodes, new AsyncCallback<Map<Date, Map<String, Double>>>()
{
public void onFailure(Throwable caught)
{
makeErrorMessageDialog(SERVER_ERROR);
errorDialogBox.center();
chartButton.setEnabled(true);
closeButton.setFocus(true);
}

public void onSuccess(Map<Date, Map<String, Double>> result)
{
makeChartDialog(result);
chartDialogBox.center();
chartButton.setEnabled(true);
closeButton.setFocus(true);
}
});
}

private Options createOptions()
{
AnnotatedTimeLine.Options options = AnnotatedTimeLine.Options.create();
options.setDisplayAnnotations(true);
options.setDisplayZoomButtons(true);
options.setScaleType(AnnotatedTimeLine.ScaleType.ALLFIXED);
options.setLegendPosition(AnnotatedTimeLine.AnnotatedLegendPosition.SAME_ROW);
return options;
}

private DataTable createDataTable(Map<Date, Map<String, Double>> rawData)
{
DataTable data = DataTable.create();
data.addColumn(AbstractDataTable.ColumnType.DATE, "Date");
if (rawData.isEmpty())
return data;
for (Entry<Date, Map<String, Double>> entry : rawData.entrySet())
{
for (String code : entry.getValue().keySet())
data.addColumn(AbstractDataTable.ColumnType.NUMBER, code);
break;
}
Integer counter = 0;
for (Entry<Date, Map<String, Double>> entry : rawData.entrySet())
{
data.addRows(1);
data.setValue(counter, 0, entry.getKey());
Integer index = 1;
for (Double price : entry.getValue().values())
{
if (price != null)
data.setValue(counter, index, price);
index++;
}
counter++;
}
return data;
}
}

I have removed less related lines for the sake of brevity, but you can see the complete file following the link mentioned above.

You can see the deployed version of application here on App Engine. It will be updated as I make changes to the code in the future.

Here is what I have been to plot so far: