Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:
workflow_dispatch:

env:
TALIB_C_VER: 0.7.1
TALIB_C_VER: 0.8.1
PIP_NO_VERIFY: 0
PIP_VERBOSE: 1
CIBW_BEFORE_BUILD: pip install -U setuptools Cython wheel meson-python ninja && pip install -U numpy
Expand Down
31 changes: 31 additions & 0 deletions CHANGELOG
Original file line number Diff line number Diff line change
@@ -1,3 +1,34 @@
0.8.0
=====

- [NEW]: Support TA-Lib C 0.8.1, which is now the minimum required version.

- [NEW]: The 40 functions TA-Lib C added since 0.7.1: AC, ADR, AO, CMF, CMOU,
COPPOCK, CUMSUM, CVI, DONCHIAN, DPO, EFI, ER, ERI, FOSC, FRACTAL, HA, HMA,
KC, KDJ, MARKETFI, MASSI, NVI, PERCENTILE, PERCENTRANK, PVI, PVO, PVT,
QSTICK, RMA, RVI, RVOL, SMI, SUPERTREND, TSI, VHF, VORTEX, VWAP, VWMA, WAD,
ZLEMA.

- [NEW]: New moving averages: ``MA_Type.HMA``, ``MA_Type.DISABLED``,
``MA_Type.DEFAULT``, ``MA_Type.ZLEMA`` and ``MA_Type.RMA``.

- [NEW]: ``set_unstable_period()`` and ``get_unstable_period()`` accept
``'RMA'``, ``'HA'`` and ``'RVI'``.

- [FIX]: ``abstract`` raised ``KeyError`` on function and output flags added
after this wrapper was written; unknown flag bits are now ignored.

- [FIX]: A moving-average parameter not spelled exactly ``matype`` -- ``KDJ``'s
``slowk_matype`` -- defaulted to SMA rather than to the function's own
documented default.

- [FIX]: An ``integer`` output is documented as the candlestick -100/0/100
convention only for candlestick functions; ``SUPERTREND``'s is a trend
direction.

- [CHANGE]: ``APO`` and ``PPO`` now default ``matype`` to EMA, and ``BBANDS``
defaults ``timeperiod`` to 20, following TA-Lib C 0.8.1.

0.7.1
=====

Expand Down
74 changes: 65 additions & 9 deletions talib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,14 +106,30 @@ def wrapper(*args, **kwds):
_wrapper = lambda x: x


from ._ta_lib import (
_ta_initialize, _ta_shutdown, MA_Type, __ta_version__,
_ta_set_unstable_period as set_unstable_period,
_ta_get_unstable_period as get_unstable_period,
_ta_set_compatibility as set_compatibility,
_ta_get_compatibility as get_compatibility,
__TA_FUNCTION_NAMES__
)
# The TA-Lib C library this wrapper is built against
TA_LIB_C_REQUIRED = '0.8.1'

try:
from ._ta_lib import (
_ta_initialize, _ta_shutdown, MA_Type, __ta_version__,
_ta_set_unstable_period as set_unstable_period,
_ta_get_unstable_period as get_unstable_period,
_ta_set_compatibility as set_compatibility,
_ta_get_compatibility as get_compatibility,
__TA_FUNCTION_NAMES__
)
except ImportError as error:
# Loading the extension resolves its symbols against whatever TA-Lib C is
# installed. Linking never catches a too-old library -- a shared object may
# keep undefined symbols -- so a missing function shows up here instead, as
# "undefined symbol: TA_CMF_Lookback" or the macOS/Windows equivalent.
raise ImportError(
'%s\n\n'
'talib could not load its extension module. This build requires the '
'TA-Lib C library %s or later; an older one is missing functions this '
'wrapper calls. See https://ta-lib.org/install/'
% (error, TA_LIB_C_REQUIRED)
) from error

# import all the func and stream functions
from ._ta_lib import *
Expand Down Expand Up @@ -154,6 +170,7 @@ def wrapper(*args, **kwds):
],
'Math Operators': [
'ADD',
'CUMSUM',
'DIV',
'MAX',
'MAXINDEX',
Expand Down Expand Up @@ -183,16 +200,26 @@ def wrapper(*args, **kwds):
'TANH',
],
'Momentum Indicators': [
'AC',
'ADX',
'ADXR',
'AO',
'APO',
'AROON',
'AROONOSC',
'BOP',
'CCI',
'CMO',
'CMOU',
'COPPOCK',
'DPO',
'DX',
'ER',
'ERI',
'FOSC',
'FRACTAL',
'IMI',
'KDJ',
'MACD',
'MACDEXT',
'MACDFIX',
Expand All @@ -203,37 +230,50 @@ def wrapper(*args, **kwds):
'PLUS_DI',
'PLUS_DM',
'PPO',
'QSTICK',
'ROC',
'ROCP',
'ROCR',
'ROCR100',
'RSI',
'SMI',
'STOCH',
'STOCHF',
'STOCHRSI',
'TRIX',
'TSI',
'ULTOSC',
'VHF',
'VORTEX',
'WAD',
'WILLR',
],
'Overlap Studies': [
'ACCBANDS',
'BBANDS',
'DEMA',
'DONCHIAN',
'EMA',
'HMA',
'HT_TRENDLINE',
'KAMA',
'KC',
'MA',
'MAMA',
'MAVP',
'MIDPOINT',
'MIDPRICE',
'RMA',
'SAR',
'SAREXT',
'SMA',
'SUPERTREND',
'T3',
'TEMA',
'TRIMA',
'VWMA',
'WMA',
'ZLEMA',
],
'Pattern Recognition': [
'CDL2CROWS',
Expand Down Expand Up @@ -301,6 +341,7 @@ def wrapper(*args, **kwds):
'Price Transform': [
'AVGDEV',
'AVGPRICE',
'HA',
'MEDPRICE',
'TYPPRICE',
'WCLPRICE',
Expand All @@ -312,19 +353,34 @@ def wrapper(*args, **kwds):
'LINEARREG_ANGLE',
'LINEARREG_INTERCEPT',
'LINEARREG_SLOPE',
'PERCENTILE',
'PERCENTRANK',
'STDDEV',
'TSF',
'VAR',
],
'Volatility Indicators': [
'ADR',
'ATR',
'CVI',
'MASSI',
'NATR',
'RVI',
'TRANGE',
],
'Volume Indicators': [
'AD',
'ADOSC',
'OBV'
'CMF',
'EFI',
'MARKETFI',
'NVI',
'OBV',
'PVI',
'PVO',
'PVT',
'RVOL',
'VWAP',
],
}

Expand Down
38 changes: 16 additions & 22 deletions talib/_abstract.pxi
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
'''
This file Copyright (c) 2013 Brian A Cappello <briancappello at gmail>
'''
import math
import threading
try:
from collections import OrderedDict
Expand Down Expand Up @@ -592,30 +591,23 @@ def __get_flags(int flag, dict flags_lookup_dict):
This function returns the flags from flag found in the provided
flags_lookup_dict.
"""
value_range = flags_lookup_dict.keys()
if not isinstance(value_range, list):
value_range = list(value_range)
min_int = int(math.log(min(value_range), 2))
max_int = int(math.log(max(value_range), 2))

# if the flag we got is out-of-range, it just means no extra info provided
if flag < 1 or flag > 2**max_int:
# A bit with no description means the installed ta-lib is newer than this
# build knows about; skip it rather than raising.
if flag < 1:
return None

# In this loop, i is essentially the bit-position, which represents an
# input from flags_lookup_dict. We loop through as many flags_lookup_dict
# bit-positions as we need to check, bitwise-ANDing each with flag for a hit.
ret = []
for i in xrange(min_int, max_int+1):
if 2**i & flag:
ret.append(flags_lookup_dict[2**i])
return ret
return [description
for bit, description in sorted(flags_lookup_dict.items())
if bit & flag]

TA_FUNC_FLAGS = {
1: 'A period of 1 performs no smoothing',
16777216: 'Output scale same as input',
33554432: 'Function has a streaming API',
67108864: 'Output is over volume',
134217728: 'Function has an unstable period',
268435456: 'Output is a candlestick'
268435456: 'Output is a candlestick',
536870912: 'Output is path-dependent',
1073741824: 'Output can be NaN or infinite',
}

# when flag is 0, the function (should) work on any reasonable input ndarray
Expand All @@ -642,7 +634,8 @@ TA_OUTPUT_FLAGS = {
512: 'Output can be negative',
1024: 'Output can be zero',
2048: 'Values represent an upper limit',
4096: 'Values represent a lower limit'
4096: 'Values represent a lower limit',
8192: 'Output is optional (nullable)',
}

def _ta_getFuncInfo(char *function_name):
Expand Down Expand Up @@ -754,13 +747,14 @@ def _get_defaults_and_docs(func_info):
docs.append(' %s: %s' % (param, params[param]))
func_args.append('[%s=%s]' % (param, params[param]))
defaults[param] = params[param]
if param == 'matype':
if param.endswith('matype'):
docs[-1] = ' '.join([docs[-1], '(%s)' % MA_Type[params[param]]])

outputs = func_info['output_names']
candlestick = 'Output is a candlestick' in (func_info['function_flags'] or [])
docs.append('Outputs:')
for output in outputs:
if output == 'integer':
if output == 'integer' and candlestick:
output = 'integer (values are -100, 0 or 100)'
docs.append(' %s' % output)

Expand Down
13 changes: 12 additions & 1 deletion talib/_common.pxi
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ cpdef _ta_check_success(str function_name, TA_RetCode ret_code):
description = 'Bad Object (TA_BAD_OBJECT)'
elif ret_code == 16:
description = 'Not Supported (TA_NOT_SUPPORTED)'
elif ret_code == 17:
description = 'Insufficient History (TA_INSUFFICIENT_HISTORY)'
elif ret_code == 5000:
description = 'Internal Error (TA_INTERNAL_ERROR)'
elif ret_code == 65535:
Expand All @@ -60,7 +62,8 @@ def _ta_shutdown():
_ta_check_success('TA_Shutdown', ret_code)

class MA_Type(object):
SMA, EMA, WMA, DEMA, TEMA, TRIMA, KAMA, MAMA, T3 = range(9)
SMA, EMA, WMA, DEMA, TEMA, TRIMA, KAMA, MAMA, T3, HMA, DISABLED, DEFAULT, \
ZLEMA, RMA = range(14)

def __init__(self):
self._lookup = {
Expand All @@ -73,6 +76,11 @@ class MA_Type(object):
MA_Type.KAMA: 'Kaufman Adaptive Moving Average',
MA_Type.MAMA: 'MESA Adaptive Moving Average',
MA_Type.T3: 'Triple Generalized Double Exponential Moving Average',
MA_Type.HMA: 'Hull Moving Average',
MA_Type.DISABLED: 'No Moving Average (identity)',
MA_Type.DEFAULT: "The Function's Own Default Moving Average",
MA_Type.ZLEMA: 'Zero-Lag Exponential Moving Average',
MA_Type.RMA: "Wilder's Smoothed Moving Average",
}

def __getitem__(self, type_):
Expand Down Expand Up @@ -107,6 +115,9 @@ _ta_func_unst_ids = {
'PLUS_DM': lib.TA_FUNC_UNST_PLUS_DM,
'RSI': lib.TA_FUNC_UNST_RSI,
'T3': lib.TA_FUNC_UNST_T3,
'RMA': lib.TA_FUNC_UNST_RMA,
'HA': lib.TA_FUNC_UNST_HA,
'RVI': lib.TA_FUNC_UNST_RVI,
'ALL': lib.TA_FUNC_UNST_ALL,
}

Expand Down
Loading