Navigation

    Backtrader Community

    • Register
    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    For code/output blocks: Use ``` (aka backtick or grave accent) in a single line before and after the block. See: http://commonmark.org/help/

    How to create pyfolio round trip tearsheet?

    Indicators/Strategies/Analyzers
    7
    27
    1333
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • kian hong Tan
      kian hong Tan @kian hong Tan last edited by

      @run-out I realized there was a html copy being saved into local directory. So I guess it's deemed successful? Initially I thought a new browser will automatically pop up to show the results.

      1 Reply Last reply Reply Quote 2
      • kian hong Tan
        kian hong Tan last edited by

        @balibou That's positive. I use the below code and now I'm able to see the html tearsheet saved in my local drive. But not sure why you have the html error.

        qs.reports.html(df_values, "SPY",output="qs.html")
        
        1 Reply Last reply Reply Quote 2
        • run-out
          run-out last edited by

          You are really into a quantstats problem at this point.

          kian hong Tan 2 Replies Last reply Reply Quote 0
          • kian hong Tan
            kian hong Tan @run-out last edited by

            @run-out ok, I will check with ranaroussi then. Thank you.

            1 Reply Last reply Reply Quote 1
            • kian hong Tan
              kian hong Tan @run-out last edited by

              @run-out I came out with a workaround, by just opening the file since it's already saved. : )

              webbrowser.open('qs.html')
              
              J 1 Reply Last reply Reply Quote 2
              • J
                Jonny8 @kian hong Tan last edited by

                @kian-hong-Tan

                Hi,

                I have issues getting the code to work. Can you post your working code ?

                Best!

                1 Reply Last reply Reply Quote 0
                • K
                  kunalp @Arun Lama last edited by

                  @Arun-Lama

                  With the second alternative,

                  pf.create_round_trip_tear_sheet(returns, positions=positions, transactions=transactions)
                  

                  , you do get the error that you have mentioned.

                  You will need to go to the pyfolio files and make certain changes. At this point I am not sure whether I should go to pyfolio github repository and do a pull request because my changes work for what I need in the context of backtrader. I am in no way certain that making these changes will not break something else in pyfolio.

                  In round_trips.py, I made the following changes
                  Original

                  grouped_price = (t.groupby(('block_dir', 'block_time')).apply(vwap))
                  

                  Modified to:

                  grouped_price = (t.groupby(['block_dir', 'block_time']).apply(vwap)) 
                  
                  

                  After you solve this error, as the pyfolio code is able to run further you will get a few more errors. As I understood, it is because pandas moved ahead and deprecated certain functionality. Link below:
                  https://pandas.pydata.org/pandas-docs/stable/whatsnew/v0.20.0.html#whatsnew-0200-api-breaking-deprecate-group-agg-dict

                  This functionality was used to pass dicts to

                  agg_all_long_short
                  

                  Earlier code was:

                  PNL_STATS = OrderedDict([
                      ('Total profit', lambda x: x.sum()),
                       ('Gross profit', lambda x: x[x > 0].sum()),
                       ('Gross loss', lambda x: x[x < 0].sum()),
                       ('Profit factor', lambda x: x[x > 0].sum() / x[x < 0].abs().sum()
                        if x[x < 0].abs().sum() != 0 else np.nan),
                       ('Avg. trade net profit', 'mean'),
                       ('Avg. winning trade', lambda x: x[x > 0].mean()),
                       ('Avg. losing trade', lambda x: x[x < 0].mean()),
                       ('Ratio Avg. Win:Avg. Loss', lambda x: x[x > 0].mean() /
                        x[x < 0].abs().mean() if x[x < 0].abs().mean() != 0 else np.nan),
                       ('Largest winning trade', 'max'),
                       ('Largest losing trade', 'min'),])
                  

                  Change this to:

                  PNL_STATS = (
                       (lambda x: x.sum()),
                       ( lambda x: x[x > 0].sum()),
                       (lambda x: x[x < 0].sum()),
                       ( lambda x: x[x > 0].sum() / x[x < 0].abs().sum()
                        if x[x < 0].abs().sum() != 0 else np.nan),
                       ('mean'),
                       (lambda x: x[x > 0].mean()),
                       ( lambda x: x[x < 0].mean()),
                       ( lambda x: x[x > 0].mean() / x[x < 0].abs().mean() if x[x < 0].abs().mean() != 0 else np.nan),
                       ('max'),
                       ('min'),
                  )
                  

                  Please make similar changes for the other dicts:
                  Original code

                  SUMMARY_STATS = OrderedDict([('Total number of round_trips', 'count'),
                      ('Percent profitable', lambda x: len(x[x > 0]) / float(len(x))),
                       ('Winning round_trips', lambda x: len(x[x > 0])),
                       ('Losing round_trips', lambda x: len(x[x < 0])),
                       ('Even round_trips', lambda x: len(x[x == 0])),
                       ])
                  

                  Modified code

                  SUMMARY_STATS = (
                       ('count'),
                       (lambda x: len(x[x > 0]) / float(len(x))),
                       (lambda x: len(x[x > 0])),
                       (lambda x: len(x[x < 0])),
                       (lambda x: len(x[x == 0])),
                  )
                  

                  And so on for even the other dicts:

                  RETURN_STATS
                  
                  DURATION_STATS
                  

                  Essentially, you now cannot pass rename logic in the dicts themselves. This also means that for you will need to create a list of the column names and pass it yourself.

                  In

                  def gen_round_trip_stats(round_trips):
                  

                  this is the updated code Main changes are that we are creating a list of column names col_list before each function call to pass to the agg_all_long_short function (for reasons explained above - pandas deprecating nested renaming)

                  col_list = ['Total profit', 'Gross profit', 'Gross loss', 'Profit factor', 'Avg. trade net profit', 'Avg. winning trade', 'Avg. losing trade', 'Ratio Avg. Win:Avg. Loss', 'Largest winning trade', 'Largest losing trade']
                  stats['pnl'] = agg_all_long_short(round_trips, 'pnl', PNL_STATS, col_list)
                  
                  col_list = ['Total number of round_trips','Percent profitable', 'Winning round_trips', 'Losing round_trips', 'Even round_trips']
                  stats['summary'] = agg_all_long_short(round_trips, 'pnl', SUMMARY_STATS, col_list)
                  
                  col_list = ['Average duration', 'Median duration','Longest duration', 'Shortest duration']
                  stats['duration'] = agg_all_long_short(round_trips, 'duration',
                                                             DURATION_STATS, col_list)
                  
                  col_list = ['Avg returns all round_trips','Avg returns winning','Avg returns losing', 'Median returns all round_trips', 'Median returns winning','Median returns losing', 'Largest winning trade', 'Largest losing trade' ]
                  stats['returns'] = agg_all_long_short(round_trips, 'rt_returns',
                                                            RETURN_STATS, col_list)
                  

                  In function definition:
                  original

                  def agg_all_long_short(round_trips, col, stats_dict):
                  

                  modified (adding col_list argument)

                  def agg_all_long_short(round_trips, col, stats_dict, col_list):
                  

                  A few more changes in tears.py
                  Original code:

                   sns.distplot(trades.rt_returns.dropna() * 100, kde=False,
                                   ax=ax_pnl_per_round_trip_pct)
                  

                  Modified code:

                   sns.distplot(trades.returns.dropna() * 100, kde=False,
                                   ax=ax_pnl_per_round_trip_pct)
                  

                  With these changes the round_trip functionality should work. If any problems are faced please reply here. It will be helpful for the community.

                  Thanks.

                  1 Reply Last reply Reply Quote 1
                  • 1
                  • 2
                  • 2 / 2
                  • First post
                    Last post
                  Copyright © 2016, 2017, 2018 NodeBB Forums | Contributors
                  $(document).ready(function () { app.coldLoad(); }); }