So now that I have historical data in my database, it’s time to have a good look at it. One popular way is to represent the data in a chart. Creating graphs on your own from scratch is a lot of work. Luckily, there are a lot of freely available charting API’s out there. For some of those API’s Grails plugins exist.
Google Charts
Google Charts generates an image from an URL with parameters. The Google Chart Grails plugin has a set of tags with, which you can specify what kind of chart you want. Install it
1 | grails install-plugin google-chart |
The testing procedure on the plugin information page did not work for me and it seems that the plugin does not support all the Google chart types. Other than that, everything seems to work fine.
Controller
I added two methods in the controller. The first one, gets historical end of day data sorted by date, for an instrument and a field. For instance, DIA and the high price field. The second method calls the first one for two different securities and the same field in order to compare the data in a chart. This method also produces a list of x axis labels.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | def historicalChart = { if(params.fieldVar == null) { return [instruments : getGoogleInstruments()] } else { def instrument = Instrument.findBySymbol(params.select1) def instrument2 = Instrument.findBySymbol(params.select2) def field = Field.findByName(params.fieldVar) def firstData = getDataForInstrument(instrument, field) def secondData = getDataForInstrument(instrument2, field) def data1 = [:] def data2 = [:] def xLabels = [] for(def added : firstData?.keySet()){ if( secondData?.keySet()?.contains(added)) { def shortKey = added.toString("MMM yy") if(!xLabels.contains(shortKey)) { xLabels << shortKey } data1[added] = Double.valueOf(firstData?.get(added)) data2[added] = Double.valueOf(secondData?.get(added)) } } return [instruments : getGoogleInstruments(), firstData : data1, secondData : data2, xLabels : xLabels] } } def getDataForInstrument(instrument, field) { def fieldVals = FieldValue.findAllByInstrumentAndField(instrument, field) def data = [:] for(int i = 0; i < fieldVals.size(); i++) { data[fieldVals[i].added] = fieldVals[i].val } return data.sort { it.key } } |
The view
The view for the chart consists of one GSP page. I put some logic in it, that possibly could have been better placed in the controller. The page consists roughly of two parts. The top part is a form, which lets you select two instruments and a field, such as a price to plot. The bottom part displays a line chart with a special tag.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 | <html>
<head>
<title>Chart Historical data</title>
</head>
<body>
<table>
<tr>
<g:form>
<td>
<g:select name="select1" from="${instruments.symbol}" value="${params.select1}"/>
</td>
<td>
<g:select name="select2" from="${instruments.symbol}" value="${params.select2}"/>
<td>
<td>
<g:select name="fieldVar" from="${['Open', 'High', 'Low', 'Close', 'Volume']}" value="${params.fieldVar}"/>
</td>
<td>
<g:actionSubmit name="doChart" action="historicalChart" value="Chart"/>
</td>
</g:form></td>
</tr>
</table>
<g:if test="${firstData != null}">
<%
def firstMax = firstData?.values()?.max()
def secondMax = secondData?.values()?.max()
def yMax = Math.max(firstMax, secondMax)
def priceData = [firstData?.values()?.asList(),
secondData?.values()?.asList()]
%>
<g:lineChart type="lc" title="End of day (${params.fieldVar}) comparison"
size="${[600,200]}"
colors="${['FF0000','0000FF']}"
axes="x,y"
lineStyles="${[[2,2,2],[2,8,4]]}"
legend="${[ params.select1, params.select2 ]}"
gridLines="${100.0/11},25"
axesLabels="${[0:xLabels,1:[0,yMax/2,yMax]] }"
data="${priceData}"
dataType="simple" />
</g:if>
</body>
</html> |
Result
The result of this little science project is a table of charts. I plotted DIA, a Dow Jones Industrial Average tracker, SPY, a Standard and Poors 500 tracker and GLD, a Gold Trust tracker against each other for OHLC and volume parameters. The underlying indices of the first two trackers have similarities, therefore I expect, that the trackers wil be also linked in some way. GLD was added for good measure, because as 9 out of 10 scientists will, tell you, gold is very shiny
.
Conclusion
As expected there seems to be a relation between the DIA and SPY prices. Volumes differ by orders of magnitudes, which makes it hard to see any pattern in the charts. I can not say much about GLD. Next time I will perform simple statistical analysis to quantify any possible correlation. Oh, yeah, Grails is great and plugins too.















