Sunday, 25 March 2018

Sinais comerciais de python


18.8. sinal - Definir manipuladores para eventos assíncronos
Este módulo fornece mecanismos para usar manipuladores de sinal em Python.
18.8.1. Regras gerais
A função sign. signal () permite a definição de manipuladores personalizados a serem executados quando um sinal é recebido. Um pequeno número de manipuladores padrão são instalados: SIGPIPE é ignorado (portanto, erros de gravação em pipes e sockets podem ser relatados como exceções Python comuns) e SIGINT é traduzido para uma exceção KeyboardInterrupt.
Um manipulador para um sinal específico, uma vez definido, permanece instalado até que ele seja redefinido explicitamente (o Python emula a interface de estilo BSD, independentemente da implementação subjacente), com exceção do manipulador do SIGCHLD, que segue a implementação subjacente.
18.8.1.1. Execução de manipuladores de sinal Python
Um manipulador de sinal Python não é executado dentro do manipulador de sinal de baixo nível (C). Em vez disso, o manipulador de sinal de nível baixo define um sinalizador que informa a máquina virtual para executar o manipulador de sinal Python correspondente em um ponto posterior (por exemplo, na próxima instrução bytecode). Isso tem conseqüências:
Não faz sentido capturar erros síncronos como SIGFPE ou SIGSEGV causados ​​por uma operação inválida no código C. O Python retornará do manipulador de sinal para o código C, o que provavelmente aumentará o mesmo sinal novamente, fazendo com que o Python aparentemente fique pendurado. A partir do Python 3.3, você pode usar o módulo faulthandler para informar sobre erros síncronos. Um cálculo de longo prazo implementado puramente em C (como a correspondência de expressões regulares em um grande corpo de texto) pode ser executado ininterruptamente por uma quantidade arbitrária de tempo, independentemente de qualquer sinal recebido. Os manipuladores de sinal Python serão chamados quando o cálculo terminar.
18.8.1.2. Sinais e threads
Os manipuladores de sinal Python são sempre executados no segmento principal do Python, mesmo que o sinal tenha sido recebido em outro segmento. Isso significa que os sinais não podem ser usados ​​como uma comunicação inter-thread. Você pode usar as primitivas de sincronização do módulo de encadeamento em vez disso.
Além disso, apenas o segmento principal é permitido configurar um novo manipulador de sinal.
18.8.2. Conteúdo do módulo
Alterado na versão 3.5: sinal (SIG *), manipulador (SIG_DFL, SIG_IGN) e sigmask (SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK) constantes relacionadas listadas abaixo foram transformadas em enums. As funções getignal (), pthread_sigmask (), sigpending () e sigwait () retornam enums legíveis por humanos.
As variáveis ​​definidas no módulo de sinal são:
Esta é uma das duas opções de tratamento de sinal padrão; Simplesmente executará a função padrão para o sinal. Por exemplo, na maioria dos sistemas, a ação padrão para o SIGQUIT é despejar o núcleo e sair, enquanto a ação padrão para o SIGCHLD é simplesmente ignorá-lo.
Este é outro manipulador de sinal padrão, que simplesmente ignorará o sinal fornecido.
Todos os números de sinal são definidos simbolicamente. Por exemplo, o sinal de interrupção é definido como signal. SIGHUP; os nomes das variáveis ​​são idênticos aos nomes usados ​​nos programas C, conforme encontrado em & lt; signal. h & gt; . A página de manual do Unix para "sinal" (")" lista os sinais existentes (em alguns sistemas, isso é sinal (2), em outros a lista está no sinal (7)). Observe que nem todos os sistemas definem o mesmo conjunto de nomes de sinais; Somente os nomes definidos pelo sistema são definidos por este módulo.
O sinal correspondente ao evento de tecla Ctrl + C. Este sinal só pode ser usado com os. kill ().
Novo na versão 3.2.
O sinal correspondente ao evento de tecla Ctrl + Break. Este sinal só pode ser usado com os. kill ().
Novo na versão 3.2.
Mais do que o número do número de sinal mais alto.
Decrementa o temporizador de intervalo em tempo real e entrega SIGALRM após a expiração.
Decrementa o temporizador de intervalo apenas quando o processo está sendo executado e entrega SIGVTALRM após a expiração.
Decrementa o temporizador de intervalo tanto quando o processo é executado quanto quando o sistema está executando em nome do processo. Juntamente com ITIMER_VIRTUAL, este temporizador geralmente é usado para perfilar o tempo gasto pelo aplicativo no usuário e no espaço do kernel. SIGPROF é entregue no vencimento.
Um possível valor para o parâmetro como pthread_sigmask () indicando que os sinais devem ser bloqueados.
Novo na versão 3.3.
Um possível valor para o parâmetro como pthread_sigmask () indicando que os sinais devem ser desbloqueados.
Novo na versão 3.3.
Um valor possível para o parâmetro como pthread_sigmask () indicando que a máscara de sinal deve ser substituída.
Novo na versão 3.3.
O módulo de sinal define uma exceção:
sinal de exceção. ItimerError В¶
Criado para sinalizar um erro da implementação subjacente do setitimer () ou getitimer (). Espere esse erro se um temporizador de intervalo inválido ou um tempo negativo for passado para setitimer (). Este erro é um subtipo de OSError.
Novo na versão 3.3: Este erro costumava ser um subtipo de IOError, que agora é um alias do OSError.
O módulo de sinal define as seguintes funções:
Se o tempo for diferente de zero, esta função solicita que um sinal SIGALRM seja enviado ao processo em segundos de tempo. Qualquer alarme programado anteriormente é cancelado (apenas um alarme pode ser agendado a qualquer momento). O valor retornado é então o número de segundos antes de qualquer alarme previamente configurado ter sido entregue. Se o tempo for zero, nenhum alarme será programado e qualquer alarme agendado será cancelado. Se o valor de retorno for zero, nenhum alarme está agendado no momento. (Consulte o ícone da página do Unix man (2).) Disponibilidade: Unix.
sinal. getignal (signalnum) В¶
Retornar o controlador de sinal atual para o sinal de sinal. O valor retornado pode ser um objeto Python ou um sinal de valores especiais. SIG_IGN, sinal. SIG_DFL ou Nenhum. Aqui, o sinal. SIG_IGN significa que o sinal foi anteriormente ignorado, o sinal. SIG_DFL significa que a maneira padrão de manipular o sinal estava anteriormente em uso, e Nenhum significa que o manipulador de sinal anterior não estava instalado no Python.
Faça com que o processo durma até que um sinal seja recebido; O processador apropriado será então chamado. Não retorna nada. Não está no Windows. (Veja o sinal da página Man do Unix (2).)
sinal. pthread_kill (thread_id, signalnum) В¶
Envie o sinal de sinal para o thread thread_id, outro segmento no mesmo processo que o chamador. O thread de destino pode estar executando qualquer código (Python ou não). No entanto, se o thread de destino estiver executando o interpretador Python, os manipuladores de sinal Python serão executados pelo segmento principal. Portanto, o único ponto de enviar um sinal para um segmento particular de Python seria forçar uma chamada do sistema em execução para falhar com InterruptedError.
Use threading. get_ident () ou o atributo ident do threading. Thread objetos para obter um valor adequado para thread_id.
Se signalnum for 0, então nenhum sinal é enviado, mas a verificação de erros ainda é realizada; Isso pode ser usado para verificar se o segmento de destino ainda está em execução.
Disponibilidade: Unix (veja a página man pthread_kill (3) para obter mais informações).
Novo na versão 3.3.
Procure e / ou altere a máscara de sinal da linha de chamada. A máscara de sinal é o conjunto de sinais cuja entrega está atualmente bloqueada para o chamador. Retorne a máscara de sinal antiga como um conjunto de sinais.
O comportamento da chamada depende do valor de como, da seguinte forma.
SIG_BLOCK: O conjunto de sinais bloqueados é a união do conjunto atual e o argumento da máscara. SIG_UNBLOCK: Os sinais na máscara são removidos do conjunto atual de sinais bloqueados. É permitido tentar desbloquear um sinal que não está bloqueado. SIG_SETMASK: O conjunto de sinais bloqueados é definido como o argumento da máscara.
máscara é um conjunto de números de sinal (por exemplo). Use o intervalo (1, sinal. NSIG) para uma máscara completa incluindo todos os sinais.
Por exemplo, signal. pthread_sigmask (signal. SIG_BLOCK, []) lê a máscara de sinal do fio de chamada.
Disponibilidade: Unix. Veja a página manual sigprocmask (3) e pthread_sigmask (3) para obter mais informações.
Novo na versão 3.3.
Define o temporizador de intervalo (um de sinal. ITIMER_REAL, sinal. ITIMER_VIRTUAL ou signal. ITIMER_PROF) especificado pelo qual disparar após segundos (flutuante é aceito, diferente do alarme ()) e depois disso todos os segundos do intervalo. O temporizador de intervalo especificado pelo qual pode ser apagado ajustando segundos a zero.
Quando um temporizador de intervalo dispara, um sinal é enviado para o processo. O sinal enviado depende do temporizador que está sendo usado; sinal. ITIMER_REAL entregará SIGALRM, signal. ITIMER_VIRTUAL envia SIGVTALRM e signal. ITIMER_PROF entregará SIGPROF.
Os valores antigos são retornados como uma tupla: (atraso, intervalo).
A tentativa de passar por um temporizador de intervalo inválido causará um ItimerError. Disponibilidade: Unix.
Retorna o valor atual de um determinado temporizador de intervalo especificado pelo qual. Disponibilidade: Unix.
sinal. set_wakeup_fd (fd) В¶
Defina o descritor do arquivo de ativação para fd. Quando um sinal é recebido, o número do sinal é escrito como um único byte no fd. Isso pode ser usado por uma biblioteca para ativar uma pesquisa ou selecionar chamada, permitindo que o sinal seja totalmente processado.
O despertador antigo fd é retornado (ou -1 se o despertador do descritor de arquivo não estiver ativado). Se fd for -1, o despertador do descritor de arquivo está desabilitado. Se não -1, fd não deve ser bloqueado. Depende da biblioteca remover todos os bytes da fd antes de fazer uma pesquisa ou selecionar novamente.
Use, por exemplo, struct. unpack ('% uB'% len (dados), dados) para decodificar a lista de números de sinal.
Quando os tópicos são habilitados, esta função só pode ser chamada a partir do segmento principal; tentar chamá-lo de outros tópicos fará com que uma exceção ValueError seja gerada.
Alterado na versão 3.5: no Windows, a função agora também suporta alças de soquete.
Alterar o comportamento do reinício da chamada do sistema: se o sinalizador for Falso, as chamadas do sistema serão reiniciadas quando interrompidas pelo sinal de sinal, caso contrário, as chamadas do sistema serão interrompidas. Não retorna nada. Disponibilidade: Unix (veja a página man siginterrupt (3) para mais informações).
Observe que a instalação de um manipulador de sinal com o sinal () irá redefinir o comportamento de reinicialização para interrupível ao chamar implicitamente siginterrupt () com um valor de sinalizador verdadeiro para o sinal fornecido.
Defina o manipulador para sinal de sinalização para o manipulador de função. o manipulador pode ser um objeto Python chamado que leva dois argumentos (veja abaixo), ou um dos valores especiais de sinal. SIG_IGN ou sinal. SIG_DFL. O manipulador de sinal anterior será retornado (veja a descrição de getignal () acima). (Veja o sinal da página Man do Unix (2).)
Quando os tópicos são habilitados, esta função só pode ser chamada a partir do segmento principal; tentar chamá-lo de outros tópicos fará com que uma exceção ValueError seja gerada.
O manipulador é chamado com dois argumentos: o número do sinal e o quadro da pilha atual (Nenhum ou um objeto do quadro, para uma descrição dos objetos do quadro, veja a descrição na hierarquia de tipos ou veja as descrições dos atributos no módulo de inspeção).
No Windows, o sinal () só pode ser chamado com SIGABRT, SIGFPE, SIGILL, SIGINT, SIGSEGV, SIGTERM ou SIGBREAK. Um ValueError será gerado em qualquer outro caso. Observe que nem todos os sistemas definem o mesmo conjunto de nomes de sinais; um AttributeError será aumentado se um nome de sinal não for definido como o nível do módulo SIG * constante.
Examine o conjunto de sinais que estão pendentes para entrega ao segmento de chamada (ou seja, os sinais que foram levantados enquanto bloqueados). Retornar o conjunto dos sinais pendentes.
Disponibilidade: Unix (veja a página man sigpending (2) para mais informações).
Novo na versão 3.3.
Suspenda a execução do fio de chamada até a entrega de um dos sinais especificados no sigset do sinal. A função aceita o sinal (remove-o da lista pendente de sinais) e retorna o número do sinal.
Disponibilidade: Unix (veja a página man sigwait (3) para mais informações).
Novo na versão 3.3.
Suspenda a execução do fio de chamada até a entrega de um dos sinais especificados no sigset do sinal. A função aceita o sinal e o remove da lista pendente de sinais. Se um dos sinais em sigset já estiver pendente para o segmento de chamada, a função retornará imediatamente com informações sobre esse sinal. O manipulador de sinal não é chamado para o sinal entregue. A função eleva um InterruptedError se for interrompido por um sinal que não esteja em sigset.
O valor de retorno é um objeto que representa os dados contidos na estrutura siginfo_t, a saber: si_signo, si_code, si_errno, si_pid, si_uid, si_status, si_band.
Disponibilidade: Unix (veja a página man sigwaitinfo (2) para mais informações).
Novo na versão 3.3.
Alterado na versão 3.5: a função agora é tentada novamente se interrompida por um sinal que não está em sigset e o manipulador de sinal não levanta uma exceção (ver PEP 475 para o raciocínio).
Como sigwaitinfo (), mas demora um timeout adicional que especifica um tempo limite. Se o tempo limite for especificado como 0, uma pesquisa será realizada. Retorna Nenhum se ocorrer um tempo limite.
Disponibilidade: Unix (veja a página man sigtimedwait (2) para mais informações).
Novo na versão 3.3.
Alterado na versão 3.5: a função agora é reiniciada com o tempo limite recalculado, se interrompido por um sinal que não está em sigset e o manipulador de sinal não levanta uma exceção (ver PEP 475 para o raciocínio).
18.8.3. Exemplo ¶
Aqui está um programa de exemplo mínimo. Ele usa a função de alarme () para limitar o tempo gasto para abrir um arquivo; Isso é útil se o arquivo for para um dispositivo serial que pode não ser ativado, o que normalmente causaria o os. open () para travar indefinidamente. A solução é configurar um alarme de 5 segundos antes de abrir o arquivo; Se a operação demorar muito, o sinal de alarme será enviado e o manipulador levará uma exceção.
Índice.
Tópico anterior.
Próximo tópico.
Navegação.
O Python Software Foundation é uma corporação sem fins lucrativos. Por favor doe.

QuantStart.
Junte-se ao portal de membros privados da Quantcademy que atende à comunidade de comerciantes de varejo de varejo em rápido crescimento. Você encontrará um grupo bem informado de mentalistas quant pronto para responder suas perguntas comerciais mais importantes.
Confira meu ebook sobre o comércio de quant, onde eu ensino você como criar estratégias de negociação sistemáticas lucrativas com ferramentas Python, desde o início.
Dê uma olhada no meu novo ebook sobre estratégias de negociação avançadas usando análise de séries temporais, aprendizado de máquina e estatísticas bayesianas, com Python e R.
Por Michael Halls-Moore em 21 de janeiro de 2014.
No artigo anterior sobre Ambientes de Análise de Análise de Pesquisa Em Python Com Pandas, criamos um ambiente de backtesting baseado em pesquisa orientado a objetos e testávamos isso 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, ou seja, o Crossover de média móvel na AAPL.
Estratégia de Crossover Média em Movimento.
A técnica de Crossover de média móvel é uma estratégia de impulso simplista extremamente conhecida. Muitas vezes, é considerado o exemplo do "Olá Mundo" para negociação quantitativa.
A estratégia descrita aqui é longa apenas. São criados dois filtros de média móvel simples separados, com diferentes períodos de lookback, de uma série temporal específica. Os sinais para comprar o recurso ocorrem quando a média móvel de lookback mais curta excede a média móvel de lookback mais longa. Se a média mais longa exceder a média mais curta, o ativo é vendido de volta. A estratégia funciona bem quando uma série temporal entra em um período de forte tendência e, em seguida, inverte lentamente a tendência.
Para este exemplo, escolhi a Apple, Inc. (AAPL) como a série temporal, com um curto lookback de 100 dias e um longo lookback de 400 dias. Este é o exemplo fornecido pela biblioteca de negociação algorítmica de tirolesa. Assim, se quisermos implementar o nosso próprio backtester, precisamos garantir que ele coincida com os resultados na linha aérea, 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 particular usei as seguintes bibliotecas:
A implementação do ma_cross. py requer backtest. py do tutorial anterior. O primeiro passo é importar os módulos e objetos necessários:
Como no tutorial anterior, vamos sub-classificar a classe base abstrata da Estratégia para produzir MovingAverageCrossStrategy, que contém todos os detalhes sobre como gerar os sinais quando as médias móveis da AAPL se cruzam.
O objeto requer um short_window e um long_window sobre o qual operar. Os valores foram configurados para padrões de 100 dias e 400 dias, respectivamente, que são os mesmos parâmetros utilizados no exemplo principal de tirolesa.
As médias móveis são criadas usando a função pandas rolling_mean nas barras ['Fechar'] preço de fechamento do estoque da AAPL. Uma vez que as médias móveis individuais foram construídas, a série do sinal é gerada definindo a coluna igual a 1,0 quando a média móvel curta é maior do que a média móvel longa, ou 0,0 caso contrário. A partir disso, as ordens de posições podem ser geradas para representar sinais comerciais.
O MarketOnClosePortfolio é subclassado do Portfolio, que é encontrado em backtest. py. É quase idêntico à implementação descrita no tutorial anterior, com a exceção de que os negócios são agora realizados em uma base Close-to-Close, em vez de Open-to-Open. Para obter detalhes sobre como o objeto Portfolio está definido, consulte o tutorial anterior. Eu deixei o código em completo e mantenho esse tutorial autônomo:
Agora que as classes MovingAverageCrossStrategy e MarketOnClosePortfolio foram definidas, uma função __main__ será chamada para amarrar toda a funcionalidade em conjunto. Além disso, o desempenho da estratégia será examinado através de um gráfico da curva de equidade.
O objeto DataReader de pandas transfere os preços de ações da AAPL da OHLCV 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 de longo tempo. Posteriormente, o portfólio é gerado com uma base de capital inicial de 100.000 USD e os retornos são calculados na curva de patrimônio.
O passo final é usar matplotlib para plotar um gráfico de dois dígitos de ambos os preços da AAPL, superado com as médias móveis e os sinais de compra / venda, bem como a curva de equidade com os mesmos sinais de compra / venda. O código de plotagem é tomado (e modificado) do exemplo de implementação de tirolesa.
A saída gráfica do código é a seguinte. Utilizei o comando IPython% paste para colocar isso diretamente no console IPython, enquanto no Ubuntu, de modo que a saída gráfica permaneça em exibição. Os roseticks cor-de-rosa representam a compra do estoque, enquanto os bastões negros representam a venda de volta:
AAPL Moving Average Crossover Performance de 1990-01-01 a 2002-01-01.
Como pode ser visto, a estratégia perde dinheiro ao longo do período, com cinco comércios de ida e volta. Isso não é surpreendente, dado o comportamento da AAPL durante o período, que estava em uma ligeira tendência descendente, seguido de um aumento significativo em 1998. O período de lookback dos sinais da média móvel é bastante grande e isso impactou o lucro do comércio final , o que de outra forma pode ter tornado a estratégia rentável.
Em artigos subsequentes, criaremos um meio mais sofisticado de análise de desempenho, além de descrever como otimizar os períodos de lookback dos sinais de média móvel individual.
Apenas iniciando o comércio quantitativo?
3 razões para se inscrever na QuantStart List:
1. Quant Trading Lessons.
Você terá acesso instantâneo a um curso gratuito de 10 partes, com sugestões e dicas para ajudá-lo a começar a negociação quantitativa!
2. Todo o conteúdo mais recente.
Todas as semanas, vou enviar-lhe um envoltório de todas as atividades no QuantStart para que você nunca mais perca uma postagem novamente.
Real, dicas de negociação viáveis, sem tonturas.

sinais de troca de Python
Obter através da App Store Leia esta publicação em nosso aplicativo!
Usando o Pandas DataFrame para gerar sinais de negociação.
Eu tenho dois DataFrames com os seguintes layouts:
O primeiro DataFrame é o preço das ações e as médias móveis. O segundo DataFrame contém sinais para quando comprar um estoque (entrada) e quando vender (sair).
A parte de entrada já está bem. Mas estou tendo problemas com a parte de saída.
Não faz sentido ter sinais de saída no 2008-06-26 porque nenhum estoque já foi adquirido. E não faria sentido ter um sinal de saída em 2008-06-30 e 2008-07-01 porque não podemos vender os mesmos estoques duas vezes.
Então eu tenho uma maneira de gerar sinais na coluna LONG EXIT, mas preciso filtrá-los olhando para trás de cada data para descobrir se é uma LONG ENTRY = 1 anterior e nenhuma LONG EXIT = 1 entre LONG ENTRY = 1 e a DATA que eu estou olhando.
O DataFrame que eu preciso parece assim, mas como posso fazer isso com os Pandas?
Aqui está um esboço de como você pode rastrear o saldo de seus sinais de entrada / saída para que você apenas comece a sair quando há uma entrada anterior ainda não cancelada pela saída subseqüente:
Adicione uma coluna para seus novos sinais filtrados:
Iterate através do DataFrame, calcule o balanço anterior (isso pressupõe que você não esteja sinalizando entrada e saída no mesmo dia) e filtre de acordo:
para obter o resultado desejado dado os casos que você mencionou:

QuantStart.
Junte-se ao portal de membros privados da Quantcademy que atende à comunidade de comerciantes de varejo de varejo em rápido crescimento. Você encontrará um grupo bem informado de mentalistas quant pronto para responder suas perguntas comerciais mais importantes.
Confira meu ebook sobre o comércio de quant, onde eu ensino você como criar estratégias de negociação sistemáticas lucrativas com ferramentas Python, desde o início.
Dê uma olhada no meu novo ebook sobre estratégias de negociação avançadas usando análise de séries temporais, aprendizado de máquina e estatísticas bayesianas, com Python e R.
Por Michael Halls-Moore em 16 de janeiro de 2014.
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 brevemente em qualquer instrumento livremente, sem quaisquer 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.
Apenas iniciando o comércio quantitativo?
3 razões para se inscrever na QuantStart List:
1. Quant Trading Lessons.
Você terá acesso instantâneo a um curso gratuito de 10 partes, com sugestões e dicas para ajudá-lo a começar a negociação quantitativa!
2. Todo o conteúdo mais recente.
Todas as semanas, vou enviar-lhe um envoltório de todas as atividades no QuantStart para que você nunca mais perca uma postagem novamente.
Real, dicas de negociação viáveis, sem tonturas.

No comments:

Post a Comment