Skip to content

homm/invest

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

46 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Что это

Это приложение командной строки, которое использует Open API Тинькофф Инвестиций для получения информации о вашем портфеле, чтобы вести точный учет. Оно не предназначено и не совершает никаких сделок, использует только методы API для чтения.

Зачем это

Инвестируя какое-то время с помощью сервиса Тинькофф Инвестиции (реферальная ссылка) я задался вопросом, а насколько мои инвестиции эффективны.

На первый взгляд кажется, что узнать это довольно просто, ведь в шапке приложения показывается стоимость моего текущего портфеля и изменение его стоимости.

tinkoff application header

Но у этого отображения есть огромное количество недостатков:

  • Самое главное — не учитываются уже проданные бумаги
  • Не учитывается разница в курсе на момент покупки бумаги
  • Не учитываются купоны и дивиденды
  • Не учитывается комиссия брокера и налоги

Поэтому я решил создать удобный инструмент для получения истории всех операций в портфеле, что позволило вести учет всего вышеперечисленного и наглядно видеть успехи инвестирования.

Безопасность

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

  • Токен передается в явном виде в заголовке запроса (issue)
  • Нет разграничения прав токена, любой токен может быть использован для операций с вашим портфелем (issue)

Поэтому я считаю особенно важно не допускать компрометации токена.

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

Для шифровки токена используется алгорит шифрования Salsa20, на текущий момент не имеющий доказанный уязвимостей, а к паролю предъявляются строгие треботвания по входящим символам и длине.

Установка

Приложение написано на языке Python, для его работы понадобится интерпретатор не ниже версии 3.7.

$ git checkout https://github.com/homm/invest.git
$ cd invest
$ python3 -m venv env && source ./env/bin/activate
$ pip install -r requirements.txt

Эти команды создают для приложения отдельное виртуальное окружение, куда будут установлены необходимые для работы пакеты. Чтобы работать с приложением, вам нужно будет один раз активировать виртуальное окружение, когда вы открываете консоль:

$ source ./env/bin/activate

Токен и первый запуск

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

$ ./run.py set_token
Seems like this is the first run. Please fill the credentials to continue.
At first, you need to choose a password.

Password should be at least 12 ASCII chars length.
It can't consist of digits only. At least one char in UPPER and lower case is required.
New password: 🔒

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

Now please paste the token once.
Do not store it anywhere else.

Paste token: 🔒

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

Получить токен можно в настройках аккаунта Тинькофф Инвестиций. На данный момент этот блок выглядит так:

tinkoff invest settings. Issue token

Для сохранности токена рекомендуется закрыть страницу с настройками аккаунта сразу после того, как вы скопируете токен в буфер обмена. А после того как вы вставите токен из буфера обмена в приложение и нажмете энтер, рекомендуется скопировать в буфер обмена любой другой текст, чтобы потом случайно не вставить токен куда-то ещё.

После окончания работы приложение выведет что-то вроде этого:

Put this code to the `conf.py` file:
# ------------- conf.py ------------
enc_token_nonce = b'\r}@\xae<$m\xee'
enc_token = (
    b"\x13\xb7\x06\x0e\xc6\x01V\x13\xa4\xeby\x1a?.T\xa9E'J\xa6S\xdf\xfbI\xc2U["
    b'P\xc3\xe3\x85\xaf\xb7v\x99<\\\xf5\xa34\xe4OH\xe6ZP"\xf0'
)

Это и есть зашифрованный токен. Создайте файл conf.py в этой же директории и вставьте в него эти строки. Как альтернатива, приложение можно было запустить так:

$ ./run.py set_token >> conf.py

Тогда файл conf.py создастся автоматически, ничего копировать не нужно будет.

Отозвать ранее выпущенный токен можно на странице безопасности аккаунта банка. На данный момент этот блок выглядит так:

tinkoff account settings. Release token

Доступные команды

Задать новый токен

$ ./run.py set_token -h
usage: run.py set_token [-h]

Эта команда рассмотрена выше. Она запускается в самом начале, если токен не задан.

Сменить пароль

$ ./run.py change_password -h
usage: run.py change_password [-h]

Запрашивает старый пароль, которым уже зашифрован текущий токен, а затем новый пароль. Выводит в конце такие же строки, как set_token, так как смена пароля по сути является сменой зашифрованного токена.

Вывести портфель

$ ./run.py portfolio -h
usage: run.py portfolio [-h]

Выводит содержимое портфеля в виде таблицы с символами табуляции в качестве разделителя столбцов. Пример:

$ ./run.py portfolio 
Password: 

Ticker	Name	Quantity	Price	Currency
IVZ	Invesco	36	7.92	USD
NLMK	НЛМК	90	124.84	RUB
TSM	Taiwan Semiconductor Manufacturing	4	46.90	USD
FNKO	Funko Inc	15	3.30	USD
PLCE	Children's Place Inc The	7	15.30	USD
XLNX	Xilinx	5	78.73	USD
T	AT&T	7	27.51	USD
PHOR	ФосАгро	8	2429.62	RUB
TCS	TCS Group (Tinkoff Bank holder)	21	11.20	USD
GLW	Corning	10	17.95	USD
CSCO	Cisco	3	39.10	USD
RU000A101GW3	ЛЕГЕНДА выпуск 2	20	938.24	RUB
RU000A101HU5	Брусника выпуск 1	10	937.13	RUB
FXTB	Казначейские облигации США (USD)	10	787.30	RUB
FXIT	Акции компаний IT-сектора США	10	5787.10	RUB
FXRL	Акции российских компаний	11	2606.77	RUB
USD	Доллар США	84	76.49	RUB

Вывести историю операций

$ ./run.py log -h
usage: run.py log [-h] --from DATE_FROM [--to DATE_TO] [--group]

optional arguments:
  --from DATE_FROM  The start date for the log. Required. Should be in
                    1999-12-31 format. Day or month could be omitted. In this
                    case `--from` also sets the default value for `--to`
                    argument. For example, `--from 2020-02-01 --to 2020-03-01`
                    could be replaced with just `--from 2020-02`.
  --to DATE_TO      The finish date for the log, not including. Should be in
                    1999-12-31 format. Default is one day in the future (show
                    records until now). Day or month could be omitted. `--from
                    2020-04 --to 2020-06` means "show all records for April
                    and May".
  --group           Groups records with the same Ticker, Name, and Currency.
                    This can significantly reduce number of the records.
                    Quantity and Sum columns will be summed up.

Выводит историю операций в виде таблицы с символами табуляции в качестве разделителя столбцов. Пример:

$ ./run.py log --from 2020-03-01
Password: 

Ticker	Name	Date	Quantity	Sum	Currency
$TAX	TaxBack	2020-03-02		400.00	RUB
ATVI	BrokerCommission	2020-03-04		-0.12	USD
ATVI	Activision Blizzard	2020-03-04	-4	248.24	USD
$TAX	Tax	2020-03-04		-252.00	RUB
T	BrokerCommission	2020-03-09		-0.05	USD
T	AT&T	2020-03-09	3	-103.50	USD
USD	BrokerCommission	2020-03-10		-0.25	USD
USD	Доллар США	2020-03-10	-500	36000.00	RUB
RU000A101HU5	BrokerCommission	2020-03-12		-4.84	RUB
RU000A101HU5	Брусника выпуск 1	2020-03-12	10	-9680.00	RUB
FXTB	BrokerCommission	2020-03-13		-3.68	RUB
FXTB	Казначейские облигации США (USD)	2020-03-13	10	-7350.00	RUB
$COM	ServiceCommission	2020-03-16		-3.96	USD
NLMK	BrokerCommission	2020-03-16		-2.17	RUB
NLMK	НЛМК	2020-03-16	40	-4340.80	RUB

Обратите внимание, что аргумент --from является обязательным. Аргумент --to указывает дату, до которой (не включительно) вы хотите получить историю. Можно опустить день или месяц (--from 2020-02), тогда --to будет автоматически установлен на конец промежутка (2020-03-01).

--group позволяет сгруппировать все похожие операции в одну. Например, если в указанный промежуток времени вы продавали и покупали какую-то бумагу, то все эти операции будут сгруппированы в одну, значения в столбцах Quantity и Sum будут проссумированны, а в Date будет указана дата первой из них. При этом комиссия по этой же бумаге тоже будет проссумирована, но в другой строке. То же самое произойдет с купонами и дивидендами. Это позволяет существенно сократить количество строк за большие промежутки.

Работа с таблицами

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

log table

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

Вложенные средства в конкретную бумагу

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

=−SUMIFS(Сделки::Сумма; Сделки::Тикер; A9)

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

instrument invest

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

Прочие расходы и прибыль

Точно так же можно посчитать все выплаченные налоги и комиссию за обслуживание:

=−SUMIFS(Сделки::Сумма; Сделки::Тикер; "$TAX")
=−SUMIFS(Сделки::Сумма; Сделки::Тикер; "$COM")

Эта же функция поможет узнать количество всех полученных дивидендов или купонов. Для этого нужно использовать поиск по подстроке:

=−SUMIFS(Сделки::Сумма; Сделки::Название; "*(Dividend)")
=−SUMIFS(Сделки::Сумма; Сделки::Название; "*(Coupon)")

Текущая стоимость бумаг

В Numbers есть специальная функция для работы с котировками ценных бумаг.

=STOCK("TICKER"; price)

К сожалению у нее очень много проблем: редкое обновление данных, нет облигаций, тикеры некоторых бумаг не совпадают с тикерами в Тинькове. Иногда она может неделю не обновлять позицию, иногда начинает возвращать ошибку. Самое веселое было с российскими ETF: цена на них возвращалась то в долларах, то в рублях в разное время суток.

Поэтому было принято решение выгружать текущую стоимость бумаг у брокера (команда portfolio).

portfolio table

Чтобы найти стоимость конкретной бумаги в этой таблице можно воспользоваться функцией VLOOKUP:

=VLOOKUP(A52; Тикер:Цена; 4; FALSE)

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

instrument price

About

No description or website provided.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages