在一些關於改進的ShapeRatio的提示之後, backtrader 已將此分析儀添加到其武器庫中。
文獻位於:
從對數回報的好處開始,並遵循在SharpeRatio方程的分母中具有標準偏差的副作用,本文檔開發了該分析儀的公式和期望。
最重要的屬性之一可能是:
- 跨時間範圍的一致價值
使用SharpeRatio
超額回報與無風險利率/資產的算術平均值除以超額回報與無風險利率/資產的標準偏差。這使得最終值取決於樣本數量和甚至可能是 0
的標準偏差。在這種情況下,將是 SharpeRatio
無限的。
backtrader包括一個範例,SharpeRatio
用於測試使用範例數據的範例,其中包括和2006
的價格2005
。不同時間幀的返回值:
-
TimeFrame.Years
:11.6473
-
TimeFrame.Months
:0.5425
-
TimeFrame.Weeks
:0.457
-
TimeFrame.Days
:0.4274
注意
為了保持一致性,該比率是年化的。該sharpe-timereturn
範例與執行方式為:
--annualize --timeframe xxx
其中xxx
代表 days
、 weeks
或 months
years
(預設值)
在此示例中,有一些明確的東西:
- 時間幀越小,值越小
SharpeRatio
這是由樣本數量引起的,對於較小的時間幀,樣本數量更大,並增加了可變性,從而增加了標準偏差,這是方程中的SharpeRatio
分母。
對標準偏差的變化有很大的敏感性
這正是他們VWR
試圖通過提供跨時間範圍的一致值來解決的。同一策略提供以下值:
-
TimeFrame.Years
:1.5368
-
TimeFrame.Months
:1.5163
-
TimeFrame.Weeks
:1.5383
-
TimeFrame.Days
:1.5221
注意
返回VWR
(遵循文獻)始終以年化形式返回。該範例通過以下方式執行:
--timeframe xxx
其中xxx
代表days
、 weeks
或 months
years
默認值是None
使用數據的基礎時間幀,即 days
一致的值,表明策略在提供一致回報方面的表現可以在任何時間範圍內進行評估。
注意
從理論上講,這些值應該是相同的,但這需要將參數(年化週期數)微調tann
為確切的交易週期。這裡沒有這樣做,因為目的只是看一致性。
結論
為使用者提供了一種新工具,它提供了一種獨立於時間框架的策略評估方法
示例用法
$ ./vwr.py --help usage: vwr.py [-h] [--data DATA] [--cash CASH] [--fromdate FROMDATE] [--todate TODATE] [--writercsv] [--tframe {weeks,months,days,years}] [--sigma-max SIGMA_MAX] [--tau TAU] [--tann TANN] [--stddev-sample] [--plot [kwargs]] TimeReturns and VWR optional arguments: -h, --help show this help message and exit --data DATA, -d DATA data to add to the system (default: ../../datas/2005-2006-day-001.txt) --cash CASH Starting Cash (default: None) --fromdate FROMDATE, -f FROMDATE Starting date in YYYY-MM-DD format (default: None) --todate TODATE, -t TODATE Starting date in YYYY-MM-DD format (default: None) --writercsv, -wcsv Tell the writer to produce a csv stream (default: False) --tframe {weeks,months,days,years}, --timeframe {weeks,months,days,years} TimeFrame for the Returns/Sharpe calculations (default: None) --sigma-max SIGMA_MAX VWR Sigma Max (default: None) --tau TAU VWR tau factor (default: None) --tann TANN Annualization factor (default: None) --stddev-sample Consider Bessels correction for stddeviation (default: False) --plot [kwargs], -p [kwargs] Plot the read data applying any kwargs passed For example: --plot style="candle" (to plot candles) (default: None)
示例代碼
from __future__ import (absolute_import, division, print_function, unicode_literals) import argparse import datetime import backtrader as bt TFRAMES = dict( days=bt.TimeFrame.Days, weeks=bt.TimeFrame.Weeks, months=bt.TimeFrame.Months, years=bt.TimeFrame.Years) def runstrat(pargs=None): args = parse_args(pargs) # Create a cerebro cerebro = bt.Cerebro() if args.cash is not None: cerebro.broker.set_cash(args.cash) dkwargs = dict() # Get the dates from the args if args.fromdate is not None: fromdate = datetime.datetime.strptime(args.fromdate, '%Y-%m-%d') dkwargs['fromdate'] = fromdate if args.todate is not None: todate = datetime.datetime.strptime(args.todate, '%Y-%m-%d') dkwargs['todate'] = todate # Create the 1st data data = bt.feeds.BacktraderCSVData(dataname=args.data, **dkwargs) cerebro.adddata(data) # Add the data to cerebro cerebro.addstrategy(bt.strategies.SMA_CrossOver) # Add the strategy lrkwargs = dict() if args.tframe is not None: lrkwargs['timeframe'] = TFRAMES[args.tframe] if args.tann is not None: lrkwargs['tann'] = args.tann cerebro.addanalyzer(bt.analyzers.Returns, **lrkwargs) # Returns vwrkwargs = dict() if args.tframe is not None: vwrkwargs['timeframe'] = TFRAMES[args.tframe] if args.tann is not None: vwrkwargs['tann'] = args.tann if args.sigma_max is not None: vwrkwargs['sigma_max'] = args.sigma_max if args.tau is not None: vwrkwargs['tau'] = args.tau cerebro.addanalyzer(bt.analyzers.VWR, **vwrkwargs) # VWR Analyzer # Add a writer to get output cerebro.addwriter(bt.WriterFile, csv=args.writercsv, rounding=4) cerebro.run() # And run it # Plot if requested if args.plot: pkwargs = dict(style='bar') if args.plot is not True: # evals to True but is not True npkwargs = eval('dict(' + args.plot + ')') # args were passed pkwargs.update(npkwargs) cerebro.plot(**pkwargs) def parse_args(pargs=None): parser = argparse.ArgumentParser( formatter_class=argparse.ArgumentDefaultsHelpFormatter, description='TimeReturns and SharpeRatio') parser.add_argument('--data', '-d', default='../../datas/2005-2006-day-001.txt', help='data to add to the system') parser.add_argument('--cash', default=None, type=float, required=False, help='Starting Cash') parser.add_argument('--fromdate', '-f', default=None, help='Starting date in YYYY-MM-DD format') parser.add_argument('--todate', '-t', default=None, help='Starting date in YYYY-MM-DD format') parser.add_argument('--writercsv', '-wcsv', action='store_true', help='Tell the writer to produce a csv stream') parser.add_argument('--tframe', '--timeframe', default=None, required=False, choices=TFRAMES.keys(), help='TimeFrame for the Returns/Sharpe calculations') parser.add_argument('--sigma-max', required=False, action='store', type=float, default=None, help='VWR Sigma Max') parser.add_argument('--tau', required=False, action='store', type=float, default=None, help='VWR tau factor') parser.add_argument('--tann', required=False, action='store', type=float, default=None, help=('Annualization factor')) parser.add_argument('--stddev-sample', required=False, action='store_true', help='Consider Bessels correction for stddeviation') # Plot options parser.add_argument('--plot', '-p', nargs='?', required=False, metavar='kwargs', const=True, help=('Plot the read data applying any kwargs passed\n' '\n' 'For example:\n' '\n' ' --plot style="candle" (to plot candles)\n')) if pargs is not None: return parser.parse_args(pargs) return parser.parse_args() if __name__ == '__main__': runstrat()