5 votos

Cómo estructurar una base de datos bursátiles

Me gustaría descargar datos bursátiles de internet (por ejemplo mediante scraping ) y organizarlos en una base de datos (estoy usando python y SQL) que se actualice diariamente o a petición. (La idea es crear un screener, hacer back testing y demás ) No estoy muy familiarizado con las bases de datos, así que estoy buscando algunas sugerencias con respecto a la estructura de la base de datos.

La estructura que tengo en mente es la siguiente (ver imagen).

Hay 8 tablas (TICKER LIST, OHLCV y 6 tablas diferentes para los estados financieros).

La tabla principal es TICKER LIST: debe contener algún tipo de identificación única de los valores. Creo que el símbolo del ticker no puede ser un ID único, ya que los símbolos del ticker de una empresa pueden cambiar. El nombre de la empresa no puede ser un ID único, ya que es posible tener la misma empresa en diferentes bolsas. Por eso he creado la columna 'id'.

A cada 'id' se le asocia una tabla OHLCV. Por ejemplo, BP tendrá una tabla OHLCV en USD de la bolsa NYSE y una tabla OHLC en GBP de la bolsa LSE). Sin embargo, los estados financieros (Ingresos, Balance, Flujo de Caja ) deben ser los mismos para ambas bolsas. Esto significa que tendré 2 réplicas de las tablas de estados financieros exactamente idénticas, una para el id 987448 y la otra para el id 239484 en este ejemplo. Tal vez tener réplicas no es la mejor manera de hacerlo

Mi pregunta es, ¿tiene sentido esta estructura? ¿Cómo la mejoraría? Como he dicho no estoy familiarizado con las bases de datos. Gracias enter image description here

1 votos

Si se trata sólo de barras eod del día, digamos de Yahoo, por qué no almacenar los datos en archivos, en el formato CSV original.

0 votos

Esta es una muy buena pregunta para Quant.SE. Muy pocas configuraciones de quant tienen sistemas de almacenamiento de datos bien diseñados.

4voto

Foxy Puntos 46

Como siempre, cualquier respuesta a esta pregunta es enormemente impulsado por sus casos de uso . La siguiente es mi interpretación y ansatz. Aquí, en QSE y en la bolsa de datos, he visto varios enfoques para mantener los datos financieros / de mercado, y las discusiones correspondientes son bastante acaloradas... Algunos sugieren simplemente volcar/leer a/desde CSV, otros sugieren bases de datos de series temporales, etc. etc. Realmente (!) depende de su caso de uso. Mina es mantener los datos de forma ordenada y tener un modelo de datos autoexplicativo y algo ampliable para mi casos de uso de análisis.


Bien, vamos: En este punto, yo interpretar su pregunta como diciendo:

"I want to store daily OHLCV data across a (limited) number of market instruments 
from a number of trading venues. I furthermore want to be able to link (in some 
sense to be yet defined) market data and financial statement data per company. 
Once that is done, I want to do some analysis, get some signals, backtesting etc.*

*Está claro que esta afirmación es todavía muy débil, pero ayuda a tener al menos un poco de lo básico.

De ahí que no se preocupe por concurrencia no se preocupa por la latencia (ultrabaja) ni por el rendimiento de la base de datos, y no se preocupa por las ventajas añadidas de bases de datos de series temporales demasiado - pero es posible que quiera preocuparse por bitemporalidad Es decir, ¿cómo quiere que se reflejen los acontecimientos históricos en sus datos (acciones corporativas, por ejemplo, o fusiones)? Para simplificar, supongamos que simplemente recarga de un ajustado series temporales cada vez que se produce una acción corporativa y ya está. Además, si se produce una fusión, simplemente se "abandona" la antigua empresa...

Como has declarado que quieres usar una base de datos relacional y SQL, sigamos con eso. Dividamos ahora todo en entidades, atributos y relaciones.


Entidades y relaciones de las que puede preocuparse

  • Empresa : Evidentemente, cada empresa es una entidad. No tenemos en cuenta los vínculos intraempresariales, las relaciones de propiedad y similares y simplemente tomamos una empresa como tal. Una empresa tiene un nombre y un moneda de referencia Al menos.

  • Instrumento : Para simplificar, cada empresa ofrece uno o más instrumentos, identificados de forma exclusiva por su ISIN de 12 dígitos. Si es necesario, puede derivar de esta tabla cualquier otra relacionada con los instrumentos.

  • Mercado : Un mercado (o recinto) es el lugar donde se negocian los instrumentos y se observan los precios. Para simplificar, fijemos la moneda en este nivel.

  • Proveedor : El proveedor es la parte responsable de hacerle llegar los datos. En un entorno profesional podría ser Reuters o Bloomberg; a nivel sencillo podría ser AlphaVantage, Yahoo, Quandl, ...

  • Símbolo : En un mercado, se puede identificar de forma exclusiva un instrumento a través de su símbolo. Sin embargo, si se utilizan algunas APIs disponibles, los símbolos pueden ser específicos del proveedor con "mapas" no deterministas. Podría ser útil simplemente escribirlos en el nivel: símbolo = <instrumento, mercado, vendedor> . (Es posible que también quieras poder ponerle un sello de tiempo, ver bitemporalidad más arriba).

  • Precio : Ahora puedes poner todo junto: símbolo,fecha,OHLCV le permite almacenar todo lo que necesita aquí.

Ahora a la datos de los estados financieros .

Como quieres trabajar con Python para el análisis de datos, te sugeriría las siguientes adiciones:

  • partida presupuestaria : Cada elemento de un balance/cuenta de resultados está más o menos ordenado jerárquicamente. Le sugiero que lo configure de manera que pueda hacer una agregación sencilla más adelante. Puede introducir una tabla para el balance y otra para la cuenta de resultados.

  • encabezado de la declaración : Esta es la tabla de cabecera de cada declaración. Indica la empresa, la fecha y el tipo de extracto (ingresos, balance..)

  • datos de la declaración : Esta tabla contiene los datos de la declaración, es decir headerid, lineitem, value .

Notas:

  • Esta configuración es bastante comprensible, en mi opinión, y la utilizo para mis actividades privadas (por ejemplo, los estados financieros). Estoy cubriendo ~ 150 tickers y cargar los datos diariamente o un par de veces por semana; Ejecutar el análisis utilizando SQL y R. Para esta pequeña cantidad de datos, esta configuración es suficiente. Pero Cambio el esfuerzo de configuración por la transparencia, por supuesto.
  • FX: Podrías introducir sociedades ficticias "EURUSD", "GBPUSD" y similares y almacenar los valores de las divisas de la misma manera que almacenas los precios de las acciones, o bien, salpicar otra tabla para esto. Desde un punto de vista práctico, una tabla distinta podría ser preferible, y como haces el análisis en Python no estás demasiado restringido por el corsé de SQL, ¿no?
  • Integridad referencial: Debe hacerla cumplir, por supuesto: Un precio tiene un símbolo tiene un instrumento/mercado/vendedor tiene una empresa.
  • Como hemos dicho anteriormente, no nos preocupamos demasiado por la bitemporalidad: si ha habido algún evento corporativo, simplemente volvemos a cargar todos los precios de un determinado símbolo. SI si quiere incorporar varias versiones de datos, necesita añadir columnas / tablas para el mantenimiento del historial, por supuesto...

I HTH, o que te ayude a ponerte en la dirección adecuada para su casos de uso...

1voto

user154138 Puntos 1

De hecho SQL no es una buena idea, sólo NYSE puede entregar 100 GB/día, te sugiero que empieces a mirar MongoDB, echa un vistazo a esta presentación James Blackburn - Python y MongoDB como plataforma para datos de mercados financieros

0 votos

(no son datos intradía, sólo OHLCV)

0 votos

Ya veo, con respecto a su diseño tal vez usted podría utilizar ISIN para tener un identificador único en ambas bolsas, el almacenamiento de datos no es un problema, entonces usted debe escuchar el comentario de Sergei y pensar en CSV, ya que está utilizando los datos de carga de Python es fácil con Pandas, también Pandas tiene integración para SQLite si usted prefiere mantener una base de datos

1voto

Craigy Puntos 111

Si la motivación principal es poder consultar los datos del mercado con SQL, eche un vistazo a Base de datos de series temporales Axibase ( mi afiliación ).

Paso 1 : Inscríbete gratis Polígono Clave API.

Paso 2 : Instalar la base de datos en una máquina Linux. Generar Ficha de la API para el método POST a /api/v1/trade-session-summary/import punto final.

Paso 3 : Descargue las barras de fin de día de varios días de Polygon. Cada archivo JSON incluye más de 9000 acciones estadounidenses, pero este punto final es razonablemente rápido y tarda menos de un minuto.

declare -a DATES=(2021-03-10 2021-03-11 2021-03-12)
for DT in "${DATES[@]}"; do \
  curl -o eod_$DT.json "https://api.polygon.io/v2/aggs/grouped/locale/us/market/stocks/$DT?unadjusted=true&apiKey=POLYGON_API_KEY"; \
done

Paso 4 : Convertir JSON a CSV

for DT in "${DATES[@]}"; do \
  (echo "datetime,exchange,class,type,stage,symbol,open,high,low,close,vwap,voltoday,numtrades,valtoday" ; \
  cat eod_$DT.json | jq -c '.results[] | [(.t/1000 | todateiso8601),"SIP","SIP","Day","C", .T, .o, .h, .l, .c, .vw//0, .v//0, .n//0, .v//(.vw//(.vw*.v))]' | \
  sed 's/\"//g;s/\[//g;s/\]//g' ) > eod_$DT.csv ; \
done

Paso 5 : Cargar archivos CSV en la ATSD

for DT in "${DATES[@]}"; do \
curl --header 'Authorization: Bearer ATSD_API_TOKEN' --insecure \
  -F "data=@eod_${DT}.csv" -F "add_new_instruments=true" \
  "https://atsd_hostname:8443/api/v1/trade-session-summary/import" ; \
done

Paso 6 : Consulta de datos EOD con SQL utilizando la consola web, o el controlador JDBC/ODBC, o a través de un punto final de la API:

SELECT symbol, datetime,open,high,low,close,ROUND(vwap*voltoday/1000000) AS "daily_val, $M"
  FROM atsd_session_summary
WHERE class = 'SIP' AND symbol IN ('AAPL', 'TSLA')
  AND datetime BETWEEN '2021-03-01' AND '2021-03-15'
ORDER BY symbol, datetime

enter image description here

En cuanto a los datos de referencia, como base de datos no relacional con un esquema extensible (en escritura), ATSD permite añadir nuevas columnas sobre la marcha. Por ejemplo, los datos de referencia de los polígonos pueden insertarse con la misma facilidad sin necesidad de gestionar el esquema.

SELECT symbol, entity.tags.name, entity.tags.sector, datetime, close
  FROM atsd_session_summary
WHERE class = 'SIP' AND entity.tags.sector IN ('Industrials', 'Basic Materials')
  AND IS_INSTRUMENT_IN_INDEX('CS10')
  AND datetime BETWEEN '2021-03-01' AND '2021-03-15'
WITH ROW_NUMBER(symbol ORDER BY datetime DESC) <= 1

| symbol | entity.tags.name             | entity.tags.sector | datetime            | close |
|--------|------------------------------|--------------------|---------------------|------:|
| AA     | Alcoa Corporation            | Basic Materials    | 2021-03-12 16:00:00 | 31.51 |
| AAL    | American Airlines Group Inc. | Industrials        | 2021-03-12 16:00:00 | 23.37 |

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