PHPackages                             metaseller/tinkoff-robot-buyer - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. metaseller/tinkoff-robot-buyer

ActiveProject

metaseller/tinkoff-robot-buyer
==============================

Консольное приложение на php, демонстрирующее работу с Tinkoff Invest Api 2, а также реализующее демо-стратегию простейшего робота-покупателя ETF

0.2.2(3y ago)5153Apache-2.0PHPPHP &gt;=7.1.0

Since May 6Pushed 2mo ago2 watchersCompare

[ Source](https://github.com/metaseller/tinkoff-robot-buyer)[ Packagist](https://packagist.org/packages/metaseller/tinkoff-robot-buyer)[ Docs](https://github.com/metaseller/tinkoff-robot-buyer)[ RSS](/packages/metaseller-tinkoff-robot-buyer/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependencies (17)Versions (8)Used By (0)

tinkoff-robot-ETF-buyer-php
===========================

[](#tinkoff-robot-etf-buyer-php)

Проект сделан для демонстрации базовых возможностей работы с Tinkoff Invest Api 2 () через PHP ради фана, а также для участия в конкурсе Tinkoff Invest Robot Сontest (, [https://t.me/tinkoff\_invest\_robot\_contest](https://t.me/tinkoff_invest_robot_contest))

Введение
========

[](#введение)

Вторая версия API Tinkoff Invest в настоящее время позиционируется как gRPC-интерфейс для взаимодействия с торговой платформой Тинькофф Инвестиции.

В настоящее доступны официальные SDK для популярных языков программирования, таких как python (), java (), csharp ().

Я решил для простоты работы сделать небольшое неофициальный SDK для PHP7 () и обертку вокруг него для популярного фреймворка Yii 2 Framework ().

Предполагается дальнейшая доработка функционала SDK путем реализации провайдеров данных аналогичных реализованному провайдеру `InstrumentsProvider` (). Буду очень рад, если найдутся контрибьютеры, которые подключатся к процессу :)

Вообще первой мыслью было снизить порог входа и облегчить жизнь для PHP программистов. PHP - это не лучший выбор для разработки торговых систем, но многие (возможно) захотят использовать функционал Tinkoff Invest Api 2 в своих продуктах/сайтах, разрабатываемых на PHP.

SDK выполнены в виде библиотек и доступны для очень простой установки через composer.

Для Tinkoff Invest Robot Сontest было решено на базе этого SDK создать простенький проект на Yii2 Framework.

Проект работает как консольное приложение на Yii2 Framework и преследует следующие цели:

1. Продемонстрировать возможность использования SDK, снизить порог входа и облегчить жизнь для PHP программистов использующих Tinkoff Invest Api 2.
2. Продемонстрировать простейший базовый функционал работы с Tinkoff Invest Api 2(как подключиться к API, как запросить данные об аккаунте и идентификаторы портфелей, как получить информацию о составе портфеля, как вывести историю пополнения портфеля, как подписаться на стрим свечей)
3. Реализовать логику простейшего торгового робота-покупателя ETF, конфигурируемого через файл конфига, работающего как консольное приложение, вызываемое по `cron`.

Логика работы стратегии робота-покупателя
=========================================

[](#логика-работы-стратегии-робота-покупателя)

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

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

Для примера реализации робот будет регулярно покупать указанный в конфиге ETF, используя вольную реализацию алгоритма Trailing Buy (перефразированный Traling Stop), постоянно готовясь к набору позиции и покупая или на росте, или на отскоке на определенную дельту от локального минимума.

Выбрана простая идея для реализации простой стратегии (легкое понимание, низкий порог входа), не требующей даже подключения СУБД. Робот также не использует стримы, ему достаточно регулярного выполнения по `cron`.

**Как работает робот:**

Для начала, робот конфигурируется через файл `./config/tinkoff-buy-strategy.php` следующими параметрами:

```
[
    'ETF' => [
        'TMOS' => [
            'ACTIVE' => true,
            'INCREMENT_VALUE' => 1, // На сколько мы увеличиваем накопленное количество лотов позиций к покупке через каждый период
            'INCREMENT_PERIOD' => 10, // Период в минутах, через который мы инкрементируем количество лотов позиций к покупке
            'BUY_CHECK_PERIOD' => 1, // Период в минутах, через который мы проверяем возможность покупки накопленного количества лотов позиций
            'BUY_LOTS_BOTTOM_LIMIT' => 5, // Не пытаемся совершить покупку, пока не достигнут указанный накопленный лимит лотов к покупке
            'BUY_TRAILING_PERCENTAGE' => 0.09, //Величина в процентах, на которую текущая цена должна превысить трейлинг цену для совершения покупки
        ],
    ],
];

```

Робот покупает ETF #TMOS () регулярно по следующей логике:

1. Есть число "**накопленное количество лотов к покупке**". В начале каждого торгового для оно равно 0. Затем каждые 10 минут (`INCREMENT_PERIOD`) с начала (и только в ходе) торгов к этому значению добавляется +1 лот (`INCREMENT_VALUE`). Это делается отдельной консольной командой, вызываемое по `cron`.
2. Одновременно с инкрементом запоминается в кэш значение "**последняя цена**" (лучший ASK по стакану). Как только "**накопленное количество лотов к покупке**" стало больше или равно значения `BUY_LOTS_BOTTOM_LIMIT` "**последняя цена**" перестает меняться в этом скрипте.
3. Параллельно каждую 1 минуту (`BUY_CHECK_PERIOD`) отдельной консольной командой вызывается скрипт, который, в случае, если "**накопленное количество лотов к покупке**" &gt;= `BUY_LOTS_BOTTOM_LIMIT` сравнивает "**последнюю цену**" с текущим лучшим ASK по стакану. Если лучший ASK меньше, чем "**последняя цена**" (цена падает), то запомненное значение "**последняя цена**" обновляется на меньшее значение (следует за падением цены, становится "**Traling price**"), и бот ожидает дальнейшего движения цены.
4. Как только лучший ASK в стакане стал больше либо равен значения "**Trailing price**" на `BUY_TRAILING_PERCENTAGE` процентов (цена отскочила вверх или просто растет), происходит выставление лимитной заявки на покупку "**накопленного количество лотов к покупке**" по цене равное лучшему ASK в стакане. А число "**накопленного количество лотов к покупке**" устанавливается в ноль. Факт успешности исполнения заявки НЕ отслеживается.
5. За небольшое количество времени до конца торгов (значение захардкожено в коде), если текущее "**накопленное количество лотов к покупке**" &gt; `BUY_LOTS_BOTTOM_LIMIT / 2`, то форсировано выставляется лимитная заявка на покупку "**накопленного количество лотов к покупке**" по цене "лучший ASK в стакане". То есть "**накопленное количество лотов к покупке**" не переносится на следующий день.

Вот такая незамысловатая стратегия регулярной покупки. Лимитная заявка на "Лучший ASK в стакане" и "небольшие" тестовые объемы практически всегда гарантируют выполнение заявки на покупку.

 [![Покупка ETF TMOS](https://camo.githubusercontent.com/0ac6cf6c54472610d0705d90ccd75ea24ac75f46cd5974f7b046e68dbf43f084/68747470733a2f2f636f6e746573742e6d65746173656c6c65722e72752f746d6f732e6a7067)](https://camo.githubusercontent.com/0ac6cf6c54472610d0705d90ccd75ea24ac75f46cd5974f7b046e68dbf43f084/68747470733a2f2f636f6e746573742e6d65746173656c6c65722e72752f746d6f732e6a7067)

Пункты 1-2 обрабатываются действием `actionIncrementEtfTrailing` () консольного контролера Yii2 `TinkoffInvestController`.

Пункты 3-5 обрабатываются действием `actionBuyEtfTrailing` () консольного контролера Yii2 `TinkoffInvestController`.

Для реализации выбран популярный фреймворк Yii2. Все действия робота, вызовы фоновых заданий по `cron`, ошибки API запросов логируются в стандартной для Yii папке (`./runtime/logs`) в соответствующем лог-таргет файле, а также выводятся в stdout.

У робота нет UI, вы можете следить за ходом работы своего робота через соответствующий лог файл (например открыв его командой `tail -f tinkoff_invest_strategy.log`) или переопределить логику обработчика ошибок и самостоятельно добавить туда отправку нотификации о событиях или неполадках себе через email/telegram или как-то иначе.

Наличие денег для выставления заявки роботом не контролируется. Робот играется сейчас на аккаунте, где выключена маржинальная торговля (с ней робот НЕ тестировался), и если средств для выставления заявки не хватает, то робот логирует соответствующее сообщение об ошибке выставления заявки и покупка просто не происходит.

Технические требования к запуску проекта
========================================

[](#технические-требования-к-запуску-проекта)

Проект сейчас запущен на хостинге VPS Timeweb (НЕ РЕКЛАМА!). Чтобы поиграться самому вам потребуется следующее:

Для начала работы нам потребуется:

- PHP 7.4 или новее (я делал и тестировал на php 7.4 / Ubuntu 18.04.5)
- PECL, Composer версии 2+.

Как установить и настроить composer, если его нет: Лучше делать 'глобальную установку'.

Проект использует зависимость от проектов (, ).

---

СПРАВКА: Моя неофициальная SDK-шка `tinkoff-invest-api-v2-php` содержит уже сгенерированные из proto файлов модели. Просто для информации, если вы захотите собрать проект из proto-файлов с официального репозитория (), то вам понадобиться

1. Установить protoc
2. Собрать плагин grpc\_php\_plugin (см )
3. Вызвать что-нибудь типа:

```
sudo protoc --proto_path=~/contracts_dir/ --php_out=~/models_dic/ --grpc_out=~/models_dir/ --plugin=protoc-gen-grpc=./grpc_php_plugin ~/contracts_dir/*

```

подставив нужные вам директории (для запуска проекта этого НЕ требуется).

---

Далее нам понадобится расширение grps.so для PHP ().

```
sudo pecl install grpc

```

а после не забываем в php.ini добавить (лучше в оба, в обычный и cli)

```
extension=grpc.so

```

А если вам необходимо логгировать исполнение, то можно также добавить в php.ini

```
grpc.grpc_verbosity=debug
grpc.grpc_trace=all,-polling,-polling_api,-pollable_refcount,-timer,-timer_check
grpc.log_filename=/var/log/grpc.log

```

Само собой не забыть

```
sudo touch /var/log/grpc.log
sudo chmod 666 /var/log/grpc.log

```

Я в качестве сервиса кеша использовал у себя Redis, которые настроил доступным с вот таким конфигом:

```
[
    'hostname' => 'localhost',
    'port' => 6379,
    'database' => 0,
]

```

Если Вам лень возиться с Redis, вы можете в конфигах проекта (см , ) заменить сервис кеша на `yii\caching\FileCache` (), не забыв выпилить из конфига Redis ().

PS: Ну и в целом, рано или поздно придется ознакомиться с документацией по GRPC:

1. Quick start with PHP -&gt;
2. Basic tutorials -&gt;

PSS: Вот здесь вы можете видеть общий список используемых для запуска проекта зависимостей:

Пошаговая установка и запуск проекта
====================================

[](#пошаговая-установка-и-запуск-проекта)

1. Будем устанавливать используя composer.

На подготовленном сервере переходим в нужную нам папку, например

```
cd /var/www/

```

и выполняем команду:

```
composer create-project --prefer-dist --stability=dev metaseller/tinkoff-robot-buyer contest.metaseller.local

```

в папку `contest.metaseller.local` будет скачан/установлен проект и подтянуты автоматически все зависимости.

Заходим в эту папку

```
cd contest.metaseller.local

```

и выполняем команду

```
./init

```

если не выполняется делаем

```
sudo chmod 755 init

```

и запускаем. Эта команда инициализирует окружение (выбираем 0 - dev)

```
Yii Application Initialization Tool v1.0

Which environment do you want the application to be initialized in?

  [0] dev
  [1] prod

  Your choice [0-1, or "q" to quit] 0

```

Затем на всякий случай проверяем/выставляем права на папку `logs`:

```
cd /var/www/contest.metaseller.local/runtime
mkdir logs
sudo chmod -R 777 logs

```

Далее заходим в директорию `config` и настраиваем свое окружение:

```
vim credentials.php

```

(кого пугает `vim` - используйте `nano` :)) Прописываем ваш токен (`secret_key`) и идентификатор портфеля/аккаунта (`account_id`):

```
