-
Notifications
You must be signed in to change notification settings - Fork 1.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Decorator to register arbitrary user defined funcs for use with pta.Strategy API #707
Comments
Here's a hacky yet working sketch given the current design of the library: from pandas_ta.custom import bind
from functools import wraps
import pandas_ta
def _get_args_dict(f):
args_names = f.__code__.co_varnames[:f.__code__.co_argcount]
return args_names
def create_class_method(f):
@wraps(f)
def method(self, *args, **kwargs):
kwarg_names = _get_args_dict(f)
valid_kwargs = {k: v for k,v in kwargs.items() if k in kwarg_names}
return f(*args, **valid_kwargs)
return method
def pta_register(f):
class_method = create_class_method(f)
bind(function_name=f.__name__, function=f, method=class_method)
@wraps(f)
def wrapper(*args, **kwargs):
return f(*args, **kwargs)
return wrapper And in use: @pta_register
def pivot_support_resistance(ohlcv, length: int):
adjusted_high = ohlcv.High.rolling(length).max()
adjusted_low = ohlcv.Low.rolling(length).min()
adjusted_close = ohlcv.Close.rolling(length).mean()
pivot_point = (adjusted_high + adjusted_low + adjusted_close) / 3
ohlcv[f'PIVOT_SUPPORT_{length}'] = (pivot_point.rolling(length).min() * 2) - adjusted_high
ohlcv[f'PIVOT_RESISTANCE_{length}'] = (pivot_point.rolling(length).max() * 2) - adjusted_low
ohlcv[f'PIVOT_POINT_{length}'] = pivot_point
ohlcv[f'PIVOT_RESISTANCE_{length}_RATIO_CL'] = ohlcv.Close / ohlcv[f'PIVOT_RESISTANCE_{length}']
ohlcv[f'PIVOT_SUPPORT_{length}_RATIO_CL'] = ohlcv.Close / ohlcv[f'PIVOT_SUPPORT_{length}']
ohlcv[f'PIVOT_SPOINT_{length}_RATIO_CL'] = ohlcv.Close / ohlcv[f'PIVOT_POINT_{length}']
return ohlcv import pandas_ta as pta
Pivot = pta.Strategy(
name = "Pivot",
ta = [
{"kind":"pivot_support_resistance", "length":20, "ohlcv": df}
]
)
df.ta.strategy(Pivot) |
Hello @arainboldt,
Currently there is no way to do this. However I do think this is a nice way extend the functionality of the library for external user defined indicators. 😎
Based upon your test code so far, how much refactoring are we talking about? Before answering, please try it out with the development version so we are on the same page. Kind Regards, |
@twopirllc the test code works, with one limitation. Strategies with funcs decorated with this will run as expected, except that the ALL strategy breaks after using the decorator due to the way it gathers or calls funcs. I'll look back at my example notebook to see what the exact error is. Generally, however, the explicit definition of each function in the DataFrame subclass is a problematic pattern. A more abstract and generalized approach would provide flexibility and extensibility down the line. Perhaps this is something to consider refactoring. |
There have been some changes with strategy() beyond being renamed to study() on the development branch that you should check out. If I recall, it fixes the ALL study/strategy issue.
Yes, it has been a thorn in my side and I unfortunately have not had the time rebuild and test a possible better working DataFrame Extension with less explicit indicator definitions. When you get a chance, please test your code on the development branch and not the main branch. KJ |
Awesome. Will do |
Is there a decorator that can be used to register arbitrary functions so that they can be used with the pta.Strategy API?
I'm thinking something like this:
If the library isn't already setup for something like this, it might take a bit of refactoring. It would, however, greatly improve the extensibility of the library for the user.
Thanks!
Andrew
The text was updated successfully, but these errors were encountered: