Plotting only chosen data?
-
Hi there,
I work with a large universe (50+) and when backtesting, plotting the results is an unseeable mess.
I was wondering if it is possible to filter the results and to only plot certain data that meet the filter - a simple example would be the top 3 and bottom 3 performing assets in the backtest.
Any help would be much appreciated!
-
What to you mean by top 3 and bottom 3 performing? Could you be more specific?
-
Perhaps this can help you in the meantime. If you know which stocks you want to chart, you can add the following after you run cerebro and before you run cerebro.plot(). Below are some sample stocks in a list.
wins_losses = ['CMD', 'EW', 'BKNG' ] for d in cerebro.datas: if d._name in wins_losses: d.plotinfo.plot = True
You must tell backtrader not to plot the lines when you are adding in your data lines.
You do this by setting 'plot=False' when creating your dataline.
data = bt.feeds.PandasData(dataname=dataframe, name='AMZN', plot=False) # Add the Data Feed to Cerebro cerebro.adddata(data)
-
@run-out said in Plotting only chosen data?:
You do this by setting 'plot=False' when creating your dataline.
This can be done at anytime, not only during creation.
-
@run-out
Thanks for your input! Unfortunately, I don't know ahead of time which assets I would like to plot.I would like to access something rank-able, such as returns of each asset, and make plotting decisions based on that (top-performing, mean, bottom-performing - for example).
Any ideas or tips on achieving that?
-
@backtrader
Sorry to bring up an old thread, but I'm still having issues with one aspect of the above.I would like to access the returns information of each data within the strategy. I don't think this is currently possible - could you help me with this?
Thanks in advance!
-
Data feeds per se have no return. Pseudo-Return (i.e.: the variation) can be calculated using Analyzers.
-
Hi, how can i not plot the resample data? I can change this option for normal datas and it works but i cant hide resampled data of my pivotpoints indicator.
-
Let us see what you do ... to find out why you cannot.
-
'''
if name == 'main':# Instantiate the Cerebro engine cerebro = bt.Cerebro() # Add a strategy cerebro.addstrategy(PIVOTPOINTS_V8) # Add the Data Feeds to Cerebro cerebro.adddata(data_eurusd_m1) cerebro.adddata(data_eurusd_m30) cerebro.adddata(data_eurusd_d1) #cerebro.adddata(data_gbpusd_m1) #cerebro.adddata(data_gbpusd_m30) #cerebro.adddata(data_gbpusd_d1) #cerebro.adddata(data_usdjpy_m1) #cerebro.adddata(data_usdjpy_m30) #cerebro.adddata(data_usdjpy_d1) # Resampled data for the indicator cerebro.resampledata(data_eurusd_m1, timeframe=bt.TimeFrame.Days) # Set our desired cash start cerebro.broker.setcash(100000.0) cerebro.broker.set_checksubmit(False) # Set the commission - 25 monetary units per 1 lot (1 lot = 100.000 monetary units), per buy/sell = 0.0125%, total= 0.025% cerebro.broker.setcommission(commission=0.000125) # Add Analyzers #cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='TradeAnalyzer') #cerebro.addanalyzer(bt.analyzers.Returns, _name='Returns') #cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='TimeReturn') #cerebro.addanalyzer(bt.analyzers.Transactions, _name='Transactions') #cerebro.addanalyzer(bt.analyzers.PositionsValue, _name='PositionsValue') #cerebro.addanalyzer(bt.analyzers.DrawDown, _name='DrawDown') #cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='AnnualReturn') # Print out the starting conditions print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Run over everything (loop over the data) results = cerebro.run() strat = results[0] # Print out the final result print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot(style='candle', numfigs=1, barup ='lime', bardown ='red', valuetags=False)
'''
-
FIRST LESSON IN ALGOTRADING (believe me when I say it is an important one)
In algotrading like in chess, look carefully at what's right before your eyes, like what's at the top of every page of this community.
For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/
2nd, this thread says (one example)
@backtrader said in Plotting only chosen data?:
@run-out said in Plotting only chosen data?:
You do this by setting
plot=False
when creating your dataline.This can be done at anytime, not only during creation.
The same can be read in the documentation here: https://www.backtrader.com/docu/plotting/plotting/
Where are you doing that in your code which seems fairly incomplete? (Actually for any of the data, you have many and only 2 are shown)
You are not even storing the resampled data instance in a variable to do that
Nobody is interested in your secret sauce. If you want to show something and hide your very profitable code, create a 10 line snippet to show the problem.
-
Thank you for your answer,
The first thing I apologize, I think I did not know how to put the code well.
The second my code is not secret, its only a test. I put only the backtest running parts because there are too many lines.
I read the documentation before post and had no problem hiding the imported data directly. My problem is that I don't know how to hide daily resampled data in the chart. Perhaps i lose something but I really can't find anything about it. Here I show everything:
from __future__ import (absolute_import, division, print_function, unicode_literals) import backtrader as bt # The backtrader platform import backtrader.feeds as btfeeds # For load CSV data. from backtrader import Indicator, CmpEx # For indicators import backtrader.indicators as btind # For indicators import datetime # For datetime objects from datetime import time import matplotlib # For ploting # Symbols to load symbol_list = ['EURUSD','GBPUSD','USDJPY'] # List for storage the loaded datas data_list = [] # Load the data feeds for symbol in symbol_list: # 1 minute data (Each tick for analyze the strategy)_______________________________________________________ data0 = btfeeds.GenericCSVData( dataname='{}_GMT+0_2018-2019_M1.csv'.format(symbol), fromdate=datetime.datetime(2018, 1, 1), todate=datetime.datetime(2018, 1, 31), #(2018, 1, 31) nullvalue=0.0, dtformat=('%d.%m.%Y %H:%M:%S'), datetime=0, open=1, high=2, low=3, close=4, volume=-1, openinterest=-1, timeframe=bt.TimeFrame.Minutes, compression=1, plot = True ) data_list.append(data0) # 30 minute data (Pullback checking and plotting)__________________________________________________________ data1 = btfeeds.GenericCSVData( dataname='{}_GMT+0_2018-2019_M30.csv'.format(symbol), fromdate=datetime.datetime(2018, 1, 1), todate=datetime.datetime(2018, 1, 31), nullvalue=0.0, dtformat=('%d.%m.%Y %H:%M:%S'), datetime=0, open=1, high=2, low=3, close=4, volume=-1, openinterest=-1, timeframe=bt.TimeFrame.Minutes, compression=30, plot = False ) data_list.append(data1) # 1 Day data (For pivot points indicator)_______________________________________________________________ data2 = btfeeds.GenericCSVData( dataname='{}_GMT+0_2018-2019_D1.csv'.format(symbol), fromdate=datetime.datetime(2018, 1, 1), todate=datetime.datetime(2018, 1, 31), nullvalue=0.0, dtformat=('%d.%m.%Y %H:%M:%S'), datetime=0, open=1, high=2, low=3, close=4, volume=-1, openinterest=-1, timeframe=bt.TimeFrame.Days, compression=1, plot = False ) data_list.append(data2) # Assign data feed variables data_eurusd_m1 = data_list[0] data_eurusd_m30 = data_list[1] data_eurusd_d1 = data_list[2] data_gbpusd_m1 = data_list[3] data_gbpusd_m30 = data_list[4] data_gbpusd_d1 = data_list[5] data_usdjpy_m1 = data_list[6] data_usdjpy_m30 = data_list[7] data_usdjpy_d1 = data_list[8] class PivotPoints_V8_Indicator(Indicator): lines = ('PP', 'R1', 'S1', 'R2', 'S2', 'R3', 'S3') #plotinfo = dict(subplot=False) plotinfo = dict(subplot=False) params = (('_autoplot', True),) # attempt to plot on real target data def _plotinit(self): # Try to plot to the actual timeframe master if self.p._autoplot: if hasattr(self.data, 'data'): self.plotinfo.plotmaster = self.data.data #self.plotinfo.plotmaster = self.data.datas[1] # The second Data (M30) # The indicator plots on resampled data* def __init__(self): h = self.data.high # current high l = self.data.low # current low c = self.data.close # current close self.lines.PP = PP = (h + l + c) / 3.0 self.lines.R1 = R1 = 2.0 * PP - l self.lines.S1 = S1 = 2.0 * PP - h self.lines.R2 = R2 = (PP - S1) + R1 self.lines.S2 = S2 = PP - (R1 - S1) self.lines.R3 = (PP - S2) + R2 self.lines.S3 = PP - (R2 - S2) #super(PivotPoint, self).__init__() # enable coopertive inheritance if self.p._autoplot: self.plotinfo.plot = False # disable own plotting self() # Coupler to follow real object def time_in_range(start, end, x): """Return true if x is in the range [start, end]""" if start <= end: return start <= x <= end else: return start <= x or x <= end # The Strategy class PIVOTPOINTS_V8(bt.Strategy): # datas[0] = EURUSD #... # datas[3] = GBPUSD #... # datas[6] = USDJPY #... def log(self, txt, dt=None): ''' Logging function for this strategy''' dt = dt or self.datas[0].datetime.datetime(0) print('%s, %s' % (dt.strftime('%d-%m-%Y %H:%M:%S'), txt)) def __init__(self): # Strategy symbol self.symbol = 'EURUSD.r' #,'GBPUSD.r','USDJPY.r' # Indicator self.pivotindicator = PivotPoints_V8_Indicator(self.datas[3]) # the resampled data #self.pivotindicator.plotinfo.plotlinelabels = True # Data references self.M1_datetime = self.datas[0].datetime self.M1_close = self.datas[0].close self.M30_close = self.datas[1].close self.D1_close = self.datas[2].close self.D1_high = self.datas[2].high self.D1_low = self.datas[2].low # Strategy variables self.pullback_size = 70 self.pullback_candles = 10 #(M30 Candles!) self.op_counters = [0,0,0,0,0,0,0,0,0,0,0,0,0,0] self.send_distance = 70 #(Points) self.open_distance = 20 #(Points) self.lot = 1.5 #(1 lot = 100.000 unitary units) self.stoploss = 100 self.takeprofit = 100 # Keep a reference to the orders #self.order = None def notify_order(self, order): #date = self.data.datetime.datetime().date() date = self.data.datetime.datetime() if order.status == order.Accepted: print('-'*32,' NOTIFY ORDER ','-'*32) print('Order Accepted') print('{}, Status {}: Ref: {}, Size: {}, Price: {}'.format( date, order.status, order.ref, order.size, 'NA' if not order.price else round(order.price,5) )) if order.status == order.Completed: print('-'*32,' NOTIFY ORDER ','-'*32) print('Order Completed') print('{}, Status {}: Ref: {}, Size: {}, Price: {}'.format( date, order.status, order.ref, order.size, 'NA' if not order.price else round(order.price,5) )) print('Created: {} Price: {} Size: {}'.format(bt.num2date(order.created.dt), order.created.price,order.created.size)) print('-'*80) if order.status == order.Canceled: print('-'*32,' NOTIFY ORDER ','-'*32) print('Order Canceled') print('{}, Status {}: Ref: {}, Size: {}, Price: {}'.format( date, order.status, order.ref, order.size, 'NA' if not order.price else round(order.price,5) )) if order.status == order.Rejected: print('-'*32,' NOTIFY ORDER ','-'*32) print('WARNING! Order Rejected') print('{}, Status {}: Ref: {}, Size: {}, Price: {}'.format( date, order.status, order.ref, order.size, 'NA' if not order.price else round(order.price,5) )) print('-'*80) def notify_trade(self, trade): date = self.data.datetime.datetime() if trade.isclosed: print('-'*32,' NOTIFY TRADE ','-'*32) print('{}, Close Price: {}, Profit, Gross {}, Net {}'.format( date, trade.price, round(trade.pnl,2), round(trade.pnlcomm,2))) print('-'*80) def next(self): #//////// Trading Time ////////////////////////////////////////////////////////////// start = time(4,0,0) #4,0,0 end = time (20,50,0) #20,50,0 now = self.M1_datetime.time() weekday = self.datas[0].datetime.datetime(0).weekday() if time_in_range(start, end, now) and weekday in [1,2,3,4]: #(Monday=0, Tueasday=1...Sunday=6) # --- Get Data ---------------------------------------------------------------------- # Pivot Points values PP = self.pivotindicator.lines.PP[0] R1 = self.pivotindicator.lines.R1[0] S1 = self.pivotindicator.lines.S1[0] R2 = self.pivotindicator.lines.R2[0] S2 = self.pivotindicator.lines.S2[0] R3 = self.pivotindicator.lines.R3[0] S3 = self.pivotindicator.lines.S3[0] # List of pivot point levels for send orders iteration (Buy and Sell each level) pp_levels = [PP,PP,R1,R1,S1,S1,R2,R2,S2,S2,R3,R3,S3,S3] # Price (M1 Close, Backtrader cant handle tick data for Bid and Ask prices) price = self.M1_close[0] # Point value if 'JPY' in self.symbol: point = 0.001 else: point = 0.00001 # Pullbacks periods_back = self.pullback_candles #(M30 Candles) back_rates = self.M1_close.get(size=periods_back, ago=0) highest = max(back_rates) lowest = min(back_rates) pullback_buy = (highest - price) / point > self.pullback_size pullback_sell = (price - lowest) / point > self.pullback_size # --- Send Orders --------------------------------------------------------------- # Check if any entry condition has been met for i in range(len(self.op_counters)): # BUY iterations on pivot levels if i in [0,2,4,6,8,10,12]: if price > pp_levels[i] and price < (pp_levels[i] + self.send_distance * point) and pullback_buy == True and self.op_counters[i] == 0 : price = pp_levels[i]+(self.open_distance*point) # Price of the limit order sl = price - (self.stoploss*point) tp =price + (self.takeprofit*point) buy_order = self.buy_bracket(limitprice=tp, price=price, stopprice=sl, exectype=bt.Order.Limit, size= self.lot*100000) # Update ticket # Update counter self.op_counters[i] +=1 # SELL iterations on pivot levels elif i in [1,3,5,7,9,11,13]: if price < pp_levels[i] and price > (pp_levels[i] - self.send_distance * point) and pullback_sell == True and self.op_counters[i] == 0 : price = pp_levels[i]-(self.open_distance*point) # Price of the limit order sl = price + (self.stoploss*point) tp =price - (self.takeprofit*point) sell_order = self.sell_bracket(limitprice=tp, price=price, stopprice=sl, exectype=bt.Order.Limit, size= self.lot*100000) # Update ticket # Update counter self.op_counters[i] +=1 # --- Orders Managment ----------------------------------------------------------- else: #//////// Out of trading Time //////////////////////////////////////////////////// # --- Reset ---------------------------------------------------------------------- self.op_counters = [0,0,0,0,0,0,0,0,0,0,0,0,0,0] # --- Close all ---------------------------------------------------------------------- if self.position: self.close() #self.close(data= self.datas[0]) if __name__ == '__main__': # Instantiate the Cerebro engine cerebro = bt.Cerebro(stdstats=False) # remove the standard observers # Add a strategy cerebro.addstrategy(PIVOTPOINTS_V8) # Add the Data Feeds to Cerebro cerebro.adddata(data_eurusd_m1) cerebro.adddata(data_eurusd_m30) cerebro.adddata(data_eurusd_d1) #cerebro.adddata(data_gbpusd_m1) #cerebro.adddata(data_gbpusd_m30) #cerebro.adddata(data_gbpusd_d1) #cerebro.adddata(data_usdjpy_m1) #cerebro.adddata(data_usdjpy_m30) #cerebro.adddata(data_usdjpy_d1) # Resampled data for the indicator cerebro.resampledata(data_eurusd_m1, timeframe=bt.TimeFrame.Days) # Set our desired cash start cerebro.broker.setcash(100000.0) cerebro.broker.set_checksubmit(False) # Set the commission - 25 monetary units per 1 lot (1 lot = 100.000 monetary units), per buy/sell = 0.0125%, total= 0.025% cerebro.broker.setcommission(commission=0.000125) # Add Analyzers #cerebro.addanalyzer(bt.analyzers.TradeAnalyzer, _name='TradeAnalyzer') #cerebro.addanalyzer(bt.analyzers.Returns, _name='Returns') #cerebro.addanalyzer(bt.analyzers.TimeReturn, _name='TimeReturn') #cerebro.addanalyzer(bt.analyzers.Transactions, _name='Transactions') #cerebro.addanalyzer(bt.analyzers.PositionsValue, _name='PositionsValue') #cerebro.addanalyzer(bt.analyzers.DrawDown, _name='DrawDown') #cerebro.addanalyzer(bt.analyzers.AnnualReturn, _name='AnnualReturn') # Print out the starting conditions print('Starting Portfolio Value: %.2f' % cerebro.broker.getvalue()) # Run over everything (loop over the data) results = cerebro.run() strat = results[0] # Print out the final result print('Final Portfolio Value: %.2f' % cerebro.broker.getvalue()) cerebro.plot(style='candle', numfigs=1, barup ='lime', bardown ='red', valuetags=False)