8. Backtesting del motor y el rendimiento (perspectiva del diseño)

Este capítulo explica, desde la perspectiva de arquitectura e implementación, cómo el motor de backtesting de qteasy utiliza la vectorización y Numba, y en qué se diferencia de marcos como VectorBT, para lectores que necesitan una comprensión más profunda o están tomando decisiones técnicas. Para explicaciones a nivel de uso, consulte 6. Backtesting Engine and Performance en “Backtesting y evaluación de estrategias comerciales”.

8.1. 1. 回测引擎在整体中的位置

El flujo de trabajo del modo backtest (modo=1) se resume en [Backtesting, Live Trading y Optimización] (06-backtest-live-optimization.md): prepare datos históricos → cree el Backtester → ejecute el Operator paso a paso de acuerdo con group_timing_table para generar señales → analizar señales y simular rellenos → evaluar y generar. Entre estos, «analizar señales y simular rellenos» es manejado por las funciones de Numba en el módulo backtest, logrando «secuencial a lo largo de la dimensión del tiempo, vectorizado a lo largo de la dimensión del instrumento».

8.2. 2. Numba 使用点与向量化结构

2.1 Funciones principales

En ⟦CÓDIGO0⟧:

  • backtest_step: @njit(nogil=True, cache=True). En un solo paso, basándose en las señales y las posiciones actuales, el efectivo y la cola de liquidación, calcula cantidades de compra/venta, tarifas, actualizaciones de posiciones y actualizaciones de la cola de liquidación; realiza operaciones de matriz en todo el lote de instrumentos.

  • calculate_trade_results: @njit, utilizado para calcular los resultados comerciales y los cambios de efectivo.

  • backtest_batch_steps: @njit(nogil=True, cache=True). Se repite dentro de Numba por signal_count (número de pasos de tiempo); en cada paso llama a backtest_step para completar todo el segmento de backtest, logrando «secuencial a lo largo de la dimensión del tiempo, vectorizado a lo largo de la dimensión del instrumento».

  • backtest_flash_steps: @njit(nogil=True, cache=True). Similar a backtest_batch_steps, pero no retiene series intermedias de efectivo y posiciones (solo se mantiene el estado final) para ahorrar memoria durante la fase de optimización cuando se realizan pruebas retrospectivas de múltiples conjuntos de parámetros.

En qteasy/blender.py, algunos operadores utilizados para la combinación de señales (como op_sum, op_floor, etc.) también utilizan @njit para la aceleración.

2.2 Ordenamiento y vectorización de la dimensión temporal a lo largo de la dimensión del instrumento

  • La dimensión temporal debe ser secuencial: debido a que existen estados como la cola de liquidación, T+1, MOQ, etc., la siguiente operación depende de las posiciones actuales y del estado de liquidación, por lo que no se puede paralelizar completamente a lo largo del eje temporal ni matrilizarla de una vez.

  • Vectorización de la dimensión del instrumento: dentro de cada paso de tiempo, use matrices NumPy y operaciones en línea dentro de Numba para las señales, posiciones, cantidades de compra/venta, tarifas, etc. de todos los instrumentos, evitando bucles a nivel de Python.

Por lo tanto, un único backtest puede entenderse como: un bucle de paso de tiempo dentro de una capa de Numba + cálculo vectorizado dentro de cada paso.

2.3 Etapa de optimización

En qteasy/optimization.py, varios conjuntos de parámetros ejecutan pruebas retrospectivas en paralelo mediante multiprocesamiento (por ejemplo, ProcessPoolExecutor); dentro de cada conjunto, utiliza rutas como backtest_flash_steps, manteniendo solo el efectivo/posiciones finales para reducir el uso de memoria y aumentar el rendimiento.

8.3. 3. 与 VectorBT 的架构差异

Dimensión

qteasy

VectorBT

Dimensión del tiempo

Pasos secuenciales (pasos de bucle), vectorizados dentro de cada paso

Operaciones matriciales de una sola vez en toda la línea de tiempo, sin ningún bucle de tiempo explícito

Dimensión de activos

En cada paso, realice operaciones de matriz en todos los activos (matrices 1D)

El instrumento y el tiempo participan juntos en la radiodifusión; Se pueden transmitir múltiples estrategias/múltiples conjuntos de parámetros de una sola vez.

Aceleración central

backtest_step, backtest_batch_steps, backtest_flash_steps, etc. son @njit; El análisis de señales, la cola de liquidación/entrega, etc. también utilizan Numba.

NumPy + Numba, con estrategias expresadas como operaciones de matriz pura

Estados y restricciones

Mantiene explícitamente efectivo, posiciones y una cola de liquidación/entrega (T+1, etc.); el estado depende del próximo comercio, por lo que la dimensión temporal debe ser secuencial.

Principalmente una curva de capital simplificada, sin enfatizar T+1/liquidación/MOQ, lo que facilita la construcción de una matriz completa.

Conclusión: qteasy no “carece de vectorización/Numba”; más bien, bajo la premisa de garantizar la corrección del estado (T+1, liquidación, MOQ, fusión de estrategias múltiples, etc.), eligió un compromiso de “ordenado en el tiempo + vectorización de dimensiones de instrumentos + Numba por paso”; tanto él como la “transmisión de matriz completa” de VectorBT tienen cada uno sus propios escenarios aplicables (qteasy se inclina hacia reglas rigurosas y coherencia con el comercio en vivo, mientras que VectorBT se inclina hacia una detección rápida sobre cuadrículas de parámetros masivas).

8.4. 4. 相关文档

  • Modos y punto de entrada unificados: [Backtesting, Live Trading y Optimización] (06-backtest-live-optimization.md).

  • Explicación del lado del usuario: [Realizar pruebas y evaluar estrategias comerciales: motor de pruebas retrospectivas y rendimiento] (…/back_testing/6.%20backtest_engine_and_performance.md).

  • Intención del diseño y aislamiento de datos: [Justificación del diseño y ventajas únicas] (08-design-rationale-and-advantages.md).