J
# -*- coding: utf-8 -*-
###############################################################################
#
# Copyright (C) 2019 http://www.backtrader.cn 3952700@qq.com
#
###############################################################################
from __future__ import (absolute_import, division, print_function,
unicode_literals)
import datetime # For datetime objects
import backtrader as bt
from backtrader import (date2num, num2date, time2num, TimeFrame, dataseries,
metabase)
from LoadData import get_stock_code_daily,get_future_code_daily,get_future_code_min,get_future_data
# Create a Stratey
class HedgeSameInstrumentStrategy1(bt.Strategy):
params = (
# ('exitbars', 5),
('maperiod', 25),
('printlog', True),
)
def log(self, txt, dt=None, doprint=False):
''' Logging function fot this strategy'''
if self.params.printlog or doprint:
dt = dt or self.datas[0].datetime.date(0)
print(len(self), ' HedgeSameInstrumentStrategy1 %s, %s' % (dt.isoformat(), txt))
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
# To keep track of pending orders and buy price/commission
self.order = None
self.buyprice = None
self.buycomm = None
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker - Nothing to do
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))
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else: # Sell
self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
# Write down: no pending order
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):
# Simply log the closing price of the series from the reference
# self.log('Close, %.2f, %.2f' % (self.dataclose[0] , 0))
# Check if an order is pending ... if yes, we cannot send a 2nd one
if self.order:
return
if len(self) == 10:
self.order = self.buy(data=self.data0, exectype=bt.Order.Market)
if len(self) == 101:
self.order = self.close(data=self.data0, exectype=bt.Order.Market)
def stop(self):
# cash is amount of money on the broker's account, value is cash available plus cost of all open positions
# Return is equal to value minus starting capital.
# If all positions are closed than, yes, value and cash should be the same.
# if short position still open, cash = value + abs(position value)
self.log('(MA Period %2d) Ending Value %.2f' %
(self.params.maperiod, self.broker.getvalue()), doprint=True)
class HedgeSameInstrumentStrategy2(bt.Strategy):
params = (
# ('exitbars', 5),
('maperiod', 25),
('printlog', True),
)
def log(self, txt, dt=None, doprint=False):
''' Logging function fot this strategy'''
if self.params.printlog or doprint:
dt = dt or self.datas[0].datetime.date(0)
print(len(self), ' HedgeSameInstrumentStrategy2 %s, %s' % (dt.isoformat(), txt))
def __init__(self):
# Keep a reference to the "close" line in the data[0] dataseries
self.dataclose = self.datas[0].close
# To keep track of pending orders and buy price/commission
self.order = None
self.buyprice = None
self.buycomm = None
def notify_order(self, order):
if order.status in [order.Submitted, order.Accepted]:
# Buy/Sell order submitted/accepted to/by broker - Nothing to do
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))
self.buyprice = order.executed.price
self.buycomm = order.executed.comm
else: # Sell
self.log('SELL EXECUTED, Price: %.2f, Cost: %.2f, Comm %.2f' %
(order.executed.price,
order.executed.value,
order.executed.comm))
self.bar_executed = len(self)
elif order.status in [order.Canceled, order.Margin, order.Rejected]:
self.log('Order Canceled/Margin/Rejected')
# Write down: no pending order
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):
# Simply log the closing price of the series from the reference
# self.log('Close, %.2f, %.2f' % (self.dataclose[0] , 0))
# Check if an order is pending ... if yes, we cannot send a 2nd one
if self.order:
return
if len(self) == 55:
self.order = self.sell(data=self.data1, exectype=bt.Order.Market)
if len(self) == 205:
self.order = self.close(data=self.data1, exectype=bt.Order.Market)
def stop(self):
# cash is amount of money on the broker's account, value is cash available plus cost of all open positions
# Return is equal to value minus starting capital.
# If all positions are closed than, yes, value and cash should be the same.
# if short position still open, cash = value + abs(position value)
self.log('(MA Period %2d) Ending Value %.2f' %
(self.params.maperiod, self.broker.getvalue()), doprint=True)
if __name__ == '__main__':
cerebro = bt.Cerebro(maxcpus = 1 )
cerebro.broker.setcash(100000.0)
# Add a strategy
cerebro.addstrategy(HedgeSameInstrumentStrategy1)
cerebro.addstrategy(HedgeSameInstrumentStrategy2)
# Datas are in a subfolder of the samples. Need to find where the script is
# because it could have been called from anywhere
# modpath = os.path.dirname(os.path.abspath(sys.argv[0]))
filePath1 = r"D:\BackTraderCN\Class1\stock_data\600827.csv"
data_1 = get_stock_code_daily(filePath1)
start_dt1 = data_1.index[0]
end_dt1 = data_1.index[-1]
filePath2 = r"D:\BackTraderCN\Class1\stock_data\600827.csv"
data_2 = get_stock_code_daily(filePath2)
start_dt2 = data_2.index[0]
end_dt2 = data_2.index[-1]
if start_dt1 < start_dt2:
start_dt1 = start_dt2
if end_dt1 > end_dt2:
end_dt1 = end_dt2
# end_dt = datetime.datetime(year=2019, month=7, day=8)
data1 = bt.feeds.PandasData(dataname=data_1,
fromdate=start_dt1,
todate=end_dt1,
timeframe=TimeFrame.Days,
)
data2 = bt.feeds.PandasData(dataname=data_2,
fromdate=start_dt1,
todate=end_dt1,
timeframe=TimeFrame.Days,
)
# Add the 1st data to cerebro
cerebro.adddata(data1)
# Add the 2nd data to cerebro
cerebro.adddata(data2)
# Add a FixedSize sizer according to the stake
cerebro.addsizer(bt.sizers.FixedSize, stake=10)
print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue())
# Set the commission
cerebro.broker.setcommission(commission=0.0)
cerebro.run()
print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue())
# cerebro.plot(style='candlestick')
cerebro.plot()