Financial Modeling and Bollinger Bands
The image frame below shows the simulation of some arbitrary (random) stock-price moving average and its Bollinger Bands over discrete time periods. The user is encouraged to run this small application and experiment with varying different parameter values, that is "Number of days" and "Type" (Alpha-level), where the change is reflected instantly from the plottings. You can plot random new generated data by clicking on the button named Generate data. The class that does this simulation is called Bollinger.java; it is named after its inventor, John Bollinger. Interested Java developers who are currently involve in projects developing financial application systems should read the references below:
- BollingerBands.com
- Bollinger Bands Introduction
- Bollinger's Brainstorm
- Technical Analysis from A to Z: Bollinger Bands
There are two classes to run the Swing applications: Bollinger.java and BollingGraphics.java.The developer/user can modify the code and develop a JavaBean using Bollinger.java, the WebStart application , applet, or servlet . To get data from a stock market repository, read the data from an input stream, convert each one into double (Java data-type) and store this array as a Matrix object. This object is the input parameter to the calculate method of the Bollinger class. Write a thread to update the data from the stock market repository, say, every 2 minutes. The first element of the old data is chopped-off and a new (recent) data is added to the end of the Matrix object, thus averaging is moving along with every new data that comes in. For example:
Asset = [9,7,3,14,6,7,9,5,7,11] New Data = 10 Lop-off the first element = 9 and add 10 to the end Asset = [7,3,14,6,7,9,5,7,11,10]
Note that the Matrix object has to be reconstructed every time new data is received, if the data being read involves a large number of elements, then consider using a Link list so that data can be added and removed in a FIFO (First-In , First-Out) manner.
Richard Baldwin has excellent tutorials right here at Gamelan in data structures: Data Structures in Java: Part 1, Getting Started The Bollinger class is written to read only one-dimensional data, the user should modify it to read two-dimensional data, because the Matrix class can handle this. This is useful when tracking stock prices of, say, the top 1,000 companies every 2 minutes, that is 20,160 discrete data points a month. The amount of data to be read is 1,000 x 20,160 = 20,160,000. This is a lot of data to be processed every 2 minutes, that is why it is better to use Link List.
import Jama.Matrix; import jamlab.JElmat; import jamlab.JDatafun; import jamlab.JElfun; public class Bollinger { private Matrix movingAverage; private Matrix upperBand ; private Matrix lowerBand; public Bollinger() { } public static void main(String[] args) { Bollinger bolling = new Bollinger(); double[] d = {3,5,4,8,6,5,7,9,4,7}; Matrix asset = new Matrix(JElmat.convertTo2D(d)); int days = 3;
try{ bolling.calculate(asset, days, 2); } catch(Exception e){ e.printStackTrace(); return; } Matrix mvav = bolling.getMovingAverage(); mvav.print(4,4); Matrix uband = bolling.getUpperBand(); uband.print(4,4); Matrix lband = bolling.getLowerBand(); lband.print(4,4); } public Matrix getMovingAverage(){ return this.movingAverage; } public Matrix getUpperBand(){ return this.upperBand; } public Matrix getLowerBand(){ return this.lowerBand; } /* * Linear calculation , 'alpha' = 1 */ public void calculate(Matrix asset, int days) throws Exception{ try{ calculate(asset,days,1.0); } catch(Exception e){ throw e; } }//end method
/** * Calculation with any value of 'alpha' */ public void calculate(Matrix asset, int days, double alpha) throws Exception{ int num_row = asset.getRowDimension(); int num_col = asset.getColumnDimension(); JElmat a = new JElmat(asset.getArrayCopy()); if (num_row > 1 && num_col > 1 ){ throw new Exception("ASSET data has to be a row or column vector matrix."); } //collapse any column-vector into row-vector: a = JElmat.toRowVector(a); int r = num_row>num_col?num_row:num_col; if (days < 2 | days > r ){ throw new Exception("Moving average days should fall in the range: { 1 < days <= "+r+" }"); } // build weight vector JElmat i = JElmat.linspace(1,days,days); double sum = JDatafun.sum(JElfun.pow(i,alpha),JDatafun.COLUMN_DIMENSION).get(0,0); JElmat weight = new JElmat( JElfun.pow(i,alpha).times(1/sum).getArray()); // build moving average vectors with a for loop movingAverage = JElmat.zeros(1,r-days+1); JElmat Band = JElmat.zeros(1,r-days+1);
for(int k=days ; k< (r+1) ; k++){ JElmat asset_submatrix = new JElmat(a.getMatrix(0,0,k-days,k-1).getArray()); double sum_asset_submatrix = JDatafun.sum(new JElmat(asset_submatrix.arrayTimes(weight).getArray()) ).get(0,0); movingAverage.set(0,k-days,sum_asset_submatrix); //standard deviation of matrix 'asset_submatrix' , where data length is normalized to 'n' (false) double standardDeviation = JDatafun.std(asset_submatrix,false,JDatafun.ROW_DIMENSION).get(0,0); double two_sum_asset_submatrix = 2*JDatafun.sum(new JElmat( weight.times(standardDeviation).getArray())).get(0,0); Band.set(0,k-days,two_sum_asset_submatrix); }//end for
upperBand = new JElmat( movingAverage.plus(Band).getArray()); lowerBand = new JElmat( movingAverage.minus(Band).getArray());
}//end calculate method
}//------------------------------- End Class Definition ------------------------
Statistical Formulas Related to Moving Average
Average (Mean) : | |
Standard Deviation 1 : | |
Standard Deviation 2 : | |
Moving Average : | |
Exponential Smoothing : |
There is a difference between Standard Deviation 1 and Standard Deviation 2, as the former is normalized to n, while the later is n-1. From the Bollinger.java class definition, the red highlighted line is a call that calculates Standard Deviation 1,
double standardDeviation = JDatafun.std(asset_submatrix,false,JDatafun.ROW_DIMENSION).get(0,0);
whereas Standard Deviation 2 is computed if a "true" boolean value is passed to the std
method:
double standardDeviation = JDatafun.std(asset_submatrix,true,JDatafun.ROW_DIMENSION).get(0,0);
when the number of data-points is small; Standard Deviation 2 is used while Standard Deviation 1 is applicable to large data-point samples. In the case of the Bollinger class, use Standard Deviation 1 for short-term and Standard Deviation 2 for long-term running moving averages. Here is an explanation from Statistics literature:
Suppose we have some draws made at random with replacement from a box whose std (standard deviation) is unknown. If we knew the average of the box, the r.m.s (root-mean-square) difference between the sample numbers and the average of the box could be used to estimate the std of the box. However, we usually do not know the average of the box and must estimate that too, using the average of the draws. Now there is a little problem. The average of the draws follows the draws around: deviations from the average of the draws tend to be smaller than deviations from the average of the box. Standard Deviation 2 corrects this problem. |
A Moving Average estimator combines the advantages of the last value and average estimators in that it uses only recent history and multiple observations. This procedure places much weight on x_{ t-n+1} as on x_{ t}. Exponential Smoothing places more weight on the most recent observation than on older observations that may be less representative of current conditions.
Application
SourceTo run this sample application, you'll need the following libraries:
Jama |
Jamlab |
JSci (Java API for Science) |
There is an excellent free Java graphic toolkit called the Scientific Graphics Toolkit, which is an advanced tool if the user needs better visualization of the data. This toolkit has such functionality as time-axis (x-axis labels with days, weeks, months), which is applicable to data such as stock prices. There are also a number of commercial Java2D graphics tools for visualization available (just do a search on the Internet).
Advanced Use
- Just looking straight into a Bollinger bands graph and moving average does not tell us all about the mechanics of stock price variations, because this process is regarded in statistics as stochastic, a model process that evolves over time in a probabilistic manner. Take the question: "What was the rate of stock price change for Sun Microsystems yesterday at 4:07 PM?" This is where calculus comes to our aid. From elementary calculus, Rate is described as the ratio of "change in y over change in x". Rate is also the first derivative of a function y(x) which is y'(x). How to do this? Gather data, say, between 3:00 PM to 5:00 PM from yesterday and then run a polynomial fitting, which gives the coefficients of a specific order polynomial (Check out Polynomial Interpolation here on this Web site: Data Interpolation and Extrapolation Using Numerical Methods of Polynomial Fittings, Part 1 ). In the JDatafun class from the Jamlab package, you will find a method for first derivatives, sDiff, that can be used to derive the polynomial. Use the Polyval class to evaluate the value of y'(x), which is the Rate of the interpolated moving average exactly at 4:07 PM.
- This sample application is one of the techniques used for analysis, but there are more advanced methods that are used by economist for modeling. These techniques involve differential equations, differential calculus, probability, bayes models, and advanced statistics, etc.
- Machine Intelligence methodology is widely used for stock market analysis software. Neural Net, Case-Based-Reasoning, Expert Systems, Fuzzy Logic, Hybrid NeuroFuzzy Systems, etc. can, indeed, outperform the human stock market guru. I will revisit "Fuzzy Logic in Java" with a tutorial here on Gamelan soon.
References
There are numerous books on statistics, but the following are the ones I am currently using:
Good for Java developers with a minimum background in statistics.
- Statistics (3rd Edition), by D. Freedman, R. Pisani, and R. Purves; Norton and Company.
- Quantitative Analysis for Management (7th Edition), by B. Render and R. M. Stair; Prentice Hall.
- Probability, by J. Pitman; Springer-Verlag.
These advanced books are excellent for Java developers who are involve in Enterprise Resource Planning, Inventory Control, Traffic-flow and Control, Queuing Theory, Supply Chain Management, Decision Analysis, and Scheduling Problem software development.
- Mathematical Statistics and Data Analysis (2nd Edition), by John A. Rice; Duxbury Press.
- Modern Industrial Statistics, Design and Control of Quality and Reliability by Ron. S. Kenett and S. Zacks; Duxbury Press.
- Introduction to Operations Research (6th Edition), (Chapter 18 - Forecasting), by F.S.Hillier and G. J. Lieberman; McGraw-Hill.
- Numerical Recipes in Fortran 77, The Art of Scientific Computing (2nd Edition), (Chapter 14 - Statistics Numerical Analysis), by W.H. Press , S.A. Teukolsky, W.T. Vettering, and B.P. Flannery; Cambridge University Press.
- Probability and Random Processes (2nd Edition), by G.R. Grimmet and D.R. Stirzaker; Oxford Science Publications.
About the Author
Sione Palu has been a Java developer for over three years and has developed software in Publishing Systems, Imaging, and Web Applications. Currently developing (in Java Swing) his own software application in Symbolic and Visualization Mathematics for high school students. Palu graduated from the University of Auckland, New Zealand, double-majoring in mathematics and computer science. He has a personal interest in applying Java and mathematics in the fields of mathematical modeling and simulations, expert systems, neural and soft computation, wavelets, digital signal processing, and control systems.
This article was originally published on February 27, 2002