API Тиньков.Инвестиции. Первые шаги

    Практически с первых дней я стал клиентом Тиньков.Инвестиции.

    И с этого же момента меня терзают смутные сомнения — отражает ли личный кабинет объективную реальность?

    Дело в том, что я покупаю ценные бумаги, номинированные в долларах, но в ЛК цены всех активов отображаются в долларах, а итоговая стоимость портфеля в рублях.

    И мне непонятно, это доллар вырос или я такой результативный инвестор?

    А как же комиссии, налоги и прочие дивиденды?

    Вот бы взять все мои сделки и расписать по ФИФО, как в складском учете… А сверху положить полученные дивиденды, а потом вычесть налоги.

    Вот тогда я и увижу понятный мне результат.

    Оказалось, у Тинькова есть API, которое позволяет писать торговых роботов (мне это совсем не интересно), а также загружать данные по своему портфелю и операциям.

    У этого API есть официальное описание, но мне не все было понятно, пришлось разбираться.
    Результаты этих разборок представляю вашему вниманию.

    Полезные ссылки:

    Описание API
    Еще описание

    Получение токена и установка библиотеки


    Перед началом работы нужно установить библиотеку и получить токен.

    Установка библиотеки:

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

    Цитирую официальную инструкцию по получению токена:

    1. Зайдите в свой аккаунт на tinkoff.ru
    2. Перейдите в раздел инвестиций
    3. Перейдите в настройки
    4. Функция «Подтверждение сделок кодом» должна быть отключена
    5. Выпустите токен OpenApi для биржи и Sandbox. Возможно система попросит вас авторизоваться еще раз, не беспокойтесь, это необходимо для подключения робота к торговой платформе.
    6. Скопируйте токен и сохраните, токен отображается только один раз, просмотреть его позже не получится, тем не менее вы можете выпускать неограниченное количество токенов.

    На момент написания статью токен выдавался на странице www.tinkoff.ru/invest/settings, кнопка в нижней части страницы.

    image

    С токеном для песочницы у меня возникали ошибки, поэтому я начал экспериментировать с боевой версией. Чего и вам желаю (Осторожно: не купите-продайте случайно что-то лишнее).

    Авторизация


    from openapi_client import openapi
    
    token = 'тут нужно вставить ваш токен'  
    client = openapi.api_client(token)

    Эти две строки делают все, что нам нужно.

    Дальше работаем с переменной client.

    Что у нас в портфеле


    Получим содержимое нашего вашего портфеля:

    pf = client.portfolio.portfolio_get()

    Посмотрим основные данные первого элемента:

    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)

    В моем случае это:

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

    value — Цена бумаги
    balance — Кличество бумаг в портфеле, value и currency — их денежное выражение.

    figi — Financial Instrument Global Identifier (Финансовый Глобальный Идентификатор инструмента)
    ticker — Тикер актива.

    По этим данным мы можем узнать человекочитаемое название актива.

    Для данного запроса нам это не нужно (см. поле name), но в других случаях пригодится.

    Получаем название бумаги по FIGI и тикету


    # Получение инструмента по FIGI
    instr = client.market.market_search_by_figi_get('BBG000BWPXQ8') 
    instr

    Получаем:

    {'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'}

    Эта API-функция у меня работает как надо. Видим, что 'BBG000BWPXQ8' -> 'British American Tobacco'.

    А вот поиск названия актива по тикеру у меня не работает :(((

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

    Разработчики предложили обновить библиотеку, но даже после этого не взлетело.

    Качаем справочник ценных бумаг


    Впрочем, я решил этот вопрос кардинально. Скачал у Тинькова полный справочник торгуемых активов:

    # Получение списка облигаций
    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]
    получил
    [{'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'}]

    Как видим, figi и name там есть. Для моих целей — более чем достаточно.

    Получаем список операций


    А вот самое интересное — получить список моих операций. В операции (в моем случае) попадают следующие действия:

    • PayIn — Пополнение брокерского счета
    • PayOut — Вывод денег
    • BuyCard — Покупка с карты
    • Sell — Продажа
    • BrokerCommission — Комиссия брокера
    • Dividend — Выплата дивидендов
    • Tax — Налоги
    • TaxDividend- Налоги c дивидендов
    • ServiceCommission — Комиссия за обслуживание

    Код для выгрузки портфеля:

    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())
    Посмотрим, что получилось. В моем случае, представляет интерес этот элемент
    ops.payload.operations[217]
    Вот что он собой являет
    {'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'}]}

    Нас интересуют поля:

    • date — дата сделки
    • figi — код актива
    • operation_type — тип операции
    • payment — сумма операции. У налогов или комиссий указана именно она. price при этом None
    • price — цена одной бумаги
    • quantity — плановое количество бумаг
    • trades — реальные биржевые сделки

    Сразу возник вопрос — зачем нам какие-то trades, если есть price и quantity?

    Все не так просто (план и факт)


    Как я понял, в quantity указано то количество бумаг, которые я хотел купить. А то, что фактически куплено, лежит в trades[i].quantity.

    Т.е. если хотите обратится к фактическим сделкам, нужно перебрать то, что лежит в trades.

    В ряде случаев, там None — например, для налогов или вводов/выводов средств.

    Чтобы получить настоящие цифры, нужно смотреть и в сделки, и в биржевые операции:

    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('--------------')
    AdBlock has stolen the banner, but banners are not teeth — they will be back

    More
    Ads

    Comments 51

      +1
      Оказалось, у Тинькова есть API, которое позволяет писать торговых роботов (мне это совсем не интересно)

      А вот мне, наоборот, оказалось интересно. Начал возиться с этим чуть больше недели назад. Написал программу, которая сигнализирует о необычных состояниях на рынке, дальнейшие решения я уже принимал вручную. В принципе, понравилось.


      Главная проблема — API очень простой, но одновременно и очень сырой. Часто тормозит и глючит. Поиграться — нормально, но если торговать профессионально, то есть варианты и получше.

        +4
        то есть варианты и получше

        Был бы рад ссылкам

          0

          Специализированные брокеры. Полноценно пока не интересовался этой темой, поэтому ссылок не дам.

            +1
            Брокеры дают Квик, там есть экспорт и импорт. По идее, должно хватить на любого робота, если он, разумеется не HFT.
              0

              Там в квике есть lua, на которой худо бедно можно накорябать робота, графики с индивидуальными индикаторами, или шлюз в другие миры.
              Но квик что-то подтормаживает, знающие люди говорят, для htf надо брать плазу2 и колокейшн у брокера.

                +2
                знающие люди говорят, для htf надо брать плазу2 и колокейшн у брокера

                Знающие люди подсказывают, что все эти колокейшены с плазой2 только самая верхушка айсберга. Железо и софт (в целом, вместе со всем) для hft тянут на сотни тысяч и миллионы долларов. Обычный сервак в колокейшене с плазой 2 был HFT примерно с десяток лет назад. Сейчас он уже никак не вытянет звание HFT в борьбе со спецжелезом, которое последние несколько лет все игроки используют для HFT.
                К сожалению, HFT сейчас удел очень крупных компаний.
                0

                Рано или поздно пытливый программистский ум все равно захочет хоть немного HFT — бота с реакцией в несколько секунд. О миллисекундах, к сожалению, речи не идёт — это удел кровавого энтерпрайса и крупных игроков.

                  0
                  Это достижимо и в Квике. Сейчас логи открыл — меньше секунды от принятия решения до подтверждения ордера из ИТС.
                    0

                    Я имею в виду тормоза самого Тинькоффа как сервиса. В обычном режиме там тоже всё исполняется в момент, но в периоды высокой активности на бирже, когда самое лучшее время делать деньги, он встаёт колом.


                    Но в целом я Т не особо за это ругаю: у него изначально была другая направленность — не на профессиональных трейдеров, а просто на желающих пощупать возможность заработка на инвестициях в долгосроке. API для торговли они предоставили совсем недавно.

                    0
                    А раз так — то зачем нужны все эти плазы, колокоейшны и прочий развод?
                      0
                      Так это не развод со стороны брокера. Это люди сами себя обманывают)
                      Колкейшен, плаза, квик и прочие технологии нужны больше для надежности.
                      Сервер у брокера это уменьшение вляния сети на обработку запросов. Опять же повышение отклика. Хороший протокол (таже плаза) это скорость обработки ордеров.
                      Конечно речь идёт не о микросекундах современных HFT систем, но все же сильно лучше и надёжнее сотен, а то и тысяч миллисекунд при обработке команд через классический Rest через интернет.
                      Да и софт для трейдинга точат именно под такие протоколы в основном. Т.е. получаем еще и единообразие, что тоже полезно.
                        –2
                        Ну вот представьте: накупили вы этих плазов, поставили колокейшн в золотом корпусе, запустили скрипты и ждете. А на другом конце интернета сидят условные Мамут с Усмановым, смотрят на экраны своих HFT и ржут над вами.

                        Почему ржут? А потому что пока скрипит ваша плаза в колокейшне, у них уже миллиончик+миллиончик+миллиончик…
                          0
                          Ну вы сейчас несусветную глупость сказали… да еще эти идиотские методы чёрной риторики про золотые сервера… ну вот зачем? ))
                          По вашей логике надо после рождения сразу на кладбище ползти, ведь зачем вся эта суета, когда во круг миллионеры делают свои миллионы, а миллиардеры свои миллиарды…
                          Вы, если не секрет, какой темой зарабатываете на жизнь?
                          Не стрёмно ей заниматься, когда во круг столько успешных миллиардеров, которые, если бы они конечно знали про ваше существование, ржут над вашими потугами на их фоне? ))
              0
              Добрый день!
              Можете скинуть пример этой программы?
              +1

              А в режиме read-only через API Тинькофф можно считать только свои позиции?

                0
                Токен можно получить, только будучи клиентом.
                Можно стать клиентом, но не торговать.
                  +1

                  Имел ввиду получение собственных открытых позиций — цена покупки, дата, количество.
                  Без возможности торговли. Для синхронизации со своими сервисами по учету.

                    +3
                    API не заставляет торговать. Я именно в таком режиме использую.
                +1

                Кто-нибудь знает — Тинькофф единственный брокер, которые имеет своё открытое апи?
                В первую очередь интересен только просмотр позиций без возможностей торговли.

                  0
                  У IB есть апи
                    0
                    А IB это кто?
                      0
                      Interactive Brokers
                      +1

                      В IB и так нет проблем с экспортом отчетов.
                      Проблема с рос. брокерами — нет единой формы, они периодически меняются, а сбербанк (бывший тройка диалог) — так в плане отчетов вообще ловить нечего — невозможно даже определить начальную цену позиции.

                      0
                      У всех нормальных брокеров есть свое АПИ.
                        0

                        И российских?

                          0
                          Конечно.
                            +2

                            И оно открыто? А кто кроме Тинькова имеет открытое апи?

                              0
                              Вот тут становится непонятно, что вы подразумеваете под «Открытым АПИ».
                              Какой вообще смысл имеет закрытое АПИ? Оно же для клиентов предназначено.
                              Понятно, что для подключения надо пройти регистрации и прочее. Как и у Тинькова собственно.
                              Без авторизации оно просто не имеет смысла.
                              Например iti capital имеет АПИ.
                                +1

                                Тинькофф Инвестиции, ITI Capital (АО «ИК «Ай Ти Инвест»).
                                А знаете ещё кто имеет апи?

                                  +1

                                  Tradernet(freedom finance)

                                    0

                                    А после слияния с Фридом Финанс апи сохранилось?

                                      0
                                      Не подскажу, описание API есть, но в работе не проверял
                                  0
                                  Вот тут становится непонятно, что вы подразумеваете под «Открытым АПИ».

                                  Ну для меня это значит, что имеется подробная документация по протоколу и возможность написания собственных клиентов, а не только плагинов и скриптов для квика.

                            0
                            У БКС, как мне кажется, API только к московской бирже.
                            А я хочу к Питерской
                              0

                              Я хотел бы через API получать свои открытые позиции в режиме только чтения.

                          +1
                          И мне непонятно, это доллар вырос или я такой результативный инвестор?

                          А что в итоге оказалось?
                            +1
                            Результат +5% (в долларах, за 3 года), но я большую часть акций в 2018 купил.
                            Самолюбие и душевный покой почти не пострадали.
                              0
                              Ясно, спасибо.
                            0
                            Одно но: если вы покупали инструменты из расширенного списка, в журнале операций по этим инструментам не будет, и для статистики API уже не годится
                              0

                              Я себе написал замену Excel для учёта сделок.
                              Всё считает. Можно посмотреть состояние портфеля на любую дату. Главное все сделки в систему завести… Можно отчёт брокера импортировать. Зацените кто хочет, https://izi-invest.ru

                                0

                                Относительно "а итоговая стоимость портфеля в рублях" — у Тинькофф есть переключатель (в мобильных приложениях на значок рубля нажать, если не путаю), можно и в долларах смотреть

                                  0
                                  Оказалось, у Тинькова есть API,

                                  Вах, не прошло и полгода, что называется…

                                  Когда я, будучи их клиентом, спросил о кусочке API для всего-то ежедневного получения курса евродоллара, меня первую неделю не могли понять вообще, вторую отвечали безопасники (упс? я вообще-то технарей спрашивал) разных уровней и задавали острожные, хоть и дурацкие на взгляд программиста, вопросы, а на третью посоветовали… парсить их главную страницу, где выводится курс…
                                  Передовой банк, что уж тут.
                                    0
                                    Подскажите, не пойму никак. portfolio_get() возвращает пустой портфель почему-то, а market_search_by_ticker_get() возвращает инфу про бумагу без цены. А у меня задача получить цену акции. Можете подсказать как?
                                      0
                                      Попробуйте market.market_orderbook_get('BBG000C3J3C9', 1)
                                        0
                                        Огромное спасибо за помощь! Кому интересно — вот рабочий код:
                                        client = openapi.api_client(token)
                                        figi = client.market.market_search_by_ticker_get('T').payload.instruments[0].figi
                                        price = client.market.market_orderbook_get(figi, 1).payload.last_price
                                      0
                                      Приветствую, коллега. Так вышло, что почти одновременно с вами я начал вынашивать идею о написании своего клиента для OpenAPI на Ruby. Как раз сегодня я зарелизил свою поделку, консольный клиент для вывода портфолио брокерского счёта.

                                      Моя задача — сделать консольную утилиту для просмотра полной итоговой суммы и процентов моего портфеля. Однако, столкнулся с несколькими недостатками данного API.

                                      1. Отсутствие итоговой суммы и процентов доходности в API. Хотя бы в приближённом виде. А это то, ради чего я вообще начал писать код.
                                      2. Список позиций на счёте вроде хорош, но в нём не хватает процентов доходности и оценочной стоимости каждой позиции. Пришлось писать кучу кода для вычисления процентов.
                                      3. Каждая позиция в своей валюте, это вроде понятно и правильно. Но когда я собрался посчитать общую стоимость, это вылилось в нетривиальную задачу. Оказывается в API нет биржевого курса долларов/евро. Пришлось считать так: брать данные своих активов доллар и евро и через сумму и доходность высчитывать курс к рублю. Потом я прохожу по списку позиций и каждую позицию умножаю на курс к рублю, чтобы получить рублёвый итог.

                                      По итогу несмотря на кучу неточных вычислений я получил довольно точные цифры, отличающиеся от приложения на доли процентов. И мне порой даже кажется, что мои данные чуть точнее, поскольку я сам вывел все формулы и сам по ним считаю свои денежки :)

                                      Во избежание ошибок float-вычислений, использую BigDecimal — этакий float с гарантированной десятичной точностью. То есть складывая 1.1 + 1.2 получится 2.3, а не 2.2999999999999.

                                      API в целом рабочее, но немного бесполезненькое. Иногда замирает, иногда некоторые поля приходят нулевые, пару раз ловил 500. Может через вебсокеты получится что-то интересное добыть.
                                        0
                                        Я курс доллара тоже у Тинькова беру

                                        cd2 = datetime.now(tz=timezone('Europe/Moscow'))
                                        cd1 = cd2 — timedelta(days=3)
                                        cur = client.market.market_candles_get('BBG0013HGFT4', cd1, cd2, 'day')

                                        if len(cur.payload.candles) == 0:
                                        print('')
                                        else:
                                        print(cur.payload.candles[len(cur.payload.candles) — 1])

                                        Это инструмент USD000UTSTOM — курс с поставкой валюты «завтра», но меня устраивает.

                                        instr = client.market.market_search_by_figi_get('BBG0013HGFT4')
                                        print(instr)
                                        0
                                        У тинькова продвинутый подход к API: они используют OpenApi довольно новой версии 3.0. Я взялся было за ейный чемодан за написание api клиента для раста (Rust), но оказалось, что swagger-codegen поддерживает раст только в ветке для OpenApi 2.0.
                                        В итоге я написал рабочий модуль генератора для OpenApi 3.0, который генерит вполне себе апишечку для раста через swagger.yaml. Вот он: rust-swagger-codegen_v3
                                        Из последнепофикшенного — исправил передачу даты в запросе.
                                          +1
                                          Короче поюзал я этот апи и разочаровался.
                                          Кстати поиграться с ним можно здесь tinkoffcreditsystems.github.io/invest-openapi/swagger-ui без всяких скачиваний непонятных библиотек…
                                          Использовать его проще, чем это описано во всяких инструкциях. Просто посылаешь post запрос на нужный адрес с нужным заголовком и получаешь данные в json формате…

                                          А разочаровался в том, что через команду /operations нельзя получить сведения о движениях денежных средств (ввод, вывод дс, получение дивидендов, купонов и т.д....) Из-за этого для меня этот апи перестал быть интересным.
                                          А ещё там код бумаги выдаётся не привычный ISIN, а какой-то экзотический FIGI… Я смог через тот же апи сделать таблицу соответствия ISIN и FIGI, но как-то заморочно всё выходит…
                                          А ещё нет ограничений по правам токена. Если выпустил токен, то он либо sandbox, который вообще ни чего не может, либо боевой, который вообще всё может (покупать, продавать), а мне нужен к примеру токен, который может только получать историю сделок, но такого нет.
                                            0
                                            Да, я тоже figi->isin конвертирую

                                          Only users with full accounts can post comments. Log in, please.