gseattle gseattle - 1 month ago 9
Python Question

Call functions based on their names as a strings in a list

Terms:
talib: Technical Analysis Library (stock market indicators, charts etc)
CDL: Candle or Candlestick


Short version: I want to run my_lib.some_function() based on the string 'some_function'

On quantopian.com I want to call all of the 60 talib functions that start with CDL, like talib.CDL2CROWS(), in a loop for brevity. First pull the function names as strings, then run the functions by the name matching the string.

Those CDL functions all take the same inputs, lists of open, high, low and closing prices for a time period and the test here just uses a list of length 1 to simplify.

import talib, re
import numpy as np

# Make a list of talib's function names that start with 'CDL'
cdls = re.findall('(CDL\w*)', ' '.join(dir(talib)))
# cdls[:3], the first three like ['CDL2CROWS', 'CDL3BLACKCROWS', 'CDL3INSIDE']

for cdl in cdls:
codeobj = compile(cdl + '(np.array([3]),np.array([4]),np.array([5]),np.array([6]))', 'talib', 'exec')
exec(codeobj)
break
# Output: NameError: name 'CDL2CROWS' is not defined


Try number two:

import talib, re
import numpy as np

cdls = re.findall('(CDL\w*)', ' '.join(dir(talib)))

for cdl in cdls:
codeobj = compile('talib.' + cdl + '(np.array([3]),np.array([4]),np.array([5]),np.array([6]))', '', 'exec')
exec(codeobj)
break
# Output: AssertionError: open is not double


I didn't find that error online.

Related, where I asked the question over there: https://www.quantopian.com/posts/talib-indicators (111 views, no replies yet)

For anyone curious about candlesticks: http://thepatternsite.com/TwoCrows.html




Update



This works, after help in chat from Anzel, possibly floats in the lists were key.

import talib, re
import numpy as np
cdls = re.findall('(CDL\w*)', ' '.join(dir(talib)))
# O, H, L, C = Open, High, Low, Close
O = [ 167.07, 170.8, 178.9, 184.48, 179.1401, 183.56, 186.7, 187.52, 189.0, 193.96 ]
H = [ 167.45, 180.47, 185.83, 185.48, 184.96, 186.3, 189.68, 191.28, 194.5, 194.23 ]
L = [ 164.2, 169.08, 178.56, 177.11, 177.65, 180.5, 185.611, 186.43, 188.0, 188.37 ]
C = [ 166.26, 177.8701, 183.4, 181.039, 182.43, 185.3, 188.61, 190.86, 193.39, 192.99 ]
for cdl in cdls: # the string that becomes the function name
toExec = getattr(talib, cdl)
out = toExec(np.array(O), np.array(H), np.array(L), np.array(C))
print str(out) + ' ' + cdl


Choices on how to add arguments to your string-turned-function:

toExec = getattr(talib, cdl)(args)
toExec()


or

toExec = getattr(talib, cdl)
toExec(args)

Answer Source

If you want to run my_lib.some_function() based on the string 'some_function', use getattr like this:

some_function = 'your_string'
toExec = getattr(my_lib, some_function)

# to call the function
toExec()

# an example using math
>>> some_function = 'sin'
>>> toExec = getattr(math, some_function)

>>> toExec
<function math.sin>
>>> toExec(90)
0.8939966636005579

update for your code to run

for cdl in cdls:
    toExec = getattr(talib, cdl)

# turns out you need to pass narray as the params
toExec(np.narray(yourlist),np.narray(yourlist),np.narray(yourlist),np.narray(yourlist))

I also suggest you need to review yourlist as it's current 1-dimension, whereas you need n-dimensions array.