Jon V.
BigData. Iniciantes. Negociação.
BigData. Iniciantes. Negociação.
Construindo um sistema backtesting em Python: ou como perdi $ 3400 em duas horas.
Construir um sistema de backtest é realmente muito fácil. Fácil de estragar, quero dizer. Embora existam toneladas de excelentes bibliotecas por aí (e as abordaremos em algum momento), eu sempre gosto de fazer isso por conta própria para ajustá-la.
De todos os sistemas backtesting que eu vi, podemos assumir que existem duas categorias:
Hoje, falaremos sobre "loopers".
Os "for-loopers" são o meu tipo favorito de backtesters. Eles são triviais para escrever e super divertidos para expandir, mas eles têm alguns fluxos vitais e, infelizmente, a maioria dos backtesters lá fora é "for-loopers" (ps: Eu preciso encontrar um nome melhor para isso!).
Como funciona o looping? Usando um loop for (como você pode ter adivinhado). É algo assim:
Muito simples, certo? É assim que funciona um sistema de backtesting, que executa uma estratégia de impulso:
Então qual é o problema?
Muito difícil de escalar (horizontalmente) Precisa de muito trabalho para manter sua estratégia de aplicação () trabalhando no backtesting e na produção Você precisa ter tudo na mesma linguagem de programação.
Vamos mergulhar nessas, uma a uma.
Escalabilidade. Eu estava experimentando um par de semanas atrás com um algoritmo de escalada de colina para otimizar uma das minhas estratégias. Ainda está em execução. Depois de duas semanas. E eu construo sistemas robustos para uma vida. Por que ainda está funcionando? Você pode usar multiprocessamento, Disco, produtor / consumidor (usando o ZeroMQ) ou apenas threads para acelerar isso, mas alguns problemas não são "paralisações embaraçosas" (sim, este é um termo real, e não uma das minhas palavras inventadas). A quantidade de trabalho para escalar um backtester como esse (especialmente quando você quer fazer a mesma máquina aprendendo em cima dela) é enorme. Você pode fazê-lo, mas é o caminho errado.
Produção e backtesting em sincronia. As vezes que fui mordido por isso. Posso recordar as trocas perdidas onde eu estava "hm, por que eu entrei nesse comércio?" ou o meu antigo favorito "POR QUE A PARADA DE REALIZAÇÃO FOI APLICADA AGORA?".
Tempo da história: tive uma ideia para otimizar minha estratégia, para executar um backtester para ver o que aconteceria se eu pudesse colocar uma parada posterior depois que o comércio fosse rentável para garantir sempre lucros. Backtesting funcionou como um charme com um aumento de 13% nos ganhos e a produção perdeu todo comércio. Descobri que depois do meu algo perdi US $ 3400 em algumas horas (uma lição muito cara).
Manter a estratégia apply_strategy em sincronia é muito difícil e torna-se quase impossível quando você deseja fazê-lo de forma distribuída. E você não quer ter duas versões de sua estratégia que sejam "quase" idênticas. A menos que você tenha US $ 3400 de sobra.
Usando diferentes idiomas, adoro Python. E Erlang. E Clojure. E J. E C. E R. E Ruby (na verdade eu odeio Ruby). Eu quero poder aproveitar a força de outros idiomas no meu sistema. Quero experimentar estratégias em R onde há bibliotecas muito bem testadas e há uma enorme comunidade por trás disso. Eu quero ter Erlang para escalar meu código e C para crunch dados. Se você quer ser bem sucedido (não apenas na negociação), você precisa usar todos os recursos disponíveis sem prejuízos. Aprendi toneladas de coisas de sair com os desenvolvedores R sobre como você pode delta hedge bonds e visualizá-los ou por que razão Sharpe pode ser uma mentira. Todo idioma tem uma multidão diferente e você quer que muitas pessoas despejam idéias em seu sistema. Se você tentar aplicar a estratégia apply_strategy em idioma diferente, então, boa sorte com (2).
Você está convencido agora? Bem, eu não estou tentando convencê-lo como for-loopers é uma ótima maneira de executar seus testes iniciais. É como eu comecei e, para muitas estratégias, não as envio para o pipeline. Um "melhor" caminho (para que você possa dormir à noite) são os geradores de eventos.
Próximamente, compartilhando e discutindo meu backtester mais simples (mas com maior sucesso)!
Se você tiver mais comentários, clique-me no jonromero ou inscreva-se no boletim informativo.
Legal outro. Este é um tutorial de engenharia sobre como construir uma plataforma algotrading para experimentação e FUN. Qualquer sugestão aqui não é um conselho financeiro. Se você perder qualquer (ou todos) o seu dinheiro porque seguiu quaisquer conselhos de negociação ou implantou este sistema na produção, não pode culpar este blog aleatório (e / ou eu). Aproveite a seu próprio risco.
Forex Mecânico.
Negociação no mercado FX usando estratégias mecânicas de negociação.
Backtesting Trading Systems em Python: não é uma escolha muito boa.
O idioma python é extremamente versátil, fácil de usar e conveniente. Não há discussão sobre a versatilidade deste idioma quando se trata da quantidade de tempo que leva para colocar uma idéia utilizável em código. Deseja carregar um arquivo csv? Deseja realizar um cálculo de indicador? Deseja traçar um conjunto de valores? Todas essas coisas podem ser feitas com apenas algumas linhas de código em python, enquanto certamente levaria páginas inteiras, senão milhares de linhas, para fazer as mesmas coisas em idiomas como C e Fortran. No entanto, o python possui várias fraquezas que tornam uma escolha fraca quando se trata de testar as estratégias de negociação, particularmente quando se trata de testes baseados em eventos. Nesta publicação, abordarei as diferentes coisas que fazem da Python uma má escolha para codificar os mecanismos de teste de back-ups e por que? apesar do tempo de codificação muito maior & # 8211; os benefícios de usar uma linguagem de nível mais baixo, provavelmente, superam os problemas para certos tipos de testes. Para executar o teste abaixo, baixe o código aqui.
Em geral, é importante entender que existem duas maneiras principais de fazer back-testing. O primeiro é o que é chamado de back-testing baseado em vetores e o segundo é chamado de back-testing baseado em eventos. Quando você faz back-tests baseados em vetores, você calcula vetores que representam decisões de negociação e você faz operações vetoriais para extrair o desempenho dessas variáveis. Digamos que você deseja testar uma estratégia de cross-over média móvel do modo vetorial, você primeiro calcula um vetor com todos os valores médios móveis, então você cria um segundo vetor que contém um booleano com a média móvel maior ou menor do que preço, você usa esses valores para calcular um vetor que represente equidade de acordo com onde você possui sinais, etc. O teste baseado em vetor em geral faz tudo ao calcular vetores e esses vetores são usados para gerar os resultados dos testes. É uma maneira matematicamente eficiente de realizar back-testing de certos tipos de sistemas.
Há, no entanto, muitas desvantagens na utilização de testes baseados em vetores (o que deixarei para discutir em uma publicação futura), o que leva muitas pessoas à alternativa, que são testes baseados em eventos. No caso de back-testing baseado em eventos, você envia os dados de negociação disponíveis e você passa o seu algoritmo todas as informações que ele tem disponíveis em cada ponto do tempo. Esta é a maneira de fazer back-testing que mais se aproxima da execução real do mercado porque sua estratégia está fazendo exatamente a mesma coisa, ele está recebendo dados e tomando decisões em cada unidade de tempo quando é necessário. Por este motivo, os testes baseados no evento podem testar todas as estratégias que podem ser negociadas no mercado e os algoritmos codificados para testes baseados em eventos geralmente podem ser usados sem modificações no comércio ao vivo, porque a mecânica é simplesmente a mesma. No caso de back-testing baseado em eventos, você faz uma corrida simulada explícita de sua estratégia através de seus dados como sua estratégia teria feito em negociação ao vivo (ou pelo menos tão perto quanto você pode gerenciar).
Se você quiser codificar um mecanismo de teste de retorno baseado em eventos no Python, você enfrentará alguns problemas sérios devido à natureza de Python & # 8217; s. Você pode ter decidido usar o Python porque a codificação dentro deste idioma é muito fácil, mas em breve você descobrirá que isso vem em um ótimo custo. Se você quiser realizar um exercício de teste de carregamento de dados simples mais baseado em eventos, você provavelmente usará algum código como o mostrado no exemplo acima. Este exemplo carrega dados de um arquivo chamado TEST_60.csv (30 anos, gerado aleatoriamente 1H) e, em seguida, executa um loop simples através de todo o quadro de dados de pandas para calcular o alcance médio de 20 bar em cada barra (algo extremamente simples). Fazer este exercício simples leva cerca de 12-15 segundos para carregar os dados em um banco de dados de pandas & # 8211; principalmente devido à análise da data & # 8211; e depois vários minutos para executar o exercício looping. É extremamente lento percorrer um quadro de dados de pandas porque as bibliotecas como pandas simplesmente não são projetadas para executar esse tipo de tarefa, elas são projetadas para operações baseadas em vetores que são otimizadas nas funções baseadas em C dentro da biblioteca.
Quando você usa bibliotecas como pandas ou numpy, o custo do loop é realmente muito maior do que o custo do looping através de uma lista de python simples, porque essas bibliotecas possuem funções bastante ineficientes para acessar elementos únicos em seus objetos porque este tipo de operação não é para o qual as bibliotecas foram projetadas. Os quadros de dados de pandas e as matrizes numpy não devem ser iterados, eles devem ser usados para executar operações baseadas em vetores (ou seja, o & # 8220; pythonic & # 8221; coisa a fazer). Você pode executar alguns testes e ver o quanto seu tempo muda quando você altera a função usada para acessar os valores dentro do quadro de dados do pandas, se você mudar de ix para iat ou iloc, você notará algumas diferenças importantes nos tempos de execução (veja aqui para mais informações sobre desempenho do método de indexação). Usar uma biblioteca como pandas ou numpy é ótimo em termos da quantidade de tempo de codificação economizado, mas se você estiver fazendo back-testing baseado em eventos, você nunca terá algo rápido o suficiente.
O custo de executar este tipo de looping em python torna o idioma praticamente inútil para qualquer projeto de back-testing de grande escala que exija testes baseados em eventos. O ciclo de barra 1H codificado acima leva vários minutos para executar e não é mesmo fazendo cálculos altamente exigentes, nem sequer rastreia equidade, negocia ou faz qualquer geração de sinal. Isso é tudo porque o looping através de objetos de pandas é tremendamente lento. Claro, poderíamos torná-lo mais rápido se não usássemos pandas por isso ou se usássemos ctypes, mas então você está se movendo para o território de linguagens de baixo nível já. Você está desistindo de algo que é tremendamente amigável para codificar com (pandas) para algo que é mais rápido (ctypes). Se você está disposto a aumentar seu tempo de codificação para ganhar velocidade, então você está melhor simplesmente indo para um idioma de nível inferior. Se você gastar 10 vezes o tempo fazendo o código python mais rápido, então, apenas gaste esse tempo codificando em C, onde você saberá que será o mais rápido possível.
Claro que não estou argumentando que não há lugar para o python no back-testing (depois de tudo, codificamos uma biblioteca de análise de séries temporais de código aberto em python chamado qqpat). Você pode executar testes baseados em vetores simples um pouco rápidos usando este idioma e se você está disposto a desistir das bibliotecas mais fáceis de usar, você provavelmente pode codificar algo muito mais rápido usando ctypes e acelerá-lo ainda mais usando algo como pypy . No entanto, o melhor uso que eu encontrei para o python é realmente usá-lo como um frontend para bibliotecas de back-testing muito mais rápidas codificadas em C / C ++. Em nossa comunidade, usamos o Python para fazer coisas como configurações de carga, gerar gráficos e carregar arquivos csv, enquanto uma biblioteca C muito mais eficiente executa os testes baseados no evento real. Fazendo isso, podemos realizar testes de tempo inteiros de 30 anos nas barras de 1H em questão de segundos enquanto faz isso em Python, usando bibliotecas fáceis de usar, como os pandas, provavelmente tomarão 100 vezes o tempo, se não mais. Não é um mistério, então, por que simplesmente existem programas de teste de back-up baseados em eventos comerciais que usam o Python, não é simplesmente um corte de idioma para este trabalho.
Se você quiser saber mais sobre back-testing e como você também pode codificar e testar estratégias usando nosso framework de programação C / C ++, considere se juntar a Asirikuy, um site repleto de vídeos educacionais, sistemas de negociação, desenvolvimento e um som, honesto e transparente abordagem para negociação automatizada.
3 Responses to & # 8220; Backtesting Trading Systems em Python: não é uma boa escolha e # 8221;
Eu acho que alguns ajustes menores ao seu código resultarão em uma aceleração significativa e, em última instância, poderão tornar Python um pouco mais aceitável.
1) a impressão é bastante dispendiosa. Se você quiser imprimir os dados contidos no intervalo médio em intervalos específicos, você pode fazê-lo depois de preenchê-lo.
2) Considere pré-atribuir uma matriz NumPy vazia:
& gt; & gt; n_elements = len (intervalo (2, len (main_rates. index)) * 20.
& gt; & gt; average_range [(i-2) * 20 + j] = range_value.
Apenas fazendo isso, chego ao tempo de execução total de 0,033 seg no dual Intel Xeon E5-2620 & # 8217; s. I & # 8217; m em IPython de 64 bits usando NumPy 1.10 e Pandas 0.17.1, para o que vale a pena.
Obrigado por publicar! Realmente boa melhoria, claramente a função de impressão foi apenas para fins ilustrativos (eu só queria que os usuários vejam o que a função estava fazendo), mas bom trabalho na redução do tempo ao pré-alocar a matriz numpy. Claro que existem todos os tipos de coisas que você pode fazer para tornar o código mais rápido em Python & # 8212; Definitivamente, não estou dizendo que não pode ser feito, especialmente em casos específicos como este. No entanto, acredito que ainda existe um ponto válido para obter um desempenho aceitável em Python, você precisa desistir de uma boa parte da amizade de codificação & # 8220; & # 8221; Isso faz com que seja uma linguagem tão atraente para começar. Quando o seu código se torna realmente complexo & # 8211; como se você quisesse aprender a máquina e # 8211; modificações como a que você publicou tornam-se cada vez mais difíceis de conseguir. No final, para chegar a tempos de execução como os de C / C ++, você pode acabar gastando tempo como se estivesse codificando nesses idiomas de nível inferior.
O que você acha? Você acredita que este é o caso? Você acha que sempre há uma otimização acessível que pode fazer com que um código de python atinja um C / C ++ como desempenho sem muito esforço? Alguma dicas de python que você gostaria de compartilhar? Claro que não tenho a última palavra em python, então qualquer oculto é definitivamente bem-vindo! Deixe-me saber e agradeço muito pela sua contribuição,
Eu acho que, de maneira geral, se a operação não é vetorializada, ficando mais perto do metal e # 8217; usando o cython (ou algo parecido) será ótimo e você está vivendo no mundo de C / C ++.
Dito isto, eu tenho resultados ótimos usando o Numba (uma biblioteca de compilação just-in-time que joga muito bem com o NumPy) para acelerar ARMA & # 8217; s e outras computações não vetorizadas. Para mais informações, veja:
Há todos os tipos de customizações e otimizações disponíveis para você, mas simplesmente decorar um loop numérico isolado, por exemplo, com jit parece ser bem executado na maioria dos casos.
Pesquisa de Ambientes de Backtesting em Python com pandas.
Pesquisa de Ambientes de Backtesting em Python com pandas.
Backtesting é o processo de pesquisa de aplicar uma idéia de estratégia de negociação a dados históricos para verificar o desempenho passado. Em particular, um backtester não garante o desempenho futuro da estratégia. No entanto, eles são um componente essencial do processo de pesquisa da estratégia de pipeline, permitindo que as estratégias sejam filtradas antes de serem colocadas em produção.
Neste artigo (e aqueles que o seguem), um sistema básico de backtesting orientado a objetos escrito em Python será delineado. Este sistema precoce será principalmente um "auxiliar de ensino", usado para demonstrar os diferentes componentes de um sistema de backtesting. À medida que avançamos através dos artigos, serão adicionadas funcionalidades mais sofisticadas.
Resumo de Backtesting.
O processo de projetar um sistema de backtesting robusto é extremamente difícil. Simular de forma efetiva todos os componentes que afetam o desempenho de um sistema de negociação algorítmico é um desafio. A fraca precisão de dados, a opacidade do roteamento de pedidos em um corretor, a latência de pedidos e uma miríade de outros fatores conspiram para alterar o desempenho "verdadeiro" de uma estratégia versus a performance de teste anterior.
Ao desenvolver um sistema de backtesting, é tentador querer constantemente "reescrevê-lo do zero", pois mais fatores são considerados cruciais na avaliação do desempenho. Nenhum sistema de backtesting já foi concluído e um julgamento deve ser feito em um ponto durante o desenvolvimento que fatores suficientes foram capturados pelo sistema.
Com estas preocupações em mente, o backtester apresentado aqui será um pouco simplista. À medida que exploramos novos problemas (otimização de portfólio, gerenciamento de riscos, processamento de custos de transações), o backtester se tornará mais robusto.
Tipos de sistemas de teste.
Geralmente, existem dois tipos de sistema de teste de retorno que serão de interesse. O primeiro é baseado em pesquisa, usado principalmente nos estágios iniciais, onde muitas estratégias serão testadas para selecionar aqueles para uma avaliação mais séria. Esses sistemas de análise de backtest são frequentemente escritos em Python, R ou MatLab, pois a velocidade de desenvolvimento é mais importante do que a velocidade de execução nesta fase.
O segundo tipo de sistema backtesting é baseado em eventos. Ou seja, executa o processo backtesting em um loop de execução similar (se não idêntico) ao próprio sistema de execução de negociação. Ele irá modelar de maneira realista os dados do mercado e o processo de execução da ordem, a fim de fornecer uma avaliação mais rigorosa de uma estratégia.
Os últimos sistemas são muitas vezes escritos em uma linguagem de alto desempenho, como C ++ ou Java, onde a velocidade de execução é essencial. Para estratégias de baixa freqüência (embora ainda intradias), Python é mais que suficiente para ser usado neste contexto.
Object-Oriented Research Backtester em Python.
O projeto e a implementação de um ambiente de backtesting baseado em pesquisa orientada a objetos agora serão discutidos. A orientação do objeto foi escolhida como o paradigma do projeto de software pelas seguintes razões:
As interfaces de cada componente podem ser especificadas antecipadamente, enquanto as componentes internas de cada componente podem ser modificadas (ou substituídas) à medida que o projeto progride. Ao especificar as interfaces antecipadas, é possível testar de forma eficaz a forma como cada componente se comporta (via teste unitário). o sistema de novos componentes pode ser construído sobre ou em adição a outros, seja por herança ou composição.
Nesta fase, o backtester foi projetado para facilidade de implementação e um grau razoável de flexibilidade, em detrimento da verdadeira precisão do mercado. Em particular, este backtester só poderá lidar com estratégias que atuem em um único instrumento. Mais tarde, o backtester será modificado para lidar com conjuntos de instrumentos. Para o backtester inicial, são necessários os seguintes componentes:
Estratégia - Uma classe de estratégia recebe um Pandas DataFrame de barras, ou seja, uma lista de pontos de dados Open-High-Low-Volume (OHLCV) em uma determinada freqüência. A Estratégia produzirá uma lista de sinais, que consistem em um carimbo de data / hora e um elemento do conjunto $ \ $ indicando um sinal longo, de espera ou curto, respectivamente. Portfolio - A maioria do trabalho de backtesting ocorrerá na classe Portfolio. Ele receberá um conjunto de sinais (conforme descrito acima) e criará uma série de posições, alocadas contra um componente de caixa. O trabalho do objeto Portfolio é produzir uma curva de patrimônio, incorporar os custos básicos de transação e acompanhar os negócios. Desempenho - O objeto Performance obtém um portfólio e produz um conjunto de estatísticas sobre seu desempenho. Em particular, produzirá características de risco / retorno (Sharpe, Sortino e Informações Ratios), métricas de comércio / lucro e informações de redução.
O que está a faltar?
Como pode ser visto, este backtester não inclui nenhuma referência ao gerenciamento de portfólio / risco, gerenciamento de execução (ou seja, sem pedidos de limite), nem fornecerá modelos sofisticados de custos de transação. Este não é um grande problema nesta fase. Isso nos permite familiarizar-se com o processo de criação de um backtester orientado a objetos e das bibliotecas Pandas / NumPy. Com o tempo, será melhorado.
Implementação.
Vamos agora descrever as implementações para cada objeto.
O objeto Estratégia deve ser bastante genérico nessa etapa, já que tratará as estratégias de previsão, média-reversão, impulso e volatilidade. As estratégias que estão sendo consideradas aqui serão sempre baseadas em séries temporais, ou seja, "preço direcionado". Uma exigência precoce para este backtester é que as classes de Estratégias derivadas aceitarão uma lista de barras (OHLCV) como entrada, em vez de carrapatos (preços de troca por meio do comércio) ou dados do livro de pedidos. Assim, a granularidade mais fina que está sendo considerada aqui será barras de 1 segundo.
A classe Estratégia também produzirá sempre recomendações de sinal. Isso significa que irá aconselhar uma instância do Portfolio no sentido de ir longo / curto ou manter uma posição. Essa flexibilidade nos permitirá criar vários "conselheiros" de estratégia que fornecem um conjunto de sinais, que uma classe de portfólio mais avançada pode aceitar para determinar as posições reais que estão sendo inseridas.
A interface das classes será aplicada utilizando uma metodologia de classe básica abstrata. Uma classe base abstrata é um objeto que não pode ser instanciado e, portanto, somente classes derivadas podem ser criadas. O código Python é dado abaixo em um arquivo chamado backtest. py. A classe Estratégia exige que qualquer subclasse implemente o método generate_signals.
Para evitar que a classe Estratégia seja instanciada diretamente (desde que é resumo!), É necessário usar os objetos ABCMeta e abstractmethod do módulo abc. Nós estabelecemos uma propriedade da classe, chamada __metaclass__ para ser igual a ABCMeta e depois decorar o método generate_signals com o decorador abstractmethod.
Embora a interface acima seja direta, ela se tornará mais complicada quando essa classe for herdada para cada tipo específico de estratégia. Em última análise, o objetivo da classe Estratégia nesta configuração é fornecer uma lista de sinais longos / curtos / de espera para cada instrumento a ser enviado para um portfólio.
A classe Portfolio é onde a maioria da lógica de negociação irá residir. Para este testador de pesquisa, o Portfolio é responsável por determinar o dimensionamento da posição, a análise de risco, o gerenciamento de custos de transações e o gerenciamento de execução (ou seja, o mercado aberto, o mercado de fechamento de pedidos). Em uma etapa posterior, essas tarefas serão divididas em componentes separados. Agora, eles serão incorporados a uma classe.
Esta classe faz um amplo uso de pandas e fornece um ótimo exemplo de onde a biblioteca pode economizar uma grande quantidade de tempo, especialmente no que diz respeito à disputa de dados "boilerplate". Como um lado, o truque principal com pandas e NumPy é evitar iterar sobre qualquer conjunto de dados usando o d para dentro. sintaxe. Isso ocorre porque o NumPy (que está subjacente aos pandas) otimiza o looping por operações vectorizadas. Assim, você verá poucas (se houver!) Iterações diretas ao utilizar pandas.
O objetivo da classe Portfolio é, em última análise, produzir uma seqüência de trades e uma curva patrimonial, que será analisada pela classe Performance. Para conseguir isso, deve ser fornecida uma lista de recomendações de negociação de um objeto Estratégia. Posteriormente, este será um grupo de objetos Estratégia.
A classe Portfolio deve ser informada sobre como o capital deve ser implantado para um determinado conjunto de sinais comerciais, como lidar com os custos de transação e quais formas de pedidos serão utilizadas. O objeto Estratégia está operando em barras de dados e, portanto, pressupostos devem ser feitos em relação aos preços alcançados na execução de um pedido. Como o preço alto / baixo de qualquer barra é desconhecido a priori, só é possível usar os preços abertos e fechados para negociação. Na realidade, é impossível garantir que um pedido seja preenchido em um desses preços particulares ao usar uma ordem de mercado, por isso será, na melhor das hipóteses, uma aproximação.
Além dos pressupostos sobre as encomendas que estão sendo preenchidas, este backtester irá ignorar todos os conceitos de restrições de margem / corretagem e assumirá que é possível passar longo e curto em qualquer instrumento livremente, sem restrições de liquidez. Esta é claramente uma hipótese muito irrealista, mas é uma que pode ser relaxada mais tarde.
A seguinte lista continua backtest. py:
Nesta fase, as classes de base abstrata Estratégia e portfólio foram introduzidas. Agora estamos em condições de gerar algumas implementações concretas derivadas dessas classes, a fim de produzir uma "estratégia de brinquedo" de trabalho.
Começaremos por gerar uma subclasse de Estratégia chamada RandomForecastStrategy, cuja única tarefa é produzir sinais longos / curtos escolhidos aleatoriamente! Embora esta seja claramente uma estratégia de negociação absurda, ela irá atender às nossas necessidades demonstrando a estrutura de backtesting orientada a objetos. Assim, iniciaremos um novo arquivo chamado random_forecast. py, com a listagem do pré provisorio aleatório da seguinte maneira:
Agora que temos um sistema de previsão "concreto", devemos criar uma implementação de um objeto Portfolio. Este objeto englobará a maioria do código de backtesting. Ele é projetado para criar dois DataFrames separados, o primeiro dos quais é um quadro de posições, usado para armazenar a quantidade de cada instrumento mantido em qualquer barra particular. O segundo, o portfólio, realmente contém o preço de mercado de todas as participações para cada barra, bem como uma contagem do caixa, assumindo um capital inicial. Isso, em última instância, fornece uma curva de equidade na qual avaliar o desempenho da estratégia.
O objeto Portfolio, embora extremamente flexível em sua interface, requer escolhas específicas quando se trata de como lidar com custos de transação, pedidos de mercado, etc. Neste exemplo básico, considero que será possível ir com um instrumento longo / curto sem restrições ou margem, compra ou venda diretamente no preço aberto do bar, custos de transação zero (abrangendo deslizamento, taxas e impacto no mercado) e especificaram a quantidade de estoque diretamente para comprar para cada comércio.
Aqui está a continuação da listagem random_forecast. py:
Isso nos dá tudo o que precisamos para gerar uma curva de equidade baseada nesse sistema. O passo final é amarrar tudo junto com uma função __main__:
A saída do programa é a seguinte. O seu será diferente da saída abaixo dependendo do intervalo de datas que você selecionar e da semente aleatória utilizada:
Neste caso, a estratégia perdeu dinheiro, o que não é surpreendente, dada a natureza estocástica do previsor. Os próximos passos são criar um objeto de desempenho que aceita uma instância do Portfolio e fornece uma lista de métricas de desempenho sobre as quais basear uma decisão para filtrar a estratégia ou não.
Também podemos melhorar o objeto da Carteira para ter um tratamento mais realista dos custos de transação (como as comissões de Interactive Brokers e o deslizamento). Também podemos incluir diretamente um mecanismo de previsão em um objeto de Estratégia, o que (espero) produza melhores resultados. Nos artigos a seguir, exploraremos esses conceitos com mais profundidade.
A Quantcademy.
Junte-se ao portal de adesão da Quantcademy que atende à comunidade de comerciantes de varejo de varejo em rápido crescimento e saiba como aumentar a rentabilidade da sua estratégia.
Comércio Algoritmo bem sucedido.
Como encontrar novas ideias de estratégia de negociação e avaliá-las objetivamente para seu portfólio usando um mecanismo de backtesting personalizado em Python.
Negociação Algorítmica Avançada.
Como implementar estratégias de negociação avançadas usando análise de séries temporais, aprendizado de máquinas e estatísticas bayesianas com R e Python.
Estratégia de Negociação de Osciladores Estocásticos Backtest em Python.
Eu pensei que para este post eu continuaria apenas com o tema de testar estratégias de negociação com base em sinais de alguns dos indicadores técnicos clássicos & # 8221; que muitos comerciantes incorporam na sua tomada de decisão; A última publicação tratou as Bandas de Bollinger e, por essa, pensei que iria para um Backstra de Estratégia de Negociação Oscilador Estocástico em Python.
Deixe começar com o que o oscilador estocástico é realmente; A Investopedia descreve da seguinte maneira:
& # 8220; O que é o & # 8216; Oscilador estocástico & # 8217;
O oscilador estocástico é um indicador de momentum que compara o preço de fechamento de uma garantia com a faixa de seus preços durante um determinado período de tempo. A sensibilidade do oscilador aos movimentos do mercado é redutível ajustando esse período de tempo ou tomando uma média móvel do resultado.
BREAKING DOWN & # 8216; Stochastic Oscillator & # 8217;
O oscilador estocástico é calculado utilizando a seguinte fórmula:
C = o preço de fechamento mais recente.
L14 = baixa das 14 sessões de negociação anteriores.
H14 = o preço mais alto negociado durante o mesmo período de 14 dias.
% K = a taxa de mercado atual para o par de moedas.
% D = média móvel de 3 períodos de% K.
A teoria geral que serve de base para esse indicador é que, em um mercado tendendo para cima, os preços se fecharão perto do alto e, no mercado, tendem a baixar, os preços fecham perto da baixa. Os sinais de transação são criados quando o% K atravessa uma média móvel de três períodos, que é chamado de% D. & # 8221;
Quero testar duas implementações diferentes do Oscilador Estocástico:
1) Um sinal de entrada de venda é fornecido quando a linha% K atravessa a linha% D e a linha% K está acima de 80. O sinal de saída para esta posição curta é dado assim que a linha% K cruza backup a linha% D, independentemente do valor real da linha% K quando isso acontecer. Um sinal de entrada de compra é dado quando a linha% K passa pela linha% D e a linha% K é menor que 20 naquele momento. O sinal de saída para esta posição longa é dado assim que a linha% K cruza de volta pela linha% D, independentemente do valor real da linha% K quando isso acontecer. Nesta implementação, existem 3 possíveis estados & # 8211; longo, curto, plano (ou seja, sem posição).
2) Nesta implementação, existem apenas 2 estados possíveis e # 8211; longo ou curto. Uma vez que uma posição é inserida, a posição é mantida até que um sinal oposto seja dado, em que ponto a posição é invertida (ou seja, de longo a curto ou de curto a longo). Por exemplo, se uma posição de entrada de compra é sinalizada pela linha% K subindo através da linha% D enquanto a linha% K é inferior a 20, a posição é mantida até a linha% K atravessar a linha% D enquanto a% A linha K está acima de 80.
Então, obtenha algum código e experimente a estratégia no estoque da Apple Inc..
Agora, vamos criar um gráfico (com 2 subtramas) mostrando o preço da Apple ao longo do tempo, juntamente com uma representação visual do Oscilador Estocástico.
Deixe traçar a posição ao longo do tempo para ter uma idéia de quando estamos longos e quando somos curtos:
Então, vemos que nossos retornos são, de fato, positivos pelo menos, mas poderíamos ter feito muito melhor apenas comprando e segurando o estoque da Apple, o que é um pouco decepcionante.
Então, na nossa segunda implementação da estratégia # 8211; aquele em que somos longos ou curtos. Eu vou apenas colar todo o código de uma só vez e apresentar a curva de equidade no final:
Desafortunadamente, esta implementação nos dá um resultado pior, com o retorno geral sendo bastante fortemente negativo.
Então, mais uma vez, mostramos que usar um indicador técnico simples, como o Oscilador Estocástico não é suficiente para gerar retornos superiores (horror de choque!), Pelo menos para a Apple durante o período testado. Eu imagino que os estoques para os quais esta estratégia funcionou de forma suficientemente robusta para confiar realmente seria poucos e distantes. Não se machucou para olhar e # 8230;
Até a próxima vez!
5 Comentários.
Muito obrigado, todos são úteis, se for puramente para as lições de codificação.
Na verdade, isso é alfa, basicamente, a lógica pode ser invertida para comprar quando o oscilador não deu um sinal.
Olá, no seu código, o que é lt, amp e gt.
O código foi infelizmente formatado incorretamente & # 8230; & # 8220; lt & # 8221; significa "# 8220; maior que & # 8221; e pode ser substituído por & # 8220; & # 8221; e amp significa & # 8220; ampersand & # 8221; e pode ser substituído por & # 8220; & amp; & # 8221;
Ignore a resposta anterior, I & # 8217; m no meu telefone e não está formatando corretamente. Eu responderei do meu laptop quando estiver em casa de viajar no início da próxima semana. Desculpas por isso.
No comments:
Post a Comment