-1

I am trying to backtest a momentum strategy using Backtesting.py. I've gathered the data and computed indicator values using pandas_ta. I've defined short and long trading conditions. Now I just need Backtesting.py to run a backtest so that I can determine the performance of my strategy on historical data.

This notebook contains all the code plus the errors I am getting:

https://github.com/kbs-code/algo_trader/blob/master/backtests/backtestingdotpy_broad_market_ema_vortex.ipynb

The latest error is this one:

ValueError: The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all().

I've googled this type of error and tried to resolve it using parentheses, bitwise (and) and logical (and). I don't think my truth statement is illegal in Python but I could be wrong. I've also read Backtesting.py's documentation to understand the framework as best I can.

Any help would be appreciated.

1 Answer 1

0

Both self.close and self.ema are DataFrame series. Comparing two series (e.g. self.close > self.ema) results in a boolean series:

a = pd.Series([1, 2, 3, 4])
b = pd.Series([3, 1, 4, 2])
print(a > b)    # Outputs pd.Series([False, True, False, True])

Using a boolean series in a if-statement (e.g. if a > b:) is ambiguous because Pandas does not know what you mean: should that expression evaluate to true if all the items are True? Of it should evaluate to true if at least one item is True?

Therefore, you need to use it with either .any() or .all():

if (a > b).all():  # If all items in `a` are greater than
    pass           # their corresponding items in `b`

if (a > b).any():  # If any item in `a` is greater than
    pass           # their corresponding item in `b`

This makes your intention clearer to the person who will read your code and for yourself.

Sign up to request clarification or add additional context in comments.

3 Comments

Hi, thanks for answering. I have seen this answer in my research but I don't understand why using .all() is necessary. It seems to me that the backtesting engine would be walking through the rows of the dataframe and using floats stored there. I'm trying to define trading logic using floats. I've written 2 more cells in my notebook to demonstrate my intent.
In the cell starting with "Logic example", you're accessing a single value by using df.iloc[1]['Close'] and df.iloc[1]['ema'], as you can see in the next cell output, a numpy.float64. Since you're manipulating a single value, it's easy for comparison: 3.14 > 2.71. However, when you compare a whole column, such as using df['Close'] and df['ema'], this comparison becomes ambiguous. Does [3.14, 1.64] > [2.71, 1.77]? Therefore, you need to use all (all comparisons must satisfy >) or any (at least one comparison must satisfy >).
You may also have a look at the official documentation on this topic.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.