En el artículo anterior, explicamos la premisa de la implementación de la estrategia comercial desde la introducción del lenguaje C ++, la gramática básica y la estructura de la estrategia.
Uno de los indicadores más utilizados en el análisis técnico, KDJ, fue reconocido por la mayoría de los operadores de todo el mundo. El nombre completo de KDJ es
KDJ se basó en la teoría estadística, un valor aleatorio (RSV) se calculó por la relación de los últimos 9 K línea
Al combinar las ventajas del concepto de impulso, el indicador de fuerza y el promedio móvil, medimos el grado de variación del precio de las acciones desde el movimiento del rango normal. Cuando el valor K es mayor que el valor D, indica que el precio de las acciones está actualmente en una tendencia al alza. Por lo tanto, cuando la línea K cruza la línea D de abajo hacia arriba, es el momento de comprar la acción. Por el contrario, cuando el valor K es menor que el valor D, indica que el mercado de valores está actualmente en una tendencia a la baja. Por lo tanto, cuando la línea K cruza la línea D de arriba hacia abajo, es el momento de vender la acción.
El cálculo del indicador KDJ es complicado. Primero se calcula el valor aleatorio (RSV), y luego se calcula el valor K, el valor D y el valor J. Su método de cálculo es el siguiente:
RSV = (precio de cierre - precio más bajo del período N) / (precio más alto de N ciclos - precio más bajo de N ciclos) * 100
Valor K = media de los ciclos N RSV
D valor = la media de los N ciclos K
Valor J = 3 * valor K -2 * valor D
void main(){ // the program starts from this main function
while (true){ // enter the loop
auto ct = exchange.SetContractType(symblo); //set the contract type
auto r = exchange.GetRecords(); // get the K line array
auto arr = TA.KDJ(r, 9, 3, 3); // calculate the KDJ indicator
auto k = arr[0]arr[0].size() - 2]; // get the previous k line KDJ indicator K value
auto d = arr[1]arr[1].size() - 2]; // get the previous k line KDJ indicator D value
auto j = arr[2]arr[2].size() - 2]; // get the previous k line KDJ indicator J value
}
}
Hay muchas maneras de usar KDJ, que se pueden usar solos o en combinación con otros indicadores. En este artículo lo usaremos de la manera más simple, que son: Si el valor K es mayor que el valor D, creemos que el poder de compra se está fortaleciendo, se ha formado una ola de mercado ascendente, y se genera la señal de posición larga de apertura; si el valor K es menor que el valor D, creemos que el poder de venta se está fortaleciendo, y se ha formado una ola de tendencia a la baja, se genera la señal de apertura de posición corta.
Si el valor de D cambia de arriba a abajo después de que se abre la posición, creemos que el poder de compra se está debilitando, o el poder de venta se está fortaleciendo, y se genera la señal de cierre de la posición larga; si se abre la posición corta, el valor de D cambia de abajo a arriba, creemos que la fuerza del poder de venta se está debilitando, o que el poder de compra se está fortaleciendo, y se generan señales de cierre de la posición corta.
Posición larga abierta: si no existe posición y el valor K es mayor que el valor D
Posición corta: si no existe posición y el valor K es inferior al valor D
Cierre de posiciones largas: si existe una posición larga mantenida y el valor D es menor que el valor D de la línea K permeable
Posición corta de cierre: si hay una posición corta mantenida y el valor D es mayor que el valor D de la línea K permeable
El primer paso en la implementación de una estrategia con código es primero considerar qué datos necesitamos? a través de qué API para obtener? después de que obtengamos los datos, cómo calcular la lógica de negociación?
La llamada arquitectura de estrategia es la forma de diseñar toda la estrategia. Como se muestra a continuación, la arquitectura consta de dos funciones: una es la función principal, el programa comienza desde la función principal, y su función es tratar con el núcleo de la lógica de la estrategia. cosas como: juzgar si la conexión con el intercambio está bien, filtrar información de registro innecesaria, controlar el intervalo de tiempo de ejecución de los núcleos de la lógica de la estrategia; y el otro es la función onTick, en esta función, principalmente es la lógica de la estrategia, que comprende: Obtener datos en bruto, calcular datos, colocar órdenes y más.
bool onTick(){ // onTick function
// strategy logic
}
void main(){ // program starts from here
while (true){ // enter the loop
if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
sleep(1000); // pause for 1 second
continue; // skip this loop, enter the next loop
}
if(!onTick()){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
sleep(1000); // pause for 1 second
}
}
}
El código anterior es el marco de estrategia C ++ que fue creado por las herramientas de la plataforma FMZ Quant. Este es un formato de codificación fijo, toda la lógica de negociación comienza desde la línea 2 y no se hacen cambios en ningún otro lugar. Además, si eres un veterano, puedes agregar o modificar las características según tu necesidad.
Puede pensar en la biblioteca de clase de trading como un módulo funcional. La ventaja de usar una biblioteca de clase de trading es que le permite centrarse en escribir lógica de estrategia. Por ejemplo, cuando usamos la biblioteca de clase de trading, para abrir o cerrar una posición, podemos usar directamente la interfaz API en la biblioteca de clase de trading; pero si no usamos la biblioteca de clase de trading, necesitamos obtener el precio de mercado al abrir la posición. Necesitamos considerar el tema de las órdenes no ejecutadas y el tema de las órdenes de retiro, y así sucesivamente.
Los diversos datos en bruto son una parte importante de la lógica de negociación. ¿Qué tipo de datos necesitamos? Desde nuestra lógica de negociación estratégica, primero necesitamos obtener datos de la línea K. Con los datos originales de la línea K, podemos calcular el indicador KDJ y, finalmente, comparar la relación entre el valor K y el valor D para determinar si se deben realizar órdenes.
Primero, necesitamos obtener la matriz de línea K, porque la matriz de línea K se utilizará para calcular el indicador KDJ. como sigue:
double position = 0; // position status parameter, the default is 0
bool onTick(string symbol){ // onTick function, all strategy logic are in this function
auto ct = exchange.SetContractType(symbol); // set the contract type and trading variety
if(ct == false){ // if the setting contract type and trading variety is not successful
return false; // return false
}
auto r = exchange.GetRecords(); // get the k-line array
if(!r.Valid || r.size() < 10){ // if getting the k-line array or the number of k-line is less than 10
return false; // return false
}
}
void main(){ // program starts from here
while (true){ // enter the loop
if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
sleep(1000); // pause for 1 second
continue; // skip this loop, enter the next loop
}
if(!onTick("this_week")){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
sleep(1000); // pause for 1 second
}
}
}
Como se muestra anteriormente:
Línea 1: Define una variable que se utiliza para recibir el estado de la posición.
Líneas 3 a 12: se define una función onTick, y esta función lleva un parámetro. Este parámetro se pasa en la variedad de negociación, en este caso, utilizando la línea k semanal.
Líneas 14 a 24: Define una función principal que maneja la lógica no estratégica. Lo único que se puede cambiar es el código de contrato
Vamos a centrarnos en la función onTick y ver cómo obtiene los datos de la línea K:
Líneas 4 a 7 : establecer el tipo de contrato y la variedad de negociación, si no se cumple el tipo de contrato y la variedad de negociación, devolver false
Línea 8: Obtener una matriz K-línea, que es un formato fijo.
Líneas 9 a 11: Filtrar la longitud de la línea K, porque el parámetro que usamos para calcular el indicador KDJ es 9. Cuando el número de líneas K es menor que 9, es imposible calcular el indicador KDJ. Así que aquí queremos filtrar la longitud de la línea K. Si la línea K es menor que 10, solo devuelva falso directamente y continúa esperando la próxima línea K.
A continuación, necesitamos calcular los valores K y D del indicador KDJ. Primero es necesario obtener una matriz de indicadores KDJ, y obtener valores K y valores D de esta matriz. En la plataforma FMZ Quant, obtener la matriz de KDJ es muy simple, simplemente llame a la API de KDJ, la dificultad es obtener el valor de los valores K y D, porque la matriz KDJ es una matriz bidimensional.
La matriz bidimensional es realmente fácil de entender, que es una matriz de matriz, las secuencias de obtención son: primero obtener la matriz especificada en la matriz, y luego obtener el elemento especificado de la matriz especificada, como se muestra a continuación:
#include <iostream>
using namespace std;
int main(){
int hour [3][2] = {{100, 50}, {66, 88}, {10, 90}};
cout << hours[0][0]; // get the hours array first elements of first element, the result is 100
cout << hours[0][1]; // get the hours array first elements of second element, the result is 50
cout << hours[1][0]; // get the hours array second elements of first element, the result is 66
return(0);
}
Como se muestra a continuación, la línea 12 utiliza directamente la API del FMZ Quant para obtener una matriz de indicadores KDJ, que es una matriz bidimensional: arr = [[valor K, valor K, valor K...], [valor D, valor D, valor D...], [valor J, valor J, valor J...]]
La línea 13 es obtener el valor k de la línea K anterior, el valor K es arr[0], luego obtener el penúltimo elemento de arr[0], arr[0].size() se puede utilizar para adquirir la longitud de la matriz de arr[0], arr[0].size() - 2 es el segundo último elemento de la matriz, ponerlo juntos son: auto k = arr [0] [arr [0].size () - 2 ]; las líneas 14 y 15 son el mismo cálculo.
double position = 0; // position status parameter, the default is 0
bool onTick(string symbol){ // onTick function, all strategy logic are in this function
auto ct = exchange.SetContractType(symbol); // set the contract type and trading variety
if(ct == false){ // if the setting contract type and trading variety is not successful
return false; // return false
}
auto r = exchange.GetRecords(); // get the k-line array
if(!r.Valid || r.size() < 10){ // if getting the k-line array or the number of k-line is less than 10
return false; // return false
}
auto arr = TA.KDJ(r, 9, 3, 3); // calculate the KDJ indicator
auto k = arr[0][arr[0].size() - 2]; // get the K value of the previous K line
auto d = arr[1][arr[1].size() - 2]; // get the D value of the previous K line
auto dPre = arr[1][arr[1].size() - 3]; // get the D value of the second last of the K line
}
void main(){ // program starts from here
while (true){ // enter the loop
if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
sleep(1000); // pause for 1 second
continue; // skip this loop, enter the next loop
}
if(!onTick("this_week")){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
sleep(1000); // pause for 1 second
}
}
}
Con los datos anteriores, podemos escribir la lógica de negociación y la parte de la orden de colocación ahora. También es muy simple, la más comúnmente utilizada es la declaración
double position = 0; // position status parameter, the default is 0
bool onTick(string symbol){ // onTick function, all strategy logic are in this function
auto ct = exchange.SetContractType(symbol); // set the contract type and trading variety
if(ct == false){ // if the setting contract type and trading variety is not successful
return false; // return false
}
auto r = exchange.GetRecords(); // get the k-line array
if(!r.Valid || r.size() < 10){ // if getting the k-line array or the number of k-line is less than 10
return false; // return false
}
auto arr = TA.KDJ(r, 9, 3, 3); // calculate the KDJ indicator
auto k = arr[0][arr[0].size() - 2]; // get the K value of the previous K line
auto d = arr[1][arr[1].size() - 2]; // get the D value of the previous K line
auto dPre = arr[1][arr[1].size() - 3]; // get the D value of the second last of the K line
string action; // define a string variable action
// if currently holding long position, and the previous K line's D value is less than the second last k line's D value, close all position
// if currently holding short position, and the previous K line's D value is greater than the second last k line's D value, close all position
if((d < dPre && position > 0) || (d > dPre && position <0)){
action = "cover";
}else if (k > d && position <= 0){ // if the previous K line's K value is greater than the previous K line's D value, and there are no long positions
action = "buy"; // set the variable action to "buy"
}else if (k < d && position >= 0){ // if the previous K line's K value is less than the previous K line's D value, and there are no short positions
action = "sell"; // set the variable action to "sell"
}
if (action.size() > 0){ // if there are placing order instruction
position = ext::Trade(action, symbol, 1); // calling the C++ trading class library, placing orders according the direction of variable "action". and also renew the position status.
}
return true; // return true
}
}
void main(){ // program starts from here
while (true){ // enter the loop
if (exchange.IO("status") == 0) // if the connection with the exchange if not stable.
sleep(1000); // pause for 1 second
continue; // skip this loop, enter the next loop
}
if(!onTick("this_week")){ // if the connection with the exchange is stable, enter this if loop, start executing the onTick function
sleep(1000); // pause for 1 second
}
}
}
En el código anterior, las líneas 19 a 28 son la lógica de negociación y el código para colocar órdenes. Sin embargo, antes de esto, necesitamos definir una variable de cadena "acción" en la línea 16, que se utiliza para ayudar a determinar la acción de la orden.
La línea 19 a la línea 21 son: si actualmente se mantiene una posición larga, y el valor anterior de la línea K
Las líneas 21 a 25 son: las condiciones para abrir una posición larga y corta.
La línea 26 a la línea 28 ejecutan la lógica de orden de colocación. En primer lugar, de acuerdo con la longitud de la variable de cadena
Hay dos lugares que hay que tener en cuenta:
Intentar (pero no necesariamente) escribir la lógica de la estrategia a medida que se establece la condición actual de la línea K, y luego colocar el pedido en la siguiente línea K. O la condición anterior de la línea K se establece, colocando pedidos en la línea K actual, de esta manera, el resultado de la prueba de retroceso y el rendimiento real del mercado no son muy diferentes.
En general, la lógica de posición de cierre debe escribir frente a la lógica de posición de apertura. El propósito de esto es tratar de hacer que la lógica de estrategia cumpla con sus expectativas. Por ejemplo, si la lógica de estrategia sólo cumple con la situación en la que necesita hacer la dirección opuesta de la negociación después de cerrar una posición, la regla de este tipo de situación es cerrar la posición primero y luego abrir la nueva posición. Si escribimos la lógica de posición de cierre frente a la lógica de posición de apertura, se cumplirá perfectamente esta regla.
En la sección anterior aprendimos cómo analizar los indicadores técnicos de KDJ y convertirlos en una estrategia de negociación cuantitativa completa. Incluyendo: introducción de la estrategia, método de cálculo del indicador de KDJ, lógica de estrategia, condiciones de negociación, implementación del código de estrategia, etc. A través de este caso de estrategia, no solo nos familiarizamos con el método de programación C ++ en la plataforma FMZ Quant, sino que también las diferentes estrategias se pueden adaptar de acuerdo con los casos en esta sección.
Para lograr una estrategia de negociación cuantitativa es resumir nuestra propia experiencia o sistema de negociación subjetivo, y luego obtener los datos en bruto requeridos por separado, y calcular los datos necesarios para la lógica de la estrategia, y finalmente llamar a la API de órdenes de colocación para realizar la negociación.
Hasta ahora, el tutorial de escritura de estrategias en esta serie ha llegado a su fin, creo que si sigues el tutorial paso a paso que te lleva aquí, ganarás mucho. En cualquier caso, desde la perspectiva de los cursos básicos de comercio cuantitativo, el largo camino ha ido más de la mitad. En el último capítulo, te enseñaremos cómo usar las herramientas de trading de backtesting de FMZ Quant, y cómo evitar los agujeros en el backtesting y hacer los preparativos finales para el trading de mercado real. Aunque es una pequeña parte del contenido, es un gran paso para entrar en el mundo del trading cuantitativo!
Trate de implementar el algoritmo de indicadores KDJ utilizando el lenguaje C ++ en la plataforma FMZ Quant.
Trate de utilizar los conocimientos de esta sección para elaborar una estrategia de indicadores de CCI.