# day1_backtrader_analyzer_demo.py
import backtrader as bt
# --- 基础策略(可复用) ---
class TestStrategy(bt.Strategy):
params = dict(
fast=10,
slow=20,
)
def __init__(self):
self.sma_fast = bt.ind.SMA(period=self.p.fast)
self.sma_slow = bt.ind.SMA(period=self.p.slow)
def next(self):
if not self.position:
if self.sma_fast > self.sma_slow:
self.buy()
else:
if self.sma_fast < self.sma_slow:
self.sell()
# --- Loader ---
def load_data():
data = bt.feeds.YahooFinanceCSVData(
dataname='data/BTC_USDT.csv',
fromdate=datetime(2021,1,1),
todate=datetime(2023,12,31),
)
return data
# --- Main ---
if __name__ == "__main__":
cerebro = bt.Cerebro()
cerebro.addstrategy(TestStrategy)
cerebro.adddata(load_data())
# 添加分析器 analyzer
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='dd')
result = cerebro.run()
strat = result[0]
print("Sharpe Ratio:", strat.analyzers.sharpe.get_analysis())
print("Max Drawdown:", strat.analyzers.dd.get_analysis())
cerebro.plot()
# day2_rsi_sma_strategy.py
import backtrader as bt
class RSISMAStrategy(bt.Strategy):
params = dict(
sma_period=20,
rsi_period=14,
rsi_buy=30,
rsi_sell=70,
)
def __init__(self):
self.sma = bt.ind.SMA(period=self.p.sma_period)
self.rsi = bt.ind.RSI(period=self.p.rsi_period)
def next(self):
# Buy signal: price > SMA AND RSI < 30
if not self.position:
if self.data.close > self.sma and self.rsi < self.p.rsi_buy:
self.buy()
else:
if self.data.close < self.sma or self.rsi > self.p.rsi_sell:
self.sell()
# ——— 数据加载 & 回测略(与昨日相同) ———
# day3_manual_param_search.py
import backtrader as bt
import pandas as pd
from strategy_rsi_sma import RSISMAStrategy
param_grid = [
{"sma_period": 10, "rsi_period": 14},
{"sma_period": 20, "rsi_period": 14},
{"sma_period": 30, "rsi_period": 14},
{"sma_period": 10, "rsi_period": 7},
{"sma_period": 20, "rsi_period": 7},
{"sma_period": 30, "rsi_period": 7},
{"sma_period": 15, "rsi_period": 10},
{"sma_period": 25, "rsi_period": 10},
{"sma_period": 35, "rsi_period": 10},
{"sma_period": 50, "rsi_period": 14},
]
results = []
def run_backtest(params):
cerebro = bt.Cerebro()
cerebro.adddata(bt.feeds.YahooFinanceCSVData(dataname="data/BTC_USDT.csv"))
cerebro.addstrategy(RSISMAStrategy, **params)
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
cerebro.addanalyzer(bt.analyzers.DrawDown, _name='dd')
res = cerebro.run()[0]
sharpe = res.analyzers.sharpe.get_analysis().get('sharperatio', 0)
maxdd = res.analyzers.dd.get_analysis()['max']['drawdown']
return sharpe, maxdd
for p in param_grid:
sharpe, maxdd = run_backtest(p)
results.append([p['sma_period'], p['rsi_period'], sharpe, maxdd])
df = pd.DataFrame(results, columns=["SMA", "RSI", "Sharpe", "MaxDD"])
print(df)
df.to_csv("week3/manual_param_search.csv", index=False)
# day4_optuna_optimize.py
import optuna
import backtrader as bt
import pandas as pd
from strategy_rsi_sma import RSISMAStrategy
def objective(trial):
# 搜索范围
sma_period = trial.suggest_int("sma", 5, 50)
rsi_period = trial.suggest_int("rsi", 5, 20)
cerebro = bt.Cerebro()
cerebro.adddata(bt.feeds.YahooFinanceCSVData(dataname="data/BTC_USDT.csv"))
cerebro.addstrategy(
RSISMAStrategy,
sma_period=sma_period,
rsi_period=rsi_period,
)
cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='sharpe')
result = cerebro.run()[0]
sharpe = result.analyzers.sharpe.get_analysis().get('sharperatio', -1)
return sharpe
# 运行优化
study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=50)
print("最佳参数:", study.best_params)
print("最佳 Sharpe:", study.best_value)
# 保存可视化图
fig = optuna.visualization.plot_optimization_history(study)
fig.write_image("week3/optuna_history.png")
# day5_commission_slippage.py
import backtrader as bt
class RSISMAStrategy(bt.Strategy):
# ... 与前一致 ...
cerebro = bt.Cerebro()
data = bt.feeds.YahooFinanceCSVData(dataname="data/BTC_USDT.csv")
cerebro.adddata(data)
# 关键:加入交易费 & 滑点
cerebro.broker.setcommission(commission=0.0004) # 交易费 0.04%
cerebro.broker.set_slippage_perc(0.0005) # 滑点 0.05%
cerebro.addstrategy(RSISMAStrategy)
cerebro.run()
# run_backtest.py
import json
import backtrader as bt
from strategy_rsi_sma import RSISMAStrategy
def run(config_path):
with open(config_path, 'r') as f:
cfg = json.load(f)
cerebro = bt.Cerebro()
data = bt.feeds.YahooFinanceCSVData(dataname=cfg["data"])
cerebro.adddata(data)
cerebro.broker.setcommission(commission=cfg["commission"])
cerebro.broker.set_slippage_perc(cfg["slippage"])
cerebro.addstrategy(
RSISMAStrategy,
sma_period=cfg["sma"],
rsi_period=cfg["rsi"],
)
result = cerebro.run()
cerebro.plot()
if __name__ == "__main__":
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--config", type=str, default="config.json")
args = parser.parse_args()
run(args.config)
config.json 模板:
{
"data": "data/BTC_USDT.csv",
"commission": 0.0004,
"slippage": 0.0005,
"sma": 20,
"rsi": 14
}