加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

Backtrader量化平台教程(一):backtrader的整体框架

(2017-06-06 18:52:42)
分类: 指标自动化

    前面两篇文章,讲了大致的框架,接下来涉及的更多的是细节。本文介绍了backtrader中的indicator,并讲述了一些别的细节的代码。所谓indicator就是技术指标,比如MA,RSI

1.预备

    在介绍backtrader的indicator之前,我们先配置一下我们的平台,也就是cerebro。

 

[python] view plain copy
  1. if __name__ == '__main__' 
  2.     Create cerebro entity  
  3.     cerebro bt.Cerebro()  
  4.     Add strategy  
  5.     cerebro.addstrategy(TestStrategy)  
  6.     本地数据,笔者用Wind获取的东风汽车数据以csv形式存储在本地。  
  7.     parase_dates True是为了读取csv为dataframe的时候能够自动识别datetime格式的字符串,big作为index  
  8.     注意,这里最后的pandas要符合backtrader的要求的格式  
  9.     dataframe pd.read_csv('dfqc.csv'index_col=0parse_dates=True 
  10.     dataframe['openinterest'0  
  11.     data bt.feeds.PandasData(dataname=dataframe,  
  12.                             fromdate datetime.datetime(201511),  
  13.                             todate datetime.datetime(20161231 
  14.                              
  15.     Add the Data Feed to Cerebro  
  16.     cerebro.adddata(data)  
  17.     Set our desired cash start  
  18.     cerebro.broker.setcash(100.0 
  19.     设置每笔交易交易的股票数量  
  20.     cerebro.addsizer(bt.sizers.FixedSize, stake=10 
  21.     Set the commission  
  22.     cerebro.broker.setcommission(commission=0.0 
  23.     Print out the starting conditions  
  24.     print('Starting Portfolio Value: %.2f' cerebro.broker.getvalue())  
  25.     Run over everything  
  26.     cerebro.run()  
  27.     Print out the final result  
  28.     print('Final Portfolio Value: %.2f' cerebro.broker.getvalue())  
  29.     cerebro.plot()  
    这里出现了

 

 

[python] view plain copy
  1. 设置每笔交易交易的股票数量  
  2.     cerebro.addsizer(bt.sizers.FixedSize, stake=10 
    这个函数,用来设置每次下单的时候买卖的股票数量。
[python] view plain copy
  1. bt.sizers.FixedSize  
    就告诉平台,我们是每次买卖股票数量固定的,stake=10就是10股。当然,实际过程中,我们不可能如此简单的制定买卖的数目,而是要根据一定的规则,这就需要自己写一个sizers,这是后话。

 

2.我们的策略

2.1策略的生命周期

策略的完整生命周期如下:

0.__init__

    这个是肯定的,任何类在生成的时候都是先调用这一初始化构造函数。也就是说,在实例生成的时候,这个函数将被调用。

1.Birth: start

    start方法在cerebro告诉strategy,是时候开始行动了,也就是说,通知策略激活的时候被调用。

2.Childhood: prenext

    有些技术指标,比如我们提到的MA,存在一个窗口,也就是说,需要n天的数据才能产生指标,那么在没有产生之前呢?这个prenext方法就会被自动调用。
3.Adulthood: next
这个方法是最核心的,就是每次移动到下一的时间点,策略将会调用这个方法,所以,策略的核心往往都是写在这个方法里的。

4.Death: stop

    策略的生命周期结束,cerebro把这一策略退出。

2.2策略当中的回调函数

    Strategy 类就像真实世界的交易员一样,当交易执行的时候,他会得到一些消息,譬如order是否执行,一笔trader赚了多少钱,等等。这些消息都将在Strategy类中通过回调函数被得以知晓。这些回调函数如下:

notify_order(order):下的单子,order的任何状态变化都将引起这一方法的调用

notify_trade(trade):任何一笔交易头寸的改变都将调用这一方法

notify_cashvalue(cash, value):任何现金和资产组合的变化都将调用这一方法 
notify_store(msg, *args, **kwargs):可以结合cerebro类进行自定义方法的调用

那么问题接踵而至,这里我们只关注前2种方法中监测对象的可变化方式。

trade指的是一笔头寸,trdae是open的状态指当前时刻,这一标的的头寸从0变到某一非零值。trade是closed则刚好相反。
    trade大概有如下常用属性
ref: 唯一id
size (int): trade的当前头寸
price (float): trade资产的当前价格
value (float): trade的当前价值
commission (float): trade的累计手续费
pnl (float): trade的当前pnl
pnlcomm (float): trade的当前pnl减去手续费
isclosed (bool): 当前时刻trade头寸是否归零
isopen (bool): 新的交易更新了trade
justopened (bool): 新开头寸
dtopen (float): trade open的datetime
dtclose (float): trade close的datetime

Orders

    order是strategy发出的指令,让cerebro去执行。
    strategy自身有buy, sell and close方法来生成order,cancel方法来取消一笔order。下单的方式有很多,后续会介绍,这里主要讲回调函数中,咱们可以获得哪些信息。
order.status可以返回order的当前状态

order.isbuy可以获得这笔order是否是buy

order.executed.price
order.executed.value
order.executed.comm

分别可以获得执行order的价格,总价,和手续费

2.3代码

 

[python] view plain copy
  1. class TestStrategy(bt.Strategy):  
  2.     params  
  3.         ('maperiod'15),  
  4.      
  5.   
  6.     def log(selftxt, dt=None):  
  7.         ''''' Logging function fot this strategy'''  
  8.         dt dt or self.datas[0].datetime.date(0 
  9.         print('%s, %s' (dt.isoformat(), txt))  
  10.   
  11.     def __init__(self):  
  12.         Keep reference to the "close" line in the data[0] dataseries  
  13.         self.dataclose self.datas[0].close  
  14.   
  15.         To keep track of pending orders and buy price/commission  
  16.         self.order None  
  17.         self.buyprice None  
  18.         self.buycomm None  
  19.   
  20.         Add MovingAverageSimple indicator  
  21.         self.sma bt.indicators.SimpleMovingAverage(  
  22.             self.datas[0], period=self.params.maperiod)  
  23.     def start(self):  
  24.         print("the world call me!" 
  25.   
  26.     def prenext(self):  
  27.         print("not mature" 
  28.   
  29.     def notify_order(selforder):  
  30.         if order.status in [order.Submitted, order.Accepted]:  
  31.             Buy/Sell order submitted/accepted to/by broker Nothing to do  
  32.             return  
  33.   
  34.         Check if an order has been completed  
  35.         Attention: broker could reject order if not enougth cash  
  36.         if order.status in [order.Completed]:  
  37.             if order.isbuy():  
  38.                 self.log(  
  39.                     'BUY EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f'  
  40.                     (order.executed.price,  
  41.                      order.executed.value,  
  42.                      order.executed.comm))  
  43.   
  44.                 self.buyprice order.executed.price  
  45.                 self.buycomm order.executed.comm  
  46.             else Sell  
  47.                 self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f'  
  48.                          (order.executed.price,  
  49.                           order.executed.value,  
  50.                           order.executed.comm))  
  51.   
  52.             self.bar_executed len(self 
  53.   
  54.         elif order.status in [order.Canceled, order.Margin, order.Rejected]:  
  55.             self.log('Order Canceled/Margin/Rejected' 
  56.   
  57.         self.order None  
    大家可以看到打印出来的结果中,有start和prenext,最后当然也有death

 

http://img.blog.csdn.net/20170421110826650?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXRseXg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

3.Backtrader的indicator

    上面的代码中,我们单独拿出init这一部分,因为这里涉及了一个新的东西,indicator,也是本文想重点介绍的。

 

[python] view plain copy
  1. def __init__(self):  
  2.     Keep reference to the "close" line in the data[0] dataseries  
  3.     self.dataclose self.datas[0].close  
  4.   
  5.     To keep track of pending orders and buy price/commission  
  6.     self.order None  
  7.     self.buyprice None  
  8.     self.buycomm None  
  9.   
  10.     Add MovingAverageSimple indicator  
  11.     self.sma bt.indicators.SimpleMovingAverage(  
  12.         self.datas[0], period=self.params.maperiod)  
    这里的最后,我们使用了一个backtrader内置的indicator,后续我们将尝试自己编写一个indicator。


0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有