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
4.4 High-performance Multi-threading
1.0 Introduction
All public functions of the libraries are documented here.
You must first install TA-Lib, which will provide all the shared/static libraries and headers needed to compile with your program.
2.0 How to build and link to TA-Lib
In your source code, add #include "ta_libc.h" and link to the library named "ta-lib".
You may need to add TA-Lib to your compiler's search path. For example, with gcc, you can use the following options:
The paths depend on the method used to install. Typical locations for headers are:
- /usr/local/include/ta-lib
- /usr/include/ta-lib
- /opt/include/ta-lib
Typical locations for the libraries are:
- /usr/lib
- /usr/lib64
- /usr/local/lib
- /usr/local/lib64
- /opt/lib
- /opt/local/lib
For homebrew, use brew --prefix ta-lib to find the paths.
For windows, look into C:\Program Files\TA-Lib for 64-bits and C:\Program Files (x86)\TA-Lib for 32-bits.
3.0 Technical Analysis Functions
Make sure TA_Initialize was called once (and only once) prior to any other API functions.
All TA functions can be directly called.
Alternatively, an app can call all TA functions using the abstraction layer. This is useful to make dynamic call without knowing at priori the function name or parameters. Example of use is to automatically integrate new functions after upgrading TA-Lib, or for "mutating" calls while strategy searching (e.g. genetic/neural network algo).
3.1 Direct call to a TA Function
Direct calls could be done through the API defined in
include/ta_func.h
All functions are simple "array processing" functions. You provides the inputs with an array, and the the output is written in a caller provided output array.
The number of data written 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[] )
All TA functions use the same calling pattern, divided in 4 groups:
- The output will be calculated only for the range specified by startIdx to endIdx. These are zero base index into the input arrays.
- One or more input arrays are then specified. Typically, these are going to be the "price" data. In that example there is only one input. All inputs parameter name starts with "in".
- Zero or more optional inputs may need to be specified. In that example there are 2 optional inputs. These parameters allow more control specific to the function. If you do not care about a particular optIn just specify TA_INTEGER_DEFAULT or TA_REAL_DEFAULT (depending on the type).
- One or more output arrays are finally specified. In that example there is only one output (outReal). The params outBegIdx and outNbElement are always specified once before the output arrays.
This calling pattern provides control on calculating ONLY the portion of data needed for your app. It is slightly complex, but it enables speed/memory optimizations.
Example calculating a 30 days simple moving average (SMA) of daily closing prices:
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] );
After the call, it is important to check the value returned by 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, outBeg will be 29 (zero base) and outNbElement will be 400-29 = 371. In other words, only the first 371 elements of out[] are valid, and these could be calculated only starting at the 30th element of the input array.
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 buffers. This capability is true for all TA functions.
3.2 Output Size
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 works consistently for all TA functions:
Method | Description |
---|---|
Input Matching | allocationSize = endIdx + 1; Pros: Easy to understand and implement. Cons: Memory allocation unnecessarily large when specifying small range. |
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. Cons: Slightly more complex. |
A function TA_XXXX_Lookback is provided for each TA function. Example: For TA_SMA, there is a TA_SMA_Lookback.
The lookback 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.
4.0 Advanced Features
4.1 Abstraction Layer
All the TA Function can be called using the interface defined in ta_abstract.h
The abstraction layer is particularly useful for an application who wishes to support the complete list of TA functions without having to maintain new code each time a new function is added to TA-Lib. If you wish to simply integrate in your application a small number of specific functions, then you may be better to do simpler direct call (see previous section).
Use Case 1:
The app is 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 API will tell your app which parameters are needed and the
valid range for each). Once all parameters are set, you can dynamically call the corresponding TA function. The output can then be drawn on the chart using some hint (from TA-Lib) about data representation (overlap study, independent indicator with its own scale etc...).
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...).
Use Case 2:
Your app is searching for "best strategies" using your own backtesting platform. You might want to automate trying various mix of "volatility" and moving average crossings using a genetic algorith, You can make your app "mutate" and switch function and parameters using the abstract interface.
Use Case 3:
You can generate any "glue code" or "wrapper" for a high-level language (e.g. Python, R, Java, C#) or for simply interfacing with your app. A lot of derived work are now "maintained" automatically using the abstract layer.
4.2 Unstable Period
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.
4.3 Input Type: float vs. double
Each TA function have two implementation. One accepts input arrays of float and the other accepts 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[] );
Internally both version do all the calculation using double e.g. when an element of a float array is accessed, it is changed to double. Consequently, both function will produce the same output
Some apps have their price bar data already loaded as float. The TA_S_XXXX functions allows to digest these directly (no copy needed) while still maintaining all intermediate calculation as double.
4.4 High-performance multi-threading
TA-Lib is multi-thread safe where it matters the most for performance: When calling any TA functions (e.g. TA_SMA, TA_RSI etc... )
One important caveat is the initialization of the "global settings" must first be done from a single thread. That includes calls to:
- TA_Initialize
- TA_SetUnstablePeriod, TA_SetCompatibility
- TA_SetCandleSettings, TA_RestoreCandleDefaultSettings
After you are done with these initial calls, the application can start performing multi-thread calls with the rest of the API (including the ta_abstract.h API).
One exception to the rule is TA_Shutdown() which must be called single threaded (typically from the only thread remaining prior to exit your application).
Note: TA-Lib assumes it is link to a thread safe malloc/free runtime library, which is the default on all modern platforms (Linux,Windows,Mac). In other word, safe with any compiler supporting C11 or more recent.