File Exchange

image thumbnail

Technical Indicators

version (10.8 KB) by Nate Jensen
A single function that calculates 27 different technical indicators


Updated 24 May 2013

View Version History

View License

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:

Commodity Channel Index
Rate of Change
Relative Strength Index
Fast Stochastic Oscillator
Slow Stochastic Oscillator
KDJ Indicator
William's %R
True Strength Index
Simple Moving Average
Exponential Moving Average
Moving Average Convergence Divergence
Wildmer's DMI (ADX)
On-Balance Volume
Chaikin Money Flow
Force Index
Money Flow Index
Bollinger Bands
Keltner Channels
Average True Range
Volatility Ratio
Highest High, Lowest Low
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

Cite As

Nate Jensen (2021). Technical Indicators (, MATLAB Central File Exchange. Retrieved .

Comments and Ratings (62)

Sinan Islam

Lautaro Parada

liang ma


danial taheri

your 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 Chow

Hi 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 Walhout

There 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 ( 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));
% Gains/Losses based on previous values
totalGain = (totalGainPrev*(period-1) + advances(i1))/period;
totalLoss = (totalLossPrev*(period-1) + declines(i1))/period;
%Calculate RSI
rs = totalGain ./ totalLoss;
trsi(i1) = 100 - (100 / (1+rs));

totalGainPrev = totalGain;
totalLossPrev = totalLoss;

Krzysztof Fajst


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.


% True Strength Index
tsi = 100*ema2./ema4;
--> new line tsi(isnan(tsi))=100;


in 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 Ulas

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

Nate Jensen


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.



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.



Fernando Esteves

Xie Ya

Nate Jensen


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

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



Hi 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,


Nate Jensen

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

Thanks for the rating!

Ray Lee

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

Nate Jensen


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



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


Nate Jensen


You should format your code like this,

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


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.


Nate Jensen

Thanks 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 Xu


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 Leija

Nate, 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:

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;
%Calculate RS and RSI
rs = totalGain ./ totalLoss;
for i2 = period:size(trsi,1)
trsi(i2) = 100 - (100 / (1+rs(i2)));

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.


Nate - 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 Hermoso

Here 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;


Nate Jensen

No 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 Hermoso

Leonardo Hermoso

Nate, 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
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;

Nate Jensen

Hi Mark,

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



Nate - 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


Thank you very much.

Nate Jensen

The 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);
title('Fast Stochastics for Disney')

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

Nate Jensen


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

I'm sorry about the error.



I 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 Jensen


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!


Ray Lee

could u add KDJ to the next version?

Nate Jensen

Thanks 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 li

Excellent 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 Jensen

Any time! Thanks again.


Works like a charm. Thanks.

Nate Jensen

Arty - 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!


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


Hi 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 Jensen

Sorry 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 Jensen

Thanks again Mike!

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


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;
fast = varargin{1};
slow = varargin{2};

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;
vout(i,1) = 100 .* fastEma(i,1) ./ fastAbsEma(i,1);

Nate Jensen

Thanks Mike!

Yeah I could probably put that in.


Oh, 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)?


Nate Jensen

The 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 Jensen

I 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 Pajusco

I'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.


Nate Jensen


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.


Thanks for the positive feedback!


Great 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.

Bruno Pajusco

Nate, 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

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?


Nate Jensen


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);


Krzysztof Fajst


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


Nate Jensen


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.


Krzysztof Fajst

It 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 ??


MATLAB Release Compatibility
Created with R2012a
Compatible with any release
Platform Compatibility
Windows macOS Linux

Community Treasure Hunt

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

Start Hunting!