Fundamentals of Return Calculations

Here we discuss a lot of the essential functionality for asset return calculations. We first cover simple return calculations, which are typically reported in practice but are often not convenient for statistical modeling purposes. We then describe continuously compounded return calculations, which are more convenient for statistical modeling purposes.

Customarily, we import as follows:

In [1]: import quantopy as qp

To begin, let’s create some example stock prices like we did in the 10 minutes to quantopy section:

In [2]: stock1_price = [10, 12, 15]

In [3]: stock2_price = [30, 20, 35]

Simple Returns

Consider purchasing an asset (e.g., stock, bond, ETF, option, etc.) at time t-1 for the price Pt-1, and then selling the asset at time t for the price Pt. If there are no intermediate cash flows (e.g., dividends) between t-1 and t, the simple net return on an investment in the asset between t−1 and t is defined as:

\[R_t = \frac{P_{t} − P_{t-1}}{P_{t-1}}\]

And we can define the simple gross return as:

\[1 + R_t = \frac{P_{t}}{P_{t-1}}\]

ReturnSeries.from_price() gives a ReturnSeries with simple returns calculated from a given price for a single asset, letting quantopy create a default integer index:

In [4]: stock1_rs = qp.ReturnSeries.from_price(stock1_price)

In [5]: stock1_rs
Out[5]: 
1    0.20
2    0.25
dtype: float64

To generate the simple returns from a list of multiple asset prices, we use ReturnDataFrame.from_price():

In [6]: stocks_rdf = qp.ReturnDataFrame.from_price(
   ...:    {
   ...:       'stock_1': stock1_price,
   ...:       'stock_2': stock2_price,
   ...:    }
   ...: )
   ...: 

In [7]: stocks_rdf
Out[7]: 
   stock_1   stock_2
1     0.20 -0.333333
2     0.25  0.750000

Multi-period returns

The simple two-month return on an investment in an asset between months t−2 and t is defined as:

\[R_t(2) = (1 + R_t)(1 + R_{t−1}) − 1.\]

Then the simple two-month gross return becomes:

\[1 + R_t(2) = (1+R_t)(1+R_{t−1})\]

In general, the k-month gross return is defined as the product of k one-month gross returns:

\[1 + R_t(k) = \prod_{j=0}^{k-1}(1+R_{t−j})\]

The method cumulated() computes the cumulated indexed values from simple returns.

In [8]: stock1_rs.cumulated()
Out[8]: 
1    1.2
2    1.5
dtype: float64

In [9]: stocks_rdf.cumulated()
Out[9]: 
   stock_1   stock_2
1      1.2  0.666667
2      1.5  1.166667

Average returns

For investments over a given horizon, it is often of interest to compute a measure of the average rate of return over the horizon. To illustrate, consider a sequence of monthly investments over T months with monthly returns R1, R2, … , RT. The T−month return is

\[1 + R(T) = (1+R_1)(1+R_2)...(1+R_T) - 1\]

What is the average monthly return? There are two possibilities. The first is the arithmetic average return

\[\bar{R}^A = \frac{1}{T}(R_1+R_2+···+R_T)\]

The second is the geometric average return

\[\bar{R}^G = [(1+R_1)(1+R_2)...(1+R_T)]^\frac{1}{T} - 1\]

Notice that the geometric average return is the monthly return which compounded monthly for T months gives the gross T−month return

\[(1 + \bar{R}^G)^T = 1 + R(T)\]

Note

The geometric mean is always less than or equal to the arithmetic mean, and the difference increases as the dispersion of the observations increases. The only time the arithmetic and geometric means are equal is when there is no variability in the observations (i.e., all observations are equal).

Since past returns are compounded each period, the geometric mean of past returns is the appropriate measure of past performance. The arithmetic mean is, however, the statistically best estimator of the next year’s returns given only the past returns, athough to estimate multi-year returns (e.g. expected return over the next five years), the geometric mean is the appropriate measure.

The method mean() computes the arithmetic mean of pasts returns.

In [10]: stock1_rs.mean()
Out[10]: 0.22499999999999998

In [11]: stocks_rdf.mean()
Out[11]: 
stock_1    0.225000
stock_2    0.208333
dtype: float64

As we have seen, for the evaluation of the average investment performance, the geometric average return is preferred to the arithmetic average return. The method gmean() computes the geometric mean of pasts returns.

In [12]: stock1_rs.gmean()
Out[12]: 0.22474487139158894

In [13]: stocks_rdf.gmean()
Out[13]: 
stock_1    0.224745
stock_2    0.080123
dtype: float64

Annualizing returns

Very often returns over different horizons are annualized, i.e., converted to an annual return, to facilitate comparisons with other investments. The annualization process depends on the holding period of the investment and an implicit assumption about compounding.

The method annualized() calculates the annualized rate of return, given the compounding period assumption. For monthly returns, we can calculate the annualized return with:

In [14]: stock1_rs.annualized(period=qp.stats.period.MONTHLY)
Out[14]: 10.390624999999988

In [15]: stocks_rdf.annualized(period=qp.stats.period.MONTHLY)
Out[15]: 
stock_1    10.390625
stock_2     1.521626
dtype: float64

We can also compute annualized rate for different periods, like daily, weekly and yearly.

Continuously compounded returns

In this section we define continuously compounded returns from simple returns, and describe their properties.

Let Rtdenote the simple periodic return on an investment. The continuously compounded periodic return, rt, is defined as:

\[r_t = ln(1 + R_t) = ln(\frac{P_t}{P_{t-1}}) = ln(P_t) − ln(P_{t−1}) = p_t − p_{t−1},\]

where pt= ln(Pt). Hence, the continuously compounded return, rt, can be computed simply by taking the first difference of the natural logarithms of the prices.

Using the price and return data from the Simple Return Example, the continuously compounded return of the stocks can be computed as:

In [16]: stock1_rs.log()
Out[16]: 
1    0.182322
2    0.223144
dtype: float64

In [17]: stocks_rdf.log()
Out[17]: 
    stock_1   stock_2
1  0.182322 -0.405465
2  0.223144  0.559616

References

  1. Zivot, E. (2016). Introduction to Computational Finance and Financial Econometrics with R. Springer.