среда, 13 июня 2018 г.

Backtesting trading strategies in r


Estratégias de Backtesting com R.


2018-05-06.


Capítulo 1 Introdução.


Este livro foi concebido para não apenas produzir estatísticas em muitos dos padrões técnicos mais comuns no mercado de ações, mas para mostrar trades reais em tais cenários.


Teste uma estratégia; rejeitar se os resultados não são promissores.


Aplique uma série de parâmetros para estratégias de otimização.


Tentativa de matar qualquer estratégia que pareça promissora.


Deixe-me explicar esse último um pouco. Só porque você pode encontrar uma estratégia que parece superar o mercado, ter bons lucros e baixa redução, isso não significa que você tenha encontrado uma estratégia para trabalhar. Pelo contrário, você deve trabalhar para refutá-lo. Nada é pior do que colocar uma estratégia não lucrativa para o trabalho, porque não foi testado rigorosamente. Vamos abordar isso mais tarde.


1.1 R Resources.


Este livro supõe que você tenha pelo menos um conhecimento básico de trabalho da plataforma R. Se você é novo em R ou precisa de uma atualização, o seguinte site deve ser benéfico:


Além disso, os pacotes utilizados neste livro podem ser encontrados no TradeAnalytics projetado no R-Forge. Você encontrará fóruns e código-fonte que ajudaram a inspirar este livro.


Eu também recomendo que você leia as apresentações de Guy Yollin no backtesting, bem como a apresentação do Quantstrat usando Jan Humme e Brian Peterson.


Este livro não se destina a substituir nenhum dos recursos existentes em estratégias de backtesting em R. Em vez disso, a intenção é aprimorar e agilizar esses recursos. Se algo não for abordado neste livro, leia as apresentações acima.


Além disso, este livro é de código aberto. Qualquer pessoa é bem-vinda a contribuir. Você pode encontrar o código fonte disponível na minha conta do Github.


1.2 Bibliotecas.


A única biblioteca necessária necessária para executar estratégias de teste é quantstrat. Quantstrat irá carregar todas as bibliotecas adicionais necessárias.


Esta versão do quantstrat inclui os seguintes pacotes, entre outros:


Com essas bibliotecas, teremos tudo o que precisamos para testar completamente as estratégias e medir o desempenho. Consulte 1.3 SessionInfo para obter mais detalhes.


Bibliotecas adicionais que podemos usar para análise ou apresentação de livros:


Estratégias de Backtesting com R.


Continuaremos usando uma variação da estratégia de Luxor. Desta vez, vamos implementar ordens stop-loss.


Também vamos manter todas as nossas configurações em variáveis ​​de modo a tornar o código mais fácil de trabalhar a partir daqui para a frente.


8.1 Adicionar indicadores.


8.2 Adicionar sinais.


8.3 Adicionar regras.


Nossas regras são em grande parte as mesmas que estavam em nossa estratégia original de Luxor. No entanto, adicionamos algumas pequenas modificações.


Vamos começar com osFUN, que é abreviado para a função de tamanho da ordem. É definido como:


função ou descritor de texto da função a ser usada para o dimensionamento da ordem.


O valor padrão para este parâmetro é osNoOp, que é uma função de pedido que não executa nenhuma operação. Em outras palavras, se você passar 100 como pedido o que é comprado.


Na regra EnterLong abaixo, passamos uma função diferente, osMaxPos (). OsMaxPos () funciona com addPosLimit () (próxima seção) para definir uma posição máxima por símbolo. Isso nos impedirá de executar as mesmas ordens repetidamente.


Também incluímos o parâmetro orderset com um valor de "ocolong". Isso ajudará a agrupar nossas ordens longas e curtas.


Até este ponto, nossa estratégia Luxor. Stop. Loss tem sido a mesma estratégia original de Luxor. Quando tomamos uma posição longa, ficamos nele até obter um sinal curto, enxaguar e repetir.


No entanto, agora vamos colocar paradas no lugar. Desde o início, não há muito diferente das regras anteriores que adicionamos. Muitos dos parâmetros são semelhantes. Contudo, temos alguns novos.


Primeiro, criamos a regra StopLossLONG como uma regra filho da regra principal EnterLONG, parte do ordenset ocolong. Atualmente não está habilitado.


A parte crítica de StopLossLONG é o parâmetro tmult e threshold. Quando uma ordem longa é cheia de limiar e tmult trabalha em conjunto para determinar o preço stoplimit (tipo de ordem)..stoploss é multiplicado (tmult) contra o preço do pedido longo preenchido. Esse preço serve como o preço stop-loss.


Se o preço do mercado se mover abaixo de US $ 133,9868 $, a ordem StopLossLONG se torna uma ordem de mercado e a ordem Exit2SHORT é cancelada (OCO).


O mesmo se aplica a StopLossSHORT, que é filho de EnterSHORT, exceto que. stoploss é adicionado ao preço de preenchimento.


8.4 Adicionar limite de posição.


Como mencionado anteriormente ao usar osMaxPos (), devemos fornecer um limite de posição para cada símbolo, nossa estratégia está funcionando. Fazemos isso com addPosLimit. Por enquanto, o único parâmetro que aplicamos é o maxpos que definimos para. orderqty.


8.5 Habilitar regras.


Quando escrevemos StopLossLONG e StopLossSHORT desativamos-nos atribuindo habilitado = FALSE. Agora, habilitamos as duas regras definidas. Isso é muito benéfico quando você deseja testar uma estratégia versus diferentes conjuntos de regras (em vez de reescrever o código).


O rótulo pode aplicar-se a uma regra específica ou combinando o valor com todas as regras com um valor semelhante (grep). Por fornecimento "StopLoss" para rotular, estamos instruindo quantstrat para habilitar todas as nossas regras com a string "StopLoss" na etiqueta, StopLossLONG e StopLossSHORT.


Estratégias de Backtesting com R.


Começamos carregando basic_symbols () na variável de símbolos:


getSymbols () faz parte do pacote quantmod que foi carregado automaticamente quando nós colocamos quantstrat. Ele deveria ter sido instalado automaticamente quando você instala o quantstrat.


Nós enviamos uma solicitação através de getSymbols () para baixar dados. Podemos usar qualquer uma das seguintes fontes:


Para dados que não sejam ações, podemos usar:


Fonte FRED (Dados Econômicos da Reserva Federal); FRED contém dados como desemprego, PIB, taxas de tesouraria e muito mais.


OANDA é um serviço de assinatura para dados de divisas e divisas.


A primeira coisa que você observa é a mensagem de aviso. Como afirma, só aparecerá na primeira vez que você executar getSymbols () em uma nova sessão.


Símbolos: um ou um vetor de símbolos múltiplos.


src: string, nossa fonte. Neste caso, Yahoo!


index. class: POSIXct. Isso define a classe do nosso índice de objetos xts.


de: string, primeira data dos dados que queremos recuperar.


fim: string, última data de dados que queremos recuperar.


ajustar: booleano, seja para ajustar nossos dados ou não. Sugerido para definir como VERDADEIRO.


getSymbols irá carregar objetos xts para cada um dos símbolos que passamos para o nosso ambiente global. Podemos visualizar os dados como faria com qualquer outro conjunto de dados.


Acessamos dados do Google como Yahoo! apenas alterando o parâmetro src.


Para carregar dados através do banco de dados MySQL, precisamos fornecer parâmetros adicionais: dbname, usuário, senha e host. O usuário precisa ter privilégios SELECT, mas nada mais para nossos propósitos.


getSymbols () atualmente não permite a passagem de valores de banco de dados através de um arquivo my. cnf. Os parâmetros são verificados no início da função, então você precisa incluí-los na chamada ou incluí-los em um arquivo R escondido fora do diretório do projeto e criar o arquivo.


Seu banco de dados deve conter uma tabela chamada por símbolo, uma para cada símbolo. Cada tabela deve ter os seguintes campos: data, o, h, l, c, v e a. Se sua tabela tiver nomes de campos diferentes, você deve adicioná-los ao parâmetro db. fields como um vetor de caracteres.


Você também pode alterar os nomes dos campos conforme eles são importados para R usando o parâmetro field. names. No entanto, nada disso é necessário, desde que db. fields atenda aos critérios padrão.


Os dados no meu banco de dados são uma duplicação do Yahoo !. A saída abaixo é mostrar o sucesso da chamada getSymbols (src = & quot; MySQL & quot;).


Para este exemplo, nós furaremos nos símbolos que usamos anteriormente. O FRED contém mais de 11.000 conjuntos de dados econômicos sem nenhum custo.


Vejamos a Taxa de Tesouraria de 10 anos:


Observe que a cauda da url tem a string alfanumérica DGS10 que usaremos em nossa chamada getSymbols ().


Observe que nossa ligação é menor do que a anterior; não precisamos classificar o índice nem precisamos ajustar os dados.


Além disso, passar parâmetros de dados não parece fazer nada; Todo o conjunto de dados é retornado.


Eu usarei quantmod :: chartSeries () para traçar os dados:


Estratégias de Backtesting com R.


Vamos começar com uma variação da estratégia de negociação de Luxor. Esta estratégia usa dois indicadores SMA: SMA (10) e SMA (30).


Se o indicador SMA (10) for maior ou igual ao indicador SMA (30), enviaremos uma ordem longa stoplimit para abrir e fechar quaisquer posições curtas que possam estar abertas. Se o SMA (10) for menor que o SMA (30), enviaremos uma ordem curta stoplimit para abrir e fechar quaisquer posições longas abertas.


Nota: Lembre-se de que já estabelecemos algumas variáveis ​​no início do livro. Se você copiar e colar o código abaixo por si mesmo, você receberá erros. Haverá tutoriais completos listados mais tarde no livro.


5.1 Configuração de Estratégia.


Carregamos nossos símbolos em símbolos.


Depois de carregarmos nossos símbolos, usamos o FinancialInstrument :: stock () para definir os meta-dados para nossos símbolos. Neste caso, estamos definindo a moeda em USD (dólares americanos) com um multiplicador de 1. O multiplicador é aplicado ao preço. Isso variará de acordo com o instrumento financeiro em que você está trabalhando, mas para ações deve ser sempre 1.


Em seguida, vamos atribuir nomes próprios para nossos objetos de portfólio, conta e estratégia. Estes podem ser qualquer nome que você deseja e deve ser baseado em como você pretende registrar os dados mais tarde.


Removemos os resíduos das corridas anteriores, eliminando os valores da carteira e da conta. Neste ponto, o que fizemos até agora é desnecessário. No entanto, é um bom hábito incluir isso com todos os seus scripts, pois os dados armazenados na memória podem afetar os resultados ou gerar erros.


Agora, inicializamos nosso portfólio, conta e pedidos. Também armazenamos nossa estratégia para economizar para mais tarde.


5.2 Adicionar indicadores.


Os indicadores são funções usadas para medir uma variável. Um SMA é apenas uma média dos preços anteriores; tipicamente preço de fechamento. Portanto, a SMA (10) é apenas uma média dos últimos 10 preços de fechamento.


Este é o lugar onde a biblioteca TTR entra; abreviação de Regras de Negociação Técnicas. SMA () é uma função da TTR, assim como muitos outros indicadores. Se você quer MACD, RSI, Bollinger Bands, etc., você usará a biblioteca TTR.


add. indicator é uma função do quantstrat e adiciona nossos indicadores ao nosso objeto de estratégia. Por enquanto, usaremos os seguintes parâmetros:


estratégia: ao armazenar nosso nome de estratégia na variável strategy. st tudo o que precisamos fazer é passar essa variável. Caso contrário, forneceríamos uma string. Use variáveis ​​quando isso se tornará redundante à medida que nos movemos.


Nome: função de indicador; para este exemplo, SMA. Nós apenas passamos o nome da função como uma seqüência de caracteres. Parâmetros para a função são passados ​​para o parâmetro de argumentos ...


argumentos: se olharmos? SMA, vemos os parâmetros necessários são x e n com o n padrão sendo 10. x é o objeto de preço. No nosso exemplo, estamos usando preços de fechamento.


etiqueta: rótulo da variável que será adicionada ao nosso conjunto de dados. Isso deve ser exclusivo para cada indicador que adicionamos.


Vamos pausar por um momento e examinar os argumentos. Observe que estamos passando uma série de funções para x. Se você quisesse acessar a variável Fechar do conjunto de dados IWM, você normalmente faria isso, ligando para IWM $ Close ou IWM [, 4]. Aqui estamos acessando um objeto de dados mktdata.


mktdata é um conjunto de dados especial criado para cada símbolo que irá armazenar todos os nossos indicadores e sinais. Quando a estratégia é executada, você verá o objeto mktdata em seu ambiente. Só existirá para o último símbolo, a estratégia executada.


A função add. indicator () (juntamente com add. signal e add. rules que discutiremos momentaneamente) não é avaliada até que executem nossa estratégia. Tudo o que faz é adicionar nossas especificações ao objeto de estratégia. Quando executamos nossa estratégia, o objeto mktdata é criado para cada iteração de símbolos em que nossos dados serão adicionados.


Cl é realmente curto para Close como você pode ter adivinhado. Na verdade, temos várias funções de mão curta para nossas variáveis:


OpCl (): Abrir e fechar (conjunto de dados n x 2)


HLC (): alto, baixo e fechado (conjunto de dados n x 3)


Veja a ajuda para qualquer um desses símbolos acima para uma listagem mais detalhada.


quote () é uma função R que simplesmente envolve o parâmetro fornecido entre aspas.


Então, adicionamos dois indicadores ao nosso objeto mktdata, nFast (SMA (10)) e nSlow (SMA (30)). Vamos agora adicionar sinais.


5.3 Adicionar sinais.


Os sinais são um valor dado quando as condições são atendidas por nossos indicadores. Por exemplo, nesta estratégia, queremos um sinal sempre que nFast seja maior ou igual a nSlow. Nós também queremos outro sinal onde nFast é menor do que nSlow. Vamos nomear estes sinais longos e curtos, respectivamente.


Mais uma vez, estamos passando strategy. st para o parâmetro de estratégia. O nome toma uma função assim como ocorreu no add. indicator. Aqui vamos usar algumas funções de Quantstrat embutidas. Vamos dar uma olhada no que está disponível:


sigComparison: booleano, compare duas variáveis ​​por relação gt maior que lt inferior a eq igual a gte maior ou igual a lte menor ou igual a.


sigCrossover: booleano, VERDADEIRO quando um sinal cruza outro. Usa os mesmos relacionamentos como sigComparison.


sigFormula: aplique uma fórmula para múltiplas variáveis.


sigPeak: identifique mínimos locais ou máximos de um indicador.


sigThreshold: booleano, quando um indicador cruza um valor. Usa relacionamentos como identificados acima.


sigTimestamp: gera um sinal com base em um timestamp.


Nós tentaremos usar cada um desses sinais ao longo do livro quando possível.


5.4 Adicionar regras.


Nós construímos agora nossos indicadores nFast e nSlow e geramos sinais baseados nesses indicadores. Agora, temos que adicionar regras para esses sinais.


add. rules determinará as posições que tomamos, dependendo dos nossos sinais, que tipo de ordem vamos colocar e quantos compartilhamentos compraremos.


Sempre que nossa variável longa (sigcol) é TRUE (sigval), queremos colocar uma ordem stoplimit (tipo de ordem). Nossa preferência está no limite superior (preferir) mais. Queremos comprar 100 ações (orderqty). Uma nova variável EnterLONG será adicionada ao mktdata. Quando entramos (digitar), uma posição EnterLONG será VERDADEIRA, caso contrário FALSO. Este pedido não substituirá quaisquer outras ordens abertas.


Se a nossa variável curta (sigcol) for TRUE (sigval), colocamos outra ordem stoplimit (tipo de ordem) com uma preferência no Low (preferir). Vamos vender 100 ações (orderqty). Este pedido não substituirá nenhuma ordem aberta (substituir).


Agora temos regras configuradas para inserir posições com base nos nossos sinais. No entanto, não temos regras para sair de posições abertas. Vamos criar esses agora.


Nossa próxima regra, Exit2SHORT, é uma ordem de mercado simples para sair (tipo) quando breve é ​​VERDADEIRO (sigcol, sigval). Isso encerra todas as posições longas (orderside, orderqty). Este pedido irá substituir (substituir) quaisquer ordens abertas.


Por fim, fechamos as posições curtas (ordens) quando há tempo é VERDADEIRO (sigcol, sigval). Nós sairemos (tipo) ao preço de mercado (tipo de ordem) todas as posições abertas (orderqty). Este pedido irá substituir quaisquer ordens abertas que possamos (substituir).


TxnFees são taxas de transação associadas a um pedido. Isso pode ser qualquer valor que você escolher, mas deve refletir com precisão as taxas cobradas pelo corretor selecionado. Além disso, mostramos apenas aqui as saídas. Alguns corretores cobram taxas em posições de entrada também. TxnFees pode ser adicionado a qualquer conjunto de regras.


Se você não tem certeza de quais taxas o corretor selecionado cobra - o que há de errado com você? Vá descobrir agora. Alguns corretores de varejo (TD Ameritrade, ETrade) cobrará menos de US $ 10 por posição em ações ilimitadas; alguns como Interactive Brokers ou TradeStation cobrará ainda menos dependendo do número de ações. $ 10 é um bom ponto de partida.


5.5 Aplicar estratégia.


Agora chegamos à parte divertida! Faz ou morre. Aqui vamos descobrir se nós construímos nossa estratégia corretamente ou se temos algum erro em nosso código. Cruze seus dedos. Vamos!


Impressionante! Sabemos que pelo menos o nosso código é bom.


applyStrategy () é a função que vamos executar quando tivermos uma estratégia direta. O que quero dizer com isso é uma estratégia que não testa parâmetros diferentes. Chegaremos a esse tipo de teste mais tarde.


Você pode ver que é uma chamada muito simples; Nós apenas passamos nossa variável strategy. st como o primeiro parâmetro e nosso portfólio como o segundo parâmetro. Não há necessidade de entrar em parâmetros adicionais no momento.


Não mostraremos os resultados de mais corridas de applyStrategy para economizar espaço. Basta saber que, se você obtiver saída de comércio, você deveria estar bem.


Em seguida, atualizamos nosso portfólio e objetos de conta. Fazemos isso com as funções updatePortf (), updateAcct () e updateEndEq (). updatePortf calcula o P & amp; L para cada símbolo nos símbolos. updateAcct calcula o patrimônio dos dados do portfólio. E updateEndEq atualiza o patrimônio final para a conta. Eles devem ser chamados em ordem.


Estratégias de Backtesting com R.


Neste livro, usamos a versão da biblioteca Quantstrat 0.9.1739. Quantstrat fornece as funções básicas que usaremos para construir nossas estratégias; adicionando indicadores, sinais e criando as regras de quando comprar e quando vender.


Quantstrat é para estratégias de negociação baseadas em sinais, não baseadas no tempo. No entanto, você pode criar funções que adicionam sinais com base em prazos e implementam essas funções como indicadores. Chegaremos a isso mais tarde.


Quantstrat também nos permite testar uma estratégia em um ou vários símbolos. A desvantagem de usar muitos símbolos é que pode ser bastante intensivo em recursos. Também podemos testar estratégias com uma variedade de parâmetros. Digamos, por exemplo, que você deseja testar uma estratégia SMA simples, mas queira encontrar o parâmetro SMA mais performante; Quantstrat permite isso. Novamente, porém, pode ser muito intensivo em recursos.


3.1 Configurações e variáveis.


As configurações listadas aqui serão usadas em todos os nossos backtestes. Eles são necessários; você receberá erros se você executar qualquer uma das estratégias sem incluir as configurações e variáveis ​​abaixo. Alguns podem mudar dependendo da estratégia que será anotada.


Primeiro, usamos Sys. setenv () para configurar o nosso fuso horário para UTC.


Em seguida, uma vez que vamos trabalhar com ações no mercado americano, precisamos definir o nosso objeto monetário em USD.


Quando estratégias de backtesting você deve sempre incluir períodos de turbulência no mercado. Afinal, você não quer apenas ver como sua estratégia funciona quando o mercado é forte, mas também quando é fraco. Para este livro, usaremos os anos de 2008 e 2009.


init_date: a data em que inicializaremos nossa conta e objetos de portfólio. Esta data deve ser o dia anterior ao início_dado.


start_date: Primeira data de dados para recuperar.


end_date: Última data de dados para recuperar.


init_equity: Equidade da conta inicial.


ajuste: booleano - VERDADEIRO se devemos ajustar os preços de pagamentos de dividendos, divisões de ações, etc. caso contrário, FALSO.


Você deve sempre trabalhar com preços ajustados quando possível para lhe dar os resultados mais verdadeiros.


3.2 Símbolos.


A maioria das nossas estratégias usará três ETFs: IWM, QQQ e SPY. Isso é apenas para fins de demonstração. Eles são carregados em basic_symbols ().


Onde podemos querer testar estratégias em uma escala ligeiramente mais amanha, usaremos enhanced_symbols () que adiciona o XLB XLX, XLE, XLF, XLI, XLK, XLP, XLU, XLV e XLY de base_symbols (), TLT e Sector SPDR ETF.


Por fim, podemos usar global_symbols () para uma melhor visão de uma estratégia. No entanto, os propósitos deste livro são mostrar como estratégias de backtest, não para encontrar estratégias rentáveis.


3.3 checkBlotterUpdate ()


A função checkBlotterUpdate () vem cortesia de Guy Yollin. O objetivo desta função é verificar se há discrepâncias entre o objeto da conta e o objeto do portfólio. Se a função retornar FALSE, devemos examinar por que (talvez não tivéssemos esvaziado nossos objetos antes de executar a estratégia?).

Комментариев нет:

Отправить комментарий