Este post irá detalhar o que eu fiz para fazer aprox. 500k de negociação de alta freqüência de 2009 a 2010. Desde que eu estava negociando completamente independente e não estou mais executando o meu programa eu estou feliz em dizer tudo. Minha negociação foi principalmente em Russel 2000 e DAX futuros contratos. A chave para o meu sucesso, creio eu, não estava em uma equação financeira sofisticada, mas sim no design de algoritmos globais que uniram muitos componentes simples e usaram aprendizado de máquina para otimizar para obter a máxima rentabilidade. Você ganhou ll ser levado para o meu projeto atual: CourseTalk, um site de revisão para MOOCs) Primeiro, eu só quero demonstrar que o meu sucesso não foi simplesmente o resultado da sorte. Meu programa fez 1000-4000 comércios por dia (metade de comprimento, meio curto) e nunca entrou em posições de mais de alguns contratos de cada vez. Isto significou a sorte aleatória de qualquer um comércio particular média fora bastante rápido. O resultado foi que eu nunca perdi mais do que 2000 em um dia e nunca tive um mês perdedor: (EDIT Estes números são depois de pagar comissões) E aqui está um gráfico para lhe dar uma noção da variação diária. Observe que isso exclui os últimos 7 meses porque - como os números pararam de subir - eu perdi a minha motivação para entrar neles. Meu fundo de negociação Antes de configurar o meu programa de negociação automatizado eu fazer um bom dinheiro. Eu só posso descrever o que eu estava fazendo como semelhante a jogar um jogo de vídeo / jogo com uma borda suposto. Ser bem sucedido significava ser rápido, ser disciplinado e ter uma boa capacidade de reconhecimento intuitivo de padrões. Eu era capaz de fazer cerca de 250k, pagar meus empréstimos estudantis e ter dinheiro sobrando. Win Durante os próximos cinco anos eu iria lançar duas startups, pegando algumas habilidades de programação ao longo do caminho. Não seria até o final de 2008 que eu voltaria à negociação. Com o dinheiro correndo baixo da venda da minha primeira inicialização, o comércio ofereceu esperanças de algum dinheiro rápido, enquanto eu descobri o meu próximo movimento. Em 2008, eu estava querendo alguns hotkeys de entrada de pedidos personalizados, então depois de descobrir T4 tinha uma API, eu assumi o desafio de aprender C (a linguagem de programação necessária para usar a API) e fui em frente e construí algumas teclas de atalho. Depois de ficar com os pés molhados com o API eu logo tinha maiores aspirações: Eu queria ensinar o computador para o comércio para mim. A API forneceu um fluxo de dados de mercado e uma maneira fácil de enviar ordens para a troca - tudo que eu tinha que fazer era criar a lógica no meio. Abaixo está uma captura de tela de uma janela de negociação T4. O que foi legal é que quando eu tenho o meu programa de trabalho, eu era capaz de assistir o comércio de computadores nesta mesma interface. Assistindo ordens reais popping dentro e fora (por si com o meu dinheiro real) foi emocionante e assustador. O projeto do meu algoritmo Desde o início meu objetivo era configurar um sistema de tal forma que eu poderia ser razoavelmente confiante de que eu ganhar dinheiro antes de fazer qualquer comércios ao vivo. Para conseguir isso, eu precisava construir uma estrutura de simulação de negociação que - com a maior precisão possível - simulasse a negociação ao vivo. Enquanto a negociação no modo ao vivo exigia o processamento de atualizações do mercado transmitidas através da API, o modo de simulação exigia a leitura de atualizações do mercado a partir de um arquivo de dados. Para coletar esses dados, eu configurei a primeira versão do meu programa para simplesmente conectar-se à API e registrar atualizações de mercado com timestamps. Eu acabei usando 4 semanas de dados de mercado recentes para treinar e testar meu sistema. Com um quadro básico no lugar eu ainda tinha a tarefa de descobrir como fazer um sistema comercial rentável. Como se vê, meu algoritmo se dividiria em dois componentes distintos, que explorarei por sua vez: Prever movimentos de preços e fazer negócios rentáveis Prever movimentos de preços Talvez um componente óbvio de qualquer sistema de negociação seja ser capaz de prever onde os preços se moverão. E a minha não foi exceção. Eu defini o preço atual como a média do lance interior e dentro da oferta e eu definir o objetivo de prever onde o preço seria nos próximos 10 segundos. Meu algoritmo precisaria chegar a essa previsão momento a momento durante todo o dia de negociação. Criando indicadores de otimização Eu criei um punhado de indicadores que provaram ter uma significativa capacidade de prever os movimentos de preços de curto prazo. Cada indicador produziu um número que era positivo ou negativo. Um indicador foi útil se mais frequentemente do que não um número positivo correspondeu com o mercado subindo e um número negativo correspondeu com o mercado vai para baixo. Meu sistema permitiu que eu rapidamente determinar o quanto a capacidade de previsão de qualquer indicador tinha assim que eu era capaz de experimentar com um monte de diferentes indicadores para ver o que funcionou. Muitos dos indicadores tinham variáveis nas fórmulas que as produziram e pude encontrar os valores ótimos para essas variáveis, fazendo comparações lado a lado dos resultados obtidos com valores variáveis. Os indicadores que foram mais úteis foram todos relativamente simples e foram baseados em eventos recentes no mercado que eu estava negociando, bem como os mercados de títulos correlacionados. Fazer previsões exatas de movimento de preços Tendo indicadores que simplesmente previam um movimento de preços para cima ou para baixo não era suficiente. Eu precisava saber exatamente quanto movimento de preço foi previsto por cada possível valor de cada indicador. Eu precisava de uma fórmula que iria converter um valor indicador para uma previsão de preços. Para conseguir isso, eu segui os movimentos de preço previsto em 50 baldes que dependiam do intervalo em que o valor do indicador caiu. Isso produziu previsões únicas para cada balde que eu era capaz de representar no Excel. Como você pode ver a mudança esperada do preço aumenta enquanto o valor do indicador aumenta. Com base em um gráfico como este, eu era capaz de fazer uma fórmula para ajustar a curva. No começo eu fiz isso manualmente, mas logo escrevi algum código para automatizar esse processo. Note que nem todas as curvas indicadoras tinham a mesma forma. Observe também que os baldes foram logaritmicamente distribuídos de modo a espalhar os pontos de dados uniformemente. Por último, note que os valores dos indicadores negativos (e as respectivas previsões de preços descendentes correspondentes) foram invertidos e combinados com os valores positivos. (Meu algoritmo tratado acima e abaixo exatamente o mesmo.) Combinando indicadores para uma única previsão Uma coisa importante a considerar era que cada indicador não era inteiramente independente. Eu não poderia mudar um efeito que as previsões de outro. A fim de todos os indicadores, ao mesmo tempo eu configurar o otimizador para passo apenas 30 do caminho para as novas curvas de previsão com cada passagem. Com este salto de 30, descobri que as curvas de previsão se estabilizariam em poucas passagens. Com cada indicador agora dando-nos a sua previsão de preços adicionais eu poderia simplesmente adicioná-los para produzir uma única previsão de onde o mercado seria em 10 segundos. Por que prever os preços não é suficiente Você pode pensar que com essa vantagem no mercado eu era dourado. Mas você precisa ter em mente que o mercado é composto de lances e ofertas - não é tão fácil. Os seguintes fatores tornam a criação de um sistema rentável difícil: com cada comércio eu tive que pagar comissões tanto para o meu corretor ea troca. A propagação (diferença entre a oferta mais alta ea oferta mais baixa) significava que se eu fosse simplesmente comprar e vender aleatoriamente eu estaria perdendo uma tonelada de dinheiro. A maior parte do volume de mercado era outros bots que só executariam um comércio comigo se eles achassem que tinham alguma vantagem estatística. Vendo uma oferta não garantia que eu poderia comprá-lo. Até o momento a minha ordem de compra chegou à troca era muito possível que essa oferta teria sido cancelada. Como um pequeno jogador de mercado não havia nenhuma maneira que eu poderia competir em velocidade sozinho. Construindo uma simulação de negociação completa Então eu tinha uma estrutura que me permitiu backtest e otimizar indicadores. Mas eu tinha que ir além disso - eu precisava de uma estrutura que me permitiria backtest e otimizar um sistema de comércio completo onde eu estava enviando ordens e ficando em posições. Neste caso I L por comércio. Isso seria mais complicado e de alguma forma impossível de modelar exatamente, mas eu fiz o melhor que pude. Aqui estão alguns dos problemas que eu tive que lidar com: Quando uma ordem foi enviada para o mercado em simulação eu tive que modelar o tempo de latência. O fato de meu sistema ter visto uma oferta não significava que poderia comprá-la imediatamente. O sistema enviaria a ordem, aguardaria aproximadamente 20 milissegundos e então somente se a oferta era ainda lá foi considerado como um comércio executado. Isto era inexato porque o tempo real do lag era inconsistent e unreported. Quando eu coloquei ofertas ou ofertas que eu tive que olhar para o fluxo de execução de comércio (fornecido pela API) e usá-los para avaliar quando a minha ordem teriam sido executados contra. Para fazer isso, eu tinha que controlar a posição da minha encomenda na fila. (It t fazer isso perfeitamente, mas fiz uma melhor aproximação. Para refinar a minha simulação de execução de ordem o que eu fiz foi pegue os meus arquivos de log de negociação ao vivo através da API e compará-los aos arquivos de log produzidos pela negociação simulada do mesmo período de tempo exato. Eu era capaz de obter a minha simulação para o ponto que era bastante preciso e para as peças que eram impossíveis de modelo exatamente eu fiz certo para, pelo menos, produzir resultados que foram estatisticamente semelhantes (nas métricas que eu pensei que eram importantes). Com um modelo de simulação de ordem no lugar eu poderia agora enviar ordens no modo de simulação e ver um P L. Simulado. Mas como meu sistema saberia quando e onde comprar e vender? As predições de movimento de preço foram um ponto de partida, mas não toda a história. Eu fiz foi criar um sistema de pontuação para cada um dos 5 níveis de preços sobre a oferta e oferta. Estes incluem um nível acima do lance interior (para uma ordem de compra) e um nível abaixo da oferta interna (para uma ordem de venda).Se a pontuação A qualquer nível de preço determinado estava acima de um certo limite que significaria que meu sistema deveria ter uma oferta / oferta ativa lá - abaixo do limite, então quaisquer ordens ativas deveriam ser canceladas. Com base nisso, não era incomum que meu sistema pudesse mostrar um lance no mercado e imediatamente cancelá-lo. (Embora eu tentei minimizar isso como é chato para qualquer um olhando para a tela com olhos humanos - incluindo-me.) Os níveis de preços foram calculados com base nos seguintes fatores: A previsão de movimento de preço (que discutimos anteriormente). O nível de preços em questão. (Níveis internos significaram maiores previsões de movimento de preço eram necessários.) O número de contratos na frente da minha ordem na fila. (Menos foi melhor.) O número de contratos por trás da minha ordem na fila. (Mais era melhor.) Essencialmente, esses fatores serviram para identificar lugares de oferta / oferta. A previsão de movimento de preços por si só não era adequada porque não contava o fato de que ao colocar uma oferta eu não era preenchido automaticamente - só fiquei preenchido se alguém me vendesse lá. A realidade era que o mero fato de alguém vender a mim a um certo preço mudou as probabilidades estatísticas do comércio. As variáveis utilizadas nesta etapa foram todas sujeitas a otimização. Isso foi feito da mesma maneira que eu otimizado variáveis nos indicadores de movimento de preços, exceto neste caso eu estava otimizando para linha de fundo P L. O que meu programa ignorado Quando o comércio como seres humanos que muitas vezes têm poderosas emoções e preconceitos que podem levar a menos Melhores decisões. Claramente eu não queria codificar esses preconceitos. Aqui estão alguns fatores que meu sistema ignorou: O preço que uma posição foi inserida - Em um escritório de negociação é o mesmo conceito de ignorar custos irrecuperáveis. Indo curto vs saindo de uma posição longa - tipicamente um comerciante teria diferentes critérios que determina onde vender uma posição longa versus onde ir curto. No entanto, da minha perspectiva de algoritmos, não havia razão para fazer uma distinção. Se o meu algoritmo esperava um movimento para baixo vender era uma boa idéia, independentemente de se ele era atualmente longo, curto ou plano. A re enganado em pensar que você está fazendo bem, porque a maioria de seus comércios serão vencedores. O problema é quando você perde você perde grande. O outro efeito é que torna difícil julgar se você realmente tem uma vantagem no mercado ou estão apenas ficando com sorte. Ser capaz de monitorar e confirmar que o meu programa de fato teve uma vantagem foi um objetivo importante. Desde que meu algoritmo tomou decisões da mesma maneira, independentemente de onde ele entrou em um comércio ou se ele estava atualmente longo ou curto que ocasionalmente sentar em (e tomar) algumas grandes operações perdedoras (além de algumas grandes tradições vencedoras). Mas, você não deve qualquer gestão de risco. Para gerenciar o risco eu reforcei um tamanho de posição máximo de 2 contratos de cada vez, ocasionalmente batido em dias de alto volume. Eu também tinha um limite máximo de perda diária para proteger contra quaisquer condições de mercado inesperadas ou um bug no meu software. Estes limites foram aplicados no meu código, mas também no back-end através do meu corretor. Como aconteceu eu nunca encontrei problemas significativos. Executando o algoritmo Desde o momento em que eu comecei a trabalhar no meu programa que me levou cerca de 6 meses antes que eu tenho que até o ponto de rentabilidade e começou a executá-lo ao vivo. Embora para ser justo uma quantidade significativa de tempo foi aprender uma nova linguagem de programação. Como eu trabalhei para melhorar o programa eu vi aumento de lucros para cada um dos próximos quatro meses. Cada semana eu retrain meu sistema baseado no valor de 4 semanas precedente dos dados. Eu encontrei este golpeou o contrapeso direito entre capturar recentes tendências behavioral do mercado e segurar meu algoritmo teve bastante dados para estabelecer testes padrões significativos. Como o treinamento começou a tomar mais e mais tempo que eu dividi-lo para que ele poderia ser realizado por 8 máquinas virtuais usando amazon EC2. Os resultados foram então coalesced na minha máquina local. O ponto alto da minha negociação foi outubro de 2009, quando eu fiz quase 100k. Depois disso, continuei a passar os próximos quatro meses tentando melhorar o meu programa apesar do lucro diminuído a cada mês. Infelizmente por este ponto eu acho que eu d implementado todas as minhas melhores idéias porque nada que eu tentei parecia ajudar muito. Com a frustração de não ser capaz de fazer melhorias e não ter um senso de crescimento eu comecei a pensar em uma nova direção. Eu enviei um email a 6 empresas de negociação de alta freqüência diferentes para ver se eles estariam interessados em comprar meu software e contratar-me para trabalhar para eles. Ninguém respondeu. Eu tinha algumas novas idéias de inicialização que eu queria trabalhar, então eu nunca segui. UPDATE - Eu postei isso em Hacker News e ele tem obtido muita atenção. Eu só quero dizer que eu não defendo ninguém tentando fazer algo parecido agora. Você precisaria de uma equipe de pessoas realmente inteligentes com uma gama de experiências para ter qualquer esperança de competir. Mesmo quando eu estava fazendo isso eu acredito que era muito raro para os indivíduos para alcançar o sucesso (embora eu tinha ouvido falar de outros.) Há um comentário no topo da página que menciona estatísticas manipuladas e refere-se a mim como alguns comentários interessantes: News. ycombinator / item id 4748624 UPDATE 2 - Eu recebi de comerciantes sobre este post. Esta parte do tutorial sobre o uso do algoritmo NEAT explica como os genomas são atravessados de forma significativa mantendo sua informação topológica e como a especiação (genomas do grupo em espécies) pode ser usado para proteger genomas fracos com novas informações topológicas de ser prematuramente erradicada do gene Antes que seu espaço de peso possa ser otimizado. A primeira parte deste tutorial pode ser encontrada aqui. Rastreando História de Gene através de Números de Inovação A Parte 1 mostrou duas mutações, link mutate e mutate de nó que ambos adicionaram novos genes ao genoma. Cada vez que um novo gene é criado (através de uma inovação topológica) um número de inovação global é incrementado e atribuído a esse gene. O número de inovação global está rastreando a origem histórica de cada gene. Se dois genes têm o mesmo número de inovação, então eles devem representar a mesma topologia (embora os pesos possam ser diferentes). Isto é explorado durante o crossover do gene. Genoma Crossover (Acoplamento) Genomas crossover leva dois genomas pai (permite chamá-los A e B) e cria um novo genoma (vamos chamá-lo a criança), tendo os genes mais fortes de A e B copiando quaisquer estruturas topológicas ao longo do caminho. Durante o crossover genes de ambos os genomas são alinhados usando o seu número de inovação. Para cada número de inovação, o gene do pai mais adequado é seleccionado e inserido no genoma infantil. Se ambos os genomas pai são a mesma aptidão, então o gene é selecionado aleatoriamente de qualquer dos pais com igual probabilidade. Se o número de inovação está presente somente em um dos progenitores, então isso é conhecido como um gene disjunto ou em excesso e representa uma inovação topológica, ela também é inserida na criança. A imagem abaixo mostra o processo de crossover para dois genomas da mesma aptidão. A especiação toma todos os genomas num dado conjunto de genomas e tenta dividi-los em grupos distintos conhecidos como espécies. Os genomas em cada espécie terão características semelhantes. Uma forma de medir a similaridade entre dois genomas é necessária, se dois genomas são genes em excesso (representando diferenças topológicas) e a diferença de pesos entre genes correspondentes. Se a soma ponderada estiver abaixo de algum limiar então os genomas são da mesma espécie. A vantagem de dividir os genomas em espécies é que durante o passo de evolução genética onde os genomas com baixa aptidão são descartados (removidos completamente da piscina do genoma) ao invés de ter cada genoma lutar por ela s pesos otimizados sobreviverão ao abate. Resumo de todo o processo Crie um conjunto de genomas com n genomas aleatórios Pegue cada genoma e aplique ao problema / simulação e calcule a aptidão do genoma Atribua cada genoma a uma espécie Em cada espécie, abate os genomas removendo alguns dos genomas mais fracos Genomas nas espécies para crossover ou mutate) Repita tudo o que foi dito acima Esta série de quatro partes irá explorar a NeuroEvolução de Aumento de Topologias (NEAT) algoritmo. Partes um e dois brevemente out-line o algoritmo e discutir os benefícios, parte três irá aplicá-lo para o problema de equilíbrio de pólo e, finalmente, parte 4 será aplicá-lo aos dados do mercado. Este algoritmo foi recentemente viral em um vídeo chamado MarI / O onde uma rede foi desenvolvida que foi capaz de completar o primeiro nível de super mario ver o vídeo abaixo. Normalmente, quando se opta por usar uma rede neural, eles têm que decidir quantas camadas ocultas existem, o número de neurônios em cada camada e quais conexões existem entre os neurônios. Dependendo da natureza do problema, pode ser muito difícil saber o que é uma topologia sensata. Uma vez que a topologia é escolhida, provavelmente será treinada usando back-propagação ou uma abordagem de evolução genética e testada. A abordagem de evolução genética é essencialmente pesquisar através do espaço de pesos de conexão e selecionar redes de alto desempenho e criá-las (isso é conhecido como evolução de topologia fixa). A abordagem acima encontra pesos de conexão ótimos, ele para ajustar manualmente a topologia da rede em uma tentativa de iterativamente encontrar redes de melhor desempenho. Isso levou ao desenvolvimento de treinamento de topologia variável, onde tanto o espaço de conexão quanto o espaço de estrutura são explorados. Com isso veio uma série de problemas, como redes tornando-se incrivelmente espessa e complexa abrandar o processo de aprendizagem da máquina. Com as abordagens genéticas, foi difícil acompanhar mutações genéticas e estrutura de cruzamento de forma significativa. O algoritmo NEAT visa desenvolver um algoritmo genético que busca através de peso de rede neural e espaço de estrutura que tem as seguintes propriedades: Possuir representação genética que permite atravessar a estrutura de forma significativa Proteger as inovações topológicas que precisam de algumas evoluções para ser otimizado assim Que não desaparece prematuramente do pool genético Minimize as topologias durante o treinamento sem funções de penalização de complexidade de rede especialmente concebidas Um tratamento através do algoritmo pode ser encontrado no papel Evolving Neural Networks by Augmenting Topologies por Kenneth O. Stanley e Risto Miikkulainen (nn. Cs. utexas. edu/downloads/papers/stanley. ec02.pdf). A informação sobre a rede é representada por um genoma, o genoma contém genes de nó e genes de ligação. Os genes do nó definem nós na rede, os nós podem ser entradas (como um indicador técnico), saídas (como uma recomendação de compra / venda) ou ocultos (usados pela rede para um cálculo). Os genes de conexão unem os nós na rede em conjunto e têm um peso ligado a eles. Os genes de ligação têm um nó de entrada, um nó de saída, um peso, um indicador activado / desactivado e um número de inovação. O número de inovação é usado para rastrear o histórico de uma evolução de genes e será explicado com mais detalhes na parte dois. Este post vai olhar para algumas das mutações que podem acontecer com a rede, vale a pena notar que cada genoma tem incorporado dentro de uma taxa de mutação para cada tipo de mutação que pode ocorrer. Estas taxas de mutação também são aleatoriamente aumentadas ou diminuídas à medida que a evolução progride. A actualização é aleatória: Peso novo Peso antigo / - Número aleatório entre 0 e genoma MutationRate Novo Peso Número aleatório entre -2 e 2 Adiciona aleatoriamente uma nova ligação à rede com um peso aleatório entre -2 e 2 Esta mutação adiciona um novo nó à rede desabilitando uma conexão, substituindo-a por uma conexão de peso 1, um nó e uma conexão com o mesmo peso que a conexão desativada. Em essência, ele foi substituído por um equivalente equivalente. Ativar Desativar Mutação Ativa e desativa conexões aleatoriamente Este post derivará as equações de movimento e simulará o clássico problema de controle de pêndulo invertido. Postagens subseqüentes aplicam aprendizagem de máquina para descobrir como controlar o pêndulo e mantê-lo no ar. Um vídeo da simulação pode ser encontrado em: A derivação da matemática segue a abordagem descrita no vídeo a seguir, no entanto eu decidi modelar o atrito entre o carrinho e pista. Carro Diagrama do corpo livre do carro Diagrama do corpo livre do pêndulo Resolver as forças nos diagramas do corpo livre e definir igual à sua aceleração Definição do sistema de coordenadas e A aceleração do pêndulo é a aceleração do carro mais a aceleração do pêndulo relativo Para o carrinho Converta o sistema de coordenadas de volta para o e componentes Substituir as acelerações na equação (1) e (2) É indesejável ter uma tensão desconhecida T para eliminar usando um truque. Substituir a equação (1) pela equação (0) Reorganizar a equação (6) e (5) dão as equações do sistema em variáveis mensuráveis conhecidas. Ambos os termos de aceleração e dependem um do outro que é indesejável, substituir a equação pela equação para remover A dependência O sistema pode então ser simulado usando equações de atualização do Euler: o Slideshare usa cookies para melhorar a funcionalidade e o desempenho e para fornecer publicidade relevante. Se você continuar navegando no site, você concorda com o uso de cookies neste site. Veja nosso Contrato de Usuário e Política de Privacidade. O Slideshare usa cookies para melhorar a funcionalidade e o desempenho e fornecer publicidade relevante. Se você continuar navegando no site, você concorda com o uso de cookies neste site. Consulte nossa Política de Privacidade e Contrato de Usuário para obter detalhes. Explore todos os seus tópicos favoritos no aplicativo SlideShare Obtenha o aplicativo SlideShare para Salvar para mais tarde, mesmo desconectado Continue para o site móvel Upload Login Signup Toque duas vezes para diminuir o zoom Algoritmos de negociação e Aprendizagem de Máquinas por Michael Kearns, Professor de Informática e Ciência da Informação Este LinkedIn Empresa
No comments:
Post a Comment