Skip to content
All library documents

Estimating Gain–Loss Asymmetry with First-Passage Times

Article Quant Q&A · Author: vonjd

Summary

The document presents ways to examine the financial-market stylized fact that upward moves can take longer than downward moves. One R example calculates, from each starting day, how long cumulative returns take to first cross positive and negative target levels, then compares the normalized distributions of those durations. It uses a broad equity index as an illustration and notes that detrending and fitting a probability distribution are absent from the example.

A second approach enumerates holding periods in a return series, groups them by rounded cumulative return, and compares average durations for matched positive and negative return levels. It also compares duration distributions for a chosen gain and loss threshold. The examples show how sampling frequency and data choices can affect the picture; the second author reports a different pattern with monthly data. These are exploratory plotting methods, and the document does not establish that the asymmetry is robust or statistically significant.

Key ideas

  • First-passage durations can be measured from each start date to positive and negative return thresholds.
  • Comparing duration distributions can help visualize gain–loss asymmetry.
  • An alternative method groups holding periods by rounded cumulative return and compares average lengths.
  • The examples omit detrending and probability-distribution fitting.
  • Sampling frequency may change the apparent asymmetry.

Tags

Full text
# Tools/R-code to create gain/loss-asymmetry plots


# Tools/R-code to create gain/loss-asymmetry plots












The gain/loss asymmetry is a well known stylized fact: It basically states that real financial time series take longer for going up than going down.

To detect it a heavy statistical machinery is needed: Detrending the time series, calculating the inverse statistics, normalizing the distribution, fitting a Generalized Gamma distribution... to name but a few.

The result are plots like these (from http://papers.ssrn.com/sol3/papers.cfm?abstract_id=844364):

My question I want to reproduce those plots. Do you know any software, tools and/or preferably R code/packages with which this can be done? Every little hint may be helpful - Thank you.

## Answer by vonjd (score 2, accepted)

https://quant.stackexchange.com/a/37742

I wrote an R function to create those plots:

```
library(quantmod)

getSymbols("^GSPC", from = "1950-01-01")
## [1] "GSPC"

inv_stat <- function(symbol, name, target = 0.05) {
  p <- coredata(Cl(symbol))
  end <- length(p)
  days_n <- days_p <- integer(end)

  # go through all days and look when target is reached the first time from there
  for (d in 1:end) {
    ret <- cumsum(as.numeric(na.omit(ROC(p[d:end]))))
    cond_n <- ret < -target
    cond_p <- ret > target
    suppressWarnings(days_n[d] <- min(which(cond_n)))
    suppressWarnings(days_p[d] <- min(which(cond_p)))
  }

  days_n_norm <- prop.table(as.integer(table(days_n, exclude = "Inf")))
  days_p_norm <- prop.table(as.integer(table(days_p, exclude = "Inf")))

  plot(days_n_norm, log = "x", xlim = c(1, 1000), main = paste0(name, " gain-/loss-asymmetry with target ", target), xlab = "days", ylab = "density", col = "red")
  points(days_p_norm, col = "blue")

  c(which.max(days_n_norm), which.max(days_p_norm))
}

inv_stat(GSPC, name = "S&P 500")
 ## [1] 10 24
```

The following plot is being produced (will take some time):

Two things are missing:

- Detrending of time series

- Fitted probability distribution

If you want to add them or if you have ideas how to improve the code, please let me know!

## Answer by Kyle Balkissoon (score 2)

https://quant.stackexchange.com/a/19122

Here is a quick example, you grab the total returns for each holding period, avg them out and compare the days for each level of return.

You can change tmp1 for whatever is your preferred filtered data set.

```
 require(PerformanceAnalytics)

require(sqldf)
data(edhec)

tmp1=edhec[,1]

period_seq = 1:nrow(tmp1)
combos=expand.grid(period_seq,period_seq)
###Remove impossible investments
combos=combos[combos[,2]>combos[,1],]
colnames(combos) = c('start','finish')
combos$day_length = combos[,2]-combos[,1]
###Calculater return for each period
combos$perreturn=NA

###Calculate return for each combo

for(i in 1:nrow(combos)){
  combos[i,]$perreturn = as.numeric(last(cumprod(1+(tmp1[combos[i,1]:combos[i,2]])))-1)

}

###Round the total return
combos$roundedperreturn = round(combos$perreturn,2)
###Calulate the avg day length per return level
ans=sqldf('select avg(day_length) as avg_day_length,roundedperreturn as return_level from combos group by 2')

##Plot it
plot(ans$avg_day_length,ans$return_level,main="Holding period per level of return",xlab="periods",ylab='Return level')

##look only at levels that have a + and -
up_side=ans[ans$return_level<=abs(min(ans$return_level))&ans$return_level>0,]
down_side = ans[ans$return_level<=abs(min(ans$return_level))&ans$return_level<0,]
down_side$return_level = abs(down_side$return_level)
plot(up_side,col="blue",type='b',main='Comparison of days required to return a return level')
points(x = down_side$avg_day_length,y=down_side$return_level,col="red",type='b')

###Constant level of return plot

time_distribution_for_level=combos[combos$roundedperreturn==0.05,]
time_distribution_for_level_down=combos[combos$roundedperreturn==-0.05,]

up_five_pct_plot=table(time_distribution_for_level$day_length)/sum(time_distribution_for_level$day_length)
up_five_pct_plot = data.frame(density=as.numeric(up_five_pct_plot),periods=as.integer(names(up_five_pct_plot)))
down_five_pct_plot=table(time_distribution_for_level_down$day_length)/sum(time_distribution_for_level_down$day_length)
down_five_pct_plot = data.frame(density=as.numeric(down_five_pct_plot),periods=as.integer(names(down_five_pct_plot)))
plot(x=up_five_pct_plot$periods,y=up_five_pct_plot$density,type='b',col='blue',main='Density plot of time required for a five percent return (loss in red)',xlab='periods',ylab='density')
points(x=down_five_pct_plot$periods,y=down_five_pct_plot$density,type='b',col='red')
```

It paints a different picture likely due to my use of monthly sample data.

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.