1#!/usr/bin/env python 2# -*- coding: utf-8; py-indent-offset:4 -*- 3############################################################################### 4# 5# Copyright (C) 2017 Daniel Rodriguez 6# 7# This program is free software: you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation, either version 3 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>. 19# 20############################################################################### 21from __future__ import (absolute_import, division, print_function, 22 unicode_literals) 23 24import argparse 25import datetime 26 27import backtrader as bt 28 29 30class NYSE_2016(bt.TradingCalendar): 31 params = dict( 32 holidays=[ 33 datetime.date(2016, 1, 1), 34 datetime.date(2016, 1, 18), 35 datetime.date(2016, 2, 15), 36 datetime.date(2016, 3, 25), 37 datetime.date(2016, 5, 30), 38 datetime.date(2016, 7, 4), 39 datetime.date(2016, 9, 5), 40 datetime.date(2016, 11, 24), 41 datetime.date(2016, 12, 26), 42 ] 43 ) 44 45 46class St(bt.Strategy): 47 params = dict( 48 ) 49 50 def __init__(self): 51 pass 52 53 def start(self): 54 self.t0 = datetime.datetime.utcnow() 55 56 def stop(self): 57 t1 = datetime.datetime.utcnow() 58 print('Duration:', t1 - self.t0) 59 60 def prenext(self): 61 self.next() 62 63 def next(self): 64 print('Strategy len {} datetime {}'.format( 65 len(self), self.datetime.date()), end=' ') 66 67 print('Data0 len {} datetime {}'.format( 68 len(self.data0), self.data0.datetime.date()), end=' ') 69 70 if len(self.data1): 71 print('Data1 len {} datetime {}'.format( 72 len(self.data1), self.data1.datetime.date())) 73 else: 74 print() 75 76 77def runstrat(args=None): 78 args = parse_args(args) 79 80 cerebro = bt.Cerebro() 81 82 # Data feed kwargs 83 kwargs = dict() 84 85 # Parse from/to-date 86 dtfmt, tmfmt = '%Y-%m-%d', 'T%H:%M:%S' 87 for a, d in ((getattr(args, x), x) for x in ['fromdate', 'todate']): 88 if a: 89 strpfmt = dtfmt + tmfmt * ('T' in a) 90 kwargs[d] = datetime.datetime.strptime(a, strpfmt) 91 92 YahooData = bt.feeds.YahooFinanceData 93 if args.offline: 94 YahooData = bt.feeds.YahooFinanceCSVData # change to read file 95 96 # Data feed 97 data0 = YahooData(dataname=args.data0, **kwargs) 98 cerebro.adddata(data0) 99 100 d1 = cerebro.resampledata(data0, 101 timeframe=getattr(bt.TimeFrame, args.timeframe)) 102 d1.plotinfo.plotmaster = data0 103 d1.plotinfo.sameaxis = True 104 105 if args.pandascal: 106 cerebro.addcalendar(args.pandascal) 107 elif args.owncal: 108 cerebro.addcalendar(NYSE_2016) 109 110 # Broker 111 cerebro.broker = bt.brokers.BackBroker(**eval('dict(' + args.broker + ')')) 112 113 # Sizer 114 cerebro.addsizer(bt.sizers.FixedSize, **eval('dict(' + args.sizer + ')')) 115 116 # Strategy 117 cerebro.addstrategy(St, **eval('dict(' + args.strat + ')')) 118 119 # Execute 120 cerebro.run(**eval('dict(' + args.cerebro + ')')) 121 122 if args.plot: # Plot if requested to 123 cerebro.plot(**eval('dict(' + args.plot + ')')) 124 125 126def parse_args(pargs=None): 127 parser = argparse.ArgumentParser( 128 formatter_class=argparse.ArgumentDefaultsHelpFormatter, 129 description=( 130 'Trading Calendar Sample' 131 ) 132 ) 133 134 parser.add_argument('--data0', default='YHOO', 135 required=False, help='Data to read in') 136 137 parser.add_argument('--offline', required=False, action='store_true', 138 help='Read from disk with same name as ticker') 139 140 # Defaults for dates 141 parser.add_argument('--fromdate', required=False, default='2016-01-01', 142 help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') 143 144 parser.add_argument('--todate', required=False, default='2016-12-31', 145 help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') 146 147 parser.add_argument('--cerebro', required=False, default='', 148 metavar='kwargs', help='kwargs in key=value format') 149 150 parser.add_argument('--broker', required=False, default='', 151 metavar='kwargs', help='kwargs in key=value format') 152 153 parser.add_argument('--sizer', required=False, default='', 154 metavar='kwargs', help='kwargs in key=value format') 155 156 parser.add_argument('--strat', required=False, default='', 157 metavar='kwargs', help='kwargs in key=value format') 158 159 parser.add_argument('--plot', required=False, default='', 160 nargs='?', const='{}', 161 metavar='kwargs', help='kwargs in key=value format') 162 163 pgroup = parser.add_mutually_exclusive_group(required=False) 164 pgroup.add_argument('--pandascal', required=False, action='store', 165 default='', help='Name of trading calendar to use') 166 167 pgroup.add_argument('--owncal', required=False, action='store_true', 168 help='Apply custom NYSE 2016 calendar') 169 170 parser.add_argument('--timeframe', required=False, action='store', 171 default='Weeks', choices=['Weeks', 'Months', 'Years'], 172 help='Timeframe to resample to') 173 174 return parser.parse_args(pargs) 175 176 177if __name__ == '__main__': 178 runstrat() 179