version 1.4.0.0 (10.8 KB) by
Nate Jensen

A single function that calculates 27 different technical indicators

INDICATORS is a technical analysis tool that calculates various technical indicators. Technical analysis is the forecasting of future financial price movements based on an examination of past price movements. Most technical indicators require at least 1 variable argument. If these arguments are not supplied, default values are used.

The included indicators are:

Momentum:

Commodity Channel Index

Rate of Change

Relative Strength Index

Fast Stochastic Oscillator

Slow Stochastic Oscillator

KDJ Indicator

William's %R

Aroon

True Strength Index

Trend:

Simple Moving Average

Exponential Moving Average

Moving Average Convergence Divergence

Wildmer's DMI (ADX)

T3

Volume:

On-Balance Volume

Chaikin Money Flow

Force Index

Money Flow Index

Volatility:

Bollinger Bands

Keltner Channels

Average True Range

Volatility Ratio

Highest High, Lowest Low

Other:

ZigZag

Price Comparison

Pivot Points

Stop and Reverse

Version : 1.1.3 (05/24/2013)

Author : Nate Jensen

Created : 10/10/2011

History :

- v1.0 10/25/2011 : initial release of 21 indicators

- v1.1 03/04/2012 : 23 indicators, fixed date conversion issue

- v1.1.1 03/25/2012 : 24 indicators

- v1.1.2 03/21/2013 : 25 indicators

- v1.1.3 05/24/2013 : 27 indicators, bug fixes

Nate Jensen (2021). Technical Indicators (https://www.mathworks.com/matlabcentral/fileexchange/33430-technical-indicators), MATLAB Central File Exchange. Retrieved .

Created with
R2012a

Compatible with any release

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!Create scripts with code, output, and formatted text in a single executable document.

Sinan IslamLautaro Paradaliang maZhengdanial taheriyour package is awesome

but i need help for find Regular Divergence Between Price and Macd Indicator

Can u Help me for that ?

nirav pandya"Not enough input arguments.

Error in indicators (line 173)

observ = size(vin,1,varagin);"

how to work wth it?

Tsz Shing ChowHi guys, I have found some problems when I was using the codes.

When I try to run the code in Matlab, it showed this

"Not enough input arguments.

Error in indicators (line 173)

observ = size(vin,1,varagin);"

What should I do to correct this problem? Thanks!

Caspar WalhoutThere is a bug in your calculation for the RSI (similar as in the default Matlab function which you appear to have used as a basis for this one).

The RSI should be based on the previous value of the RSI, not just on the prices of a stock (http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi). To solve the issue, the for loop should be replaced by:

for i1 = period:size(diffdata, 1)

if i1 == period

% Gains/losses

totalGain = sum(advances((i1 - (period-1)):i1));

totalLoss = sum(declines((i1 - (period-1)):i1));

else

% Gains/Losses based on previous values

totalGain = (totalGainPrev*(period-1) + advances(i1))/period;

totalLoss = (totalLossPrev*(period-1) + declines(i1))/period;

end

%Calculate RSI

rs = totalGain ./ totalLoss;

trsi(i1) = 100 - (100 / (1+rs));

totalGainPrev = totalGain;

totalLossPrev = totalLoss;

end

Krzysztof FajstHi,

I believe there is a small bug in tsi

subprogram i.e. some 1st words can be NaNs. So I added this line to remove it.

Krzysztof

% True Strength Index

tsi = 100*ema2./ema4;

--> new line tsi(isnan(tsi))=100;

Yonain the adx it have a mistake:

adx(2*period) = sum(dmx(period+1:2*period))/(2*period-period-1);

it need to be an average and you divide it by N-1 and not by N. so you can change to mean or remove the -1 in the end.

NOTE: some site calculate the adx witch ema and not witch smooth ma.

Cihan UlasCould you check the SAR computation. It seems it has a different result than metastock.

Nate JensenVamsi,

Thank you!

That is correct, the function is suitable for (1) stock at a time. I will look into this and see what I can come up with, no guarantees.

For the moment you can get around this issue by using a for loop. I know, not the fastest solution, but it works.

VamsiHi,

Thanks for putting up all the efforts for these indicators and look forward to more!

Just had a query regarding the indicators. If I read the functions correctly - they are suitable for only one column or one stock?

What would be a great functionality to be added would be to input an entire column oriented matrix of lets say all S&P 500 stocks.

Let me know what your thoughts are.

Cheers!

YonaFernando EstevesXie YaNate JensenFuad,

No problem. I'm glad my code has worked out for you.

I do. Please see my other submission to the exchange located here:

http://www.mathworks.com/matlabcentral/fileexchange/32992-figure-pixel-resize-function

Nate

FuadHi Nate, thanks for sharing.

Do you have any code for the charts you display in the preview image? Would be great to plot indicators at the bottom of my chart like you do...

Many thanks,

Fuad

Nate JensenLet me look into this Ha and see what I can do for you.

Thanks for the rating!

Ray Leehi, Nate, could you please add adaptive moving average (e.g. Kaufman, fractral, Jurik) and Andrew's Pitchfork to this function?

Nate JensenJean,

Could you please rephrase; I'm not sure exactly what you mean.

jeanHi,

Any idea how to calculate the return of these rule please?

thanks

Nate JensenGeorge,

You should format your code like this,

vout = indicators([hi,lo,cl],'kdj',k,d)

where,

vout = output vector

hi = high prices

lo = low prices

cl = closing prices

k = number of periods for %K

d = number of periods for %D

In order to extract fpctk, fpctd, and jline, please use the following code:

fpctk = vout(:,1);

fpctd = vout(:,2);

jline = vout(:,3);

Please note:

1. All inputs must be vertically oriented

2. All outputs are returned vertically oriented

3. This code is intended to be used for hundreds or thousands of points of data. Normally you cannot use any of these functions for 1 single point. This function will require at least 1 more point of data for each of the hi, lo, and cl inputs than the maximum of the k or d inputs.

HTH,

Nate

Nate JensenThanks for the feedback Alejandro! I'm glad everything is working out for you.

At the moment I do not have access to Matlab in order to make this change but as soon as I do, I will add in your suggestion.

George XuNate:

How to use the code on KDJ? Please,

Say, I have tick data(tick[30000]) and like to has KDJ(9,2,3). Thanks,

I did try, but get error.

______________________________

>> [fpctk,fpctd,jline] = indicators([2500,2490,2495],'kdj',9,2);

??? Error using ==> indicators

Too many output arguments.

Alejandro LeijaNate, I want to thank you a lot for sharing your code because it works great and saved me a lot of time.

I've been working with some of these indicators and found differences between your RSI calculation and another very popular version (used in platforms like MT4), where the second and subsequent totalGain/totalLoss values depend on their previous values providing a smoother result -similar to what is done in exponential moving averages. Here you find a detailed explanation: http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:relative_strength_index_rsi

The following modification over your code provides the smoothed RSI:

% Calculate the RSI of the non-nan closing prices. Ignore first non-nan

% vin b/c it is a reference point. Take into account any leading nans

% that may exist in vin vector.

trsi = nan(size(diffdata, 1)-numLeadNans, 1);

% Pre-allocating totalGain and totalLoss using 'trsi' size as reference.

totalGain = zeros(size(trsi,1),1);

totalLoss = zeros(size(trsi,1),1);

% First values are different than others

totalGain(period) = sum(advances(1:period))/period;

totalLoss(period) = sum(declines(1:period))/period;

% Subsequent totalGain/Loss values

for i1 = period+1:size(trsi, 1)

totalGain(i1) = (totalGain(i1-1)*(period-1)+advances(i1))/period;

totalLoss(i1) = (totalLoss(i1-1)*(period-1)+declines(i1))/period;

end

%Calculate RS and RSI

rs = totalGain ./ totalLoss;

for i2 = period:size(trsi,1)

trsi(i2) = 100 - (100 / (1+rs(i2)));

end

An improvement could be a "method option" in the formula to choose one of both versions of RSI; one method with your original RSI version and a second one with the smoothed RSI version.

RuilongNate - I wanted to thank you for your sharing of your collection of trading based technical indicators.

But the results of indicators(price,'t3',period,volfact) are different from what you can get by using the same function in TA-Lib.

Leonardo HermosoHere goes another one i use

function [ velocidade ] = velocidade( price,pipSize,period )

%This indicator calculates price velocity. I developed this based on

%pyshics formula velocity v = v0 +at

%pipsize is for forex or data that the variation is small like 0.001

%points, in this case you should use 0.001 as pipsize.

velocidade= (((2 .* (price - [zeros(period,1);price(1:size(price,1)-period,:)])) / period.^2)./pipSize).*period;

end

Nate JensenNo problem Leonardo. I'm glad you have been able to put my code to good use and thank you for sharing for your hard work.

Leonardo HermosoLeonardo HermosoNate, tks a lot for this.

I use another indicator here that is fibonacci bands, i user your work to develop this indicador in matlab, and here is the code.

Tks again

function [upperband1,upperband2,upperband3,upperband4,lowerband1,lowerband2,lowerband3,lowerband4 ] = fibo(high,low,close,periodsEma,periodsAtr)

%This will calculate the fibonacciBands using the Atr (True Average

%Range).

%indicator

ema = indicators(close,'ema',periodsEma);

atr = indicators([high,low,close],'atr',periodsAtr);

upperband1 = ema + atr.*1.62;

upperband2 = ema + atr.*2.62;

upperband3 = ema + atr.*4.62;

upperband4 = ema + atr;

lowerband1 = ema - atr.*1.62;

lowerband2 = ema - atr.*2.62;

lowerband3 = ema - atr.*4.62;

lowerband4 = ema - atr;

end

Nate JensenHi Mark,

Thank you for sharing your work. Your efforts are greatly appreciated and I hope that others may find your work helpful.

Nate

MarkNate - I wanted to thank you for your sharing of your collection of trading based technical indicators.

I wanted to share similar work with you and your followers in the hopes that some may find it complimentary and useful. As it isn't a file submission direct to Mathworks I really can't create my own thread.

I have created a C++ mex-able wrapper for the open source TA-LIB library of functions.

It is available in the repository of http://www.openAlgo.org

JoseNate,

Thank you very much.

Nate JensenThe issues have been fixed and the update should appear shortly. I have also added 2 more indicators.

The example should have read:

load disney.mat

vout = indicators([dis_HIGH,dis_LOW,dis_CLOSE],'fsto',14,3);

fpctk = vout(:,1);

fpctd = vout(:,2);

plot(1:length(fpctk),fpctk,'b',1:length(fpctd),fpctd,'g')

title('Fast Stochastics for Disney')

There was also an error in the FSTO and SSTO functions.

Nate JensenJose,

Thank you for pointing this issue out! I will upload a fix tonight.

I'm sorry about the error.

Nate

JoseI do not understand what is happening. I'm using your example!!!

load disney.mat

[fpctk,fpctd] = indicators([dis_HIGH,dis_LOW,dis_CLOSE],'fsto',14,3)

Error using indicators

Too many output arguments.

Nate JensenHa,

I have just added the KDJ Indicator as requested. It should appear shortly depending on how long Matlab takes to approve my submission.

This indicator was a little confusing. I'm not sure exactly which method is correct so I input 3 different methods. Simply uncomment whichever method you wish to use.

Method # 1:

J = 3*FastK - 2*FastD;

Method # 2:

J = ema(K,period);

Method # 3:

J = 3*SlowK - 2*SlowD;

Hope that helps!

Nate

Ray Leecould u add KDJ to the next version?

Nate JensenThanks Lu Li!

I'll try my hand at the mex function, but unfortunately I don't have a whole lot of experience with them so no guarantees.

I do agree with you, this function is slow as an optimizer. I suggest pulling out the individual indicators that you are interested in and turn them into their own functions. Then try to optimize those, that way you aren't bogged down by the 'Switch' statement.

lu liExcellent work!

I want to use it in an optimization, but it is kind of slow.

It would be wonderful if it can be into mex funtcion so the it will be much faster.

Nate JensenAny time! Thanks again.

ArtyWorks like a charm. Thanks.

Nate JensenArty - If you look at line 680,

ema6 = [nan(5*period-1,1); ema(ema5(~isnan(ema5)),period,observ-5*period+1)];

notice that ema6 must have a minimum of '5*period-1' for the size of the input vector. In your case you input a period of 20, therefore, you would need at least 5*20-1 (or 99) for size of your input vector. Either increase the size of your input vector, or decrease the period.

Thanks for the compliment!

Peter - Yeah there are many calculations like that in my code where you could use one method or another to calculate ema or use sma over ema. It is really a matter of opinion. Thank you for the rating!

PeterNoticed the stochastics delay is calculated using EMA, my TA program calculates it using SMA so there was a slight discrepancy.

ArtyHi Nate, I tried the t3 indicator and got an error message:

>> t3 = indicators(A, 't3', 20, 0.7);

??? Error using ==> plus

Matrix dimensions must agree.

Error in ==> indicators at 689

t3 = c1*ema6+c2*ema5+c3*ema4+c4*ema3;

Do you know what the problem is? I'm knew to Matlab so having a hard time trying to decipher the code. SMA's and other stuff work fine. Cheers for the hard work.

Nate JensenSorry for the delay, but I have finally added the True Strength Index. Work has been crazy busy and this unfortunately was moved down on the priority list.

I would like to point out that I have included 2 methods for calculating the ema in the tsi. The first method is very similar to Mike's, and is based off of Wikipedia's interpretation of the ema. The second method is based off of Matlab's interpretation of the ema. To choose one or the other, simply comment whichever method you do not wish to use. The default method is based off of Wikipedia.

Nate JensenThanks again Mike!

I will take at look at your code this weekend and hopefully have something put together by Sunday.

MikeNate,

I had some time so I coded the True Strength Index (TSI). Probably not the most efficient code, and I don't know if it handles the NaN's properly, but basically it works with your program. I quickly checked the output and it looks right. Here it is:

% tsi - True Strength Index

% tsi = indicators(cl ,'tsi' ,fast,slow)

case 'tsi' % True Strength Index

% Input Data

close = vin(:,1);

% Variable Argument Input

if isempty(varargin)

fast = 3;

slow = 14;

else

fast = varargin{1};

slow = varargin{2};

end

momentum = [0; (close(2:end,1)) - close(1:end-1,1)];

slowEma = 0;

fastAbsEma = 0;

fastEma = 0;

slowAbsEma = 0;

vout = 0;

for i = uint16([2:size(momentum,1)])

slowEma(i,1) = (momentum(i,1) .* (2.0 ./ (1 + slow)) + (1 - (2.0 ./ (1 + slow))) .* slowEma(i-1,1));

fastEma(i,1) = (slowEma(i,1) .* (2.0 ./ (1 + fast)) + (1 - (2.0 ./ (1 + fast))) .* fastEma(i-1,1));

slowAbsEma(i,1) = (abs(momentum(i,1)) .* (2.0 ./ (1 + slow)) + (1 - (2.0 ./ (1 + slow))) .* slowAbsEma(i-1,1));

fastAbsEma(i,1) = (slowAbsEma(i,1) .* (2.0 ./ (1 + fast)) + (1 - (2.0 ./ (1 + fast))) .* fastAbsEma(i-1,1));

if(fastAbsEma(i,1) == 0)

vout(i,1) = 0;

else

vout(i,1) = 100 .* fastEma(i,1) ./ fastAbsEma(i,1);

end

end

Nate JensenThanks Mike!

Yeah I could probably put that in.

MikeOh, I see you added these:

mfi - Money Flow Index

atr - Average True Range

excellent! Thank you.

Any plans to code the True Strength Index (TSI)?

MikeNate JensenThe problem is fixed, and the new file should appear shortly.

I decided to use Matlab's datvecmx function to calculate the year, month, and day rather than try to figure it out on my own. I originally thought that I could write a script to calculate dates faster than Matlab's built-in functions could, but at the moment I can't even calculate those values correctly, much less faster than Matlab.

Nate JensenI forgot about this problem. The problem arises because I don't evaluate leap years correctly. I'll try to fix it in the next day or two.

Bruno PajuscoI've first got the error by running the function using S&P exchange prices on the last 4000 observations. I have also tried with smaller subsets of other market data and even used my fake market data constructed from random variables but the error was still there. You could try to run it with your own data as I suspect you will get that same error but if you want me to send you the actual values for dates, open, high, low, close prices I would need your email address.

Bruno

Nate JensenBruno,

Could you give me an example of how you are getting this error? You could email me your input that triggers the error, and I will see if I can reproduce it.

Mike,

Thanks for the positive feedback!

MikeGreat code, easy to use, and Very well documented! Thank you! Saved me a lot of time by not having to code this from scratch.

Note: When running this on Matlab version 2008 or older, the tilde (~) output argument is not supported. Simply change this to a dummy value (such as "val"), and the error will go away. Search for "~" and change lines: 407, 408, 802, 811, 858, 867. http://www.mathworks.com/help/techdoc/matlab_prog/bresuxt-1.html#br67dkp-1

Bruno PajuscoNate, I have come across a problem with the file while trying to estimate pivot points. The problem seems to be related to the code where you work out years, months and days from Matlab serial dates. In particular I had issues with the following block of code:

% Convert Matlab time to years, months, and days

temp_var1 = floor(date); % number of full days

temp_var2 = temp_var1/365.242199; % number of years

year = floor(temp_var2); % number of full years

if (4*(year/4-floor(year/4)) == 0) & ... % if it is a leap year

(100*(year/100-floor(year/100)) ~= 0) ...

| (400*(year/400-floor(year/400)) == 0) %#ok<AND2,OR2>

temp_var3 = floor((temp_var2-year)*366);% number of full days in year

month = cum_days1(temp_var3); % determine month

day = temp_var3-cum_days3(month); % determine day

else % if it's a normal year

temp_var3 = floor((temp_var2-year)*365);% number of full days in year

month = cum_days2(temp_var3); % determine month

day = temp_var3-cum_days4(month); % determine day

end

The code throws the following exception when constructing the variable month:

"Subscript indices must either be real positive integers or logicals.

Error in indicators (line 967)

month = cum_days2(temp_var3); % determine month"

I'm not sure why this is the case but when I construct similar variable to temp_var3 cum_days2 and then run that block of code it seems a lot happier than when I run the function. Any ideas?

Bruno

Nate JensenKrzysztof,

I suggest you simply write a new ema code that includes the previous ema value and you should be set. The following should do what you want,

function vout = ema(vin,prev_ema)

k = 2/(lag+1);

kvin = vin * k;

oneK = 1-k;

vout = kvin + (prev_ema * oneK);

end

Krzysztof FajstHi,

I made some more investigation and I think tsmovavg based solution has a major drawback i.e. will not work for real time application. Lets assume you have 10k bars and you calculate ema on it. Than a new bar comes and calculate again 10k would be very time costly - much easier to calculate just last bar.

But in this case this code will not work because instead of use x-1 data

for initial value (so last data point of 1st calculation of ema) it will use some average values.

in other words it means that ema calculated on 10k+1 bars in one pass will have different value than ema calculated on last bar and it should not be a case.

Filter solution seems to be ok

Krzysztof

Nate JensenKrzysztof,

The method that I used is the method that Matlab uses to calculate the ema in their own moving average function 'tsmovavg'. This is not to say that that method is correct, but that is why I used it.

I briefly compared it to Google's ema on their finance page and the results were the same.

I would suggest to stick with what I have.

Nate

Krzysztof FajstIt looks that there are at least 2 versions of code for EMA around i.e.

EMA calculated with algorithm from this function and EMA calculated with this code

% convert the period to an exponential percentage

ep = 2/(period+1);

% calculate the EMA

out = filter(ep,[1-(1-ep)],data,data(1)*(1-ep));

Unfortunately they give different results. Which one is correct ??

Krzysztof