Tuesday 4 July 2017

Movimento Média Crossover Backtest


Backtesting um Crossover média móvel em Python com pandas No artigo anterior sobre Research Backtesting Ambientes Em Python Com Pandas criamos um ambiente de backtesting baseado em pesquisa orientada a objetos e testá-lo em uma estratégia de previsão aleatória. Neste artigo, faremos uso da maquinaria que introduzimos para realizar pesquisas sobre uma estratégia real, a saber, o Crossover Médio Móvel na AAPL. Estratégia de Crossover Médio em Movimento A técnica de Crossover de Moving Average é uma estratégia de momentum simplista extremamente bem conhecida. É freqüentemente considerado o exemplo Hello World para negociação quantitativa. A estratégia aqui descrita é longa. São criados dois filtros separados de média móvel simples, com períodos de retrocesso variáveis, de uma série temporal específica. Os sinais para comprar o ativo ocorrem quando a média móvel de retrocesso mais curta excede a média móvel de retrocesso mais longa. Se a média mais longa subseqüentemente exceder a média mais curta, o ativo é vendido de volta. A estratégia funciona bem quando uma série de tempo entra em um período de forte tendência e, em seguida, lentamente inverte a tendência. Para este exemplo, eu escolhi a Apple, Inc. (AAPL) como a série de tempo, com um lookback curto de 100 dias e um lookback longo de 400 dias. Este é o exemplo fornecido pela biblioteca de negociação algorítmica do zipline. Assim, se queremos implementar nosso próprio backtester, precisamos garantir que ele corresponda aos resultados em tirolesa, como um meio básico de validação. Implementação Certifique-se de seguir o tutorial anterior aqui. Que descreve como a hierarquia de objeto inicial para o backtester é construída, caso contrário, o código abaixo não funcionará. Para esta implementação em particular, usei as seguintes bibliotecas: A implementação do macross. py requer backtest. py do tutorial anterior. O primeiro passo é importar os módulos e objetos necessários: Como no tutorial anterior, vamos subclassificar a classe base Abstract de Estratégia para produzir MovingAverageCrossStrategy. Que contém todos os detalhes sobre como gerar os sinais quando as médias móveis de AAPL cruzam-se uns aos outros. O objeto requer uma janela curta e uma janela longa sobre a qual operar. Os valores foram ajustados para padrões de 100 dias e 400 dias respectivamente, que são os mesmos parâmetros usados ​​no exemplo principal de tirolesa. As médias móveis são criadas usando a função rollingmean pandas sobre as barrasFechar fechar preço do estoque AAPL. Uma vez construídas as médias móveis individuais, a Série de sinais é gerada ajustando a coluna igual a 1,0 quando a média móvel curta é maior que a média móvel longa, ou 0,0 caso contrário. A partir daí, as ordens de posição podem ser geradas para representar sinais de negociação. O MarketOnClosePortfolio é subclassificado do Portfolio. Que é encontrado em backtest. py. É quase idêntico à implementação descrita no tutorial anterior, com a exceção de que as negociações são agora realizadas em uma base Close-to-Close, ao invés de uma base Open-to-Open. Para obter detalhes sobre como o objeto Portfolio está definido, consulte o tutorial anterior. Ive deixou o código em para a integridade e para manter este tutorial auto-contido: Agora que as classes MovingAverageCrossStrategy e MarketOnClosePortfolio foram definidas, uma função principal será chamado para amarrar toda a funcionalidade em conjunto. Além disso, o desempenho da estratégia será analisado através de um gráfico da curva de equivalência patrimonial. O objeto DataReader do pandas faz o download dos preços OHLCV das ações da AAPL para o período de 1º de janeiro de 1990 a 1º de janeiro de 2002, momento em que os sinais DataFrame são criados para gerar os sinais long-only. Posteriormente, a carteira é gerada com uma base de capital inicial de 100.000 USD e os retornos são calculados na curva de equivalência patrimonial. O passo final é usar matplotlib para traçar um gráfico de dois dígitos de ambos os preços AAPL, sobreposta com as médias móveis e os sinais de buysell, bem como a curva de equidade com os mesmos sinais de buysell. O código de plotagem é obtido (e modificado) a partir do exemplo de implementação da tirolesa. A saída gráfica do código é a seguinte. Eu fiz uso do comando IPython colar para colocar isso diretamente no console IPython enquanto no Ubuntu, de modo que a saída gráfica permaneceu na vista. Os upticks cor-de-rosa representam a compra do estoque, enquanto os downticks negros representam vendê-lo de volta: Como pode ser visto a estratégia perde dinheiro durante o período, com cinco comércios de ida e volta. Isto não é surpreendente dado o comportamento da AAPL ao longo do período, que estava em uma ligeira tendência descendente, seguido por um aumento significativo começando em 1998. O período de retrocesso dos sinais de média móvel é bastante grande e isso afetou o lucro do comércio final , O que de outra forma pode ter feito a estratégia rentável. Em artigos subseqüentes, criaremos um meio mais sofisticado de analisar o desempenho, bem como descrevendo como otimizar os períodos de retorno dos sinais individuais de média móvel. Basta começar com Quantitative TradingMoving média Crossover estratégia de negociação Backtest em Python 8211 V 2.0 Este é um teste de texto do anúncio Bem-vindo back8230 esta postagem vai lidar com um par de perguntas que recebi na seção de comentários de um post anterior, uma relativa a um movimento Estratégia de troca cruzada média 8211 o artigo pode ser encontrado aqui. As perguntas que eu recebi no início perguntaram se o código para o backtest poderia ser adaptado para seguir as seguintes regras: (1) Se a média curta móvel atravessa acima da média móvel longa ir longa para x dias. (2) se a média móvel curta cruzar abaixo da média móvel longa curta para x dias. (3a) Se houver um crossover adicional durante o período de espera ignorá-lo (3b) Se não houver crossovers segurar o dinheiro Aqui está o código original: import relevantes módulos importação pandas como pd import numpy como np de pandasdatareader importar dados de matemática importação sqrt import Matplotlib. pyplot como plt baixar dados em DataFrame e criar médias móveis colunas sp500 data. DataReader (GSPC, yahoo, start112000) sp50042d np. round (sp500Close. rolling (window42).mean (), 2) sp500252d np. round (sp500Close. Sp50042-252 sp50042d - sp500252d definir o número desejado de pontos como limite para diferença de propagação e criar uma coluna contendo estratégia Stance X 50 sp500Stance np. where (sp50042-252) Sp500Stance np. where (sp50042-252 lt X, -1, sp500Stance) sp500Stance. valuecounts () criam colunas que contêm log diário do mercado retorna e a estratégia retorna log diário sp500Market Retorna np. log (sp500Close sp500Close. shift (1)) s P500Strategy sp500Market Retorna sp500Stance. shift (1) defina estratégia de partida de equidade para 1 (i. e. Sp500Strategy Equity sp500Strategy Equity sp500Strategy. cumsum () 1 mapa de espessura da curva de equidade sp500Strategy Equity. plot () E aqui está o código que incorpora as regras acima: Importação de módulos import relevantes pandas como importação pd numpy como np da importação pandasdatareader Dados de importação de matemática importação sqrt matplotlib. pyplot como plt matplotlib dados de download inline em DataFrame e criar colunas médias móveis sp500 data. DataReader (GSPC, yahoo, start112014) sp50042d np. round (sp500Close. rolling (window42).mean (), 2 ) Sp500252d np. round (sp500Close. rolling (window252).mean (), 2) criar coluna com diferença média móvel sp50042-252 sp50042d - sp500252d definir o número desejado de pontos como limite para diferença de propagação e criar coluna contendo estratégia Stance X 50 Sp500Stance np. where (sp50042-252 gt X, 1, 0) sp500Stance np. where (sp50042-252 lt - X, -1, sp500Stance) sp500Stance. valuecounts () criar colunas que contenham log diário do mercado retorna e estratégia diária log ret Sp500Market Retorna sp500Market sp500Market Retorna sp500Store. shift (1) configurar uma nova coluna para manter nossa posição relevante para o período de espera pré-especificado sp500Stance2 0 definir período de espera predeterminado, após o qual o tempo Vamos voltar a segurar dinheiro e esperar a próxima média móvel atravessar - também vamos ignorar quaisquer crossovers extra durante este período de detenção dias 50 iterar através do DataFrame e atualizar a coluna quotStance2quot para manter a posição revelante para i no intervalo (X (Sp500Stance. iloci gt sp500Stance. iloci-1) e (sp500Stance. iloci-1 0): teste lógico para verificar se 1) uma cruz sobre curto longo MA 2) que estamos atualmente em dinheiro se (sp500Stance. iloci gt sp500Stance. iloci-1) E sp500Stance2.iloci-1 0): preencher o DataFrame em tempo para a quantidade de dias em nosso período de retenção para k no intervalo (dias): try: sp500Stance2.ilocik 1 sp500Stance2.ilocik1 0 exceto: passar o teste lógico para verificar Para 1) uma cruz sobre curto sob MA longo 2) T (Sp500Stance. iloci-1 0) e (sp500Stance2.iloci-1 0): preencher o DataFrame para a frente em tempo para a quantidade de dias em nosso Sp500Stance2.ilocik -1 sp500Stance2.ilocik1 0 exceto: pass Calcular os retornos diários do mercado e os retornos diários da estratégia sp500Market Retorna np. log (sp500Close sp500Close. shift (1)) sp500Strategy sp500Market Retorna sp500Stance2 A estratégia de plotagem retorna contra o retorno do mercado. Sp500Market Retorna, Strategy. cumsum (). Plot (gridTrue, figsize (8,5)) plt. show () Sp500Strategy Equity sp500Strategy. cumsum () 1 mostra gráfico da curva de equidade sp500Strategy Equity. plot (gridTrue, figsize (8,5)) plt. show () Depois de postar este código eu recebi as seguintes perguntas de acompanhamento : 8220 Obrigado pela resposta. Estou tendo alguns problemas para entender este pedaço de código. O código está funcionando, mas eu gostaria de entender melhor. Estou principalmente confundido com o iloc, ek e I. Eu realmente não entendo o que aqueles são ou de onde eles estão puxando informações. Qualquer clareza seria muito apreciada8221 So8230. Aqui é a minha tentativa de tentar esclarecer o meu pensamento enquanto escrevo o código, e tentar explicar exatamente o que está acontecendo linha por linha. Let8217s começar com o 8220iloc8221 aqui é a informação da documentação Pandas oficial:.iloc é principalmente posição inteira com base (de 0 a comprimento-1 do eixo), mas também pode ser usado com uma matriz booleana. Iloc aumentará IndexError se um indexador solicitado estiver fora dos limites, exceto os indexadores de fatia que permitem a indexação fora dos limites. (Isto está de acordo com a semântica da fatia pythonnumpy). As entradas permitidas são: Um número inteiro, p. 5 Uma lista ou matriz de inteiros 4, 3, 0 Um objeto de fatia com ints 1: 7 Uma matriz booleana Uma função chamada com um argumento (a série, o DataFrame ou o Painel) que retorna saída válida para indexação (uma das opções acima ) Assim como afirmado acima, 8220iloc8221 é apenas uma maneira fácil de fazer referência a uma posição de linha em seu DataFrame 8211 simples como isso. Se criarmos o seguinte DataFrame e mostrá-lo, obtemos: iterar através do DataFrame e atualizar a coluna quotStance2quot para manter a posição revelante para i no intervalo (X, len (sp500)): Está usando a função 8220range8221 para criar uma lista de Valores começando em 8220X8221 e subindo para (mas não incluindo) o valor de por muito tempo que o sp500 DataFrame é, usando a função 8220len8221. Assim, se X é 50, por exemplo, eo comprimento do sp500 DataFrame é 500, a lista de valores que iremos iterar passará de 50 a 499 8211, ou seja, a partir do 50º dia no nosso DataFrame até o último. Quando combinamos o 8220.iloc8221 e o 8220for i no range8221 e realmente passamos o valor de 8220i8221 para o 8220iloc8221 como 8220.iloci8221 8211 podemos usar o iterador 8220i8221, que está aumentando para cima por um cada vez que o loop for, Para acessar cada índice de linha do DataFrame, um após o outro. Direito, então devemos agora ser claros sobre o 8220for principal no intervalo (X, len (sp500)): 8221 loop 8211 estamos literalmente apenas iterando embora cada linha no DataFrame um por um, começando na linha X e terminando na Final do DataFrame (na verdade tecnicamente estamos terminando no segundo último dia como a função de intervalo cria uma lista que vai até, mas doesn8217t incluir o segundo valor passado 8211, mas para os nossos fins de acabamento no segundo último dia não tem efeito sobre o Saída) Então, agora let8217s tentar abordar todos esses 8220if8221 e 8220for k8221 loops e testes dentro do exterior principal 8220for8221 loop explicado acima. Os testes 8220if8221 estão apenas executando um par de testes lógicos em cada linha do DataFrame que estamos iterando através de 8211 os primeiros testes lógicos lidar com crossovers quando a média curta móvel passa por cima da média móvel longa e usa os valores na coluna 8220Stance8221 em primeiro lugar Para verificar se os valores se movem de 0 para 1 a partir do dia 8220T-18221 para o dia 8220T8221 E o valor na coluna 8220Stance28221 no dia 8220T-18221 também é 0 8211 se assim for, isto significa que a média móvel curta cruzou acima do movimento longo Média e devemos entrar em uma posição. Se isso não está claro por que ter um pouco de tempo para pensar a lógica. Precisamos da coluna 8220Stance8221 para passar de 0 para 1 para significar um crossover MA mais curto, mas também precisamos da coluna 8220Stance28221 no dia 8220T-18221 para ser 0, como se fosse, nenhuma posição é atualmente realizada e deve-se portanto Ser celebrado. Se 8220Stance28221 no dia 8220T-18221 não foi zero, então isso significa que já estamos em uma posição e nada deve ser feito, mesmo que o primeiro teste lógico mostre um crossover de média móvel. Eu aprecio este poderia fazer exame de um pouco de tempo para trabalhar completamente e começar sua cabeça ao redor, mas tudo que eu posso dizer é que os testes lógicos como ajustados acima no código seguem certamente a lógica apresentada nas perguntas iniciais. O segundo conjunto de 8220if8221 testes são apenas a imagem espelho do primeiro 8211 e lidar com crossovers quando a curta média móvel cruza abaixo da média móvel longo. Agora, finalmente, espero que o acima é tudo claro (como lama) e tudo o que temos à esquerda para lidar com o uso de 8220k8221 no 8220for k no intervalo (dias) 8221 loop. Em primeiro lugar, 8220days8221 é apenas uma variável que detém o número de dias que deseja manter nossas posições antes de automaticamente sair dessas posições. 8220days8221 foi definido para 50 no código, mas poderia ser definido para qualquer valor desejado para a sua estratégia específica. Assim, com isso em mente, o loop 8220for k em intervalo (dias) 8221 executa se e somente se os testes lógicos anteriores forem satisfeitos, e nossa estratégia está nos dizendo para abrir uma posição (seja longa ou curta). Se um sinal de entrada é apresentado, então iterar para a frente no tempo de 8220k8221 dias (começando no dia 8220i8221 8211 por isso usamos 8220ik8221 como o nosso dia de início) e definir o nosso 8220Stance28221 para 1 ou -1 (dependendo se o sinal é um longo Ou sinal de posição curta). Isso representa o tempo que desejamos manter nossa posição antes de sair automaticamente. Assim, se um sinal de entrada for produzido no dia 100 (em que ponto i será igual a 100), a posição no dia 8220i k8221 será ajustada para -1 ou 1 k começará em 0 e irá para 49, incrementando por um com cada Executar através do loop 8220for k in8221. Assim, a postura no dia 8220i k8221, fixa o dia 100 0 a 1 ou -1, depois o dia 100 1 depois 100 2 etc, até a posição ser retirada no dia 100 49 e a posição no dia 100 50 é ajustada para zero para Mostram uma posição plana. Um par de possivelmente confuso adições à lógica acima e nas seguintes linhas: para k no intervalo (dias): try: sp500Stance2.ilocik 1 sp500Stance2.ilocik1 0 exceto: pass são o uso da segunda linha 8220sp5008216Stance28217.ilocik1 08221 8211 I Incluímos isso para certificar-se de que a coluna 8220Stance28221 foi redefinida para 0, já que saímos de nossa posição e agora estamos de novo plana 8211 essa posição plana é definida para o dia depois que saímos de nossa posição 8211 no dia de efeito (ik1). A segunda adição possivelmente confusa é a utilização da 8220try e except8221. Usamos isso para que, se chegarmos ao final do DataFrame enquanto continuamos iterando no tempo em X dias, em vez de lançar um erro 8220index fora do limite8221 e sair do código, o código simplesmente passa e termina sem erro. Isso pode acontecer, por exemplo, se a nossa janela 8220days8221 é definida como 50 e com apenas 30 dias restantes dos dados, um sinal de entrada é produzido 8211 se tentarmos iterar para a frente 50 dias no tempo quando apenas 30 dias de dados existe 8211 sem tryexcept Nosso código vai cuspir um erro e sair. Esperemos que este post explica e esclarece a grande maioria do código aumentado 8211 se não, então por favor deixe suas perguntas e comentários abaixo e I8217ll tentar atacá-los all8230 Até próxima vez Boa informação. Mas eu tenho que anotar que o projeto precedente do Web site era muito muito melhor do que este. Esse texto cinza é difícil de ler, funções de zoom inout não funciona neste tema. Todo o site funciona mais lento do que com o tema anterior. Talvez porque vários plugins instalados como Squirrly SEO, W3 Total Cache e Jetpack. Beleive me, tendo tal conteúdo informativo, você don8217t necessidade de todos os que seo lixo em tudo. Oi, eu concordo totalmente, desisti com o tema anterior, era muito complexo nos bastidores e eu nunca conseguiria nada para parecer o jeito que eu queria. Então I8217ve decidiu usar este novo tema agora eu estaria interessado em ouvir o que você pensa se ele Obrigado pelo feedback 8211 it8217s sempre muito apreciado e definitivamente get8217s escutouMoving Média Crossover Trading Backtest Estratégia em Python Este é um texto de anúncio de teste Oi pessoal, Para este post eu estarei construindo um backtest simples de estratégia de troca de crossover média móvel em Python. Usando o SampP500 como o mercado para testar. Uma simples média móvel cruzar a estratégia é possivelmente um, se não o exemplo mais simples de uma estratégia de negociação baseada em regras usando indicadores técnicos, então eu pensei que este seria um bom exemplo para aqueles que aprendem Python tentar mantê-lo tão simples quanto possível e construir Até de lá. Assim como sempre ao usar Python para dados relacionados finacial shenanigans, it8217s tempo para importar nossos módulos necessários: importar pandas como importação de pd numpy como np de dados de importação de pandasdatareader Nós usaremos primeiramente a funcionalidade de pandas-datareader para download os dados de preço da primeira negociação (GSPC, yahoo, start112000) Este é um teste de uma outra estratégia de negociação VIX da excelente Logical-Invest (ver o nosso teste anterior de LIs Bollinger Bandas). Este usa um crossover de média móvel de 515 dias para trocar VIX ETPs como XIV (ou VXX curto). O gráfico abaixo mostra os resultados da estratégia de negociação XIV (azul), em comparação com a compra e exploração XIV (cinza), a partir de meados de 2004. Leia sobre pressupostos de teste. Ou obter ajuda na sequência desta estratégia. Regras de estratégia: Vá longo XIV no fechamento de hoje se sua média móvel simples de 5 dias (SMA) vai fechar acima de sua SMA de 15 dias. Segure até que seu SMA de 5 dias feche abaixo de sua SMA de 15 dias e, em seguida, mova para caixa. A estratégia (como a variação de banda de Bollinger) é de uma forma indireta uma estratégia de momentum. A estratégia está comprando XIV quando a sua recente força mostrando, e segurando até XIV se move para trás abaixo da sua média de médio prazo. Note que nosso backtest difere de Logical-Invests teste original de três maneiras: LIs teste começou no início de 2009. Weve adicionou quase 5 anos de dados simulados adicionais (1). O teste de LIs supôs que nós viramos curto VXX. Enquanto Ive mostrou resultados negociando longo XIV para permitir uma comparação maçãs-a-maçãs com outros backtests aqui em Volatility Made Simple. LIs teste assumiu nós executados comércios nos próximos dias abertos, ao invés de fechar hoje. Eu testa no fechamento porque não há nenhum método de confiança para simular dados pré-2009 para o aberto. Como seria de esperar intuitivamente com base nas regras das estratégias, o seu feito um bom trabalho sidestepping a maioria dos levantamentos XIVs significativa porque a sua estratégia de forçar a XIV começa a mover-se contra o comerciante, independentemente de todas as outras considerações como o estado dos futuros VIX Mas que a ânsia de sair posições rapidamente também deixa um monte de ganhos na mesa quando XIV está em uma tendência de alta consistente (ou seja, VXX está em uma forte tendência de baixa), como tem sido o caso nos últimos 2 anos. A estratégia de banda Bollinger testada anteriormente ajudou a responder que, tornando-se um pouco mais difícil sair posições (ver post para mais detalhes). Com base nos testes muito mais longos que Ive apresentou aqui, das duas variações, eu prefiro a banda Bollinger um. Um grande obrigado a Logical-Invest para publicar esta estratégia. Quando as estratégias que abordamos em nosso blog (incluindo este) sinalizam novos negócios, incluímos um alerta no relatório diário enviado aos assinantes. Isso é completamente independentes do nosso próprio sinal strategys apenas serve para adicionar um pouco de cor para o relatório diário e permite que os assinantes para ver o que outras estratégias quantitativas estão dizendo sobre o mercado. Clique para ver Volatility Made Simples própria solução elegante para o puzzle VIX ETP. Boa Negociação, Volatilidade Made Simple Nota Wonk: Dados antes do lançamento do XIV foi simulada. Foram capazes de fazer isso com precisão usando uma combinação dos índices e os dados de futuros em que este ETP é baseado. Leia mais sobre a simulação de dados para ETPs VIX. Post navigation Categorias Mensagens recentes

No comments:

Post a Comment