Desenvolvimento automatizado da estratégia de negociação
Negociação algorítmica.
Desenvolvimento de robôs comerciais e indicadores técnicos.
A negociação algorítmica (negociação automatizada) é uma das características mais fortes do MetaTrader 4, permitindo que você desenvolva, teste e aplique consultores especializados e indicadores técnicos. Elimina quaisquer obstáculos na atividade analítica e comercial.
A plataforma possui o IDE MQL4 (Integrated Development Environment), permitindo que você desenvolva Expert Advisors (robôs comerciais) e indicadores técnicos de qualquer complexidade. Seu núcleo é a linguagem de programação orientada a objetos MQL4 para o desenvolvimento da estratégia de negociação. Oferece alta eficiência, flexibilidade e funcionalidade.
O MetaEditor incorporado foi projetado para o desenvolvimento de estratégias de negociação no MQL4. Ele também possui o depurador. A compilação também é realizada no editor. Depois disso, o aplicativo é movido automaticamente para o MetaTrader 4, onde ele pode ser testado ou otimizado no testador Estratégia, que é mais um outro componente IDE MQL4. A plataforma MetaTrader 4 executa aplicações comerciais e, portanto, é o último componente do ambiente.
Então, no MetaTrader 4, seu indicador analisa os mercados, enquanto um consultor especialista negocia neles. Mas isso não é tudo. Você pode usar o seu produto pronto de outras maneiras:
publique-o na Base de Código, para que milhões de comerciantes possam baixá-lo gratuitamente, comercialize-o no mercado, entregue-o ao seu cliente através do serviço Freelance e receba um pagamento pelo seu trabalho.
Automated Trading Championship (uma competição de robôs comerciais realizada por nossa empresa) demonstrou claramente o poder do idioma. Ao longo de três meses, os MQL4 Expert Advisors competiram por um fundo de prêmios de 80 000 USD sem qualquer intervenção humana, e você pode descobrir os detalhes.
Em outras palavras, o MetaTrader 4 oferece as maiores oportunidades para o desenvolvimento de Expert Advisors e indicadores técnicos. Além disso, com o MetaTrader 4, você recebe serviços adicionais, permitindo que você aproveite ao máximo seus talentos de programação.
Desenvolvimento automatizado da estratégia de negociação
O QuantDesk é uma solução completa de ponta a ponta para um fundo quantitativo de qualquer tamanho. Inclui OpenQuant IDE, QuantRouter (servidor de execução de algo com replicação de feed, consolidação, agregação e roteamento de pedidos inteligentes), QuantBase (servidor de dados de mercado com captura de feed em tempo real e gerenciamento de dados históricos centralizado), QuantTrader (mecanismo de implantação de produção para estratégias de negociação automatizadas desenvolvidas com OpenQuant) e QuantController, um aplicativo de servidor que complementa o QuantDesk para permitir um gerenciamento eficiente da arquitetura de negociação distribuída da SmartQuant.
Claro, ainda passamos muito tempo experimentando, tentando e testando diferentes estratégias. Ter um bom ambiente de desenvolvimento não permite que você ignore esse passo. A vantagem real de uma estrutura bem projetada é cortar o tempo entre testes e produção ao mínimo, e na natureza escalonável da infra-estrutura, que pode crescer com a empresa de gerenciar um pequeno capital de semente para níveis verdadeiramente institucionais. Com um sistema como este, os gerentes emergentes podem se sentir em condições equitativas ao negociar no mesmo mercado como concorrentes muito maiores e podem perceber plenamente as vantagens inerentes de ser ágil e adaptável.
Desenvolvimento automatizado da estratégia de negociação
Para uma versão gratuita do Adaptrade Builder, visite a página de download do Construtor.
Operadores de variação no desenvolvimento de estratégias automatizadas.
por Michael R. Bryant.
As ferramentas para desenvolvimento automatizado da estratégia de negociação, como o Adaptrade Builder, são projetadas para criar estratégias de negociação com entrada e intervenção mínima do usuário. Em vez de o comerciante chegar a idéia de estratégia e programá-lo, o usuário fornece os requisitos gerais, e o software faz o resto. Isso levanta a questão: como um computador apresenta idéias comerciais? A resposta cabe aos chamados operadores de variação.
Se você já otimizou as entradas para uma estratégia de negociação, provavelmente você entende a idéia básica de otimização. O objetivo é simples: você deseja encontrar os valores dos parâmetros que maximizam algum objetivo, como lucro líquido ou fator de lucro. Os parâmetros para uma estratégia de negociação normalmente seriam variáveis como os comprimentos de look-back do indicador, portanto, por exemplo, seu objetivo talvez seja encontrar o comprimento de uma média móvel que maximize o lucro líquido de sua estratégia de negociação. Embora pareça ser bastante diferente, a mesma abordagem geral é usada com o desenvolvimento automatizado de estratégias. Como encontrar os valores de entrada ótimos para uma estratégia de negociação, o desenvolvimento automático de estratégias de negociação é um problema de otimização e a otimização depende de operadores de variação.
O que os operadores de variação fazem? A otimização é essencialmente uma maneira sistemática de tentar valores diferentes do objeto sendo otimizado até encontrar o valor ou os valores que maximizam a função objetivo. Por exemplo, a técnica mais simples é tentar todos os valores possíveis e gravar aquele que dá o resultado ideal. Métodos mais sofisticados, como otimização genética 1 ou otimização de enxames de partículas 2, bem como métodos tradicionais, como descida de gradiente 3 ou recozimento simulado, 4 fornecem diferentes maneiras de selecionar os valores para chegar a solução ideal mais rápido, sem ter para tentar todos os valores possíveis. O operador de variação modifica o valor atual para chegar ao próximo valor a tentar.
Numa "força bruta" otimização, em que todo o valor possível é testado, o operador de variação para encontrar o comprimento ideal da parte traseira seria simplesmente adicionar 1 ao valor atual. No método de descida mais íngreme, o operador de variação envolve a derivada parcial da função objetiva; ele adiciona uma fração da derivada parcial ao valor atual, de modo que segue a inclinação da função objetiva para o seu pico (ou por baixo, dependendo se você está minimizando ou maximizando). Em geral, os operadores de variação são o que permite que o processo de busca percorra o espaço de todas as soluções possíveis no caminho para encontrar o melhor.
Quando o objeto a ser otimizado é um conjunto de regras para uma estratégia de negociação, os operadores de variação precisam ser um pouco mais complexos. Neste caso, o espaço de todas as soluções possíveis consiste em todas as regras de negociação possíveis para a estratégia. A variação de operadores precisa ser capaz de atravessar esse espaço. Em outras palavras, eles precisam ser capazes de gerar uma infinita variedade de idéias comerciais. Os operadores de variação são os geradores de ideias do algoritmo de otimização.
Algoritmos evolutivos, como otimização genética e programação genética, geralmente usam dois tipos de operadores de variação: cruzamento e mutação. Estes são os dois tipos básicos de operadores de variação utilizados no Adaptrade Builder, bem como em outras ferramentas automatizadas de desenvolvimento de estratégias baseadas em programação genética. Este artigo irá ilustrar os operadores de variação específicos e únicos utilizados no Adaptrade Builder, bem como a forma como vários aspectos do processo evolutivo são controlados.
Crossover e Mutação em Programação Genética.
Quando a programação genética é aplicada ao desenvolvimento automatizado da estratégia de negociação, a lógica da estratégia é representada por uma ou mais estruturas de árvores. Essas árvores de regra avaliam verdadeiro ou falso, que é usado como uma condição para entrar ou sair de um comércio. O Crossover é um operador de variação que troca uma subárvore da árvore de regras de uma estratégia com uma subárvore da árvore de regras de uma estratégia diferente. Desta maneira, dois "pai" as árvores produzem dois "filhos" ou árvores descendentes, como mostrado abaixo na Fig. 1.
Figura 1. O operador de crossover no Adaptrade Builder é usado para trocar parte de uma árvore de regras com outra. As duas árvores parentes no topo são equivalentes às seguintes regras: (Momentum (DayH, 32) & lt; = DayL - C) = (FastK (100) & lt; = FastK (64)); (L [16] Cruce abaixo DayO) = (Tempo = 13:30). Depois de trocar os subárboles delineados nas caixas vermelhas, as novas árvores se tornam: (Momentum (DayH, 32) & lt; = DayL - C) = (Tempo = 13:30); (L [16] Cruce abaixo DayO) = (FastK (100) & lt; = FastK (64)).
Na figura acima, como com as figuras que se seguem, as árvores parentes são mostradas no topo da figura com as árvores menores abaixo. As partes das árvores descritas nas caixas vermelhas são modificadas entre o pai e a criança, com as partes modificadas descritas em caixas verdes nas árvores menores. No caso do crossover, as subveres nas caixas vermelhas são trocadas. As funções do indicador são abreviadas: O, H, L e C representam o aberto, alto, baixo e próximo, respectivamente; DayH e DayL são os preços altos e baixos do dia, respectivamente, nos dados intradiários; & quot; = & quot; é usado para representar o operador de igualdade (em oposição a "atribuição"). Todos os exemplos para este artigo são retirados dos resultados de compilação reais do Adaptrade Builder.
A estrutura da árvore mostra como os indicadores são combinados. Por exemplo, a árvore no canto superior esquerdo da Fig. 1 pode ser escrita como (Momentum (DayH, 32) & lt; = DayL - C) = (FastK (100) & lt; = FastK (64)). O operador de igualdade significa que essa expressão seria verdadeira se as expressões em cada lado do operador forem verdadeiras ou ambas falsas ao mesmo tempo. Uma característica-chave do crossover é que os componentes básicos (isto é, indicadores, operadores e valores de entrada) não são alterados, mas seu arranjo é modificado.
Os operadores de mutação, por outro lado, alteram os componentes básicos de uma maneira ou de outra. O operador de mutação mais simples é chamado de mutação pontual, mostrado abaixo na Figura 2. Na mutação pontual, os diferentes componentes da árvore são alterados com alguma probabilidade de mutação. Por exemplo, se a probabilidade de mutação for de 20%, há uma chance de 20% de que um componente específico seja alterado. Cada componente é considerado, por sua vez, e se a probabilidade escolhida aleatoriamente for inferior ao limite, como 20%, um novo componente compatível será escolhido para substituir o original. "Compatível" significa que o novo componente não deve alterar o número de entradas ou o tipo de retorno de qualquer função e, se for um valor, deve estar dentro do mesmo intervalo de parâmetros que o valor que está substituindo.
Figura 2. Na mutação pontual, os componentes da árvore superior nas caixas vermelhas são alterados para componentes semelhantes, mostrados na árvore inferior nas caixas verdes. Antes da mutação: (TrueRange + H & gt; AdaptVarMA (DayL, 27, 100, 1.380)) = (Dia = 5). Após a mutação: (TrueRange + H & lt; AdaptZeroLagTrend (DayO, 27, 100, 3.631)) = (Day & gt; = 5).
Na substituição de subárvore, também conhecida como mutação de subárvore, uma subárvore é substituída por uma nova subárvore gerada aleatoriamente. Por exemplo, na Fig. 3, abaixo, a subárvore mostrada na caixa vermelha é substituída pela nova mostrada na caixa verde.
Figura 3. Na substituição da subárvore, a árvore-filho é criada substituindo uma sub-árvore (mostrada na caixa vermelha) na árvore-mãe com uma nova sub-árvore gerada aleatoriamente (mostrada na caixa verde). Antes da mutação: (FastK (95) & lt; = 26) = (StdDev (H, 11) & gt; = AdaptZeroLag (TrueRange, 7, 100, 3.310)). Após a mutação: (FastK (95) & lt; = 26) = (L [11] & gt; TrueRange + DayH).
Outra maneira de mutar uma árvore de regras é torná-la mais complexa. O operador complicado executa esta função substituindo uma função por um pequeno número de entradas com uma função mais complexa que retorna o mesmo tipo de valor, como preço, diferença de preço, valor do oscilador, etc. Um exemplo é mostrado abaixo na Fig. 4 . Neste exemplo, a função de preço, O [13] (ou seja, o preço aberto 13 bares atrás) é substituída pela média móvel de 16 barras do aberto. A nova função é escolhida aleatoriamente no conjunto de todas as funções que atendem aos requisitos. O operador de mutação complicado não só retém o tipo de retorno (preço neste caso), mas o tipo de preço (ou seja, o preço aberto).
Figura 4. O operador de mutação complicada substitui a função O [13] com a função mais complexa MovAve (O, 16), que retém o tipo de retorno (preço) e o tipo de preço (aberto). Antes da mutação: O [13] Cruza acima de L. Após a mutação: MovAve (O, 16) cruza acima de L.
O oposto do operador complicado é o operador de simplificação, que substitui uma função por múltiplas entradas com uma função similar com menos entradas. A nova função é escolhida aleatoriamente do conjunto de todas as funções que retornam do mesmo tipo, mas com menos entradas. Tal como acontece com o operador complicado, o tipo de preço (se aplicável) é mantido na nova função. Por exemplo, como mostrado na Fig. 5, a função WgtMA (O, 62) (isto é, média móvel ponderada de 62 barras do aberto) é substituída pelo preço aberto.
Figura 5. O operador de mutação simplificadora substitui a função WgtMA (O, 62) com o preço simples, O. Antes da mutação: InvFisherRSI (WgtMA (O, 62), 39) & gt; 0. Após a mutação: InvFisherRSI (O, 39) & gt; 0.
Outra maneira de mutar uma estrutura de árvore é cultivá-la. O operador crescer subárvore adiciona uma nova subárvore à árvore existente. A nova subárvore é gerada aleatoriamente e adicionada à árvore existente usando uma nova função lógica, escolhida aleatoriamente de "e", "ou" ou "=". Por exemplo, na Fig. 6, a nova subárvore "Time & gt; 9: 30 " está conectado à árvore existente usando o & quot; e & quot; função. Tanto o operador complicado como o operador de crescimento de subárvore aumentam a complexidade da árvore, mas complicam isso com modificações mínimas na estrutura da árvore, enquanto o crescimento sempre adiciona uma nova subárvore.
Figura 6. O operador de crescimento da subárvore adiciona a nova sub-árvore Time & gt; 9:30 para a árvore-mãe usando o & quot; e & quot; função. Antes da mutação: DayO & lt; = ZeroLagTrend (menor (O, 40), 97). Após a mutação: (DayO & lt; = ZeroLagTrend (menor (O, 40), 97)) e (Horário & gt; 9:30).
O oposto de cultivar uma árvore é poda. O operador de ameixa de ameixa da subárvore remove uma subárvore da árvore existente. A subárvore a remover é selecionada aleatoriamente e a função lógica principal ("e", "ou" ou "quê?" É removida. Por exemplo, na Fig. 7, a sub-árvore "H [14] & lt; = DayL" é removido, juntamente com o & quot; ou? função. Tanto o operador de simplificação como o operador de ameixa da subárvore diminuem a complexidade da árvore, mas simplificá-la com modificações mínimas na estrutura da árvore, enquanto a ameixa sempre remove uma subárvore.
Figura 7. O operador de ameixa subárvore remove a subárvore H [14] & lt; = DayL da árvore-mãe, juntamente com o & quot; ou & quot; função. Antes da mutação: (H [14] & lt; = DayL) Ou (StdDev (DayO, 93) & gt; = ZeroLagTrend (TrueRange, 50)). Após a mutação: StdDev (DayO, 93) & gt; = ZeroLagTrend (TrueRange, 50).
Selecionando o Operador de Variação.
Os sete operadores de variação descritos acima (cruzamento, mutação pontual, substituição de sub-árvore, complicam, simplificam, crescem sub-árvore, ameixa sub-árvore) são a forma como o algoritmo de programação genética gera novas estratégias de negociação. No entanto, com sete formas diferentes de gerar uma nova estratégia, o algoritmo precisa saber qual operador de variação escolher. A primeira escolha é entre crossover e mutation. No Adaptrade Builder, a probabilidade de cruzamento, que é uma das configurações do usuário, determina a porcentagem de estratégias geradas por meio de cruzamento, com o restante gerado por mutação. Por exemplo, se a percentagem de crossover for de 60%, essa porcentagem de estratégias será gerada através de cruzamento com 40% gerados por mutação.
Das estratégias geradas por mutação, o operador de mutação é escolhido aleatoriamente de acordo com a probabilidade de cada operador. Essas probabilidades de mutação são auto-adaptativas. Isso significa que as probabilidades dos seis operadores de mutação são desenvolvidas juntamente com a população de estratégias de negociação. Em outras palavras, o mesmo processo evolutivo que é usado para evoluir as estratégias de negociação é usado para evoluir as probabilidades de mutação. Cada estratégia de negociação tem um conjunto de probabilidades de mutação, e cruzamento e mutação são aplicados às probabilidades de mutação durante o processo de compilação. Ao fazê-lo, as probabilidades de mutação associadas a melhores estratégias tendem a ser propagadas para a próxima geração junto com as estratégias.
Para ver como isso funciona na prática, considere a Fig. 8, abaixo. Isso mostra como as seis probabilidades de mutação, calculadas em média sobre os membros da população, mudam durante o processo de construção. Inicialmente, as seis probabilidades são inicializadas para valores aleatórios próximos de 16,67% (isto é, 100% dividido por 6). A soma das probabilidades para os seis operadores deve somar até 100%. Ao longo de gerações sucessivas, o processo evolutivo tende a favorecer certos operadores sobre outros. Na Fig. 8, o operador de simplificação tem a maior probabilidade, seguido de mutação pontual e substituição de subárvore. Na geração 600, por exemplo, a probabilidade de selecionar o operador de simplificação foi de cerca de 30%, a probabilidade de seleção de mutação pontual foi de cerca de 25%, e assim por diante (assumindo que a mutação foi escolhida por crossover).
Figura 8. As probabilidades de aplicar os seis operadores de mutação diferentes são desenvolvidas juntamente com a população como parte do processo de construção.
Para outros exemplos de compilação, as probabilidades serão diferentes. Além disso, a ordenação das probabilidades pode mudar ao longo do tempo. Por exemplo, observe que na Fig. 8, antes da geração 200, a probabilidade de mutação pontual foi maior que a do operador simplificado. Observe também que a probabilidade de poda da sub-árvore tendia para zero após um grande número de gerações. Isto é provavelmente porque a poda é ativamente aplicada como parte de um processo separado para evitar que a profundidade da árvore exceda um limite especificado. Isso é explicado mais à frente na próxima seção.
Prevenção da Profundidade Excessiva da Árvore.
Cada uma das árvores de regra ilustradas acima tem uma profundidade de árvore associada, que é definida como o número de ramificações da raiz até o final da árvore para o ramo mais longo. Por exemplo, a árvore primária na Fig. 7 tem uma profundidade de árvore de três, enquanto a árvore infantil na Fig. 6 tem uma profundidade de árvore de quatro. A profundidade da árvore é uma medida da complexidade da estratégia. Uma vez que altos níveis de complexidade podem aumentar as chances de excesso de ajuste, o Adaptrade Builder verifica a profundidade da árvore de cada estratégia e aplica o operador de poda da subárvore se a profundidade da árvore exceder a configuração do usuário.
Figura 9. Sem a poda da sub-árvore, a profundidade média da árvore tende a aumentar em relação às sucessivas gerações. Quando a poda da sub-árvore é aplicada a estratégias que excedem uma profundidade de árvore especificada, a profundidade da árvore permanece quase constante.
Ao longo de gerações sucessivas, essa abordagem tende a manter a profundidade da árvore bastante constante, como mostrado pela curva inferior na Fig. 9. Sem essa aplicação de poda de sub-árvore, a profundidade da árvore tende a aumentar, como mostra a curva superior na Fig. 9.Porque as árvores de regra se ramificam para além da profundidade, uma árvore com uma profundidade de seis pode ter mais de oito vezes mais "nós" como uma árvore com uma profundidade de três. Manter a profundidade da árvore durante o processo de construção através do operador de poda da sub-árvore é uma maneira de evitar a complexidade excessiva e a sobreposição.
O desenvolvimento automatizado da estratégia usando métodos como a programação genética pode parecer um pouco misterioso no início. Como o software vem com regras de negociação e lógica? Como as estratégias evoluem em torno de gerações sucessivas? Os operadores de variação descritos acima são uma parte fundamental desse processo. Os operadores de variação de crossover e mutação geram todas as novas estratégias de negociação depois que a população inicial de estratégias é estabelecida e permite que o algoritmo de otimização busque o espaço de possíveis estratégias de negociação em busca dos que atendem aos objetivos e requisitos do usuário.
Além do crossover, o Adaptrade Builder usa seis operadores de mutação diferentes para fornecer a máxima variação na lógica da estratégia. Se o usuário tiver que selecionar as probabilidades com as quais aplicar todos esses operadores diferentes, é improvável que o usuário possa escolher as melhores probabilidades para cada caso de compilação. Por esse motivo, o Builder seleciona as probabilidades de mutação de forma auto-adaptativa, o que significa que eles evoluíram durante o processo de compilação usando a mesma abordagem evolutiva aplicada às próprias estratégias comerciais.
Uma desvantagem potencial de empregar uma grande variedade de operadores de variação é que a complexidade das árvores de regra pode aumentar ao longo de gerações sucessivas, o que pode levar ao excesso de ajuste. Para evitar isso, o operador de poda de subárvore é aplicado a novas estratégias se suas profundidades de árvore excederem a configuração de profundidade de árvore do usuário. Isso ajuda a evitar a complexidade desenfreada enquanto ainda permite a variação. A complexidade ainda pode ser controlada de forma independente durante o processo de compilação usando a métrica de complexidade do programa, que se baseia no número de entradas de estratégia independentes. Uma vez que esta é uma medida de complexidade diferente da profundidade da árvore, é possível alcançar diferentes níveis da métrica de complexidade para o mesmo limite de profundidade da árvore.
Eiben, A. E. e Smith, J. E. Introdução à computação evolutiva, Springer-Verlag, Berlim, 2010, pp. 37-69.
Rini, D. P., Shamsuddin, S. M. e Yuhaniz, S. S. "Otimização de enxertia de partículas": técnica, sistema e desafios ", International Journal of Computer Applications, Vol. 14, No. 1, pp. 19-27, 2011.
Gill, P. E., Murray, W. e Wright, M. H. Otimização prática, Academic Press, Inc., Londres, 1981, pp. 99-105.
Michalewicz, Z. e Fogel, D. B. Como resolver: Heurística moderna, Springer-Verlag, Berlim, 2000, pp. 116-117.
Boa sorte com sua negociação.
Os exemplos apresentados neste artigo foram criados usando o Adaptrade Builder versão 2.3.1. Para uma avaliação gratuita, vá para o Adaptrade / Builder / Download. htm.
Este artigo apareceu na edição de setembro de 2017 do boletim informativo Adaptrade Software.
Se você quiser ser informado de novos desenvolvimentos, novidades e ofertas especiais do Adaptrade Software, por favor, junte-se à nossa lista de e-mail. Obrigado.
Copyright (c) 2004-2017 Adaptrade Software. Todos os direitos reservados.
Desenvolvimento de Estratégia Automatizada - produto de complemento para Ninjatrader.
(Se você já possui uma conta, inicie sessão no topo da página)
Estamos aqui para ajudar. Apenas deixe-nos saber o que você precisa. Trabalhamos extremamente para manter as coisas positivas em nossa comunidade. Não toleramos comportamento grosseiro, trolling ou vendedores publicitários em postagens. Nós acreditamos firmemente e incentivamos a partilha. O santo Graal está dentro de você, podemos ajudá-lo a encontrá-lo. Esperamos que nossos membros participem e se tornem parte da comunidade. Ajude-se ajudando os outros.
Você precisará se registrar para ver o conteúdo dos tópicos e começar a contribuir para a nossa comunidade. É grátis e simples.
Desenvolvimento de Estratégia Automatizada - produto de complemento para Ninjatrader.
Esse artigo é realmente útil. Eu gosto especialmente da parte sobre remover a estratégia de saída como um teste e usar um pequeno objetivo de lucro e parar (devem ser iguais, talvez 2 carrapatos cada). Isso lhe dará uma ótima indicação de como suas entradas estão fazendo observando o & quot;% rentável & quot; coluna do backtest. Claro que não se pode olhar para o fator de lucro e outros detalhes no relatório, pois isso é especificamente para julgar a precisão da entrada, mas nunca menos brilhante.
programação de negociação quantitativa.
Software de sistemas de negociação automatizado e discricionário e indicadores técnicos personalizados projetados para lhe dar a vantagem quantitativa com mais lucro e menos risco.
Estratégia de negociação Aero de Catalyst ESTRATÉGIA NINJATRADER BASADA EM REGRA.
Aero é uma estratégia de negociação discricionária que melhora drasticamente a clareza da ação de preços, a fim de ajudar a identificar oportunidades comerciais mais lucrativas com mais facilidade. Nenhuma obrigação de teste gratuito de 10 dias.
Programação Quantitativa & amp; Consultoria de sistemas.
Nossos serviços de programação personalizados para NinjaTrader, MetaTrader & amp; A TradeStation é capaz de desenvolver estratégias de negociação automatizadas e indicadores que são limitados apenas pela sua imaginação. Entre em contato conosco para discutir seu projeto mais recente e descobrir como podemos fornecer valor à sua operação comercial. Consultoria de sistemas algorítmicos adaptada aos Fundos Institucionais, CTA e Hedge Funds.
© 2014 Catalyst Research Group, LLC - Todos os direitos reservados.
Aviso legal do governo dos EUA - Negociação de Futuros de Mercadorias A negociação de Futuros e Opções tem grandes recompensas em potencial, mas também grande risco potencial. Você deve estar ciente dos riscos e estar disposto a aceitá-los para investir nos mercados de futuros e opções. Não troque com dinheiro que não pode perder. Isso, e todas as outras informações em nosso site, não são uma solicitação nem uma oferta para comprar ou vender futuros ou opções. Nenhuma representação está sendo feita para que qualquer conta seja ou seja susceptível de atingir lucros ou perdas semelhantes às discutidas neste site. O desempenho passado de qualquer sistema ou metodologia comercial não é necessariamente indicativo de resultados futuros.
CLÁUSULA CFTC 4.41 - RESULTADOS DE DESEMPENHO HIPOTÉTICOS OU SIMULADOS TÊM CERTAS LIMITAÇÕES. DESEJO UM REGISTRO DE DESEMPENHO REAL, OS RESULTADOS SIMULADOS NÃO REPRESENTAM A NEGOCIAÇÃO REAL. TAMBÉM, DESDE QUE OS NEGÓCIOS NÃO FORAM EXECUTADOS, OS RESULTADOS PODERÃO TER COMPRIMIDO COM COMPENSADO PARA O IMPACTO, SE QUALQUER, DE CERTOS FATORES DE MERCADO, COMO FALTA DE LIQUIDEZ. PROGRAMAS DE NEGOCIAÇÃO SIMULADOS EM GERAL SÃO TAMBÉM SUJEITOS AO FATO QUE ESTÃO DESIGNADOS COM O BENEFÍCIO DE HINDSIGHT. NENHUMA REPRESENTAÇÃO ESTÁ FAZENDO QUE QUALQUER CONTA VOCE OU POSSIBILIDADE DE ALCANÇAR LUCROS OU PERDAS SIMILARES ÀOS MOSTRADOS.
Desenvolvimento de sistema de negociação automatizado baseado em nuvem com aprendizado de máquina.
Este artigo é o projeto final apresentado pelos autores como parte de seus cursos em Programa Executivo em Negociação Algorítmica (EPAT) na QuantInsti.
Derek começou sua carreira no chão do CBOT, em seguida, mudou-se para se concentrar em negociação proprietária e desenvolvimento de estratégia. Ele gerencia portfólios globais de várias estratégias, focando no espaço de futuros e opções. Atualmente, é Diretor Adjunto de Negociação Sistemática da Foretrade Investment Co Ltd.
No final do Programa Executivo em Palestras de Negociação Algorítica (EPAT), Derek e eu estávamos passando uma quantidade significativa de tempo trocando pontos de vista sobre uma variedade de mídia. Nós discutimos idéias para um projeto, e os mesmos temas nos despertaram. Primeiro, estávamos interessados em lidar com futuros e não com instrumentos de caixa. Em segundo lugar, nós dois tivemos uma experiência sólida usando R para pesquisas quantitativas e interessados em deixar nossas mãos sujas no lado da execução, especialmente na implementação de estratégias orientadas a eventos em Python (que nenhum de nós sabia antes do programa EPAT) . Terceiro, passamos horas conversando e avaliando o desempenho da Aprendizagem de Máquinas para aplicações comerciais e ficamos bastante ansiosos para tentar nossas idéias. Finalmente, estávamos muito interessados em design de arquitetura prática, particularmente no que era a melhor maneira de gerenciar as necessidades de recursos variáveis de qualquer estrutura de Aprendizagem em Máquina (treinamento versus avaliação).
O escopo do nosso projeto, portanto, surgiu naturalmente: o desenvolvimento de um sistema de negociação automatizado totalmente baseado na nuvem que alavancasse algoritmos de execução simples, rápidos de reversão ou de tendência e chamasse a tecnologia de aprendizado de máquina para alternar entre estes.
Descrição do Projeto.
A classe de aprendizagem da máquina do programa EPAT apresentou o uso de uma Máquina de Vetores de Suporte e evidenciou como melhorou um pouco melhor do que um modelo GARCH na previsão de volatilidade. A literatura sugeriu que os modelos das Redes Neurais Recorrentes poderiam ser ainda melhores nas circunstâncias adequadas [1], e que os modelos de combinação ("modelagem de espessura") podem mitigar as preocupações sobre-ajustadas [2]. Isso realmente foi uma perspectiva atraente, mas o nosso uso de estruturas ML (principalmente e1071, caret e nnet para R, e o excelente scikit-learn ou o pirein mais fácil em Python) deram luz sobre um problema-chave: gerenciamento de recursos. A fase de aprendizagem da maioria dos modelos pode ser dolorosamente longa em um computador desktop de médio alcance, e o tamanho total da maioria dos conjuntos de dados absorverá uma quantidade considerável de RAM. Um PC relativamente alto, por exemplo, provavelmente faria razoavelmente bem usando otimização de GPU. No entanto, isso traria mais desafios além do custo: administrar esse sistema é uma arte em si mesma, e uma que não tivemos experiência. Além disso, a maioria das bibliotecas mencionadas acima pode ser complicada para configurar corretamente; Isso é particularmente problemático para a pesquisa de aprendizagem em máquina, pois os coeficientes dos neurônios, por exemplo, não possuem valores salientes que podem ser facilmente verificados pela sanidade. Um modelo que funciona mal tem causas potenciais suficientes para não adicionar uma camada de administração de amadores, especialmente em nossa escala.
Figura 1: Pilha de Tecnologia.
Nossa arquitetura é relativamente simples e foi projetada para viver em servidores remotos. Após a seqüência de inicialização quando os dados históricos do mercado são puxados, um processo de cronometrista desencadeia uma atualização do desvio padrão e padrão [3], juntamente com uma atualização incremental da barra de dados de minutos. A cada 5 minutos, ele ativará uma chamada da pilha de aprendizado da máquina para obter uma avaliação dos próximos 5 minutos. Os dados transmitidos do corretor são enfileirados e processados pelo manipulador para atualizar todos os principais parâmetros de negociação. Uma estratégia muito simples avalia continuamente os sinais: se a pilha de aprendizagem da máquina indicou um regime de tendências, ele observará um limite de Z-Score como uma tendência inicial, caso contrário, ele irá para um comércio de reversão média. Os sinais estão em fila onde a execução da ordem irá buscá-los e "ingenuamente" processar ordens. Praticamente, a execução executa uma ordem limite na oferta (longa) ou pergunte (curta) e aguarde um ack (as mensagens ack são inseridas em uma terceira fila quando capturadas pela API do corretor). Se um ack não for detectado dentro de um parâmetro de tempo limite, a ordem é considerada obsoleta e cancelada se for uma ordem de posição inicial ou alterada para uma ordem de mercado se for uma tomada de lucro ou uma ordem de parada. Os preenchimentos inferidos de acks são adicionados ao monitor plot. ly (traçado de fluxo externo do stream).
Figura 2: monitoramento gráfico em tempo real, com execução comercial e indicadores.
Não divulgaremos os detalhes completos do modelo de aprendizagem da máquina, mas o princípio geral é que temos dois "hemisférios" treinados separadamente para prever condições de variação ou tendência. Cada hemisfério possui três modelos diferentes com parâmetros específicos, e cada lado examina seus modelos para decidir sobre as próximas condições. No caso de ambos os lados discordarem (por exemplo, condições de "intervalo" e "tendência" detectadas), a pilha avalia os parâmetros de confiança dos modelos a serem decididos.
Figura 3: Visão geral da pilha de aprendizado de máquina.
Figura 4: Distribuição de resultados fora da amostra.
Um dos recursos muito agradáveis sobre o Azure Machine Learning Studio é que ele permite o desenvolvimento de funções personalizadas. No nosso caso, desenvolvemos uma metodologia de pesquisa simples para pesquisar ambos os "hemisférios" e, caso ocorram inconsistências, acompanhar o lado cuja confiança foi coletivamente mais alta.
R Snippet 1: dispositivo de polling simples, conectado à rede Azure Stack.
Em alguns casos raros, nenhum dos lados conclui a um sinal, caso em que não fazemos nada por 5 mn. A escolha deste 5 mn não foi totalmente arbitrária, mas sim um compromisso educado entre nossa visão sobre um ambiente de negociação "estável" (mesmo temporariamente) e os períodos definitivos definitivos do WTI [4] (o pacote wavelet foi bastante útil).
Figura 5: Vista Wavelet (espectral) dos preços WTI.
O desempenho fora da amostra foi impressionante de 74%, com a ressaltação muito importante de que nossa amostra foi limitada a 6 meses de barras de 1 minuto. O código R para contornar dados faz parte do repositório github e, essencialmente, converte uma série em indicadores "padrão" (SMA, LMA, RSI, ATR, etc.) para os 5 mn anteriores em apenas 50 pontos de dados (entrada) + 1 saída. Treinamento no framework Azure é rápido e a interface brilhante facilita a inclusão no código personalizado em python ou R. Ir do treinamento para uma API RESTful ao vivo é bem-vinda e o tempo de resposta claramente abaixo de 100ms.
R Snippet 2: função Eyeball para gerar as Figuras 6 e amp; 7.
Desenvolvimento de Estratégia de Negociação.
Determinamos três princípios orientadores que mantivemos durante o desenvolvimento de nossa estratégia. Principalmente, precisávamos de uma estratégia que dependesse significativamente e aproveitasse a arquitetura de aprendizagem de máquinas. Em segundo lugar, precisávamos da estratégia para realizar de tal forma que a análise empírica do desempenho de diferentes estados de regime nos permitisse julgar a própria estratégia de negociação, mas também ver se o aprendizado da máquina estava funcionando bem em tempo real. Finalmente, é claro, com todas as estratégias de negociação, queríamos que fosse lucrativo.
As complexidades inatas da nossa arquitetura de aprendizagem de máquinas nos levam a permanecer relativamente simplistas em nossa estratégia comercial. Isso foi essencial por várias razões, a lógica de negociação simplificada nos permitiu evitar armadilhas clássicas de desenvolvimento de estratégias. Por exemplo: sobre montagem, limitando graus de liberdade, erros de lógica de confusão e contaminação de dados. Ao executar vários tipos diferentes de treinamento e testes de volta, primeiro para a arquitetura de aprendizagem de máquinas, então o desenvolvimento da lógica de negociação em si representou duas vezes mais oportunidades para cair nas armadilhas clássicas de desenvolvimento de estratégias.
O sistema de negociação é baseado na inferência estatística frequente para nossos cálculos. Decidimos usar uma medida estatística simples, o Z-score como base de nossa estratégia. Esta é uma fórmula estatística padrão extremamente simples. A razão para isso é porque não queremos que a complexidade adicional surgisse da combinação da estrutura ML mais nosso modelo de lógica comercial.
Python Snippet 1: trecho da fórmula z-score.
Processo de disparo de entrada.
A condição da nossa entrada baseava-se simplesmente em dois fatores, principalmente o estado do regime de mercado de aprendizado de máquina e uma condição de gatilho gerado por Z.
Tabela 1: matriz lógica de condição de entrada.
Python Snippet 2: condição de gatilho da lógica de negociação.
Nosso raciocínio para o uso de lógica de gatilho simétrico simples é o seguinte. Ao manter o método mais simples e absoluto para o desencadeamento, podemos maximizar nossa dependência da aprendizagem da máquina. Se o regime de mercado for incorreto devido à natureza simplista do gatilho, a quantidade de alfa independente gerada deve ser próxima de 0 ou negativa se você incluir fricções de mercado. Isso faz com que o pressuposto de que os mercados para curtos períodos de dados de alta freqüência são um Processo de Movimento Browniano Geométrico (GBM), e. Caminhada aleatória.
Se o aprendizado da máquina pode detectar quando esse não é o caso e há alguma distribuição onde as caudas são divergentes de uma distribuição log-normal, então podemos gerar alfa. Por exemplo, temos três estados de regime: tendência, alcance e nada. Se o GBM for verdade, a série temporal deve estar em nada ou no alcance. Isso é esclarecido pela Figura 4, no entanto, mostramos que uma parcela estatisticamente significativa do tempo é gasto na área de tendências. O que mostraria que as séries temporais têm variação na kurtosis e volatilidade estocástica. Isso leva a áreas onde podemos gerar alfa a partir de estratégias de tendências devido ao excesso de curtose. No entanto, um escore Z padrão é incapaz de discernir esses diferentes regimes de séries temporais e faz a suposição de uma distribuição normal. Portanto, o gatilho de negociação pode tornar-se lucrativo se e somente se a arquitetura de aprendizagem da máquina puder discernir com precisão o estado do regime de mercado.
This strategy also includes the same type of assumptions that are present in our machine learning two hemispheres, that in different regimes we should have two types of market price distributions. One would be more leptokurtic and lead to fatter tails, marking a trend regime. The other would be a more normal or even platykurtic with comparably thinner tails, leading to a range regime.
The Z-score would assume a normal distribution which means all of the targetable activity that we are looking to take advantage is in the tails. Therefore by using a Z-score trigger we can simply do that and only have trigger points at what we judged to be extreme values, looking to take advantage of different tail conditions. Our parameter trigger point was any Z-Score between 2 and 2.5 (Z_THRESH and Z_THRESH + Z_THRESH_UP)
Our exits are extremely simple as well, given our primary goals. We use two types of exit conditions. For “range” regime mean reverting trades a Z-score higher than our Z_TARGET for longs or lower for shorts was used. We expect mean reverting activity which would be a Z-score of 0 but we have it a slightly larger range to close a position of +/-0.2 in our parameters. We also have an additional 4 tick trailing stop, this was used for both systems. However for the trending trade was the only exit condition.
Parâmetros.
Our parameter set was taken directly from the normal distribution assumption. These are controlled by a separate config file in our architecture, which makes for easy modification. We used a Z-score threshold (Z_THRESH) of 2 and limited to a 2.5 (Z_THRESH + Z_THRESH_UP). This is so we do not try to enter trades that have already diverged extremely far away. The STOP_OFFSET are in ticks for a trailing stop, and Z_TARGET is Z-score of 0.2 where we close mean reverting positions around the mean.
Python Snippet 3: Trading logic parameters.
How did the project go?
The parameters we have been using lead to a 14x-16x turn per hours (7-8 round turns). It is significant, especially if looking at the number from a nominal perspective: that is roughly 16.5MUSD nominal traded every day, on around 5KUSD of margin (the latter, however, is the only interesting parameter from on ROE perspective)
The strategy performed fairly well: 45% wins at around 1.8 ticks per contract, 29% losses at around 1.7 ticks per contract, and 26% scratch. However, the average profit, at ca. 0.32 tick per round-trip trade has to be put in perspective with the 1.42USD that IB would charge us for each trade [5]; the economics for retail traders are tough. Net, 3.2USD profit for 2.84USD brokerage and exchange fees would yield a theoretic 20%-30% monthly return on the margin posted. This might look impressive, but given the leverage involved doesn’t nearly compensate for the potential loss that could arise from unforeseen, odd market conditions (spike linked to announcements, liquidity drops) and even less so for operational risks (bug or system breakage). Besides, it is not clear we could have scaled the strategy enough to make returns worth some “true” investments without significant slippage.
On the other hand, resource costs were ridiculously low: the AWS micro instance is free for a year, and given the heavy lifting (ML) is done at azure that was enough processing power for us, and the Azure stack comes out at under 10USD/m (“seat” and then 50ct for a 1,000 API calls)
Conclusão.
With regards to trading, our three main conclusions are:
Software as a service for machine learning makes absolute sense whenever possible. Response time at 50ms-100ms is a clear limit, but the incremental investment and operational risk to go under that mark is very significant. For any longer horizon application, the technology, and Microsoft’s Azure ML Studio in particular is worth exploring. It is still possible to make money on automated trading with limited resources, even on outrights. However, exchanges/brokerage fees can quickly erode or even cancel profits. Incentive/Tiered program are of paramount importance for such strategies to be profitable. And yes, this is stating the obvious, but we now have a first-hand experience. Between the obvious research and coding part, engineering abstract concepts into actionable objects and code is probably more art than science. There is a clear premium to having actual experience (and failures) under one’s belt in that area.
Recommendations to future students/coders:
Explore libraries, and get a thorough understanding of what they can/will do . IBPY, for example, has the merit of simply existing. Documentation is almost inexistent, but it does have a very large number of wrappers calling all API functionalities. Chances are we ended up re-writing some functionalities that existed (and when we did, our implementation is very likely to be worst) “ A game of chess is like a swordfight, you must think first before you move ” – Wu-Tang Clan. This ancient wisdom definitely also applies to development, especially for when classes and concurrency are involved. Since we had no experience of such development or designing software architecture, we started by hacking through James Ma “High Frequency” project. It’s safe to say almost nothing remains from James’ excellent work in our project; working around limitations induced by the scope differences always eventually ended in blocks, and refactoring. In the end, we would have saved a lot of time thinking longer about conceptual blocks and then working toward them from the ground up (with the caveat that at the time we had no idea how to do that, and Jame’s work was a good bootstrap). Ironically, our eventual architecture looks very much like the one in Quantinsti’s System Architecture 101. Most of our R/Python at work involves sequential workflow, developed iteratively. Trading systems involve data being streamed from the exchanges, orders being pushed based on signals, acknowledgements or orders, etc. In hindsight, this, of course screams “threads” and “concurrency”, but James had (very well) managed to keep his work sequential and relying on classes alone. This did not work for us, and compounded with the aforementioned issue led to the first refactoring (unsuccessfully, since we had bet on the wrong library for the job: threading). We would very much encourage anyone looking into python for trading to dig into asyncio if one’s using python 3.5 or concurrent. Futures which is backported for 2.7 as well (we used the later). Now, multiprocessing has its own frustrating challenges: thread dying in silence, (not) thread-safe objects, etc. and is generally a very different design paradigm. On the plus side, it is incredibly gratifying when it does work Quality Assurance is probably the least sexy aspect of development. It is also the one we have, and will, invest a lot of learning/reading time in. This is not a skill that is as critical in a notebook-type environment because debugging can be performed on the go for the most part, one step at a time. Of course, when multiple threads interact with data from various sources, this is a very different situation. Writing print statements everywhere won’t cut it, and both logging and traceback are libraries very much worth investing time in. To be fair, none are particularly intuitive (nor is the Exception class use, by the way) but systematic try/except and logging points truly is a lifesaver The old “feel the pain now or feel the pain later” moniker is particularly apt when it comes to development. Using class and other less-than-intuitive taxonomy of object and process is a double-edged sword. Most classes and functions will not be straight forward to test, and attempting to test basic functionalities (proper typing of output, e. g.) in an integrated test is a recipe for disaster. We ended up using the very nice __main__ python semantic to “scaffold” individual classes with basics required to run, as a poor man’s unitest (another un-sexy library that is really critical). In the end, the time required to develop testing features is not insignificant (we assume it could have been around 20%) but it is a very good use of resource. A good example is that we did not build a market simulator. That was a decision we had made based on the limited interest we had actually trading much with IB (due in large part to contractual restrictions) and, quite frankly, on the skills we had at the beginning. This was a really bad decision from a time perspective alone: the boot sequence to register on IB is roughly 20 seconds long. Accounting for a signal to happen, this is probably 30 seconds minimum which in a 4-hours development sequence might require 20 to 30 reboots. Conservatively, 10-20 minutes of wasted time or 5%-10% or productivity loss. That is before even being able to test specific situations rather than waiting for one to happen, and there is no doubt in our mind that even biting the bullet mid-way would still have been largely beneficial (including for parameters adjustment).
Broadly speaking, this was the key takeaway: getting a project 80% done is the easy and fun part. The hard and tedious one is the last 20%, and that is also where actual skills matter (especially in quality assurance).
We gained a lot in the process and would like to thank the faculty for their help and guidance. We do not plan to maintain the public release of the program given our respective contractual limitations but plan on working together again in the near-term.
Referências.
[1] Non-Linear Time Series Models in Empirical Finance – Philip Hans Franses, Dick van Dijk; Direction-of-Change Forecasting Using a Volatility Based Recurrent Neural Network – Stelio Bekiros and Dimitris Georgoutsos.
[2] Is Combining Classifiers Better than Selecting the Best One – Saso Dzeroski and Bernard Zenko; Popular Ensemble Methods: An Empirical Study – D Opitz and R. Maclin.
[3] For the standard deviation we have used the unbiased estimator (R Almgren – Time Series Analysis and Statistical arbitrage, NUY)
[4] Wavelet Multiresolution Analysis of Financial Time Series – M. Ranta.
[5] The retail commissions would be 0.85USD brokerage plus 1.45USD for NYMEX exchange fees. However, under the Tiered volume program of both NYMEX/CME and IB, the rates would likely be 0.65USD and 0.77USD per trade, respectively.
Próximos passos.
For more such student projects, check Statistical Arbitrage Strategy using R. If you are a coder or a tech professional looking to start your own automated trading desk. Learn automated trading from live Interactive lectures by daily-practitioners. Programa Executivo em Negociação Algorítmica abrange módulos de treinamento como Statistics & amp; Econometria, Computação Financeira e Tecnologia e Algorítmica e Negociação quantitativa. Inscreva-se agora!
Posts Relacionados:
One thought on “ Development of Cloud-Based Automated Trading System with Machine Learning ”
It was very useful for me. Keep sharing such ideas in the future as well. This was actually what I was looking for, and I am glad to came here! Thanks for sharing the such information with us.
Para uma versão gratuita do Adaptrade Builder, visite a página de download do Construtor.
Operadores de variação no desenvolvimento de estratégias automatizadas.
por Michael R. Bryant.
As ferramentas para desenvolvimento automatizado da estratégia de negociação, como o Adaptrade Builder, são projetadas para criar estratégias de negociação com entrada e intervenção mínima do usuário. Em vez de o comerciante chegar a idéia de estratégia e programá-lo, o usuário fornece os requisitos gerais, e o software faz o resto. Isso levanta a questão: como um computador apresenta idéias comerciais? A resposta cabe aos chamados operadores de variação.
Se você já otimizou as entradas para uma estratégia de negociação, provavelmente você entende a idéia básica de otimização. O objetivo é simples: você deseja encontrar os valores dos parâmetros que maximizam algum objetivo, como lucro líquido ou fator de lucro. Os parâmetros para uma estratégia de negociação normalmente seriam variáveis como os comprimentos de look-back do indicador, portanto, por exemplo, seu objetivo talvez seja encontrar o comprimento de uma média móvel que maximize o lucro líquido de sua estratégia de negociação. Embora pareça ser bastante diferente, a mesma abordagem geral é usada com o desenvolvimento automatizado de estratégias. Como encontrar os valores de entrada ótimos para uma estratégia de negociação, o desenvolvimento automático de estratégias de negociação é um problema de otimização e a otimização depende de operadores de variação.
O que os operadores de variação fazem? A otimização é essencialmente uma maneira sistemática de tentar valores diferentes do objeto sendo otimizado até encontrar o valor ou os valores que maximizam a função objetivo. Por exemplo, a técnica mais simples é tentar todos os valores possíveis e gravar aquele que dá o resultado ideal. Métodos mais sofisticados, como otimização genética 1 ou otimização de enxames de partículas 2, bem como métodos tradicionais, como descida de gradiente 3 ou recozimento simulado, 4 fornecem diferentes maneiras de selecionar os valores para chegar a solução ideal mais rápido, sem ter para tentar todos os valores possíveis. O operador de variação modifica o valor atual para chegar ao próximo valor a tentar.
Numa "força bruta" otimização, em que todo o valor possível é testado, o operador de variação para encontrar o comprimento ideal da parte traseira seria simplesmente adicionar 1 ao valor atual. No método de descida mais íngreme, o operador de variação envolve a derivada parcial da função objetiva; ele adiciona uma fração da derivada parcial ao valor atual, de modo que segue a inclinação da função objetiva para o seu pico (ou por baixo, dependendo se você está minimizando ou maximizando). Em geral, os operadores de variação são o que permite que o processo de busca percorra o espaço de todas as soluções possíveis no caminho para encontrar o melhor.
Quando o objeto a ser otimizado é um conjunto de regras para uma estratégia de negociação, os operadores de variação precisam ser um pouco mais complexos. Neste caso, o espaço de todas as soluções possíveis consiste em todas as regras de negociação possíveis para a estratégia. A variação de operadores precisa ser capaz de atravessar esse espaço. Em outras palavras, eles precisam ser capazes de gerar uma infinita variedade de idéias comerciais. Os operadores de variação são os geradores de ideias do algoritmo de otimização.
Algoritmos evolutivos, como otimização genética e programação genética, geralmente usam dois tipos de operadores de variação: cruzamento e mutação. Estes são os dois tipos básicos de operadores de variação utilizados no Adaptrade Builder, bem como em outras ferramentas automatizadas de desenvolvimento de estratégias baseadas em programação genética. Este artigo irá ilustrar os operadores de variação específicos e únicos utilizados no Adaptrade Builder, bem como a forma como vários aspectos do processo evolutivo são controlados.
Crossover e Mutação em Programação Genética.
Quando a programação genética é aplicada ao desenvolvimento automatizado da estratégia de negociação, a lógica da estratégia é representada por uma ou mais estruturas de árvores. Essas árvores de regra avaliam verdadeiro ou falso, que é usado como uma condição para entrar ou sair de um comércio. O Crossover é um operador de variação que troca uma subárvore da árvore de regras de uma estratégia com uma subárvore da árvore de regras de uma estratégia diferente. Desta maneira, dois "pai" as árvores produzem dois "filhos" ou árvores descendentes, como mostrado abaixo na Fig. 1.
Figura 1. O operador de crossover no Adaptrade Builder é usado para trocar parte de uma árvore de regras com outra. As duas árvores parentes no topo são equivalentes às seguintes regras: (Momentum (DayH, 32) & lt; = DayL - C) = (FastK (100) & lt; = FastK (64)); (L [16] Cruce abaixo DayO) = (Tempo = 13:30). Depois de trocar os subárboles delineados nas caixas vermelhas, as novas árvores se tornam: (Momentum (DayH, 32) & lt; = DayL - C) = (Tempo = 13:30); (L [16] Cruce abaixo DayO) = (FastK (100) & lt; = FastK (64)).
Na figura acima, como com as figuras que se seguem, as árvores parentes são mostradas no topo da figura com as árvores menores abaixo. As partes das árvores descritas nas caixas vermelhas são modificadas entre o pai e a criança, com as partes modificadas descritas em caixas verdes nas árvores menores. No caso do crossover, as subveres nas caixas vermelhas são trocadas. As funções do indicador são abreviadas: O, H, L e C representam o aberto, alto, baixo e próximo, respectivamente; DayH e DayL são os preços altos e baixos do dia, respectivamente, nos dados intradiários; & quot; = & quot; é usado para representar o operador de igualdade (em oposição a "atribuição"). Todos os exemplos para este artigo são retirados dos resultados de compilação reais do Adaptrade Builder.
A estrutura da árvore mostra como os indicadores são combinados. Por exemplo, a árvore no canto superior esquerdo da Fig. 1 pode ser escrita como (Momentum (DayH, 32) & lt; = DayL - C) = (FastK (100) & lt; = FastK (64)). O operador de igualdade significa que essa expressão seria verdadeira se as expressões em cada lado do operador forem verdadeiras ou ambas falsas ao mesmo tempo. Uma característica-chave do crossover é que os componentes básicos (isto é, indicadores, operadores e valores de entrada) não são alterados, mas seu arranjo é modificado.
Os operadores de mutação, por outro lado, alteram os componentes básicos de uma maneira ou de outra. O operador de mutação mais simples é chamado de mutação pontual, mostrado abaixo na Figura 2. Na mutação pontual, os diferentes componentes da árvore são alterados com alguma probabilidade de mutação. Por exemplo, se a probabilidade de mutação for de 20%, há uma chance de 20% de que um componente específico seja alterado. Cada componente é considerado, por sua vez, e se a probabilidade escolhida aleatoriamente for inferior ao limite, como 20%, um novo componente compatível será escolhido para substituir o original. "Compatível" significa que o novo componente não deve alterar o número de entradas ou o tipo de retorno de qualquer função e, se for um valor, deve estar dentro do mesmo intervalo de parâmetros que o valor que está substituindo.
Figura 2. Na mutação pontual, os componentes da árvore superior nas caixas vermelhas são alterados para componentes semelhantes, mostrados na árvore inferior nas caixas verdes. Antes da mutação: (TrueRange + H & gt; AdaptVarMA (DayL, 27, 100, 1.380)) = (Dia = 5). Após a mutação: (TrueRange + H & lt; AdaptZeroLagTrend (DayO, 27, 100, 3.631)) = (Day & gt; = 5).
Na substituição de subárvore, também conhecida como mutação de subárvore, uma subárvore é substituída por uma nova subárvore gerada aleatoriamente. Por exemplo, na Fig. 3, abaixo, a subárvore mostrada na caixa vermelha é substituída pela nova mostrada na caixa verde.
Figura 3. Na substituição da subárvore, a árvore-filho é criada substituindo uma sub-árvore (mostrada na caixa vermelha) na árvore-mãe com uma nova sub-árvore gerada aleatoriamente (mostrada na caixa verde). Antes da mutação: (FastK (95) & lt; = 26) = (StdDev (H, 11) & gt; = AdaptZeroLag (TrueRange, 7, 100, 3.310)). Após a mutação: (FastK (95) & lt; = 26) = (L [11] & gt; TrueRange + DayH).
Outra maneira de mutar uma árvore de regras é torná-la mais complexa. O operador complicado executa esta função substituindo uma função por um pequeno número de entradas com uma função mais complexa que retorna o mesmo tipo de valor, como preço, diferença de preço, valor do oscilador, etc. Um exemplo é mostrado abaixo na Fig. 4 . Neste exemplo, a função de preço, O [13] (ou seja, o preço aberto 13 bares atrás) é substituída pela média móvel de 16 barras do aberto. A nova função é escolhida aleatoriamente no conjunto de todas as funções que atendem aos requisitos. O operador de mutação complicado não só retém o tipo de retorno (preço neste caso), mas o tipo de preço (ou seja, o preço aberto).
Figura 4. O operador de mutação complicada substitui a função O [13] com a função mais complexa MovAve (O, 16), que retém o tipo de retorno (preço) e o tipo de preço (aberto). Antes da mutação: O [13] Cruza acima de L. Após a mutação: MovAve (O, 16) cruza acima de L.
O oposto do operador complicado é o operador de simplificação, que substitui uma função por múltiplas entradas com uma função similar com menos entradas. A nova função é escolhida aleatoriamente do conjunto de todas as funções que retornam do mesmo tipo, mas com menos entradas. Tal como acontece com o operador complicado, o tipo de preço (se aplicável) é mantido na nova função. Por exemplo, como mostrado na Fig. 5, a função WgtMA (O, 62) (isto é, média móvel ponderada de 62 barras do aberto) é substituída pelo preço aberto.
Figura 5. O operador de mutação simplificadora substitui a função WgtMA (O, 62) com o preço simples, O. Antes da mutação: InvFisherRSI (WgtMA (O, 62), 39) & gt; 0. Após a mutação: InvFisherRSI (O, 39) & gt; 0.
Outra maneira de mutar uma estrutura de árvore é cultivá-la. O operador crescer subárvore adiciona uma nova subárvore à árvore existente. A nova subárvore é gerada aleatoriamente e adicionada à árvore existente usando uma nova função lógica, escolhida aleatoriamente de "e", "ou" ou "=". Por exemplo, na Fig. 6, a nova subárvore "Time & gt; 9: 30 " está conectado à árvore existente usando o & quot; e & quot; função. Tanto o operador complicado como o operador de crescimento de subárvore aumentam a complexidade da árvore, mas complicam isso com modificações mínimas na estrutura da árvore, enquanto o crescimento sempre adiciona uma nova subárvore.
Figura 6. O operador de crescimento da subárvore adiciona a nova sub-árvore Time & gt; 9:30 para a árvore-mãe usando o & quot; e & quot; função. Antes da mutação: DayO & lt; = ZeroLagTrend (menor (O, 40), 97). Após a mutação: (DayO & lt; = ZeroLagTrend (menor (O, 40), 97)) e (Horário & gt; 9:30).
O oposto de cultivar uma árvore é poda. O operador de ameixa de ameixa da subárvore remove uma subárvore da árvore existente. A subárvore a remover é selecionada aleatoriamente e a função lógica principal ("e", "ou" ou "quê?" É removida. Por exemplo, na Fig. 7, a sub-árvore "H [14] & lt; = DayL" é removido, juntamente com o & quot; ou? função. Tanto o operador de simplificação como o operador de ameixa da subárvore diminuem a complexidade da árvore, mas simplificá-la com modificações mínimas na estrutura da árvore, enquanto a ameixa sempre remove uma subárvore.
Figura 7. O operador de ameixa subárvore remove a subárvore H [14] & lt; = DayL da árvore-mãe, juntamente com o & quot; ou & quot; função. Antes da mutação: (H [14] & lt; = DayL) Ou (StdDev (DayO, 93) & gt; = ZeroLagTrend (TrueRange, 50)). Após a mutação: StdDev (DayO, 93) & gt; = ZeroLagTrend (TrueRange, 50).
Selecionando o Operador de Variação.
Os sete operadores de variação descritos acima (cruzamento, mutação pontual, substituição de sub-árvore, complicam, simplificam, crescem sub-árvore, ameixa sub-árvore) são a forma como o algoritmo de programação genética gera novas estratégias de negociação. No entanto, com sete formas diferentes de gerar uma nova estratégia, o algoritmo precisa saber qual operador de variação escolher. A primeira escolha é entre crossover e mutation. No Adaptrade Builder, a probabilidade de cruzamento, que é uma das configurações do usuário, determina a porcentagem de estratégias geradas por meio de cruzamento, com o restante gerado por mutação. Por exemplo, se a percentagem de crossover for de 60%, essa porcentagem de estratégias será gerada através de cruzamento com 40% gerados por mutação.
Das estratégias geradas por mutação, o operador de mutação é escolhido aleatoriamente de acordo com a probabilidade de cada operador. Essas probabilidades de mutação são auto-adaptativas. Isso significa que as probabilidades dos seis operadores de mutação são desenvolvidas juntamente com a população de estratégias de negociação. Em outras palavras, o mesmo processo evolutivo que é usado para evoluir as estratégias de negociação é usado para evoluir as probabilidades de mutação. Cada estratégia de negociação tem um conjunto de probabilidades de mutação, e cruzamento e mutação são aplicados às probabilidades de mutação durante o processo de compilação. Ao fazê-lo, as probabilidades de mutação associadas a melhores estratégias tendem a ser propagadas para a próxima geração junto com as estratégias.
Para ver como isso funciona na prática, considere a Fig. 8, abaixo. Isso mostra como as seis probabilidades de mutação, calculadas em média sobre os membros da população, mudam durante o processo de construção. Inicialmente, as seis probabilidades são inicializadas para valores aleatórios próximos de 16,67% (isto é, 100% dividido por 6). A soma das probabilidades para os seis operadores deve somar até 100%. Ao longo de gerações sucessivas, o processo evolutivo tende a favorecer certos operadores sobre outros. Na Fig. 8, o operador de simplificação tem a maior probabilidade, seguido de mutação pontual e substituição de subárvore. Na geração 600, por exemplo, a probabilidade de selecionar o operador de simplificação foi de cerca de 30%, a probabilidade de seleção de mutação pontual foi de cerca de 25%, e assim por diante (assumindo que a mutação foi escolhida por crossover).
Figura 8. As probabilidades de aplicar os seis operadores de mutação diferentes são desenvolvidas juntamente com a população como parte do processo de construção.
Para outros exemplos de compilação, as probabilidades serão diferentes. Além disso, a ordenação das probabilidades pode mudar ao longo do tempo. Por exemplo, observe que na Fig. 8, antes da geração 200, a probabilidade de mutação pontual foi maior que a do operador simplificado. Observe também que a probabilidade de poda da sub-árvore tendia para zero após um grande número de gerações. Isto é provavelmente porque a poda é ativamente aplicada como parte de um processo separado para evitar que a profundidade da árvore exceda um limite especificado. Isso é explicado mais à frente na próxima seção.
Prevenção da Profundidade Excessiva da Árvore.
Cada uma das árvores de regra ilustradas acima tem uma profundidade de árvore associada, que é definida como o número de ramificações da raiz até o final da árvore para o ramo mais longo. Por exemplo, a árvore primária na Fig. 7 tem uma profundidade de árvore de três, enquanto a árvore infantil na Fig. 6 tem uma profundidade de árvore de quatro. A profundidade da árvore é uma medida da complexidade da estratégia. Uma vez que altos níveis de complexidade podem aumentar as chances de excesso de ajuste, o Adaptrade Builder verifica a profundidade da árvore de cada estratégia e aplica o operador de poda da subárvore se a profundidade da árvore exceder a configuração do usuário.
Figura 9. Sem a poda da sub-árvore, a profundidade média da árvore tende a aumentar em relação às sucessivas gerações. Quando a poda da sub-árvore é aplicada a estratégias que excedem uma profundidade de árvore especificada, a profundidade da árvore permanece quase constante.
Ao longo de gerações sucessivas, essa abordagem tende a manter a profundidade da árvore bastante constante, como mostrado pela curva inferior na Fig. 9. Sem essa aplicação de poda de sub-árvore, a profundidade da árvore tende a aumentar, como mostra a curva superior na Fig. 9.Porque as árvores de regra se ramificam para além da profundidade, uma árvore com uma profundidade de seis pode ter mais de oito vezes mais "nós" como uma árvore com uma profundidade de três. Manter a profundidade da árvore durante o processo de construção através do operador de poda da sub-árvore é uma maneira de evitar a complexidade excessiva e a sobreposição.
O desenvolvimento automatizado da estratégia usando métodos como a programação genética pode parecer um pouco misterioso no início. Como o software vem com regras de negociação e lógica? Como as estratégias evoluem em torno de gerações sucessivas? Os operadores de variação descritos acima são uma parte fundamental desse processo. Os operadores de variação de crossover e mutação geram todas as novas estratégias de negociação depois que a população inicial de estratégias é estabelecida e permite que o algoritmo de otimização busque o espaço de possíveis estratégias de negociação em busca dos que atendem aos objetivos e requisitos do usuário.
Além do crossover, o Adaptrade Builder usa seis operadores de mutação diferentes para fornecer a máxima variação na lógica da estratégia. Se o usuário tiver que selecionar as probabilidades com as quais aplicar todos esses operadores diferentes, é improvável que o usuário possa escolher as melhores probabilidades para cada caso de compilação. Por esse motivo, o Builder seleciona as probabilidades de mutação de forma auto-adaptativa, o que significa que eles evoluíram durante o processo de compilação usando a mesma abordagem evolutiva aplicada às próprias estratégias comerciais.
Uma desvantagem potencial de empregar uma grande variedade de operadores de variação é que a complexidade das árvores de regra pode aumentar ao longo de gerações sucessivas, o que pode levar ao excesso de ajuste. Para evitar isso, o operador de poda de subárvore é aplicado a novas estratégias se suas profundidades de árvore excederem a configuração de profundidade de árvore do usuário. Isso ajuda a evitar a complexidade desenfreada enquanto ainda permite a variação. A complexidade ainda pode ser controlada de forma independente durante o processo de compilação usando a métrica de complexidade do programa, que se baseia no número de entradas de estratégia independentes. Uma vez que esta é uma medida de complexidade diferente da profundidade da árvore, é possível alcançar diferentes níveis da métrica de complexidade para o mesmo limite de profundidade da árvore.
Eiben, A. E. e Smith, J. E. Introdução à computação evolutiva, Springer-Verlag, Berlim, 2010, pp. 37-69.
Rini, D. P., Shamsuddin, S. M. e Yuhaniz, S. S. "Otimização de enxertia de partículas": técnica, sistema e desafios ", International Journal of Computer Applications, Vol. 14, No. 1, pp. 19-27, 2011.
Gill, P. E., Murray, W. e Wright, M. H. Otimização prática, Academic Press, Inc., Londres, 1981, pp. 99-105.
Michalewicz, Z. e Fogel, D. B. Como resolver: Heurística moderna, Springer-Verlag, Berlim, 2000, pp. 116-117.
Boa sorte com sua negociação.
Os exemplos apresentados neste artigo foram criados usando o Adaptrade Builder versão 2.3.1. Para uma avaliação gratuita, vá para o Adaptrade / Builder / Download. htm.
Este artigo apareceu na edição de setembro de 2017 do boletim informativo Adaptrade Software.
Se você quiser ser informado de novos desenvolvimentos, novidades e ofertas especiais do Adaptrade Software, por favor, junte-se à nossa lista de e-mail. Obrigado.
Copyright (c) 2004-2017 Adaptrade Software. Todos os direitos reservados.
Desenvolvimento de Estratégia Automatizada - produto de complemento para Ninjatrader.
(Se você já possui uma conta, inicie sessão no topo da página)
Estamos aqui para ajudar. Apenas deixe-nos saber o que você precisa. Trabalhamos extremamente para manter as coisas positivas em nossa comunidade. Não toleramos comportamento grosseiro, trolling ou vendedores publicitários em postagens. Nós acreditamos firmemente e incentivamos a partilha. O santo Graal está dentro de você, podemos ajudá-lo a encontrá-lo. Esperamos que nossos membros participem e se tornem parte da comunidade. Ajude-se ajudando os outros.
Você precisará se registrar para ver o conteúdo dos tópicos e começar a contribuir para a nossa comunidade. É grátis e simples.
Desenvolvimento de Estratégia Automatizada - produto de complemento para Ninjatrader.
Esse artigo é realmente útil. Eu gosto especialmente da parte sobre remover a estratégia de saída como um teste e usar um pequeno objetivo de lucro e parar (devem ser iguais, talvez 2 carrapatos cada). Isso lhe dará uma ótima indicação de como suas entradas estão fazendo observando o & quot;% rentável & quot; coluna do backtest. Claro que não se pode olhar para o fator de lucro e outros detalhes no relatório, pois isso é especificamente para julgar a precisão da entrada, mas nunca menos brilhante.
programação de negociação quantitativa.
Software de sistemas de negociação automatizado e discricionário e indicadores técnicos personalizados projetados para lhe dar a vantagem quantitativa com mais lucro e menos risco.
Estratégia de negociação Aero de Catalyst ESTRATÉGIA NINJATRADER BASADA EM REGRA.
Aero é uma estratégia de negociação discricionária que melhora drasticamente a clareza da ação de preços, a fim de ajudar a identificar oportunidades comerciais mais lucrativas com mais facilidade. Nenhuma obrigação de teste gratuito de 10 dias.
Programação Quantitativa & amp; Consultoria de sistemas.
Nossos serviços de programação personalizados para NinjaTrader, MetaTrader & amp; A TradeStation é capaz de desenvolver estratégias de negociação automatizadas e indicadores que são limitados apenas pela sua imaginação. Entre em contato conosco para discutir seu projeto mais recente e descobrir como podemos fornecer valor à sua operação comercial. Consultoria de sistemas algorítmicos adaptada aos Fundos Institucionais, CTA e Hedge Funds.
© 2014 Catalyst Research Group, LLC - Todos os direitos reservados.
Aviso legal do governo dos EUA - Negociação de Futuros de Mercadorias A negociação de Futuros e Opções tem grandes recompensas em potencial, mas também grande risco potencial. Você deve estar ciente dos riscos e estar disposto a aceitá-los para investir nos mercados de futuros e opções. Não troque com dinheiro que não pode perder. Isso, e todas as outras informações em nosso site, não são uma solicitação nem uma oferta para comprar ou vender futuros ou opções. Nenhuma representação está sendo feita para que qualquer conta seja ou seja susceptível de atingir lucros ou perdas semelhantes às discutidas neste site. O desempenho passado de qualquer sistema ou metodologia comercial não é necessariamente indicativo de resultados futuros.
CLÁUSULA CFTC 4.41 - RESULTADOS DE DESEMPENHO HIPOTÉTICOS OU SIMULADOS TÊM CERTAS LIMITAÇÕES. DESEJO UM REGISTRO DE DESEMPENHO REAL, OS RESULTADOS SIMULADOS NÃO REPRESENTAM A NEGOCIAÇÃO REAL. TAMBÉM, DESDE QUE OS NEGÓCIOS NÃO FORAM EXECUTADOS, OS RESULTADOS PODERÃO TER COMPRIMIDO COM COMPENSADO PARA O IMPACTO, SE QUALQUER, DE CERTOS FATORES DE MERCADO, COMO FALTA DE LIQUIDEZ. PROGRAMAS DE NEGOCIAÇÃO SIMULADOS EM GERAL SÃO TAMBÉM SUJEITOS AO FATO QUE ESTÃO DESIGNADOS COM O BENEFÍCIO DE HINDSIGHT. NENHUMA REPRESENTAÇÃO ESTÁ FAZENDO QUE QUALQUER CONTA VOCE OU POSSIBILIDADE DE ALCANÇAR LUCROS OU PERDAS SIMILARES ÀOS MOSTRADOS.
Desenvolvimento de sistema de negociação automatizado baseado em nuvem com aprendizado de máquina.
Este artigo é o projeto final apresentado pelos autores como parte de seus cursos em Programa Executivo em Negociação Algorítmica (EPAT) na QuantInsti.
Derek começou sua carreira no chão do CBOT, em seguida, mudou-se para se concentrar em negociação proprietária e desenvolvimento de estratégia. Ele gerencia portfólios globais de várias estratégias, focando no espaço de futuros e opções. Atualmente, é Diretor Adjunto de Negociação Sistemática da Foretrade Investment Co Ltd.
No final do Programa Executivo em Palestras de Negociação Algorítica (EPAT), Derek e eu estávamos passando uma quantidade significativa de tempo trocando pontos de vista sobre uma variedade de mídia. Nós discutimos idéias para um projeto, e os mesmos temas nos despertaram. Primeiro, estávamos interessados em lidar com futuros e não com instrumentos de caixa. Em segundo lugar, nós dois tivemos uma experiência sólida usando R para pesquisas quantitativas e interessados em deixar nossas mãos sujas no lado da execução, especialmente na implementação de estratégias orientadas a eventos em Python (que nenhum de nós sabia antes do programa EPAT) . Terceiro, passamos horas conversando e avaliando o desempenho da Aprendizagem de Máquinas para aplicações comerciais e ficamos bastante ansiosos para tentar nossas idéias. Finalmente, estávamos muito interessados em design de arquitetura prática, particularmente no que era a melhor maneira de gerenciar as necessidades de recursos variáveis de qualquer estrutura de Aprendizagem em Máquina (treinamento versus avaliação).
O escopo do nosso projeto, portanto, surgiu naturalmente: o desenvolvimento de um sistema de negociação automatizado totalmente baseado na nuvem que alavancasse algoritmos de execução simples, rápidos de reversão ou de tendência e chamasse a tecnologia de aprendizado de máquina para alternar entre estes.
Descrição do Projeto.
A classe de aprendizagem da máquina do programa EPAT apresentou o uso de uma Máquina de Vetores de Suporte e evidenciou como melhorou um pouco melhor do que um modelo GARCH na previsão de volatilidade. A literatura sugeriu que os modelos das Redes Neurais Recorrentes poderiam ser ainda melhores nas circunstâncias adequadas [1], e que os modelos de combinação ("modelagem de espessura") podem mitigar as preocupações sobre-ajustadas [2]. Isso realmente foi uma perspectiva atraente, mas o nosso uso de estruturas ML (principalmente e1071, caret e nnet para R, e o excelente scikit-learn ou o pirein mais fácil em Python) deram luz sobre um problema-chave: gerenciamento de recursos. A fase de aprendizagem da maioria dos modelos pode ser dolorosamente longa em um computador desktop de médio alcance, e o tamanho total da maioria dos conjuntos de dados absorverá uma quantidade considerável de RAM. Um PC relativamente alto, por exemplo, provavelmente faria razoavelmente bem usando otimização de GPU. No entanto, isso traria mais desafios além do custo: administrar esse sistema é uma arte em si mesma, e uma que não tivemos experiência. Além disso, a maioria das bibliotecas mencionadas acima pode ser complicada para configurar corretamente; Isso é particularmente problemático para a pesquisa de aprendizagem em máquina, pois os coeficientes dos neurônios, por exemplo, não possuem valores salientes que podem ser facilmente verificados pela sanidade. Um modelo que funciona mal tem causas potenciais suficientes para não adicionar uma camada de administração de amadores, especialmente em nossa escala.
Figura 1: Pilha de Tecnologia.
Nossa arquitetura é relativamente simples e foi projetada para viver em servidores remotos. Após a seqüência de inicialização quando os dados históricos do mercado são puxados, um processo de cronometrista desencadeia uma atualização do desvio padrão e padrão [3], juntamente com uma atualização incremental da barra de dados de minutos. A cada 5 minutos, ele ativará uma chamada da pilha de aprendizado da máquina para obter uma avaliação dos próximos 5 minutos. Os dados transmitidos do corretor são enfileirados e processados pelo manipulador para atualizar todos os principais parâmetros de negociação. Uma estratégia muito simples avalia continuamente os sinais: se a pilha de aprendizagem da máquina indicou um regime de tendências, ele observará um limite de Z-Score como uma tendência inicial, caso contrário, ele irá para um comércio de reversão média. Os sinais estão em fila onde a execução da ordem irá buscá-los e "ingenuamente" processar ordens. Praticamente, a execução executa uma ordem limite na oferta (longa) ou pergunte (curta) e aguarde um ack (as mensagens ack são inseridas em uma terceira fila quando capturadas pela API do corretor). Se um ack não for detectado dentro de um parâmetro de tempo limite, a ordem é considerada obsoleta e cancelada se for uma ordem de posição inicial ou alterada para uma ordem de mercado se for uma tomada de lucro ou uma ordem de parada. Os preenchimentos inferidos de acks são adicionados ao monitor plot. ly (traçado de fluxo externo do stream).
Figura 2: monitoramento gráfico em tempo real, com execução comercial e indicadores.
Não divulgaremos os detalhes completos do modelo de aprendizagem da máquina, mas o princípio geral é que temos dois "hemisférios" treinados separadamente para prever condições de variação ou tendência. Cada hemisfério possui três modelos diferentes com parâmetros específicos, e cada lado examina seus modelos para decidir sobre as próximas condições. No caso de ambos os lados discordarem (por exemplo, condições de "intervalo" e "tendência" detectadas), a pilha avalia os parâmetros de confiança dos modelos a serem decididos.
Figura 3: Visão geral da pilha de aprendizado de máquina.
Figura 4: Distribuição de resultados fora da amostra.
Um dos recursos muito agradáveis sobre o Azure Machine Learning Studio é que ele permite o desenvolvimento de funções personalizadas. No nosso caso, desenvolvemos uma metodologia de pesquisa simples para pesquisar ambos os "hemisférios" e, caso ocorram inconsistências, acompanhar o lado cuja confiança foi coletivamente mais alta.
R Snippet 1: dispositivo de polling simples, conectado à rede Azure Stack.
Em alguns casos raros, nenhum dos lados conclui a um sinal, caso em que não fazemos nada por 5 mn. A escolha deste 5 mn não foi totalmente arbitrária, mas sim um compromisso educado entre nossa visão sobre um ambiente de negociação "estável" (mesmo temporariamente) e os períodos definitivos definitivos do WTI [4] (o pacote wavelet foi bastante útil).
Figura 5: Vista Wavelet (espectral) dos preços WTI.
O desempenho fora da amostra foi impressionante de 74%, com a ressaltação muito importante de que nossa amostra foi limitada a 6 meses de barras de 1 minuto. O código R para contornar dados faz parte do repositório github e, essencialmente, converte uma série em indicadores "padrão" (SMA, LMA, RSI, ATR, etc.) para os 5 mn anteriores em apenas 50 pontos de dados (entrada) + 1 saída. Treinamento no framework Azure é rápido e a interface brilhante facilita a inclusão no código personalizado em python ou R. Ir do treinamento para uma API RESTful ao vivo é bem-vinda e o tempo de resposta claramente abaixo de 100ms.
R Snippet 2: função Eyeball para gerar as Figuras 6 e amp; 7.
Desenvolvimento de Estratégia de Negociação.
Determinamos três princípios orientadores que mantivemos durante o desenvolvimento de nossa estratégia. Principalmente, precisávamos de uma estratégia que dependesse significativamente e aproveitasse a arquitetura de aprendizagem de máquinas. Em segundo lugar, precisávamos da estratégia para realizar de tal forma que a análise empírica do desempenho de diferentes estados de regime nos permitisse julgar a própria estratégia de negociação, mas também ver se o aprendizado da máquina estava funcionando bem em tempo real. Finalmente, é claro, com todas as estratégias de negociação, queríamos que fosse lucrativo.
As complexidades inatas da nossa arquitetura de aprendizagem de máquinas nos levam a permanecer relativamente simplistas em nossa estratégia comercial. Isso foi essencial por várias razões, a lógica de negociação simplificada nos permitiu evitar armadilhas clássicas de desenvolvimento de estratégias. Por exemplo: sobre montagem, limitando graus de liberdade, erros de lógica de confusão e contaminação de dados. Ao executar vários tipos diferentes de treinamento e testes de volta, primeiro para a arquitetura de aprendizagem de máquinas, então o desenvolvimento da lógica de negociação em si representou duas vezes mais oportunidades para cair nas armadilhas clássicas de desenvolvimento de estratégias.
O sistema de negociação é baseado na inferência estatística frequente para nossos cálculos. Decidimos usar uma medida estatística simples, o Z-score como base de nossa estratégia. Esta é uma fórmula estatística padrão extremamente simples. A razão para isso é porque não queremos que a complexidade adicional surgisse da combinação da estrutura ML mais nosso modelo de lógica comercial.
Python Snippet 1: trecho da fórmula z-score.
Processo de disparo de entrada.
A condição da nossa entrada baseava-se simplesmente em dois fatores, principalmente o estado do regime de mercado de aprendizado de máquina e uma condição de gatilho gerado por Z.
Tabela 1: matriz lógica de condição de entrada.
Python Snippet 2: condição de gatilho da lógica de negociação.
Nosso raciocínio para o uso de lógica de gatilho simétrico simples é o seguinte. Ao manter o método mais simples e absoluto para o desencadeamento, podemos maximizar nossa dependência da aprendizagem da máquina. Se o regime de mercado for incorreto devido à natureza simplista do gatilho, a quantidade de alfa independente gerada deve ser próxima de 0 ou negativa se você incluir fricções de mercado. Isso faz com que o pressuposto de que os mercados para curtos períodos de dados de alta freqüência são um Processo de Movimento Browniano Geométrico (GBM), e. Caminhada aleatória.
Se o aprendizado da máquina pode detectar quando esse não é o caso e há alguma distribuição onde as caudas são divergentes de uma distribuição log-normal, então podemos gerar alfa. Por exemplo, temos três estados de regime: tendência, alcance e nada. Se o GBM for verdade, a série temporal deve estar em nada ou no alcance. Isso é esclarecido pela Figura 4, no entanto, mostramos que uma parcela estatisticamente significativa do tempo é gasto na área de tendências. O que mostraria que as séries temporais têm variação na kurtosis e volatilidade estocástica. Isso leva a áreas onde podemos gerar alfa a partir de estratégias de tendências devido ao excesso de curtose. No entanto, um escore Z padrão é incapaz de discernir esses diferentes regimes de séries temporais e faz a suposição de uma distribuição normal. Portanto, o gatilho de negociação pode tornar-se lucrativo se e somente se a arquitetura de aprendizagem da máquina puder discernir com precisão o estado do regime de mercado.
This strategy also includes the same type of assumptions that are present in our machine learning two hemispheres, that in different regimes we should have two types of market price distributions. One would be more leptokurtic and lead to fatter tails, marking a trend regime. The other would be a more normal or even platykurtic with comparably thinner tails, leading to a range regime.
The Z-score would assume a normal distribution which means all of the targetable activity that we are looking to take advantage is in the tails. Therefore by using a Z-score trigger we can simply do that and only have trigger points at what we judged to be extreme values, looking to take advantage of different tail conditions. Our parameter trigger point was any Z-Score between 2 and 2.5 (Z_THRESH and Z_THRESH + Z_THRESH_UP)
Our exits are extremely simple as well, given our primary goals. We use two types of exit conditions. For “range” regime mean reverting trades a Z-score higher than our Z_TARGET for longs or lower for shorts was used. We expect mean reverting activity which would be a Z-score of 0 but we have it a slightly larger range to close a position of +/-0.2 in our parameters. We also have an additional 4 tick trailing stop, this was used for both systems. However for the trending trade was the only exit condition.
Parâmetros.
Our parameter set was taken directly from the normal distribution assumption. These are controlled by a separate config file in our architecture, which makes for easy modification. We used a Z-score threshold (Z_THRESH) of 2 and limited to a 2.5 (Z_THRESH + Z_THRESH_UP). This is so we do not try to enter trades that have already diverged extremely far away. The STOP_OFFSET are in ticks for a trailing stop, and Z_TARGET is Z-score of 0.2 where we close mean reverting positions around the mean.
Python Snippet 3: Trading logic parameters.
How did the project go?
The parameters we have been using lead to a 14x-16x turn per hours (7-8 round turns). It is significant, especially if looking at the number from a nominal perspective: that is roughly 16.5MUSD nominal traded every day, on around 5KUSD of margin (the latter, however, is the only interesting parameter from on ROE perspective)
The strategy performed fairly well: 45% wins at around 1.8 ticks per contract, 29% losses at around 1.7 ticks per contract, and 26% scratch. However, the average profit, at ca. 0.32 tick per round-trip trade has to be put in perspective with the 1.42USD that IB would charge us for each trade [5]; the economics for retail traders are tough. Net, 3.2USD profit for 2.84USD brokerage and exchange fees would yield a theoretic 20%-30% monthly return on the margin posted. This might look impressive, but given the leverage involved doesn’t nearly compensate for the potential loss that could arise from unforeseen, odd market conditions (spike linked to announcements, liquidity drops) and even less so for operational risks (bug or system breakage). Besides, it is not clear we could have scaled the strategy enough to make returns worth some “true” investments without significant slippage.
On the other hand, resource costs were ridiculously low: the AWS micro instance is free for a year, and given the heavy lifting (ML) is done at azure that was enough processing power for us, and the Azure stack comes out at under 10USD/m (“seat” and then 50ct for a 1,000 API calls)
Conclusão.
With regards to trading, our three main conclusions are:
Software as a service for machine learning makes absolute sense whenever possible. Response time at 50ms-100ms is a clear limit, but the incremental investment and operational risk to go under that mark is very significant. For any longer horizon application, the technology, and Microsoft’s Azure ML Studio in particular is worth exploring. It is still possible to make money on automated trading with limited resources, even on outrights. However, exchanges/brokerage fees can quickly erode or even cancel profits. Incentive/Tiered program are of paramount importance for such strategies to be profitable. And yes, this is stating the obvious, but we now have a first-hand experience. Between the obvious research and coding part, engineering abstract concepts into actionable objects and code is probably more art than science. There is a clear premium to having actual experience (and failures) under one’s belt in that area.
Recommendations to future students/coders:
Explore libraries, and get a thorough understanding of what they can/will do . IBPY, for example, has the merit of simply existing. Documentation is almost inexistent, but it does have a very large number of wrappers calling all API functionalities. Chances are we ended up re-writing some functionalities that existed (and when we did, our implementation is very likely to be worst) “ A game of chess is like a swordfight, you must think first before you move ” – Wu-Tang Clan. This ancient wisdom definitely also applies to development, especially for when classes and concurrency are involved. Since we had no experience of such development or designing software architecture, we started by hacking through James Ma “High Frequency” project. It’s safe to say almost nothing remains from James’ excellent work in our project; working around limitations induced by the scope differences always eventually ended in blocks, and refactoring. In the end, we would have saved a lot of time thinking longer about conceptual blocks and then working toward them from the ground up (with the caveat that at the time we had no idea how to do that, and Jame’s work was a good bootstrap). Ironically, our eventual architecture looks very much like the one in Quantinsti’s System Architecture 101. Most of our R/Python at work involves sequential workflow, developed iteratively. Trading systems involve data being streamed from the exchanges, orders being pushed based on signals, acknowledgements or orders, etc. In hindsight, this, of course screams “threads” and “concurrency”, but James had (very well) managed to keep his work sequential and relying on classes alone. This did not work for us, and compounded with the aforementioned issue led to the first refactoring (unsuccessfully, since we had bet on the wrong library for the job: threading). We would very much encourage anyone looking into python for trading to dig into asyncio if one’s using python 3.5 or concurrent. Futures which is backported for 2.7 as well (we used the later). Now, multiprocessing has its own frustrating challenges: thread dying in silence, (not) thread-safe objects, etc. and is generally a very different design paradigm. On the plus side, it is incredibly gratifying when it does work Quality Assurance is probably the least sexy aspect of development. It is also the one we have, and will, invest a lot of learning/reading time in. This is not a skill that is as critical in a notebook-type environment because debugging can be performed on the go for the most part, one step at a time. Of course, when multiple threads interact with data from various sources, this is a very different situation. Writing print statements everywhere won’t cut it, and both logging and traceback are libraries very much worth investing time in. To be fair, none are particularly intuitive (nor is the Exception class use, by the way) but systematic try/except and logging points truly is a lifesaver The old “feel the pain now or feel the pain later” moniker is particularly apt when it comes to development. Using class and other less-than-intuitive taxonomy of object and process is a double-edged sword. Most classes and functions will not be straight forward to test, and attempting to test basic functionalities (proper typing of output, e. g.) in an integrated test is a recipe for disaster. We ended up using the very nice __main__ python semantic to “scaffold” individual classes with basics required to run, as a poor man’s unitest (another un-sexy library that is really critical). In the end, the time required to develop testing features is not insignificant (we assume it could have been around 20%) but it is a very good use of resource. A good example is that we did not build a market simulator. That was a decision we had made based on the limited interest we had actually trading much with IB (due in large part to contractual restrictions) and, quite frankly, on the skills we had at the beginning. This was a really bad decision from a time perspective alone: the boot sequence to register on IB is roughly 20 seconds long. Accounting for a signal to happen, this is probably 30 seconds minimum which in a 4-hours development sequence might require 20 to 30 reboots. Conservatively, 10-20 minutes of wasted time or 5%-10% or productivity loss. That is before even being able to test specific situations rather than waiting for one to happen, and there is no doubt in our mind that even biting the bullet mid-way would still have been largely beneficial (including for parameters adjustment).
Broadly speaking, this was the key takeaway: getting a project 80% done is the easy and fun part. The hard and tedious one is the last 20%, and that is also where actual skills matter (especially in quality assurance).
We gained a lot in the process and would like to thank the faculty for their help and guidance. We do not plan to maintain the public release of the program given our respective contractual limitations but plan on working together again in the near-term.
Referências.
[1] Non-Linear Time Series Models in Empirical Finance – Philip Hans Franses, Dick van Dijk; Direction-of-Change Forecasting Using a Volatility Based Recurrent Neural Network – Stelio Bekiros and Dimitris Georgoutsos.
[2] Is Combining Classifiers Better than Selecting the Best One – Saso Dzeroski and Bernard Zenko; Popular Ensemble Methods: An Empirical Study – D Opitz and R. Maclin.
[3] For the standard deviation we have used the unbiased estimator (R Almgren – Time Series Analysis and Statistical arbitrage, NUY)
[4] Wavelet Multiresolution Analysis of Financial Time Series – M. Ranta.
[5] The retail commissions would be 0.85USD brokerage plus 1.45USD for NYMEX exchange fees. However, under the Tiered volume program of both NYMEX/CME and IB, the rates would likely be 0.65USD and 0.77USD per trade, respectively.
Próximos passos.
For more such student projects, check Statistical Arbitrage Strategy using R. If you are a coder or a tech professional looking to start your own automated trading desk. Learn automated trading from live Interactive lectures by daily-practitioners. Programa Executivo em Negociação Algorítmica abrange módulos de treinamento como Statistics & amp; Econometria, Computação Financeira e Tecnologia e Algorítmica e Negociação quantitativa. Inscreva-se agora!
Posts Relacionados:
One thought on “ Development of Cloud-Based Automated Trading System with Machine Learning ”
It was very useful for me. Keep sharing such ideas in the future as well. This was actually what I was looking for, and I am glad to came here! Thanks for sharing the such information with us.
Comments
Post a Comment