Data checks: loading, preparing and checking price series
A backtest is only as good as its prices. Portfolio Lab's data checks examine every price series before any calculation uses it: they look for price jumps, changes of unit, frozen prices and gaps, and report them as notes with the results. This page describes how the series are loaded and prepared, which limits apply and at which point the app does intervene after all.
Where the prices come from
The basis is adjusted daily closing prices: distributions are treated as reinvested and splits are adjusted for. These are therefore total return series in the trading currency. If the source provides fewer than 20 daily prices for a security over its entire history but more monthly values, Portfolio Lab takes the monthly values and dates them to the month-end. Loaded series are cached for twelve hours. After that, only the new days are reloaded, with ten days of overlap as a check: if the overlapping prices differ by more than 0.01%, the source has changed the adjusted history retroactively (for example after a distribution), and the entire series is reloaded. If a download fails, the app keeps calculating with the most recently stored prices (old data are better than none) and reports this with the results in the note “download failed” and “prices only up to …”, together with the date of the last price.
Preparation
- Dates are set to the calendar day without a time zone; duplicate days keep the last price; prices of zero or below are dropped.
- Removing outlier days: a single day on which the price jumps by more than 0.35 in log return (roughly +42% or −30%) and returns to within 0.10 on the following day is deleted. This is the only silent correction. It catches typical single-day errors in fund data.
- Prices in sub-units such as pence or US cents are divided by 100 on download and treated as the main currency. This keeps price and currency consistent even in order lists without a current price. The prices are then converted into the base currency at the day's exchange rate (or, if that is missing, the last known one).
- If a proxy is set, the series is extended backwards with the proxy's returns, joined at the same level.
- Common period: from the latest first price of all securities; up to seven consecutive missing price days are filled with the last price, after which only days on which all securities have a price count.
- If asset classes with monthly values are involved, everything is calculated on month-ends; Monte Carlo, financial goals and ALM use monthly returns anyway.
The check
Every series is checked over the period used, a proxy only up to the start of the security it extends; asset classes with chained long-term series are not checked. A jump is a daily return above a limit that depends on the type of security. Leveraged products (recognised by their name, such as “2x”, “3x”, “Leveraged”, “Short”) get twice the limit, as do series with monthly values (average spacing of more than five days).
| Type | Limit per day |
|---|---|
| Stock | 50% |
| ETF, fund, index | 25% |
| Future | 30% |
| Crypto | 60% |
| Currencies | 15% |
| Other | 30% |
Findings
| Finding | Rule | Severity |
|---|---|---|
| Factor 100 | price jumps to a hundred times or to one hundredth of its value (± 40%): change of unit | severe |
| Cluster | three or more jumps no more than 60 days apart: two price sources or unadjusted splits | severe |
| Large permanent jump | |ln(1 + r)| ≥ ln(1 + 2 × limit) with no reversal, i.e. a factor of 1.5 for ETFs: split or data error | severe |
| Outlier? | jump that reverses by at least 80% within the next three prices | minor |
| Jump | smaller permanent jump (may be a genuine crash) | minor |
| Frozen | at least ten identical daily prices in a row | minor |
| Gap | more than 20 calendar days without a price | minor |
Frozen prices are only reported if the series otherwise moves: if the typical daily move is smaller than 0.1%, as with money market funds or short-term bonds, unchanged prices are normal. The app only checks gaps and frozen prices for daily prices. It reports the longest phase and the number of phases, or the largest gap.
What happens with the findings
All findings appear as a note “Data check …” with the results, severe ones first. For a severe finding, the app adds that results with this series are unreliable and that it is better to choose a proxy, a later start or a different ticker. In the portfolio grid, a warning sign marks securities with a severe finding; it relies on the stored prices, without a new download, and opens the dialogue for setting a proxy. The calculation runs anyway. Apart from the removed outlier days, the check does not change any prices. A single wrong day is enough to show how a faulty price distorts metrics: it creates a spurious return followed shortly by the same loss, raises the volatility and can produce a maximum drawdown that never happened.
Why the limits are so high
Real returns have fat tails: days of −10% or worse occur far more often than a normal distribution would suggest (Mandelbrot 1963; Cont 2001). A strict limit would report genuine crisis days such as October 1987 or March 2020 as errors. That is why the limits are wide, outliers count only as minor, and only what can hardly be genuine is severe: a factor of 100, a cluster of jumps, or a jump of more than twice the limit with no reversal. There is one data problem the app does not check: funds that have been liquidated are missing from any present-day selection. This survivorship bias makes fund averages look better than they were (Brown et al. 1992; Malkiel 1995); more on this in the backtest methodology.
Limitations
- The check only detects conspicuous patterns. A wrong price below the limit, a missing distribution or a wrong currency goes undetected.
- Outlier days above the threshold that reverse on the following day are deleted on loading and therefore do not appear in any note.
- The app only recognises leveraged products by their name.
- If a download fails, the calculation uses stored prices; the note states the last price date, and the analysis then ends earlier.
Frequently asked questions
Does Portfolio Lab correct faulty prices?
No, with one exception: single days with a jump of more than about +42% or −30% that reverses on the following day are removed on loading. Everything else is only reported.
What should I do about a severe finding?
Set a proxy, move the start date later or load the same security under a different ticker. Results with the faulty series are unreliable.
Why is a genuine crash reported?
The check cannot tell a genuine crash from a data error. A single permanent jump below twice the limit (a factor of 1.5 for ETFs) therefore only counts as a minor note to check.
Why doesn't the app report frozen prices for money market funds?
Because their prices hardly move anyway. If the typical daily move is smaller than 0.1%, identical prices over several days are normal.
How up to date are the prices?
The app calculates with the closing prices of completed trading days: it leaves out the current day's price while the exchange is still trading. Stored prices are valid until midnight; after that, the first calculation loads the new days, and for the most frequently used securities this already happens shortly after midnight. Results of identical calculations are also valid until midnight. If there is an error, the app calculates with the most recently stored prices and says so in the note “download failed”, with the date of the last price.
Literature
- Brown, Stephen J.; Goetzmann, William; Ibbotson, Roger G.; Ross, Stephen A. (1992): Survivorship Bias in Performance Studies. Review of Financial Studies 5 (4), pp. 553–580. doi:10.1093/rfs/5.4.553
- Cont, R. (2001): Empirical properties of asset returns: stylized facts and statistical issues. Quantitative Finance 1 (2), pp. 223–236. doi:10.1080/713665670
- Malkiel, Burton G. (1995): Returns from Investing in Equity Mutual Funds 1971 to 1991. The Journal of Finance 50 (2), pp. 549–572. doi:10.1111/j.1540-6261.1995.tb04795.x
- Mandelbrot, Benoit (1963): The Variation of Certain Speculative Prices. The Journal of Business 36 (4). doi:10.1086/294632
This page describes how Portfolio Lab calculates; past results are not a forecast. All terms in the glossary.