4.6 Como implementar estratégias na linguagem C++

Autora:Bem-estar, Criado: 2019-05-06 13:00:27, Atualizado:

Resumo

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.

Introdução à 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 é Random indicator, que era um indicador de análise técnica muito novo e prático usado no mercado de futuros de commodities.

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.

img

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.

Método de cálculo do indicador KDJ

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
    }
}

Estratégia lógica

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.

img

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.

Condições de negociação

  • 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

Implementação do código de estratégia

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:

Passo 1: utilização da biblioteca de arquitetura de estratégia e classes de negociação

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.

Passo 2: Obtenha todos os tipos de dados

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.

  • Obtenha os dados da linha K.

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 this_week na linha 20, que não precisa ser modificado em outro lugar, pois este é um formato fixo.

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.

  • Obter indicadores KDJ, valor K e valores D

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
        }
    }
} 

Passo 3: Enviar encomendas

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 if, que pode ser descrita como: se a condição 1 e a condição 2 forem verdadeiras, coloque a ordem; se a condição 3 ou a condição 4 forem verdadeiras, coloque a ordem.

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 ação para cobertura.

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 action, é julgado se há uma instrução para colocar ordens. Se houver, o código entrará na linha 27, e depois chamará a biblioteca de classes de negociação FMZ Quant, preformando funções de ordem de colocação.

Há dois lugares que devem ser notados:

  1. 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.

  2. 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.

Resumindo

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.

Anúncio da secção seguinte

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!

Exercícios após a escola

  1. Tente implementar o algoritmo de indicador KDJ usando a linguagem C ++ na plataforma FMZ Quant.

  2. Tente utilizar o conhecimento desta secção para elaborar uma estratégia de indicadores do CCI.


Mais.