# -*- coding: utf-8 -*-
"""
Created on Wed Sep 17 15:37:16 2025
@author: cdlei
"""
import backtrader as bt
import pandas as pd
symbol='515800'
def read_data(symbol):
file="./data/"+symbol+".csv"
daily_price = pd.read_csv(file,parse_dates=['date'])
data=daily_price.set_index('date')
return data
class TestStrategy(bt.Strategy):
params=(('period1',5),
('period2',10),)
def log(self, txt, dt=None):
''' Logging function fot this strategy'''
dt = dt or self.datas[0].datetime.date(0)
print('%s, %s' % (dt.isoformat(), txt))
def __init__(self):
# 打印数据集和数据集对应的名称
# print("-------------self.datas-------------")
# print(self.datas)
# print("-------------self.data-------------")
# print(self.data._name, self.data)
# print("-------------self.data0-------------")
# print(self.data0._name, self.data0)
# print("-------------self.datas[0]-------------")
# print(self.datas[0]._name, self.datas[0])
# print(self.data.close)
# print(self.data.open)
#计算均线
self.ma1 = bt.indicators.SMA(self.data.close, period=self.p.period1)
self.ma2 = bt.indicators.SMA(self.data.close, period=self.p.period2)
#计算2条均线交叉信号:ma2 上穿 ma1 时,取值为 +1; ma2 下穿 ma1 时,取值为 -1
self.crossover = bt.indicators.CrossOver(self.ma2, self.ma1)
# 初始化订单
self.order = None
def next(self):
# 打印每日的资金和持仓情况
print('date', self.data0.datetime.date(0))
print('当前可用资金', self.broker.getcash())
print('当前总资产', self.broker.getvalue())
print('当前持仓量', self.broker.getposition(self.data).size)
print('当前持仓成本', self.broker.getposition(self.data).price)
# 取消之前未执行的订单
if self.order:
self.cancel(self.order)
# 检查是否有持仓
if not self.position:
# 10日均线上穿5日均线,买入
if self.crossover > 0:
self.order = self.buy(size=10000) # 以下一日开盘价买入10000股
# # 10日均线下穿5日均线,卖出
elif self.crossover < 0:
self.order = self.close() # 平仓,以下一日开盘价卖出
def notify_order(self, order):
# 未被处理的订单
if order.status in [order.Submitted, order.Accepted]:
return
# 已被处理的订单
if order.status in [order.Completed, order.Canceled, order.Margin]:
if order.isbuy():
self.log(
'执行买入, ref:%.0f,Price: %.4f, Size: %.2f, Cost: %.4f, Comm %.4f, Stock: %s' %
(order.ref,
order.executed.price,
order.executed.size,
order.executed.value,
order.executed.comm,
order.data._name))
else: # Sell
self.log('执行卖出, ref:%.0f, Price: %.4f, Size: %.2f, Cost: %.4f, Comm %.4f, Stock: %s' %
(order.ref,
order.executed.price,
order.executed.size,
order.executed.value,
order.executed.comm,
order.data._name))
#使用示例
if __name__ == '__main__':
#读取数据
data=read_data(symbol)
#修改格式
datafeed = bt.feeds.PandasData(dataname=data)
cerebro=bt.Cerebro()
#添加策略
cerebro.addstrategy(TestStrategy)
#加载数据
cerebro.adddata(datafeed)
#设置初始资金
cerebro.broker.set_cash(100000)
#设置滑点
#cerebro.broker.set_slippage_perc(perc=0.0001)
#运行回测
cerebro.run()
#输出最终资产
print(f'最终资产价值:{cerebro.broker.getvalue():.2f}')