均线交叉

# -*- 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}')
    

发表评论