Cómo cambiar precios de un marco temporal a otro con Python

Share this

En esta entrada voy a explicar cómo conseguir precios en formato tick y transformarlos en cualquier otro marco temporal. En concreto, vamos a coger un fichero de precios tick a tick y lo convertiremos en un fichero OHLC de 5 minutos. Podríamos convertirlo en cualquier otro formato, como 10 segundos o 1 día.

No voy a hacer publicidad de programas de software. Hay muchas maneras de conseguir datos. Por ejemplo, podemos exportar de nuestro cliente de trading los datos que va recibiendo del servidor. Pero en este caso, vamos a usar un gran servicio del broker Dukascopy que permite descargar ficheros de datos de múltiples fuentes gratis.

Para descargarlos, hay que ir a la web https://www.dukascopy.com/swiss/spanish/marketwatch/historical/ y elegir un instrumento. Una vez elegido podemos ya seleccionar los datos a descargar. Hay programas que lo hacen de forma automática, solo tienes que buscar en Internet para encontrar alguno gratis, que los hay.

En mi caso, me he descargado todos los datos tick a tick del par de divisas EURUSD entre 2003 y 2019 en formato CSV. Esto son unos 13Gb de tamaño. Las columnas que me interesan son: [«date»,»ask»,»bid»]. El tamaño es inmanejable, así que en principio, para echarle un vistazo, se puede usar la librería de Python llamada daske que tiene una especie de Pandas.DataFrame con algunas de las funciones de pandas y soporta ficheros enormes, distribuidos, etc…

Pero, en general, daske, no me vale para lo que quiero hacer, así que lo que voy a hacer en primer lugar es convertir el fichero único CSV de 13GB en unos más pequeños, porque si no colapsaré la memoria de mi equipo al procesar tanta información.

Pandas puede convertir en trozos un fichero más grande, así que he escrito este código para reducir el tamaño individual de cada archivo en bloques de 5E6 filas:

import pandas as pd
 
def process(chunk,count):
    prefix = chunk.iloc[0].date.split(" ")[0]
    chunk.to_csv(prefix + "_EURUSDTICK_" + str(count) + ".csv",index=False)
 
count=0
chunksize = 5 * 10 ** 6 
for chunk in pd.read_csv(r"./sample_data/TICK_EURUSD.csv",header=-1, chunksize=chunksize):
    count=count+1
    chunk.columns = ["date","ask","bid","volume","zero"]
    chunk=chunk[["date","ask","bid"]]
    process(chunk, count)

Tras el proceso, se me han generado unos 60 ficheros más pequeños.

Aún así, la columna date está en formato texto, tipo «2016.05.01 1:23:04.092», con lo que necesitaré formatearla a un tipo fecha. Para ello, voy a cargar cada uno de los ficheros y le aplicaré una función de conversión en el campo fecha.

afiles = [f for f in os.listdir("./sample_data") if ".csv" in f]
 
for file in afiles:
    print (file)
    df = pd.read_csv(file)
    df["date"]=df["date"].apply(lambda x:datetime.datetime.strptime(x,'%Y.%m.%d %H:%M:%S.%f'))
    df.to_csv(file)

Una vez reescritos o sobreescritos los csv parciales con la columna corregida, pasamos a cambiar el muestreo. Voy a preparar mis datos para convertir los ficheros de ticks en ficheros de 5m.

Como tenemos los precios Ask y Bid, nos interesa tener OHLC con ambos, para determinar cuál es el rango aplicable en compra y cuál en venta. Además, podemos calcular spreads de diferentes maneras. Veamos un ejemplo con uno de los ficheros generados cualquiera. Para que funcione, la columna date la tenemos que convertir en el índice del DataFrame.

processed = "./sample_data/2015.02.05_EURUSDTICK_41.csv"
df = pd.read_csv(processed)
df_5m_ohlc = df[["date","ask","bid"]].set_index("date").resample('5Min').ohlc()

Y tendríamos finalmente ya los datos convertidos de formato tick a format OHLC. Veamos el formato de los ficheros, cómo eran originalmente y cómo quedan al final.

Antes:

Después:

La utilidad de estos procesos es notablemente alta para la simulación de estrategias basadas en análisis técnico, ya que nos permite estudiar el marco temporal de referencia a la vez que generar los ticks, precios y spreads de forma exacta.

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.