You can download project source code from: http://www.aquafold.com/download/v17.0.0/solutions/MathSolutions.zip

Updated: Jan-29-2011

A technical indicator is a series of data points that are derived by applying a formula to the price data of a security. Price data includes any combination of the open, high, low or close over a period of time. Some indicators may use only the closing prices, while others incorporate volume and open interest into their formulas. The price data is entered into the formula and a data point is produced.

Indicators that use the same scale as prices of the security are typically plotted on top of the price bars and are therefore referred to as "Overlays."

AquaOpen API has financial methods that are useful in modeling price behavior. Some financial indicators shown in this example are implemented in a single API method and can be invoked in one line of code, others require calling several API methods. The AquaScript environment available to the user can be a valuable asset in constructing custom financial tools.

In order to illustrate some of the features of aqua.math.financial, we will be using standard pricing data. Specifically, the High, Low, Close, Open, Volume, and Adjusted Close of the Dow Index daily values for 2010. Stock data for this example is taken from a stockdata2.csv file included in the project. The file in turn was created by downloading data from one of publicly available sources such as http://finance.yahoo.com/

var high= new Array();

var low= new Array();

var close= new Array();

var open= new Array();

var volume = new Array();

var date = new Array(); //csv import

var TextFile = "C:/Aqua10-0 Workspace/share/aqua-projects/Solution Examples/Math Solutions/User Files/stockdata2.csv";

var reader = aqua.io.newTextReader();

reader.setFile(TextFile);

reader.setFirstLineContainsColumnNames(true);

reader.setCellDelimiter(",");

var dataSet = aqua.data.newDataSet();

dataSet.importData(reader);

dataSet.sort("Date",true);

aqua.console.println(dataSet.getValueAt(0,1))

N=dataSet.getRowCount();

for(i=0;i<>

date[i]=dataSet.getValueAt(i,0);

open[i]=parseFloat(dataSet.getValueAt(i,1));

high[i]=parseFloat(dataSet.getValueAt(i,2));

low[i]=parseFloat(dataSet.getValueAt(i,3));

close[i]=parseFloat(dataSet.getValueAt(i,4));

volume[i]=parseFloat(dataSet.getValueAt(i,5));

}

var low= new Array();

var close= new Array();

var open= new Array();

var volume = new Array();

var date = new Array(); //csv import

var TextFile = "C:/Aqua10-0 Workspace/share/aqua-projects/Solution Examples/Math Solutions/User Files/stockdata2.csv";

var reader = aqua.io.newTextReader();

reader.setFile(TextFile);

reader.setFirstLineContainsColumnNames(true);

reader.setCellDelimiter(",");

var dataSet = aqua.data.newDataSet();

dataSet.importData(reader);

dataSet.sort("Date",true);

aqua.console.println(dataSet.getValueAt(0,1))

N=dataSet.getRowCount();

for(i=0;i<>

date[i]=dataSet.getValueAt(i,0);

open[i]=parseFloat(dataSet.getValueAt(i,1));

high[i]=parseFloat(dataSet.getValueAt(i,2));

low[i]=parseFloat(dataSet.getValueAt(i,3));

close[i]=parseFloat(dataSet.getValueAt(i,4));

volume[i]=parseFloat(dataSet.getValueAt(i,5));

}

One of the most common ways to view pricing data is via candlestick plot. This chart has two components, the body (range of open to close price) and the wick (range of high to low price) and illustrates the difference between these two ranges.

Read More: http://en.wikipedia.org/wiki/Candlestick_chart

This chart type is available in the Aqua Open API charting toolset.

chart.getProperties().setChartTypeCandleStick();

A method of smoothing a time series to reduce the effects of random variation and reveal any underlying trend. This indicator is frequently used in technical analysis showing the average value of a security's price over a set period. Moving averages are used to emphasize the direction of a trend and to smooth out price and volume fluctuations, or "noise", that can confuse interpretation. Typically, upward momentum is confirmed when a short-term average (e.g.15-day) crosses above a longer-term average (e.g. 50-day). Downward momentum is confirmed when a short-term average crosses below a long-term average. Exponential Moving Average (EMA) is similar to Moving Average but values of the selected data points are weighted by exponentially decreasing with time coefficients.

Read More: http://en.wikipedia.org/wiki/Moving_average

Moving Averages functions are available in the Aqua Open API "math" package.

movAverage9 = aqua.math.financial.movingaverage(close,9); // calculate simple moving average on closing price over period of 9 days

emovAverage9 = aqua.math.financial.ema(close,9); // calculate exponential moving average on closing price over period of 9 days

emovAverage9 = aqua.math.financial.ema(close,9); // calculate exponential moving average on closing price over period of 9 days

Moving Average Envelopes are percentage-based envelopes set above and below a moving average. The moving average, which forms the base for this indicator, can be a simple or exponential moving average. Each envelope is then set the same percentage above or below the moving average. This creates parallel bands that follow price action. With a moving average as the base, Moving Average Envelopes can be used as a trend following indicator. However, this indicator is not limited to just trend following. The envelopes can also be used to identify overbought and oversold levels when the trend is relatively flat and stock prices move beyond the envelope boundaries.

We can also construct moving average envelopes using Aqua Open API functions.

model.setValue(0,i,ma9[i]+.025*ma9[i]); //upper band

model.setValue(1,i,ma9[i]-.025*ma9[i]); //lower band

model.setValue(1,i,ma9[i]-.025*ma9[i]); //lower band

In addition to tracking general trends, we may also wish to study the variablity of pricing information. This can be done by calculating the moving standard deviation, which tells us the variability of the data over a given period. We can then overlay the pricing data with an upper and lower bound on expected variability. A special case of this is the popular Bollinger Band (2 standard deviations from moving average). Bollinger Bands are a technical analysis tool invented by John Bollinger that can be used to measure the highness or lowness of the price relative to previous trades. Bollinger Bands consist of:

- a middle band being an N-period simple moving average (MA)
- an upper band at K times an N-period standard deviation above the middle band (MA + K?)
- a lower band at K times an N-period standard deviation below the middle band (MA ? K?)

Read More: http://en.wikipedia.org/wiki/Bollinger_Bands

Moving Standard Deviation and Bollinger Bands functions are available in the Aqua Open API "math" package.

movStd9 = aqua.math.financial.movingstd(close,9); // calculate moving standard deviation of closing price over period of 9 days

bollinger9 = aqua.math.financial.bollinger(close,9); // calculate bollinger bands bounding closing price over period of 9 days

bollinger9 = aqua.math.financial.bollinger(close,9); // calculate bollinger bands bounding closing price over period of 9 days

The general case of bounding the price with moving standard deviation can be done in aquascript.

model3.setValue(0,i,ma9[i]+1*mstd9[i]); //upper band

model3.setValue(1,i,ma9[i]-1*mstd9[i]); //lower band

model3.setValue(1,i,ma9[i]-1*mstd9[i]); //lower band

The previous overlays are already available in aqua.math.financial, but users can use the scripting environment to construct custom overlays. We will build two useful overlays, Keltner Channel and IchiMoku Clouds.

Keltner Channel is a technical analysis indicator showing a central moving average line plus channel lines at a distance above and below. It is an envelope overlay that tracks variability, like Bollinger Bands. However, instead of calculating the moving standard deviation, we use the Average True Range of the price as the variability measure. The width of the Keltner bands are twice the difference between the average true range and the 20-day exponential moving average. In Keltner's description the centre line is an 10-day simple moving average of typical price, where typical price each day is the average of high, low and close. The lines above and below are drawn a distance from that centre line, a distance which is the simple moving average of the past 10 days' trading ranges (ie. range high to low on each day). The trading strategy is to regard a close above the upper line as a strong bullish signal, or a close below the lower line as strong bearish sentiment, and buy or sell with the trend accordingly, but perhaps with other indicators to confirm.

Read More: http://en.wikipedia.org/wiki/Keltner_channel

There is no Keltner Channel function in the Aqua Open API. We need to make a few calculations using available API methods to create it.

We first calculate the True Range of the price data using aqua financial methods trh (true range high) and trl (true range low).

trueHigh=aqua.math.financial.trh(high,close); //calculate true range high

trueLow=aqua.math.financial.trl(low,close); //calculate true range low

var trueRange=new Array();

for(i=0;i < trueLow.length;i++){

trueRange[i]=trueHigh[i]-trueLow[i];

trueLow=aqua.math.financial.trl(low,close); //calculate true range low

var trueRange=new Array();

for(i=0;i < trueLow.length;i++){

trueRange[i]=trueHigh[i]-trueLow[i];

Then, we find the moving average over 10 days of the true range, as well as the 20 day exppnential moving average.

averageTrueRange=aqua.math.financial.movingaverage(trueRange,10);

expMA20=aqua.math.financial.ema(close,20);

expMA20=aqua.math.financial.ema(close,20);

Finally, we find the difference between the average true range and the 20 day exponential moving average. This can be assigned in the chart via setValue.

model.setValue(7,i,ema20[k]-2*averageTrueRange[k]); //lower Keltner Line

model.setValue(8,i,ema20[k]+2*averageTrueRange[k]); //upper Keltner Line

model.setValue(8,i,ema20[k]+2*averageTrueRange[k]); //upper Keltner Line

Ichimoku clouds, or the One-Look Equilibrium Charts, are used to illustrate support and resistance levels as well as direction and strength of trends. The "cloud" is the colored region between the Senkou spans (leadingA and LeadingB). In general, the location of the pricing activity relative to the cloud is used as an indicator of bullish versus bearish market activity. Four of the five plots within the Ichimoku Cloud are based on the average of the high and low over a given period of time. For example, the first plot is simply an average of the 9-day high and 9-day low. Before computers were widely available, it would have been easier to calculate this high-low average rather than a 9-day moving average.

The Ichimoku Cloud consists of five plots:

Tenkan-sen (Conversion Line): (9-period high + 9-period low)/2)) The default setting is 9 periods and can be adjusted. On a daily chart, this line is the mid point of the 9 day high-low range, which is almost two weeks.

Kijun-sen (Base Line): (26-period high + 26-period low)/2)) The default setting is 26 periods and can be adjusted. On a daily chart, this line is the mid point of the 26 day high-low range, which is almost one month).

Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2)) This is the midpoint between the Conversion Line and the Base Line. The Leading Span A forms one of the two Cloud boundaries. It is referred to as "Leading" because it is plotted 26 periods in the future and forms the faster Cloud boundary.

Senkou Span B (Leading Span B): (52-period high + 52-period low)/2)) On the daily chart, this line is the mid point of the 52 day high-low range, which is a little less than 3 months. The default calculation setting is 52 periods, but can be adjusted. This value is plotted 26 periods in the future and forms the slower Cloud boundary.

Chikou Span (Lagging Span): Close plotted 26 days in the past The default setting is 26 periods, but can be adjusted.

Read More: http://en.wikipedia.org/wiki/Ichimoku_Kink%C5%8D_Hy%C5%8D

There is no Ichimoku Cloud function in the Aqua Open API. We need to make a few calculations using available API methods to create it.

After declaring the relevant variables,

var convline=new Array(); Tenkan-sen (Conversion Line): //(9-period high + 9-period low)/2))

var baseline=new Array(); //Kijun-sen (Base Line): (26-period high + 26-period low)/2))

var leadingA=new Array(); //Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2))

var leadingA=new Array(); //Senkou SpanB (Leading Span B): (52-period high + 52-period low)/2))

var lagging=new Array(); //Lagging Span (26 day lag of price)

var baseline=new Array(); //Kijun-sen (Base Line): (26-period high + 26-period low)/2))

var leadingA=new Array(); //Senkou Span A (Leading Span A): (Conversion Line + Base Line)/2))

var leadingA=new Array(); //Senkou SpanB (Leading Span B): (52-period high + 52-period low)/2))

var lagging=new Array(); //Lagging Span (26 day lag of price)

we calculate the 9, 26 and 52 period highs and lows for the price data.

high9=aqua.math.financial.hhigh(close,9);// 9-day high

low9=aqua.math.financial.llow(close,9);// 9-day low

high26=aqua.math.financial.hhigh(close,26); //26-day high

low26=aqua.math.financial.llow(close,26); //26-day low

high52=aqua.math.financial.hhigh(close,52); //52-day high

low52=aqua.math.financial.llow(close,52); //52-day low

low9=aqua.math.financial.llow(close,9);// 9-day low

high26=aqua.math.financial.hhigh(close,26); //26-day high

low26=aqua.math.financial.llow(close,26); //26-day low

high52=aqua.math.financial.hhigh(close,52); //52-day high

low52=aqua.math.financial.llow(close,52); //52-day low

Next we build the spans, as well as the base and conversion lines.

for(i=0;i < high9.length;i++){

convline[i]=(high9[i]+low9[i])/2;

baseline[i]=(high26[i]+low26[i])/2;

leadingA[i]=(convline[i]+baseline[i])/2;

leadingB[i]=(high52[i]+low52[i])/2;

convline[i]=(high9[i]+low9[i])/2;

baseline[i]=(high26[i]+low26[i])/2;

leadingA[i]=(convline[i]+baseline[i])/2;

leadingB[i]=(high52[i]+low52[i])/2;

Note that we can advance the leadingA and leadingB plots during the chart definition. Specifically,

model5.setValue(4,i,leadingA[k-26]);// plots the leadingA data 26 days ahead

model5.setValue(5,i,leadingB[k-26]); // plots the leadingB data 26 days ahead

model5.setValue(5,i,leadingB[k-26]); // plots the leadingB data 26 days ahead