Need Help on Backtesting with Oanda Data
-
I need help on few problems I had while using Oanda data.
Before anything, I tried
oandatest.py
and it worked fine.python oandatest.py --token XXXX --account 0000 --data0 EUR_USD --timeframe Minutes --historical
gave me
-------------------------------------------------- Strategy Created -------------------------------------------------- -- Contract Details: {'instrument': 'EUR_USD', 'displayName': 'EUR/USD', 'pip': '0.0001', 'maxTradeUnits': 10000000} Datetime, Open, High, Low, Close, Volume, OpenInterest, SMA ***** DATA NOTIF: DELAYED Data0, 0001, 736732.538194, 2018-02-07T12:55:00.000000, 1.234450, 1.234540, 1.234320, 1.234320, 46, 0, nan . . . Data0, 0500, 736633.366667, 2017-10-31T08:48:00.000000, 1.164445, 1.164460, 1.164300, 1.164325, 18, 0, 1.164377 ***** DATA NOTIF: DISCONNECTED
Then I tried to test the strategy from "Quickstart"
import backtrader as bt from datetime import datetime # For datetime objects #Oanda Account Info api_key = "XXXX" account_number = "0000" # Create a Stratey class TestStrategy(bt.Strategy): def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.datas[0].datetime.date(0) print('%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 def next(self): # Simply log the closing price of the series from the reference self.log('Close, %.2f' % self.dataclose[0]) if __name__ == '__main__': cerebro = bt.Cerebro() cerebro.addstrategy(TestStrategy) oandastore = bt.stores.OandaStore(token=api_key, account=account_number, practice=True) cerebro.broker = oandastore.getbroker() data = oandastore.getdata( dataname = "USD_JPY", timeframe = bt.TimeFrame.Minutes, compression = 30, fromdate = datetime(2017,11,1), todate=datetime(2017,11,30) ) # Add data cerebro.adddata(data) print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.run() print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Finally plot the end results cerebro.plot(style="candle")
It worked but with two problems:
One problem iscompression
of 30 and below shows no log.Starting Portfolio Value: 0.00 position for instrument: USD_JPY Final Portfolio Value: 96053.55
But
compression
of 60 and above does show logs.Starting Portfolio Value: 0.00 position for instrument: USD_JPY 2017-11-01, Close, 113.88 2017-11-01, Close, 113.90 . . . 2017-11-29, Close, 112.00 2017-11-30, Close, 111.98 Final Portfolio Value: 96053.55
Is there a problem with my coding or is it the practice server thing?
Second problem is that, as you can see from above logs, "Starting Portfolio Value:" is 0 and "Final Portfolio Value:" shows the amount of USD I have on Oanda account. Aren't those two supposed to be same?
Lastly, when I change the strategy to the next one (
compression=60
and keeping everything else same),class TestStrategy(bt.Strategy): def log(self, txt, dt=None): ''' Logging function fot this strategy''' dt = dt or self.datas[0].datetime.date(0) print('%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 self.order = 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 # Check if an order has been completed # Attention: broker could reject order if not enough cash if order.status in [order.Completed]: if order.isbuy(): self.log('BUY EXECUTED, %.2f' % order.executed.price) elif order.issell(): self.log('SELL EXECUTED, %.2f' % order.executed.price) 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 next(self): # Simply log the closing price of the series from the reference self.log('Close, %.2f' % self.dataclose[0]) # Check if an order is pending ... if yes, we cannot send a 2nd one if self.order: return # Check if we are in the market if not self.position: # Not yet ... we MIGHT BUY if ... if self.dataclose[0] < self.dataclose[-1]: # current close less than previous close if self.dataclose[-1] < self.dataclose[-2]: # previous close less than the previous close # BUY, BUY, BUY!!! (with default parameters) self.log('BUY CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.buy() else: # Already in the market ... we might sell if len(self) >= (self.bar_executed + 5): # SELL, SELL, SELL!!! (with all possible default parameters) self.log('SELL CREATE, %.2f' % self.dataclose[0]) # Keep track of the created order to avoid a 2nd order self.order = self.sell()
I get an error of
AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Strateg' object has no attribute 'bar_executed'
What do I need to do?
-
@vensaiten said in Need Help on Backtesting with Oanda Data:
One problem is compression of 30 and below shows no log.
This may be due to a bug in the
OandaData
feed, which was using the same code to retrieve 5 minutes bars as to retrieve 10, 15 and 30 minutes bars. Recalling things, the codes were copied verbatim from Oanda's reference documentation, but they are different today. Regardless of the source it has been pushed.@vensaiten said in Need Help on Backtesting with Oanda Data:
I get an error of AttributeError: 'Lines_LineSeries_LineIterator_DataAccessor_Strateg' object has no attribute 'bar_executed' What do I need to do?
Initialize
self.bar_executed
somewhere in your code.