I am very new to this.
backtrader have a addwriter can write down some data,
cerebro.addwriter(bt.WriterFile, csv=True, out='outputfiles3\{}cerebro.csv'.format(ticker))
but buy and sell price always not match to the execute price.
so alternatively:
i did cerebro.addanalyzer(WritingAnalyzer)
before cerebro.run()
so I am trying to build the csv file with 'datetime','open','close','cash','value','position size'
but I don't know how to access those data. I can only point at current day close price with self.data[0]
I don't know how to do it right. I hope someone might able to give me some directions.
import backtrader as bt
from backtrader import Analyzer
import csv
class WritingAnalyzer(Analyzer):
def __init__(self):
def create_analysis(self):
self.counter = 0
print(self.counter)
with open('demo1.csv',mode='w') as csv_file:
fieldnames=['datetime','open','close','cash','value','position size']
writer = csv.DictWriter(csv_file, fieldnames=fieldnames)
writer.writeheader()
def next(self):
self.counter += 1
print('close price:',self.data[0], "counter:",self.counter,)
# the following line suppose to write into csv file but i dont know how to get most of the data.
bt.writer.writerow({'datetime': '??', 'open': '??', 'close': self.data[0],'cash':'??','value':'??','position size':'??'})
def stop(self):
print("SSSSSSSSSSSSSTTTTTTOOOOOOOOOOOOPPPPPPPPPP")
self.rets._close()
You need to handle your analyzer a bit differently. You can literally grab data at every bar and then have it available to you at the end.
Create a new analyzer, in my case I made:
class BarAnalysis(bt.analyzers.Analyzer):
In your analyzer in start you will create a new list.
def start(self):
self.rets = list()
Then in next you will add a list of data for each bar. I use a try statement just in case there are any data problems, but it's probably not necessary. Strategy
is included as as subclass and you can use its methods by calling self.strategy.getvalue()
as an example.
def next(self):
try:
self.rets.append(
[
self.datas[0].datetime.datetime(),
self.datas[0].open[0],
self.datas[0].high[0],
self.datas[0].low[0],
self.datas[0].close[0],
self.datas[0].volume[0],
self.strategy.getposition().size,
self.strategy.broker.getvalue(),
self.strategy.broker.getcash(),
]
)
except:
pass
Finally create a get_analysis
method that you can use to get your results at the end.
def get_analysis(self):
return self.rets
Add your analyzer to before running cerebro. You can name it whatever you want, we'll need the name to call the results.
cerebro.addanalyzer(BarAnalysis, _name="bar_data")
Make sure you provide a variable for the results of the cerebro.run() method so you can collect the results of the backtest.
strat = cerebro.run()
Finally, get the data out of strat and do as you wish with it. In this case I'm creating a dataframe and printing.
bar_data_res = strat[0].analyzers.bar_data.get_analysis()
df = pd.DataFrame(bar_data_res)
print(df)
And the printout looks like:
/home/runout/projects/rb_master/venv/bin/python /home/runout/projects/scratch/20210424_analyzer.py
0 1 2 ... 6 7 8
0 2020-01-02 23:59:59.999989 212.70 213.36 ... 0 10000.00 10000.00
1 2020-01-03 23:59:59.999989 210.81 213.28 ... 0 10000.00 10000.00
2 2020-01-06 23:59:59.999989 210.18 213.59 ... 0 10000.00 10000.00
3 2020-01-07 23:59:59.999989 213.11 214.13 ... 0 10000.00 10000.00
4 2020-01-08 23:59:59.999989 212.43 216.47 ... 0 10000.00 10000.00
.. ... ... ... ... .. ... ...
247 2020-12-23 23:59:59.999989 268.38 269.31 ... 1 10015.38 9747.25
248 2020-12-24 23:59:59.999989 267.76 269.67 ... 1 10016.48 9747.25
249 2020-12-28 23:59:59.999989 270.48 270.55 ... 1 10014.82 9747.25
250 2020-12-29 23:59:59.999989 268.30 268.78 ... 1 10011.78 9747.25
251 2020-12-30 23:59:59.999989 264.45 265.64 ... 1 10010.86 9747.25
[252 rows x 9 columns]
Process finished with exit code 0
The whole code looks like this:
import datetime
import backtrader as bt
import pandas as pd
class BarAnalysis(bt.analyzers.Analyzer):
def start(self):
self.rets = list()
def next(self):
try:
self.rets.append(
[
self.datas[0].datetime.datetime(),
self.datas[0].open[0],
self.datas[0].high[0],
self.datas[0].low[0],
self.datas[0].close[0],
self.datas[0].volume[0],
self.strategy.getposition().size,
self.strategy.broker.getvalue(),
self.strategy.broker.getcash(),
]
)
except:
pass
def get_analysis(self):
return self.rets
class Strategy(bt.Strategy):
params = (
("lowerband", 30),
("upperband", 70),
)
def __init__(self):
self.rsi = bt.ind.RSI(period=10)
def next(self):
if not self.position:
if self.rsi <= self.p.lowerband:
self.buy()
elif self.rsi >= self.p.upperband:
self.close()
if __name__ == "__main__":
cerebro = bt.Cerebro()
ticker = "HD"
data = bt.feeds.YahooFinanceData(
dataname=ticker,
timeframe=bt.TimeFrame.Days,
fromdate=datetime.datetime(2020, 1, 1),
todate=datetime.datetime(2020, 12, 31),
reverse=False,
)
cerebro.adddata(data, name=ticker)
cerebro.addanalyzer(BarAnalysis, _name="bar_data")
cerebro.addstrategy(Strategy)
# Execute
strat = cerebro.run()
bar_data_res = strat[0].analyzers.bar_data.get_analysis()
df = pd.DataFrame(bar_data_res)
print(df)