这是一个可能的解决方案:
步骤 1:从 Binance 获取数据并执行 TA 计算。
- 从 Binance 获取 klines 数据
- 将其存储为
pandas.DataFrame
- 执行
talib
操作(此处: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)
输出,步骤 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]
第 2 步:使用 bt 的回测
df
准备从原始对象派生的数据框。
- 定义策略和回测
- 执行回测
- 显示结果
# 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()
输出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 % -
输出plot()
: