Search code examples
pythonpandasnumpyquantitative-finance

given total returns and dividends, vectorize the implied price


consider the time series of total return indices tr_idx

import pandas as pd
import numpy as np

np.random.seed([314,15])
n = 5
tidx = pd.date_range('2015-12-31', periods=n)
lognormal_kw = dict(mean=2e-4, sigma=1e-2, size=n)
tr_idx = pd.Series(np.random.lognormal(**lognormal_kw),
                   tidx, name='TRIdx')

tr_idx

2015-12-31    0.999499
2016-01-01    1.014569
2016-01-02    1.002259
2016-01-03    0.988591
2016-01-04    0.987725
Freq: D, Name: TRIdx, dtype: float64

and a time series of dividends paid

div = pd.Series(1e-3, tidx, name='Div')
div

2015-12-31    0.001
2016-01-01    0.001
2016-01-02    0.001
2016-01-03    0.001
2016-01-04    0.001
Freq: D, Name: Div, dtype: float64

How Do I Vectorize The Implied Price Calculation?

We know the total return can be calculated as

enter image description here

Which we can back out the price calculation

enter image description here

I can use these formulas in a loop like this

price = pd.Series(np.nan, tidx, name='Price')

p0 = 100  # Initial Price
for i, (date, prc) in enumerate(price.iteritems()):
    p0 = price.iloc[i] = tr_idx.iloc[i] * p0 - div.iloc[i]

And view the results

pd.concat([tr_idx, div, price], axis=1)

enter image description here


Solution

  • Here's a vectorized approach using broadcasting -

    p0 = 100  # Initial Price
    y1 = np.append(tr_idx.values,1)[::-1].cumprod()[::-1]
    y2 = np.append(p0,-div.values)
    price_out = np.tril(y1/y1[:,None]*y2).sum(1)[1:]