
Backtrader 是一個非常受歡迎且功能強大的 Python 回測框架,主要用於量化交易策略的開發、測試與實盤交易。它支援各種市場資料(如股票、期貨、外匯、加密貨幣等)以及多種回測功能,並且能夠輕鬆地擴展以適應各種交易策略。
Backtrader 的核心概念與結構
Backtrader 主要由以下幾個核心組件構成:
- 策略 (Strategy)
策略是 Backtrader 的核心,代表了用戶的交易邏輯。在策略中,你可以定義買賣條件、風險控制等行為。策略是繼承bt.Strategy
類來實現的。 - 資料 (Data)
資料是 Backtrader 回測中用來運行策略的市場數據。資料可以來自各種來源,比如 CSV、SQL、API、Pandas DataFrame 等。Backtrader 支援多種類型的市場資料,如時間序列資料(K 線圖)。 - 回測引擎 (Cerebro)
Cerebro
是 Backtrader 的回測引擎,它負責組織策略、資料和其他元素。你可以在Cerebro
中設定回測的初始資金、交易費用、保證金比例等參數。 - 指標 (Indicators)
Backtrader 提供了大量內建的技術指標,如簡單移動平均 (SMA)、相對強弱指標 (RSI)、移動平均收斂發散指標 (MACD) 等,這些可以直接使用在策略中,也支援自定義指標。 - 交易 (Broker)
Broker
是處理交易執行的組件,負責計算資金變動、手續費、執行訂單等。它是策略的背後支持,會與市場資料交互。
Backtrader 的主要功能
- 回測 (Backtesting)
Backtrader 最核心的功能就是回測,它能夠將你的策略運行在歷史市場數據上,幫助你評估策略的效果。你可以設定初始資金、交易費用、手數等,並查看回測的結果和資金曲線。 - 優化 (Optimization)
Backtrader 支援策略優化,你可以對策略的參數進行多維度的搜尋和測試(例如對移動平均線的時間窗進行優化),從而找出最佳的參數設置。 - 實盤交易 (Live Trading)
除了回測,Backtrader 也可以用來進行實盤交易,並且支援與許多券商 API 的整合(如 Interactive Brokers、Binance、OANDA、Alpaca 等)。你可以直接將回測策略應用於實際的交易中。 - 多策略回測 (Multiple Strategies)
Backtrader 允許同時運行多個策略,你可以在同一個回測中測試多個策略的表現,或者在不同的市場條件下使用不同策略。 - 多資料回測 (Multiple Data Feeds)
你可以將多個資料來源加入到同一個回測中,比如同時使用多個市場或多幣種資料進行回測,這對於跨市場或多樣化的策略非常有用。 - 視覺化 (Visualization)
Backtrader 提供了內建的圖表功能,可以將回測結果可視化,顯示策略的資金曲線、持倉情況、指標線以及買賣信號等。
Backtrader 範例解說
以下是一個簡單的範例,展示如何使用 Backtrader 進行回測。
範例:簡單的移動平均交叉策略
import backtrader as bt
import pandas as pd
# 策略定義
class SMACross(bt.Strategy):
def __init__(self):
# 定義兩條簡單移動平均線(SMA)
self.sma1 = bt.indicators.SMA(self.data.close, period=10) # 10日SMA
self.sma2 = bt.indicators.SMA(self.data.close, period=30) # 30日SMA
def next(self):
# 進行買賣操作
if not self.position: # 如果目前沒有持倉
if self.sma1[0] > self.sma2[0]: # 當短期SMA上穿長期SMA
self.buy()
elif self.sma1[0] < self.sma2[0]: # 如果短期SMA下穿長期SMA
self.sell()
# 從 CSV 載入市場數據
df = pd.read_csv('BTCUSD.csv', parse_dates=['Date'])
df.set_index('Date', inplace=True)
# 將資料轉換成 Backtrader 可用的格式
data = bt.feeds.PandasData(dataname=df)
# 建立回測引擎
cerebro = bt.Cerebro()
# 添加策略到引擎
cerebro.addstrategy(SMACross)
# 添加資料
cerebro.adddata(data)
# 設定初始資金
cerebro.broker.setcash(100000)
# 執行回測
print(f'初始資金: {cerebro.broker.getvalue():.2f}')
cerebro.run()
print(f'最終資金: {cerebro.broker.getvalue():.2f}')
# 顯示回測結果圖
cerebro.plot()
Backtrader 的工作流程概覽
- 策略開發:用戶定義策略的邏輯,設定買賣條件、止盈止損等。
- 資料輸入:從 CSV、API 或其他來源載入歷史市場數據。
- 設定回測引擎:配置回測的初始資金、交易費用、槓桿等。
- 回測執行:將策略應用於資料上,進行回測,並查看結果。
- 結果分析:查看回測結果、資金曲線等,並根據結果調整策略。
- 優化與實盤:優化策略的參數並將策略應用於實際交易。
這個有什麼用呢?
像是回測完發現不錯的參數
就可以打包成函數
例如我之前的專案
https://github.com/skywalker0803r/telegram-investment_crypto-advice-bot
def get_signal_fast(
pair='BTCUSDT',
freq='15m',
n_bar = 10000,
client = None,
n1 = 65,
n2 = 95,
):
# get data
ohlcv = finlab_crypto.crawler.get_nbars_binance(pair,freq,n_bar,client)
# get signal table
table = pd.DataFrame()
table['close'] = ohlcv.close
table['n1'] = ohlcv.close.rolling(n1).mean()
table['n2'] = ohlcv.close.rolling(n2).mean()
table['buy'] = ((table['n1'] > table['n2']) & (table['n1'].shift() < table['n2'].shift())).astype(int)
table['sell'] = ((table['n1'] < table['n2']) & (table['n1'].shift() > table['n2'].shift())).astype(int)
table = table.replace(0,np.nan).tail(1)
# if buy and sell eqal np.nan pass
if table[['buy','sell']].sum().sum() == 0:
signal = 'PASS'
# if buy == 1
if table[['buy']].values[0][0] == 1:
signal = 'BUY'
# if sell == 1
if table[['sell']].values[0][0] == 1:
signal = 'SELL'
return signal,n1,n2,table['close'].values[-1]
裡面的
n1 = 65,
n2 = 95,
都是可以調整的
調完再寫一段自動化程式碼
# TRADING SETTING
pair='DOGEUSDT'
freq = '15m'
n_bar = 10000
n1 = 65
n2 = 95
quantity = 100
# MAIN
if __name__ == '__main__':
while True:
side,n1,n2,price = get_signal_fast(pair,freq,n_bar,client,n1,n2)
message = f"交易對:{pair}\n當前價格:{price}\n多空:{side}\n雙均線參數: n1 {n1} n2 {n2}\n現在時間:{datetime.now().strftime('%Y-%m-%d %H:%M:%S')}"
print(message)
send_to_telegram(message,apiToken,chatID)
if side != 'PASS':
order_result = place_order(symbol=pair,side='SELL',client=client,quantity = quantity)
print(order_result)
send_to_telegram(f'執行下單函數結果:{order_result}\n',apiToken,chatID)
time.sleep(60*15)
os.system("cls")
讓他自動執行即可