metaseller / tinkoff-robot-buyer
一个基于PHP的控制台应用程序,演示了如何使用Tinkoff Invest Api 2,同时实现了ETF简单购买机器人的演示策略。
Requires
- php: >=7.1.0
- ext-curl: *
- ext-exif: ^7.2
- ext-fileinfo: *
- ext-imagick: ^3.4
- ext-intl: *
- ext-json: *
- ext-pdo: ^7.4
- metaseller/tinkoff-invest-api-v2-yii2: >=0.1.5
- omnilight/yii2-scheduling: *
- yiisoft/yii2: ~2.0.14
- yiisoft/yii2-bootstrap4: ~2.0.0
- yiisoft/yii2-redis: ^2.0
- yiisoft/yii2-swiftmailer: ~2.0.0 || ~2.1.0
Requires (Dev)
- codeception/codeception: ^4.0
- codeception/module-asserts: ^1.0.0
- codeception/module-filesystem: ^1.0.0
- codeception/module-yii2: ^1.0.0
- codeception/specify: ~0.4.6
- codeception/verify: ~0.5.0 || ~1.1.0
- symfony/browser-kit: >=2.7 <=4.2.4
- yiisoft/yii2-debug: ~2.1.0
- yiisoft/yii2-faker: ~2.0.0
- yiisoft/yii2-gii: ~2.2.0
- yiisoft/yii2-shell: ^2.0
This package is auto-updated.
Last update: 2024-09-19 05:15:34 UTC
README
该项目是为了展示与Tinkoff Invest Api 2(https://www.tinkoff.ru/invest/open-api/)的基本操作能力而制作的,通过PHP实现,同时也是为了参加Tinkoff Invest Robot Contest(https://meetup.tinkoff.ru/event/tinkoff-invest-robot-contest/,https://t.me/tinkoff_invest_robot_contest)而设计的。
简介
Tinkoff Invest API的第二个版本目前定位为与Tinkoff Investment交易平台的gRPC接口。
目前,已提供适用于Python(https://github.com/Tinkoff/invest-python)、Java(https://github.com/Tinkoff/invest-api-java-sdk)、C#(https://github.com/Tinkoff/invest-api-csharp-sdk)等流行编程语言的官方SDK。
为了简化操作,我决定制作一个小型的非官方SDK,用于PHP7(https://github.com/metaseller/tinkoff-invest-api-v2-php)以及用于流行框架Yii 2 Framework的包装器(https://github.com/metaseller/tinkoff-invest-api-v2-yii2)。
计划通过实现类似InstrumentsProvider
(https://github.com/metaseller/tinkoff-invest-api-v2-php/blob/main/src/providers/InstrumentsProvider.php)的数据提供程序来进一步改进SDK的功能。如果有人愿意加入这个过程,我将非常高兴 :)
最初的想法是降低门槛,让PHP开发者更容易使用。虽然PHP不是开发交易系统的最佳选择,但许多开发者可能会希望在PHP产品/网站上使用Tinkoff Invest Api 2的功能。
SDK以库的形式提供,可以通过composer轻松安装。
基于此SDK,决定在Yii2 Framework上创建一个简单的项目,以参加Tinkoff Invest Robot Contest。
该项目作为一个控制台应用程序运行,旨在
- 展示SDK的使用方法,降低门槛,让使用Tinkoff Invest Api 2的PHP开发者更容易使用。
- 展示使用Tinkoff Invest Api 2的基本功能(如何连接到API,如何请求账户和投资组合标识符,如何获取投资组合信息,如何获取投资组合充值历史,如何订阅K线流)。
- 实现一个简单的ETF购买机器人的逻辑,通过配置文件配置,作为控制台应用程序运行,可以通过cron调用。
购买机器人的工作策略
实现的机器人不是一个赚取买卖差价的 scalp robot。这是一个购买ETF的机器人(在微小修改后也可以购买其他工具,但这只是作业!) :)
一种流行的投资策略是定期购买并持有你相信的东西。定期意味着在上涨和下跌时都购买,而不是试图捕捉底部或趋势。均匀性可以消除所有这些。而且,位置组合越均匀,越好!我们的机器人会将这个想法推向极致 :)
为了示例实现,机器人将定期购买配置中指定的ETF,使用自由实现的跟踪买入算法(重新表述的跟踪止损),随时准备建仓,并在上涨或回调到局部最低点的一定范围内购买。
选择了简单易懂、门槛低的简单策略实现,甚至不需要连接数据库。机器人也不使用流数据,只需要按照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(https://www.tinkoff.ru/invest/etfs/TMOS/)
- 有一个名为 "待购买累计手数" 的数值。在每次交易开始时,它等于0。然后,每10分钟(
INCREMENT_PERIOD
)从交易开始(只在交易期间)增加1手(INCREMENT_VALUE
)。这是通过一个单独的控制台命令执行的,由cron
调用。 - 同时,将 "最后价格"(最佳ASK价格)的值保存在缓存中。一旦 "待购买累计手数" 大于或等于
BUY_LOTS_BOTTOM_LIMIT
,则在此脚本中停止更改 "最后价格"。 - 同时,每分钟(
BUY_CHECK_PERIOD
)通过单独的控制台命令调用一个脚本,该脚本如果 "待购买累计手数" >=BUY_LOTS_BOTTOM_LIMIT
,则将 "最后价格" 与当前最佳ASK价格进行比较。如果最佳ASK价格小于 "最后价格"(价格下跌),则将保存的 "最后价格" 更新为较小的值(跟随价格下跌,变为 "跟踪价格"),然后机器人等待价格进一步变动。 - 一旦最佳ASK价格在价格牌中变为大于或等于 "跟踪价格" 的
BUY_TRAILING_PERCENTAGE
百分比(价格反弹或持续上涨),则提交一个购买 "待购买累计手数" 的限价订单,价格为最佳ASK价格。然后将 "待购买累计手数" 设置为0。不跟踪订单执行成功的事实。 - 在交易结束前的一小段时间内(值在代码中硬编码),如果当前 "待购买累计手数" >
BUY_LOTS_BOTTOM_LIMIT / 2
,则强制提交一个限价订单购买 "待购买累计手数",价格为 "最佳ASK价格"。也就是说,"待购买累计手数" 不会转移到第二天。
这就是这样一个简单的定期购买策略。限价订单和 "小的" 测试量几乎总是能保证购买订单的执行。
第1-2点由actionIncrementEtfTrailing
(https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L175)控制台控制器 Yii2 TinkoffInvestController
处理。
第3-5点由actionBuyEtfTrailing
(https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L268)控制台控制器 Yii2 TinkoffInvestController
处理。
为了实现,选择了一个流行的框架Yii2。所有机器人的操作、通过cron
调用的后台任务、API请求错误都记录在Yii的标准文件夹(./runtime/logs
)中相应的日志目标文件中,同时也输出到stdout。
机器人没有UI,您可以通过相应的日志文件(例如使用命令tail -f tinkoff_invest_strategy.log
打开)跟踪机器人的工作进度,或者重写错误处理程序逻辑,自行添加通过email/telegram或其它方式发送事件或错误通知到自己的功能。
机器人提交申请时不需要监控资金。当前机器人正在一个已关闭杠杆交易的账户上操作(与它未进行测试),如果资金不足,机器人将记录相应的错误信息,购买操作将不会进行。
项目启动的技术要求
项目目前部署在Timeweb VPS主机上(非广告!)。如果您想亲自尝试,您需要以下内容:
开始工作之前,我们需要以下内容
- PHP 7.4或更高版本(我已在php 7.4 / Ubuntu 18.04.5上进行开发和测试)
- PECL,Composer版本2+。
如果还没有Composer,请按照以下链接进行安装和配置:[Composer安装](https://getcomposer.org.cn/doc/00-intro.md#installation-linux-unix-macos)。最好进行“全局安装”。
项目依赖于以下项目(https://github.com/metaseller/tinkoff-invest-api-v2-yii2,https://github.com/metaseller/tinkoff-invest-api-v2-php)。
说明:我使用的非官方SDK tinkoff-invest-api-v2-php
已经包含了从proto文件生成的模型。仅供参考,如果您想从官方仓库(https://github.com/Tinkoff/investAPI/)构建项目,则需要:
- 安装protoc
- 构建grpc_php_plugin插件(参见https://grpc.org.cn/docs/languages/php/basics/#setup)
- 执行类似以下命令
sudo protoc --proto_path=~/contracts_dir/ --php_out=~/models_dic/ --grpc_out=~/models_dir/ --plugin=protoc-gen-grpc=./grpc_php_plugin ~/contracts_dir/*
替换为您的相应目录(启动项目时不需要这些)。
然后我们需要PHP的grps.so扩展(https://cloud.google.com/php/grpc)。
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,可以在项目配置中(参见https://github.com/metaseller/tinkoff-robot-buyer/blob/main/config/console.php#L46,https://github.com/metaseller/tinkoff-robot-buyer/blob/main/config/web.php#L51)将缓存服务替换为yii\caching\FileCache
(https://yiiframework.cn/doc/api/2.0/yii-caching-filecache),并从配置中移除Redis(https://github.com/metaseller/tinkoff-robot-buyer/blob/main/config/web.php#L40)。
PS:总体来说,迟早需要了解GRPC的文档。
- 使用PHP快速入门 -> https://grpc.org.cn/docs/languages/php/quickstart/
- 基础教程 -> https://grpc.org.cn/docs/languages/php/basics/
PSS:以下是可以用于启动项目的依赖项列表:[依赖项列表](https://packagist.org.cn/packages/metaseller/tinkoff-robot-buyer)
项目的安装和启动步骤
- 我们将使用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
)
<?php
return [
'tinkoff_invest' => [
'secret_key' => '<ВАШ API ТОКЕН>',
'account_id' => '<ВАШ ИДЕНТИФИКАТОР ПОРТФЕЛЯ>',
],
];
如何获取令牌请参阅此处:https://tinkoff.github.io/investAPI/token/ 如果您不知道账户标识符,则只需输入令牌,然后执行控制台命令
cd /var/www/contest.metaseller.local
php yii tinkoff-invest/accounts
(如果一切设置正确并启动,并且令牌有效)您将在 stdout 中看到您的投资组合标识符列表
root@server:/var/www/contest.metaseller.local# php yii tinkoff-invest/accounts
Портфель 1 => 206*******
ИИС => 205*******
Инвесткопилка => 203*******
接下来需要配置 cron
sudo su
crontab -e
在 crontab 中添加一行
* * * * * cd /var/www/contest.metaseller.local && sudo -u www-data php yii app-schedule/run --scheduleFile=@app/config/schedule.php 1>>runtime/logs/scheduler.log 2>&1
(作为按计划运行的过程的管理员,使用的是 https://github.com/omnilight/yii2-scheduling 库,在项目中它配置在文件 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/config/schedule.php 中)
最后,我们需要配置我们的机器人购买者的策略参数(别忘了在 config/credentials.php
文件中写入获取到的 account_id)
cd /var/www/contest.metaseller.local/config/
vim tinkoff-buy-strategy.php
内容
<?php
return [
'ETF' => [
'TMOS' => [
'ACTIVE' => true,
'INCREMENT_VALUE' => 1, // На сколько мы увеличиваем накопленное количество лотов позиций к покупке через каждый период
'INCREMENT_PERIOD' => 10, // Период в минутах, через который мы инкрементируем количество лотов позиций к покупке
'BUY_CHECK_PERIOD' => 1, // Период в минутах, через который мы проверяем возможность покупки накопленного количества лотов позиций
'BUY_LOTS_BOTTOM_LIMIT' => 5, // Не пытаемся совершить покупку, пока не достигнут указанный накопленный лимит лотов к покупке
'BUY_TRAILING_PERCENTAGE' => 0.09, //Величина в процентах, на которую текущая цена должна превысить трейлинг цену для совершения покупки
],
],
];
这些控制参数的语义在上面的“策略工作逻辑”部分中已说明。
顺便说一下,您有权限更改请求的 appname(请参阅 https://tinkoff.github.io/investAPI/grpc/#appname)
cd /var/www/contest.metaseller.local/config/
vim tinkoff-invest.php
内容
<?php
$credentials = require __DIR__ . '/credentials.php';
return [
'secret_key' => $credentials['tinkoff_invest']['secret_key'] ?? '',
'account_id' => $credentials['tinkoff_invest']['account_id'] ?? '',
'app_name' => 'metaseller.tinkoff-robot-buyer',
];
Tinkoff Invest Api 2 功能演示
正如我在引言中所写的那样,这个项目是为了演示如何在 PHP7 上使用 Tinkoff Invest 2 API 的基本功能而制作的。该项目是一个控制台应用程序,所有主要业务逻辑都描述在控制台控制器 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php 中
除了 ETF 机器人购买者的功能外,您还可以尝试以下控制台命令
- 在 STDOUT 中获取您的配置文件信息
cd /var/www/contest.metaseller.local
php yii tinkoff-invest/user-info
结果
array(1) {
["user_info"]=>
array(3) {
["prem_status"]=>
bool(false)
["qual_status"]=>
bool(false)
["qualified_for_work_with"]=>
array(4) {
[0]=>
string(4) "bond"
[1]=>
string(11) "foreign_etf"
[2]=>
string(14) "foreign_shares"
[3]=>
string(14) "russian_shares"
}
}
}
此命令由 TinkoffInvestController::actionUserInfo()
方法处理(请参阅 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L76)
- 在 STDOUT 中获取您的投资组合标识符列表
cd /var/www/contest.metaseller.local
php yii tinkoff-invest/accounts
结果
Портфель 1 => 206*******
ИИС => 205*******
Инвесткопилка => 203*******
此命令由 TinkoffInvestController::actionAccounts()
方法处理(请参阅 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L137)
- 在 STDOUT 中获取指定账户标识符(投资组合)的配置文件信息
cd /var/www/contest.metaseller.local
php yii tinkoff-invest/portfolio 206*******
此命令从命令行接收账户标识符,并由 TinkoffInvestController::actionPortfolio(string $account_id)
方法处理(请参阅 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L193)
- 在 STDOUT 中获取投资组合的总充值信息,按时间段划分(这个功能是我偶然发现的,当时需要控制 IIS 按月(每月投入多少)和按年(每年投入多少)的总充值金额)
cd /var/www/contest.metaseller.local
php yii tinkoff-invest/funding 206******* 2021
结果
Запрашиваем информацию о пополнениях счета 206*******
[2021 год] => 168535.52 руб.
[2022 год] => 43639.99 руб.
[Всего] => 212175.51 руб.
Разбивка по месяцам текущего года:
January -> 1989.5 руб.
February -> 37649.68 руб.
March -> 0.81 руб.
April -> 3000 руб.
May -> 1000 руб.
此命令从命令行接收账户标识符和起始年,并由 TinkoffInvestController::actionFunding(string $account_id, int $from_year = 2021)
方法处理(请参阅 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L554)
- 订阅蜡烛流并显示来自流的信息,输出到 STDOUT(无限循环,按 Ctrl-C / Cmd-C 中断)
cd /var/www/contest.metaseller.local
php yii tinkoff-invest/candles-stream SBER
此命令从命令行接收工具的股票代码。由 TinkoffInvestController::actionCandlesStream(string $ticker)
方法处理(请参阅 https://github.com/metaseller/tinkoff-robot-buyer/blob/main/commands/TinkoffInvestController.php#L554)
PS: 此外,请注意,我的SDK Tinkoff Invest 2 for PHP中也有一些简单的示例,您可以使用composer将https://github.com/metaseller/tinkoff-invest-api-v2-php库连接到您的PHP项目,并无需使用Yii2框架就可以运行示例https://github.com/metaseller/tinkoff-invest-api-v2-php/tree/main/examples。
有用链接
- 此演示项目: https://github.com/metaseller/tinkoff-robot-buyer (https://packagist.org.cn/packages/metaseller/tinkoff-robot-buyer)
- PHP版的非官方Tinkoff Invest Api v2 SDK: https://github.com/metaseller/tinkoff-invest-api-v2-php (https://packagist.org.cn/packages/metaseller/tinkoff-invest-api-v2-php)
- PHP版的非官方Tinkoff Invest Api v2 SDK的Yii2封装: https://github.com/metaseller/tinkoff-invest-api-v2-yii2 (https://packagist.org.cn/packages/metaseller/tinkoff-invest-api-v2-yii2)
- Tinkoff Invest Api开发者文档链接: https://tinkoff.github.io/investAPI/
- Telegram开发者社区: https://t.me/joinchat/VaW05CDzcSdsPULM
- 算法交易开发者社区: https://t.me/tradinggroupTinkoff
- Tinkoff Invest机器人竞赛社区: https://t.me/tinkoff_invest_robot_contest