C/C++ API Documentation
2.0 How to build and link to TA-Lib
3.0 Technical Analysis Functions
4.1 Abstraction layer
4.2 Unstable Period
4.3 Input Type: float vs. double
2.0 How to build and link to TA-Lib
3.0 Technical Analysis Functions
4.1 Abstraction layer
4.2 Unstable Period
4.3 Input Type: float vs. double
All functions available to the end-user are documented here.
To use the library in C/C++ project, you just need to #include "ta_libc.h" and link to the static library corresponding to your type of application.
All the required header file are in ta-lib/c/include. Header files in other directories should never be included by your application directly.
Here is the list of variant of the static library currently supported:
Static Library Name | Use runtime DLL? | Multithreaded? | Debug info? |
---|---|---|---|
ta_libc_csr.lib | - | - | - |
ta_libc_csd.lib | - | - | Yes |
ta_libc_cmr.lib | - | Yes | - |
ta_libc_cmd.lib | - | Yes | Yes |
ta_libc_cdr.lib | Yes | Yes | - |
ta_libc_cdd.lib | Yes | Yes | Yes |
Pre-compiled
version of these libraries is part of the MSVC package. If you wish to
re-build yourself the static libraries, makefiles can be found in ta-lib/c/make/<ENV>/win32/msvc.
These MSVC makefiles also works with Visual Studio 2005.
The <ENV> is a 3 letter sub-directories (cmd, cmr, csd, csr, cdd
and cdr)
allowing to select the "standard library runtime" setting for your
application).
Just type "nmake" or "nmake /A" to build all targets.
The generated targets will be found in ta-lib/c/lib and ta-lib/c/bin.
To rebuild from scratch do "nmake clean" and then "nmake" again.
The application without debug info are the speed optimized version. They cannot be trace for debugging though.
Visual Studio 2005 project files can be found in
ta-lib/c/ide/vs2005
If you observe
link errors on Windows, verify that the "Use runtime library" setting in the
C/C++ Code generation tab is the same as your choice of static libraries.
Link errors will show up if your application does not links with wininet and odbc32. These are provided with MSVC and Borland and should be found on your system.
The SVN repository and the Win32 packages contains multiple makefiles generated for multiple platforms, including Linux. The makefiles are found in ta-lib/c/make/<ENV>/linux/g++.
The <ENV> is a 3 letter sub-directories (cmd,cmr,csd,csr) allowing to select an environment of development applicable to your application (see section 2.1). The cdd and cdr type does not apply to Linux.
Just type "make clean" and "make" to build all targets. The generated target will be found in ta-lib/c/lib and ta-lib/c/bin.
You will need to link to 3 static libraries: ta-abstract, ta-func and ta-common
Download the source code tar.gz package and perform the following as root:
./configure
./make
./make install
TA-Lib is contained in a single shared library called "libta-lib" (name will vary depending of your platform). With gcc you link using the switch "-lta-lib".
When building the complete source tree, an application called "ta_regtest" is created in the ta-lib/c/bin directory. This is a suite of tests to validate that the library you did compiled is behaving as expected within your environment.
Whenever you re-compile the TA-Lib libraries, it is suggested to re-run ta_regtest. An internet connection is required since web data fetching is one feature being tested.
Make sure TA_Initialize was called once (and only once) prior to any other API functions.
The individual TA function can be directly called. User who would like to integrate the TA functions without prior knowledge of their parameters, should consider the abstraction layer interface.
The source code of all the TA functions is in ta-lib/c/src/ta_func.
Direct call could be done through the interface defined in ta-lib/c/include/ta_func.h
All the TA functions are simple mathematical function. You provides the inputs with an array, and the function simply store the output in a caller provided output array. The TA functions are NOT allocating any space for the caller. The number of data in the output will NEVER exceed the number of elements requested to be calculated (with the startIdx and endIdx explained below).
Here is an example:
We will dissect the TA_MA function allowing to calculate a simple moving average.
TA_RetCode TA_MA(
int startIdx,
int endIdx,
const double inReal[],
int
optInTimePeriod,
int
optInMAType,
int
*outBegIdx,
int *outNbElement,
double outReal[],
)
At first it appears that there is a lot of parameters, but do not be discourage, all functions are consistent and share the same parameter structure. The parameters are provided in 4 sections:
The output will be calculated only for the range specified by startIdx to endIdx.
One or more data inputs are then specified. In that example there is only one input. All inputs parameter name starts with "in".
zero or more optional inputs are specified here. In that example there is 2 optional inputs. These parameters allows to fine tune the function. If you do not care about a particular optIn just specify TA_INTEGER_DEFAULT or TA_REAL_DEFAULT (depending of the type).
One or more output are finally specified. In that example there is only one output which is outReal (the parameters outBegIdx and outNbElement are always specified once before the list of outputs).
This structure of parameters gives a lot of flexibility to make the function calculate ONLY the portion of required data. It is slightly complex, but it allows demanding user to manage efficiently the memory and the CPU processing.
Lets say you wish to calculate a 30 day moving average using closing prices. The function call could look as follow:
TA_Real closePrice[400]; TA_Real out[400]; TA_Integer outBeg; TA_Integer outNbElement;
/* ... initialize your closing price here... */
retCode = TA_MA( 0, 399, &closePrice[0], 30,TA_MAType_SMA, &outBeg, &outNbElement, &out[0] );
/* The output is displayed here */ for( i=0; i < outNbElement; i++ ) printf( "Day %d = %f\n", outBeg+i, out[i] );
One important aspect of the output are the outBeg and outNbElement. Even if it was requested to calculate for the whole range (from 0 to 399), the moving average is not valid until the 30th day. Consequently, the outBeg will be 29 (zero base) and the outNbElement will be 400-29 = 371. Meaning only the first 371 elements of out are valid, and these could be calculated only starting at the 30th element of the input.
As an alternative example, if you would have requested to calculate only in the "125 to 225" range (with startIdx and endIdx), the outBeg will be 125 and outNbElement will be 100. (the "30" minimum required is not an issue because we dispose of 125 closing price before the start of the requested range...). As you may have already understand, the "out" array will be written only for its first 100 elements. The rest will be left untouched.
Here is another example. In that case we want to calculate a 14 bars exponential moving average only for 1 price bar in particular (say the last day of 300 price bar):
TA_Real closePrice[300]; TA_Real out; TA_Integer outBeg; TA_Integer outNbElement;
/* ... initialize your closing price here... */
retCode = TA_MA( 299, 299, &closePrice[0], 14, TA_MAType_EMA, &outBeg, &outNbElement, &out );
In that example: outBeg will be 299, outNbElement will be 1, and only one value gets written into out.
In the case that you do not provide enough data to even being able to calculate at least one value, outNbElement will be 0 and outBeg shall be ignored.
If the input and output of a TA function are of the same type, the caller can re-use the input buffer for storing one of the output of the TA function. The following example will work:
#define BUFFER_SIZE 100 TA_Real buffer[BUFFER_SIZE]; ... retCode = TA_MA( 0, BUFFER_SIZE-1, &buffer[0], 30, TA_MAType_SMA, &outBeg, &outNbElement, &buffer[0] );
Of course, the input is overwritten, but this capability diminish needs for temporary memory allocation for certain application. You can assume this capability is true for all TA functions.
It is important that the output array is large enough. Depending of your needs, you might find one of the following method useful to determine the output allocation size. All these methods are consistent and works with all TA functions:
Method | Description |
---|---|
Input Matching | allocationSize = endIdx + 1;
Pros: Easy to understand and implement. |
Range Matching | allocationSize = endIdx - startIdx + 1; Pros: Easy to implement. Cons: Allocation slightly larger than needed. Example: for a 30 period SMA, you will get 29 elements wasted because of the lookback. |
Exact Allocation | lookback = TA_XXXX_Lookback( ... ) ; temp = max( lookback, startIdx ); if( temp > endIdx ) allocationSize = 0; // No output else allocationSize = endIdx - temp + 1;
Pros: Optimal allocation algorithm. |
A function TA_XXXX_Lookback is provided for each TA function. Example: For TA_SMA, there is a TA_SMA_Lookback.
The lookback function indicates how many inputs are consume before the first output can be calculated. Example: A simple moving average (SMA) of period 10 will have a lookback of 9.
All the TA Function can be called using the interface defined in ta-lib/c/include/ta_abstract.h
The abstraction layer is particularly interesting for an application who wishes to support the complete list of TA functions without having
to re-write new code each time a new function is added to the TA-LIB. If you wish to simply integrate in your application a small number of specific
function, you may be better to simply call these directly (see previous section).
Example:
Lets say you are doing a charting software. When the user select a price bar, a side list offers blindly all the TA functions
that could be applied to a price bar. The user selects one of these, then a dialog open for allowing to adjust
the optional parameters (TA-LIB will tell your software which parameter are needed and the
valid value range for each). Once all the parameter are set, you can call blindly the
corresponding TA function. The returned information can then also blindly be drawn on the chart (some
output flags allows to get some hint on how the data shall be drawn). The same "abstract" logic apply to all the TA functions.
Some TA Functions works only on volume, or can work indifferently with any time series
data (the open, close, another indicator...) All the applicable functions to the currently selected/available
data can be determined through this "virtual" interface.
The abstraction layer is a complex, but powerful interface.
Some TA functions provides different results depending of the "starting point" of the data being involve. This is often referred as a function having memories. An example of such function is the Exponential Moving Average. It is possible to control the unstable period (the amount of data to strip off) with TA_SetUnstablePeriod and TA_GetUnstablePeriod.
For each technical analysis algorithm, there is one version of the function accepting the input as array of float and another accepting array of double. The float version has a "TA_S_" suffix e.g. for TA_MA there is an equivalent TA_S_MA function.
TA_RetCode TA_MA( int startIdx,
int endIdx,
const double inReal[],
int optInTimePeriod,
TA_MAType optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[] );
TA_RetCode TA_S_MA( int startIdx,
int endIdx,
const float inReal[],
int optInTimePeriod,
TA_MAType optInMAType,
int *outBegIdx,
int *outNbElement,
double outReal[] );
Both version do all the calculation using double e.g. when an element of a float array is accessed, it is changed to double-precision. Consequently, both function will yield the same result.
It is typical that users have their price bar data as float and maintain all their intermediate calculation as double. Having direct support for both type in TA-Lib is more memory efficient. With only one type, the user would be potentially forced to duplicate their input data in a new array of a different type prior to a TA function call.