stratanalyzer – Strategy analyzers

Strategy analyzers provide an extensible way to attach different calculations to strategy executions.

class pyalgotrade.stratanalyzer.StrategyAnalyzer

Bases: object

Base class for strategy analyzers.

Note

This is a base class and should not be used directly.

Returns

class pyalgotrade.stratanalyzer.returns.Returns

Bases: pyalgotrade.stratanalyzer.StrategyAnalyzer

A pyalgotrade.stratanalyzer.StrategyAnalyzer that calculates time-weighted returns for the whole portfolio.

getCumulativeReturns()

Returns a pyalgotrade.dataseries.DataSeries with the cumulative returns for each bar.

getReturns()

Returns a pyalgotrade.dataseries.DataSeries with the returns for each bar.

Sharpe Ratio

class pyalgotrade.stratanalyzer.sharpe.SharpeRatio(useDailyReturns=True)

Bases: pyalgotrade.stratanalyzer.StrategyAnalyzer

A pyalgotrade.stratanalyzer.StrategyAnalyzer that calculates Sharpe ratio for the whole portfolio.

Parameters:useDailyReturns (boolean.) – True if daily returns should be used instead of the returns for each bar.
getSharpeRatio(riskFreeRate, annualized=True)

Returns the Sharpe ratio for the strategy execution. If the volatility is 0, 0 is returned.

Parameters:
  • riskFreeRate (int/float.) – The risk free rate per annum.
  • annualized (boolean.) – True if the sharpe ratio should be annualized.

DrawDown

class pyalgotrade.stratanalyzer.drawdown.DrawDown

Bases: pyalgotrade.stratanalyzer.StrategyAnalyzer

A pyalgotrade.stratanalyzer.StrategyAnalyzer that calculates max. drawdown and longest drawdown duration for the portfolio.

getLongestDrawDownDuration()

Returns the duration of the longest drawdown.

Return type:datetime.timedelta.

Note

Note that this is the duration of the longest drawdown, not necessarily the deepest one.

getMaxDrawDown()

Returns the max. (deepest) drawdown.

Trades

class pyalgotrade.stratanalyzer.trades.Trades

Bases: pyalgotrade.stratanalyzer.StrategyAnalyzer

A pyalgotrade.stratanalyzer.StrategyAnalyzer that records the profit/loss and returns of every completed trade.

Note

This analyzer operates on individual completed trades. For example, lets say you start with a $1000 cash, and then you buy 1 share of XYZ for $10 and later sell it for $20:

  • The trade’s profit was $10.
  • The trade’s return is 100%, even though your whole portfolio went from $1000 to $1020, a 2% return.
getCount()

Returns the total number of trades.

getProfitableCount()

Returns the number of profitable trades.

getUnprofitableCount()

Returns the number of unprofitable trades.

getEvenCount()

Returns the number of trades whose net profit was 0.

getAll()

Returns a numpy.array with the profits/losses for each trade.

getProfits()

Returns a numpy.array with the profits for each profitable trade.

getLosses()

Returns a numpy.array with the losses for each unprofitable trade.

getAllReturns()

Returns a numpy.array with the returns for each trade.

getPositiveReturns()

Returns a numpy.array with the positive returns for each trade.

getNegativeReturns()

Returns a numpy.array with the negative returns for each trade.

getCommissionsForAllTrades()

Returns a numpy.array with the commissions for each trade.

getCommissionsForProfitableTrades()

Returns a numpy.array with the commissions for each profitable trade.

getCommissionsForUnprofitableTrades()

Returns a numpy.array with the commissions for each unprofitable trade.

getCommissionsForEvenTrades()

Returns a numpy.array with the commissions for each trade whose net profit was 0.

Example

Save this code as sma_crossover.py:

from pyalgotrade import strategy
from pyalgotrade.technical import ma
from pyalgotrade.technical import cross


class SMACrossOver(strategy.BacktestingStrategy):
    def __init__(self, feed, instrument, smaPeriod):
        strategy.BacktestingStrategy.__init__(self, feed)
        self.__instrument = instrument
        self.__position = None
        # We'll use adjusted close values instead of regular close values.
        self.setUseAdjustedValues(True)
        self.__prices = feed[instrument].getPriceDataSeries()
        self.__sma = ma.SMA(self.__prices, smaPeriod)

    def getSMA(self):
        return self.__sma

    def onEnterCanceled(self, position):
        self.__position = None

    def onExitOk(self, position):
        self.__position = None

    def onExitCanceled(self, position):
        # If the exit was canceled, re-submit it.
        self.__position.exitMarket()

    def onBars(self, bars):
        # If a position was not opened, check if we should enter a long position.
        if self.__position is None:
            if cross.cross_above(self.__prices, self.__sma) > 0:
                shares = int(self.getBroker().getCash() * 0.9 / bars[self.__instrument].getPrice())
                # Enter a buy market order. The order is good till canceled.
                self.__position = self.enterLong(self.__instrument, shares, True)
        # Check if we have to exit the position.
        elif not self.__position.exitActive() and cross.cross_below(self.__prices, self.__sma) > 0:
            self.__position.exitMarket()

and save this code in a different file:

from pyalgotrade.barfeed import yahoofeed
from pyalgotrade.stratanalyzer import returns
from pyalgotrade.stratanalyzer import sharpe
from pyalgotrade.stratanalyzer import drawdown
from pyalgotrade.stratanalyzer import trades
import sma_crossover

# Load the yahoo feed from the CSV file
feed = yahoofeed.Feed()
feed.addBarsFromCSV("orcl", "orcl-2000.csv")

# Evaluate the strategy with the feed's bars.
myStrategy = sma_crossover.SMACrossOver(feed, "orcl", 20)

# Attach different analyzers to a strategy before executing it.
retAnalyzer = returns.Returns()
myStrategy.attachAnalyzer(retAnalyzer)
sharpeRatioAnalyzer = sharpe.SharpeRatio()
myStrategy.attachAnalyzer(sharpeRatioAnalyzer)
drawDownAnalyzer = drawdown.DrawDown()
myStrategy.attachAnalyzer(drawDownAnalyzer)
tradesAnalyzer = trades.Trades()
myStrategy.attachAnalyzer(tradesAnalyzer)

# Run the strategy.
myStrategy.run()

print "Final portfolio value: $%.2f" % myStrategy.getResult()
print "Cumulative returns: %.2f %%" % (retAnalyzer.getCumulativeReturns()[-1] * 100)
print "Sharpe ratio: %.2f" % (sharpeRatioAnalyzer.getSharpeRatio(0.05))
print "Max. drawdown: %.2f %%" % (drawDownAnalyzer.getMaxDrawDown() * 100)
print "Longest drawdown duration: %s" % (drawDownAnalyzer.getLongestDrawDownDuration())

print
print "Total trades: %d" % (tradesAnalyzer.getCount())
if tradesAnalyzer.getCount() > 0:
    profits = tradesAnalyzer.getAll()
    print "Avg. profit: $%2.f" % (profits.mean())
    print "Profits std. dev.: $%2.f" % (profits.std())
    print "Max. profit: $%2.f" % (profits.max())
    print "Min. profit: $%2.f" % (profits.min())
    returns = tradesAnalyzer.getAllReturns()
    print "Avg. return: %2.f %%" % (returns.mean() * 100)
    print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
    print "Max. return: %2.f %%" % (returns.max() * 100)
    print "Min. return: %2.f %%" % (returns.min() * 100)

print
print "Profitable trades: %d" % (tradesAnalyzer.getProfitableCount())
if tradesAnalyzer.getProfitableCount() > 0:
    profits = tradesAnalyzer.getProfits()
    print "Avg. profit: $%2.f" % (profits.mean())
    print "Profits std. dev.: $%2.f" % (profits.std())
    print "Max. profit: $%2.f" % (profits.max())
    print "Min. profit: $%2.f" % (profits.min())
    returns = tradesAnalyzer.getPositiveReturns()
    print "Avg. return: %2.f %%" % (returns.mean() * 100)
    print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
    print "Max. return: %2.f %%" % (returns.max() * 100)
    print "Min. return: %2.f %%" % (returns.min() * 100)

print
print "Unprofitable trades: %d" % (tradesAnalyzer.getUnprofitableCount())
if tradesAnalyzer.getUnprofitableCount() > 0:
    losses = tradesAnalyzer.getLosses()
    print "Avg. loss: $%2.f" % (losses.mean())
    print "Losses std. dev.: $%2.f" % (losses.std())
    print "Max. loss: $%2.f" % (losses.min())
    print "Min. loss: $%2.f" % (losses.max())
    returns = tradesAnalyzer.getNegativeReturns()
    print "Avg. return: %2.f %%" % (returns.mean() * 100)
    print "Returns std. dev.: %2.f %%" % (returns.std() * 100)
    print "Max. return: %2.f %%" % (returns.max() * 100)
    print "Min. return: %2.f %%" % (returns.min() * 100)

The output should look like this:

Final portfolio value: $1295887.22
Cumulative returns: 29.59 %
Sharpe ratio: 0.70
Max. drawdown: 24.53 %
Longest drawdown duration: 277 days, 0:00:00

Total trades: 13
Avg. profit: $14437
Profits std. dev.: $127539
Max. profit: $420866
Min. profit: $-89320
Avg. return:  2 %
Returns std. dev.: 13 %
Max. return: 46 %
Min. return: -7 %

Profitable trades: 3
Avg. profit: $197053
Profits std. dev.: $158987
Max. profit: $420866
Min. profit: $66537
Avg. return: 21 %
Returns std. dev.: 18 %
Max. return: 46 %
Min. return:  6 %

Unprofitable trades: 10
Avg. loss: $-40348
Losses std. dev.: $23601
Max. loss: $-89320
Min. loss: $-4516
Avg. return: -3 %
Returns std. dev.:  2 %
Max. return: -0 %
Min. return: -7 %

Table Of Contents

Previous topic

strategy – Basic strategy classes

Next topic

plotter – Strategy plotter

This Page