Quantitative models all require the correct calculation of performance and returns. Some stylized analysis can be done using time series analysis with no regard for actual portolio transactions data. They can be done using weights and returns. However, as the model backtests become more complicated, these approaches easily develop subtle mathematical errors which invalidate the final performance results. These errors typically involve money “leaking in” or “leaking out” of the portfolio. Defining an accounting system which tracks portfolio decisions as if they are portfolio transactions with actual nominal amount of money and with transaction costs avoids these mathematical errors. Accounting identities preclude money to mysteriously leak in or out of the system.
Fixed number of assets to buy and hold with no leverage. USD cash is one such asset.
Distinguish and calculate pre- and post- trade weights of the portfolio.
Portfolio is traded at discrete regular intervals. Transactions are instantaneous and can only occur at the interval time points. Portfolio manager receives information at the pre- trade instant, process the information and take action instanteously at the post- trade instant. No market price fluctuations are assumed to occur between pre- and post- trade instants.
The starting condition of the portfolio at time \(t=0\) is an initial endowment of cash \(C_0\).
Transactions are not costless. A fixed transaction fee rate is charged to the market value of the traded assets upon purchase or sale. It is deducted from the cash balance of the portfolio at the post- trade instant of the transaction.
A minimum level of cash should be maintained to cover transaction costs since negative cash balances should be limited or avoided.
Asset returns are provided for each period.
Asset/Portfolio position values are needed at each period.
The time is split into intervals (which represent economically meaningful periods) where asset returns change, interest is accrued and news is developed. Each time interval is marked by a start and end point (a time point). Time is divided into consecutive, equal and linearly ordered time intervals. Each time point (denoted \(t\)) is composed of two instants. The pre-trade instant \(A(t)\) is when asset returns over the prior interval are observed. Asset transactions at time point \(t\) are executed at the post-trade instant \(B(t)\) using the asset prices provided at \(Pre(t)\).
\(s\) = security index variable in the portfolio.
\(\kappa\) = cash asset. No transaction costs apply to cash movements.
\(r_{f}(t)\) denotes the risk-free cash interest rate for 1-period forward \([t,t+1]\).
\(A(t)\) = pre-trade instant of time.
\(B(t)\) = post-trade instant of time.
\(\gamma\) = one-way transaction cost on the market-value of any non-cash asset \(s\). Typically example \(\gamma = 0.00025\) or 2.5 basis points per 1-way trade.
\(t=0..T\) is the time index for the backtest period.
\(t=0\) is the initial period when capital is allocated.
\(K_0\) is the initial capital endowment for the backtest.
| Time | Price | Paydown | Cpn/Div | Note |
|---|---|---|---|---|
| \(B(t-1)\) | \(L(s,t-1)\) | |||
| \(A(t)\) | \(L(s,t)\) | \(f(s,t)\) | \(g(s,t)\),\(h(s,t)\) | Pre-trade Instant of time \(t\) |
| \(B(t)\) | \(L(s,t)\) | Post-trade Instant of time \(t\) |
| Time | Quantity | Pos. MV | Pos. Weight | Traded Qty | Trans Cost | Port MV |
|---|---|---|---|---|---|---|
| \(B(t-1)\) | \(M(s,B(t-1))\) | \(P(s,B(t-1))\) | \(w(s,B(t-1))\) | \(Q(s,B(t-1))\) | \(c(s,B(t-1))\) | \(G(B(t-1))\) |
| \(A(t)\) | \(M(s,A(t))\) | \(P(s,A(t))\) | \(w(s,A(t))\) | \(G(A(t))\) | ||
| \(B(t)\) | \(M(s,B(t))\) | \(P(s,B(t))\) | \(w(s,B(t))\) | \(Q(s,B(t))\) | \(c(s, B(t))\) | \(G(B(t))\) |
We initialize the backtest by allocating capital \(K_0\) at time \(t=0\) at instant \(A(0)\).
\(w(\kappa, A(0)) = 1\) sets up cash as the only initial security with non-zero weight. Weights have units of fraction of one. \(w(s, A(0)) = 0\) for \(s \ne \kappa\).
\(M(\kappa, A(0)) = K_0\)
\(M(s, A(0)) = 0\) for \(s \ne \kappa\).
\(L(\kappa, t) = 1\) for all \(t\). Price of cash is always 1.0 in investor’s base currency.
\(P(s,A(0)) = M(s, A(0)) \dot L(s,A(0))\) means position market value equals position quantity times price.
\(G(A(0)) = \sum_{s} P(s, A(0) )\) means portfolio market value is sum of position market values.
Without loss of generality, we can assume the initial trades of the backtest occur at \(t=1\). That is, we can assume cash is not instanteously invested into tradeable positions at time \(t=0\). Where this assume does not hold, we can trivial start the backtest one period earlier and assume cash risk free rate is zero in that prior period.
The above conditions therefore allow us to work out the position at \(B(0)\):
\(w(\kappa, B(0)) = 1\)
\(w( s, B(0)) = 0\) for \(s \ne \kappa\).
\(M(\kappa, B(0)) = M(\kappa, A(0)) = K_0\).
\(M(s, B(0)) = 0\) for \(s \ne \kappa\).
\(G(B(0)) = G(A(0)) = K_0\)
We calculate the iterative steps in a sequence of calculations which assumes the initialization conditions of the backtest hold. We assume the portfolio conditions for period \(B(t-1)\) are previously calculated and available to us.
First, we check for any corporate actions that impact our position quantity or cash balance.
For a single non-cash security, the cash flows associated with paydown of principal, coupon interest income or equity dividend income are:
\[Income(s,A(t)) = M(s,B(t-1)) \left[ P(s) \cdot [1 - \frac{f(s, t)}{f(s,t-1)} + g(s,t) ]+ h(s, t) \right]\]
In the above equation, \(P(s)\) denotes the par price at which principal paydown and coupon income is paid to the investor. Normally, \(P(s)=100\%\). In addition, \(f(s,t)\) is expressed as the fraction of original face remaining after the \(t\) principal payment. Likewise, \(g(s,t)\) is the coupon rate due on time point \(t\) on the current face \(M(s,B(t-1))P(s)\). However, the equity dividend \(h(s,t)\) is quoted in units of money per share. In the case of equities, \(M(s,B(t-1))\) would denote the number of shares. If \(s\) is a fixed income bond, \(M(s,B(t-1))\) denote the current face as of \(B(t-1)\), i.e. after paydowns made at timepoint \(t-1\).
Thus, we update the cash balance to be:
\[M(\kappa, A(t)) = M(\kappa, B(t-1)) \cdot (1 + r_{f}(t-1)) + \sum_{s \ne \kappa} Income(s, A(t)) \] \[M(\kappa, A(t)) = M(\kappa, B(t-1))(1+r_{f}(t-1)) + \sum_{s \ne \kappa} M(s, B(t-1))[ P(s)((1-\frac{f(s,t)}{f(s,t-1)}) + g(s,t)) + h(s,t)] \]
We update the position quantity to be:
\[M(s, A(t)) = M(s, B(t-1)) \cdot f(s, t) \text{ for principal paydowns where } s \ne \kappa \]
We set the position market value to be:
\[P(s, A(t)) = M(s, A(t)) \cdot L(s,t) \text{ market value equals position quantity times price }\]
We set the pre-trade portfolio market value to be:
\[G(A(t)) = \sum_{s} P(s, A(t))\]
We define the position weight (pre-trade) to be:
\[w(s, A(t)) = \frac{P(s,A(t))}{G(A(t))} \text{ (position weight depends on position market value) } \]
Since the strategy manager will calculate the target position weights (for all non-cash assets), we obtain the traded market value at time \(B(t)\):
\[Q(s, B(t)) = w(s, B(t)) \cdot G(A(t)) - P(s, A(t)) \text{ where } s \ne \kappa \]
The trading cost is defined in terms of the traded market value of each position:
\[c(s,B(t)) = \gamma \cdot | Q(s, B(t)) | \text{ where } s \ne \kappa\]
The post-trade position quantity is defined in terms of the target weight for non-cash assets:
\[M(s, B(t)) = \frac{w(s, B(t)) \cdot G(A(t))}{L(s, t)} \text{ where } s \ne \kappa \text{ and } L(s, t) \ne 0\]
The post-trade position quantity is defined in terms of the target weight for non-cash assets where the market price is zero is unchanged:
\[M(s, B(t)) = M(s, A(t)) \text{ where } s \ne \kappa \text{ and } L(s, t ) = 0\]
The post-trade cash balance is updated for cash outflows for purchases minus sales and transaction costs:
\[M(\kappa, B(t)) = M(\kappa, A(t)) - \sum_{s \ne \kappa} Q(s, B(t)) - \sum_{s \ne \kappa} c(s, B(t)) \]
The post-trade position market value is simply post-trade quantity times price:
\[ P(s, B(t)) = M(s, B(t)) \cdot L(s, B(t)) \] The post-trade portfolio value is:
\[ G(B(t)) = \sum_{s} P(s, B(t)) \]
These equations define how accounting works for a quantitative backtest model. Where the strategy signal can be computed by the model, the accounting identities above solve the problem of properly tracking portfolio values to avoid the leakage of cash or portfolio value in unexplained ways. The key is to recognize that all cash and portfolio quantities can only change for well-defined reasons. The accounting identities are invariant under all asset returns or strategy signals.
A few limitations of the accounting identities need to be clarified:
num_sec = 10
sec_data = data.frame( A_qty = vector(mode="double", length=num_sec),
B_qty = vector(mode="double", length=num_sec),
A_pos_mv = vector(mode="double", length=num_sec),
B_pos_mv = vector(mode="double", length=num_sec) )