sting_bo/mengine

Laravel 的匹配引擎

v1.0 2023-12-23 13:19 UTC

This package is auto-updated.

Last update: 2024-09-24 04:15:08 UTC


README

快速开始

  • 安装: composer require sting_bo/mengine
  • 复制配置文件: php artisan vendor:publish

依赖

  • predis

新闻

使用说明

  • 对于已有数据的系统,如果使用此库,可以编写一个初始化脚本先将数据推入队列。

  • 下订单

  • 下单后,将其存储在数据库中,然后实例化订单对象。

use StingBo\Mengine\Core\Order;

$uuid = 3; // User unique identifier
$oid = 4; // Order unique identifier
$symbol = 'abc2usdt'; // Trading pair
$transaction = 'buy'; // Trading direction, buy/sell
$price = 0.4; // Trading price, will be converted to an integer based on the set precision
$volume = 15; // Trading quantity, will be converted to an integer based on the set precision

$order = new Order($uuid, $oid, $symbol, $transaction, $volume, $price);

交易方向精度可以在配置文件中灵活设置。

return [
    'mengine' => [
        // Transaction types, not subject to change.
        'transaction' => [
            'buy',
            'sell',
        ],

        // Default precision, can be changed.
        'accuracy' => 8,
        // If the precision for the trading pair is set, use it; otherwise, take the default accuracy.
        'abc2usdt_accuracy' => 6, // Example of a trading pair
        'test2usdt_accuracy' => 7, // Example of a trading pair

        // If strict mode is set to true, it will validate that the decimal places of the transaction volume or price must be less than the configured length, otherwise the order will fail.
        // If strict mode is set to false, the data will be truncated to the configured decimal places length.
        'strict_mode' => false,
    ],
];
  • 推送到队列,队列任务需要手动启动。
use StingBo\Mengine\Services\MengineService;

$ms = new MengineService();
$ms->pushQueue($order);

启动队列任务: php artisan queue:work --queue=abc2usdt 您也可以使用 horizonsupervisor 来辅助,使您的工作更加高效!

当队列被消费时,它将进入匹配程序。一般步骤如下

  1. 获取匹配的委托订单。
  2. 如果没有匹配的订单,进入订单池,触发订单池变更事件,见第5点。
  3. 如果有匹配的订单,程序将匹配并更新订单池数据。
  4. 成功的交易会触发事件。开发者应在监听器中处理带有事务的订单,例如更新数据库数据、WebSocket 通知等。在 EventServiceProvider 中为成功的匹配注册监听器
// Successful match notification, parameters are: current order, matched order, transaction quantity
event(new MatchEvent($order, $match_order, $match_volume));

// Register listener
protected $listen = [
    'StingBo\Mengine\Events\MatchEvent' => [
        'App\Listeners\YourListener', // Your own listener, should also be implemented asynchronously
    ],
];
  1. 如果只部分填充,剩余部分进入订单池,触发订单池变更事件,通知 K 线或深度列表变化等。按以下方式注册监听器
// Order pool data change event
event(new PushQueueEvent($order));

// Register listener
protected $listen = [
    'StingBo\Mengine\Events\PushQueueEvent' => [
        'App\Listeners\YourListener', // Your own listener, should also be implemented asynchronously
    ],
];
  • 取消订单

取消过程应该是首先查询数据库以确认是否可以取消,然后成功从 Redis 中删除数据,最后更新数据库。

$order = new Order($uuid, $oid, $symbol, $transaction, $volume, $price);
$ms = new MengineService();
$ms->deleteOrder($order);

此匹配引擎没有实现数据库的锁定机制。为了防止在订单正在匹配时发出取消命令的情况,下单和取消订单都使用相同的队列以确保顺序,并且每个交易对都有一个独立的队列。这确保了效率,但开发者需要实现异步通知功能。按以下方式注册监听器

// Successful cancellation notification
event(new DeleteOrderSuccEvent($order));

// Register listener
protected $listen = [
    'StingBo\Mengine\Events\DeleteOrderSuccEvent' => [
        'App\Listeners\YourListener', // Your own listener, should also be implemented asynchronously
    ],
];
  • 获取交易对的买卖深度列表

$symbol = 'abc2cny';
$transaction = 'buy';
$ms = new MengineService();
$ms->getDepth($symbol, $transaction);

总结

在本地测试,交易的平均匹配速度约为每秒200次。计划对匹配速度进行进一步的优化。

Design of a Matching Engine Based on Redis

技术支持