Productos secos 丨 Tutorial de reproducción de datos históricos de DolphinDB

Cuando se utiliza una estrategia cuantitativa en transacciones reales, el programa que procesa datos en tiempo real suele estar impulsado por eventos. Al desarrollar una estrategia cuantitativa, es necesario utilizar datos históricos para backtesting, y el programa en este momento no suele estar impulsado por eventos. Por lo tanto, la misma estrategia requiere escribir dos conjuntos de código, lo que requiere mucho tiempo y es propenso a errores. En la base de datos DolphinDB, los usuarios pueden importar datos históricos a la tabla de datos de transmisión en orden cronológico en forma de "datos en tiempo real", de modo que el mismo conjunto de códigos se pueda utilizar para backtesting y trading real.

El marco de procesamiento de datos en streaming de DolphinDB utiliza un modelo de publicación-suscripción-consumo. Los productores de datos continúan publicando datos en tiempo real para todos los suscriptores de datos en forma de transmisiones. Una vez que el suscriptor recibe el mensaje, puede utilizar una función personalizada o el motor de agregación integrado de DolphinDB para procesar el mensaje. La interfaz de transmisión de datos de DolphinDB admite API en varios lenguajes, incluidos C ++, C #, Java y Python. Los usuarios pueden utilizar estas API para escribir una lógica de procesamiento más compleja e integrarse mejor con el entorno de producción real. Los amigos interesados ​​pueden buscar "DolphinDB Streaming Data Tutorial" para obtener más información.

Este artículo presenta las funciones de reproducción y reproducción de DS, y luego utiliza datos financieros para mostrar el proceso y los escenarios de aplicación de la reproducción de datos.

1. Introducción a la función

repetición

replay (inputTables, outputTables, [dateColumn], [timeColumn], [replayRate], [paraleloLevel = 1])

La función de la reproducción es reproducir varias tablas o fuentes de datos en la tabla de salida correspondiente al mismo tiempo. El usuario debe especificar la tabla de datos de entrada o la fuente de datos, la tabla de salida, la columna de fecha, la columna de tiempo, la velocidad de reproducción y el paralelismo.

El concepto de parámetros de la función de reproducción es el siguiente:

  • inputTables: una sola tabla o una tupla que contiene varias tablas o fuentes de datos (consulte la introducción a replayDS).
  • outputTables: una sola tabla o una tupla que contiene varias tablas. Estas tablas suelen ser tablas de datos de flujo continuo. El número de tablas de entrada y de salida es el mismo, existe una correspondencia uno a uno y la estructura de cada par de tablas de entrada y salida es la misma.
  • dateColumn, timeColumn: string, representa la columna de fecha y hora de la tabla de entrada, si no se especifica, la primera columna es la columna de fecha por defecto. Si la columna de hora en la tabla de entrada contiene fecha y hora, debe establecer dateColumn y timeColumn en la misma columna. Durante la reproducción, el sistema determinará la precisión de tiempo mínima de reproducción de acuerdo con los ajustes de dateColumn y timeColumn. Con esta precisión de tiempo, los datos al mismo tiempo se enviarán en el mismo lote. Por ejemplo, una tabla tiene una columna de fecha y una columna de hora, pero solo se establece dateColumn en la función de reproducción, luego todos los datos del mismo día se generarán en un lote.
  • replayRate: número entero, que representa el número de elementos de datos reproducidos por segundo. Dado que los datos se generan en el mismo lote al mismo tiempo durante la reproducción, cuando replayRate es menor que el número de filas en un lote, la tasa de salida real será mayor que replayRate.
  • paralelismoLevel: entero, que indica el paralelismo de lectura de datos. Cuando el tamaño de los datos de origen excede el tamaño de la memoria, es necesario utilizar la función replayDS para dividir los datos de origen en varias fuentes de datos pequeñas, y luego leer los datos del disco y reproducirlos. Especificar varios subprocesos para leer datos puede aumentar la velocidad de lectura de datos.

replayDS

replayDS (sqlObj, [dateColumn], [timeColumn], [timeRepartitionSchema])

La función replayDS puede convertir la consulta SQL de entrada en una fuente de datos y usarla junto con la función de reproducción. Su función es dividir la consulta SQL original en varias consultas SQL pequeñas en orden cronológico según la partición de la tabla de entrada y timeRepartitionSchema.

El concepto de los parámetros de la función replayDS es el siguiente:

  • sqlObj: metacódigo SQL, que representa los datos que se van a reproducir, como <select * from sourceTable>.
  • dateColumn: cadena, que representa la columna de fecha. Si no se especifica, la primera columna es la columna de fecha por defecto. La columna de fecha predeterminada de la función replayDS es una columna de partición de la fuente de datos y la consulta SQL original se divide en varias consultas según la información de la partición.
  • timeColumn: cadena, que representa la columna de tiempo, utilizada con timeRepartitionSchema.
  • timeRepartitionSchema: Vector de tipo de tiempo, como 08:00:00 .. 18:00:00. Si timeColumn se especifica al mismo tiempo, la consulta SQL se divide aún más en la dimensión de tiempo.

Reproducción de tabla de memoria única

La reproducción de una tabla de memoria única solo necesita establecer la tabla de entrada, la tabla de salida, la columna de fecha, la columna de tiempo y la velocidad de reproducción.

reproducir (inputTable, outputTable, `fecha,` hora, 10)

Reproducción de una sola tabla usando una fuente de datos

Cuando hay demasiadas filas en una sola tabla, puede usar replayDS para la reproducción. Primero, use replayDS para generar la fuente de datos. En este ejemplo, se especifican la columna de fecha y timeRepartitionColumn. La llamada de reproducción es similar a la reproducción de una sola tabla de memoria, pero se puede especificar el paralelismo de reproducción. La implementación interna de la reproducción utiliza el marco de la canalización, y la obtención y salida de datos se ejecutan por separado. Cuando la entrada es una fuente de datos, se pueden leer varios bloques de datos en paralelo para evitar esperar el hilo de salida. En este ejemplo, el grado de paralelismo se establece en 2, lo que significa que hay dos subprocesos que realizan operaciones de obtención de datos al mismo tiempo.

inputDS = replayDS (<seleccionar * from inputTable>, `date,` time, 08: 00: 00.000 + (1..10) * 3600000) 
replay (inputDS, outputTable, `date,` time, 1000, 2)

Reproducción de varias tablas utilizando una fuente de datos

La reproducción también admite la reproducción simultánea de varias tablas. Solo necesita pasar varias tablas de entrada para reproducirlas en forma de tuplas y especificar las tablas de salida por separado. Aquí, la tabla de salida y la tabla de entrada deben corresponder uno a uno, y cada par debe tener la misma estructura de tabla. Si se especifica una columna de fecha o una columna de hora, debería haber columnas correspondientes en todas las tablas.

ds1 = replayDS (<seleccionar * de entrada1>, `fecha,` hora, 08: 00: 00.000 + (1..10) * 3600000) 
ds2 = replayDS (<seleccionar * de entrada2>, `fecha,` hora, 08 : 00: 00.000 + (1..10) * 3600000) 
ds3 = replayDS (<seleccionar * de input3>, `date,` time, 08: 00: 00.000 + (1..10) * 3600000) 
replay ([ds1 , ds2, ds3], [out1, out2, out3], `fecha,` hora, 1000, 2)

Cancelar la reproducción

Si submitJob llama a la función de reproducción, puede usar getRecentJob para obtener el jobId y luego usar cancelJob para cancelar la reproducción.

getRecentJobs () 
cancelJob (jobid)

Si se llama directamente, puede usar getConsoleJobs para obtener el jobId en otra sesión de GUI y luego usar cancelConsoleJob para cancelar la tarea de reproducción.

getConsoleJobs () 
cancelConsoleJob (jobId)

2. Cómo utilizar los datos de reproducción

Los datos reproducidos existen en forma de transmisión de datos. Podemos utilizar las siguientes tres formas de suscribirnos y consumir estos datos:

  • Suscríbase a DolphinDB y use el script DolphinDB para personalizar la función de devolución de llamada para consumir datos de transmisión.
  • Suscríbase a DolphinDB y utilice el motor informático de transmisión integrado para procesar la transmisión de datos, como el motor de agregación de series de tiempo, el motor de agregación de sección transversal, el motor de detección de anomalías, etc. El motor de agregación integrado de DolphinDB puede realizar cálculos de agregación en tiempo real en datos de transmisión, que es fácil de usar y tiene un rendimiento excelente. En 3.2, utilizamos el motor de agregación transversal para procesar los datos reproducidos y calcular el valor intrínseco del ETF. Para el uso específico del motor de agregación de sección transversal, consulte el manual del usuario de DolphinDB.
  • Los clientes de terceros se suscriben y consumen datos a través de la API de transmisión de datos de DolphinDB.

3. Ejemplo financiero

Reproduzca los datos de negociación de nivel 1 del mercado de valores de EE. UU. Durante un día y calcule el valor de ETF

En este ejemplo, se utilizan los datos de transacciones de nivel 1 del mercado de valores de EE. UU. El 17 de agosto de 2007, replayDS se utiliza para la reproducción de datos y el valor ETF se calcula mediante el motor de agregación transversal integrado en DolphinDB. Los datos se almacenan en la tabla de cotizaciones de la base de datos distribuida dfs: // TAQ A continuación se muestra la estructura y la vista previa de datos de la tabla de cotizaciones.

// Cargar los datos de la tabla de cotizaciones en la base de datos, comprobar la estructura de la tabla 
quotes = database ("dfs: // TAQ") .loadTable ("quotes"); 
quotes.schema (). ColDefs; 

name typeString typeInt 
time SEGUNDO 10 
símbolo SÍMBOLO 17 
ofrsiz INT 4 
ofr DOUBLE 16 
mode INT 4 
mmid SYMBOL 17 
ex CHAR 2 
date DATE 6 
bidsize INT 4 
bid DOUBLE 16 

// Ver los datos de las primeras diez filas en la tabla de cotizaciones 
seleccionar los 10 primeros * de las cotizaciones; 

símbolo fecha hora bid ofr bidsiz ofrsiz mode ex mmid 
A 2007.08.17 04:15:06 0.01 0 10 0 12 80
A 2007.08.17 06:21:16 1 0 1 0 12 80
A 2007.08.17 06:21:44 0.01 0 10 0 12 80 
A 2007.08.17 06:49:02 32.03 0 1 0 12 80 
A 2007.08.17 06:49:02 32.03 32.78 1 1 12 80 
A 2007.08.17 07 : 02: 01 18.5 0 1 0 12 84 
A 2007.08.17 07:02:01 18.5 45.25 1 1 12 84 
A 2007.08.17 07:54:55 31.9 45.25 3 1 12 84 
A 2007.08.17 08:00:00 31.9 40 3 2 12 84 
A 2007.08.17 08:00:00 31.9 35.5 3 2 12 84

(1) Divida los datos que se van a reproducir. Dado que hay un total de 336,305,414 piezas de datos en un día, habrá una gran demora en la reproducción después de importar la memoria una vez, y puede causar un desbordamiento de la memoria. Por lo tanto, primero use la función replayDS y especifique el parámetro timeRepartitionSchema para dividir los datos en 62 partes de acuerdo con la marca de tiempo.

sch = seleccionar nombre, typeString como tipo de quotes.schema (). colDefs 
trs = cutPoints (09: 30: 00.001..18: 00: 00.001, 60) 
rds = replayDS (<seleccionar * entre comillas>, `fecha,` tiempo, trs);

(2) Defina la tabla de salida outQuotes, que generalmente es una tabla de datos de flujo.

compartir streamTable (100: 0, sch.name, sch.type) como outQuotes

(3) Defina los pesos del diccionario de ponderaciones de existencias y la función de agregación etfVal para calcular el valor ETF. En este ejemplo, solo calculamos el valor ETF de AAPL, IBM, MSFT, NTES, AMZN y GOOG.

defg etfVal (pesos, sym, precio) { 
    return wsum (precio, pesos [sym]) 
} 
pesos = dict (CADENA, DOBLE) 
pesos [`AAPL] = 0.1 
pesos [` IBM] = 0.1 
pesos [`MSFT] = 0.1 
pesos [`NTES] = 0.1 
pesos [` AMZN] = 0.1 
pesos [`GOOG] = 0.5

(4) Cree un motor de agregación de transmisión y suscríbase a la tabla de salida outQuotes para la reproducción de datos. Al suscribirse a la tabla outQuotes, especificamos las condiciones de filtro para la tabla de publicación. Solo los datos con el símbolo AAPL, IBM, MSFT, NTES, AMZN, GOOG se publicarán en el motor de agregación de sección transversal, lo que reduce la sobrecarga de red y la transmisión de datos innecesarias.

setStreamTableFilterColumn (outQuotes, `symbol) 
outputTable = table (1: 0,` time`etf, [TIMESTAMP, DOUBLE]) 
tradesCrossAggregator = createCrossSectionalAggregator ("etfvalue", <[etfVal {weights} (symbol, ofr)]>, quotes, outputTable, `symbol,` perBatch) 
subscribeTable (, "outQuotes", "tradesCrossAggregator", - 1, append! {tradesCrossAggregator}, true ,,,,, `AAPL`IBM`MSFT`NTES`AMZN`GOOG)

(5) Inicie la reproducción, configúrelo para reproducir 100.000 datos por segundo y el motor de agregación consumirá los datos de reproducción en tiempo real.

submitJob ("replay_quotes", "replay_quotes_stream", repetición, [rds], [`outQuotes],` fecha, `hora, 100000,4)

(6) Ver el valor ETF de las acciones que seleccionamos en diferentes momentos.

// Ver las primeras 15 filas de datos en la tabla outputTable, donde la hora en la primera columna es la hora en que ocurrió el cálculo de agregación 
> seleccionar los 15 principales * de outputTable; 

time etf 
2019.06.04T16: 40: 18.476 14.749 
2019.06.04T16: 40: 19.476 14.749 
2019.06 .04T16: 40: 20.477 14.749 
2019.06.04T16: 40: 21.477 22.059 
2019.06.04T16: 40: 22.477 22.059 
2019.06.04T16: 40: 23.477 34.049 
2019.06.04T16: 40: 24.477 34.049 
2019.06.04T16: 40: 25.477 284.214 
2019 40.06.04T7716 22.059 2019 : 22.04T7716 : 40: 26.477 284.214 
2019.06.04T16: 40: 27.477 285.68 
2019.06.04T16: 40: 28.477 
285.68 2019.06.04T16: 40: 29.478 285.51 
2019.06.04T16: 40: 30.478 285.51 
2019.06.04T16: 40: 31.478 285.51 
2019.06.04 : 32.478 285.51

4. Prueba de rendimiento

Realizamos una prueba de rendimiento sobre la función de reproducción de datos de DolphinDB en el servidor. La configuración del servidor es la siguiente:

Anfitrión: DELL PowerEdge R730xd

CPU: CPU Intel Xeon (R) E5-2650 v4 (24 núcleos, 48 ​​subprocesos, 2,20 GHz)

Memoria: 512 GB (32 GB × 16, 2666 MHz)

Disco duro: 17T HDD (1.7T × 10, velocidad de lectura 222 MB / s, velocidad de escritura 210 MB / s)

Red: 10 Gigabit Ethernet

El script de prueba es el siguiente:

sch = seleccionar nombre, typeString como tipo de quotes.schema (). colDefs 
trs = cutPoints (09: 30: 00.001..18: 00: 00.001,60) 
rds = replayDS (<seleccionar * entre comillas>, `fecha,` tiempo, trs); 
compartir streamTable (100: 0, sch.name, sch.type) como outQuotes 
jobid = submitJob ("replay_quotes", "replay_quotes_stream", replay, [rds], [`outQuotes],` fecha, `hora,, 4)

Cuando la velocidad de reproducción no está establecida (es decir, la reproducción a la velocidad más rápida) y no hay suscripción a la tabla de salida, solo se necesitan de 90 a 110 segundos para reproducir 336,305,414 piezas de datos.


Supongo que te gusta

Origin blog.51cto.com/15022783/2590411
Recomendado
Clasificación