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 stockdata.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();

Standard MACD is the 12-day Exponential Moving Average (EMA) less the 26-day EMA. Closing prices are used for these moving averages. A 9-day EMA of MACD is plotted alongside to act as a signal line to identify turns in the indicator. The MACD-Histogram represents the difference between MACD and its 9-day EMA, the signal line. The histogram is positive when MACD is above its 9-day EMA and negative when MACD is below its 9-day EMA.

As its name implies, MACD is all about the convergence and divergence of the two moving averages. Convergence occurs when the moving averages move towards each other. Divergence occurs when the moving averages move away from each other. The shorter moving average (12-day) is faster and responsible for most MACD movement. The longer moving average (26-day) is slower and less reactive to price changes in the underlying security.

MACD oscillates above and below the zero line, which is also known as the centerline. These crossovers signal that the 12-day EMA has crossed the 26-day EMA. The direction, of course, depends on direction of the moving average cross. Positive MACD indicates that the 12-day EMA is above the 26-day EMA. Positive values increase as the shorter EMA diverges further from the longer EMA. This means upside momentum is increasing. Negative MACD indicates that the 12-day EMA is below the 26-day EMA. Negative values increase as the shorter EMA diverges further below the longer EMA. This means downside momentum is increasing.

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

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

The aqua.math.financial.macd method returns both the MACD and its signal line. The difference between these two is often plotted as the MACD Histogram.

md = aqua.math.financial.macd(close,12,21,9); // calculate moving average convergence/divergence

//md[][0] = macd

//md[][1] = signal line

//md[][0] = macd

//md[][1] = signal line

Relative Strength Index (RSI) is a momentum oscillator that measures the speed and change of price movements relative to the previous price. RSI oscillates between zero and 100. Traditionally, if RSI is above 70 the stock considered as overbought and when RSI is below 30 the stock is oversold. RSI is normalized (to be between 0 and 100) Relative Strength (RS), where RS is the ratio of Average Gain to Average Loss over a period of time.

The very first calculations for average gain and average loss are simple 14 period averages.

- First Average Gain = Sum of Gains over the past 14 periods / 14.
- First Average Loss = Sum of Losses over the past 14 periods / 14
- The second, and subsequent, calculations are based on the prior averages and the current gain loss:
- Average Gain = [(previous Average Gain) x 13 + current Gain] / 14.
- Average Loss = [(previous Average Loss) x 13 + current Loss] / 14.

We can also construct RSI using Aqua Open API functions

relsi=aqua.math.financial.rsi(close,9); // calculate relative strength index over period of 9 days

if (temp>=70)

{

model.setValue(2,i,10); //if rsi over 70, set alert for overbought

model.setValue(1,i,NaN);

}

if (temp<=30)

{

model.setValue(1,i,10); //if rsi under 30, set alert for oversold

model.setValue(2,i,NaN);

}

if (temp>=70)

{

model.setValue(2,i,10); //if rsi over 70, set alert for overbought

model.setValue(1,i,NaN);

}

if (temp<=30)

{

model.setValue(1,i,10); //if rsi under 30, set alert for oversold

model.setValue(2,i,NaN);

}

The Stochastic Oscillator is a momentum indicator that, according to its inventor 'doesn't follow price, it doesn't follow volume or anything like that. It follows the speed or the momentum of price. It is also used to identify overbought and oversold levels. As a rule, the momentum changes direction before price. As such, bullish and bearish divergences in the Stochastic Oscillator can be used to foreshadow reversals.

Stochastic Oscillator %K = (Current Close - Lowest Low)/(Highest High - Lowest Low) * 100

%D = 3-day Simple Moving Average of %K

The default setting for the Stochastic Oscillator is 14 periods, which can be days, weeks, months or an intraday timeframe.

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

Stochastic Oscillator method is available in the Aqua Open API "math" package.

The stochastic oscilator method returns two quantities. %K is how near the period low a closing value of a stock is, scaled by the period's range (highest high-lowest low). %D is the exponential moving average of %K. The are three versions of this method available in aqua.math.financial: The fast, slow, and the general oscillators. They differ on the windows used for the exponential moving averages. The fast oscillator, for example, obtains %D by smoothing %K with a 3 period window. The slow smooths both %K and %D with 3 period windows. The general oscillator allows the user to assign an arbitrary window length for smoothing.

sto=aqua.math.financial.stochosc(high,low,close,15,9); // calculate %K and %D over 15 days, smoothing with a 9 day exponential moving average

On Balance Volume (OBV) measures buying and selling pressure as a cumulative indicator that adds volume on up days and subtracts volume on down days. It is a volume accumulator, adding volume if the stock closes up and subtracting if it closes down. Analysts can look for divergences between OBV and price to predict price movements or use OBV to confirm price trends. The On Balance Volume (OBV) line a running total of positive and negative volume. A period's volume is positive when the close is above the prior close. A period's volume is negative when the close is below the prior close.

If the closing price is above the prior close price then: Current OBV = Yesterday's OBV + Current Volume

If the closing price is below the prior close price then: Current OBV = Yesterday's OBV - Current Volume

If the closing prices equals yesterday's closing price then: Current OBV = Yesterday's OBV (no change)

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

On Balance Volume method is available in the Aqua Open API "math" package.

We can use the obv calculation to script a volume / obv chart that indicates whether the stock closed up or down.

onbv = aqua.math.financial.obv(close,volume); // calculate on balance volume

prc = aqua.math.financial.proc(onbv); // calculate rate of change of on balance volume (to decide color of volume histogram)

for(i=0;i<100;i++){

k=i+21

model3.addCategory(date[k]);

//obv volume chart

temp = aqua.math.signum(prc[k]); //determine direction of obv slope

if (temp>=0)

{

model3.setValue(0,i,volume[k]/1e6); //if positive, volume series to green

model3.setValue(1,i,NaN);

} else {

model3.setValue(1,i,volume[k]/1e6); //if negative, volume series to red

model3.setValue(0,i,NaN);

}

prc = aqua.math.financial.proc(onbv); // calculate rate of change of on balance volume (to decide color of volume histogram)

for(i=0;i<100;i++){

k=i+21

model3.addCategory(date[k]);

//obv volume chart

temp = aqua.math.signum(prc[k]); //determine direction of obv slope

if (temp>=0)

{

model3.setValue(0,i,volume[k]/1e6); //if positive, volume series to green

model3.setValue(1,i,NaN);

} else {

model3.setValue(1,i,volume[k]/1e6); //if negative, volume series to red

model3.setValue(0,i,NaN);

}

The previous indicators are already available in aqua.math.financial, but users can use the scripting environment to construct custom ones. We will construct the Detrended Price Oscillator.

The Detrended Price Oscillator (DPO) is an indicator designed to remove trend from price and make it easier to identify cycles. It measures the difference between a past price and a moving average. DPO does not extend to the last date because it is based on a displaced moving average. However, alignment with the most recent is not an issue because DPO is not a momentum oscillator. Instead, DPO is used to identify cycles highs/lows and estimate cycle length.

Price {X/2 + 1} periods ago less the X-period simple moving average.

X refers to the number of periods used to calculate the Detrended Price Oscillator. A 20-day DPO would use a 20-day SMA that is displaced by 11 periods {20/2 + 1 = 11}. This displacement shifts the 20-day SMA 11 days to the left, which actually puts it in the middle of the look-back period. The value of the 20-day SMA is then subtracted from the price in the middle of this look-back period. In short, DPO(20) equals price 11 days ago less the 20-day SMA.

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

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

The detrended price oscillator is the difference between the price and its 20-day exponential moving average. Since the moving average is a trend identifier, we can remove the overall trend (detrending) and study the price's movement around the trend. For this oscillator, we only need the exponential moving average.

ema20=aqua.math.financial.ema(close,20); //calculate the 20-day exponential moving average

var detrendOsc=new Array();

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

detrendOsc[i]=ema20[i]-close[i];

var detrendOsc=new Array();

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

detrendOsc[i]=ema20[i]-close[i];