pandas-ta
pandas-ta copied to clipboard
How To Test TMO Indicator
I want to first give a big thanks to @luisbarrancos and @twopirllc for working on the indicator. I have been trying to backtest it but am having trouble. I keep getting an error when inputting the first part of the code:
from numpy import broadcast_to, isnan, nan, nansum, newaxis, pad, sign, zeros
from numpy.lib.stride_tricks import sliding_window_view
from pandas import DataFrame, Series
from pandas_ta._typing import DictLike, Int
from pandas_ta.ma import ma
from pandas_ta.utils import (
v_bool,
v_mamode,
v_offset,
v_pos_default,
v_series
)
I get this error when running it:
ModuleNotFoundError: No module named 'pandas_ta._typing'
Do I need to run the code on another platform I am currently using Jupyter?
Hello @azimgiant
I am curious why your testing code begins like the beginning of an indicator code?
The tmo indicator is only available on the development branch. So if you do not have that installed, you will need to do so first.
Second you don't necesarily need Jupyter for testing, but you can if you want.
# your imports here
df = # your ohlcv date retrieval here
df.ta.tmo(append=True) # Apply tmo
# Continue your backtesting here
Kind Regards KJ
I tried installing the development branch first but received this error:
pip install -U git+https://github.com/twopirllc/pandas-ta.git@development
ERROR: Error [WinError 2] The system cannot find the file specified while executing command git version
ERROR: Cannot find command 'git' - do you have 'git' installed and in your PATH?
So, I decided to copy to the raw code thinking it would work like that. As you can see, I am a complete beginner lol. Do you know the right code to install the development branch or why it isn't installing?
@twopirllc
So I was able to download git but when trying to run the backtest the values for the tmo show up as NaN. I don't think I am pulling the tmo correctly from the development branch. Here is the code maybe you can help as to why the values show up as NaN.
import pandas as pd
from backtesting import Backtest, Strategy
from backtesting.lib import crossover
import yfinance as yf
yf.pdr_override()
import numpy as np
import talib
import pandas_ta as ta
df = pd.read_csv("SPY_3m.csv", index_col='Datetime', parse_dates=True)
df=df[df.Volume!=0]
df.ta.tmo(append=True)
class TMO(Strategy):
tmo_length = 14
calc_length = 5
smooth_length = 3
zero = 0
sma_window2 = 29
def init(self):
self.tmo = self.I(ta.tmo, close=self.data.Close, open=self.data.Open,
tmo_length=self.tmo_length, calc_length=self.calc_length, smooth_length=self.smooth_length)
self.sma2 = self.I(talib.SMA, self.data.Close, self.sma_window2)
self.Buy_position_open = False
self.Sell_position_open = False
def next(self):
if crossover(self.tmo, self.zero):
self.buy(size=0.5)
self.Buy_position_open = True
if crossover(self.sma2, self.data.Close) and self.Buy_position_open:
self.position.close()
self.Buy_position_open = False
if crossover(self.zero, self.tmo):
self.sell(size=0.5)
self.Sell_position_open = True
if crossover(self.data.Close, self.sma2) and self.Sell_position_open:
self.position.close()
self.Sell_position_open = False
bt = Backtest(df, TMO, cash=900_000, exclusive_orders=True)
stats = bt.run()
stats
I get this error popping up: RuntimeError: Indicator "tmo(C,O,14,5,3)" errored with exception: tmo() missing 1 required positional argument: 'open_'
When I change the column using this: df = df.rename(columns={'Open': 'open_'}) # Rename 'Open' column to 'open_' I get error saying pandas dataframe only takes the "Open" and not "open_"
@azimgiant
So you were able to install the development version via git?
To avoid confusion with Python's keyword open, I used open_ instead. So the parameter keyword is open_= and not open=.
Should be this if calling with named parameters:
self.tmo = self.I(ta.tmo, close=self.data.Close, open_=self.data.Open,
tmo_length=self.tmo_length, calc_length=self.calc_length, smooth_length=self.smooth_length)
Don't forget to also use: help(ta.tmo)
. When in doubt, check the source.
KJ
@twopirllc
I was able to install the development version. Watched a Youtube video on how to install git and it worked. I'm not sure what's causing the problem here. This hasn't happened for other indicators maybe because this isn't on the main library. When I changed my code to what you suggested this is the error I receive:
ValueError: Indicators must return (optionally a tuple of) numpy.arrays of same length as data
(data shape: (32380,); indicator "tmo(C,O,14,5,3)"shape: , returned value: None)
I saw someone run into a similar issue on Stack Overflow and I used there solution this is the updated code:
self.tmo = self.I(ta.tmo, close=pd.Series(self.data.Close), open_=pd.Series(self.data.Open), tmo_length=self.tmo_length, calc_length=self.calc_length, smooth_length=self.smooth_length)
I get no error when using the above code however after running the stats all the results show up as NaN:
Start 2022-11-07 09:30:00 End 2023-11-03 15:57:00 Duration 361 days 06:27:00 Exposure Time [%] 0.0 Equity Final [$] 900000.0 Equity Peak [$] 900000.0 Return [%] 0.0 Buy & Hold Return [%] 16.517008 Return (Ann.) [%] 0.0 Volatility (Ann.) [%] 0.0 Sharpe Ratio NaN Sortino Ratio NaN Calmar Ratio NaN Max. Drawdown [%] -0.0 Avg. Drawdown [%] NaN Max. Drawdown Duration NaN Avg. Drawdown Duration NaN
Trades 0
Win Rate [%] NaN Best Trade [%] NaN Worst Trade [%] NaN Avg. Trade [%] NaN Max. Trade Duration NaN Avg. Trade Duration NaN Profit Factor NaN Expectancy [%] NaN SQN NaN _strategy TMO _equity_curve ... _trades Empty DataFrame dtype: object
@azimgiant
Since your a beginner and Pandas is used everywhere, I recommend becoming more familiar with this popular tool starting here.
In short, help(ta.tmo)
says that it returns a DataFrame with four columns: main, smooth, main momentum, smooth momentum. Your crossover condition is trying to compare 4 values with 0:
if crossover(self.tmo, self.zero):
and Pandas does not know how to do that, so you have to isolate the column you need. I am assuming the first column: main.
Additionally, I do not know what crossover()
takes for it's arguments, two values, two Series, or a value and a Series/array or a Series/array and a value?
If you need the first column (a Series):
if crossover(self.tmo.iloc[:,0], self.zero):
Or the first column and last value for (a Value):
if crossover(self.tmo.iloc[-1,0], self.zero):
Lastly I do not know the backtesting package, so any particular details or issues you should bring to their attention.
Hope this helps!
Hello @azimgiant,
I assume by no response that the solution provided was sufficient. Thus I will be closing this issue in a few days.
Kind Regards, KJ