3333333333333333-**444444444444444444444444444444444444444444

Day 1 — Backtrader 最小框架(最小可运行示例)

安装

pip install backtrader

代码模板:

# --- Week 2 / Day 1 ---
import backtrader as bt
import pandas as pd

# 1. 建立 Strategy
class TestStrategy(bt.Strategy):
    def __init__(self):
        pass

    def next(self):
        print("Close:", self.data.close[0])

# 2. 创建 Cerebro
cerebro = bt.Cerebro()

# 3. 加载数据 (用你自己的 CSV)
df = pd.read_csv("BTCUSDT_1h.csv", parse_dates=["open_time"], index_col="open_time")

data = bt.feeds.PandasData(
    dataname=df,
    open='open', high='high', low='low', close='close', volume='volume'
)

cerebro.adddata(data)

# 4. 加入策略
cerebro.addstrategy(TestStrategy)

# 5. 开跑
cerebro.run()
cerebro.plot()


📅 Day 2 — 指标(SMA、EMA、RSI)纯 Python + Pandas 版本

SMA、EMA、RSI 代码模板

# --- Week 2 / Day 2 ---
import pandas as pd

# SMA
def SMA(series, window):
    return series.rolling(window).mean()

# EMA
def EMA(series, window):
    return series.ewm(span=window, adjust=False).mean()

# RSI(纯 python 版)
def RSI(series, period=14):
    delta = series.diff()
    gain = delta.clip(lower=0)
    loss = -delta.clip(upper=0)

    avg_gain = gain.rolling(period).mean()
    avg_loss = loss.rolling(period).mean()

    rs = avg_gain / avg_loss
    rsi = 100 - (100 / (1 + rs))
    return rsi

# 测试
df = pd.DataFrame({"close": [100,102,101,104,107,109,112,110,115]})
df["SMA20"] = SMA(df["close"], 20)
df["EMA20"] = EMA(df["close"], 20)
df["RSI14"] = RSI(df["close"], 14)

df


📅 Day 3 — Backtrader SMA 金叉/死叉(第一个策略)

# --- Week 2 / Day 3 ---
import backtrader as bt
import pandas as pd

class SMACross(bt.Strategy):
    params = dict(fast=10, slow=20)

    def __init__(self):
        self.sma_fast = bt.ind.SMA(self.data.close, period=self.p.fast)
        self.sma_slow = bt.ind.SMA(self.data.close, period=self.p.slow)

        self.crossover = bt.ind.CrossOver(self.sma_fast, self.sma_slow)

    def next(self):
        if not self.position:  # no position
            if self.crossover > 0:   # 金叉买入
                self.buy()
        else:
            if self.crossover < 0:   # 死叉卖出
                self.sell()

# --- Run ---
cerebro = bt.Cerebro()
df = pd.read_csv("BTCUSDT_1h.csv", parse_dates=["open_time"], index_col="open_time")

data = bt.feeds.PandasData(dataname=df)
cerebro.adddata(data)
cerebro.addstrategy(SMACross)

results = cerebro.run()
cerebro.plot()

# 打印净值
print("Final Portfolio Value:", cerebro.broker.getvalue())


📅 Day 4 — 回测可视化(权益曲线 + 胜率统计)

① 导出每日 equity curve

# --- Week 2 / Day 4 ---
class StrategyWithEquity(bt.Strategy):
    def __init__(self):
        self.sma = bt.ind.SMA(self.data.close, period=20)

    def next(self):
        pass

    def stop(self):
        self.equity_curve = self.broker.getvalue()

# Run
cerebro = bt.Cerebro()
cerebro.addstrategy(StrategyWithEquity)

data = bt.feeds.PandasData(dataname=df)
cerebro.adddata(data)

result = cerebro.run()

# 绘图
cerebro.plot()

② 手动胜率统计模板

import matplotlib.pyplot as plt

trades = [
    {"pnl": 10},
    {"pnl": -5},
    {"pnl": 20},
    {"pnl": -3},
]

wins = [t for t in trades if t["pnl"] > 0]
loss = [t for t in trades if t["pnl"] <= 0]

winrate = len(wins) / len(trades)

print("Winrate:", winrate)

plt.bar(["Wins", "Losses"], [len(wins), len(loss)])
plt.title("Win / Loss Count")
plt.show()