Skip to content
All library documents

Block Bootstrapping Returns While Preserving Cross-Asset Dependence

Article Quant Q&A · Author: NoviceProg

Summary

The document raises practical questions about using block bootstrap to generate synthetic histories for a stock portfolio and a market index. Its central concern is preserving pairwise dependence across assets while resampling time-series data. It asks whether synchronized resampling is needed, how to choose block lengths when histories differ, and whether to bootstrap returns or prices.

The example uses a geometric block bootstrap on a single stock’s daily discrete returns, with block length estimated from the data, then compounds the sampled returns to compare cumulative paths. The resulting illustration shows a synthetic path that can diverge substantially from the observed price history. The document poses questions about discrete versus log returns but does not include an accepted answer or establish a recommended method. Its example therefore illustrates implementation and potential path variability, while leaving multivariate synchronization, unequal sample lengths, and return representation unresolved.

Key ideas

  • Resampling assets independently can fail to preserve their pairwise dependence; synchronized multivariate sampling is the relevant issue.
  • Block length affects how much temporal structure remains in simulated return paths.
  • Bootstrapping returns and compounding them produces synthetic price paths that can diverge substantially from history.
  • The example uses geometric blocks on daily discrete returns, but the document does not resolve its methodological questions.

Tags

Full text
# Block bootstrap to synthesize asset prices


# Block bootstrap to synthesize asset prices












I have a few basic questions on block bootstrapping on a financial time series ('TS').

Assuming my trade universe consists of 10 stocks, I would like to create a set of synthetic prices for all 10 stocks plus the S&P500 index using their respective historical prices over the past 10 years. The bootstrap method should maintain, to a fair extent, the linear pairwise correlation among these 10 stocks and with the index at different points in time.

I read from academic literature and online resources that block bootstrap is appropriate for my endeavor. However, I still have the following 4 questions:

(1) I would be implementing in R. Assuming I set the same seed for all 10 stocks + index, does block bootstrap maintain the relative 'pairwise' correlation for them?

(2) Should all 10 stocks use the same block length or individual lengths? Some of the 10 stocks do not have 10 years of historical data.

(3) Is it more appropriate to bootstrap on daily returns or the absolute prices? The former leads to some very volatile outcomes (chart 1) while the latter leads to high 'gappy-ness' (chart 2) in the synthetic prices.

(4) If the answer to (3) is 'daily returns', should it be simple/discrete returns or log returns?

Hope to get some guidance and thanks in advance!

The charts are created in R using the `boot` package. Code for Chart 1 is given below the charts.

CHART 1 (Volatile - synthetic prices ended up 10x the actual at one point):

CHART 2 (Gappy - gap down at start, followed by gap up in middle of chart):

Code for Chart 1

```
library( quantmod )
library( np )
library( PerformanceAnalytics )
library( boot )

# Define dummy function
Fn <- function( aa ) { return ( aa ) }

u_seed <- 25

getSymbols( "AAL" )  # Get Price data

AAL_OHLC <- AAL[ , -( 5:6 ) ]  # Remove unwanted cols

plot( AAL$AAL.Close )

# Compute returns
AAL_DRet <- CalculateReturns( AAL_OHLC, method = "discrete" )
AAL_DRet2 <- AAL_DRet[ -1, ]

# Compute block length
tmp_len <- b.star( AAL_DRet2 )
blk_len <- round( median( tmp_len[ , 1 ] ), 0 )

AALC_DRet <- AAL_DRet2$AAL.Close

for( seed in u_seed )
{
  set.seed( seed )

  z <- tsboot( AALC_DRet, Fn, 1L, l = blk_len, endcorr = T, sim = "geom" )

  # Process new simulated data to xts
  a_BS <- z$t
  dim( a_BS ) <- NULL  # Flatten wide matrix into vector
  names( a_BS ) <- index( AALC_DRet )

  # Chg to xts
  xts_BS <- as.xts( a_BS )
  index( xts_BS ) <- index( AALC_DRet )

  # Plot relative chart
  xts_CumRet <- merge.xts( xts_BS, AALC_DRet )
  palette( bluefocus )
  chart.CumReturns( xts_CumRet, legend.loc = "top", geometric = T )
}
```

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.