Você está perdendo oportunidades de negociação:
- Aplicativos de negociação gratuitos
- 8 000+ sinais para cópia
- Notícias econômicas para análise dos mercados financeiros
Registro
Login
Você concorda com a política do site e com os termos de uso
Se você não tem uma conta, por favor registre-se
Deep Learning Trading Strategy desde o início até a produção usando TensorFlow 2.0 e TFX
Deep Learning Trading Strategy desde o início até a produção usando TensorFlow 2.0 e TFX
Tenho o prazer de me apresentar como Denis e dou as boas-vindas ao ClosetoAlgotrading, seu canal para todas as coisas relacionadas à negociação algorítmica.
Já faz algum tempo desde que a ideia surgiu em minha mente: criar uma estratégia de negociação utilizando apenas o poder do aprendizado profundo. O conceito gira em torno do desenvolvimento de uma rede neural capaz de identificar de forma autônoma os parâmetros necessários para executar negociações lucrativas. Para embarcar nesta emocionante jornada, decidi realizar um experimento ao vivo, que espero também cative o seu interesse. Nos próximos episódios, guiarei você em cada etapa envolvida na implementação de uma abordagem de ciência de dados para elaborar uma estratégia de negociação robusta, desde os estágios iniciais até a produção final.
Meu objetivo é cobrir todas as etapas intermediárias de forma abrangente, incluindo preparação de dados, testes rigorosos e muito mais. Olhando para o futuro, utilizarei o TensorFlow 2.0 e explorarei as possibilidades oferecidas pelo pipeline tfx. Pretendo evitar cálculos ou regras complexas, confiando no poder do aprendizado profundo para verificar se podemos criar um empreendimento verdadeiramente lucrativo. Se esta ideia ressoa com você, eu o encorajo a se inscrever no canal e se juntar a mim nesta expedição cativante. Juntos, navegaremos pelas reviravoltas da negociação algorítmica e nos esforçaremos para desbloquear seu potencial oculto.
Para quem tem curiosidade de se aprofundar na abordagem da ciência de dados, uma simples busca no Google renderá diversos recursos elucidando o assunto. Entre os resultados, você pode encontrar artigos informativos e representações visuais que descrevem os passos para seguir esta metodologia.
O primeiro bloco crucial em nossa jornada é a fase de entendimento do negócio. Nesta conjuntura, devemos definir meticulosamente nossas metas e estabelecer Indicadores Chave de Desempenho (KPIs) que sirvam como valores mensuráveis para avaliar a eficácia de nossa estratégia na consecução desses objetivos. Para embarcar nesta fase, é crucial dedicar tempo para compreender completamente os meandros do seu domínio de negócios específico. Ao obter uma compreensão profunda de seu alvo, você pode prosseguir com clareza e foco. É imperativo discernir se você visa prever resultados específicos ou classificar fenômenos particulares.
Para determinar a natureza de nossa tarefa, devemos buscar respostas para questões fundamentais. Se nossa investigação gira em torno de "Quanto" ou "Quanto", estamos lidando com uma tarefa de regressão. Por outro lado, se indagamos sobre "qual categoria", estamos nos aventurando no reino da classificação e assim por diante. Uma vez que entendemos o tipo de tarefa que buscamos realizar, é essencial definir as métricas que significarão o sucesso. No nosso caso, essas métricas podem incluir o retorno sobre o investimento (ROI) e a precisão. Afinal, nosso objetivo final é lucrar com o mercado, necessitando de uma compreensão firme dos movimentos futuros de preços.
Prever efetivamente o movimento futuro dos preços envolve não apenas determinar a direção, mas também identificar o nível de preço preciso e o momento em que será alcançado. No entanto, apenas saber a direção é insuficiente. Exigimos o nível de preço exato e o momento em que ele será atingido. Para evitar períodos de espera intermináveis por nosso preço-alvo, podemos definir um preço-alvo mínimo esperado e um período de espera máximo. Em outras palavras, procuramos verificar a direção dos movimentos futuros de preços, assemelhando-se a uma tarefa de classificação em que o preço pode subir, cair ou permanecer no mesmo nível.
Para medir inicialmente o desempenho do nosso modelo na previsão da direção, podemos empregar a precisão da classificação. Essa métrica quantifica o número de previsões corretas dividido pelo número total de previsões, multiplicado por 100 para expressá-lo como uma porcentagem. Agora, e quanto ao nosso nível de preço-alvo? Para nossa estratégia de negociação, podemos definir o nível de lucro como uma porcentagem de nosso capital investido. Além disso, devemos determinar nossa tolerância ao risco estabelecendo um nível de stop loss como o risco máximo aceitável para uma única negociação. Nossos níveis de lucro e stop servem como valores de ROI para cada negociação. Por exemplo, vamos supor que compramos ações a US$ 100 e as vendemos quando atingirem US$ 105. Esse movimento de preço de 5% renderia um retorno de 5% sobre nosso investimento. Com nossos níveis de saída definidos, abrangendo tanto o take profit quanto o stop-loss, devemos abordar a questão do tempo. Não queremos esperar indefinidamente que o preço atinja os níveis desejados.
Portanto, estabelecemos um período máximo de retenção, embora usando o volume negociado em vez de um período de tempo fixo. A lógica por trás dessa escolha ficará mais clara no próximo episódio, onde falarei sobre a preparação dos dados.
Para resumir nossa abordagem até agora: estamos desenvolvendo uma estratégia intradiária que emprega take profit, stop loss e um período máximo de retenção para fechar posições. Para iniciar as negociações, vamos treinar um modelo de classificação capaz de prever a direção futura do preço: alta, baixa ou estável. Inicialmente, empregaremos a precisão como medida da eficácia de nosso modelo. Com essa base estabelecida, concluímos nossa discussão de hoje. Definimos nossos objetivos, metas e métricas de desempenho. No episódio subsequente, vamos nos aprofundar em nossos dados, preparando conjuntos de dados e rótulos para análises e desenvolvimentos posteriores.
Não perca a próxima parte da nossa jornada. Até lá, cuidem-se, e aguardo ansiosamente nosso próximo encontro.
Deep Learning Trading Strategy desde o início até a produção. Parte II.
Deep Learning Trading Strategy desde o início até a produção. Parte II.
Tenho o prazer de recebê-lo na segunda parte de nossa jornada cativante na criação de um sistema de negociação. No vídeo anterior, discutimos nossos objetivos e hoje vamos nos concentrar em preparar e rotular nosso conjunto de dados. Então vamos mergulhar de cabeça!
Para começar, defini um conjunto de funções que nos ajudará na preparação do conjunto de dados. Em primeiro lugar, precisamos carregar nossos dados. Para a demonstração de hoje, usarei um pequeno conjunto de dados para manter o tempo de execução do código gerenciável. Como você pode ver, o conjunto de dados compreende dados de ticks, incluindo informações como Tempo, Preço, Volume, Bid e Ask. Para o propósito desta demonstração, utilizarei dados de um período de um ano. Vamos começar examinando algumas estatísticas para entender as características do conjunto de dados. Um dos principais aspectos que observamos é o preço mínimo e máximo, que gira em torno de US$ 100. Isso é vantajoso, pois permite o cálculo fácil das porcentagens de lucro.
Além disso, introduzi um parâmetro crucial no conjunto de dados: o tamanho do spread. O spread é calculado como a diferença entre os preços Ask e Bid. Por que o tamanho do spread é importante? Para ilustrar, vamos considerar um exemplo em que o preço Bid é $ 100 e o preço Ask é $ 101. Nesse caso, o spread é igual a US$ 1. Se comprássemos e vendêssemos imediatamente a ação, sempre perderíamos o spread, que, neste exemplo, equivale a US$ 1. Para obter informações sobre o tamanho do spread, calculei o spread médio de todos os dias para cada segundo. Conforme ilustrado no gráfico, o spread normalmente varia entre 1 e 2 centavos, com ocorrências ocasionais de spreads ligeiramente maiores. Com base nessa análise, podemos decidir executar negócios apenas se o spread for inferior a 3 centavos.
Curiosamente, o gráfico mostra que os maiores spreads tendem a ocorrer nos primeiros minutos após a abertura do mercado. Consequentemente, é prudente pular os 10 a 15 minutos iniciais ao implementar uma estratégia intradiária. Agora que definimos o período de tempo e examinamos o spread, podemos gerar rótulos para nosso modelo, que preverá a direção do movimento do preço. Como geramos esses rótulos? Conforme mencionado no vídeo anterior, como não temos gatilhos para abrir uma posição, precisamos gerar rótulos para cada barra com base no retorno esperado.
Para isso, empregaremos o método da janela, onde as etiquetas são geradas quando os preços cruzam as barreiras da janela. Veja como funciona: definimos uma janela de comprimento n barras e definimos barreiras de janela superiores e inferiores com base em nosso retorno esperado em porcentagem. À medida que deslizamos esta janela sobre todas as barras, com um tamanho de passo de uma barra, se o preço sair da janela, a primeira barra da janela receberá o rótulo. Antes de prosseguir com a geração da etiqueta, vamos estabelecer os parâmetros da janela. Embora a ideia por trás disso seja simples, selecionar o tamanho ideal da janela e os níveis de barreira pode ser um desafio. Pessoalmente, passei um tempo considerável lidando com esse problema e ainda não encontrei uma solução definitiva.
Para enfrentar esse desafio, calcularei a volatilidade histórica ao longo do dia e todo o conjunto de dados. Por exemplo, o gráfico apresentado ilustra a mudança de preço em cada tick dentro de um dia, junto com a volatilidade correspondente. Além disso, podemos avaliar a volatilidade em todo o conjunto de dados. Como mostrado, a volatilidade média é de apenas 0,003%, o que equivale a aproximadamente 30 centavos do preço atual. No entanto, não pretendo usar uma janela que abranja o dia inteiro. Para determinar o comprimento da janela, tentei gerar 100 janelas com tamanhos aleatórios e avaliei a volatilidade média dentro de cada janela. O gráfico resultante retrata a volatilidade média para janelas de diferentes comprimentos. Ao selecionar um tamanho de janela de 50 barras, por exemplo, podemos antecipar uma volatilidade em torno de 0,001%.
Esse valor de volatilidade torna-se útil para definir nosso retorno mínimo esperado e calcular o tamanho de nosso preço de stop loss. Com essas informações em mãos, podemos gerar barras de volume a partir de nossos dados de ticks. A utilização de barras em vez de ticks nos permite calcular o comprimento da janela com mais facilidade, pois uma barra geralmente contém um volume semelhante, garantindo condições estáveis. Para gerar uma barra de volume, iteramos pelos ticks e acumulamos o volume até que ultrapasse ou iguale um volume alvo predefinido (por exemplo, 1000). Os ticks encontrados durante esta fase de acumulação representam uma barra de volume. Vamos gerar barras de volume para um único dia como exemplo. Conforme ilustrado, obtemos 179 barras para o dia selecionado.
Consequentemente, o gráfico de preços agora consiste nessas barras de volume. Além disso, podemos calcular a variação percentual em cada barra e a volatilidade diária usando o preço de fechamento. No entanto, não pretendo utilizar uma janela que abranja o dia inteiro. Para determinar o comprimento da janela, empreguei a volatilidade média e janelas geradas aleatoriamente para todo o conjunto de dados. O gráfico resultante mostra a volatilidade da janela em todo o conjunto de dados.
Agora que concluímos essas etapas preparatórias, estamos prontos para gerar os rótulos. Para esta demonstração, escolhi um tamanho de janela de 50 barras e um retorno esperado de 0,003%, que corresponde a aproximadamente 30 centavos com base no preço médio. Após a conclusão do processo de rotulagem, podemos encontrar vários rótulos semelhantes, conhecidos como rótulos cruzados. Para evitar rótulos idênticos para eventos diferentes, reteremos apenas os rótulos com a distância mais próxima entre a primeira barra da janela e a barra onde o preço cruza a barreira da janela. Ao inspecionar, observamos que temos cerca de 700 rótulos, distribuídos uniformemente entre as três categorias (up, down e flat).
Agora, vamos salvar nosso conjunto de dados. Criaremos dois arquivos: um contendo o conjunto de dados da barra de volume e outro arquivo contendo as informações dos ticks de cada barra. O último pode ser útil em nosso modelo, então vale a pena preservá-lo. Com isso, farei uma pausa em nossa discussão por hoje. Acredito que cobrimos um amplo terreno e, para os interessados em se aprofundar na rotulagem de dados, recomendo explorar os capítulos 3 e 4 do livro de Marcos Lopez de Prado, que fornecem informações valiosas.
Nossa próxima etapa envolverá a engenharia de recursos e a execução de tudo por meio do pipeline tfx. Espero criar um novo episódio em breve para compartilhar informações mais intrigantes.
Até lá, cuidem-se, e aguardo nosso próximo vídeo.
Deep Learning Trading Strategy desde o início até a produção. Parte III. Oleoduto TFX.
Deep Learning Trading Strategy desde o início até a produção. Parte III. Oleoduto TFX.
Estou muito feliz em recebê-lo de volta para outro episódio de "Close to AlgoTrading" comigo, Denis. Retomamos nosso experimento após o feriado de Ano Novo e, embora o progresso tenha sido lento, ainda estamos avançando. No vídeo de hoje, veremos mais de perto nossos dados rotulados e exploraremos o pipeline TFX. Então, vamos mergulhar de cabeça!
No vídeo anterior, criamos rótulos com sucesso para nossos dados, mas esqueci de mostrar como eles aparecem em um gráfico. Como uma atualização rápida, armazenamos todos os dados em um novo quadro de dados. Vamos em frente e ler este quadro de dados.
Dentro de nosso quadro de dados, a coluna 'dir' contém os rótulos, enquanto a coluna 'cross_idx' representa o número do tick quando o preço cruza nossa janela definida. Para representar visualmente os eventos de posição aberta e fechada com base nessas colunas, criei uma função simples. No gráfico, um evento de posição aberta é indicado por um triângulo preenchido, enquanto um evento de posição fechada é representado por um triângulo não preenchido.
Como você pode ver, a maioria dos eventos abertos ocorre em pontos máximos ou mínimos locais no gráfico de preços. Seguindo em frente, continuaremos trabalhando com um pequeno conjunto de dados, semelhante ao que usamos anteriormente. Além disso, dividirei o conjunto de dados em conjuntos de dados de treinamento, avaliação e teste.
Agora que entendemos melhor nossos rótulos, vamos para a próxima etapa e começar a trabalhar com o pipeline TFX. Para aqueles que não estão familiarizados com TFX, significa Tensorflow Extended e é uma estrutura poderosa projetada especificamente para tarefas de aprendizado de máquina escalonáveis e de alto desempenho. O pipeline TFX consiste em uma sequência de componentes que executam vários estágios do fluxo de trabalho de aprendizado de máquina, como ingestão de dados, modelagem, treinamento, inferência de serviço e gerenciamento de implantação.
Para nos familiarizarmos com o TFX, recomendo explorar a página oficial do Tensorflow TFX, que fornece informações detalhadas sobre seus componentes e como eles estão interconectados. Você pode encontrar os links relevantes na descrição do vídeo.
Como também sou novo no TFX, aprenderemos juntos a cada episódio. Hoje, vamos nos concentrar nos primeiros quatro componentes do pipeline. Vamos apresentá-los brevemente:
ExampleGen: esse componente de entrada inicial do pipeline ingere o conjunto de dados de entrada e, opcionalmente, o divide em diferentes subconjuntos. Em nosso caso, ele não oferece suporte direto a divisões de séries temporais personalizadas, portanto, divido manualmente os dados em conjuntos de dados de treinamento, avaliação e teste.
StatisticsGen: Este componente calcula estatísticas para o conjunto de dados, fornecendo informações sobre a distribuição de dados, desvio padrão, valores ausentes e muito mais. Ele gera artefatos estatísticos para análise posterior.
SchemaGen: Depois de examinar as estatísticas, o componente SchemaGen cria um esquema de dados com base nas características dos dados observados. O esquema descreve a estrutura e as propriedades de nossos dados.
ExampleValidator: Este componente verifica anomalias e valores ausentes no conjunto de dados, usando as estatísticas e o esquema como referências. Ele ajuda a identificar quaisquer padrões de dados inesperados ou inconsistentes.
Para garantir que estamos no caminho certo, usarei o exemplo do táxi de Chicago fornecido pela equipe do Tensorflow como modelo. Este exemplo demonstra o fluxo de trabalho de ponta a ponta, incluindo análise de dados, validação, transformação, treinamento de modelo e exibição.
Agora, vamos mudar nosso foco de volta para nossos próprios dados. Depois de importar os módulos necessários e definir as variáveis necessárias para as pastas de dados de entrada e saída, podemos tentar carregar nossos dados no pipeline TFX. A pasta de entrada contém subpastas para os conjuntos de dados de avaliação, treinamento e teste.
Usando o componente ExampleGen, devemos ser capazes de carregar facilmente nossos dados no pipeline. No entanto, parece que ExampleGen não suporta diretamente divisões de séries temporais personalizadas. Por padrão, ele divide os dados apenas em conjuntos de treinamento e avaliação. Felizmente, podemos dividir manualmente os dados e configurar nossa própria configuração de divisão de entrada, garantindo um mapeamento um-para-um entre as divisões de entrada e saída.
Como resultado, o componente ExampleGen produz dois artefatos: um para o conjunto de dados de treinamento e outro para o conjunto de dados de avaliação. Vamos examinar os três primeiros elementos do nosso conjunto de treinamento para verificar se ele corresponde ao nosso conjunto de dados original. Seguindo em frente, passamos a saída do componente ExampleGen para o componente StatisticsGen. Este componente gera artefatos estatísticos para os conjuntos de dados de treinamento e avaliação. Com apenas um único comando, podemos representar visualmente as estatísticas do conjunto de dados, incluindo distribuição de dados, desvio padrão, valores ausentes e muito mais.
Aqui, podemos observar as estatísticas do conjunto de dados de treinamento, obtendo informações valiosas sobre as características dos dados. Também podemos examinar o mesmo conjunto de estatísticas para o conjunto de avaliação. Com base nas estatísticas, notamos que apenas 2% de nossos rótulos são diferentes de zero, sugerindo que nossos eventos de entrada para negociações lucrativas podem ser outliers. Isso pode representar um desafio no futuro devido ao desequilíbrio entre as classes.
Em seguida, geramos o esquema de dados automaticamente usando o componente SchemaGen. Esse esquema é derivado das estatísticas observadas, mas também podemos definir nossa própria descrição de dados, se desejado. A saída é um esquema que fornece uma descrição abrangente da estrutura e das propriedades de nossos dados. Por fim, chegamos ao componente ExampleValidator, que valida os dados com base nas estatísticas e no esquema gerados. Ele verifica quaisquer anomalias ou inconsistências no conjunto de dados. Por exemplo, no exemplo do táxi de Chicago, o recurso '_company' tinha um valor de string inesperado. Podemos usar o ExampleValidator para detectar tais problemas em nosso próprio conjunto de dados.
Em nosso caso, felizmente, não encontramos nenhuma anomalia ou inconsistência em nosso conjunto de dados. Este é um sinal positivo, indicando que nossos dados estão relativamente limpos e alinhados com nossas expectativas. Bem, isso encerra nossa rápida introdução ao TFX. No próximo episódio, vamos nos aprofundar nos componentes restantes do TFX e explorar como transformar nossos dados e treinar nosso modelo.
Obrigado por assistir, e estou ansioso para vê-lo no próximo vídeo!
Parte IV. Deep Learning Trading Strategy desde o início até a produção. Pipeline TFX 2.
Parte IV. Deep Learning Trading Strategy desde o início até a produção. Pipeline TFX 2.
Bem-vindo a mais um episódio de "Perto da Algotrading". Eu sou Denis, e hoje vamos continuar explorando o pipeline TFX como parte da construção de nossa estratégia de negociação.
No vídeo anterior, abordamos os quatro primeiros componentes do pipeline TFX: ExampleGen, StatisticsGen, SchemaGen e ExampleValidator. Esses componentes estabeleceram a base para nosso pipeline, garantindo a validação e a consistência dos dados.
Agora, vamos nos aprofundar nos componentes restantes: Transformer, Trainer, Evaluator, ModelValidator e Pusher. Esses componentes nos permitirão transformar nossos dados, treinar nosso modelo, avaliar seu desempenho, validar o modelo em relação a uma linha de base e, finalmente, enviar o modelo validado para um ambiente de produção.
Mas antes de prosseguirmos, deixe-me abordar alguns pontos importantes. Embora o pipeline TFX ofereça uma estrutura poderosa, vale a pena notar que ainda pode ter alguns bugs e alguns componentes podem estar em construção. No entanto, vamos abordar cada etapa com cuidado e discutir quaisquer limitações ao longo do caminho. No vídeo anterior, validamos nossos dados com sucesso e agora é hora de passar para a etapa de transformação. Para isso, usaremos o componente Transformer fornecido pela TFX.
O componente Transform é responsável por realizar transformações de dados e engenharia de recursos consistentes para treinamento e serviço. Isso significa que podemos usar a mesma função de transformação de dados para treinar o modelo e usá-lo na produção. Essa funcionalidade é uma das principais razões pelas quais comecei a explorar o TFX em primeiro lugar.
Para iniciar o processo de transformação, precisamos criar alguns arquivos Python. O primeiro arquivo conterá nossas constantes, como uma lista de recursos numéricos e rótulos. O segundo arquivo conterá uma função de pré-processamento (preprocessing_fn), que é uma função de retorno de chamada usada por tf.Transform para pré-processar os dados de entrada. Nesta função, definiremos as etapas de transformação de dados e construção de recursos. Por enquanto, vamos nos concentrar em transformar todos os recursos de entrada numérica em pontuações z e alterar os valores de rótulo de -1, 0 e 1 para 0, 1 e 2, respectivamente. Essa transformação de rótulo é necessária porque o estimador do TensorFlow espera valores positivos.
É importante observar que, na versão atual do TFX, apenas os estimadores do TensorFlow são compatíveis. Se você preferir usar um modelo Keras, precisará convertê-lo em um estimador usando a API model_to_estimator. Embora o TFX versão 0.21 afirme oferecer suporte a modelos Keras para o componente Trainer, encontrei alguns problemas com sua funcionalidade de contexto interativo. Esperamos que a equipe do TFX resolva esses problemas em breve e forneça uma ferramenta estável e totalmente funcional.
Agora, vamos prosseguir com a transformação de dados. Como você pode ver, o componente Transform espera os seguintes parâmetros como entrada: os exemplos gerados, o esquema de dados e o caminho para o arquivo que contém a função preprocessing_fn. Após a conclusão da transformação, podemos prosseguir para a criação e treinamento de nosso modelo. O componente Trainer será responsável por treinar o modelo com base nas especificações que definirmos.
No arquivo Python contendo nosso modelo e funções de entrada, definimos uma função trainer_fn que será chamada pelo componente Trainer. Esta função deve retornar um dicionário com os seguintes itens:
Dentro desse arquivo, definimos a função _input_fn, que gera os recursos de entrada e rótulos para treinamento e avaliação. Também temos funções adicionais, como _example_serving_receiver_fn, que cria as entradas de serviço e _eval_input_receiver_fn, que prepara as entradas necessárias para o TensorFlow Model Analysis (TFMA).
Para criar nosso estimador, definimos uma função build_estimator. Nesta função, configuramos o conjunto de recursos de entrada e criamos nosso estimador. Vale ressaltar que usei o DNNLinearCombinedEstimator porque o DNNClassifier e o DNNEstimator estavam causando erros relacionados à passagem de recursos do TensorFlow 1. Acredito que não, pois estamos usando os métodos do TensorFlow 2. Infelizmente, não encontrei uma solução para este problema. No entanto, o estimador Linear parece funcionar bem.
Agora que nosso modelo está definido, podemos continuar treinando-o usando o componente Trainer. Como você pode ver, o componente Trainer espera um module_file que contém a função trainer_fn, juntamente com outros parâmetros, como transformador_exemplos, esquema de dados, gráfico de transformação e argumentos de treinamento e avaliação. Por enquanto, especificamos apenas o número de etapas para treinamento e avaliação. Após a conclusão do treinamento do modelo, podemos passar para a análise do modelo usando o TensorFlow Model Analysis (TFMA). Antes de prosseguirmos, certifique-se de ter instalado o TFMA seguindo o link fornecido. O TFMA nos permite realizar análises em nosso modelo, seja em todo o conjunto de dados ou em fatias de recursos específicos. Nesse caso, faremos a análise em três fatias: o conjunto de dados completo, o rótulo e dois recursos específicos.
Analisando o conjunto de dados completo, observamos uma precisão notável de 98%. No entanto, ao examinar o desempenho do modelo com base nos rótulos, notamos que ele prevê consistentemente o rótulo 0. Esse resultado era esperado devido aos rótulos desbalanceados e à ausência de recursos úteis em nosso modelo. No entanto, o TFMA fornece uma maneira conveniente de avaliar o desempenho do modelo.
Seguindo em frente, temos o componente ModelValidator, que nos ajuda a validar nossos modelos exportados. Ele compara novos modelos com uma linha de base (como o modelo atualmente em exibição) e determina se eles atendem a critérios predefinidos. Essa validação inclui avaliar os modelos em um conjunto de dados de avaliação e calcular métricas como AUC e perda. Se as métricas do novo modelo satisfizerem os critérios especificados pelo desenvolvedor em relação à linha de base, o modelo será considerado "bom o suficiente" e marcado como tal.
Por fim, temos o componente Pusher, que verifica se o modelo passou na validação. Se o modelo atender aos critérios de validação, ele será enviado para um destino de arquivo especificado. Esta etapa garante que apenas modelos validados sejam implantados no ambiente de produção.
Para concluir nosso pipeline, podemos exportar todos os componentes para um pipeline do Apache Beam. Podemos então empacotar todos os arquivos necessários em um arquivo zip. Ao descompactar os arquivos do arquivo em nosso diretório de trabalho no servidor, podemos executar o pipeline. Após a conclusão da execução, teremos um modelo treinado pronto para uso com o TensorFlow Serving. Se você estiver interessado em aprender como iniciar e usar o TensorFlow Serving a partir de um contêiner Docker, poderá encontrar um tutorial em vídeo no meu canal.
Embora tenhamos coberto muito terreno nesta série, é importante observar que a versão atual do TFX ainda tem certas limitações. Dependendo de seus requisitos específicos, pode ser necessário implementar um pipeline que dependa exclusivamente da função de transformação com um modelo Keras. No entanto, espero que esta exploração do TFX tenha sido informativa e benéfica.
No próximo vídeo, voltaremos ao nosso objetivo principal de desenvolver uma estratégia de negociação. Fique atento a isso! Não se esqueça de comentar, se inscrever e curtir este vídeo. Obrigado por assistir, e até a próxima!
Parte V. GIGO. Deep Learning Trading Strategy desde o início até a produção.
Parte V. GIGO. Deep Learning Trading Strategy desde o início até a produção.
Bem-vindo de volta a outro episódio de "Perto da Algotrading". Meu nome é Denis e estou aqui para compartilhar minhas experiências e falhas no desenvolvimento de um sistema de negociação de aprendizado profundo.
Tenho dedicado um tempo significativo para implementar todo o sistema usando o TensorFlow, mas devo admitir que estou bastante decepcionado com a qualidade da biblioteca. Embora eu aprecie o conceito, a documentação fornecida pelo TensorFlow tem sido uma fonte de frustração. Parece que mesmo as mentes brilhantes com seus PhDs lutam para escrever uma documentação bem estruturada. Embora tenha melhorado em relação ao passado, continua confuso em vários pontos.
No entanto, a documentação é apenas um problema menor em comparação com o problema maior que encontrei. Muitas funções simplesmente não funcionam como esperado quando tentei usá-las, e mesmo os exemplos oficiais às vezes não funcionam corretamente. Isso me deixou questionando se posso ter perdido alguns pontos centrais dessa estrutura. Mas vamos voltar ao assunto principal deste vídeo: meus fracassos. Como você deve se lembrar, decidi gerar rótulos para movimentação de preços com base em uma porcentagem especificada. A maioria desses rótulos acabou sendo mínimos ou máximos locais nos dados.
Depois de executar alguns processamentos e preparações simples de dados, criei uma rede LSTM simples e a coloquei em teste. Minhas expectativas não eram excepcionalmente altas, mas os resultados foram realmente decepcionantes. Como você pode ver no visual a seguir, a rede não conseguiu aprender nada significativo.
Agora, é importante lembrar que uma rede neural não foi feita para fazer milagres. Talvez seja hora de reavaliar nossa abordagem. Os eventos que estamos tentando prever representam apenas 2% de todo o conjunto de dados. Esses eventos podem ser considerados outliers, e nossa rede simples se esforça para distingui-los do resto dos dados. Além disso, existe uma grande probabilidade de que esses eventos não estejam relacionados e tenham causas distintas, dificultando a construção de um modelo que os preveja com precisão.
Diante desses desafios, ficou evidente que precisamos nos concentrar em entender melhor os dados e identificar recursos com poder preditivo. Com isso em mente, decidi revisitar uma estratégia simples de média móvel. Em nossa abordagem inicial, não tínhamos um entendimento claro de por que deveríamos entrar em uma posição. No entanto, agora temos uma estratégia para abrir posições. Embora não seja perfeito, é uma estratégia amplamente utilizada que podemos alavancar. Adicionei duas médias móveis e um indicador RSI (Índice de Força Relativa) ao nosso conjunto de dados e coletei todos os eventos em que as médias móveis se cruzaram. Isso nos permitiu estimar as direções do movimento dos preços.
Em seguida, criei meta-rótulos usando o mesmo método de rotulagem de antes, mas desta vez, rotulei apenas as barras onde as médias móveis se cruzam. Há uma diferença importante aqui: como já sabemos a direção da posição (longa ou curta), o significado de nossos rótulos será diferente. Um rótulo de 1 indica um lucro, -1 representa uma perda e 255 é atribuído para outros casos. Com o conjunto de dados e rótulos atualizados, treinei um modelo LSTM simples e obtive uma curva ROC (Receiver Operating Characteristic) perfeita. A curva ROC mostra o desempenho de um modelo de classificação em diferentes limiares de classificação. O valor AUC (área sob a curva) da curva ROC nos ajuda a avaliar o quão bem o modelo distingue entre as classes.
No entanto, ao examinar as previsões do modelo, notei que ele previu consistentemente a classe 0. Esse resultado ocorreu porque, mais uma vez, usei todo o conjunto de dados em vez de apenas os eventos relevantes. Nosso conjunto de dados permaneceu desequilibrado e os recursos careciam de capacidade preditiva. As curvas ROC não são ideais para conjuntos de dados desequilibrados, pois podem mascarar o baixo desempenho do modelo na previsão de outras classes.
Para resolver o desequilíbrio nos dados, fiz ajustes e foquei apenas nos dados relevantes para os eventos abertos. Infelizmente, mesmo após essas modificações, meu modelo falhou em exibir poder preditivo. Produziu os mesmos resultados que um modelo aleatório. Também tentei um modelo feedforward simples, que mostrou resultados um pouco melhores, mas ainda insatisfatórios. Em conclusão, como você pode ver, não há mágica no aprendizado profundo se você alimentar seu modelo com dados de baixa qualidade. O princípio de "Entra lixo, sai lixo" é válido neste contexto. Além disso, ao lidar com conjuntos de dados altamente desequilibrados e sem recursos com forte poder preditivo, um modelo de classificação tenderá a prever a classe que constitui a maioria do conjunto de dados.
Como mencionei anteriormente, é crucial entendermos nossos dados e identificar processos que possam nos ajudar a encontrar uma maneira de vencer o mercado.
Isso encerra o episódio de hoje. Espero que você tenha achado perspicaz e informativo. Cuidem-se, fiquem em casa e mantenham-se saudáveis.
Parte VI. Aprendizagem por Reforço. Estratégia de negociação de aprendizado profundo desde o início até a produção
Parte VI. Aprendizagem por Reforço. Estratégia de negociação de aprendizado profundo desde o início até a produção
Sou Denis e bem-vindo a mais um episódio de "Close to Alga Trading". Em nossos episódios anteriores, trabalhamos para construir uma estratégia de negociação lucrativa usando aprendizado profundo. Vamos recapitular nosso progresso até agora.
Começamos observando as condições de mercado em busca de ineficiências. Uma vez identificados, criamos regras simples e preparamos os dados para nossos modelos de aprendizado profundo. No entanto, ao implementar nossa abordagem direta, descobrimos que ela não produzia os resultados desejados. Isso nos levou a perceber que precisamos repensar nossa abordagem e considerar estratégias alternativas.
No episódio de hoje, exploraremos uma nova direção: aprendizado por reforço. O aprendizado por reforço obteve sucesso significativo em vários domínios, superando o desempenho humano em jogos como xadrez, Dota e Go. Também é utilizado em robótica de controle e carros autônomos. Então, por que não aplicá-lo à negociação? Embora eu não possa garantir seu sucesso, é um caminho intrigante a ser explorado.
Para começar, vamos nos aprofundar em uma breve introdução ao aprendizado por reforço e nos familiarizar com as principais definições.
O aprendizado por reforço pode ser descrito como o aprendizado por tentativa e erro para resolver problemas de controle ótimo. Em termos mais simples, envolve encontrar a melhor ação a ser executada em um determinado estado do ambiente para maximizar uma recompensa numérica final. Para entender melhor esse conceito, vamos visualizá-lo com uma analogia simples.
Imagine um trader sentado em frente a um monitor, comprando e vendendo ações. Aqui, o trader representa o agente, enquanto o preço do gráfico e o corretor formam o ambiente. O agente observa o estado atual do ambiente e realiza ações, como comprar uma ação. Em troca, o agente recebe uma recompensa, que pode ser os honorários do corretor. À medida que o ambiente muda, o agente pode comprar mais ações, vender ou não fazer nada. Ao final do dia de negociação, o agente recebe uma recompensa final, que pode ser positiva ou negativa. O objetivo do agente é maximizar essa recompensa final.
No aprendizado por reforço, nosso objetivo é projetar agentes que possam aprender interagindo com um ambiente. Agora, vamos nos familiarizar com as principais definições que encontraremos ao longo de nossa jornada.
Agente: O algoritmo que toma decisões, executa ações, observa o ambiente, recebe feedback e visa maximizar a recompensa.
Ambiente: O mundo no qual o agente reside. Ele engloba todos os dados disponíveis para o nosso agente tomar decisões.
Estado: A configuração do ambiente que o agente detecta.
Recompensa: O feedback que o agente recebe após realizar uma ação. É um valor que o agente busca maximizar. É importante ressaltar que no aprendizado por reforço, a recompensa não significa necessariamente dinheiro ou um troféu físico. É simplesmente um valor numérico que também pode ser negativo, e nosso objetivo é maximizar esse valor.
Ação: Qualquer coisa que o agente é capaz de fazer em um determinado ambiente. Para simplificar, vamos considerar três ações: comprar, vender ou não fazer nada.
Episódio: Uma execução completa de toda a tarefa.
Estas são as principais definições que usaremos ao longo de nossa jornada. Existem termos adicionais importantes que abordaremos em vídeos futuros.
Com esta introdução ao aprendizado por reforço, aprenderemos sobre o ambiente e criaremos nosso próprio ambiente usando o TensorFlow no próximo vídeo.
Obrigado por se juntar a mim hoje e estou ansioso para explorar ainda mais o aprendizado por reforço com você. Vejo você em breve!
Parte VII. Aprendizagem por Reforço. Ambiente de Negociação.
Parte VII. Aprendizagem por Reforço. Ambiente de Negociação.
Eu sou Denis, e você está assistindo "Close to AlgoTrading". Em nosso último episódio, fornecemos uma breve introdução ao aprendizado por reforço. Hoje, vamos nos aprofundar na criação de um ambiente de negociação simples para nosso agente. Vamos explorar os detalhes.
Primeiro, precisamos considerar o que o ambiente de negociação representa. É baseado apenas em dados de preços ou devemos incorporar fatores adicionais, como o livro de pedidos completo, notícias ou até mesmo rumores do Twitter? Essa decisão moldará a complexidade do nosso ambiente.
Em seguida, precisamos determinar as ações que nosso agente pode executar. Deve ser limitado a ações de "comprar" e "vender" ou também pode pular algumas etapas? Definir o espaço de ação é crucial para o processo de tomada de decisão do nosso agente.
Agora, vamos discutir o alvo e como definiremos as recompensas. No mundo real, o ambiente de negociação possui um espaço de estado contínuo. No entanto, para simplificar, vamos manter o ambiente o mais direto possível, permitindo-nos entender seu funcionamento interno e sua implementação.
Para começar, em vez de usar dados de preços reais, vamos gerar um processo de passeio aleatório que consiste em apenas 20 valores. Esses preços diários simulados servirão como nossa entrada. O episódio começará no meio dessa sequência de preços, ou seja, o estado inicial incluirá os 10 preços históricos. Os preços invisíveis restantes serão preenchidos com zeros. A cada passo, um novo preço será adicionado ao array. O episódio terminará quando todos os 20 preços ficarem visíveis para o agente. Portanto, temos um total de 10 etapas até a conclusão do episódio.
Além dos dados de preço, o estado incluirá informações sobre nossa posição aberta. Vamos representar a posição usando codificação one-hot: [0,0] para nenhuma posição aberta, [1,0] para uma posição longa e [0,1] para uma posição curta.
Considerando as ações típicas de negociação, incluiremos "comprar" e "vender" para os casos em que nenhuma posição estiver aberta. No entanto, se já houver uma posição aberta, o agente só poderá optar por pular ou fechar a posição. Assim, neste cenário, a ação "vender" ou "comprar" é equivalente a "pular".
O objetivo do nosso agente é maximizar lucros e perdas (PnL) durante o período de 10 dias. Portanto, definiremos a recompensa como o PnL diário.
Com uma compreensão clara da estrutura e do comportamento do nosso ambiente, podemos agora prosseguir para o estágio de implementação. Conforme mencionado anteriormente, utilizaremos a estrutura TensorFlow (tf-agent). A equipe do tf-agent forneceu um guia abrangente sobre o desenvolvimento de um ambiente adequado para o tf-agent, que recomendo verificar para uma compreensão mais profunda do código.
Para criar nosso ambiente, começaremos herdando a classe PyEnvironment, pois ela define a interface que todos os ambientes Python devem implementar. Dentro da função Init, vamos inicializar variáveis, definir estados iniciais e, mais importante, especificar as especificações de ação e observação. No nosso caso, o espaço de ação será composto por quatro ações diferentes, com valores mínimo e máximo definidos como 0 e 3, respectivamente. A especificação da observação descreverá o estado do ambiente, com o preço partindo de 0 e sem limite máximo. O tipo de dados para preços será float. Retornar as especificações de ação e observação é crucial para uma integração perfeita com o tf-agent.
A próxima função significativa a ser implementada é redefinida. Esta função redefinirá o ambiente para seu estado inicial. Garantir a correta execução dessa função é vital para o bom funcionamento do ambiente.
Agora, vamos discutir a função mais crítica: step. A função step recebe uma ação como parâmetro de entrada e é responsável por gerenciar as transições de estado do ambiente. Nesta função, trataremos de todas as ações possíveis e calcularemos o PnL (recompensa). A função retorna um time_step, que consiste na observação (a parte do estado do ambiente que o agente pode observar para escolher suas ações na próxima etapa), a recompensa (o objetivo de aprendizado do agente), step_type (indicando se esse intervalo de tempo é o primeiro, intermediário ou último em uma sequência) e desconto.
Na função step, temos dois cenários de retorno diferentes: um para os passos intermediários e outro para o último passo do episódio.
Após a criação do ambiente, é fundamental validá-lo para identificar e corrigir eventuais bugs. O pacote util fornece uma função chamada valid_py_environment, que pode ser usada para esse propósito. Além disso, verificar as especificações do ambiente ajudará a garantir que tudo esteja funcionando conforme o esperado.
Com nosso ambiente pronto para uso, é uma boa ideia testá-lo com diferentes ações para depurar e validar seu comportamento.
Realizei alguns testes usando um simples DQN tf-agent e aqui estão os resultados. Após 20.000 passos, o agente demonstrou desempenho aceitável. No entanto, lembre-se de que tínhamos apenas uma série temporal para o agente aprender, tornando-a relativamente direta. Se introduzirmos uma segunda série temporal e executarmos 20.000 passos, os resultados podem não ser tão promissores. Mas com cerca de 100.000 passos, o desempenho do agente melhorou significativamente.
Parte VIII. Estratégia de Negociação de Aprendizagem por Reforço. DQN: QNetwork, QRNNNetwork
Parte VIII. Estratégia de Negociação de Aprendizagem por Reforço. DQN: QNetwork, QRNNNetwork
Olá, meu nome é Denis, e você está assistindo "Close to AlgoTrading". Neste vídeo, forneceremos uma breve atualização sobre nosso ambiente anterior para o agente de aprendizado por reforço. Também faremos uma breve descrição do Q-Learning e do agente DQN. Em seguida, procederemos à implementação das principais etapas de aprendizado para um agente rDQN da biblioteca tf-agents e discutiremos os resultados do teste.
Para começar, vamos revisitar o ambiente de negociação que criamos no vídeo anterior. Nesse ambiente, usamos dados gerados sintéticos. Porém, nesta versão atualizada, nosso ambiente receberá um dataframe com dados históricos como parâmetros de entrada. A observação_spec para o ambiente é um dicionário com duas chaves: "Price" e "Pos". A chave "Preço" contém 20 elementos com dados de abertura, fechamento, alta, baixa e volume. A tecla "Pos" contém informações sobre nossa posição aberta.
No início de cada episódio, selecionamos aleatoriamente uma fatia de 20 preços de nossos dados. Essa mudança permite que nosso agente de aprendizado por reforço aprenda com dados históricos reais.
Seguindo em frente, vamos discutir o Q-Learning e o conceito de Q-Table. O Q-Learning envolve atribuir um valor Q a cada par de (estado, ação). Esta tabela, conhecida como Q-Table, é utilizada pelo agente para selecionar as ações com o valor Q máximo no estado atual. O agente explora o ambiente, recebe recompensas e atualiza os valores Q com base nas recompensas observadas.
Para atualizar os valores Q, usamos uma fórmula que envolve o valor Q antigo e o valor Q futuro. Calculamos o valor Q futuro procurando o valor Q máximo para o próximo estado em nossa Tabela Q. Com o valor Q futuro obtido, atualizamos o valor Q associado ao par inicial (estado, ação).
Porém, no nosso caso, o mercado financeiro possui um state space muito amplo, tornando inviável a utilização de uma Q-Table. Para superar esse desafio, podemos usar uma rede neural profunda para prever os valores Q para um determinado estado. Essa abordagem, conhecida como agente DQN (Deep Q-Network agent), usa uma Q-Network, onde os valores Q são atualizados minimizando a perda por retropropagação. A função perda utilizada no agente DQN é dada por uma equação específica.
Agora que entendemos bem o Q-Learning e o agente DQN, vamos implementar as principais etapas de aprendizado do agente rDQN usando a biblioteca tf-agents.
O algoritmo de treinamento geral segue estas etapas:
Criar o ambiente é uma tarefa simples. Envolvemos nosso ambiente de negociação no TFPyEnvironment, que permite uma integração perfeita com tf-agents.
Em seguida, criamos uma Q-Network para o agente DQN. A biblioteca tf-agents fornece uma classe Q-Network que podemos usar para definir nossa Q-network. Definimos uma rede Q simples com uma camada oculta totalmente conectada consistindo de 40 neurônios. Como nossa observação é um dicionário, também definimos uma camada simples de pré-processamento para ela.
Com o Q-Network criado, passamos a criar um agente DQN. Instanciamos a classe tf_agents.agents.dqn.dqn_agent, passando nossa Q-network como parâmetro. Também definimos o otimizador e a função de perda para treinar o modelo.
Para treinar o agente, precisamos de dados do ambiente. Coletamos esses dados por meio de uma política e, para essa etapa, podemos selecionar aleatoriamente as ações. O agente DQN tem duas políticas: agent.policy, que é usado para avaliação e implementação, e agent.collect_policy, que é usado para coleta de dados.
A coleta de dados envolve pegar o estado atual, selecionar uma ação, receber o próximo estado e recompensa e armazenar essas informações em um buffer. Colecionamos várias etapas ou episódios, formando trajetórias. A biblioteca tf-agents fornece um driver chamado DynamicEpisodeDriver, que coleta etapas até o final de um episódio. O driver atualiza os observadores, incluindo um buffer de resposta.
Para armazenar os dados, podemos usar o comumente usado TFUniformReplayBuffer da biblioteca tf-agents. Definimos as especificações dos elementos de dados que o buffer armazenará, o tamanho do lote e o comprimento máximo de cada segmento do lote.
Uma vez concluída a etapa de coleta de dados, podemos treinar nosso agente. O agente requer acesso ao buffer de reprodução. Criamos um pipeline tf.data.Dataset para fornecer dados ao agente. Cada linha do buffer de replay armazena uma única trajetória, mas o agente DQN precisa tanto da observação atual quanto da próxima para computar a perda. Portanto, definimos o parâmetro num_steps como 2, o que permite que o pipeline do conjunto de dados faça uma amostra de duas linhas para cada item no lote.
Neste ponto, temos tudo para treinar dois agentes DQN nos mesmos dados e avaliar seu desempenho. Um agente usa uma Q-Network simples, enquanto o outro usa uma QRNNNetwork. Ambos os agentes são treinados usando 200 dias de dados históricos de preços.
Após 700 etapas de treinamento, observamos que o agente Q-Network simples não aprendeu muito e, na maioria das vezes, apresenta um retorno médio negativo. No entanto, o agente QRNNNetwork apresenta em sua maioria retornos médios positivos. Este resultado está alinhado com as expectativas, pois o agente RNN pode capturar alguma dinâmica nos dados e aprender mais rápido.
Embora esse experimento simples forneça alguma esperança para o uso do aprendizado por reforço na construção de um agente lucrativo, ainda há outras métricas a serem consideradas para avaliar o desempenho do agente. Vamos explorá-los em um vídeo futuro.
Obrigado por assistir, e vejo vocês no próximo episódio.
Parte IX Estratégia de Negociação de Aprendizagem por Reforço. DQN: Testando a estratégia de negociação com base na política do agente
Parte IX Estratégia de Negociação de Aprendizagem por Reforço. DQN: Testando a estratégia de negociação com base na política do agente
Tenho o prazer de anunciar que atingimos um marco significativo em nossa jornada: testar nossa estratégia. Para esse propósito, utilizaremos uma estrutura Python de backtest simples para conduzir nossos testes. Para começar, você pode instalar o framework executando o comando "pip install" seguido do nome do framework.
O autor da estrutura forneceu um exemplo simples que demonstra como usá-la efetivamente. No entanto, antes de mergulharmos nisso, precisamos implementar nossa própria estratégia. Vamos começar inicializando e definindo todas as variáveis que precisaremos para nossa estratégia.
Um aspecto interessante é que podemos carregar nossa política salva usando a API do TensorFlow. Como estamos usando uma QRNNNetwork, precisamos obter o estado inicial da política. Consequentemente, implementamos a função de inicialização. Agora é hora de implementar a função "next", que será chamada a cada novo passo. No início, precisamos coletar dados dos primeiros 10 dias e, posteriormente, podemos alimentar nosso dicionário de observação. A cada passo, atualizamos a observação e passamos para a política.
Depois de criar o dicionário de observação, precisamos criar um objeto timestep, pois nosso modelo de política o requer como entrada. Para facilitar esse processo, criei uma função simples que converte nossos dados de observação no objeto timestep. Os elementos cruciais aqui são os dados de observação e o step_type. Depois de obter nosso objeto timestep, podemos recuperar uma ação da política. Como você pode ver, a função "runPolicy" redefine o estado da política se o step_type for igual a 0 e retorna a ação e o novo policy_state.
Em seguida, precisamos atualizar nossos estados de posição e executar a ação. Finalmente, ao final da função "next", incrementamos o contador e redefinimos tudo para os estados iniciais para simular o início de um novo episódio. Ótimo! Implementamos nossa estratégia com sucesso. Agora, precisamos de alguns dados para fins de teste. Podemos usar a biblioteca panda_datareader para recuperar dados diários do Yahoo Finance. Vamos começar testando nossa estratégia nas ações da Intel, usando dados históricos de um ano.
Criamos um objeto de backtest e iniciamos o teste. Os resultados do teste mostram um retorno de 106%, o que é impressionante. No entanto, é importante observar que a estrutura de backtesting inicia os cálculos a partir de 100%, o que significa que nosso retorno real é de apenas 6%. No entanto, este não é um resultado ruim, considerando que nossa política não foi treinada extensivamente. Para fornecer uma avaliação mais abrangente, vamos também testar nossa estratégia nas ações da AMD. Como você pode ver, o resultado da AMD mostra uma queda de aproximadamente 40%. Assim, podemos comparar lado a lado o desempenho de nossa estratégia nas ações da AMD e da Intel.
Agora você sabe como usar a política do agente com uma estrutura de backtesting. Da mesma forma, se você estiver usando o Python para seu ambiente de negociação real, poderá empregar a política da mesma maneira. No entanto, para aqueles que usam outras linguagens, você pode implantar a política usando a estrutura Flask e acessá-la por meio de uma API REST.
Espero que você tenha achado esses vídeos interessantes e informativos. Se sim, considere se inscrever, e vejo você no próximo episódio.
O que é um Sistema de Negociação Quantitativo? Estrutura e descrição.
O que é um Sistema de Negociação Quantitativo? Estrutura e descrição.
Olá pessoal! Espero que todos estejam bem. Já faz algum tempo desde a última vez que lancei um vídeo, mas quero garantir que não esqueci de você. Hoje, estou animado para começar um tópico novo e interessante: a arquitetura de software de um sistema de negociação automatizado.
Antes de nos aprofundarmos nos detalhes da arquitetura de software, vamos primeiro entender o que é um sistema de negociação e em que consiste. Neste vídeo, exploraremos a estrutura e os elementos de um sistema de negociação automatizado. Agora, como diz o ditado, "Não há nada de novo sob o sol." Quando comecei minha jornada neste campo, estava em busca de uma descrição bem estruturada de um sistema de negociação. Eu queria algo que facilitasse o entendimento de quais blocos implementar e como criar uma solução de software robusta.
Encontrei um livro de Rishi K. Narang chamado "Inside the Black Box", onde ele descreve um sistema quantitativo composto de cinco blocos comuns: o modelo alfa, modelo de risco, modelo de custo de transação, modelo de construção de portfólio e modelo de execução. Além disso, há mais um bloco essencial: dados.
Vamos dar uma olhada mais de perto nessa estrutura, começando com o bloco de dados. Embora o bloco de dados não seja tecnicamente uma parte do sistema de negociação, ele desempenha um papel vital como o oxigênio do qual todos os componentes do sistema dependem. O bloco de dados abrange vários tipos de dados exigidos pelo sistema de negociação. Esses dados podem vir de diferentes fontes, como bolsas, reguladores, agências de notícias e outras fontes relevantes, como dados microeconômicos, taxas de corretoras ou informações de portfólio.
Agora que entendemos o bloco de dados, vamos explorar os elementos do sistema de negociação e as relações entre eles. No diagrama, você pode ver as setas que representam o fluxo de informações. O modelo alfa, modelo de risco e modelo de custo de transação não tomam decisões finais; em vez disso, fornecem informações ao modelo de construção do portfólio, que, por sua vez, aciona o modelo de execução. É importante observar que existem estratégias em que apenas um subconjunto desses elementos está presente e as relações entre os elementos podem variar. No entanto, essa estrutura nos dá uma visão holística dos principais elementos de um sistema de negociação.
O primeiro elemento dessa estrutura é o modelo alfa. O modelo alfa representa a ideia ou estratégia de negociação projetada para prever resultados futuros. Normalmente, a saída desse modelo é uma previsão de retorno ou direção. Existem dois tipos bem conhecidos de modelos de negociação: modelos técnicos baseados em dados de preço e análise técnica e modelos fundamentais que utilizam dados financeiros e análise fundamental. Também podemos ter modelos híbridos que combinam aspectos de ambos. Independentemente da complexidade, o objetivo principal do modelo alfa é fornecer conselhos na forma de previsão.
Em seguida, temos o modelo de risco. O modelo de risco é projetado para ajudar a reduzir ou minimizar a exposição a fatores que podem levar a perdas. Os modelos de risco podem ser classificados em dois tipos. O primeiro tipo foca no dimensionamento de posições para reduzir riscos, empregando estratégias como hard sizing ou funções complexas. A saída desse tipo de modelo de risco é o tamanho da posição. O segundo tipo de modelo de risco visa mitigar tipos específicos de riscos, como o risco de direção do mercado. Nesses casos, o modelo pode sugerir uma posição de hedge como saída.
O terceiro elemento é o modelo de custos de transação. Este modelo fornece informações sobre o custo associado à execução de uma negociação. Existem três custos principais: comissões e taxas, derrapagem e impacto no mercado. Os modelos de custo de transação podem variar de modelos simples que retornam um valor de custo fixo a modelos mais complexos, como funções de custo quadrático, que visam prever o custo real com a maior precisão possível. O gráfico abaixo demonstra como diferentes funções de custo podem funcionar.
Uma vez que temos todos os elementos que fornecem informações, passamos ao modelo de construção do portfólio. Esse modelo recebe informações do modelo alfa, modelo de risco e modelo de custo de transação e decide como alocar fundos entre diferentes ativos. Tem como objetivo construir um portfólio baseado em alguma função objetivo. Existem dois tipos principais de modelos de construção de portfólio: modelos baseados em regras (por exemplo, pesos iguais, risco igual, métodos de árvore de decisão) e otimizadores de portfólio. O último envolve a otimização de uma função objetivo para alcançar uma alocação de ativos mais otimizada no portfólio.
Por fim, temos o modelo de execução, que recebe informações do modelo de construção da carteira e tem como foco a execução das ordens ao melhor preço possível. Existem vários tipos de modelos de execução, desde ordens simples de mercado ou limitadas até ordens mais complexas que analisam a microestrutura do mercado e utilizam algoritmos de aprendizado de máquina.
Isso conclui a breve descrição dos principais elementos de um sistema de comércio quantitativo. Espero que esta visão geral tenha fornecido a você uma melhor compreensão da estrutura do sistema de negociação e como ele funciona em geral.
Nos próximos vídeos, tentarei criar uma arquitetura de sistema de software com base nessa descrição. Se você achar este tópico interessante, considere se inscrever no canal para atualizações futuras. Obrigado por assistir, e vejo você no próximo vídeo.