No artigo anterior, explicamos a premissa da implementação da estratégia de negociação a partir da introdução da linguagem C ++, gramática básica e estrutura de estratégia.
Um dos indicadores mais usados na análise técnica, o KDJ, foi reconhecido pela maioria dos traders em todo o mundo. O nome completo do KDJ é
O KDJ foi baseado em teoria estatística, um valor aleatório (RSV) foi calculado pela relação do preço mais alto, mais baixo e de fechamento da linha 9 K recente. em seguida, calculando o valor K, o valor D e o valor J de acordo com a média móvel e desenhando um gráfico para julgar a tendência do preço.
Ao combinar as vantagens do conceito de impulso, indicador de força e média móvel, medimos o grau de variação do preço da ação do movimento da faixa normal. Quando o valor K é maior que o valor D, ele indica que o preço da ação está atualmente em uma tendência ascendente. Portanto, quando a linha K atravessa a linha D de baixo para cima, é hora de comprar a ação. Por outro lado, quando o valor K é menor que o valor D, ele indica que o mercado de ações está atualmente em uma tendência descendente. Portanto, quando a linha K atravessa a linha D de cima para baixo, é hora de vender a ação.
O cálculo do indicador KDJ é complicado. Primeiro, o valor aleatório (RSV) é calculado e, em seguida, o valor K, o valor D e o valor J são calculados. Seu método de cálculo é o seguinte:
RSV = (preço de encerramento - preço mais baixo do período N) / (preço mais alto de N ciclos - preço mais baixo de N ciclos) * 100
Valor K = média dos N ciclos RSV
Valor D = média de 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
}
}
Existem muitas maneiras de usar o KDJ, que podem ser usados sozinhos ou em combinação com outros indicadores. Neste artigo vamos usá-lo da maneira mais simples, que são: Se o valor K for maior que o valor D, acreditamos que o poder de compra está fortalecendo, uma onda de mercado crescente foi formada e o sinal de posição longa de abertura é gerado; se o valor K for menor que o valor D, acreditamos que o poder de venda está fortalecendo, e uma onda de tendência de queda foi Formar sinal, a abertura da posição curta é gerada.
Se o valor D mudar de cima para baixo após a abertura da posição, acreditamos que o poder de compra está enfraquecendo, ou o poder de venda está fortalecendo, e o sinal de posição longa de fechamento é gerado; se a posição curta for aberta, o valor D muda de baixo para cima, acreditamos que a força do poder de venda está enfraquecendo, ou que o poder de compra está fortalecendo, e são gerados sinais de posição curta de fechamento.
Posição longa aberta: Se não houver posição e o valor K for superior ao valor D
Posição curta: se não houver posição e o valor K for inferior ao valor D
Fechamento de posições longas: se houver uma posição longa mantida e o valor D for inferior ao valor D da linha K permeável
Fechamento de posição curta: se houver uma posição curta mantida e o valor D for superior ao valor D da linha K permeável
O primeiro passo na implementação de uma estratégia com código é primeiro considerar quais dados precisamos? através de que API para obter? depois de termos os dados, como calcular a lógica de negociação? Em seguida, qual a maneira de colocar as ordens? finalmente, vamos implementá-lo passo a passo:
A chamada arquitetura de estratégia é a maneira de projetar toda a estratégia. Como mostrado abaixo, a arquitetura consiste em duas funções: uma é a função principal, o programa começa a partir da função principal, e sua função é lidar com o núcleo da lógica da estratégia. coisas como: julgar se a conexão com a troca está ok, filtrar informações de log desnecessárias, controlar o intervalo de tempo de execução dos núcleos de lógica da estratégia; e o outro é a função onTick, nesta função, principalmente é a lógica da estratégia, que compreende: Obter dados brutos, calcular dados, colocar ordens e muito mais.
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
}
}
}
O código acima é o framework de estratégia C ++ criado pelas ferramentas da plataforma FMZ Quant. Este é um formato de codificação fixo, toda a lógica de negociação começa a partir da linha 2 e não há alterações feitas em outro lugar. Além disso, se você é um veterano, pode adicionar ou modificar os recursos de acordo com sua necessidade.
Você pode pensar na biblioteca de classe de negociação como um módulo funcional. A vantagem de usar uma biblioteca de classe de negociação é que ela permite que você se concentre em escrever lógica de estratégia. Por exemplo, quando usamos a biblioteca de classe de negociação, para abrir ou fechar uma posição, podemos usar diretamente a interface API na biblioteca de classe de negociação; mas se não usarmos a biblioteca de classe de negociação, precisamos obter o preço de mercado ao abrir a posição. Precisamos considerar a questão das ordens não executadas e a questão das ordens de retirada, e assim por diante.
Os vários dados brutos são uma parte importante da lógica de negociação. Que tipo de dados precisamos? De nossa lógica de negociação estratégica, primeiro precisamos obter dados da linha K. Com os dados originais da linha K, podemos calcular o indicador KDJ e, finalmente, comparar a relação entre o valor K e o valor D para determinar se devemos colocar ordens. Então vamos obter esses dados.
Primeiro, precisamos obter a matriz de linha K, porque a matriz de linha K será usada para calcular o indicador KDJ. como segue:
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 mostrado acima:
Linha 1 : Define uma variável utilizada para receber o status da posição.
Linhas 3 a 12 : Uma função onTick é definida e esta função carrega um parâmetro.
Linhas 14 a 24: Defina uma função principal que lida com a lógica não estratégica. A única coisa que pode ser alterada é o código de contrato
Vamos focar na função onTick e ver como ela obtém os dados da linha K:
Linhas 4 a 7 : definir o tipo de contrato e a variedade de negociação, se o tipo de contrato e a variedade de negociação não forem definidos com êxito, retornar falso
Linha 8: Obtenha uma matriz de linha K, que é um formato fixo.
Linhas 9 a 11: Filtrar o comprimento da linha K, porque o parâmetro que usamos para calcular o indicador KDJ é 9. Quando o número de linhas K é menor que 9, é impossível calcular o indicador KDJ. Então aqui queremos filtrar o comprimento da linha K. Se a linha K for menor que 10, basta retornar falso diretamente e continuar esperando pela próxima linha K.
Em seguida, precisamos calcular os valores K e D do indicador KDJ. É necessário primeiro obter uma matriz de indicadores KDJ e obter valores K e D dessa matriz. Na plataforma FMZ Quant, obter a matriz de KDJ é muito simples, basta chamar a API de KDJ, a dificuldade é obter o valor dos valores K e D, porque a matriz KDJ é uma matriz bidimensional.
A matriz bidimensional é realmente fácil de entender, que é uma matriz de matriz, as sequências de obtenção são: primeiro obter a matriz especificada na matriz e, em seguida, obter o elemento especificado a partir da matriz especificada, como mostrado abaixo:
#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 mostra a seguir, a 12a linha utiliza diretamente a API do FMZ Quant para obter uma matriz de indicadores KDJ, que é uma matriz bidimensional: arr = [[valor K, valor K, valor K...], [valor D, valor D, valor D...], [valor J, valor J, valor J...]]
A linha 13 é para obter o valor k da linha K anterior, o valor K é arr[0], em seguida, obter o penúltimo elemento de arr[0], arr[0].size() pode ser usado para adquirir o comprimento da matriz de arr[0], arr[0].size() - 2 é o segundo último elemento da matriz, colocá-lo juntos são: auto k = arr [0] [arr [0].size () - 2 ]; as linhas 14 e 15 são o mesmo 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
}
}
}
Com os dados acima, podemos escrever a lógica de negociação e a parte de colocação de ordem agora. Também é muito simples, a mais usada é a declaração
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
}
}
}
No código acima, as linhas 19 a 28 são a lógica de negociação e o código para a colocação de ordens.
A linha 19 até a linha 21 são: se a posição longa estiver atualmente mantida, e o valor D da linha K anterior for menor que o valor D da segunda última linha k, feche toda a posição, se a posição curta estiver atualmente mantida, e o valor D da linha K anterior for maior que o valor D da segunda última linha k, feche toda a posição. e mude a variável
As linhas 21 a 25 são: as condições para abrir uma posição longa e curta.
A linha 26 até a linha 28 executam a lógica de ordem de colocação. Primeiro, de acordo com o comprimento da variável de cadeia
Há dois lugares que devem ser notados:
Tente (mas não necessariamente) escrever a lógica da estratégia como a condição atual da linha K é estabelecida, em seguida, colocando a ordem na próxima linha k. Ou a condição anterior da linha k é estabelecida, colocando ordens na linha atual k, desta forma, o resultado do backtest e o desempenho real do mercado não são muito diferentes.
Em geral, a lógica da posição de fechamento deve ser escrita na frente da lógica da posição de abertura. O propósito disso é tentar fazer a lógica da estratégia atender às suas expectativas. Por exemplo, se a lógica da estratégia apenas atender a situação em que precisa fazer a direção oposta de negociação depois de fechar uma posição, a regra deste tipo de situação é fechar a posição primeiro e depois abrir a nova posição. Se escrevermos a lógica da posição de fechamento na frente da lógica da posição de abertura, ela irá cumprir perfeitamente essa regra.
Acima aprendemos como analisar indicadores técnicos KDJ e convertê-los em uma estratégia de negociação quantitativa completa. Incluindo: introdução da estratégia, método de cálculo do indicador KDJ, lógica da estratégia, condições de negociação, implementação do código da estratégia, etc. Através deste caso de estratégia, não só nos familiarizamos com o método de programação C ++ na plataforma FMZ Quant, mas também as diferentes estratégias podem ser adaptadas de acordo com os casos desta seção.
Para alcançar uma estratégia de negociação quantitativa é resumir a nossa própria experiência de negociação subjetiva ou sistema, e, em seguida, obter os dados necessários em bruto separadamente, e calcular os dados necessários para a lógica da estratégia, e, finalmente, chamar a API de ordens de colocação para realizar a negociação.
Até agora, o tutorial de escrita de estratégia nesta série chegou ao fim, acredito que se você seguir o tutorial passo a passo que o leva aqui, você ganhará muito. Em qualquer caso, da perspectiva dos cursos básicos de negociação quantitativa, o longo caminho já passou mais da metade. No último capítulo, vamos ensiná-lo a usar as ferramentas de negociação de backtesting de FMZ Quant, e como evitar buracos no backtesting e fazer os preparativos finais para a negociação de mercado real. Embora seja uma pequena parte do conteúdo, é um grande passo para entrar no mundo da negociação quantitativa!
Tente implementar o algoritmo de indicador KDJ usando a linguagem C ++ na plataforma FMZ Quant.
Tente utilizar o conhecimento desta secção para elaborar uma estratégia de indicadores do CCI.