TURTLE.py

from __future__ import (absolute_import, division, print_function,unicode_literals)
import datetime 
import backtrader as bt
import pandas as pd 
from sqlalchemy import create_engine


class TestSizer(bt.Sizer):
    params = (('stake', 1),)    
    def _getsizing(self, comminfo, cash, data, isbuy):
        if isbuy:          
            return self.p.stake        
        position = self.broker.getposition(data)        
        if not position.size:            
            return 0        
        else:            
            return position.size        
        return self.p.stakeclass 

class TestStrategy(bt.Strategy):
    params = ( ('maperiod', 15),  ('printlog', False), )   
    def log(self, txt, dt=None, doprint=False):
        if self.params.printlog or doprint:            
            dt = dt or self.datas[0].datetime.date(0)           
            print('%s, %s' % (dt.isoformat(), txt))    

    def __init__(self):        

        self.dataclose = self.datas[0].close      
        self.datahigh = self.datas[0].high        
        self.datalow = self.datas[0].low     

        self.order = None      
        self.buyprice = 0      
        self.buycomm = 0      
        self.newstake = 0      
        self.buytime = 0       
        # 参数计算,唐奇安通道上轨、唐奇安通道下轨、ATR        
        self.DonchianHi = bt.indicators.Highest(self.datahigh(-1), period=20, subplot=False)        
        self.DonchianLo = bt.indicators.Lowest(self.datalow(-1), period=10, subplot=False)       
        self.TR = bt.indicators.Max((self.datahigh(0)- self.datalow(0)), abs(self.dataclose(-1) -   self.datahigh(0)), abs(self.dataclose(-1)  - self.datalow(0) ))        
        self.ATR = bt.indicators.SimpleMovingAverage(self.TR, period=14, subplot=True)       
        # 唐奇安通道上轨突破、唐奇安通道下轨突破       
        self.CrossoverHi = bt.ind.CrossOver(self.dataclose(0), self.DonchianHi)        
        self.CrossoverLo = bt.ind.CrossOver(self.dataclose(0), self.DonchianLo)    
        
    def notify_order(self, order):        
        if order.status in [order.Submitted, order.Accepted]:            
            return

        if order.status in [order.Completed]:            
            if order.isbuy():               
                self.log(                    
                'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %                   
                (order.executed.price,
                order.executed.value,
                order.executed.comm),doprint=True)              
                self.buyprice = order.executed.price              
                self.buycomm = order.executed.comm            
            else:             
                self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %                        
                     (order.executed.price,
                     order.executed.value,
                     order.executed.comm),doprint=True)                             
                self.bar_executed = len(self)       
        elif order.status in [order.Canceled, order.Margin, order.Rejected]:           
            self.log('Order Canceled/Margin/Rejected')        
        self.order = None    

    def notify_trade(self, trade):      
        if not trade.isclosed:
            return        
        self.log('OPERATION PROFIT, GROSS %.2f, NET %.2f' % (trade.pnl, trade.pnlcomm)) 

    def next(self): 
        if self.order:
            return        
        #入场        
        if self.CrossoverHi > 0 and self.buytime == 0:                                 
            self.newstake = self.broker.getvalue() * 0.01 / self.ATR            
            self.newstake = int(self.newstake / 100) * 100                             
            self.sizer.p.stake = self.newstake            
            self.buytime = 1            
            self.order = self.buy()        
        #加仓        
        elif self.datas[0].close >self.buyprice+0.5*self.ATR[0] and self.buytime > 0 and self.buytime < 5:           
            self.newstake = self.broker.getvalue() * 0.01 / self.ATR            
            self.newstake = int(self.newstake / 100) * 100            
            self.sizer.p.stake = self.newstake            
            self.order = self.buy()           
            self.buytime = self.buytime + 1        
        #出场        
        elif self.CrossoverLo < 0 and self.buytime > 0:            
            self.order = self.sell()            
            self.buytime = 0        
        #止损        
        elif self.datas[0].close < (self.buyprice - 2*self.ATR[0]) and self.buytime > 0:           
            self.order = self.sell()
            self.buytime = 0   

    def stop(self):        
        self.log('(MA Period %2d) Ending Value %.2f' % (self.params.maperiod, self.broker.getvalue()), doprint=True)

if __name__ == '__main__':    
    # 创建主控制器    
    cerebro = bt.Cerebro()    
    # 加入策略    
    cerebro.addstrategy(TestStrategy)   
    # 准备股票日线数据,输入到backtrader    
    engine = create_engine('sqlite:////home/zhangjun/quanter/quant/test.sqlite')
    k_data_code='300017.SZ'
    k_data=pd.read_sql('select distinct * from k_data where ts_code=\'300017.SZ\' order by trade_date',engine)
    
    convert_datetime = lambda x: pd.to_datetime(str(x))
    k_data['trade_date'] = k_data['trade_date'].apply(convert_datetime)
    k_data.set_index(["trade_date"], inplace=True)  
    dataframe=k_data

    data = bt.feeds.PandasData(dataname=dataframe,fromdate=datetime.datetime(2020, 1, 1),  todate=datetime.datetime(2020, 12, 31))    
    cerebro.adddata(data)    
    # broker设置资金、手续费    
    cerebro.broker.setcash(100000.0)    
    cerebro.broker.setcommission(commission=0.001)
    # 设置买入策略    
    cerebro.addsizer(TestSizer)    
    print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())   
    # 启动回测    
    cerebro.run()    
    print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())    
    # 曲线绘图输出    
    cerebro.plot()
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值