API de Tinkov, investimento. Primeiros passos

Quase desde os primeiros dias, tornei-me cliente da Tinkov Investments.

E a partir desse momento, vagas dúvidas me atormentam - a conta pessoal reflete a realidade objetiva?

O fato é que eu compro títulos denominados em dólares, mas na LC os preços de todos os ativos são exibidos em dólares e o valor total da carteira em rublos.

E não entendo se o dólar cresceu ou sou um investidor tão bem-sucedido?

Mas e as comissões, impostos e outros dividendos?

Gostaria de pegar todas as minhas transações e anotá-las no FIFO, como na contabilidade de ações ... E colocar os dividendos recebidos em cima e deduzir os impostos.

E então eu vou ver o resultado que eu entendo.

Aconteceu que Tinkov tem uma API que permite escrever robôs de negociação (não estou nem um pouco interessado nisso), bem como enviar dados sobre seu portfólio e operações.

Essa API tem uma descrição oficial, mas nem tudo estava claro para mim, eu tinha que entender.
Os resultados desses confrontos são apresentados à sua atenção.

Links úteis: Descrição da

API
Outra descrição

Obtendo um token e instalando uma biblioteca


Antes de começar, você precisa instalar a biblioteca e obter um token.

Instalação da biblioteca:

pip install -i https://test.pypi.org/simple/ --extra-index-url=https://pypi.org/simple/ tinkoff-invest-openapi-client

Cito o token oficial que recebe instruções:

  1. Faça login na sua conta em tinkoff.ru
  2. Vá para a seção de investimentos
  3. Vá para as configurações
  4. A função "Confirmação de transações por código" deve ser desativada
  5. Emita o token OpenApi para a troca e o Sandbox. Talvez o sistema solicite que você efetue login novamente, não se preocupe, isso é necessário para conectar o robô à plataforma de negociação.
  6. Copie o token e salve; o token é exibido apenas uma vez; não será possível visualizá-lo mais tarde; no entanto, você pode emitir um número ilimitado de tokens.

No momento da redação, o token era emitido na página www.tinkoff.ru/invest/settings , um botão na parte inferior da página.

imagem

Como tive erros com o token da sandbox, comecei a experimentar a versão de combate. O que eu desejo a você (Cuidado: não compre, venda acidentalmente algo extra).

Conecte-se


from openapi_client import openapi

token = '    '  
client = openapi.api_client(token)

Essas duas linhas fazem tudo o que precisamos.

Em seguida, trabalhamos com a variável do cliente.

Conteúdo do nosso portfólio


Obtenha o conteúdo do nosso portfólio:

pf = client.portfolio.portfolio_get()

Vamos ver os dados básicos do primeiro elemento:

print('value:', pf.payload.positions[0].average_position_price.value)
print('currency:', pf.payload.positions[0].average_position_price.currency)
print('balance:', pf.payload.positions[0].balance)
print('figi:', pf.payload.positions[0].figi)
print('ticker:', pf.payload.positions[0].ticker)
print('name:', pf.payload.positions[0].name)

No meu caso, é o seguinte:

value: 45.98
currency: USD
balance: 21.0
figi: BBG000BWPXQ8
ticker: BTI
name: British American Tobacco

valor -
Saldo do preço do papel - O número de títulos na carteira, valor e moeda - seu valor monetário.

Figi - Instrumento Financeiro da Global Identifier (Identificador Global de Instrumento Financeiro)
ticker - Ticker ativos.

A partir desses dados, podemos descobrir o nome legível por humanos do ativo.

Para esta solicitação, não precisamos disso (consulte o campo de nome), mas em outros casos isso será útil.

Obter o nome do artigo por FIGI e ticket


#    FIGI
instr = client.market.market_search_by_figi_get('BBG000BWPXQ8') 
instr

Nós temos:

{'payload': {'currency': 'USD',
             'figi': 'BBG000BWPXQ8',
             'isin': 'US1104481072',
             'lot': 1,
             'min_price_increment': 0.01,
             'name': 'British American Tobacco',
             'ticker': 'BTI',
             'type': 'Stock'},
 'status': 'Ok',
 'tracking_id': 'a1979917d2141916'}

Essa função de API funciona para mim como deveria. Vemos que 'BBG000BWPXQ8' -> 'British American Tobacco'.

Mas a pesquisa pelo nome do ativo por ticker não funciona para mim: ((((

instr = client.market.market_search_by_ticker_get('BTI' ) 
print(instr)

Os desenvolvedores sugeriram atualizar a biblioteca, mas mesmo depois disso não decolou.

Faça o download do diretório de valores mobiliários


No entanto, resolvi esse problema radicalmente. Eu baixei de Tinkov um diretório completo de ativos negociados:

#   
bonds = client.market.market_bonds_get() 

#   ETF
etfs = client.market.market_etfs_get() 

#   
stocks = client.market.market_stocks_get() 

instr_list = bonds.payload.instruments + etfs.payload.instruments + stocks.payload.instruments

instr_list[:3]
obteve
[{'currency': 'RUB',
  'figi': 'BBG00844BD08',
  'isin': 'RU000A0JU898',
  'lot': 1,
  'min_price_increment': 0.1,
  'name': '  9',
  'ticker': 'RU000A0JU898'}, {'currency': 'RUB',
  'figi': 'BBG00R05JT04',
  'isin': 'RU000A1013Y3',
  'lot': 1,
  'min_price_increment': 0.1,
  'name': ' \xa02',
  'ticker': 'RU000A1013Y3'}, {'currency': 'RUB',
  'figi': 'BBG00PNLY692',
  'isin': 'RU000A100DC4',
  'lot': 1,
  'min_price_increment': 0.1,
  'name': '- 002P  2',
  'ticker': 'RU000A100DC4'}]

Como você pode ver, figi e nome estão lá. Para meus propósitos - mais do que suficiente.

Obter uma lista de operações


Mas o mais interessante é obter uma lista das minhas operações. As seguintes ações caem na operação (no meu caso):

  • PayIn - Reabastecimento de conta de corretagem
  • Pagamento - Retirar dinheiro
  • BuyCard - Compre de um cartão
  • Venda - Venda
  • BrokerCommission - Comissão de Corretores
  • Dividendo - Pagamento de dividendos
  • Imposto - Impostos
  • TaxDividend- Dividend Taxes
  • ServiceCommission - Taxa de serviço

Código para descarregar um portfólio:

from datetime import datetime
from pytz import timezone

#     30  2016 (      )
d1 = datetime(2016, 9, 30, 0, 0, 0, tzinfo=timezone('Europe/Moscow'))  # timezone  .  - 
d2 = datetime.now(tz=timezone('Europe/Moscow'))  #   
ops = client.operations.operations_get(_from=d1.isoformat(), to=d2.isoformat())
Vamos ver o que aconteceu. No meu caso, esse elemento é de interesse
ops.payload.operations[217]
É isso que ele é
{'commission': {'currency': 'USD', 'value': -0.42},
 'currency': 'USD',
 'date': datetime.datetime(2018, 11, 7, 10, 55, 53, 648913, tzinfo=tzoffset(None, 10800)),
 'figi': 'BBG000PSKYX7',
 'id': '42281525510',
 'instrument_type': 'Stock',
 'is_margin_call': False,
 'operation_type': 'BuyCard',
 'payment': -141.05,
 'price': 141.05,
 'quantity': 4,
 'status': 'Done',
 'trades': [{'date': datetime.datetime(2018, 11, 7, 10, 55, 53, 648913, tzinfo=tzoffset(None, 10800)),
             'price': 141.05,
             'quantity': 1,
             'trade_id': '42636800'}]}

Estamos interessados ​​nos campos:

  • data - data da transação
  • figi - código do ativo
  • operation_type - tipo de operação
  • pagamento - o valor da transação. Para impostos ou comissões, é ela quem é indicada. preço enquanto Nenhum
  • preço - preço de um artigo
  • quantidade - quantidade planejada de títulos
  • operações - ofertas de câmbio reais

A questão surgiu imediatamente - por que precisamos de algumas operações se houver preço e quantidade?

Nem tudo é tão simples (plano e fato)


Pelo que entendi, a quantidade indica o número de papéis que eu queria comprar. E o que realmente é comprado está na quantidade [i].

Essa. se você quiser recorrer a transações reais, precisará resolver o que está nas negociações.

Em alguns casos, não há Nenhum - por exemplo, para impostos ou depósitos / retiradas de fundos.

Para obter números reais, é necessário analisar as transações e trocar as transações:

for op in ops.payload.operations: #  
    print(op.figi) # figi    
    print(op.operation_type)   #    
    if op.trades == None:      #    
        print('price:', op.price)       #     
        print('payment:', op.payment)   #  
        print('quantity:', op.quantity) #   
    else:     
        for t in op.trades:                   #     -   
            print('price:', t.price)          #     
            print('quantity:', t.quantity)
    print('--------------')

All Articles