TradingView Backtesting

Autocorrelation in Trading Returns: Lag, Overlap and Effective Samples

Autocorrelation measures the linear association between a return series and its own lagged values. Serial correlation is the same idea. Positive dependence can make a long trade list contain much less information about average returns than an equally long independent sample. Define the observation clock, calculate several lags, and check overlap and session patterns before interpreting that dependence as a tradable signal.

See the decision guide

Choose the return and its clock

For account returns without external cash flows, use r(t) = E(t) / E(t-1) - 1 from consistently valued equity, including open positions. Price returns measure the asset instead. A sequence of closed-trade P&L percentages measures trade outcomes; it does not recover daily account returns because exposure, position sizes and elapsed times differ.

  • Use equally spaced periods for the calendar-time ACF interpretation. If sampling trading sessions, call the lag a session lag. Do not silently treat an overnight gap as a five-minute interval.
  • Keep chronological order. Sorting returns by size destroys the time series. Flag missing observations instead of replacing unknown returns with zero or deleting gaps and pretending adjacent records remain adjacent periods.
  • For event-time trade analysis, declare entry order or exit order and how simultaneous events are handled. Overlapping positions and shared market exposure can couple trades even when their identifiers differ.
SeriesMeaning of lag 1Required record
Daily account returnsOne valuation intervalDated equity, costs and cash-flow treatment
Intraday bar returnsOne selected bar intervalSession, timezone, missing bars and overnight policy
Trade outcomes ordered by entryNext entry in a declared orderEntry/exit timestamps, capital basis and tie rule

Calculate the ACF with one denominator convention

For n finite returns and lag k from 0 to n-1, let m be the full-sample mean. Use rho_hat(k) = Σ[t=k+1..n](r(t)-m)(r(t-k)-m) / Σ[t=1..n](r(t)-m)². The numerator has n-k pairs; the denominator uses all n observations at every lag. This is the NIST convention and corresponds to autocovariances each divided by n, so those n factors cancel.

  • Do not substitute Pearson correlation of two truncated vectors: it recenters and rescales each vector separately and can give a different result. An adjusted autocovariance using n-k instead of n also changes nonzero lags; record the software setting.
  • A constant series has zero denominator, so its ACF is undefined, including lag zero. Otherwise rho_hat(0) = 1. Fewer than two observations cannot support a nonzero lag.
  • Large lags have few pairs and noisy estimates. Select the lag range from the holding horizon and session calendar before inspecting which lags look favorable.

Reproduce an eight-return example

The constructed returns, in percentage points, are [-2, -1, 0, 1, 2, 1, 0, -1]. Their mean is zero and squared-deviation sum is 12 pp². Lag 1 has numerator 2 + 0 + 0 + 2 + 2 + 0 + 0 = 6 pp², giving 0.5. These eight values explain arithmetic; they are not observed strategy performance or a sufficient sample for reliable inference.

Lag kPairs n-kCross-product sum (pp²)ACF
08121.000000
1760.500000
26-1-0.083333
35-6-0.500000
44-6-0.500000
Independent Python calculation using the stated full-sample mean and fixed denominator. Returns may use decimals or percentage points, but must use one unit throughout.python
from math import isfinite


def acf(values, max_lag):
    x = [float(value) for value in values]
    n = len(x)
    if n < 2 or not all(isfinite(value) for value in x):
        raise ValueError("Need at least two finite observations")
    if type(max_lag) is not int or not 0 <= max_lag < n:
        raise ValueError("max_lag must be an integer from 0 to n-1")
    mean = sum(x) / n
    centered = [value - mean for value in x]
    denominator = sum(value * value for value in centered)
    if not isfinite(denominator) or denominator <= 0:
        raise ValueError("ACF undefined for constant or numerically invalid data")
    return [
        sum(centered[t] * centered[t-k] for t in range(k, n))
        / denominator
        for k in range(max_lag + 1)
    ]


returns = [-2, -1, 0, 1, 2, 1, 0, -1]
print([round(value, 6) for value in acf(returns, 4)])
# [1.0, 0.5, -0.083333, -0.5, -0.5]

Separate mechanical overlap from predictive dependence

Assume one-period log returns x(t) are independent with common variance sigma². A rolling five-period log return y(t) = x(t) + x(t-1) + ... + x(t-4) shares four increments with y(t-1). Its variance is 5 sigma² and lag-1 covariance is 4 sigma². Its population ACF is therefore 0.8, despite independence of the underlying increments.

  • This exact derivation uses sums of log returns with independent, equal-variance increments. Compounded simple returns, unequal position sizes and changing volatility do not automatically have this ACF.
  • Opening a new five-day position each day also produces overlapping exposure. Actual trade P&L correlation depends on the signal, direction, sizing, exits and costs; the 0.8 value is not a universal estimate for such strategies.
  • Compare non-overlapping returns and preserve the original account timeline. Removing overlap reduces reused increments, but regimes and shared factors can still create dependence.
  • Independent trade shuffling breaks chronological dependence. For inference, consider a justified block resampling design or a heteroskedasticity-and-autocorrelation-consistent covariance estimate, with block length or lag bandwidth declared in advance.
LagShared incrementsPopulation correlation
144/5 = 0.8
233/5 = 0.6
322/5 = 0.4
411/5 = 0.2
5 or more00 under these assumptions

Check time-of-day patterns in return magnitude

Intraday seasonality can repeat in volatility even when signed returns have little linear correlation. Andersen and Bollerslev document that intraday periodicity affects high-frequency volatility dynamics. Inspect the ACF of signed returns and of their squares or absolute values separately, then compare observations from the same session slot.

  • A constructed three-session example has four slots per session: [2, 1, -1, -2], [-2, -1, 1, 2], [2, -1, 1, -2] pp. The squared series is [4, 1, 1, 4] repeated three times. Its mean is 2.5 pp²; the lag-4 cross-product sum is 18 pp⁴ and the denominator is 27 pp⁴, so the squared-return ACF at one session is 2/3.
  • The example deliberately fixes slot magnitudes at [2, 1, 1, 2]. Dividing each return by its slot magnitude makes every squared standardized return equal to 1. The resulting squared-series ACF is undefined, not zero, because no variance remains. This toy construction illustrates a seasonal component rather than estimating a market model.
  • For real data, estimate slot means and positive slot scales on a development sample, freeze them, and inspect z(t) = [r(t) - slot_mean] / slot_scale on later data. Compare raw and standardized diagnostics. Fitting the pattern on the evaluation sample leaks information into the diagnostic workflow.
  • Record exchange timezone, daylight-saving rules, holidays, early closes and the number of valid observations in every slot. Separate overnight returns. A fixed session-length lag is meaningful only when session structure is consistent; do not fill shortened sessions with synthetic zero returns.

Effective sample size describes the precision of a mean

For a covariance-stationary series with finite positive marginal variance gamma(0), the exact variance of its n-observation mean is gamma(0)/n × D(n), where D(n) = 1 + 2 Σ[k=1..n-1](1-k/n) rho(k). Here rho(k) is the population autocorrelation. When D(n) is positive, define n_eff = n/D(n) by matching that mean variance to independent observations with the same marginal variance.

  • For a long series with absolutely summable autocorrelations and a finite positive long-run variance, D(n) approaches tau = 1 + 2 Σ[k=1..infinity] rho(k). Then n_eff is approximately n/tau. Confidence intervals also need conditions for a suitable central limit theorem; stationarity alone is insufficient.
  • In the five-period overlap model, tau = 1 + 2 × (0.8 + 0.6 + 0.4 + 0.2) = 5. Thus 300 overlapping returns, built from 304 independent one-period increments, have mean precision equivalent to about 60 independent five-period returns. The finite-n denominator is 4.973333, giving 60.321716. Neither value counts independent trading opportunities.
  • The shortcut n_eff ≈ n × (1-phi)/(1+phi) assumes a stationary AR(1) model with rho(k) = phi^k and |phi| < 1. For n = 300 and phi = 0.5 it gives 100; phi = -0.5 gives 900. Lag-1 correlation alone does not justify this model or the shortcut.
  • Negative correlation can reduce the variance of the mean, so a defensible n_eff above n is possible. It does not create extra observations or establish the precision of a win rate, quantile or drawdown. Each statistic needs its own uncertainty analysis.
  • Estimated autocorrelations at long lags are noisy. Do not blindly sum all available lags: with full-sample demeaning and this fixed denominator, 1 + 2 × Σ[k=1..n-1] rho_hat(k) is exactly zero. Use a justified long-run variance estimator and disclose its truncation, weights and sensitivity.
  • A nonpositive estimated denominator cannot support a finite positive n_eff. A near-zero denominator or an estimate that changes sharply with bandwidth is unstable; report that failure instead of clamping it to a convenient count. Mean shifts, nonsummable dependence or infinite variance can invalidate the approximation altogether.

Keep the TradingView export and the statistical calculation separate

TradingView exports Strategy Report tabs separately. The List of Trades CSV contains trade information; the Performance Summary export contains metrics. Pineify Backtest Deep Report parses entry and exit timestamps, prices, quantity, net P&L, P&L percentage and excursion fields, and calculates supported results such as net profit and profit factor. Those records can help audit overlapping positions, but a trade CSV alone does not provide a complete account valuation at every bar.

  • Keep the strategy version, symbol, chart interval, session, costs and original CSV. Reconcile the parsed trades and identify common holding intervals before constructing an event-time series.
  • Obtain regularly sampled equity separately for calendar-time account returns. Calculate the ACF, slot adjustment and mean effective sample size independently using the definitions above. These statistics are not claimed as built-in outputs of Backtest Deep Report or the TradingView report.
  • Pine Script AI Coding Agent can help draft custom series output from an explicit specification. Define the clock, valuation policy and missing-data behavior, then review the generated code and compare its values with an independent calculation.
Where Pineify fits

Backtest Deep Report

Review supported metrics and parsed TradingView trade records before performing the separate dependence analysis.

Also useful: Pine Script AI Coding Agent. Draft custom return-series output with explicit observation timing, then reconcile the output independently.

Review Backtest Deep Report

Frequently asked questions

Educational information, not investment advice. All numerical examples are constructed and do not represent measured strategy performance. Dependence diagnostics do not establish causation, trading profitability or future returns.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.