Running a backtest from a single class
-
Hi,
I am doing a web project using Backtrader for my class. Basically, the web page allows users to input variables such as initial cash, indicator values, risk management values, etc, and run a simple backtest with Backtrader from the web itself.
As far as I know, to run a simple strategy you'll need to
- Instantiate Cerebro
- cerebro.broker.addstrategy(strategy)
- Add Data and set cash
- cerebro.run()
To backtest from the web I have to run the backtest from a single class. I named the class "Simulate" and have decided to insert steps 1-4 into the class' __ init __
class Simulate: def __init__(self, initialCash): self.cash = initialCash self.cerebro = bt.Cerebro() #self.TestStrategy = TestStrategy() self.cerebro.addstrategy(TestStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/Misc/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2000, 12, 31), reverse=False) self.cerebro.adddata(data) self.cerebro.broker.setcash(self.cash) print('Starting Portfolio Value: %.2f' % self.cerebro.broker.getvalue()) self.cerebro.run() print('Final Portfolio Value: %.2f' % self.cerebro.broker.getvalue()) self.cerebro.plot(style="candlestick", barup='green', bardown='red')
The bt.strategy class that I will be using is outside of the "Simulate" class.
class Simulate: ... class TestStrategy(bt.Strategy): ...
Let's say in this example I wanted to log the "Initial Cash" every time I place a Buy order. This "Initial Cash" is supposed to be in Simulate's __ init __
class Simulate: def __init__(self, initialCash): self.cash = initialCash
and to log
- Buy Create's Close
- Current Cash
- Initial Cash
self.log('BUY CREATE, %.2f, Cash: %.2f, Initial Cash:%.2f' % ( self.dataclose[0],self.cerebro.broker.getcash(), self.cash))
How do I get the values from Simulate class to the strategy class, I've been trying to solve this for days, but just can't figure it out. Please help :c
.
.
.
Here is the full code(the strategy is an example strategy from the quickstart docs):from __future__ import (absolute_import, division, print_function, unicode_literals) import backtrader as bt import datetime class Simulate: def __init__(self, initialCash): self.cash = initialCash self.cerebro = bt.Cerebro() #self.TestStrategy = TestStrategy() self.cerebro.addstrategy(TestStrategy) data = bt.feeds.YahooFinanceCSVData( dataname="datas/Misc/orcl-1995-2014.txt", fromdate=datetime.datetime(2000, 1, 1), todate=datetime.datetime(2000, 12, 31), reverse=False) self.cerebro.adddata(data) self.cerebro.broker.setcash(self.cash) print('Starting Portfolio Value: %.2f' % self.cerebro.broker.getvalue()) self.cerebro.run() print('Final Portfolio Value: %.2f' % self.cerebro.broker.getvalue()) self.cerebro.plot(style="candlestick", barup='green', bardown='red') class TestStrategy(bt.Strategy): def log(self, txt, dt=None): dt = dt or self.datas[0].datetime.date(0) print('%s, %s' % (dt.isoformat(), txt)) def __init__(self): self.dataclose = self.datas[0].close 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, %.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') self.order = None def next(self): self.log('Close, %.2f' % self.dataclose[0]) if self.dataclose[0] < self.dataclose[-1]: if self.dataclose[-1] < self.dataclose[-2]: self.log('BUY CREATE, %.2f, Cash: %.2f, Initial Cash:%.2f' % ( self.dataclose[0],self.cerebro.broker.getcash(), self.cash)) self.buy() Simulate(100000)
-
i got it!
I insert few functions to call the values from bt.cerebro to mimic cerebro.broker.getcash()
but any other solutions are welcome!