Backtesting Long, Short, and Flat Signals with R Tools
Summary
The document discusses ways to backtest a daily signal that indicates buying, selling, or holding an equity position. It names R packages for strategy testing and portfolio analysis, while noting that a simple strategy can also be modeled with return and position vectors. Aligning trades with the period after a signal helps avoid assuming execution at information that was not yet available.
The answers emphasize that short returns must be compounded using the changing value of the position; multiplying asset returns by a short position can give an incorrect result over multiple periods. Another example shows mapping signals to target positions and using a backtesting package to produce trade records and net asset value. These are implementation suggestions, not a comparison from a controlled benchmark. The appropriate setup still depends on timing, position rules, prices, and other assumptions, which the question does not specify.
Key ideas
- A simple backtest can represent portfolio exposure with position values and combine them with asset returns.
- Trades should be timed after the signal becomes available to avoid look-ahead assumptions.
- Short positions require careful compounding because their return path differs from simply negating long returns.
- R packages can help manage signals, trades, and portfolio performance records.
- Backtest results depend on assumptions about prices, timing, and position management.
Tags
Full text
# Is there a good backtesting package in R?
# Is there a good backtesting package in R?
My model exports a vector that have for each day b-buy s-sell or h- hold it's look like this:
> sig [1] b b s s b b b s s b s b s s b s b s s s s b b s s b b b b b b s b b b b b b b
I want to backtest that it will buy or sell all the equity in the portfolio at the end of each day and for hold will do nothing. what is the best way to backtest in R or other method this strategy?
Thanks
## Answer by Sergey Bushmanov (score 4)
https://quant.stackexchange.com/a/21106
- In R, there are basically two packages to backtest your strategy: `SIT` and `quantstrat`. I personally prefer the former because it's much faster and more transparent in terms of how your positions are managed. In addition, `SIT` gives your more flexibility in how your trading signals are formed.
- If you have a very basic strategy, like long/short/stay on the sidelines, perhaps the best approach to quickly test your strategy is to have 2 vectors like @Rime advised above: one for returns and the other for your positions (either 1, -1, or 0), and multiply them to get returns for your positions when you are in the market (either short or long). Two pieces of advice if I may: Shift your action (buy or sell) one period forward relative to the signal. Short position. Think carefully how you would accumulate profits over multiple periods. If you happen to short a stock which had lost 10% each day for 3 days in a row (i.e. from 100 to 90 on first day, to 81 on second, and to 72.9 on the third day) that wouldn't make you wealthier by 33.1% (1.1^3 -1), as if it were for positive returns on the long side. Your return would rather be 27.1% which you would not get by simply multiplying returns and positions... (more at this blogpost at SIT)
## Answer by Enrico Schumann (score 4)
https://quant.stackexchange.com/a/58085
To add another possibility: Here is how such a model could be run in the PMwR package (which I maintain). It seems that `sig` holds the desired position. Suppose we have a time series of prices `P`.
```
sig <- c("b", "b", "s", "s", "b", "b", "b", "s",
"s", "b", "s", "b", "s", "s", "b", "s",
"b", "s", "s", "s", "s", "b", "b", "s",
"s", "b", "b", "b", "b", "b", "b", "s",
"b", "b", "b", "b", "b", "b", "b")
P <- cumsum(sample(c(1, -1), replace = TRUE, size = length(sig))) + 100
```
Then with `PMwR::btest`, the backtest could be run as follows:
```
library("PMwR")
signal <- function(sig)
switch(sig[Time()], "b" = 1, "s" = 0, NULL)
bt <- btest(P, signal, sig = sig)
## initial wealth 0 => final wealth 10
```
The `signal` function maps `sig` at every point in time to a position of either 1 or 0. The result, stored in `bt`, is a list that stores the details of the backtest.
```
journal(bt)
## instrument timestamp amount price
## 1 asset 1 2 1 100
## 2 asset 1 4 -1 100
## 3 asset 1 6 1 98
## 4 asset 1 9 -1 101
## 5 asset 1 11 1 101
## [....]
plot(NAVseries(bt))
## etc.
```
## Answer by marbel (score 3)
https://quant.stackexchange.com/a/58081
With the following packages I think you have enough tools to develop a backtest:
- quantmod
- PerformanceAnalytics
- xts
I prefer to understand what's happening rather than have all the complexity abstracted away. There are multiple examples in Joshua Ulrich's blog on how to develop a backtest, that should be enough to get started. I've personally also found useful using `data.table` in combination with these packages.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.