Code covered by the BSD License  

Highlights from
Technical Indicators

4.9 | 17 ratings Rate this file 81 Downloads (last 30 days) File Size: 10.8 KB File ID: #33430 Version: 1.4
image thumbnail

Technical Indicators


Nate Jensen (view profile)


25 Oct 2011 (Updated )

A single function that calculates 27 different technical indicators

| Watch this File

File Information

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

MATLAB release MATLAB 7.14 (R2012a)
Tags for This File   Please login to tag files.
Please login to add a comment or rating.
Comments and Ratings (54)
09 Apr 2015 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;

19 Mar 2015 Yona

Yona (view profile)

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.

Comment only
14 Mar 2015 Cihan Ula?

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

Comment only
18 Feb 2015 Nate Jensen

Nate Jensen (view profile)


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.

Comment only
18 Feb 2015 Vamsi

Vamsi (view profile)


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.


30 Dec 2014 Yona

Yona (view profile)

10 Dec 2014 Fernando Esteves  
11 Nov 2014 Xie Ya

Xie Ya (view profile)

18 Feb 2014 Nate Jensen

Nate Jensen (view profile)


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

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


Comment only
18 Feb 2014 Fuad

Fuad (view profile)

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,


27 Jan 2014 Nate Jensen

Nate Jensen (view profile)

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

Thanks for the rating!

Comment only
27 Jan 2014 Ray Lee

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

28 Dec 2013 Nate Jensen

Nate Jensen (view profile)


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

Comment only
27 Dec 2013 jean

jean (view profile)


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


Comment only
24 Nov 2013 Nate Jensen

Nate Jensen (view profile)


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.


Comment only
24 Nov 2013 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
23 Nov 2013 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.

Comment only
18 Sep 2013 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.

02 Sep 2013 Ruilong

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.

Comment only
26 Aug 2013 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;


Comment only
22 Aug 2013 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
22 Aug 2013 Leonardo Hermoso  
22 Aug 2013 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;

26 Jul 2013 Nate Jensen

Nate Jensen (view profile)

Hi Mark,

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


Comment only
16 Jul 2013 Mark

Mark (view profile)

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

27 May 2013 Jose

Jose (view profile)

Thank you very much.

Comment only
24 May 2013 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
24 May 2013 Nate Jensen

Nate Jensen (view profile)


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

I'm sorry about the error.


Comment only
24 May 2013 Jose

Jose (view profile)

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.

21 Mar 2013 Nate Jensen

Nate Jensen (view profile)


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!


Comment only
11 Mar 2013 Ray Lee

could u add KDJ to the next version?

19 Dec 2012 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
19 Dec 2012 lu li

lu li (view profile)

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.

13 Jun 2012 Nate Jensen

Nate Jensen (view profile)

Any time! Thanks again.

Comment only
13 Jun 2012 Arty

Arty (view profile)

Works like a charm. Thanks.

13 Jun 2012 Nate Jensen

Nate Jensen (view profile)

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!

Comment only
13 Jun 2012 Peter

Peter (view profile)

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

12 Jun 2012 Arty

Arty (view profile)

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.

Comment only
25 Mar 2012 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
08 Mar 2012 Nate Jensen

Nate Jensen (view profile)

Thanks again Mike!

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

Comment only
07 Mar 2012 Mike

Mike (view profile)

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

Comment only
05 Mar 2012 Nate Jensen

Nate Jensen (view profile)

Thanks Mike!

Yeah I could probably put that in.

Comment only
05 Mar 2012 Mike

Mike (view profile)

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

Comment only
05 Mar 2012 Mike

Mike (view profile)

04 Mar 2012 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
03 Mar 2012 Nate Jensen

Nate Jensen (view profile)

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.

Comment only
02 Mar 2012 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.


Comment only
29 Feb 2012 Nate Jensen

Nate Jensen (view profile)


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!

Comment only
29 Feb 2012 Mike

Mike (view profile)

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.

Comment only
29 Feb 2012 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?


Comment only
17 Feb 2012 Nate Jensen

Nate Jensen (view profile)


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


Comment only
17 Feb 2012 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


Comment only
08 Jan 2012 Nate Jensen

Nate Jensen (view profile)


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.


Comment only
08 Jan 2012 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 ??


Comment only
04 Mar 2012 1.1

added 2 more indicators, corrected date conversion issue

25 Mar 2012 1.2

Added the True Strength Index

21 Mar 2013 1.3

Added the KDJ Indicator

24 May 2013 1.4

Added Volatility Ratio, Highest High Lowest Low. Fixed example error. Fixed FSTO and SSTO error.

Contact us