QSTrader Asset Class Hierarchy

In this new article series we are going to begin looking at the classes within the QSTrader open source backtesting engine. This particular article will discuss the Asset class hierarchy.

In this new series of articles we are going to begin discussing the implementation for all of the Python object oriented classes associated with QuantStart's QSTrader open source backtesting tool. This particular article will cover the Asset class hierarchy, which is responsible for encapsulating aspects of tradeable assets within the backtesting system.

As of the publishing date of this article the two available derived subclasses of Asset are Cash and Equity. Each of these two subclasses are simple extensions of the base class, which contains no interface specification at this stage. The reason for the use of this class hierarchy is to allow future development and interface specification when more sophisticated assets, such as derivatives are developed.

We will begin by defining the Asset base class:

from abc import ABCMeta


class Asset(object):
    """
    Generic asset class that stores meta data about a trading asset.
    """

    __metaclass__ = ABCMeta

There are no abstract methods on this class but it does provide a placeholder for future interface specification.

The first derived subclass is Cash. This represents the 'cash asset' that will be held in a brokerage account when any tradeable assets have yet to be purchased. It contains two attributes. The first is the cash_like boolean, which simply tells the asset whether it is 'cash like' or not. The second is a string describing which currency the cash belongs to. This defaults to US dollars:

from qstrader.asset.asset import Asset


class Cash(Asset):
    """
    Stores meta data about a cash asset.
    Parameters
    ----------
    currency : str, optional
        The currency of the Cash Asset. Defaults to USD.
    """

    def __init__(
        self,
        currency='USD'
    ):
        self.cash_like = True
        self.currency = currency

The more interesting derived subclass is the Equity asset. This contains a simple set of attributes that store information about a common stock or exchange traded fund (ETF). In particular it has a name and a ticker symbol. The latter does not yet have any functionality for ticker mapping, which would be necessary in a more robust institutional settings. The third attribute, tax_exempt is a boolean specific to certain geographic regions that tells the backtesting system whether the asset should have taxation applied on transactions. An example of such a taxation is UK stamp duty:

from qstrader.asset.asset import Asset


class Equity(Asset):
    """
    Stores meta data about an equity common stock or ETF.

    Parameters
    ----------
    name : `str`
        The asset's name - the company name and/or
        share class.
    symbol : `str`
        The asset's original ticker symbol.
    tax_exempt: `boolean`, optional
        Is the share exempt from government taxation?
        Necessary for taxation on share transactions, such
        as UK stamp duty.
    """

    def __init__(
        self,
        name,
        symbol,
        tax_exempt=True
    ):
        self.cash_like = False
        self.name = name
        self.symbol = symbol
        self.tax_exempt = tax_exempt

    def __repr__(self):
        """
        String representation of the Equity Asset.
        """
        return (
            "Equity(name='%s', symbol='%s', tax_exempt=%s)" % (
                self.name, self.symbol, self.tax_exempt
            )
        )

Notice that all of the asset subclasses contain a __repr__ double-underscore—'dunder'—method to allow a representation string. The intent here is to allow each asset to be fully replicated from this representation. This would be the case if it was typed directly into a Python console, for instance.

In the next article of the series we will be taking a look at simulating a brokerage, by considering the FeeModel class hierarchy. This is used to specify a brokerage's commission and fee structure, which is necessary to appropriately model trading transaction costs.