1 votos

¿Por qué esta cesta cointegrada parece demasiado buena para ser verdad?

Necesitas quantmod y tseries en R para ejecutar esto:

library(quantmod)
library(tseries)

pairs <- c(
    "EUR/USD",
    "GBP/USD",
    "AUD/USD",
    "USD/CAD",
    "USD/CHF",
    "NZD/USD"
    )

name <- function(n) {
    gsub("/","",n,fixed=TRUE)
}

getFrame <- function(p) {
    result <- NULL
    as.data.frame(lapply(p, function(x) {
        if(!exists(name(x))) {
            getSymbols(x, src="oanda") 
        }
        if(is.null(result)) {
            result <- get(name(x))
        } else {
            result <- merge(result, get(name(x))) 
        }
    }))
}

isStationary <- function(frame) {
    model <- lm(frame[,1] ~ as.matrix(frame[,-1]) + 0)
    spread <- frame[,1] - rowSums(coef(model) * frame[, -1])
    results <- adf.test(spread, alternative="stationary", k=10)
    if(results$p.value < 0.05) {
            coefficients <- coef(model)
            names(coefficients) <- gsub("as.matrix.frame.......", "", names(coefficients))
            plot(spread[1:100], type = "b")
            cat("Minimum spread: ", min(spread), "\n")
            cat("Maximum spread: ", max(spread), "\n")
            cat("P-Value: ", results$p.value, "\n")
        cat("Coeficients: \n")
        print(coefficients)
    }
}

frame <- getFrame(pairs)
isStationary(frame)

Obtengo los datos diarios de FX de Oanda, hago una regresión lineal simple para encontrar los ratios de cobertura, y luego uso la prueba de DF aumentada para probar el valor P de reversión media en el spread.

Cuando lo ejecuto me sale esto:

Minimum spread:  -1.894506 
Maximum spread:  2.176735 
P-Value:  0.03781909 
Coeficients: 
        GBP.USD     AUD.USD     USD.CAD     USD.CHF     NZD.USD 
 0.59862816  0.48810239 -0.12900886  0.04337268  0.02713479

El coeficiente EUR.USD es 1.

Cuando trazo la extensión, los primeros 100 días se ven así:

enter image description here

Seguramente algo debe estar mal. El santo grial no debería ser tan fácil de encontrar.

¿Puede alguien ayudarme a encontrar lo que está mal?

He intentado hacer backtesting en Dukascopy con los coeficientes anteriores como tamaños de lote de una cesta, pero me encuentro con pérdidas. Y el spread tiene un orden de magnitud diferente en dukascopy. ¿Por qué es eso?

9voto

Jose Brox Puntos 969

El principal problema en su código es esta línea:

rowSums(coef(model) * frame[, -1])

No estoy seguro de lo que hace exactamente, quizás alguna multiplicación de matrices, pero definitivamente no es lo que se espera que haga. Intenta sustituirlo por una multiplicación manual

spread <- frame[,1] - (coef(model)[1]*frame[,2] + coef(model)[2]*frame[,3] + coef(model)[3]*frame[,4] + coef(model)[4]*frame[,5] + coef(model)[5]*frame[,6])

Y el santo grial desaparecerá

no more holy grail

También veo un par de errores más:

  1. No se puede vender a precio de consulta. Con getSymbols.oanda siempre obtienes ASK
  2. Es mejor separar los conjuntos de datos de prueba y de entrenamiento

3voto

doekman Puntos 5187

@Sergey identificó correctamente el problema. La explicación es que coef(model) es un vector, frame es un data.frame, y la multiplicación elemento a elemento tiene lugar en orden columna-mayor. El vector más corto ( coef(model) ) se recicla a lo largo del vector más largo (cada columna de frame ). Por ejemplo:

frame <- data.frame(V1=1:5)
frame$V2 <- 2
frame$V3 <- 5
coef.model <- 1:3
frame * coef.model
#   V1 V2 V3
# 1  1  6 10
# 2  4  2 15
# 3  9  4  5
# 4  4  6 10
# 5 10  2 15

Lo que pretendía era algo así:

sweep(frame,2,coef.model,"*")
#   V1 V2 V3
# 1  1  4 15
# 2  2  4 15
# 3  3  4 15
# 4  4  4 15
# 5  5  4 15

Finanhelp.com

FinanHelp es una comunidad para personas con conocimientos de economía y finanzas, o quiere aprender. Puedes hacer tus propias preguntas o resolver las de los demás.

Powered by:

X