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 porsignal_count(número de pasos de tiempo); en cada paso llama abacktest_steppara 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 abacktest_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 |
|
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).