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 classSharpeRatio
?Thanks!
-
-
AFAIU you may try to set the
timeframe
andcompression
attributes for the analyzer. They areTimeFrame.Years
and `1 -
Ops (hit submit by mistake)
AFAIU you may try to set the
timeframe
andcompression
attributes for the analyzer. They are TimeFrame.Years and1
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 https://github.com/mementum/backtrader/blob/master/backtrader/analyzer.py#L399-L406:
# 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?
-
@soulmachine said in How to initialize bt.analyzers.SharpeRatio?:
is there any doc describing it intuitively?
https://www.backtrader.com/docu/data-resampling/data-resampling/
-
@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
andcompression=1
, but sharpe ratio varies with differentcompression
.What
compression
is the correct value in this situation? -
Anyone knows what's the difference between
timeframe=bt.TimeFrame.Days, compression=1, factor=365
andtimeframe=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
inSharpeRatio
has no relation to the timeframe of the data feed. The timeframe inSharpeRatio
means how frequent you want to snapshot the equity curve. -
After reading the source code I think I've figured out.
timeframe
andcompression
are used at analyzers/sharpe.py#L153:returns = list(itervalues(self.timereturn.get_analysis()))
timeframe=bt.TimeFrame.Days, compression=1
, meansTimeReturn
will take a snapshot on the equity curve per daytimeframe=bt.TimeFrame.Minutes, compression=24*60
, meansTimeReturn
will take a snapshot on the equity curve per24*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 convertriskfreerate
torate
, which used at analyzers/sharpe.py#L186: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
andconvertrate=True
, Backtrader already sets them default - Set
timeframe
andcompression
to makeTimeReturn
take a snapshot on equity curve per day, if the timeframe of your data feed is equal or less than 1 day, settimeframe=bt.TimeFrame.Days, compression=1
, otherwise settimeframe=bt.TimeFrame.Days, compression=data_feed
- Set
factor
to252
for stocks and365
for cryptocurrencies.
Examples:
- 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
-
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?