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

How to initialize bt.analyzers.SharpeRatio?

  • I'm backtesting a BTC/USDT strategy, I have only two months realtime trading data, and I've already built 1-minute OHLCV bars based on the data.

    Since I don't have one year data, so the following code will always give me None:

    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='mysharpe')

    How should I chose params for the class SharpeRatio?


  • AFAIU you may try to set the timeframe and compression attributes for the analyzer. They are TimeFrame.Years and `1

  • Ops (hit submit by mistake)

    AFAIU you may try to set the timeframe and compression attributes for the analyzer. They are TimeFrame.Years and 1 by default.

    cerebro.addanalyzer(bt.analyzers.SharpeRatio, _name='mysharpe', timeframe=bt.TimeFrame.Months, compression=1)

  • @soulmachine Thanks for asking this question. I ran into issues with this a while ago and was to lazy to dig up the answer.

    @vladisld is correct in how you put in the timeframes. Small caveat to his comment, the compression only works on intraday timeframes. So typically say 1min compression to 30 or 60 minutes.

        cerebro.addanalyzer(bt.analyzers.SharpeRatio, timeframe=bt.TimeFrame.Minutes, compression=30, _name="mysharpe_1")
        cerebro.addanalyzer(bt.analyzers.SharpeRatio, timeframe=bt.TimeFrame.Minutes, compression=60, _name="mysharpe_2")
    # Output
    mysharpe_1: -2.3099,      mysharpe_2: -1.7835

    If you try the same thing with say Weekly or Monthly timeframes, there's no impact on results.

    cerebro.addanalyzer(bt.analyzers.SharpeRatio, timeframe=bt.TimeFrame.Weeks, compression=2, _name="mysharpe_1")
            cerebro.addanalyzer(bt.analyzers.SharpeRatio, timeframe=bt.TimeFrame.Weeks, compression=4, _name="mysharpe_2")
    # Output
    mysharpe_1: -0.3472,      mysharpe_2: -0.3472

    For more information you can look in the docs or directly at the code.

  • Hi @vladisld , @run-out , thanks for your answers, I'm still quite confused by compression, I never met this concept in any papers, is there any doc describing it intuitively?

    I've read its source code at

    # Apply compression to update point position (comp 5 -> 200 // 5)
    point = point // self.compression
    # Move to next boundary
    point += 1
    # Restore point to the timeframe units by de-applying compression
    point *= self.compression

    What's the purpose of the above code?

  • @run-out The link you posted above explains compression clearly, thanks a lot!

  • @run-out I got different sharpe ratio values if using different params, my data are 1-minute OHLCV bars from 2020-05-09 to 2020-05-15.

    Params Sharpe ratio
    timeframe=bt.TimeFrame.Days, compression=1, factor=365 0.26936215606006514
    timeframe=bt.TimeFrame.Days, compression=2, factor=365 0.26936215606006514
    timeframe=bt.TimeFrame.Days, compression=3, factor=365 0.26936215606006514
    timeframe=bt.TimeFrame.Minutes, compression=1, factor=365 -0.02323860385901048
    timeframe=bt.TimeFrame.Minutes, compression=2, factor=365 -0.012041289387197245
    timeframe=bt.TimeFrame.Minutes, compression=3, factor=365 -0.006921681345592514
    timeframe=bt.TimeFrame.Minutes, compression=24*60, factor=365 0.26936215606006514

    I set factor=365 because Bitcoin is trading 24 hours a day and 7 days a week.

    Since my data are 1-minute OHLCV bars, I think I should use timeframe=bt.TimeFrame.Minutes and compression=1, but sharpe ratio varies with different compression.

    What compression is the correct value in this situation?

  • Anyone knows what's the difference between timeframe=bt.TimeFrame.Days, compression=1, factor=365 and timeframe=bt.TimeFrame.Minutes, compression=24*60, factor=365? My data are 1-minute OHLCV bars from 2020-05-09 to 2020-05-15.

  • After reading some source code and several experiments, my guess is that the timeframe in SharpeRatio has no relation to the timeframe of the data feed. The timeframe in SharpeRatio means how frequent you want to snapshot the equity curve.

  • After reading the source code I think I've figured out.

    timeframe and compression are used at analyzers/

    returns = list(itervalues(self.timereturn.get_analysis()))
    • timeframe=bt.TimeFrame.Days, compression=1, means TimeReturn will take a snapshot on the equity curve per day
    • timeframe=bt.TimeFrame.Minutes, compression=24*60, means TimeReturn will take a snapshot on the equity curve per 24*60 minutes, which is the same as a day

    returns is a list of (timestamp, percentage), sharpe ratio is calculated on top of this list.

    timeframe, compression --> TimeReturn -->returns --> sharpe_ratio

    The factor is used to convert riskfreerate to rate, which used at analyzers/

    ret_free = [r - rate for r in returns]

    Since I snapshot on the equity curve per day, and one year contains 365 trading days(crypto exchanges never stop on weekends, which is different with stocks).

    Recommended configurations:

    • Prerequisites: make sure you have over 2 days data and make over 2 trades during backtesting, otherwise you'll get None
    • Always set annualize =True, because sharpe ratio is usually in annual form.
    • Set riskfreerate=0.01 and convertrate=True, Backtrader already sets them default
    • Set timeframe and compression to make TimeReturn take a snapshot on equity curve per day, if the timeframe of your data feed is equal or less than 1 day, set timeframe=bt.TimeFrame.Days, compression=1, otherwise set timeframe=bt.TimeFrame.Days, compression=data_feed
    • Set factor to 252 for stocks and 365 for cryptocurrencies.


    • 1-day OHLCV bars for US stocks, timeframe=bt.TimeFrame.Days, compression=1, factor=252,annualize =True
    • 3-day OHLCV bars for US stocks, timeframe=bt.TimeFrame.Days, compression=3, factor=252,annualize =True
    • 1-day OHLCV bars for cryptocurrency, timeframe=bt.TimeFrame.Days, compression=1, factor=365,annualize =True
    • 3-day OHLCV bars for cryptocurrency, timeframe=bt.TimeFrame.Days, compression=3, factor=365,annualize =True
    • 15-minutes OHLCV bars for cryptocurrency, timeframe=bt.TimeFrame.Days, compression=1, factor=365,annualize =True

  • @soulmachine

    I'm just a rookies here. But I think Sharpe ratio is a ratio compare to risk free only. The timeframe and length of series data are important for strategy, the Sharpe result in analyzer is a forecast/far-seeing for standard 1 year from the current series data (less than a year series data).

    So, the most important mean of Sharpe is compare to risk free with THE RISK of strategy in trading result.

  • @soulmachine Hello, tks for your explanation. I'm testing cryptocurrency too, on 30 mins data. If I'm testing more than a year of data, I do not need to change the default parameters right? maybe only change the factor to 365?

Log in to reply