def __init__(self): super(SharpeRatio, self).__init__() if self.p.legacyannual: self.anret = AnnualReturn() else: self.timereturn = TimeReturn(timeframe=self.p.timeframe, compression=self.p.compression)
def __init__(self): if self.p.legacyannual: self.anret = AnnualReturn() else: self.timereturn = TimeReturn( timeframe=self.p.timeframe, compression=self.p.compression)
def __init__(self): super(SharpeRatio, self).__init__() if self.p.legacyannual: self.anret = AnnualReturn() else: self.timereturn = TimeReturn( timeframe=self.p.timeframe, compression=self.p.compression)
class SharpeRatio(Analyzer): '''This analyzer calculates the SharpeRatio of a strategy using a risk free asset which is simply an interest rate See also: - https://en.wikipedia.org/wiki/Sharpe_ratio Params: - ``timeframe``: (default: ``TimeFrame.Years``) - ``compression`` (default: ``1``) Only used for sub-day timeframes to for example work on an hourly timeframe by specifying "TimeFrame.Minutes" and 60 as compression - ``riskfreerate`` (default: 0.01 -> 1%) Expressed in annual terms (see ``convertrate`` below) - ``convertrate`` (default: ``True``) Convert the ``riskfreerate`` from annual to monthly, weekly or daily rate. Sub-day conversions are not supported - ``factor`` (default: ``None``) If ``None``, the conversion factor for the riskfree rate from *annual* to the chosen timeframe will be chosen from a predefined table Days: 252, Weeks: 52, Months: 12, Years: 1 Else the specified value will be used - ``annualize`` (default: ``False``) If ``convertrate`` is ``True``, the *SharpeRatio* will be delivered in the ``timeframe`` of choice. In most occasions the SharpeRatio is delivered in annualized form. Convert the ``riskfreerate`` from annual to monthly, weekly or daily rate. Sub-day conversions are not supported - ``stddev_sample`` (default: ``False``) If this is set to ``True`` the *standard deviation* will be calculated decreasing the denominator in the mean by ``1``. This is used when calculating the *standard deviation* if it's considered that not all samples are used for the calculation. This is known as the *Bessels' correction* - ``daysfactor`` (default: ``None``) Old naming for ``factor``. If set to anything else than ``None`` and the ``timeframe`` is ``TimeFrame.Days`` it will be assumed this is old code and the value will be used - ``legacyannual`` (default: ``False``) Use the ``AnnualReturn`` return analyzer, which as the name implies only works on years Methods: - get_analysis Returns a dictionary with key "sharperatio" holding the ratio ''' params = ( ('timeframe', TimeFrame.Years), ('compression', 1), ('riskfreerate', 0.01), ('factor', None), ('convertrate', True), ('annualize', False), ('stddev_sample', False), # old behavior ('daysfactor', None), ('legacyannual', False), ) RATEFACTORS = { TimeFrame.Days: 252, TimeFrame.Weeks: 52, TimeFrame.Months: 12, TimeFrame.Years: 1, } def __init__(self): if self.p.legacyannual: self.anret = AnnualReturn() else: self.timereturn = TimeReturn( timeframe=self.p.timeframe, compression=self.p.compression) def stop(self): super(SharpeRatio, self).stop() if self.p.legacyannual: rate = self.p.riskfreerate retavg = average([r - rate for r in self.anret.rets]) retdev = standarddev(self.anret.rets) self.ratio = retavg / retdev else: # Get the returns from the subanalyzer returns = list(itervalues(self.timereturn.get_analysis())) rate = self.p.riskfreerate # factor = None # Hack to identify old code if self.p.timeframe == TimeFrame.Days and \ self.p.daysfactor is not None: factor = self.p.daysfactor else: if self.p.factor is not None: factor = self.p.factor # user specified factor elif self.p.timeframe in self.RATEFACTORS: # Get the conversion factor from the default table factor = self.RATEFACTORS[self.p.timeframe] if factor is not None: # A factor was found if self.p.convertrate: # Standard: downgrade annual returns to timeframe factor rate = pow(1.0 + rate, 1.0 / factor) - 1.0 else: # Else upgrade returns to yearly returns returns = [pow(1.0 + x, factor) - 1.0 for x in returns] # Get the excess returns - arithmetic mean - original sharpe ret_free = [r - rate for r in returns] ret_free_avg = average(ret_free) retdev = standarddev(ret_free, avgx=ret_free_avg, bessel=self.p.stddev_sample) try: ratio = ret_free_avg / retdev if factor is not None and \ self.p.convertrate and self.p.annualize: ratio = math.sqrt(factor) * ratio except (ValueError, TypeError): ratio = None self.ratio = ratio self.rets['sharperatio'] = self.ratio
class Sortino(Analyzer): params = ( ('timeframe', TimeFrame.Years), ('compression', 1), ('riskfreerate', 0.01), ('factor', None), ('convertrate', True), ('annualize', False), ) RATEFACTORS = { TimeFrame.Days: 252, TimeFrame.Weeks: 52, TimeFrame.Months: 12, TimeFrame.Years: 1, } def __init__(self): super(Sortino, self).__init__() self.ret = TimeReturn(timeframe=self.p.timeframe, compression=self.p.compression) self.ratio = 0.0 def stop(self): returns = list(self.ret.get_analysis().values()) rate = self.p.riskfreerate factor = None if self.p.timeframe in self.RATEFACTORS: # Get the conversion factor from the default table factor = self.RATEFACTORS[self.p.timeframe] if factor is not None: # A factor was found if self.p.convertrate: # Standard: downgrade annual returns to timeframe factor rate = pow(1.0 + rate, 1.0 / factor) - 1.0 else: # Else upgrade returns to yearly returns returns = [pow(1.0 + x, factor) - 1.0 for x in returns] if len(returns): # Sortino Ratio = (R - T) / TDD # R = Avg Returns # T = Target (risk-free rate) # TDD = Downside Risk ret_free_avg = np.mean(returns) - rate tdd = math.sqrt(np.mean([min(0, r - rate)**2 for r in returns])) try: ratio = ret_free_avg / tdd if factor is not None and \ self.p.convertrate and self.p.annualize: ratio = math.sqrt(factor) * ratio except (ValueError, TypeError, ZeroDivisionError): ratio = None else: # no returns ratio = None self.ratio = ratio def get_analysis(self): return dict(sortino=self.ratio)
def __init__(self): super(Sortino, self).__init__() self.ret = TimeReturn(timeframe=self.p.timeframe, compression=self.p.compression) self.ratio = 0.0
class SharpeRatio(Analyzer): '''This analyzer calculates the SharpeRatio of a strategy using a risk free asset which is simply an interest rate See also: - https://en.wikipedia.org/wiki/Sharpe_ratio Params: - timeframe: (default: TimeFrame.Years) - compression (default: 1) Only used for sub-day timeframes to for example work on an hourly timeframe by specifying "TimeFrame.Minutes" and 60 as compression - riskfreerate: (default: 0.01 -> 1%) Expressed in annual terms (see ``convertrate`` below) - convertrate (default: True) Convert the ``riskfreerate`` from annual to monthly, weekly or daily rate. Sub-day conversions are not supported - daysfactor (default: 256) On a conversion of annual to daily rate use the value as the number of trading days in a year. Unlike months (12) and weeks (52) this can be adjusted - legacyannual (default: False) Use the 'AnnualReturn' return analyzer, which as the name implies only works on years Methods: - get_analysis Returns a dictionary with key "sharperatio" holding the ratio ''' params = ( ('timeframe', TimeFrame.Years), ('compression', 1), ('riskfreerate', 0.01), ('convertrate', True), ('daysfactor', 256), ('legacyannual', False), ) RATEFACTORS = { TimeFrame.Weeks: 52, TimeFrame.Months: 12, TimeFrame.Years: 1, } def __init__(self): if self.p.legacyannual: self.anret = AnnualReturn() else: self.timereturn = TimeReturn( timeframe=self.p.timeframe, compression=self.p.compression) def stop(self): super(SharpeRatio, self).stop() if self.p.legacyannual: retfree = [self.p.riskfreerate] * len(self.anret.rets) retavg = average(list(map(operator.sub, self.anret.rets, retfree))) retdev = standarddev(self.anret.rets) self.ratio = retavg / retdev else: rate = self.p.riskfreerate factor = None if self.p.timeframe in self.RATEFACTORS: # rate provided on an annual basis ... downgrade it factor = self.RATEFACTORS[self.p.timeframe] elif self.p.timeframe == TimeFrame.Days: factor = self.p.daysfactor if factor is not None: rate = math.pow(1.0 + rate, 1.0 / factor) - 1.0 returns = list(itervalues(self.timereturn.get_analysis())) retfree = itertools.repeat(rate) ret_free = map(operator.sub, returns, retfree) ret_free_avg = average(list(ret_free)) retdev = standarddev(returns) if retdev != 0: self.ratio = ret_free_avg / retdev if self.p.convertrate else (factor ** .5) * ret_free_avg / retdev else: self.ratio = None self.rets['sharperatio'] = self.ratio
class SharpeRatio(Analyzer): ''' This analyzer calculates the SharpeRatio of a strategy using a risk free asset which is simply an interest rate See also: - https://en.wikipedia.org/wiki/Sharpe_ratio Params: - timeframe: (default: TimeFrame.Years) - compression (default: 1) Only used for sub-day timeframes to for example work on an hourly timeframe by specifying "TimeFrame.Minutes" and 60 as compression - riskfreerate: (default: 0.01 -> 1%) Expressed in annual terms (see ``convertrate`` below) - convertrate (default: True) Convert the ``riskfreerate`` from annual to monthly, weekly or daily rate. Sub-day conversions are not supported - daysfactor (default: 256) On a conversion of annual to daily rate use the value as the number of trading days in a year. Unlike months (12) and weeks (52) this can be adjusted - legacyannual (default: False) Use the 'AnnualReturn' return analyzer, which as the name implies only works on years Methods: - get_analysis Returns a dictionary with key "sharperatio" holding the ratio ''' params = ( ('timeframe', TimeFrame.Years), ('compression', 1), ('riskfreerate', 0.01), ('convertrate', True), ('daysfactor', 256), ('legacyannual', False), ) RATEFACTORS = { TimeFrame.Weeks: 52, TimeFrame.Months: 12, TimeFrame.Years: 1, } def __init__(self): super(SharpeRatio, self).__init__() if self.p.legacyannual: self.anret = AnnualReturn() else: self.timereturn = TimeReturn(timeframe=self.p.timeframe, compression=self.p.compression) def stop(self): if self.p.legacyannual: retfree = [self.p.riskfreerate] * len(self.anret.rets) retavg = average(list(map(operator.sub, self.anret.rets, retfree))) retdev = standarddev(self.anret.rets) self.ratio = retavg / retdev else: rate = self.p.riskfreerate if self.p.convertrate: factor = None if self.p.timeframe in self.RATEFACTORS: # rate provided on an annual basis ... downgrade it factor = self.RATEFACTORS[self.p.timeframe] elif self.p.timeframe == TimeFrame.Days: factor = self.p.daysfactor if factor is not None: rate = math.pow(1.0 + rate, 1.0 / factor) - 1.0 returns = list(itervalues(self.timereturn.get_analysis())) retfree = itertools.repeat(rate) ret_free = map(operator.sub, returns, retfree) ret_free_avg = average(list(ret_free)) retdev = standarddev(returns) self.ratio = ret_free_avg / retdev def get_analysis(self): return dict(sharperatio=self.ratio)