📱

Get Our Mobile App

Take your business learning on the go!

Download on the App StoreGet it on Google Play

Python API - Requesting Market Data TWS API

Interactive Brokers17:22

Transcription

Bem-vindos a esta aula sobre solicitação de dados de mercado na API da Trader Workstation. Neste vídeo, destacaremos os requisitos para solicitar dados de mercado, como solicitar dados atrasados, como solicitar dados de mercado ao vivo e como solicitar dados históricos.

Observe que estes são os métodos mais populares de solicitar dados de mercado. No entanto, a Interactive Brokers também oferece dados de ticks, dados de histograma e profundidade de mercado. Vamos começar discutindo as assinaturas de dados de mercado.

Para que os clientes se inscrevam em dados de mercado, os usuários devem ter uma conta ibkr financiada com pelo menos US$ 500, na maioria dos casos. Existem algumas instâncias em que este não é o caso, no entanto, para o indivíduo médio e a Interactive Brokers, US$ 500 é o mínimo. Este limite deve ser mantido, além do custo de quaisquer assinaturas mantidas na conta.

Para aqueles com uma conta ibkr Pro de longa data, você pode ter observado que alguns instrumentos retornam dados de mercado para sua Trader Workstation gratuitamente, por padrão. Isso ocorre porque alguns dados de mercado podem ser fornecidos aos usuários gratuitamente enquanto estiverem na plataforma. Na plataforma significa simplesmente que os usuários estão observando dados exibidos diretamente por meio de uma das plataformas da Interactive Brokers. As bolsas consideram a funcionalidade da API como fora da plataforma e, como resultado, geralmente têm um custo associado a elas para receber dados de mercado.

Algumas das assinaturas de dados de mercado mais populares para uso da API estão listadas na documentação da API para dados de mercado no campus ibkr. Os usuários podem se inscrever em dados de mercado por meio do portal do cliente. Também vale a pena esclarecer que os dados de mercado são afiliados por usuário. Muitos clientes executarão uma única instância da Trader Workstation para monitorar negociações. No entanto, é comum ter uma máquina separada executando seu algoritmo de negociação no IV Gateway hospedado em uma máquina virtual em outro local. Para que ambas as plataformas recuperem dados de mercado, cada usuário ativo consumindo dados de mercado precisaria se inscrever nos dados separadamente.

Com a discussão de assinatura fora do caminho, podemos começar a mergulhar na solicitação real da API. Observe que usaremos a mesma estrutura do nosso vídeo de componentes essenciais. Portanto, se houver alguma dúvida sobre a estrutura inicial deste vídeo, certifique-se de revisar essa aula primeiro.

A maneira mais popular de solicitar e visualizar dados na API seria com o método eclient.reqMktData, que solicita os mesmos dados disponíveis na lista de observação do TWS. Clientes que não possuem assinatura de dados de mercado para instrumentos podem frequentemente solicitar dados atrasados de 15 minutos. Esta é apenas uma etapa extra em comparação com as assinaturas padrão de dados de mercado, portanto, a incluirei abaixo antes de prosseguir para esclarecer se sua solicitação será ao vivo ou atrasada. Os usuários simplesmente precisam chamar a função app.reqMktDataType. Os únicos argumentos que isso recebe são o tipo de dados a serem recuperados, que podem ser 1, 2, 3 ou 4 para ao vivo, congelado, atrasado ou atrasado congelado, respectivamente. Dados congelados referem-se a dados de mercado do fechamento mais recente, enquanto dados congelados atrasados retornarão os valores de fechamento de ontem. E, então, como mencionamos, os dados atrasados padrão retornarão dados atrasados de 15 minutos. Se eu estiver inscrito em dados de mercado em um determinado instrumento, mas solicitar dados de mercado atrasados, os dados ao vivo ainda serão retornados. A Interactive Brokers sempre tentará fornecer os dados de mercado mais atualizados sempre que possível.

Agora, vamos começar a construir nossa solicitação para dados em streaming. Estaremos focados em solicitar dados de preço e tamanho. No entanto, a solicitação de dados de mercado W também pode retornar notícias de string, genéricas e até mesmo valores gregos, dependendo dos tipos de ticks solicitados de dentro de nossa classe de aplicativo de teste. Vamos começar definindo uma de nossas funções de tick, tickPrice. Isso tratará todos os valores retornados relacionados aos valores de preço. tickPrice recebe self, reqId, tickType, price e attrib como argumentos. Embora já estejamos familiarizados com os dois primeiros, os dois últimos são bastante autoexplicativos. O argumento tickType é usado para indicar que tipo de dados está chegando. Cada tickType é um valor inteiro que se correlaciona a um valor específico, seja preço de oferta, último tamanho, preço de fechamento ou outro. Para uma lista completa de todos esses valores de tick, podemos olhar ticktype.py dentro dos arquivos de origem da API IB e ver exatamente a que tudo está se relacionando. Os usuários podem referenciar os valores inteiros retornados diretamente. No entanto, o enumerador contém um método twoString que converte ou tickType inteiros nos valores que vemos antes de nós em nosso arquivo. Podemos adicionar uma importação de from IBapi.ticktype import TickType. Isso nos permitirá referenciar o método tickType e .twoString e imprimir nossos valores diretamente. Em um momento, imprimirei todos esses valores em uma string f, incluindo nossa referência de tickType e n.twoString. Como discutimos antes, seria perfeitamente aceitável imprimir os valores de preço. No entanto, também quero ver as quantidades de nossas negociações afetadas por isso também. Para fazer isso, também adicionaremos a função wrapper.tickSize à nossa classe de aplicativo de teste. Esta função leva apenas os argumentos self, tickType e size. Os tamanhos retornados aqui se relacionarão aos preços retornados em nossa função tickPrice e nos permitirão criar uma imagem mais clara das negociações que estão ocorrendo.

Agora que temos tudo no lugar para receber os dados, vamos criar nosso objeto de contrato e uma solicitação de dados de mercado. Partindo do nosso vídeo anterior, farei uma solicitação de dados de mercado da Apple usando os valores de símbolo, tipo de segurança, moeda e câmbio. Com o contrato agora definido, posso chamar app.reqMktData para começar a solicitar meus dados em streaming. Para argumentos, precisaremos passar o reqId, que usaremos nossa função app.nextId para. Posso passar meu contrato para o objeto de contrato e, então, para nosso próximo argumento, a lista genérica de ticks, passarei como uma string o número 232, para que eu possa receber o preço de mercado da minha solicitação. Para usuários que procuram solicitar vários ticks genéricos, você simplesmente separaria os valores por vírgula na string. Então, talvez você passaria '232, 233, 234' como exemplo. O próximo argumento define se estamos solicitando um valor de instantâneo. Esta é uma única instância de retorno que agrega os últimos 11 segundos de negociação. Se nenhuma negociação ocorreu, isso não retornará nenhum valor e, se virmos uma negociação nos últimos 11 segundos, veremos esses valores retornados em agregado. Da mesma forma, o próximo argumento determina se estamos solicitando um instantâneo regulatório. Este é um instantâneo usado para determinar o preço de um instrumento antes de executar uma negociação. Os instantâneos regulatórios custarão aproximadamente 1 centavo de dólar por solicitação até atingirmos o custo da assinatura afetada. Se eu solicitar dados de mercado para a Apple repetidamente, a Interactive Brokers eventualmente adicionará a assinatura à sua conta, pois o custo do instantâneo regulatório equivale ao valor da assinatura de qualquer maneira. O argumento final recebe opções de dados de mercado, que é um argumento usado apenas para fins internos. Para este argumento, apenas passaremos uma lista vazia. Se executarmos este script, encontraremos um fluxo inicial de dados representando os valores mais recentes para vários tipos de ticks. Então, com o tempo, receberemos dados para todos os preços e tamanhos ao vivo à medida que eles chegam.

Solicitar dados históricos segue um padrão semelhante às solicitações de dados de mercado ao vivo. A única ressalva é que os dados de mercado não podem ser recuperados se você não tiver uma assinatura de dados de mercado de oferta. Antes de começarmos a analisar os dados históricos, gostaria de primeiro descobrir o quanto podemos solicitar dados de mercado. Começarei a encontrar esse valor usando um novo arquivo Python. No meu novo arquivo, criarei uma nova função na classe de aplicativo de teste para definir a função headTimestamp. Isso leva três argumentos: self, reqId e a string headTimestamp. Dentro da minha nova função, imprimirei meu valor headTimestamp. Também farei uma solicitação para self.cancelHeadTimestamp para terminar a solicitação agora que terminei e podemos apenas passar o reqId que recebemos como argumento. Com a parte eWrapper fora do caminho, sairei da classe de aplicativo de teste e criarei minha solicitação headTimestamp. Copiarei o mesmo contrato da Apple que usei no script de dados ao vivo, porque quero validar o quanto posso encontrar dados de mercado da Apple. Em seguida, farei uma chamada para a função app.reqHeadTimestamp. Isso leva um argumento para um reqId, que podemos usar nossa função nextId e uma referência de contrato, que levará meu objeto de contrato. Depois desses dois, estou agora encontrando algo conhecido como o valor whatToShow. Esse mesmo valor é usado para denotar quais dados são exibidos nos seus gráficos de barras TWS. No meu caso, usarei o valor para negociações, embora a lista completa de valores whatToShow esteja disponível em nossa documentação. O próximo argumento se relaciona ao uso de horários de negociação regulares. A1 indicará que queremos a data mais antiga dentro do horário de negociação, enquanto 0 solicitará a data mais antiga fora do horário de negociação. Finalmente, temos o parâmetro formatDate. Isso indicará se queremos 1 um timestamp UTC em formato de string ou 2 um timestamp de época. Este último é uma representação inteira do mesmo timestamp. Você pode considerar o primeiro melhor para consumo humano, enquanto o último é melhor utilizado em uma estrutura de solicitação programática. Mostrarei esses em breve fazendo duas solicitações. Se executarmos este script usando 1 como formato de data, veremos 19800112-147, o que significa que os dados de mercado de negociações da Apple podem voltar até 12 de dezembro de 1980, às 9h30, horário do leste. Antes de prosseguirmos, adicionarei rapidamente outra instrução print ao meu método headTimestamp para a função datetime.datetime.fromtimestamp. Isso levará a versão inteira do nosso headTimestamp. Se eu mudar minha solicitação original para usar 2 como meu formato de data, imprimirei o valor de época original, bem como o horário datetime traduzido para Python, que é automaticamente convertido para o horário local do meu PC no horário central dos EUA.

Agora que conhecemos nossa faixa de datas históricas, podemos começar a fazer solicitações de dados históricos. Você pode usar o mesmo arquivo, mas para minha demonstração, começarei com um novo exemplo de nosso layout padrão, mas adicionarei nosso contrato da Apple novamente. Como sempre, definiremos a função eWrapper dentro do aplicativo de teste usando def historicalData. Esta função recebe um argumento para self, reqId e bar. Concluiremos a função imprimindo os valores reqId e bar. Observarei que estamos imprimindo o objeto bar completo. No entanto, o objeto bar pode ser dividido, para que você possa imprimir bar.open para o preço de abertura, bar.close para o preço de fechamento e assim por diante. Mas apenas para nossa apresentação aqui, imprimirei tudo. Cada tamanho de barra é retornado separadamente, portanto, para sabermos que terminamos, devemos referenciar a função eWrapper para historicalData. Esta função recebe um argumento para self, reqId, start e end e destina-se apenas a indicar que todos os dados disponíveis foram retornados ao usuário. Os argumentos start e end descrevem as faixas de data de início e fim oficiais para nossa solicitação. Criarei uma string f denotando o início e o fim de nossos dados históricos. Com as funções wrapper definidas, iniciaremos nossa solicitação eclient. Para fazer a solicitação, chamaremos a função app.reqHistoricalData. Isso leva 10 argumentos no total, começando com reqId e contract. O próximo argumento é endDateTime, que recebe o valor que gostaríamos de finalizar nossos dados históricos. Se deixarmos isso como uma string vazia, o sistema assumirá o horário atual. Caso contrário, você criaria um formato para ano, mês, dia, seguido pelo carimbo de data e hora de 24 horas e um fuso horário. Você deve passar o fuso horário para a bolsa disponível por meio da solicitação de detalhes do contrato. O fuso horário exato usado para seu TWS, que é definido antes da tela inicial ou usando o horário UTC. Enviarei minha solicitação para 20240523 160000 us/Eastern. Então, passaremos um valor de duração, que corresponde ao intervalo completo em que os dados serão retornados. Portanto, se eu especificar 1D, receberei quantas barras em um único dia. Sobre as barras, o próximo argumento receberá meu tamanho de barra. No meu caso, posso passar 1 hora para receber uma barra de 1 hora. Isso significa que receberei exatamente sete barras para meu dia. Um pouco mais sobre isso mais tarde. Seguindo em frente em nossos argumentos, encontraremos valores mais familiares, como o valor whatToShow que usamos antes, que usarei para negociações novamente. Então, use rth e formatDate novamente usando 1 em ambos os casos. Agora temos a opção keepUpToDate, que nos permite construir barras à medida que os dados estão disponíveis e retornar essas novas barras para a função de atualização de dados históricos. Não estou interessado nesses dados no momento, então vou deixar isso como falso por enquanto. Finalmente, terminamos com opções de dados de mercado, que novamente deixarei como uma lista vazia. Agora, se executarmos este script, verei meu reqId e todos os meus valores de barras. Embora a maior parte disso seja autoexplicativo, há alguns pontos que gostaria de mencionar do ponto de vista programático. Você pode notar que enviamos esta solicitação usando usEastern, mas meus dados mostram América Chicago. Isso ocorre porque estou escolhendo imprimir meu fuso horário do operador, embora tenha feito a solicitação com o fuso horário dos instrumentos. Você pode modificar o fuso horário retornado no TWS abrindo a página de configuração global e abrindo as configurações da API. Você notará uma seção para enviar atributos específicos do instrumento para clientes de modo duplo. Especificar o fuso horário do operador retorna o fuso horário do seu TWS. O fuso horário do instrumento retorna o fuso horário para o contrato e o UTC é obviamente o fuso horário UTC. A outra parte que gostaria de mencionar são as sete barras que mencionei anteriormente. O valor de data na barra faz referência ao horário de início da barra. No meu caso, você pode ver que minha barra começou às 8h30, horário de Chicago, que é quando a NASDAQ abre para negociações da Apple, mas então veremos 0900 como nossa próxima barra, o que significa que nossa primeira barra tem apenas 30 minutos de duração antes de se transformar em uma série de barras de 1 hora. Este é o mesmo comportamento que a Trader Workstation, embora possa não ser tão comumente compreendido ao extrair dados programaticamente. Portanto, é a melhor prática usar a próxima barra como um indicador de um tamanho profissional. Isso conclui nossa aula sobre dados de mercado na API TWS. Obrigado por assistir. Se você tiver alguma dúvida, certifique-se de revisar nossa documentação ou deixar um comentário abaixo deste vídeo. Esperamos tê-lo na próxima aula da API TWS.