Voy a recomendar algo que no dudo que hará que la gente se alborote por completo y que probablemente haga que la gente me ataque. Ya me pasó en el pasado y perdí muchos puntos en StackOverflow porque la gente votó en contra de mi respuesta. Ciertamente espero que la gente sea más abierta en el foro de quant.
Nota - Parece que esta sugerencia ha vuelto a crear un fuerte desacuerdo. Antes de que leas esto me gustaría señalar que esta sugerencia es para una "Pequeña empresa de compra" y no para un sistema multiusuario masivo.
Pasé 7 años dirigiendo una operación de comercio de alta frecuencia y nuestro principal objetivo era construir sistemas como éste. Pasamos mucho tiempo tratando de encontrar la manera más eficiente de almacenar, recuperar y analizar los datos de nivel de orden de la Bolsa de Nueva York, NASDAQ y una amplia variedad de ECNs. Lo que les estoy presentando es el resultado de ese trabajo.
Nuestra respuesta fue No utilice una base de datos . Un sistema básico de archivos estructurados de trozos de datos serializados funciona mucho mejor. Los datos de las series temporales del mercado son únicos en muchos aspectos, tanto en su uso como en su almacenamiento. Las bases de datos se desarrollaron para necesidades muy diferentes y, de hecho, perjudican el rendimiento de lo que se intenta hacer.
Esto se da en el contexto de una operación comercial de tamaño pequeño o mediano que se centra en el análisis de datos relacionados con las estrategias comerciales o el análisis de riesgos. Si estás creando una solución para un gran corredor de bolsa, un banco o tienes que satisfacer las necesidades de un gran número de clientes simultáneos, entonces me imagino que tu solución será diferente a la mía.
Resulta que me encantan las bases de datos. Ahora mismo estoy usando MongoDB para parte de un nuevo proyecto que nos permite analizar las operaciones de opciones, pero mis datos de series temporales de mercado, incluyendo 16 años de datos de opciones, están todos incorporados en un almacén de archivos estructurados.
Permítanme explicar el razonamiento que hay detrás de esto y por qué es más eficaz.
En primer lugar, veamos cómo se almacenan los datos. Las bases de datos están diseñadas para permitir que un sistema haga una gran variedad de cosas con los datos. Las funciones CRUD básicas: crear, leer, actualizar y eliminar. Para hacer estas cosas de forma eficaz y segura, hay que implementar muchas comprobaciones y mecanismos de seguridad. Antes de leer los datos la base de datos necesita estar segura de que los datos no están siendo modificados, está comprobando si hay colisiones, etc. Cuando se leen los datos en una base de datos, el servidor hace un gran esfuerzo para almacenar esos datos en la caché y determinar si se pueden servir más rápidamente después. Hay operaciones de indexación y replicación de datos para prepararlos para ser vistos de diferentes maneras. Los diseñadores de bases de datos se han esforzado mucho en diseñar estas funciones para que sean rápidas, pero todas ellas requieren tiempo de procesamiento y si no se utilizan son sólo un impedimento.
Los datos de las series temporales del mercado se almacenan de una manera completamente diferente. De hecho, yo diría que se preparan más que se almacenan. Cada elemento de datos sólo tiene que escribirse una vez y, después, nunca tiene que modificarse o cambiarse. Los elementos de datos pueden escribirse secuencialmente, no hay necesidad de insertar nada en el medio. No necesita ninguna funcionalidad ACID. No tienen apenas referencias a otros datos. La serie de tiempo es efectivamente su propia cosa.
Como una base de datos hace toda la magia que hace que las bases de datos sean maravillosas, también se llena de bytes. El mínimo espacio que pueden ocupar los datos es su propio tamaño original. Se pueden hacer algunos trucos con la normalización de los datos y la compresión, pero sólo llegan hasta cierto punto y ralentizan las cosas. La indexación, el almacenamiento en caché y las referencias a los datos acaban por acumular bytes y consumir el almacenamiento.
La lectura también está muy simplificada. Encontrar los datos es tan sencillo como la hora y el símbolo. La indexación compleja no sirve de nada. Dado que los datos de las series temporales suelen leerse de forma lineal y en un trozo secuencial a la vez, las estrategias de almacenamiento en caché en realidad ralentizan el acceso en lugar de ayudar. Se necesitan ciclos del procesador para almacenar en caché los datos que no se van a volver a leer en breve.
Estas son las estructuras básicas que nos han funcionado. Creamos estructuras de datos básicas para serializar los datos. Si tu mayor preocupación es la velocidad y el tamaño de los datos puedes ir con un simple almacenamiento binario personalizado. En otra respuesta, omencat sugirió usar TeaFiles y parece que también es prometedor. Nuestra necesidad reciente es la de una mayor flexibilidad, por lo que optamos por utilizar un formato JSON bastante denso, pero flexible.
Hemos dividido los datos en trozos bastante obvios. Los datos bursátiles EOD son un ejemplo muy sencillo, pero el concepto también funciona para nuestros conjuntos de datos más amplios.
Utilizamos los datos para el análisis en escenarios de series temporales bastante tradicionales. Se puede hacer referencia a una cita o a una serie que contenga años de datos a la vez. Era importante dividir los datos en trozos del tamaño de un bocado para su almacenamiento, por lo que optamos por hacer que un "bloque" de nuestros datos equivalga a un año de datos de series temporales de acciones EOD. Cada bloque es un archivo que contiene un año de datos EOD de OHLC serializados como JSON. El nombre del archivo es el símbolo de la acción precedido por un guión bajo. Nota: el guión bajo evita problemas cuando el símbolo de la acción entra en conflicto con comandos del DOS como COM o PRN.
Nota, asegúrese de entender las limitaciones de su sistema de archivos. Nos metimos en problemas cuando pusimos demasiados archivos en un solo lugar. Esto llevó a una estructura de directorio que es efectivamente su propio índice. Se desglosa por el año de los datos y luego también se ordena por la primera letra del símbolo de la acción. Esto nos da entre 20 y unos cientos de archivos de símbolos por directorio. El aspecto es más o menos el siguiente;
\StockEOD\ {YYYY} {Inicial} \_symbol.json
Los datos de AAPL para 2015 serían
\StockEOD\2015\A\_AAPL.json
Un pequeño fragmento de su archivo de datos tiene el siguiente aspecto;
[{"dt":"2007-01-03T00:00:00","o":86.28,"h":86.58,"l":81.9,"c":83.8,"v":43674760},
{"dt":"2007-01-04T00:00:00","o":84.17,"h":85.95,"l":83.82,"c":85.66,"v":29854074},
{"dt":"2007-01-05T00:00:00","o":85.84,"h":86.2,"l":84.4,"c":85.05,"v":29631186},
{"dt":"2007-01-08T00:00:00","o":85.98,"h":86.53,"l":85.28,"c":85.47,"v":28269652}
Tenemos un objeto router que puede darnos una lista de nombres de archivos para cualquier solicitud de datos en sólo un puñado de líneas. Cada archivo se lee con un Async filestream y se deserializa. Cada cita se convierte en un objeto y se añade a una lista ordenada en el sistema. En ese momento, podemos hacer una consulta muy rápida para recortar los datos innecesarios. Los datos están ahora en la memoria y pueden ser utilizados en casi cualquier forma necesaria.
Si el tamaño de la consulta es demasiado grande para el ordenador, no es difícil fragmentar el proceso. Se necesita una petición masiva para conseguirlo.
He tenido programadores a los que les he descrito esto que casi entran en cólera diciéndome que lo estaba haciendo mal. Que esto era "rodar mi propia base de datos" y una completa pérdida de tiempo. De hecho, cambiamos de una base de datos bastante sofisticada. Cuando hicimos nuestra base de código para manejar esto cayó a un pequeño puñado de clases y menos de 1/4 del código que utilizamos para gestionar la solución de base de datos. También obtuvimos un salto de casi 100 veces en la velocidad. Puedo recuperar 7 años de datos de acciones al final del día para 20 símbolos en un par de milisegundos.
Nuestro antiguo sistema de comercio HF utilizaba conceptos similares, pero en un entorno Linux altamente optimizado y operaba en el rango de los nanosegundos.
5 votos
¿Ha pensado en utilizar github.com/manahl/arctic ?
0 votos
No lo he hecho. ¿Cree usted que es un buen ajuste? He hojeado la descripción y no estoy seguro de que lo haga mejor que pg con la extensión de almacén de columnas o Cassandra. ¿Qué opinas?
1 votos
Creo que la API que proporciona es muy amigable y el autor dice que el rendimiento debería compararse favorablemente con OpenTSDB / Kairosdb.( No lo he probado yo mismo.) También podría valer la pena probar Kairosdb basado en Cassandra. Puedes ejecutar algunos benchmarks para ver cuál se ajusta a tus necesidades.
0 votos
@ mountainclimber, ¿podría compartir su opinión sobre su iniciativa, es decir, qué base de datos eligió finalmente (probó otras alternativas), los pros y los contras de la aplicación actual, sugerencias, etc.? Gracias
0 votos
@SM4 - Sí, pienso hacerlo una vez que lo pongamos en producción. Decidí empezar con una base de datos PostgreSQL en parte porque estoy familiarizado con ella y me gusta apoyar las soluciones de código abierto cuando puedo. Hasta ahora todo va bien, pero realmente no lo sabremos hasta que lo usemos mucho. Mi suposición en esta fase inicial es que una vez que empecemos a utilizarla veremos la necesidad de crear un almacén de datos que haga más rápidas las consultas de los usuarios, lo que formaba parte del plan. Hasta ahora, parece que hemos tomado la decisión correcta, pero el tiempo lo dirá y pienso actualizar el OQ una vez que pueda decir con seguridad cómo ha resultado.
0 votos
@ mountainclimber gracias. En realidad, estoy en un lugar similar, pero elegí para empezar w / esquema de archivo plano en lugar de MS SQL (plan B). Me encantaría compartir con vosotros mi experiencia hasta el momento y ver cómo se comporta RDMBS. ¿Qué entorno de programación (C#, C++, Java, Python, etc.) estás utilizando para mantener tu infraestructura (operaciones CRUD)? Además, ¿obtienes los datos de un proveedor externo (Bloomberg, Thomson, Factset)?
0 votos
@SM4 - Estoy llegando a la conclusión de que muchos lenguajes de propósito general te servirían para ETL/infraestructura/CRUD. Yo diría que elijas algo que conozcas y pueda hacer el trabajo. Sí, proveedor de datos de terceros. Estaré encantado de colaborar una vez que haya pasado por el grueso de la cuestión.
0 votos
@mountainclimber - ¿cómo se manejan las acciones corporativas? Es decir, ¿almacenas conjuntos de datos crudos (backtesting) y normalizados (investigación)?
0 votos
¿Sería posible compartir su experiencia y qué marco de trabajo eligió y eventualmente qué marco de trabajo está utilizando ahora (suponiendo que este proyecto todavía está en marcha). Estoy almacenando mis propios datos financieros actualmente en postgreSQL y actualmente me estoy preguntando si cambiar a flatfiles sería más conveniente para mí (encontré la respuesta de @drobertson muy interesante/apasionante). Interesado en sus comentarios
1 votos
@Hotone - después de trabajar en un hedge fund desde 2011-02-14 y ascender a CT/CRO, me despidieron en 2018 por no romper el acuerdo de licencia de datos de Bloomberg. Lol. Me fui de allí cuando aún estaba desarrollando este proyecto. Así que no hay información que dar en esta pregunta. Es probable que vuelva a retomar este tipo de proyecto con mi organización sin ánimo de lucro, Confidence Infinite International. Intentaré publicar información entonces. Suerte, no cambies nada hasta que empieces a tener problemas. No te prepares demasiado para el futuro.