Primeros pasos con la ingeniería de características SQL para el comercio cuantitativo de acciones

Aunque varios tutoriales cuantitativos y plataformas de autoayuda son abrumadores, lo más importante para que los recién llegados comiencen es explorar las funciones.

Para la ruta de aprendizaje tradicional, el primer paso es aprender Python o un cierto lenguaje de programación.Aunque es fácil comenzar con Python, todavía es problemático analizar datos de stock y extraer características útiles en aplicaciones prácticas. Tome un análisis simple como ejemplo, utilizando los datos del mercado de valores japonés descargados de Kaggle (utilice experimentalmente stock_prices.csv en el directorio train_files, o descargue directamente el archivo adjunto CSDN ):

  1. Calcule los ingresos de tenencia durante 1 día y 2 días después de comprar
  2. Calcule 3 indicadores: 5 días, precio promedio de 10 días y el valor máximo de 5 días del precio diario más alto dividido por el precio más bajo.
  3. Analice los tres indicadores anteriores y la relación entre la combinación y los ingresos para encontrar combinaciones de características potencialmente disponibles.
  4. Después de que el índice se divide en engranajes, las características se analizan más a fondo.

Usar el lenguaje de programación directamente ciertamente puede resolver el problema, pero existen varios desafíos:

  1. Los datos originales contienen datos de múltiples acciones en múltiples días de negociación y deben dividirse.
  2. Para un solo dato de stock, el cálculo de las características requiere algoritmos de diseño propio para administrar las ventanas de tiempo.
  3. La división de engranajes de datos y la permutación y combinación de características requieren una gran cantidad de código para implementar.
  4. Es difícil verificar la corrección del código y el costo de mantenimiento y comprensión es alto.

En comparación con los lenguajes de programación como Python, la característica más importante de SQL es declarativa. Solo necesita decirle al sistema lo que quiere hacer y cómo hacerlo en segundo plano. El sistema lo ayudará en silencio en segundo plano. Los diversos desafíos que mencionamos anteriormente se pueden completar fácilmente con la ayuda de las funciones SQL OLAP.

Este tutorial está escrito con Jupyter Lab . Puede instalar el depósito de la familia Anaconda directamente, o puede instalar un mini conda más pequeño . Hay un enlace al tutorial de referencia de instalación relevante al final del artículo. Después de la instalación, ejecute " pip install asqlcell " para instalar un complemento sql de jupyter lab. La programación mixta de Python/SQL en este artículo depende de este complemento. En el tutorial, también explicaremos las funciones OLAP utilizadas por cierto.

Haga clic aquí para descargar datos de prueba.

Primero importa los paquetes que necesitamos

import asqlcell

Use sql para cargar datos y use directamente archivos csv como fuente de datos. %%sql representa la instrucción SQL que se ejecutará más tarde. El nombre seguido de %%sql se utiliza para almacenar el resultado de la ejecución de la instrucción SQL. Es el tipo de marco de datos de pandas y se puede acceder y utilizar directamente en código Python.

%%sql prices
select RowId as code,
       strftime(Date, '%Y-%m-%d') as date,
       Open as open,
       High as high,
       Low as low,
       Close as close
from stock_prices.csv

Los resultados de la ejecución son los siguientes:

Con el complemento asqlcell, se muestra directamente un mensaje de distribución simple para el tipo numérico en la barra de título, en el que se puede hacer clic para ordenar y ver todos los datos en las páginas.

El campo de código de los datos de origen tiene el formato "date_stock code". Esta parte del procesamiento también se puede hacer con SQL, pero la ventaja de usar el complemento asqlcell es que se puede usar para programación mixta, porque el conjunto de datos devuelto por la instrucción SQL es un marco de datos de pandas, por lo que aquí hay un proceso simple usando Python.

prices['code'] = prices['code'].str.split('_', expand=True)[1]
prices

Verifique los precios y, después de la confirmación, comenzaremos el análisis y el procesamiento sobre esta base.

Ahora hablemos de las funciones OLAP Aunque muchos estudiantes dominan el uso de funciones de agrupación y agregación para sumar y promediar, aún no están familiarizados con las funciones relacionadas con OLAP.

Tenemos una tabla de rendimiento de ventas de la siguiente manera, y necesitamos ordenar el rendimiento de ventas de cada región. Usa directamente ordenar por para ordenar el desempeño de todas las personas. Si usas agrupar por, puedes ordenar según el resumen de desempeño (suma, promedio...) de cada región. Entonces, ¿cómo agrupar según cada región y luego dar el número de clasificación según los resultados de clasificación de cada grupo?

personal área logro
Tomás Llevar a la fuerza 80
Jacobo Cantón 90
Casar Cantón 110
Miguel Llevar a la fuerza 85
jeff Llevar a la fuerza 70

Ahora necesitamos usar funciones OLAP, también conocidas como funciones de ventana. Porque dividimos los datos en ventanas por región y luego clasificamos dentro de las ventanas. el código se muestra a continuación:

%%sql sales_rank
select *, rank() over (partition by 地区 order by 业绩 desc) as ranking
from data.csv

Las reglas básicas de sintaxis de las funciones de ventana son las siguientes:

<窗口函数> over (partition by <用于分组的列名> order by <用于排序的列名>)

Aquí agrupamos los datos según las regiones , ordenamos los datos en cada región en orden inverso según el desempeño y luego usamos la función de clasificación para calcular la clasificación de los empleados en cada ventana. Si esta función se implementa en Python, se puede dividir aproximadamente en los siguientes pasos: 1) agrupar datos a través de diccionarios; 2) implementar funciones de clasificación; 3) completar clasificaciones según los resultados de la clasificación; 4) fusión de datos. Obviamente, la eficiencia de la implementación de SQL ha mejorado mucho y la eficiencia de la ejecución se reflejará en nuestros ejemplos posteriores. Debe ejecutarse más rápido de lo que lo implementa directamente con Python.

En comparación con GROUP BY, la función de ventana no afecta el número total de filas de datos, pero el cálculo se realiza por separado en cada ventana.

Si es necesario reutilizar la ventana, puede usar la palabra clave window para extraer esta parte:

%%sql sales_rank
select *, rank() over area_window as ranking
from data.csv
window
    area_window as (partition by 地区 order by 业绩 desc)

Ahora entramos en tema, los requisitos son los siguientes, y se calculan las siguientes características:

  1. FA : media móvil de 5 días
  2. FB : media móvil de 10 días
  3. FC : El máximo de 5 días del precio diario más alto dividido por el precio más bajo
  4. GA1 : Los ingresos de comprar al precio de apertura del siguiente día de negociación del día de negociación actual y vender al precio de cierre en el día T+1
  5. GA2 : Compre al precio de apertura del siguiente día de negociación en el día de negociación actual y venda al precio de cierre en el día T+2

Usamos el conjunto de datos de precios generado anteriormente, tomando como ejemplo la característica del promedio móvil de 5 días. La primera es cómo dividir la ventana, porque los datos contienen los datos de todas las acciones en un período de tiempo, entonces dividimos la ventana según el código de la acción, cada ventana representa una acción y luego ordenamos según la fecha desde lejos. a cerca. Debido a que lo que estamos buscando es el promedio móvil de 5 días, usamos between para limitar el rango de datos. " 4 precedentes y 0 siguientes " representa un total de 5 días desde hace 4 días hasta hoy.

el código se muestra a continuación:

%%sql fa
select code,
       date,
       avg(close) over five as fa,
from prices
window
    five as (partition by code order by date asc rows between 4 preceding and 0 following)

Con 2,3 millones de filas de datos, el cálculo y la salida se completaron en 1,65 segundos.

A continuación, necesitamos calcular el ingreso de T + 1. Para el registro de una determinada acción en un día determinado, el precio de compra se calcula en función del precio de apertura del día siguiente y el precio de venta se calcula en función del cierre. precio del día siguiente. Dividimos las ventanas directamente según el código de stock, y cada ventana se puede ordenar por fecha. Podemos usar la función principal sobre cómo seleccionar los registros de los próximos N días. Si son los N días anteriores, utilice la función de retraso.

%%sql gain
select code,
       date,
       (lead(close, 2, null) over days) / (lead(close, 1, null) over days) - 1 as ga1,
       (lead(close, 3, null) over days) / (lead(close, 1, null) over days) - 1 as ga2
from prices
window
    days as (partition by code order by date asc)

Aquí puedes intentar resolver estos dos problemas por ti mismo:

  1. Calcule el " valor máximo de 5 días dividido por el precio más alto diario dividido por el precio más bajo "
  2. Puede haber una situación en la que el precio de apertura se tire parcialmente y no se pueda comprar.¿Cómo juzgar?

A continuación proporcionamos la instrucción SQL completa:

%%sql features
select code,
       date,
       avg(close) over five as FA,
       avg(close) over ten as FB,
       max(high / close) OVER five as FC,
       (lead(low, 1, null) over days) < (lead(high, 1, null) over days) as canBuy,
       (lead(close, 2, null) over days) / (lead(close, 1, null) over days) - 1 as GA1,
       (lead(close, 3, null) over days) / (lead(close, 1, null) over days) - 1 as GA2
from prices
window
    five as (partition by code order by date asc rows between 4 preceding and 0 following),
    ten as (partition by code order by date asc rows between 9 preceding and 0 following),
    days as (partition by code order by date asc)

Los 2,3 millones de filas de datos se procesaron en menos de 3 segundos.

 A continuación, analizaremos las tres características de FA/FB/FC según la situación de ingresos. Los siguientes datos deben ser filtrados antes del análisis: 1) Registros con un retorno de más del 30% (no crea que no hay pastel en el cielo); 2) Registros sin oportunidades de compra (consulte las acciones A, que significa que todo el límite diario está cerrado). Después del procesamiento, se encontró que se filtraron alrededor de 40,000 registros.

%%sql filtered_features
select *
from features
where GA1 is not null and
      abs(GA1) < 0.30 and
      GA2 is not null and
      abs(GA2) < 0.3 and
      canBuy is not null and
      canBuy

Hacemos un análisis de correlación simple y calculamos el coeficiente de correlación entre características y rendimientos. En términos generales, cuanto mayor sea el coeficiente de correlación, más digno de nuestra atención, y más obvia la convergencia de la dirección del cambio. Un valor negativo indica la dirección opuesta del cambio.

%%sql corr
select corr(FA, GA1) as ca_1,
       corr(FB, GA1) as cb_1,
       corr(FC, GA2) as cc_1,
       corr(FA, GA2) as ca_2,
       corr(FB, GA2) as cb_2,
       corr(FC, GA2) as cc_2
from filtered_features

En el trabajo real, una característica a menudo continúa dividida, como los ingresos, subdividiremos diferentes niveles de ingresos. Aquí dividimos la característica del promedio móvil de 5 días en varios engranajes y verificamos la distribución de ingresos de los diferentes engranajes. Aquí encontraremos que el rendimiento de ingresos de la marcha baja es mejor que el de la marcha alta.

%%sql analysis
SELECT RFA, avg(GA1) * 100 as GA1, avg(GA2) * 100 as GA2, count(1) as rows
from
(
    select cast(percent_rank() over wfa * 5 as int) as RFA,
           ga1, ga2
    from filtered_features
    window
        wfa as (partition by date order by FA)
)
group by RFA

En aplicaciones prácticas, definitivamente no usaremos un solo indicador ¿Qué pasa si queremos ver la permutación y combinación de todos los indicadores? La función cube puede ayudarte. Usar cube(a, b, c) es equivalente a generar diferentes combinaciones de group by y luego combinar los resultados.

%%sql cube_analysis
SELECT RFA, RFB, RFC, avg(GA1) * 100 as GA1, avg(GA2) * 100 as GA2, count(1) as rows
from
(
    select cast(percent_rank() over window_fa * 5 as int) as RFA,
           cast(percent_rank() over window_fb * 5 as int) as RFB,
           cast(percent_rank() over window_fc * 5 as int) as RFC,
           ga1, ga2
    from filtered_features
    window
        window_fa as (partition by date order by FA),
        window_fb as (partition by date order by FB),
        window_fc as (partition by date order by FC)
)
group by cube(RFA, RFB, RFC)

Podemos filtrar directamente para saber los registros donde la rentabilidad T+1 es superior al 0,1% o la rentabilidad T+2 es superior al 0,2%. Ordenando los resultados encontramos algunas buenas combinaciones de características. La mejor característica en realidad tiene una ganancia de casi el 3% por día, pero la cantidad de registros es demasiado pequeña, lo cual es raro. Puede hacer clic en las filas para ver la cartera con más registros, el ingreso está cerca del 0,1% por día y el ingreso anualizado supera el 20% independientemente de la tarifa de manejo. Al competir por esta característica, puede considerar intentar hacer una investigación más profunda para ver si hay una oportunidad de oferta firme.

%%sql good_features
select *
from cube_analysis
where (GA1 > 0.1) or (GA2 > 0.2)

En comparación con la programación tradicional de Python, el uso de instrucciones SQL para jugar con datos tiene una mayor capacidad expresiva, más fácil para solucionar errores y más conveniente para verificar los resultados. Puede intentar descargar datos de Internet para experimentos, practicar habilidades mágicas y lograr la libertad financiera lo antes posible.

Referencia de instalación de Jupyter Lab:

  1. Se recomienda instalar Anaconda o Mini Conda .
  2. Instalación y configuración de Jupyter Notebook/Jupyter Lab|
  3. Guía de instalación de Jupyter notebook/lab - Alibaba Cloud Developer Community

Supongo que te gusta

Origin blog.csdn.net/panda_lin/article/details/129159106
Recomendado
Clasificación