bt backtesting -- > AttributeError: 'Series' object has no attribute 'columns'

1.2k Views Asked by At

Im extract a tickers from binance and made a dataframe

Then I used talib to add different indicators to my df.

But when I try to do a backtesting it gave me this error.

enter code here

    klines = client.get_historical_klines("BNBUSDT", Client.KLINE_INTERVAL_1DAY, "1 jul, 2021")
    df=pd.DataFrame(klines)

df.rename(columns={df.columns[0]: 'open time', df.columns[1]: 'open',df.columns[2]: 'high',df.columns[3]: 'low',df.columns[4]: 'close',df.columns[5]: 'volume'},inplace=True) 


import bt
# Define the strategy
bt_strategy = bt.Strategy('AboveSMA', 
                          [bt.algos.SelectWhere(df["close"]> df["MA30"]),
                           bt.algos.WeighEqually(),
                           bt.algos.Rebalance()])
# Create the backtest and run it
bt_backtest = bt.Backtest(bt_strategy, df["close"])
bt_result = bt.run(bt_backtest)
# Plot the backtest result
bt_result.plot(title='Backtest result')
plt.show()
1

There are 1 best solutions below

0
On

Here is a possible solution:


Step 1: Get data from Binance and perform TA calculations.

  1. Get klines data from Binance
  2. Store it as pandas.DataFrame
  3. Perform a talib operation (here: SMA)
import bt
import binance
import pandas as pd
import talib

# Initiate binance client
client = binance.Client()

# Define column names for klines response
currency_pair = 'BNBUSDT'
columns = [
    'open_time', 'open', 'high', 'low', 'close', 'volume',
    'close_time', 'quote_asset_volume', 'number_of_trades',
    'taker_buy_base_asset_volume', 'taker_buy_quote_asset_volume',
    'ignore'
]

# Get klines from Binance (nested list)
klines = client.get_historical_klines(currency_pair, client.KLINE_INTERVAL_1DAY, "1 jul, 2021")

# Store klines ind pd.DataFrame
df = pd.DataFrame(klines, columns=columns)

# Keep only OHLCV
df = df[['open_time', 'open', 'high', 'low', 'close', 'volume']].apply(pd.to_numeric)

# Perform talib MACD calculation and store in original dataframe
df['SMA30'] = talib.SMA(df['close'], 30)

df['open_time'] = pd.to_datetime(df['open_time'], unit='ms')
df.set_index('open_time', inplace = True)

# Show dataframe before preparing for bt
print(df)

Output, Step 1:

              open    high     low   close        volume       SMA30
open_time                                                           
2021-07-01  303.75  304.00  281.00  287.43  1.388151e+06         NaN
2021-07-02  287.49  290.74  276.40  287.17  1.003331e+06         NaN
2021-07-03  287.17  303.21  282.77  298.13  1.016732e+06         NaN
2021-07-04  298.18  314.91  292.58  307.62  1.309414e+06         NaN
2021-07-05  307.63  307.68  291.00  302.02  1.403218e+06         NaN
...            ...     ...     ...     ...           ...         ...
2021-10-03  427.00  437.20  421.50  430.50  8.209108e+05  403.123333
2021-10-04  430.50  430.90  410.90  426.30  9.744234e+05  400.743333
2021-10-05  426.40  444.00  424.00  442.10  8.836998e+05  398.653333
2021-10-06  442.00  442.80  414.70  434.90  1.245089e+06  396.613333
2021-10-07  434.90  450.00  423.60  441.90  7.514009e+05  397.386667

[99 rows x 6 columns]


Step 2: Use backtesting from bt

  1. Prepare dataframes, derived from original df object.
  2. Define Strategy and Backtest
  3. Execute backtest
  4. Show results
# Prepare dataframes for comparison
# Dataframes must have the same column names
data, sma = df[['close']], df[['SMA30']]
data.rename(columns={'close': currency_pair}, inplace=True)
sma.rename(columns={'SMA30': currency_pair}, inplace=True)

# Define the strategy
bt_strategy = bt.Strategy(
    'AboveSMA',
    [
        bt.algos.SelectWhere(data > sma),
        bt.algos.WeighEqually(),
        bt.algos.Rebalance(),
    ]
)

# Create the backtest and run it
bt_backtest = bt.Backtest(bt_strategy, data)
bt_result = bt.run(bt_backtest)

# Plot the backtest result
bt_result.plot(title='Backtest result')
bt_result.display()

Output display():

Stat                 AboveSMA
-------------------  ----------
Start                2021-06-30
End                  2021-10-07
Risk-free rate       0.00%

Total Return         36.08%
Daily Sharpe         1.91
Daily Sortino        3.04
CAGR                 211.60%
Max Drawdown         -17.06%
Calmar Ratio         12.41

MTD                  4.84%
3m                   36.08%
6m                   -
YTD                  36.08%
1Y                   -
3Y (ann.)            -
5Y (ann.)            -
10Y (ann.)           -
Since Incep. (ann.)  211.60%

Daily Sharpe         1.91
Daily Sortino        3.04
Daily Mean (ann.)    89.51%
Daily Vol (ann.)     46.75%
Daily Skew           -0.66
Daily Kurt           10.35
Best Day             11.23%
Worst Day            -15.60%

Monthly Sharpe       1.55
Monthly Sortino      6.70
Monthly Mean (ann.)  113.11%
Monthly Vol (ann.)   73.16%
Monthly Skew         1.41
Monthly Kurt         2.63
Best Month           39.57%
Worst Month          -9.74%

Yearly Sharpe        -
Yearly Sortino       -
Yearly Mean          -
Yearly Vol           -
Yearly Skew          -
Yearly Kurt          -
Best Year            -
Worst Year           -

Avg. Drawdown        -5.09%
Avg. Drawdown Days   5.78
Avg. Up Month        15.82%
Avg. Down Month      -9.74%
Win Year %           -
Win 12m %            -

Output plot():

enter image description here