backtrader期权回测框架
生活随笔
收集整理的這篇文章主要介紹了
backtrader期权回测框架
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
使用backtrader數(shù)據(jù)進行回測,數(shù)據(jù)源來自于交易所爬取。
效果還行,我相信各位通過這個的框架學(xué)習(xí),會對backtrader的應(yīng)用有更深的領(lǐng)悟。包括數(shù)據(jù)的連接,新指標(biāo)的加入。
導(dǎo)入框架:
__future__ import (absolute_import, division, print_function, unicode_literals) import pymysql from sqlalchemy import create_engine import pandas as pd import numpy as np import pymssql import datetime import os.path import sys import backtrader as bt import pandas as pd import akshare as ak import matplotlib import matplotlib.pyplot as plt from backtrader.feeds import PandasData import datetime from backtrader.feeds import PandasData starttime = datetime.datetime.now() print(starttime)導(dǎo)入數(shù)據(jù)
df_read = pd.read_csv('option1.csv') #df_read = df_read[~df_read['ts_code'].isin([0])]date_value_list = []創(chuàng)建策略
class BollStrategy(bt.Strategy):# 可配置策略參數(shù)params = dict(poneplot=False, # 是否打印到同一張圖pstake=1, # 單筆交易股票數(shù)據(jù))def __init__(self):self.order = None# for i, d in enumerate(self.datas):# #跳過第一只股票data,第一只股票data作為主圖數(shù)據(jù)# if i == 0:# if self.p.poneplot:# d.plotinfo.plotmaster = self.datas[0]def prenext(self):# for i,d in enumerate(self.datas):# print(d._name)self.next()# 策略核心,根據(jù)條件執(zhí)行買賣交易指令(必選)def next(self):# 獲取當(dāng)天日期date = self.datas[0].datetime.date(0)# 獲取當(dāng)天valuevalue = self.broker.getvalue()# 存入列表date_value_list.append((date, value))for i,d in enumerate(self.datas):#self.log(f'收盤價,{self.datas[i].close[0]}')dt,dn = self.datetime.date(), d._name #獲取時間和股票代碼print(self.datas[i].rt[0])if self.order:returnpos = self.getposition(d).sizeif not pos:if self.datas[i].close[0] > 0:self.log(d._name, 'SELL Create, %2f' %self.datas[i].close[0])self.order = self.sell(d , size=self.p.pstake)elif self.datas[i].close[0] == 0 or self.datas[i].close[0] > pos.price * 2 or self.datas[i].rt[0] == 0 :self.log(d._name, 'CLOSE Create, %2f' % self.datas[i].close[0])self.order = self.close(d , size= self.p.pstake)#pass# print(self.datetime.date())# for i, d in enumerate(self.datas):# pos = self.getposition(d)# if not len(pos):# if d.close[0]>0:# self.sell(d,size= self.p.pstake)# elif d.close[0] ==0 or d.close[0] > pos.price * 2:# self.close(d,size= self.p.pstake)# for d in self.datas:# if len(d) == 0:# continue# else:# # 獲取當(dāng)天日期# date = self.datetime.date()# print(self.datas[0].datetime[0])# #print(date)# #查看持倉盈利情況# for i,d in enumerate(self.datas):# pos = self.getposition(d)# # if self.datas[i].close[0] < 0.05:# # self.close(d,size = self.params.pstake)# if len(pos):# # print('{}, 持倉:{}, 成本價:{}, 當(dāng)前價:{}, 盈虧:{:.2f}'.format(# # d._name, pos.size, pos.price, pos.adjbase, pos.size * (pos.adjbase - pos.price)),# # file=self.log_file)# # print('{}, 持倉:{}, 成本價:{}, 當(dāng)前價:{}, 盈虧:{:.2f}'.format(# # d._name, pos.size, pos.price, pos.adjbase, pos.size * (pos.adjbase - pos.price)),# # )# if self.datas[i].close[0] == 0:# self.close(d,size=self.params.pstake)# # 獲取當(dāng)天value# value = self.broker.getvalue()## # 存入列表# date_value_list.append((date, value))## for i,d in enumerate(self.datas):# #if self.datas[i].close[0] > 0.01:# try:# if self.datas[i].close[0] > 0:# #print('buy',d.close[0])# self.sell(data = d, size=self.params.pstake)# #print(d._name)# #order.addinfo(ticker=d._name)# #print(d._name)# # else:# # #print('sell',d.close[0])# # self.close(data = d, size=self.params.pstake)# # #order.addinfo(ticker=d._name)# # #print(d._name)# except:# pass#交易記錄日志def log(self,txt,dt = None,doprint=False):dt = dt or self.datas[0].datetime.date(0)f = open("log.txt",'a')date = self.datas[0].datetime.date(0)f.write(f'{date},{txt}')f.write("\n")f.close()print(f'{txt}')# 記錄交易收益情況(可省略,默認不輸出結(jié)果)def notify_trade(self, trade):if not trade.isclosed:returnself.log(f'策略收益:\n毛收益 {trade.pnl:.2f}, 凈收益 {trade.pnlcomm:.2f}')# 訂單狀態(tài)變化時引擎會調(diào)用notify_order# 記錄交易執(zhí)行情況(可省略,默認不輸出結(jié)果)def notify_order(self, order):#print(order.getstatusname(order.status))if order.status in [order.Submitted, order.Accepted]:return# 如果交易已經(jīng)完成,顯示成交信息if order.status in [order.Completed]:if order.isbuy() or order.issell():self.log(f'買入:\n價格:{order.executed.price},\成本:{order.executed.value},\手續(xù)費:{order.executed.comm}')self.buyprice = order.executed.priceself.buycomm = order.executed.commelse:self.log(f'賣出:\n價格:{order.executed.price},\成本: {order.executed.value},\手續(xù)費{order.executed.comm}')self.bar_executed = len(self)elif order.status in [order.Canceled, order.Margin, order.Rejected]:self.log('交易失敗')self.order = None #回測結(jié)束后輸出結(jié)果(可省略,默認輸出結(jié)果)# def stop(self):# self.log('(MA均線: %2d日) 期末總資金 %.2f' %# (self.params.maperiod, self.broker.getvalue()), doprint=True)def stop(self):self.log('期末總資金 %.2f' %(self.broker.getvalue()), doprint=True)添加參數(shù)
#添加參數(shù) class ETFOptionPandasData(PandasData):# 新增兩條數(shù)據(jù)線lines = ('rt',)# 新增數(shù)據(jù)在dataframe中的位置,分別是第6列和第7列params = (('rt', 6),)調(diào)取數(shù)據(jù),放入cerebro
cerebro = bt.Cerebro() # 建立期權(quán)池 stk_pools = df_read['ts_code'].unique().tolist() # 獲取期權(quán)數(shù)據(jù) for stk_code in stk_pools:df = df_read[df_read['ts_code'] == stk_code]df.index = pd.to_datetime(df['datetime'])#print(df.head())#data = ETFOptionPandasData(dataname=df)df = df[['ts_code', 'open', 'high', 'low', 'close', 'volume','rt']]#print(df.head())data = ETFOptionPandasData(dataname = df,datetime = -1)cerebro.adddata(data, name = str(stk_code))運行策略,添加交易參數(shù)
cerebro.broker.setcash(10000000.0) cerebro.broker.setcommission(commission=1.62,margin = 2000,mult= 10000 ) cerebro.addstrategy(BollStrategy) cerebro.broker.set_coc(True)#設(shè)置以當(dāng)天收盤價成交 cerebro.run() #減少內(nèi)存。此設(shè)置會自動禁止數(shù)據(jù)預(yù)加載(preload)和指標(biāo)預(yù)計算(runonce),也禁止繪圖plot,因為內(nèi)存中數(shù)據(jù)不足以繪圖了。 for d in cerebro.datas:d.plotinfo.plot =False print('cash',cerebro.broker.getvalue())總結(jié)
以上是生活随笔為你收集整理的backtrader期权回测框架的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: btree索引和hash索引的区别(待更
- 下一篇: BC范式介绍