Example #1
0
 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)
Example #2
0
 def __init__(self):
     if self.p.legacyannual:
         self.anret = AnnualReturn()
     else:
         self.timereturn = TimeReturn(
             timeframe=self.p.timeframe,
             compression=self.p.compression)
Example #3
0
 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)
Example #4
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

      - ``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
Example #5
0
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)
Example #6
0
 def __init__(self):
     super(Sortino, self).__init__()
     self.ret = TimeReturn(timeframe=self.p.timeframe,
                           compression=self.p.compression)
     self.ratio = 0.0
Example #7
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
Example #8
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):
        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)