Turning Long, Flat, and Short Signals into Backtest Returns
Summary
The document asks how to backtest and plot a strategy whose signals indicate long, flat, or short exposure, using historical prices. The proposed calculation forms log price returns, multiplies them by the prior period’s signal to represent the position held over the return interval, and plots cumulative returns after exponentiating their cumulative sums. The questioner reports that the resulting chart looks wrong but does not provide enough detail about the data, signal timing, or graph to diagnose the specific cause.
The answer points to established Python backtesting and performance-analysis libraries as examples of standard workflows. It describes the general sequence of converting signals into positions, positions into returns, and returns into cumulative performance or summary statistics. These references offer implementation patterns, but the document does not explain the reported discrepancy or present a corrected calculation. A sound backtest still depends on consistent timing conventions and appropriate treatment of costs and other trading assumptions, which are not worked through here.
Key ideas
- A trading signal can be shifted to represent the position held during the next return interval.
- Log price returns multiplied by positions can be accumulated and exponentiated to visualize compounded performance.
- Backtesting workflows commonly distinguish signals, positions, and resulting returns.
- The answer recommends consulting established tools for return calculations and performance charts.
- The provided information is insufficient to identify the specific cause of the charting problem.
Tags
Full text
# "Backtesting" from trading signals and historical prices not functioning properly # "Backtesting" from trading signals and historical prices not functioning properly How does one go about properly backtesting and visualising their strategy using their trading signals and historical prices where the trading signals are 1 for long, 0 for no position -1 for short? Obviously the end result should look something like this, this visual originates from a simple moving average strategy from "Python for Finance" My strategy is not the same however since the trading signals are just 1s and -1s I would expect to be able to get a similar result, however when I try using the following code, I get the following graph, and I have absolutely no idea why. ``` data['XONRETURNS'] = np.log(data['XON'] / data['XON'].shift(1)) data['XONSTRATEGY'] = (data['POSITIONXON'].shift(1)) * (data['XONRETURNS']) ax = data[['XONRETURNS', 'XONSTRATEGY']].cumsum().apply(np.exp).plot(figsize=(10, 6)) ``` XON is simply the raw price data and XON strategy is using the trading signals i.e. POSITIONXON. My suspicion is that either the returns or something relating to taking the log(or not) is causing this issue? General answers on backtesting from trading signals will also be very helpful so that I can start from scratch if need be. Many thanks! ## Answer by Brian from QuantRocket (score 1) https://quant.stackexchange.com/a/70600 There's plenty of open source code out there that can point you in the right direction. - Moonshot is a vectorized backtester developed by QuantRocket that uses 1, -1, and 0 for signals. The base.py module has functions that turn DataFrames of signals into positions and positions into returns. - Moonchart is an accompanying visualization library. Check out the utils.py module for an example of turning a Series or DataFrame of returns into cumulative returns. - Empyrical is another library with similar utility functions as Moonchart for calculating cumulative returns, Sharpe ratio, CAGR, etc. It was developed by the now-defunct company Quantopian. Check out the stats.py module for most of the core functions. - Empyrical is used as a helper library by Pyfolio, a visualization library that was also developed by Quantopian. All of these packages are based on standard Python data science libraries (pandas, numpy, matplotlib, etc). You probably don't need to install the packages themselves but can just lift relevant snippets of code that show how to calculate the various performance metrics.
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.