
Em um
artigo anterior, comecei a comparar métodos de otimização paramétrica, ou seja, selecionar parâmetros, avaliar a lucratividade de negociar um robô durante o
backtest subsequente. Descobriu-se que o método banal de Monte Carlo - a geração de combinações aleatórias e não correlacionadas de parâmetros de robôs - funciona muito bem. Agora, quero testar um algoritmo popular, incluindo um na comunidade de traders de programação: o
algoritmo de otimização genética .
Algoritmo genético para otimizar uma estratégia de negociação
Vamos considerar esse algoritmo como um exemplo de otimização de 2 parâmetros. Os parâmetros otimizados do nosso robô são o período da
média móvel e
TakeProfit . Para uma imersão maior na “genética”, vamos concordar em chamar o período da média móvel de gene responsável pelo “crescimento” e TakeProfit - o gene da “cor dos olhos”.
No espaço de valores de parâmetros admissíveis, cada ponto, cada par de coordenadas - "altura / cor dos olhos" teoricamente descreve um "indivíduo". Suponha que criamos aleatoriamente 10 indivíduos. Este foi o
primeiro passo do algoritmo de otimização genética - para criar a primeira geração:

No espaço de coordenadas M - T, os pontos são selecionados aleatoriamente. Por exemplo, dois pontos marcados com uma moldura vermelha são "indivíduos" com nomes neutros em termos de gênero (este é um ponto importante!) Zhenya e Sasha. O "crescimento" de Sasha (na formulação inicial do problema é o período médio móvel) é de 11 unidades, a "cor dos olhos" é de 0,6 (olhos verde-azulados). Zhenya é um pouco diferente nos parâmetros. As mesmas características descrevem os 8 indivíduos restantes.
O segundo passo é a reprodução
Desde toda a primeira geração, determinamos um certo número de indivíduos com "sucesso". O critério, obviamente, é o valor de
CF. Esses indivíduos se reproduzem, formando pares aleatoriamente (por esse motivo, receberam nomes de gênero neutro). Em geral, várias regras podem ser definidas para pares correspondentes. Por exemplo, para selecionar indivíduos com características próximas (ou seja, literalmente, mais próximas no espaço de coordenadas) dos indivíduos - consanguinidade. Você pode, pelo contrário, procurar opostos (consanguinidade). Não consegui encontrar argumentos a favor de uma dessas opções - na minha implementação, os pares são formados estritamente por acidente ... Por exemplo, Zhenya e Sasha passaram na qualificação e decidiram dar à luz um descendente. O que isso significa em nosso contexto:

De dois indivíduos "parentais", obtemos o terceiro indivíduo, que herda parte das características de um dos pais, parte do outro. Por exemplo, Zhenya e Sasha deram à luz uma Nikita individual (Nikita, Nikita?):
- Nikita herdou o sinal "cor dos olhos" (parâmetro TakeProfit do robô) de um de seus pais - "Zhenya",
- "Crescimento" (o período do robô com média móvel) Nikita herdou de "Sasha" ... mas ligeiramente ajustado na direção de outro pai, Zhenya.
O fato é que quanto menor a dimensão do espaço de otimização (no nosso caso, é igual a 2), mais "próxima" a prole estará. O algoritmo de otimização genética não determina estritamente as regras para a "herança" de genes para uma filha. Portanto, aleatoriamente, Nikita emprestou a cor de seus olhos sem nenhuma alteração, mas ele ficou no meio entre os dois pais, mais perto de um deles. Na minha implementação, com o mesmo sucesso, Nikita poderia emprestar os parâmetros originais de ambos os pais.
O terceiro passo é criar
Motor do processo evolutivo, seleção natural. 4 dos 10 melhores indivíduos deram mais 10 descendentes. Agora temos 20 indivíduos. O algoritmo de otimização genética envolve a manutenção de um tamanho populacional constante. 10 indivíduos devem "morrer". Nesta implementação, a maioria dos indivíduos da primeira geração “morre”, de 80% a 100%.
Assim, em nosso exemplo, a nova geração será composta de 0 ... 2 pais e 8 - 10 de seus filhos. Em outras palavras, se você omitir a letra, os novos vetores dos parâmetros do robô de negociação serão calculados a partir dos vetores obtidos na etapa anterior, “propagação” (combinação) dos 4 melhores melhores testes. A maioria dos “idosos” não aceitará participação na nova iteração de seleção (outras opções para implementar a seleção são possíveis).
Conclusão do algoritmo
A reprodução e a seleção são repetidas N vezes. Especificamente, em nosso exemplo, para comparação com três algoritmos testados anteriormente, 4 gerações de 10 indivíduos são testadas, totalizando 40 testes.
Mas pode acontecer que outra população entre em colapso. Em outras palavras, todos os testes estarão próximos de vários pontos. Para evitar essa situação, vários mecanismos são usados, em particular:
- infusão de “sangue fresco” na população. Aos descendentes da população atual são adicionados vários novos indivíduos obtidos por acaso, da mesma forma que a população inicial foi formada,
- mecanismo de mutação: um indivíduo filhote pode ter algumas das características (coordenadas) ligeiramente diferentes das características de seus pais:

neste exemplo
- as características dos descendentes Jane e Joss - “crescimento” e “cor dos olhos” são emprestadas de cada um dos pais,
- as características dos filhos de Sam e Siri são um pouco diferentes das características correspondentes de ambos os pais.
Na minha implementação, apesar de mutações e “indivíduos novos”, a população teve que ser atualizada periodicamente como um todo para evitar convergência prematura, localização de toda a população em um espaço limitado.
Se retornarmos aos dados originais nos quais testamos os algoritmos de Monte Carlo, a descida do gradiente e o algoritmo com o nome de trabalho "batalha no mar", o processo de otimização pode ser ilustrado pela seguinte animação:

Como você pode ver na animação, a princípio, a disposição dos pontos é caótica, mas, com as gerações subsequentes, tende a áreas com valores mais altos do DF.
Agora compare os algoritmos na mesma superfície:
P = f (
M ,
T ):

Monte Carlo | descida gradiente | "Batalha no mar" | algoritmo genético |
---|
95,7% | 92,1% | 97,0% | 96,8% |
O valor médio do extremo encontrado da FC como uma porcentagem do valor global.
Obviamente, é muito cedo para julgar por um conjunto de dados de entrada, mas até agora o GA, em relação ao nosso robô de negociação, é inferior ao algoritmo de "batalha marítima":
- insignificante - pela média do valor quase ótimo encontrado da CF,
- fornece a pior estimativa da estabilidade paramétrica do algoritmo de negociação, uma vez que não “investiga” o ambiente das tuplas de parâmetro quase ótimas encontradas com muito poucos detalhes.
Teste final de 4 algoritmos de otimização
O teste final foi realizado em 4 conjuntos de dados de entrada - os resultados do backtest da estratégia de negociação em 4 segmentos diferentes do histórico de preços (
EURUSD : 2016, EURUSD: 2017,
XAUUSD : 2016, XAUUSD: 2017).

(exemplos de filtros digitais como funções de
dois parâmetros para 4 séries temporais de preços)
Desta vez, a otimização foi realizada de acordo com 3 parâmetros:
- período de média móvel "rápida"
- período de média móvel "lenta"
- TakeProfit (lucro da transação, em porcentagem, ao atingir o qual a transação foi concluída).
Cada um dos parâmetros levou 20 valores diferentes. Total para criar a tabela
P = F (Mf, Senhora, T)
onde P é o lucro, Mf é o período da média móvel "rápida", Ms é o período da média móvel "lenta", T é TakeProfit,
20 * 20 * 20 = 8.000 iterações de teste foram realizadas.
A otimização foi realizada com uma restrição de 160, 400 e 800 testes (cálculos de DF nas coordenadas selecionadas). Cada vez, os resultados foram calculados para 1.000 iterações de otimização. O valor médio do DF para o vetor quase ótimo de parâmetros encontrado foi:
Monte Carlo | descida gradiente | "Batalha no mar" | algoritmo genético |
---|
84,1% | 83,9% | 77,0% | 92,6% |
Separadamente, vale ressaltar que o GA mostra um bom resultado, mesmo com uma pequena porcentagem de testes do número total possível de opções:
testes | Monte Carlo | descida gradiente | "Batalha no mar" | algoritmo genético |
---|
160 de 8.000 | 79,1% | 76,7% | 73,1% | 87,7% |
400 de 8.000 | 84,7% | 85,0% | 77,4% | 93,7% |
800 de 8.000 | 88,6% | 90,1% | 80,4% | 96,3% |
Em vez de uma conclusão
Fiquei um pouco surpreso com o resultado, que mostrou um algoritmo de otimização genética. Eu não acho que especificamente o "paradigma genético" do método tenha fornecido a ele o primeiro lugar na lista. Em certo sentido, de acordo com a lógica da escolha das coordenadas, assemelhava-se aos métodos de dicotomia / proporção áurea. Provavelmente vale a pena tentar um desses algoritmos e comparar o GA com ele.
Voltando ao robô comercial, vale a pena observar como o “relevo” da superfície formada pelo CF (lucro) muda de ano para ano. Ou seja, tendo “otimizado” o robô na história de 2017,
não faz sentido aplicar essas configurações em 2018 (primeiro trimestre, mês, semana ... 2018).
Estratégias de negociação artificiais, dogmáticas e desamparadas como a nossa (comprando no cruzamento da média móvel) provavelmente não sairão de moda em breve. Infelizmente, eu não tinha outras estratégias. Assim, atribuo o lucro ou a perda dos robôs de negociação à sorte, e não às vantagens / desvantagens do algoritmo. Portanto, a tarefa de otimização paramétrica de um robô de negociação é para mim pessoalmente exclusivamente de interesse acadêmico.