Skip to content
All library documents

Interpreting Moving-Average Positions in an R Backtest

Article Quant Q&A · Author: Eka

Summary

The document explains a simple SPY backtest that compares the closing price with its 20-day simple moving average. The signal assigns a position of long exposure when the close is above the average and short exposure when it is below. Multiplying daily asset returns by the lagged position estimates strategy returns, with the lag intended to apply the prior signal to the next return period and avoid using a signal before it is known.

The code then binds the asset’s daily returns and the strategy returns as separate columns and passes them to a performance summary chart. This lets a reader compare the buy-and-hold series with the strategy’s return path. The explanation clarifies what the position values and column binding mean, but it does not evaluate the strategy’s results or discuss practical backtest details such as transaction costs, slippage, or signal timing conventions. Those omissions limit what can be inferred from the chart as evidence of tradable performance.

Key ideas

  • A position of one represents long exposure, while negative one represents short exposure.
  • The strategy return series is formed by multiplying asset returns by the lagged position.
  • Lagging the signal applies the previously determined position to the next return period.
  • Column binding places the underlying returns and strategy returns side by side for charting.
  • The explanation does not assess costs or establish that the strategy is profitable in live trading.

Tags

Full text
# What is the logic behind this backtesting code in R


# What is the logic behind this backtesting code in R












I am new to R and I have found this simple backtesting code and can you explain me what is happening here.

```
library(quantmod)
library(PerformanceAnalytics)

s <- get(getSymbols('SPY'))["2012::"]
s$sma20 <- SMA(Cl(s) , 20)
s$position <- ifelse(Cl(s) > s$sma20 , 1 , -1)
myReturn <- lag(s$position) * dailyReturn(s)
charts.PerformanceSummary(cbind(dailyReturn(s),myReturn))
```

I know the code uses this strategy

```
    Buy    
    close > SMA20
    sell
    close < SMA20
```

But I have doubts especially in these lines

```
s$position <- ifelse(Cl(s) > s$sma20 , 1 , -1) 
myReturn <- lag(s$position) * dailyReturn(s)
charts.PerformanceSummary(cbind(dailyReturn(s),myReturn))
```

`s$position <- ifelse(Cl(s) > s$sma20 , 1 , -1)` if close price is greater than 20 days moving average then `s$postion=1` else `s$postion=-1`, Buy why assign 1 and -1? why calculating dailyreturns and whats is happing with myReturn,cbind()? Also can you explain this results https://i.sstatic.net/B1h7E.png

## Answer by Forgottenscience (score 2, accepted)

https://quant.stackexchange.com/a/19234

When position = 1, then you are long the S&P ETF. When position is -1, your portfolio consist of a short position of -1 S&P ETF. You will therefore have a vector like $Pos = (1,1,1,1,1,-1,-1,-1,-1,1,1,1,-1,-1,-1, \ldots)$, that will give you the evolution of your portfolio.

Your returns are then the daily returns on the S&P multiplied by your position.

Cbind is the command for binding two vector together by their columns. So you take the evolution of the S&P (dailyReturns) and column-bind them with the evolution of your portfolio (myReturn), and plot them using the PerformanceAnalytics package.

Shown in full with attribution under the source's licence. Licence: CC BY-SA 4.0 (Stack Exchange)

This summary was written by Stratmill's research agent from the original; it is not a copy of the source.