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:
OnBalance 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 (2020). Technical Indicators (https://www.mathworks.com/matlabcentral/fileexchange/33430technicalindicators), MATLAB Central File Exchange. Retrieved .
1.4.0.0  Added Volatility Ratio, Highest High Lowest Low. Fixed example error. Fixed FSTO and SSTO error. 

1.3.0.0  Added the KDJ Indicator 

1.2.0.0  Added the True Strength Index 

1.1.0.0  added 2 more indicators, corrected date conversion issue 
Create scripts with code, output, and formatted text in a single executable document.
your package is awesome
but i need help for find Regular Divergence Between Price and Macd Indicator
Can u Help me for that ?
"Not enough input arguments.
Error in indicators (line 173)
observ = size(vin,1,varagin);"
how to work wth it?
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!
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 (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  (period1)):i1));
totalLoss = sum(declines((i1  (period1)):i1));
else
% Gains/Losses based on previous values
totalGain = (totalGainPrev*(period1) + advances(i1))/period;
totalLoss = (totalLossPrev*(period1) + declines(i1))/period;
end
%Calculate RSI
rs = totalGain ./ totalLoss;
trsi(i1) = 100  (100 / (1+rs));
totalGainPrev = totalGain;
totalLossPrev = totalLoss;
end
Hi,
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;
in the adx it have a mistake:
adx(2*period) = sum(dmx(period+1:2*period))/(2*periodperiod1);
it need to be an average and you divide it by N1 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.
Could you check the SAR computation. It seems it has a different result than metastock.
Vamsi,
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.
Hi,
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!
Fuad,
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/32992figurepixelresizefunction
Nate
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,
Fuad
Let me look into this Ha and see what I can do for you.
Thanks for the rating!
hi, Nate, could you please add adaptive moving average (e.g. Kaufman, fractral, Jurik) and Andrew's Pitchfork to this function?
Jean,
Could you please rephrase; I'm not sure exactly what you mean.
Hi,
Any idea how to calculate the return of these rule please?
thanks
George,
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
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.
Nate:
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.
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: 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 nonnan closing prices. Ignore first nonnan
% 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);
% Preallocating 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(i11)*(period1)+advances(i1))/period;
totalLoss(i1) = (totalLoss(i11)*(period1)+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.
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 TALib.
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;
end
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.
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
%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
Hi Mark,
Thank you for sharing your work. Your efforts are greatly appreciated and I hope that others may find your work helpful.
Nate
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++ mexable wrapper for the open source TALIB library of functions.
It is available in the repository of http://www.openAlgo.org
Nate,
Thank you very much.
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);
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.
Jose,
Thank you for pointing this issue out! I will upload a fix tonight.
I'm sorry about the error.
Nate
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.
Ha,
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
could u add KDJ to the next version?
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.
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.
Any time! Thanks again.
Works like a charm. Thanks.
Arty  If you look at line 680,
ema6 = [nan(5*period1,1); ema(ema5(~isnan(ema5)),period,observ5*period+1)];
notice that ema6 must have a minimum of '5*period1' for the size of the input vector. In your case you input a period of 20, therefore, you would need at least 5*201 (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.
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.
Thanks again Mike!
I will take at look at your code this weekend and hopefully have something put together by Sunday.
Nate,
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:end1,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(i1,1));
fastEma(i,1) = (slowEma(i,1) .* (2.0 ./ (1 + fast)) + (1  (2.0 ./ (1 + fast))) .* fastEma(i1,1));
slowAbsEma(i,1) = (abs(momentum(i,1)) .* (2.0 ./ (1 + slow)) + (1  (2.0 ./ (1 + slow))) .* slowAbsEma(i1,1));
fastAbsEma(i,1) = (slowAbsEma(i,1) .* (2.0 ./ (1 + fast)) + (1  (2.0 ./ (1 + fast))) .* fastAbsEma(i1,1));
if(fastAbsEma(i,1) == 0)
vout(i,1) = 0;
else
vout(i,1) = 100 .* fastEma(i,1) ./ fastAbsEma(i,1);
end
end
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)?
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 builtin functions could, but at the moment I can't even calculate those values correctly, much less faster than Matlab.
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.
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.
Bruno
Bruno,
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!
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. http://www.mathworks.com/help/techdoc/matlab_prog/bresuxt1.html#br67dkp1
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/4floor(year/4)) == 0) & ... % if it is a leap year
(100*(year/100floor(year/100)) ~= 0) ...
 (400*(year/400floor(year/400)) == 0) %#ok<AND2,OR2>
temp_var3 = floor((temp_var2year)*366);% number of full days in year
month = cum_days1(temp_var3); % determine month
day = temp_var3cum_days3(month); % determine day
else % if it's a normal year
temp_var3 = floor((temp_var2year)*365);% number of full days in year
month = cum_days2(temp_var3); % determine month
day = temp_var3cum_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
Krzysztof,
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 = 1k;
vout = kvin + (prev_ema * oneK);
end
Hi,
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 x1 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
Krzysztof,
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
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(1ep)],data,data(1)*(1ep));
Unfortunately they give different results. Which one is correct ??
Krzysztof