For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

Is it possible to get the realized PnL from Backtrader?



  • Hi,

    I would like to ask, whether and how I could retrieve the realized Profit and Loss from Backtrader?

    Thanks in advance!



  • You can use analyzers for this purpose.

    TradeAnalyzer has extensive calculation on trades. When turned into a dataframe it looks like this:

    total_total	10
    total_open	1
    total_closed	9
    streak_won_current	0
    streak_won_longest	3
    streak_lost_current	1
    streak_lost_longest	1
    pnl_gross_total	23.16975
    pnl_gross_average	2.574416667
    pnl_net_total	23.16975
    pnl_net_average	2.574416667
    won_total	6
    won_pnl_total	42.99625
    won_pnl_average	7.166041667
    won_pnl_max	16.645
    lost_total	3
    lost_pnl_total	-19.8265
    lost_pnl_average	-6.608833333
    lost_pnl_max	-6.6445
    long_total	6
    long_pnl_total	19.77975
    long_pnl_average	3.296625
    long_pnl_won_total	26.35125
    long_pnl_won_average	5.27025
    long_pnl_won_max	16.35125
    long_pnl_lost_total	-6.5715
    long_pnl_lost_average	-6.5715
    long_pnl_lost_max	-6.5715
    long_won	5
    long_lost	1
    short_total	3
    short_pnl_total	3.39
    short_pnl_average	1.13
    short_pnl_won_total	16.645
    short_pnl_won_average	16.645
    short_pnl_won_max	16.645
    short_pnl_lost_total	-13.255
    short_pnl_lost_average	-6.6275
    short_pnl_lost_max	-6.6445
    short_won	1
    short_lost	2
    len_total	2282
    len_average	253.5555556
    len_max	383
    len_min	12
    len_won_total	1508
    len_won_average	251.3333333
    len_won_max	383
    len_won_min	12
    len_lost_total	774
    len_lost_average	258
    len_lost_max	382
    len_lost_min	29
    len_long_total	1169
    len_long_average	194.8333333
    len_long_max	383
    len_long_min	12
    len_long_won_total	1140
    len_long_won_average	228
    len_long_won_max	383
    len_long_won_min	12
    len_long_lost_total	29
    len_long_lost_average	29
    len_long_lost_max	29
    len_long_lost_min	29
    len_short_total	1113
    len_short_average	371
    len_short_max	382
    len_short_min	363
    len_short_won_total	368
    len_short_won_average	368
    len_short_won_max	368
    len_short_won_min	368
    len_short_lost_total	745
    len_short_lost_average	372.5
    len_short_lost_max	382
    len_short_lost_min	363
    

    Trade_list is awesome... thank you @ab_trader

    ref	ticker	dir	datein	pricein	dateout	priceout	chng%	pnl	pnl%	size	value	cumpnl	nbars	pnl/bar	mfe%	mae%	win
    1	ES	short	2020-01-10 09:35:00	3,279	2020-01-10 15:43:00	3,263	-51%	17	17%	-1	-3,279	17	368	0	56%	-14%	1
    2	ES	long	2020-01-10 15:45:00	3,263	2020-01-10 15:57:00	3,266	10%	3	3%	1	3,263	20	12	0	14%	-5%	1
    3	ES	long	2020-01-13 09:37:00	3,270	2020-01-13 15:54:00	3,287	50%	16	16%	1	3,270	36	377	0	51%	-7%	1
    4	ES	long	2020-01-14 09:32:00	3,286	2020-01-14 10:01:00	3,279	-20%	-7	-7%	1	3,286	30	29	0	2%	-21%	0
    5	ES	long	2020-01-14 10:02:00	3,282	2020-01-14 15:57:00	3,283	2%	1	0%	1	3,282	30	355	0	40%	-14%	1
    6	ES	long	2020-01-15 09:34:00	3,285	2020-01-15 15:57:00	3,289	12%	4	4%	1	3,285	34	383	0	43%	-11%	1
    7	ES	short	2020-01-16 09:31:00	3,305	2020-01-16 15:34:00	3,312	20%	-7	-7%	-1	-3,305	28	363	0	8%	-20%	0
    8	ES	long	2020-01-16 15:44:00	3,313	2020-01-16 15:57:00	3,315	7%	2	2%	1	3,313	30	13	0	11%	-2%	1
    9	ES	short	2020-01-17 09:33:00	3,322	2020-01-17 15:55:00	3,329	20%	-7	-7%	-1	-3,322	23	382	0	10%	-20%	0


  • One more. I'm pretty sure I got this from somewhere but for the life of me cannot find the source. This is clean and simple and shows you how to make your own custom analyzer.

    
    class TradeClosed(bt.analyzers.Analyzer):
        """
        Analyzer returning closed trade information.
        """
    
        def start(self):
            super(TradeClosed, self).start()
    
        def create_analysis(self):
            self.rets = {}
            self.vals = tuple()
    
        def notify_trade(self, trade):
            """Receives trade notifications before each next cycle"""
            if trade.isclosed:
                self.vals = (
                    self.strategy.datetime.datetime(),
                    trade.data._name,
                    round(trade.pnl, 2),
                    round(trade.pnlcomm, 2),
                    trade.commission,
                    (trade.dtclose - trade.dtopen),
                )
                self.rets[trade.ref] = self.vals
    
        def get_analysis(self):
            return self.rets
    
    

    Then add this to cerebro.

    self.cerebro.addanalyzer(TradeClosed, _name="trade_closed")
    

    The output is a dictionary that converts to this...

    ![b616de60-94fe-423b-8920-79f4f5332ba1-image.png](/assets/uploads/files/1588702280750-b616de60-94fe-423b-8920-79f4f5332ba1-image.png) 
    ```trade_id	date_closed	ticker	pnl	pnlcomm	commission	days_open
    1	2020-01-10 15:43:00	ES	17	17	0	0.25556
    2	2020-01-10 15:57:00	ES	3	3	0	0.00833
    3	2020-01-13 15:54:00	ES	16	16	0	0.26181
    4	2020-01-14 10:01:00	ES	-7	-7	0	0.02014
    5	2020-01-14 15:57:00	ES	1	1	0	0.24653
    6	2020-01-15 15:57:00	ES	4	4	0	0.26597
    7	2020-01-16 15:34:00	ES	-7	-7	0	0.25208
    8	2020-01-16 15:57:00	ES	2	2	0	0.00903
    9	2020-01-17 15:55:00	ES	-7	-7	0	0.26528


  • Hi @run-out ,

    thanks for your very good and concise answer.

    I made a mistake in my question.

    I forgot to mention that I would like to get the realized Profit and Loss at any moment in time and specially also for the case that I have staggered buys and sells.

    E. g.:

    I buy one stock at (1) and another one at (2) for 50 each.
    At (3) the stock price rises from 50 to 75.
    At (4) I sell one stock. The realized PnL should rise accordingly from 0 to 25.
    At (5) I sell the other stock. The realized PnL should rise from 25 to 50.

    My intention is how I could get the realized PnL (in red in the picture) at any point in time directly from Backtrader.

    realizedPnL5.jpg



  • I believe the chart I provided you with is doing what you asked. The date is the closed date of all trades. pnl is the profit or loss for that trade. pnlcomm is the pnl after commission. Commission is 0 in this case.

    All you need to do is graph it.



  • If you need a diagram of the realized PnL, than you can write an observer based on the analyzer shown above. In this case bt will show you the diagram and it will be no need to import it somewhere else.



  • Thanks.

    So in the end I was able to get the realized PnL from the analyzer described here: analyzer to calculate and save realized pnl and opened positions for each strategy date to date.

    But your posts were very helpful to direct me in the direction to look more at analyzers in general!

    Thanks again.


Log in to reply
 

});