Big Data Management 4 - Utilizando el datalake en Zipline
En este artículo, vamos a crear una solución para poder utilizar cualquier tipo de dato, dentro de un pipeline de zipline. Crearemos un algoritmo, que consulte el datalake, realice las transformaciones oportunas y posteriormente ingiera los datos hacia zipline dentro del denominado bundle.
Antecedentes
Llegados a este punto, tenemos nuestro dalalake totalmente desplegado, con datos de información de EOHDH. Podemos acceder desde pandas a los datos, para todo tipo de análisis y estudios en JupyterLab.
Ahora vamos a ampliar la funcionalidad de nuestro stack programando un algoritmo que realice la siguiente función;
BACKTESTER INGEST DATA ->
REQUEST FROM DATALAKE ->
DOWNLOAD - TRANSFORM ->
INGEST IN BACKTESTER
O dicho de otro modo, vamos a crear un algoritmo que cuando el backtester solicite la información, consultaremos con articdb, lo descargaremos, transformaremos para utilizar el formato de zipline, y lo añadiremos al backtester.
En este caso, vamos a trabajar únicamente con una lista de acciones americanas muy reducida, pero explicaremos como crear universos y filtrar los activos en función de sus características.
Que es Zipline
Zipline es el backtester utilizado por el proyecto Quantopian, integrable con su stack de herramientas. Si desea conocer más sobre Zipline, recomendamos:
En estos artículos, encontrará toda la teoría y practica necesaria para dar sus primeros pasos con Zipline. Pero ¿Y como añade datos personalizados de activos alternativos, o simplemente datos de acciones de su data-bróker habitual? Pues, ese problema vamos a solucionar en este artículo.
Introducción a la arquitectura de Zipline
Zipline, al ser de un proyecto Open Source, todos los desarrolladores pueden modificar el código en función a sus necesidades, pero además proporciona la ventaja de entender, en profundidad, como funciona su motor interno.
En la siguiente imagen vemos como gestiona las llamadas.
Los datos que tenemos en nuestro datalake storeados, debemos solicitarlos, y transformarlos a un formato que zipline acepte, para que posteriormente, zipline de forma automatizada los ajuste mediante bcolz_storage
Sobre bcolz storage
Para todos aquellos que no conozcan que fue bcolz:
bcolz provides columnar, chunked data containers that can be compressed either in-memory and on-disk. Column storage allows for efficiently querying tables, as well as for cheap column addition and removal. It is based on NumPy, and uses it as the standard data container to communicate with bcolz objects, but it also comes with support for import/export facilities to/from HDF5/PyTables tables and pandas dataframes.
En una etapa temprana del trading algorítmico para Python, soluciones como la actual articdb, no eran más que sueños, dado que eran irrealizables a nivel tecnológico, se necesitaban librerías de gestión de datos con la menor latencia posible, y bcols soluciono el requisito, de una forma además panda-friendly, lo cual proporcio su "adaptación masiva" en muchos proyectos.
Básicamente, un bundle, es un universo de activos, donde debemos añadir todos los símbolos necesarios para su composición, y además un mecanismo de carga de los mismos.
En nuestro caso particular, vamos a seleccionar un universo de pocos que serán:
SPY, QQQ, DIA, TLT, GLD
Los universos pueden ser declarados de forma explícita, como vamos a realizar en nuestro caso, o pueden ser creados mediante parámetros.
Los universos creados mediante parámetros hacen referencia, en que para conocer los tickers finales que utilizaremos, podríamos filtrar, por el año de lanzamiento de la compañía, para evitar compañías excesivamente nuevas, podríamos filtrarlas por capitalización bursátil, o cualquier otro requisito, como que hagan overpeformance la semana pasada a un índice, o que pertenezcan a un sector determinado.
Como añadir datos del Datalake a Zipline
El código completo lo podéis encontrar al final del post, para usuarios registrados. Aquí vamos a comentar ciertas partes relevantes, que es donde realmente sucede la "magia".
En el siguiente fragmento, consultamos el archivo .env de nuestro entorno, que nos proporciona las credenciales para poder acceder al datalake, y las asignamos a variables, para posteriormente poder crear nuestro puesto.
Nuestro puntero es la variable asignada como ac, que dentro de la variable, hay un objeto que contiene toda la información necesaria, para hacer la conexión con el datalake, y será el punto de llamada a cualquier interacción con el datalake de arcticdb ubicado en la nube.
warnings.filterwarnings('ignore')
dotenv_path = '/root/.env'
load_dotenv(dotenv_path)
endpoint = getenv("ENDPOINT")
db = getenv("DB")
access_key = getenv("ACCESS_KEY")
secret_key = getenv("SECRET_KEY")
ac = Arctic(f's3s://{endpoint}:{db}?access={access_key}&secret={secret_key}')
my_cal = get_calendar('NYSE')
prices = ac.get_library('prices.etfs.us.stable')
for sid, symbol in enumerate(symbols):
print('[QA DATALAKE CARNIVORE ] ||| Loading {}...'.format(symbol))
df = prices.read(symbol).data
df = df['2010':]
start_date = df.index[0]
end_date = df.index[-1]
sessions = my_cal.sessions_in_range(start_date, end_date)
df = df[df.index.isin(sessions)]
df = df.reindex(sessions.tz_localize(None))[start_date:end_date] #tz_localize(None)
df.fillna(method='ffill', inplace=True)
df.dropna(inplace=True)
ac_date = end_date + pd.Timedelta(days=1)
metadata.loc[sid] = start_date, end_date, ac_date, symbol, 'QAX'
El siguiente fragmento forma parte de un bucle, donde se asignan los parámetros del activo, como su calendario, y posteriormente se consulta al datalake para leer la información a partir de 2010, y transformarla para que posteriormente pueda ser ingerida por zipline, haciendo reindex en función de las sesiones horarias de mercado (para evitar problemas con los medios días y los festivos).
Repetiremos el proceso también con los splits y los dividendos, además de añadir siempre datos no ajustados, donde dejamos que el mismo engine de zipline, con la información proporcionada, realice de manera interna en sus backtests los ajustes pertinentes para el precio, y así tener el control del cálculo en todas las etapas del proceso, y no depender de terceros como pueda ser él data-bróker.
Conclusiones
Una vez llegados a este punto, disponemos de un datalake, con información financiera de EODHD, y una integración con zipline.
El siguiente paso natural es crear un entorno completo, donde utilicemos todo lo creado hasta el momento. Un entorno de desarrollo profesional, basado en la tecnología de contenedores Docker, donde facilite las labores de despliegue y manteamiento al researcher. Simplificando su ejecución, y totalmente personalizable por parte del usuario.
Este entorno será tomado como base, para futuros desarrollos, y se asume que todos los lectores están familiarizados con él.