El mundo financiero está lleno de datos, desde precios de activos (acciones, divisas, derivados, criptomonedas) hasta información contable de empresas y estadísticas económicas. Obtener datos de calidad suele ser costoso, pero para el aprendizaje o la investigación personal existen alternativas gratuitas en R. En este artículo se comparan tres paquetes populares (quantmod, tidyquant y pedquant) para descargar datos históricos de acciones, complementados con las API de las plataformas Tushare y JoinQuant, y se discute la calidad de los datos.
1. Uso de paquetes R para obtener datos
(1) quantmod
quantmod es una herramienta clásica. La función getSymbols() obtiene datos de múltiples fuentes. A continuación se descargan datos de la acción de China Merchants Bank (código 600036.SS) desde Yahoo Finance:
library(quantmod)
cmb_quant <- getSymbols("600036.ss", src = "yahoo",
from = "2019-01-01", to = "2020-09-30",
auto.assign = FALSE)
head(cmb_quant, 3)
# Resultado: columnas Open, High, Low, Close, Volume, Adjusted
(2) tidyquant
tidyquant envuelve quantmod en un formato tidyverse (tibble).
library(tidyquant)
cmb_tq <- tq_get("600036.ss", get = "stock.prices",
from = "2019-01-01", to = "2020-09-30")
head(cmb_tq, 3)
# Resultado: tibble con symbol, date, open, high, low, close, volume, adjusted
(3) pedquant
Para el mercado chino, pedquant es una alternativa más fiable. Usa md_stock() con fuente de NetEase (163):
library(pedquant)
cmb_pd <- md_stock("600036.ss", from = "2019-01-01", to = "2020-09-30",
source = "163", adjust = NULL)
cmb_pd_tidy <- cmb_pd[[1]] %>%
as_tibble() %>%
select(symbol, date, open, high, low, close, volume)
head(cmb_pd_tidy, 3)
Con adjust = "dividend" se obtienen precios ajustados por split y dividendos (forward adjustment).
2. Datos a través de plataformas de trading cuantitativo
(1) Tushare
Requiere registro y token. Se usa el paquete Tushare:
library(Tushare)
bar <- Tpro_bar(token = "tu_token")
cmb_ts <- bar(ts_code = "600036.SH", start_date = "20190101",
end_date = "20200930")
head(cmb_ts, 3)
# Columnas: ts_code, trade_date, open, high, low, close, pre_close, change, pct_chg, vol, amount
Para precios ajustados forward se añade adj = "qfq".
(2) JoinQuant (聚宽)
Proporciona una función request personalizada. Ejemplo:
request <- function(method, ...) {
# ... (código de autenticación y llamada)
}
cmb_jq <- request("get_price", code = "600036.XSHG", count = 427,
unit = "1d", end_date = "2020-09-30")
head(cmb_jq, 3)
# Columnas: date, open, close, high, low, volume, money, ...
Para ajuste forward, se añade fq_ref_date = "2020-09-30".
3. Problemas de calidad de los datos
Al comparar los datos obtenidos se observan diferencias notables.
- quantmod/tidyquant: devuelven 425 filas en lugar de 427, faltando los días
2019-04-29y2019-04-30. - Ajuste forward (前复权): Los datos de pedquant difieren sistemáticamente de los de Tushare/JoinQuant. pedquant aplica una resta simple del dividendo al precio anterior, mientras que Tushare/JoinQuant usan factores de ajuste que preservan los rendimientos reales. Por ejemplo, en el periodo 2019-07-12 a 2020-07-09:
# Verificación del método de pedquant
precio_original <- cmb_pd[[1]] %>% filter(date >= "2019-07-12", date <= "2020-07-09")
precio_ajustado_pd <- md_stock("600036.ss", ..., adjust = "dividend")[[1]] %>%
filter(date >= "2019-07-12", date <= "2020-07-09")
head(precio_original$close - 1.2, 3) # igual a precio_ajustado_pd$close
# Pero los rendimientos diarios no se preservan
Usando un bucle iterativo para preservar los rendimientos se obtienen valores equivalentes a los de JoinQuant:
n <- nrow(precio_original)
adj_close <- numeric(n)
adj_close[n] <- precio_original$close[n] - 1.2
for (i in (n-1):1) {
adj_close[i] <- adj_close[i+1] / (1 + 0.01 * precio_original$change_pct[i+1])
}
head(adj_close) # coincide con JoinQuant
4. Ejemplos de web scraping
R dispone de potentes herramientas para extraer datos financieros directamente de la web.
(1) Datos intradiarios (k-line de minutos)
Usando la API de Sina:
library(jsonlite)
url <- "http://money.finance.sina.com.cn/quotes_service/api/json_v2.php/CN_MarketData.getKLineData?symbol=sh600036&scale=60&ma=no&datalen=500"
stock_json <- read_json(url)
stock_tbl <- bind_rows(stock_json)
stock_tbl[,2:6] <- apply(stock_tbl[,2:6], 2, as.numeric)
head(stock_tbl)
# Columnas: day, open, high, low, close, volume, ma_price5, ma_volume5
(2) Transacciones históricas detalladas
NetEase proporciona archivos xls:
url_xls <- "http://quotes.money.163.com/cjmx/2020/20200929/0600036.xls"
download.file(url_xls, destfile = "600036_20200929.xls")
Estos métodos ofrecen una base sólida para el análisis cuantitativo en R, aunque es crucial compredner las diferencias en los algoritmos de ajuste de precios para evitar conclusiones erróneas.