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 daAPIOutra descriçãoObtendo 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:- Faça login na sua conta em tinkoff.ru
- Vá para a seção de investimentos
- Vá para as configurações
- A função "Confirmação de transações por código" deve ser desativada
- 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.
- 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.
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
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()
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
d1 = datetime(2016, 9, 30, 0, 0, 0, tzinfo=timezone('Europe/Moscow'))
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 interesseops.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)
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('--------------')