De la negociación cuantitativa a la gestión de activos - Desarrollo de la estrategia de CTA para el rendimiento absoluto

El autor:FMZ~Lydia, Creado: 2023-02-07 09:58:41, Actualizado: 2023-09-18 20:25:11

, [nowTime, this.basb]]); ObjChart.add (([4, [nowTime, este.sabb]]); ObjChart.update ((gráfico); ¿ Por qué?

### 4. In the entry function main(), execute the pre-transaction pre-processing code, which will only run once after the program is started, including:

- ```SetErrorFilter ( )``` to filter the unimportant information in the console
- ```exchange.IO ( )``` to set the digital currency to be traded
- ```ObjChart.reset ( )``` to clear the previous chart drawn before starting the program
- ```LogProfitReset ( )``` to clear the status bar information before starting the program

After the above pre-transaction pre-processing is defined, the next step is to enter the polling mode and execute the onTick() function repeatedly. It also sets the sleep time for Sleep () polling, because the API of some digital currency exchanges has built-in access limit for a certain period of time.

Función principal (() { // Filtrar la información sin importancia en la consola SetErrorFilter ((429 debeGetRecords: debeGetOrders: debeGetDepth: debeGetAccount debe: debeBuy debeSelltimeout debeFutures_OP); exchange.IO(moneda, nombre + _USDT); // Establezca la moneda digital que se comercia ObjChart.reset(); // Borre el gráfico anterior dibujado antes de iniciar el programa LogProfitReset ((); // Borre la información de la barra de estado antes de iniciar el programa mientras (verdadero) { // Introduzca el modo de votación enTick(); // Ejecutar la función onTick Dormir (500); // Dormir durante 0,5 segundos ¿ Por qué? ¿ Por qué?

## II. Get and calculate data

1. Obtain basic data object, account balance, and boll indicator data for use in the trading logic.

Función encendida Marque var data = nuevo Data ((tradeTypeA, tradeTypeB); // Crear un objeto de datos básicos var cuentaStocks = data.accountData.Stocks; // Saldo de la cuenta var boll = data.boll ((dataLength, timeCycle); // Obtener datos del indicador de boll si (!boll) devuelve; // devuelve si no hay datos de boll ¿ Por qué?

## III. Place an order and handle the follow-up

1. Execute the buying and selling operation according to the above strategic logic. First, judge whether the price and indicator conditions are valid, then judge whether the position conditions are valid, and finally execute the trade () order function.

// Explicación de la diferencia de precio // basb = (Vender un precio del contrato A - Comprar un precio del contrato B) // sabb = (Comprar un precio del contrato A - Vender un precio del contrato B) si (data.sabb > boll.middle && data.sabb < boll.up) { // Si sabb es superior a la vía media si (data.mp(tradeTypeA, 0)) { // Compruebe si el contrato A tiene órdenes largas antes de realizar una orden datos.trade ((tradeTypeA, closebuy); // El contrato A cierra una posición larga ¿ Por qué? si (data.mp(tradeTypeB, 1)) { // Compruebe si el contrato B tiene órdenes cortas antes de realizar una orden data.trade ((tradeTypeB, closesell); // El contrato B cierra una posición corta ¿ Por qué? } else si (data.basb < boll.middle && data.basb > boll.down) { // Si basb es inferior a la pista media si (data.mp(tradeTypeA, 1)) { // Compruebe si el contrato A tiene órdenes cortas antes de realizar una orden data.trade ((tradeTypeA, closesell); // El contrato A cierra una posición corta ¿ Por qué? si (data.mp(tradeTypeB, 0)) { // Compruebe si el contrato B tiene órdenes largas antes de realizar una orden data.trade ((tradeTypeB, closebuy); // El contrato B cierra una posición larga ¿ Por qué? ¿ Por qué? si (cuentaStocks * Math.max(data.askA, data.askB) > 1) { // Si hay saldo en la cuenta si (data.basb < boll.down) { // Si la diferencia de precios de basb es inferior a la línea descendente si (!data.mp(tradeTypeA, 0)) { // Compruebe si el contrato A tiene órdenes largas antes de realizar una orden datos.trade ((tradeTypeA, buy); // El contrato A abre una posición larga ¿ Por qué? si (!data.mp(tradeTypeB, 1)) { // Compruebe si el contrato B tiene órdenes cortas antes de realizar una orden data.trade ((tradeTypeB, sell); // El contrato B abre una posición corta ¿ Por qué? } else if (data.sabb > boll.up) { // Si la diferencia de precios de sabb es mayor que la línea superior si (!data.mp(tradeTypeA, 1)) { // Compruebe si el contrato A tiene órdenes cortas antes de realizar una orden datos.trade ((tradeTypeA, sell); // El contrato A abre una posición corta ¿ Por qué? si (!data.mp(tradeTypeB, 0)) { // Compruebe si el contrato B tiene órdenes largas antes de realizar una orden data.trade ((tradeTypeB, buy); // El contrato B abre una posición larga ¿ Por qué? ¿ Por qué? ¿ Por qué?

2. After the order is placed, it is necessary to deal with the abnormal situations such as the unsettled order and the holding of a single contract. And draw the chart.

datos.cancelOrders(); // cancelar las órdenes Datos.dibujoCuadro ((bol); // dibujo datos.isEven(); // Manejar la celebración de contratos individuales

As above, we have created a simple cross-period arbitrage strategy of digital currency completely through more than 200 lines code. The complete code is as follows:

// Variable global // Declare un objeto de gráfico para el gráfico de configuración el gráfico var = { __isStock: cierto, Consejo de herramientas: { xDateFormat: %Y-%m-%d %H:%M:%S, %A El número de Título: texto: curva de pérdidas y ganancias por transacción (detallado) El número de Selector de rango: { Los botones: tipo: hora, número: 1, texto: 1h ¿Por qué no? tipo: hora, número: 2, texto: 3h ¿Por qué no? tipo: hora, Cuenta: 8, texto: 8h ¿Por qué no? tipo: todos, texto: Todos Se trata de: seleccionado: 0, entradaActivado: falso El número de El eje x: { tipo: fecha y hora El número de Eje y: { Título: texto: diferencia de precios El número de contrario: falso, El número de serie: [{ nombre: carril superior, id: línea 1, arriba, datos: [] ¿Por qué no? nombre: medio camino, id: línea2, media, datos: [] ¿Por qué no? nombre: bajo la vía, id: línea3, hacia abajo, datos: [] ¿Por qué no? nombre: basb, id: línea4, basb, datos: [] ¿Por qué no? nombre: sabb, id: línea5, sabb, datos: [] ¿ Qué pasa? Se trata de: var ObjChart = Gráfico (gráfico); // Objeto de dibujo var bar = []; // Serie de diferencias de precios de almacenamiento var oldTime = 0; // Registra la fecha y hora de los datos históricos

// Parámetros var tradeTypeA = this_week; // Arbitraje Un contrato el contrato de arbitraje B var dataLength = 10; // longitud del período del indicador var timeCycle = 1; // Período de línea K var nombre = ETC; // Monedas Unidad var = 1; // cantidad de pedido

// datos básicos Función Datos ((tradeTypeA, tradeTypeB) { // Pasa en el contrato de arbitraje A y el contrato de arbitraje B this.accountData = _C(exchange.GetAccount); // Obtener información de la cuenta this.positionData = _C(exchange.GetPosition); // Obtener información de la posición var recordsData = _C(exchange.GetRecords); // Obtener datos de línea K exchange.SetContractType(tradeTypeA); // Suscribirse al arbitraje de un contrato var depthDataA = _C(exchange.GetDepth); // Arbitraje Datos de profundidad de un contrato exchange.SetContractType(tradeTypeB); // Suscribirse al contrato de arbitraje B var depthDataB = _C(exchange.GetDepth); // Arbitraje B datos de profundidad del contrato this.time = recordsData[recordsData.length - 1].Time; // Tiempo para obtener los datos más recientes esto.askA = profundidadDataA.Asks[0].Precio; // Vender un precio de arbitraje Un contrato esto.bidA = profundidadDataA.Bids[0].Precio; // Comprar un precio de arbitraje Un contrato este.askB = profundidadDataB.Asks[0].Precio; // Vender un precio del contrato de arbitraje B this.bidB = depthDataB.Bids[0].Precio; // Comprar un precio del contrato de arbitraje B // Diferencia de precio de arbitraje positivo (Vender un precio del contrato A - Comprar un precio del contrato B) este.basb = profundidadDataA.Asks[0].Precio - profundidadDataB.Bids[0].Precio; // Diferencia de precio de arbitraje negativo (Comprar un precio del contrato A - Vender un precio del contrato B) este.sabb = profundidadDataA.Oferta[0].Precio - profundidadDataB.Preguntas[0].Precio; ¿ Por qué?

// Obtener la posición Data.prototype.mp = función (comercioTipo, tipo) { var positionData = this.positionData; // Obtener información de la posición Para (var i = 0; i < posiciónData.length; i++) { si (posiciónDatos[i].Tipo de contrato ==Tipo de operación) { si (posiciónDatos[i].Tipo == tipo) { si (posiciónDatos[i].Cantidad > 0) { posición de retornoDatos[i].Cantidad; ¿ Por qué? ¿ Por qué? ¿ Por qué? ¿ Por qué? devuelve falso; ¿ Por qué?

// Síntesis de nuevos datos de la línea K y de los datos del indicador Boll Data.prototype.boll = función (número, tiempoCiclo) { var self = {}; // objetos temporales // Valor mediano de la diferencia de precio de arbitraje positivo y la diferencia de precio de arbitraje negativo El mismo.Cierre = (este.basb + este.sabb) / 2; si (este tiempoA == este tiempoB) { self.Time = este tiempo; } // Compare dos marcas de tiempo de datos de profundidad si (this.time - oldTime > timeCiclo * 60000) { barras.push ((auto); oldTime = este tiempo; } // Pasar en el objeto de datos de diferencia de precio en la matriz K-línea de acuerdo con el período de tiempo especificado si (longitud de barras > num * 2) { bar.shift(); // Controlar la longitud de la matriz de K-línea No lo sé. el retorno; ¿ Por qué? var boll = TA.BOLL(bars, num, 2); // Llame al indicador de la barra en la biblioteca talib retorno { hacia arriba: boll[0][boll[0].length - 1], // indicador de boll vía superior medio: boll[1][boll[1].longitud - 1], // indicador de boll vía media hacia abajo: boll[2][boll[2].length - 1] // indicador de boll hacia abajo de la pista } // Devuelve los datos del indicador de bollas procesados ¿ Por qué?

// Ponga un pedido Data.prototype.trade = función (tradeTipo, tipo) { exchange.SetContractType(tradeType); // Volver a suscribirse a un contrato antes de hacer un pedido Precio de venta, precio de oferta. si (tradeType == tradeTypeA) { // Si la orden se coloca en el contrato A AskPrice = this.askA; // Establecer el precio de la pregunta Pago de precio = esto.pago de precio; // Establecer Pago de precio } si (tradeType == tradeTypeB) { // Si la orden se realiza en el contrato B PreguntaPrice = esto.preguntaB; // Establecer PreguntaPrice El precio de la oferta es el precio de la oferta. ¿ Por qué? Conmutación (tipo) { // Modo de colocación de orden de coincidencia caso comprar: exchange.SetDirection ((tipo); // Establecer el modo de colocación de pedidos cambio de devolución.Comprar ((preguntarPrecio, unidad); caso venta: exchange.SetDirection ((tipo); // Establecer el modo de colocación de pedidos cambio de devolución.Venta ((oferta) Precio, unidad); el caso closebuy: exchange.SetDirection ((tipo); // Establecer el modo de colocación de pedidos cambio de devolución.Venta ((oferta) Precio, unidad); el caso closesell: exchange.SetDirection ((tipo); // Establecer el modo de colocación de pedidos cambio de devolución.Comprar ((preguntarPrecio, unidad); por defecto: devuelve falso; ¿ Por qué? ¿ Por qué?

// Cancelar las órdenes Datos.prototype.cancelOrders = función () { Dormir ((500); // retraso antes de la cancelación, porque algunos intercambios, usted sabe lo que quiero decir Var órdenes = _C ((exchange.GetOrders); // Obtener una matriz de órdenes sin completar si (orders.length > 0) { // Si hay pedidos no cumplidos para (var i = 0; i < orders.length; i++) { // Iterar a través de la matriz de órdenes sin completar exchange.CancelOrder ((ordenes[i].Id); // Cancelar los pedidos no cumplidos uno por uno Dormir (500); // Dormir durante 0,5 segundos ¿ Por qué? Retorno falso; // Retorno falso si se cancela un pedido sin completar ¿ Por qué? Retorno verdadero; // Retorno verdadero si no hay pedidos sin completar ¿ Por qué?

// Manejar la celebración de contratos individuales Datos.prototipo.espar = función () { var positionData = this.positionData; // Obtener información de la posición var tipo = nulo; // Cambiar la dirección de la posición // Si el restante 2 de la longitud de la matriz de posición no es igual a 0 o la longitud de la matriz de posición no es igual a 2 si (posiciónData.length % 2!= 0posiciónData.length!= 2) { para (var i = 0; i < positionData.length; i++) { // Iterar a través de la matriz de posición si (positionData[i].Type == 0) { // Si es una orden larga tipo = 10; // Establecer los parámetros de orden } else si (positionData[i].Type == 1) { // Si es un orden corto tipo = -10; // Establecer los parámetros de orden ¿ Por qué? // Cierre todas las posiciones este.comercio(posiciónDatos[i].ContratoTipo, tipo, posiciónDatos[i].Cuota); ¿ Por qué? ¿ Por qué? ¿ Por qué?

// dibujo Datos.prototipo.dibujo Gráfico = función (bol) { var nowTime = nuevo Date().getTime(); ObjChart.add (([0, [nowTime, boll.up]]); ObjChart.add (([1, [nowTime, boll.middle]]); ObjChart.add (([2, [nowTime, boll.down]]); ObjChart.add (([3, [nowTime, this.basb]]); ObjChart.add (([4, [nowTime, este.sabb]]); ObjChart.update ((gráfico); ¿ Por qué?

// Condiciones de comercio Función encendida Marque var data = nuevo Data ((tradeTypeA, tradeTypeB); // Crear un objeto de datos básicos var cuentaStocks = data.accountData.Stocks; // Saldo de la cuenta var boll = data.boll ((dataLength, timeCycle); // Obtener datos del indicador de boll si (!boll) devuelve; // devuelve si no hay datos de boll // Explicación de la diferencia de precio // basb = (Vender un precio del contrato A - Comprar un precio del contrato B) // sabb = (Comprar un precio del contrato A - Vender un precio del contrato B) si (data.sabb > boll.middle && data.sabb < boll.up) { // Si sabb es superior a la vía media si (data.mp(tradeTypeA, 0)) { // Compruebe si el contrato A tiene órdenes largas antes de realizar una orden datos.trade ((tradeTypeA, closebuy); // El contrato A cierra una posición larga ¿ Por qué? si (data.mp(tradeTypeB, 1)) { // Compruebe si el contrato B tiene órdenes cortas antes de realizar una orden data.trade ((tradeTypeB, closesell); // El contrato B cierra una posición corta ¿ Por qué? } else si (data.basb < boll.middle && data.basb > boll.down) { // Si basb es inferior a la pista media si (data.mp(tradeTypeA, 1)) { // Compruebe si el contrato A tiene órdenes cortas antes de realizar una orden data.trade ((tradeTypeA, closesell); // El contrato A cierra una posición corta ¿ Por qué? si (data.mp(tradeTypeB, 0)) { // Compruebe si el contrato B tiene órdenes largas antes de realizar una orden data.trade ((tradeTypeB, closebuy); // El contrato B cierra una posición larga ¿ Por qué? ¿ Por qué? si (cuentaStocks * Math.max(data.askA, data.askB) > 1) { // Si hay un saldo en la cuenta si (data.basb < boll.down) { // Si la diferencia de precios de basb es inferior a la línea descendente si (!data.mp(tradeTypeA, 0)) { // Compruebe si el contrato A tiene órdenes largas antes de realizar una orden datos.trade ((tradeTypeA, buy); // El contrato A abre una posición larga ¿ Por qué? si (!data.mp(tradeTypeB, 1)) { // Compruebe si el contrato B tiene órdenes cortas antes de realizar una orden data.trade ((tradeTypeB, sell); // El contrato B abre una posición corta ¿ Por qué? } else if (data.sabb > boll.up) { // Si la diferencia de precios de sabb es mayor que la línea superior si (!data.mp(tradeTypeA, 1)) { // Compruebe si el contrato A tiene órdenes cortas antes de realizar una orden datos.trade ((tradeTypeA, sell); // El contrato A abre una posición corta ¿ Por qué? si (!data.mp(tradeTypeB, 0)) { // Compruebe si el contrato B tiene órdenes largas antes de realizar una orden data.trade ((tradeTypeB, buy); // El contrato B abre una posición larga ¿ Por qué? ¿ Por qué? ¿ Por qué? datos.cancelOrders(); // Cancelar las órdenes Datos.dibujoCuadro ((bol); // Dibujo datos.isEven ((); // Manejar la celebración de contratos individuales ¿ Por qué?

// Función de entrada Función principal (() { // Filtrar información sin importancia en la consola SetErrorFilter ((429 debeGetRecords: debeGetOrders: debeGetDepth: debeGetAccount debe: debeBuy debeSelltimeout debeFutures_OP); exchange.IO ((moneda, nombre + _USDT); //Instalar la moneda digital a negociar ObjChart.reset(); // Borre el gráfico anterior dibujado antes de iniciar el programa LogProfitReset ((); // Borre la información de la barra de estado antes de iniciar el programa mientras (verdadero) { // Introduzca el modo de votación enTick(); // Ejecutar la función onTick Dormir (500); // Dormir durante 0,5 segundos ¿ Por qué? ¿ Por qué? ` El comercio de arbitraje se originó a partir de la estrategia de negociación de acciones de Morgan Stanley. Su idea es que la diferencia de precio de dos variedades altamente correlacionadas se ajusta al proceso de palomitas de maíz, es decir, la diferencia de precio sigue regresando a la media desde una posición que se desvía de la media histórica, y luego se desvía de nuevo de la media.

Por lo tanto, podemos comprar bajo y vender alto en la diferencia de precio para obtener ganancias. Luego, de acuerdo con el principio de desviación estándar en estadísticas, la banda de Bollinger está formada por una pista media y las pistas superior e inferior calculadas por la desviación estándar, la formación de tres bandas de malla, que son muy prácticas en la transacción de arbitraje de diferencia de precio.

Después de las pruebas, operando de acuerdo con esta estrategia, el ingreso general es relativamente estable, aunque el ingreso no es muy grande cada vez sin tener en cuenta la tarifa de manejo y el costo de impacto. Debe tenerse en cuenta que debido al arbitraje estadístico, existe el riesgo de expansión inversa de la diferencia de precio. Debemos considerar el problema de stop-loss al diseñar. En segundo lugar, también debemos prestar atención al costo de impacto. Cuando la liquidez de los dos contratos involucrados en la transacción se reduce, tendrá un gran impacto en el ingreso, y los inversores deben evitarlo según corresponda.

4. Iteración avanzada del desarrollo de estrategias de CTA

4.1 Evitar las trampas de la estrategia de CTA de futuros

En las dos últimas clases, escribimos una estrategia de tendencia en MyLanguage y una estrategia de arbitraje en JavaScript. No vimos ningún problema en la prueba de retroceso de la estrategia. Sin embargo, el comercio cuantitativo no es un programa, cuya prueba de retroceso se puede hacer directamente sin ningún problema.

De hecho, el backtest es solo una simulación de la estrategia. Solo se utiliza para evaluar el rendimiento de la estrategia en los datos históricos. Permite a los operadores evaluar y descartar algunas estrategias comerciales rápidamente.

En muchos casos, las estrategias que se ven bien en la prueba de retroceso a menudo no cumplen con el estándar de prueba de retroceso en el mercado real por una variedad de razones.

Datos estáticos y datos dinámicos

Debemos tener un concepto de datos estáticos y datos dinámicos para cuantificar primero. En la prueba de retroceso, usamos datos históricos estáticos. El precio de apertura alta y cierre baja con cada línea K está completo, y cada señal de transacción se puede cerrar al 100%. Pero los datos en el mercado real son dinámicos. Por ejemplo, si el precio máximo es mayor que el precio máximo dentro de 1 hora de la apertura, compre. Pero si la línea K actual no ha terminado, el precio máximo es dinámico, y la señal de negociación puede parpadear hacia adelante y hacia atrás. Esta situación indica que la estrategia utiliza la función futura para juzgar las condiciones de la negociación de compra y venta.

Función futura

¿Cuál es la función futura? Echemos un vistazo a la explicación de la Enciclopedia Baidu primero: Una cantidad depende de otra cantidad, como la cantidad A y la cantidad B. Si B cambia, A cambia, entonces A es una función de B. Si B es una cantidad posterior, A es una cantidad anterior, A cambia con B, y A es una función futura de B. Puede confundirse.

En términos generales, es una función de cotización de datos futuros, como predecir el precio de mañana con el precio de mañana. Si un indicador técnico contiene una función futura, su señal es incierta. A menudo es la señal de transacción actual. Cuando aparece la siguiente línea K, la señal desaparece o cambia de posición.

El precio de cierre es una función futura. El precio de cierre siempre está cambiando hasta que la última línea K se agota. Debe esperar hasta que la línea K se agota para determinar el precio de cierre. Como el precio de cierre en sí es una función futura, todos los indicadores técnicos basados en el precio de cierre también son funciones futuras.

Por lo tanto, si un indicador técnico utiliza el precio de cierre confirmado como datos básicos, la señal de negociación no cambiará sin importar cuánto tiempo haya pasado, se puede decir que el indicador técnico no se refiere a la función futura.

Precios pasados

La función futuro utiliza el precio futuro, que también puede utilizar el precio pasado al contrario. Este también es un problema que muchos novatos tienden a ignorar. Para ilustrar mejor este problema en el futuro, tomemos un ejemplo: si el precio máximo actual es mayor que el precio máximo dentro de 1 hora después de la apertura, compre al precio de apertura. Obviamente, no hay problema con las condiciones de la señal de compra y venta, pero el precio de la orden ha utilizado el precio pasado.

En el backtest, la estrategia es normal, porque el motor de backtest basado en datos estáticos solo puede cerrarse al 100% si hay una señal de compra. Sin embargo, cuando el precio más alto es mayor que el precio más alto dentro de la hora después de la apertura, es seguro que la orden no se puede emitir al precio de apertura del precio anterior.

Vacío de precios

El llamado vacío de precios se refiere a los precios que se muestran en el gráfico de líneas K, pero a los precios que no se pueden negociar en el mercado real, divididos principalmente en los siguientes casos:

  • 1. Cualquiera que haya hecho trading sabe que es difícil comprar cuando el precio sube y es difícil vender cuando el precio baja.
  • 2. El mecanismo de coincidencia del intercambio es la prioridad de precio y la prioridad de tiempo. Algunas variedades a menudo tendrán un gran número de órdenes en el mercado. Si usted está operando con órdenes en el mercado real, debe clasificarse detrás de otras órdenes. Solo puede operar después de que se negocien otras órdenes. Incluso antes de que el precio pueda ser negociado, el precio ha cambiado. Sin embargo, en la prueba posterior, si su estrategia es tratar con el pedido, se tratará a tiempo, lo que es diferente del entorno real del mercado.
  • 3. Si usa una estrategia de arbitraje, el beneficio de la prueba de retroceso es muy alto, porque se supone que ha capturado estas diferencias de precio cada vez. En realidad, muchos diferenciales de precio no se pueden agarrar, o solo se puede agarrar una pierna. En términos generales, debe ser la que no sea favorable a su dirección. Luego debe llenar la otra pierna inmediatamente. En este momento, el punto de deslizamiento ya no es de 1 o 2 puntos, y la estrategia de arbitraje en sí misma tiene como objetivo ganar la diferencia de precio de estos puntos. Esta situación no se puede simular en la prueba de retroceso. La ganancia real no es tan buena como la prueba de retroceso.
  • 4. Aunque el evento del cisne negro no se usa comúnmente, todavía tiene un gran impacto en la negociación cuantitativa. Como se muestra en el cuadro a continuación, en el caso del evento del cisne negro del franco suizo de divisas, tanto los precios altos como los bajos se pueden ver en el cuadro. De hecho, en el mercado extremo del día, el precio medio es vacío, y un gran número de órdenes de stop loss causan eventos de estampida. La liquidez es cero, y es muy difícil de tratar, pero puede detener la pérdida en la prueba de retroceso.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

Reajuste excesivo

El sobreajuste es un error común cometido por los principiantes del comercio cuantitativo. ¿Qué es el sobreajuste? Para tomar un ejemplo simple, algunas personas usan una gran cantidad de ejercicios para memorizar cada pregunta en el examen escolar. No puede hacerlo si el tema cambia un poco durante el examen. Debido a que memorizó la práctica de cada pregunta de una manera muy compleja, no abstrajo las reglas generales.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

Como el gráfico anterior, un modelo puede adaptarse a los datos perfectamente siempre que sea lo suficientemente complejo. Esto también es cierto para el sobreajuste en el comercio cuantitativo. Si su estrategia es compleja y tiene muchos parámetros externos, siempre habrá uno o varios parámetros que pueden encajar perfectamente en el mercado histórico en la prueba de retroceso de datos históricos limitados.

Sin embargo, en el futuro mercado real, el cambio de precio puede exceder el límite de su estrategia. De hecho, la esencia del desarrollo de estrategias comerciales cuantitativas es el proceso de emparejamiento de datos locales no aleatorios de una gran cantidad de datos aparentemente aleatorios. Por lo tanto, necesitamos usar el conocimiento estadístico para evitar la trampa. ¿Cómo lo hacemos?

La solución de compromiso es utilizar datos intra-muestra y extra-muestra. Dividir todos los datos en dos partes, y utilizar la intra-muestra como el conjunto de entrenamiento, que es responsable de la prueba de retroceso de datos. La muestra extra se utiliza como el conjunto de prueba y es responsable de la verificación. Si hay pocos datos históricos, también se puede utilizar el método de prueba cruzada.

Si usted encuentra que los datos de la muestra no funcionan bien, y usted siente que es demasiado malo perder el modelo o usted no está dispuesto a admitir que su modelo no es bueno, y usted continúa optimizando el modelo para los datos de extra-muestra hasta que los datos de extra-muestra también funcionan bien, entonces usted debe perder su dinero al final.

Vicio de supervivencia

El sesgo de supervivencia se puede explicar con los siguientes ejemplos: 1. Cuando están de pie en el tuyere, los cerdos volarán. Las personas que venden paracaídas en línea son elogiadas, porque las personas con problemas con los paracaídas ya no viven. 3.El reportero preguntó si los pasajeros habían comprado billetes en el autobús, porque las personas sin billetes no pueden subir al autobús en absoluto. 4. Los medios de comunicación anuncian que se puede ganar la lotería, porque los medios de comunicación no promoverán activamente a las personas que no ganan la lotería.

En el ejemplo anterior, podemos encontrar que la información que las personas suelen recibir en realidad se filtra, lo que hace que una gran cantidad de datos o muestras sean ignoradas selectivamente, y el resultado es que las conclusiones basadas en el sesgo de supervivencia se han desviado de tiempo real.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

  • Gráfico izquierdo (parecido): Una muy buena estrategia de negociación. Sin retiro importante, los inversores pueden obtener rendimientos estables de la inversión.
  • Gráfico derecho (la realidad): Este es sólo el mejor de 200 pruebas de trading aleatorias.

La imagen de la izquierda es una muy buena estrategia comercial. La curva de capital es buena, y no hay una retirada significativa, y se pueden obtener retornos de ganancias estables. Pero mire la imagen de la derecha. Es solo la mejor de los cientos de transacciones de backtest. Por otro lado, cuando miramos el mercado financiero, siempre hay más estrellas y menos estrellas de longevidad. Si la estrategia de los operadores es consistente con la situación del mercado, entonces el mercado cada año puede crear un lote de estrellas, pero es difícil ver estrellas de longevidad que puedan obtener ganancias constantes durante más de tres años consecutivos.

Choque de costes

A menos que esté pendiente de una orden, puede tener un precio deslizante al operar. En las variedades con negociación activa, el precio de oferta y el precio de compra generalmente son diferentes en un punto. En las variedades con negociación inactiva, la diferencia puede ser mayor. Cada vez que desea tomar la iniciativa de cerrar un trato, necesita al menos una diferencia de punto, o incluso más. Sin embargo, en la prueba posterior, no necesitamos considerar el tema de la transacción, siempre que haya una señal, podemos operar, por lo que para simular el entorno comercial real, debemos agregar al menos un precio deslizante.

Especialmente para la estrategia que se negocia con más frecuencia, si el precio de deslizamiento no se agrega cuando la estrategia se prueba, la curva de capital siempre se inclinará hacia arriba, y una vez que se agrega el precio de deslizamiento razonable, se convertirá en una pérdida de inmediato.

Capacidad estratégica

La misma estrategia será muy diferente en mercados eficientes e ineficientes, incluso lo contrario. Por ejemplo, en mercados ineficientes como los mercados de valores nacionales, futuros de productos básicos y monedas digitales extranjeras, debido a la pequeña base de volumen de negociación, la capacidad de la estrategia de alta frecuencia en sí no es muy grande, y no hay espacio de ganancia para más personas, e incluso la estrategia que originalmente era rentable se ha convertido en una pérdida. Pero en un mercado de divisas eficiente, puede acomodar muchos tipos diferentes de estrategias de alta frecuencia.

Las siguientes son los problemas y trampas que pueden ocurrir en el desarrollo y uso de estrategias. Para un desarrollador de sistemas comerciales experimentado, la prueba de retroceso es una necesidad. Porque puede decirle si una idea estratégica se puede verificar en transacciones históricas. Pero muchas veces, la prueba de retroceso no significa que será rentable en el futuro.

4.2 Establecer la mejor gestión de la posición

En Reminiscencias de un operador de acciones, hay un párrafo muy interesante: el Viejo Turquía (anteriormente conocido como Partridge) que está en la misma compañía de valores que el héroe Livermore, siempre hace un gran negocio.

Incluso Livermore suspiró finalmente: No hay nada notable en la tendencia. Siempre hay muchas personas que son optimistas en el mercado alcista y bajistas en el mercado bajista. Pero siempre son buenos en negociar con el mercado, tratando de comprar en el punto más bajo y vender en el punto más alto. Al igual que el Viejo Turquía, son aquellos que ven el mercado y mantienen sus posiciones los que realmente hacen una gran fortuna, que también es la más difícil de aprender. Esto no solo enfrenta la elección del objetivo y el momento, sino que también enfrenta una pregunta más importante: ¿cuánta posición (riesgo) debemos mantener (bear)?

Todos los traders fracasados tienen un pensamiento unilateral. Al operar, las personas codiciosas solo ven ganancias en lugar de riesgos, mientras que las personas tímidas solo ven riesgos en lugar de ganancias. Las personas codiciosas y tímidas se olvidan de los riesgos cuando suben, y se olvidan de las ganancias cuando caen. Sin embargo, los traders exitosos considerarán tanto los riesgos como los retornos, es decir, asumirán varios dólares de riesgo por cada dólar que ganen. Entonces, el índice para medir el rendimiento y el riesgo es la relación de riesgo de retorno.

Muchas personas saben que el riesgo es tan grande como el beneficio, es decir, el rendimiento es proporcional al riesgo.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

Pero en la transacción real, el rendimiento y el riesgo están lejos de ser tan simples como dos puntos de una línea, al menos no siempre se mueven linealmente. El riesgo real es la cantidad máxima de pérdida que se puede tomar con el rendimiento esperado, o lo que llamamos la máxima volatilidad. Aunque a veces la pérdida flotante máxima no siempre es igual a la pérdida de cierre en términos del resultado del comercio, la pérdida flotante máxima es real.

De esto, podemos saber que la relación rendimiento/riesgo en la figura anterior no es el rendimiento real. En un entorno comercial real, la relación rendimiento/riesgo debe ser la misma que en el gráfico siguiente:

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

La curva amarilla muestra la fluctuación del patrimonio neto en diferentes riesgos. Con la expansión de los rendimientos esperados, los riesgos también se expanden gradualmente. Si establecemos la bancarrota en 0.5, es decir, la pérdida máxima alcanza el 50%, entonces esta es una estrategia comercial fallida. Aunque el rendimiento final de la estrategia es positivo por el resultado, ya se ha declarado en bancarrota en el medio.

Incluso si su estrategia es positiva, será liquidaciones bajo la gestión incorrecta de la posición. Así que desde este punto de vista, cuánto comprar y vender es más importante que cuándo comprar y vender. Cómo administrar la posición científicamente se ha convertido en un problema fundamental en las transacciones financieras. Así que antes de tratar de resolver este problema, veamos cómo apostar científicamente en el juego.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

Tomemos el lanzamiento de monedas como ejemplo. Supongamos que ambos lados de una moneda tienen el mismo peso. Si hay una ganancia de 2 yuanes y una pérdida de 1 yuanes, es obvio que este es un juego de expectativas positivas. La tasa de ganancia es del 50% y una pérdida de 2. Aquí viene la pregunta: Ahora que tienes 100 yuanes, ¿cómo puedes repetir la apuesta para que 100 yuanes puedan alcanzar 1 millón de yuanes a la velocidad más rápida?

Si no pensamos bien, pensaremos que dado que el retorno de cada apuesta es de 50% * 2-50% * 1, es decir, 50%, entonces para lograr el máximo retorno rápidamente, debemos invertir tanto capital como sea posible en cada apuesta.

Sin embargo, es obvio que no es razonable invertir el 100% del capital en cada juego de apuestas, porque siempre que pierdas el capital una vez, se perderá, aunque sea muy poco probable.

Alguien puede preguntar, ya que la apuesta del 100% es irrazonable, ¿qué pasa con el 90% o una apuesta más baja? De hecho, para resolver este problema, podemos hacer un experimento para simular el juego de apuestas y ver cómo es el resultado de cada apuesta.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

De la tabla, podemos ver que cuando reducimos gradualmente la posición de 90%, 80%, 70%, 60% y 50%, en la misma apuesta, los resultados son completamente diferentes.

Entonces algunas personas pueden preguntar si cuanto menor sea la apuesta cada vez, mejor, como el 10%. Es imposible calcular cada proporción de apuesta. Este es el problema que debe ser resuelto por el famoso Criterio Kelly. En estadísticas, el Criterio Kelly puede maximizar la tasa de crecimiento a largo plazo de una estrategia con una expectativa positiva de apuestas repetidas, y puede calcular la mejor proporción de apuesta en cada apuesta.

No solo eso, asumiendo que el principal y la apuesta se pueden dividir infinitamente, es imposible ir a la quiebra en cualquier apuesta utilizando el Criterio Kelly. Especialmente en la aplicación práctica de las transacciones financieras, es una estrategia de gestión de posiciones con tanto ataque como defensa. Veamos cómo se calcula el Criterio Kelly y veamos la siguiente figura:

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

  • f es el coeficiente de apuesta óptimo para el capital disponible;
  • b es la relación de probabilidades, que también puede denominarse relación de ganancias/pérdidas en el comercio;
  • p es la tasa de éxito;
  • q es la tasa de fallas.

Entonces podemos calcular el ejemplo de juego en esta lección de acuerdo con el Criterio de Kelly. El capital inicial de 100 yuanes puede alcanzar 1 millón de yuanes a la velocidad más rápida utilizando la proporción de apuestas cuando la proporción ganadora es del 50% y las probabilidades son 2.

(0.5*(2+1) -1)/2=0.25

La tasa de ganancia del 50% es 0.5. Multiplicar las probabilidades por 2 más 1, luego restar 1, y luego dividir por 2. El resultado del cálculo es 0.25. Es decir, en cada apuesta, usando el 25% del principal, puede llegar a 1 millón de yuanes a la velocidad más rápida. Podemos simular manualmente según los resultados del cálculo para ver si es correcto.

From Quantitative Trading to Asset Management - CTA Strategy Development for Absolute Return

La figura anterior es el resultado de la simulación manual. Por favor, vea la última línea. En la misma apuesta, después de más de 100 rondas, el 25% de las posiciones alcanzaron 1 millón de yuanes primero. El resultado de 90%, 80%, 70% y 60% de las posiciones es negativo, lo que muestra que incluso una estrategia de negociación de expectativas positivas se declarará en quiebra bajo la gestión incorrecta de la posición.

También podemos ver que el 50% de las posiciones no perderá o ganará al final, lo que también es consistente con el resultado de la ley de los grandes números. Para ilustrar aún más el problema, también se agregó una posición del 10% en la simulación manual. Aunque el resultado final fue un retorno positivo, el efecto fue varios órdenes de magnitud peor que el de una posición del 25%.

Si usted elige el 10% de la posición principal en la aplicación real, su principal se convertirá en más de 30.000 en más de 100 apuestas. Aunque el retorno es grande, en comparación con el 25% de la posición principal, es equivalente a ningún beneficio.

Si quieres obtener ganancias con el criterio de Kelly en la vida, necesitas cumplir con las condiciones de aplicación del criterio de Kelly. No hay duda de que esta apuesta debe provenir del mercado financiero. Especialmente en el comercio cuantitativo, podemos calcular aproximadamente la proporción ganadora y las probabilidades correspondientes a través del backtesting de datos históricos.

Por supuesto, la aplicación práctica del Criterio Kelly en las transacciones financieras no puede ser tan simple, y hay muchos detalles que tratar, como el costo del capital en las transacciones apalancadas, el capital y la posición en las transacciones reales no se pueden dividir de forma inalámbrica, y la proporción de ganancias y pérdidas en las transacciones están cambiando dinámicamente, y así sucesivamente.


Contenido relacionado

Más contenido