Can't seem to get Renko to show up correctly on forward testing
-
Hi there so I basically took this script https://www.backtrader.com/blog/posts/2017-06-26-renko-bricks/renko-bricks/ and built some basic logic on top of it for testing.
Algorithm is as follows:
- only take longs
- when you get 2 green Renko bars, go long
- after that, when 2 red Renko bars show up, close the long position
It seems to work as expected in backtesting, but when forward testing on a live data feed, I can't seem to make any sense of the data and the results returned.
Here you can see data feed claims to be on a long green streak, so it buys in, however the chart on Oanda shows the streak is actually red, which is the wrong time to buy in. The data feed also acts like the price keeps going up by the box size so there are a ton of bars being formed or something, when there was in fact only 1. I am proud to say this bot loses 100% of the time! 😂
On Oanda it is using Traditional, 0.01 settings for the box size, so I assume this is similar to these settings for the program:
renko.py --renko size=0.01 --plot
but as you can see, the prices are off by a tenth or so, so I have no idea how to make them match up.
Code:
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import datetime import pandas as pd import backtrader as bt import alpaca_backtrader_api import btoandav20 StoreCls = btoandav20.stores.OandaV20Store DataCls = btoandav20.feeds.OandaV20Data # BrokerCls = btoandav20.brokers.OandaV20Broker from keys.keys import key_id, secret_key, base_url class St(bt.Strategy): params = dict( ) def __init__(self): # for d in self.datas: # bt.ind.RSI(d) self.c = self.datas[0].close self.o = self.datas[0].open self.streak = 0 self.required_streak = 2 def next(self): if self.c > self.o: if self.streak > 0: self.streak += 1 else: self.streak = 1 elif self.c < self.o: if self.streak < 0: self.streak -= 1 else: self.streak = -1 txt = list() txt.append('Data0') txt.append('%04d' % len(self.data0)) dtfmt = '%m-%d %H:%M:%S' txt.append('%s' % self.data.datetime.datetime(0).strftime(dtfmt)) txt.append('C {:2f}'.format(self.data.close[0])) txt.append('O {:2f}'.format(self.data.open[0])) txt.append('{}'.format(self.streak)) print(', '.join(txt)) if not self.position: if self.c > self.o and self.streak >= self.required_streak: print('BUY') self.buy() elif self.position: if self.c < self.o and self.streak <= -selfrequired_streakthres: print('CLOSE') self.close() def runstrat(args=None): args = parse_args(args) cerebro = bt.Cerebro() # Data feed kwargs kwargs = dict() # Parse from/to-date dtfmt, tmfmt = '%Y-%m-%d', 'T%H:%M:%S' for a, d in ((getattr(args, x), x) for x in ['fromdate', 'todate']): if a: strpfmt = dtfmt + tmfmt * ('T' in a) kwargs[d] = datetime.datetime.strptime(a, strpfmt) # data0 = bt.feeds.BacktraderCSVData(dataname=args.data0, **kwargs) # ALPACA # store = alpaca_backtrader_api.AlpacaStore( # key_id=key_id, # secret_key=secret_key, # paper=True, # ) # DataFactory = store.getdata # data0 = DataFactory(dataname='TSLA', # # timeframe=bt.TimeFrame.Days, # timeframe=bt.TimeFrame.Minutes, # compression=1, # # fromdate=pd.Timestamp.now(), # # fromdate=pd.Timestamp.today(), # # fromdate=pd.Timestamp(2020,5,1), # # todate=pd.Timestamp(2020,5,7), # historical=False, # ) # OANDA store = btoandav20.stores.OandaV20Store( token='mytoken', account='myaccount', practice=True, ) DataFactory = store.getdata data0 = DataFactory(dataname='USD_JPY', timeframe=bt.TimeFrame.Minutes, historical=False, backfill_start=False, ) fkwargs = dict() fkwargs.update(**eval('dict(' + args.renko + ')')) if not args.dual: data0.addfilter(bt.filters.Renko, **fkwargs) cerebro.adddata(data0) else: cerebro.adddata(data0) data1 = data0.clone() data1.addfilter(bt.filters.Renko, **fkwargs) cerebro.adddata(data1) # Broker # cerebro.broker = bt.brokers.BackBroker(**eval('dict(' + args.broker + ')')) broker = store.getbroker() cerebro.setbroker(broker) # Sizer # cerebro.broker.setcash(100000) cerebro.addsizer(bt.sizers.FixedSize, stake=1) # Strategy cerebro.addstrategy(St, **eval('dict(' + args.strat + ')')) # Execute kwargs = dict(stdstats=True) kwargs.update(**eval('dict(' + args.cerebro + ')')) cerebro.run(**kwargs) if args.plot: # Plot if requested to kwargs = dict(style='candle') kwargs.update(**eval('dict(' + args.plot + ')')) # cerebro.plot() cerebro.plot(style='candle', barup='green', bardown='maroon') def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description=( 'Renko bricks sample' ) ) parser.add_argument('--data0', default='data/TSLA.csv', required=False, help='Data to read in') # Defaults for dates parser.add_argument('--fromdate', required=False, default='', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--todate', required=False, default='', help='Date[time] in YYYY-MM-DD[THH:MM:SS] format') parser.add_argument('--cerebro', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--broker', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--sizer', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--strat', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--plot', required=False, default='', nargs='?', const='{}', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--renko', required=False, default='', metavar='kwargs', help='kwargs in key=value format') parser.add_argument('--dual', required=False, action='store_true', help='put the filter on a second version of the data') return parser.parse_args(pargs) if __name__ == '__main__': runstrat()
Any help would be greatly appreciated! Just trying to get something, anything simple working here with Renko bars!
-
Please ignore this typo
@booboothefool said in Can't seem to get Renko to show up correctly on forward testing:
if self.c < self.o and self.streak <= -selfrequired_streakthres:
if self.c < self.o and self.streak <= -self.required_streak:
e.g.
2 green bars = +2
2 red bars = -2You get the idea. Thanks!