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()
TURTLE.py
最新推荐文章于 2023-10-10 20:15:48 发布