For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
backtrader addwriter output buy and sell point error?
-
I used
cerebro.addwriter(bt.WriterFile, csv=True, out='outputfiles\{}.csv'.format(ticker))
to write out the output.
the output CSV file has 2 "datetime" columns 3 "len" columns
question 1, how to output only desired columns (say: tickername, date, cash, value)
question 2, the output CSV file wrote down buy and sell price, but those prices are none of the open/high/low/close. How can I find out how/where does the backtrader gets those values?
following is the screenshot of the output file.I attached the code here:
import pandas as pd import datetime import backtrader as bt import pickle from zclasses.GoldenCross1 import GoldCross from zclasses.sma_crossover import MA_CrossOver # def run_test_macd(): # with open("sp500tickers.pickle", "rb") as f: # tickers = pickle.load(f) # for ticker in tickers: # print(ticker) # macd_stock_test2(ticker) def run_test_single(): ticker="OXY" print("ticker") print(ticker) macd_stock_test2(ticker) def macd_stock_test2(ticker): cerebro = bt.Cerebro() cerebro.addstrategy(GoldCross) # cerebro.addstrategy(MA_CrossOver) cerebro.broker.set_cash(1000000) ticker_prices = pd.read_csv('stock_dfs/{}.csv'.format(ticker), index_col='Date', parse_dates=True) # print(ticker_prices) feed = bt.feeds.PandasData( dataname=ticker_prices, timeframe=bt.TimeFrame.Days, fromdate=datetime.datetime(1996, 1, 1), # this is used for all # fromdate=datetime.datetime(2020, 5, 1), #this is used for debug todate=datetime.datetime(2020, 12, 31), #this is used for all # todate=datetime.datetime(2012, 12, 31), #this is used for debug # reverse=False, ) # feed = bt.feeds.YahooFinanceData( # # dataname=ticker, # # timeframe=bt.TimeFrame.Days, # fromdate=datetime.datetime(1996, 1, 1), # todate=datetime.datetime(2020, 12, 31), # reverse=False, # ) cerebro.adddata(feed) # cerebro.addsizer(bt.sizers.FixedSize, stake=1000) # cerebro.addanalyzer(bt.analyzers.DrawDown) # cerebro.addanalyzer(btanalyzers.DrawDown, _name='returns') # cerebro.addanalyzer(SQN) # print("starting portfolio value: %.2f" % cerebro.broker.getvalue()) cerebro.addwriter(bt.WriterFile, csv=False, out='outputfiles\{}.csv'.format(ticker)) cerebro.run() print("final portfolio value: %.2f" % cerebro.broker.getvalue()) # cerebro.plot(style='candle') run_test_single() class GoldCross(bt.Strategy): #unknow gold cross # set parameters to define fast and slow fastd = 12 slowd = 26 params = ( ("fast", fastd), ("slow", slowd), ("order_percentage", 1), ("ticker", "stock"), ) # define constractors def __init__(self): print("position size:", self.position.size) self.fast_moving_average = bt.indicators.EMA( self.data.close, period=self.params.fast, plotname="12 day moving average" ) self.slow_moving_average = bt.indicators.EMA( self.data.close, period=self.params.slow, plotname="26 day moving average" ) self.crossover = bt.indicators.CrossOver( self.fast_moving_average, self.slow_moving_average ) def log(self, txt, dt=None): """ Logging function fot this strategy""" dt = dt or self.data.datetime[0] if isinstance(dt, float): dt = bt.num2date(dt) print("%s, %s" % (dt.date(), txt)) def notify_order(self, order): """ Triggered upon changes to orders. """ # Suppress notification if it is just a submitted order. if order.status == order.Submitted: return # Print out the date, security name, order number and status. dt, dn = self.datetime.date(), order.data._name type = "Buy" if order.isbuy() else "Sell" # self.log( # # print(dn) # f"{order.data._name:<6} Order: {order.ref:3d}\tType: {type:<5}\tStatus" # f" {order.getstatusname():<8} \t" # f"Size: {order.created.size:9.2f} Price: {order.created.price:9.2f} " # f"Position: {self.getposition(order.data).size}" # ) if order.status == order.Margin: return # Check if an order has been completed if order.status in [order.Completed]: self.log( f"{order.data._name:<6} {('BUY' if order.isbuy() else 'SELL'):<5} " f"EXECUTED for: {dn} " f"Price: {order.executed.price:6.2f} " f"Cost: {order.executed.value:6.2f} " # f"Comm: {order.executed.comm:4.2f} " f"Size: {order.created.size:9.0f} " ) def notify_trade(self, trade): """Provides notification of closed trades.""" if trade.isclosed: self.log( "{} Closed: PnL Gross {}, Net {},".format( trade.data._name, round(trade.pnl, 2), round(trade.pnlcomm, 2), ) ) def next(self): if self.position.size == 0: if self.crossover > 0: amount_to_invest = self.params.order_percentage * self.broker.cash self.size = math.floor(amount_to_invest / self.data.open[1]) # self.size = math.floor(amount_to_invest / self.data.close) # self.log( # "Buy {} shares of {} at {}".format( # self.size, # self.params.ticker, # # self.data.close[0], # self.data.open[1], # ) # ) # self.buy(size=self.size,price=self.data.close[0]) self.buy(size=self.size, price=self.data.open[1]) if self.position.size > 0: if self.crossover < 0: # self.log( # "Sell {} shares of {} at {}".format( # # self.size, self.params.ticker, self.data.close[0], # self.size, self.params.ticker, self.data.open[1], # ) # ) self.sell(size=self.size,price=self.data.open[1]) def end(self): # self.sell(size=self.size, price=self.data.close[0]) self.sell(size=self.size, price=self.data.open[1]) return if __name__ == "__main__": print("File one executed when ran directly") else: print("File one executed when imported") class GoldCross(bt.Strategy): #unknow gold cross # set parameters to define fast and slow fastd = 12 slowd = 26 params = ( ("fast", fastd), ("slow", slowd), ("order_percentage", 1), ("ticker", "stock"), ) # define constractors def __init__(self): print("position size:", self.position.size) self.fast_moving_average = bt.indicators.EMA( self.data.close, period=self.params.fast, plotname="12 day moving average" ) self.slow_moving_average = bt.indicators.EMA( self.data.close, period=self.params.slow, plotname="26 day moving average" ) self.crossover = bt.indicators.CrossOver( self.fast_moving_average, self.slow_moving_average ) def log(self, txt, dt=None): """ Logging function fot this strategy""" dt = dt or self.data.datetime[0] if isinstance(dt, float): dt = bt.num2date(dt) print("%s, %s" % (dt.date(), txt)) def notify_order(self, order): """ Triggered upon changes to orders. """ # Suppress notification if it is just a submitted order. if order.status == order.Submitted: return # Print out the date, security name, order number and status. dt, dn = self.datetime.date(), order.data._name type = "Buy" if order.isbuy() else "Sell" # self.log( # # print(dn) # f"{order.data._name:<6} Order: {order.ref:3d}\tType: {type:<5}\tStatus" # f" {order.getstatusname():<8} \t" # f"Size: {order.created.size:9.2f} Price: {order.created.price:9.2f} " # f"Position: {self.getposition(order.data).size}" # ) if order.status == order.Margin: return # Check if an order has been completed if order.status in [order.Completed]: self.log( f"{order.data._name:<6} {('BUY' if order.isbuy() else 'SELL'):<5} " f"EXECUTED for: {dn} " f"Price: {order.executed.price:6.2f} " f"Cost: {order.executed.value:6.2f} " # f"Comm: {order.executed.comm:4.2f} " f"Size: {order.created.size:9.0f} " ) def notify_trade(self, trade): """Provides notification of closed trades.""" if trade.isclosed: self.log( "{} Closed: PnL Gross {}, Net {},".format( trade.data._name, round(trade.pnl, 2), round(trade.pnlcomm, 2), ) ) def next(self): if self.position.size == 0: if self.crossover > 0: amount_to_invest = self.params.order_percentage * self.broker.cash self.size = math.floor(amount_to_invest / self.data.open[1]) # self.size = math.floor(amount_to_invest / self.data.close) # self.log( # "Buy {} shares of {} at {}".format( # self.size, # self.params.ticker, # # self.data.close[0], # self.data.open[1], # ) # ) # self.buy(size=self.size,price=self.data.close[0]) self.buy(size=self.size, price=self.data.open[1]) if self.position.size > 0: if self.crossover < 0: # self.log( # "Sell {} shares of {} at {}".format( # # self.size, self.params.ticker, self.data.close[0], # self.size, self.params.ticker, self.data.open[1], # ) # ) self.sell(size=self.size,price=self.data.open[1]) def end(self): # self.sell(size=self.size, price=self.data.close[0]) self.sell(size=self.size, price=self.data.open[1]) return if __name__ == "__main__": print("File one executed when ran directly") else: print("File one executed when imported")
-