polkachu/kraken-api-client

为 Kraken.com 提供最强大和可扩展的 REST API / Websocket 客户端。基于 PHP8.0 构建

v2.6.1 2023-10-11 00:34 UTC

This package is auto-updated.

Last update: 2024-09-11 06:16:42 UTC


README

kraken

为 Kraken.com 提供最强大和可扩展的 REST API / Websocket 客户端。基于 PHP8.1 构建

这是一个非官方的 Kraken.com PHP8.1 包,可以帮助用户快速连接到 API 并从他们的 Laravel 或其他 PHP 项目中。当然,该包的主要功能是能够与 Kraken REST API 进行交互,同时也允许连接到 Kraken Websocket 服务器

Support me on Patreon Build Status Packagist Downloads License

特性

  • REST API 客户端
  • Websocket 客户端
  • 文档完善
  • 测试完善

要求

  • Laravel 8.x, Laravel 9.x, Laravel 10.x 或其他框架
  • PHP 8.1 及以上

安装

使用以下命令通过 composer 安装此包:composer require butschster/kraken-api-client

使用

Laravel 自动发现

如果您使用的是 Laravel 8.0 或更高版本,则该包将自动注册 KrakenServiceProvider。

其他 PHP 框架

REST API 客户端

$client = new \Butschster\Kraken\Client(
    new GuzzleHttp\Client(),
    new \Butschster\Kraken\NonceGenerator(),
    (new \Butschster\Kraken\Serializer\SerializerFactory())->build(),
    'api-key',
    'api-secret'
);

$client->getAccountBalance();

Websocket 客户端

$client = new \Butschster\Kraken\WebsocketClient(
   (new \Butschster\Kraken\Serializer\SerializerFactory())->build(),
   \React\EventLoop\Factory::create()
);

$client->connectToPublicServer(...);

配置

您可以使用以下内容更新您的 .env 文件:

KRAKEN_KEY=my_api_key
KRAKEN_SECRET=my_secret
KRAKEN_OTP=my_otp_key # if two-factor enabled, otherwise not required

REST API 方法

API 客户端使用

通过依赖注入

use App\Http\Controllers\Controller;
use Butschster\Kraken\Contracts\Client;

class BalanceController extends Controller {

    public function getBalance(Client $client)
    {
        $balances = $client->getAccountBalance();
       
        ...
    }
}

发起请求

此包使用 jms/serializer 将 API 响应转换为对象,因此您必须传递用于反序列化的类。

注意:对于不存在的 API 方法,您必须自行创建响应类。

/** @var \Butschster\Kraken\Contracts\Client $client */

// Public request
$client->request('public/Spread', RecentSpreadsResponse::class, array $params): RecentSpreadsResponse;

// Private request
$balance = $client->request('private/Balance', \Butschster\Kraken\Responses\AccountBalanceResponse::class, array $params);

如果请求返回错误,将抛出异常 \Butschster\Kraken\Exceptions\KrakenApiErrorException

获取服务器时间

获取服务器时间。

见:https://docs.kraken.com/rest/#operation/getServerTime

/** @var \Butschster\Kraken\Contracts\Client $client */
$response = $client->getServerTime();

$response->time; // DateTimeInterface
$response->rfc1123; // string:"Sun, 21 Mar 21 14:23:14 +0000

获取系统状态

获取当前系统状态或交易模式。

见:https://docs.kraken.com/rest/#operation/getSystemStatus

/** @var \Butschster\Kraken\Contracts\Client $client */
$response = $client->getSystemStatus();

$response->status; // string:"online"
$response->timestamp; // DateTimeImmutable

获取资产信息

获取可用于存款、提款、交易和质押的资产信息。

见:https://docs.kraken.com/rest/#operation/getAssetInfo

use Butschster\Kraken\ValueObjects\AssetClass;

/** @var \Butschster\Kraken\Contracts\Client $client */
$response = $client->getAssetInfo(array $assets = ['all'], ?AssetClass $class = null);

foreach ($response as $asset => $info) {
    $asset; // string: "XXBT"
    
    $info->class; // string:"currency"
    $info->altname; // string:"XBT"
    $info->decimals; // int:10
    $info->displayDecimals; // int:5
}

获取可交易资产对

获取可交易资产对。

见:https://docs.kraken.com/rest/#operation/getTradableAssetPairs

use Butschster\Kraken\ValueObjects\AssetPair;
use Butschster\Kraken\ValueObjects\TradableInfo;
use Butschster\Kraken\Responses\Entities\Fee;

/** @var \Butschster\Kraken\Contracts\Client $client */

$pair = new AssetPair('XXBTCZUSD', 'XETHXXBT');
$info = TradableInfo::leverage();

$response = $client->getTradableAssetPairs($pair, $info);

foreach ($response as $pair => $assetPair) {
    $pair ;// string:"XETHXXBT"
    
    $assetPair->altname; // string:"ETHXBT"
    $assetPair->wsname; // string:"ETH/XBT"
    $assetPair->classBase; // string:"currency"
    $assetPair->base; // string:"XETH"
    $assetPair->classQuote; // string:"currency"
    $assetPair->quote; // string:"XXBT"
    $assetPair->pairDecimals; // int:5
    $assetPair->lotDecimals; // int:8
    $assetPair->lotMultiplier; // int:1
    $assetPair->leverageBuy; // array:[2,3,4,5]
    $assetPair->leverageSell; // array:[2,3,4,5]
    $assetPair->feeVolumeCurrency; // string:"ZUSD"
    $assetPair->marginCall; // int:80
    $assetPair->marginStop; // int:40
    $assetPair->ordermin; // string:"0.005"
    
    foreach ($assetPair->fees as $fee) {
        $fee->getPercentFee(); // float:0.2
        $fee->getVolume(); // int:2500000
    }
    
    foreach ($assetPair->feesMaker as $fee) {
        $fee->getPercentFee(); // float:0.2
        $fee->getVolume(); // int:2500000
    }
    
}

获取行情信息

注意:今天的价格从 UTC 中午开始。

见:https://docs.kraken.com/rest/#operation/getTickerInformation

use Brick\Math\BigDecimal;

/** @var \Butschster\Kraken\Contracts\Client $client */
$response = $client->getTickerInformation(['XBTUSD', 'XXBTZUSD', ...]);

foreach ($response as $pair => $tickerInfo) {
    $pair; // string: "XXBTZUSD"
    
    $tickerInfo->ask->getLotVolume(); // BigDecimal
    $tickerInfo->ask->getPrice(); // BigDecimal
    $tickerInfo->ask->getWholeLotVolume(); // BigDecimal
    
    $tickerInfo->bid->getLotVolume(); // BigDecimal
    $tickerInfo->bid->getPrice(); // BigDecimal
    $tickerInfo->bid->getWholeLotVolume(); // BigDecimal
    
    $tickerInfo->lastTradeClosed[0]; // string:"52641.10000"
    $tickerInfo->lastTradeClosed[1]; // string:"0.00080000"
    
    $tickerInfo->volume->getLast24Hours(); // BigDecimal
    $tickerInfo->volume->getToday(); // BigDecimal
    
    $tickerInfo->volumeWightedAveragePrice->getLast24Hours(); // BigDecimal
    $tickerInfo->volumeWightedAveragePrice->getToday(); // BigDecimal
    
    $tickerInfo->trades->getLast24Hours(); // int:0
    $tickerInfo->trades->getToday(); // int:10
    
    $tickerInfo->low->getToday(); // BigDecimal
    $tickerInfo->low->getLast24Hours(); // BigDecimal
    
    $tickerInfo->high->getToday(); // BigDecimal
    $tickerInfo->high->getLast24Hours(); // BigDecimal
    
    $tickerInfo->openingPrice; // BigDecimal
}

获取订单簿

见:https://docs.kraken.com/rest/#operation/getOrderBook

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->getOrderBook(['XBTUSD', 'XXBTZUSD'], 100);

foreach ($response as $pair => $orders) {
    foreach ($orders->asks as $order) {
        $order->getPrice(); // BigDecimal
        $order->getVolume(); // BigDecimal
        $order->getTimestamp(); // int:1616663113
        $order->getDate(); // DateTimeInterface
    }
    
    foreach ($orders->bids as $order) {
        $order->getPrice(); // BigDecimal
        $order->getVolume(); // BigDecimal
        $order->getTimestamp(); // int:1616663113
        $order->getDate(); // DateTimeInterface
    }
}

获取账户余额

检索所有现金余额,扣除待处理的提款。

见:https://docs.kraken.com/rest/#operation/getAccountBalance

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->getAccountBalance();

foreach ($response as $balance) {
    $balance->getAsset(); // string:"ZUSD"
    $balance->getBalance(); // BigDecimal
}

获取交易余额

检索保证金余额摘要、保证金头寸估值、权益和保证金水平。

见:https://docs.kraken.com/rest/#operation/getTradeBalance

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->getTradeBalance();

$response->equivalentBalance; // BigDecimal
$response->tradeBalance; // BigDecimal
$response->marginAmount; // BigDecimal
$response->net; // BigDecimal
$response->cost; // BigDecimal
$response->valuation; // BigDecimal
$response->equity; // BigDecimal
$response->freeMargin; // BigDecimal
$response->marginLevel; // BigDecimal

获取开放订单

检索当前开放订单的信息。

见:https://docs.kraken.com/rest/#operation/getOpenOrders

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->getOpenOrders();

foreach ($response as $txId => $order) {
    $txId; // string:"OQCLML-BW3P3-BUCMWZ"
    
    $order->refId; // string|null
    $order->userRef; // int:0
    $order->status; // string:"online"
    $order->openTimestamp; // int:1616666559.8974
    $order->startTimestamp; // int:0
    $order->expireTimestamp; // int:0
    
    $order->description->pair; // string:"XBTUSD"
    $order->description->type; // string:"buy"
    $order->description->orderType; // string:"limit"
    $order->description->price; // BigDecimal
    $order->description->secondaryPrice; // BigDecimal
    $order->description->leverage; // string:"none"
    $order->description->order; // string:"buy 1.25000000 XBTUSD @ limit 30010.0"
    $order->description->close; // string:""
    
    $order->volume; // BigDecimal
    $order->volumeExecuted; // BigDecimal
    $order->cost; // BigDecimal
    $order->fee; // BigDecimal
    $order->price; // BigDecimal
    $order->stopPrice; // BigDecimal
    $order->limitPrice; // BigDecimal
    $order->miscellaneous; // array<string>
    $order->flags; // array:["fciq"]
    $order->trades; // array:["TCCCTY-WE2O6-P3NB37"]
}

获取已关闭订单

检索已关闭订单(已成交或已取消)的信息。每次返回50条结果,默认按时间顺序排列。注意:如果订单的tx ID用于起始或结束时间,则使用订单的开启时间(opentm)

参见: https://docs.kraken.com/rest/#operation/getClosedOrders

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$start = \Carbon\Carbon::now()->subDay();
$end = \Carbon\Carbon::now();

$response = $client->getClosedOrders(
    start: $start, end: $end, offset: 100
);

$response->count; // 5

foreach ($response->closed as $txId => $order) {
    $txId; // string:"OQCLML-BW3P3-BUCMWZ"
    
    $order->refId; // string|null
    $order->userRef; // int:0
    $order->status; // string:"canceled"
    $order->reason; // string:"User requested"
    $order->openTimestamp; // int:1616666559.8974
    $order->startTimestamp; // int:0
    $order->expireTimestamp; // int:0
    
    $order->description->pair; // string:"XBTUSD"
    $order->description->type; // string:"buy"
    $order->description->orderType; // string:"limit"
    $order->description->price; // BigDecimal
    $order->description->secondaryPrice; // BigDecimal
    $order->description->leverage; // string:"none"
    $order->description->order; // string:"buy 1.25000000 XBTUSD @ limit 30010.0"
    $order->description->close; // string:""
    
    $order->volume; // BigDecimal
    $order->volumeExecuted; // BigDecimal
    $order->cost; // BigDecimal
    $order->fee; // BigDecimal
    $order->price; // BigDecimal
    $order->stopPrice; // BigDecimal
    $order->limitPrice; // BigDecimal
    $order->miscellaneous; // array<string>
    $order->flags; // array:["fciq"]
    $order->trades; // array:["TCCCTY-WE2O6-P3NB37"]
}

查询订单信息

检索特定订单的信息。

参见: https://docs.kraken.com/rest/#operation/getOrdersInfo

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->queryOrdersInfo(['OBCMZD-JIEE7-77TH3F', 'OMMDB2-FSB6Z-7W3HPO']);

foreach ($response as $txId => $order) {
    $txId; // string:"OQCLML-BW3P3-BUCMWZ"
    
    $order->refId; // string|null
    $order->userRef; // int:0
    $order->status; // string:"canceled"
    $order->reason; // string:"User requested"
    $order->openTimestamp; // int:1616666559.8974
    $order->startTimestamp; // int:0
    $order->expireTimestamp; // int:0
    
    $order->description->pair; // string:"XBTUSD"
    $order->description->type; // string:"buy"
    $order->description->orderType; // string:"limit"
    $order->description->price; // BigDecimal
    $order->description->secondaryPrice; // BigDecimal
    $order->description->leverage; // string:"none"
    $order->description->order; // string:"buy 1.25000000 XBTUSD @ limit 30010.0"
    $order->description->close; // string:""
    
    $order->volume; // BigDecimal
    $order->volumeExecuted; // BigDecimal
    $order->cost; // BigDecimal
    $order->fee; // BigDecimal
    $order->price; // BigDecimal
    $order->stopPrice; // BigDecimal
    $order->limitPrice; // BigDecimal
    $order->miscellaneous; // array<string>
    $order->flags; // array:["fciq"]
    $order->trades; // array:["TCCCTY-WE2O6-P3NB37"]
}

添加订单

下具新订单。注意:有关可用交易对、价格和数量精度、订单最小量、可用杠杆等详细信息,请参阅AssetPairs端点。

参见: https://docs.kraken.com/rest/#operation/addOrder

/** @var \Butschster\Kraken\Contracts\Client $client */

use Butschster\Kraken\ValueObjects\CloseOrder;
use Butschster\Kraken\ValueObjects\OrderDirection;
use Butschster\Kraken\ValueObjects\OrderType;


$order = new \Butschster\Kraken\Requests\AddOrderRequest(
    OrderType::stopLoss(), OrderDirection::sell(), 'XXBTZUSD'
);

$order->setCloseOrder(new CloseOrder(OrderType::stopLoss(), '38000', '36000'));
$order->setPrice('45000.1');
$order->...

$response = $client->addOrder($order);

$response->description->order; // string:"sell 2.12340000 XBTUSD @ limit 45000.1 with 2:1 leverage"
$response->description->close; // string:"close position @ stop loss 38000.0 -> limit 36000.0"
$response->txId; // array:["OUF4EM-FRGI2-MQMWZD"]

取消订单

通过txid或userref取消特定的开放订单(或一组开放订单)

参见: https://docs.kraken.com/rest/#operation/cancelOrder

/** @var \Butschster\Kraken\Contracts\Client $client */

$response = $client->cancelOrder('OYVGEW-VYV5B-UUEXSK');
$response; // int:1

取消所有订单

取消所有开放订单

参见: https://docs.kraken.com/rest/#operation/cancelAllOrders

/** @var \Butschster\Kraken\Contracts\Client $client */

$response = $client->cancelAllOrders();
$response; // int:1

在X之后取消所有订单

CancelAllOrdersAfter提供了一种“自动取消开关”机制,以保护客户端免受网络故障、极端延迟或意外匹配引擎停机的影响。客户端可以发送一个带有超时(以秒为单位)的请求,这将启动一个倒计时计时器,在计时器到期时取消所有客户端订单。客户端必须持续发送新请求以推迟触发时间,或通过指定超时为0来停用该机制。如果计时器到期,所有订单将被取消,并且计时器将保持禁用,直到客户端提供新的(非零)超时。

建议每15到30秒调用一次,提供60秒的超时。这允许客户端在短暂断开连接或暂时延迟的情况下保持订单不变,同时在网络故障的情况下保持安全。在定期安排的交易引擎维护之前禁用计时器也是建议的(如果启用了计时器,交易引擎从停机状态恢复时将取消所有订单 - 计划内或计划外)。

参见: https://docs.kraken.com/rest/#operation/cancelAllOrdersAfter

/** @var \Butschster\Kraken\Contracts\Client $client */

$response = $client->cancelAllOrdersAfter(60);
$response->currentTime; // DateTimeInterface
$response->triggerTime; // DateTimeInterface

获取存款方式

检索特定资产可用的存款方法。

参见: https://docs.kraken.com/rest/#operation/getDepositMethods

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->getDepositMethods('XBT');
$response->method; // string:"Bitcoin"
$response->limit; // int|bool:false
$response->fee; // BigDecimal
$response->generatedAddress; // bool:true
$response->addressSetupFee; // string:""

获取存款地址

检索(或生成新的)特定资产和方法的存款地址。

参见: https://docs.kraken.com/rest/#operation/getDepositAddresses

/** @var \Butschster\Kraken\Contracts\Client $client */

$response = $client->getDepositAddresses('XBT', 'Bitcoin');

foreach ($response as $address) {
    $address->address; // string:"2N9fRkx5JTWXWHmXzZtvhQsufvoYRMq9ExV"
    $address->expireTimestamp; // int:0
    $address->new; // bool:true
}

获取提款信息

检索有关特定资产、密钥和金额的潜在提款的费用信息。

参见: https://docs.kraken.com/rest/#operation/getWithdrawalInformation

/** @var \Butschster\Kraken\Contracts\Client $client */

use Brick\Math\BigDecimal;

$response = $client->getWithdrawalInformation('XBT', 'btc_testnet_with1', BigDecimal::of(0.725));

$response->method; // string:"Bitcoin"
$response->limit; // BigDecimal
$response->amount; // BigDecimal
$response->fee; // BigDecimal

获取Websockets令牌

为了连接和验证我们的Websockets API,必须通过此REST API端点请求身份验证令牌。令牌应在创建后15分钟内使用,但一旦建立成功的Websockets连接和私有订阅,并且保持连接,则不会过期。

参见: https://docs.kraken.com/rest/#operation/getWebsocketsToken

/** @var \Butschster\Kraken\Contracts\Client $client */

$response = $client->getWebsocketsToken();
$response->token; // string:"1Dwc4lzSwNWOAwkMdqhssNNFhs1ed606d1WcF3XfEMw"
$response->expires; // int:900
$response->expiresAt(); // DateTimeInterface

Websocket客户端

Websocket客户端使用

通过依赖注入

namespace App\Console\Commands\ExampleCommand;

use Butschster\Kraken\Contracts\WebsocketClient;
use Butschster\Kraken\Websocket\Connection;

class ExampleCommand extends Command 
{
    ...
    
    public function handle(WebsocketClient $client)
    {
        $client->connectToPublicServer(function (Connection $connection) {
        
            ...
        
        });
    }
}

ping

客户端可以ping服务器以确定连接是否活跃,服务器响应pong。这与WebSocket标准中的默认ping不同,后者是由服务器发起的

见: https://docs.kraken.com/websockets/#message-ping

/** @var \Butschster\Kraken\Contracts\WebsocketClient $client */

use Butschster\Kraken\Websocket\Connection;
use Butschster\Kraken\Websocket\Requests\Ping;
use Butschster\Kraken\Websocket\Timer;

$client->connectToPublicServer(function (Connection $connection) {
    $connection->sendEvent(new Ping());
    
    // or
    
    $connection->addPeriodicTimer(
        new Timer(5, new Ping())
    );
});


$client->connectToPrivateServer('websocket-token', function (Connection $connection) {
    ...
});

心跳

如果1秒内(大约)没有订阅流量,则发送服务器心跳

见: https://docs.kraken.com/websockets/#message-heartbeat

/** @var \Butschster\Kraken\Contracts\WebsocketClient $client */

use Butschster\Kraken\Websocket\Connection;
use Butschster\Kraken\Websocket\Requests\HeartBeat;
use Butschster\Kraken\Websocket\Timer;

$client->connectToPublicServer(function (Connection $connection) {
    $connection->sendEvent(new HeartBeat());
    
    // or
    
    $connection->addPeriodicTimer(
        new Timer(5, new HeartBeat())
    );
});

订阅事件

订阅单个或多个货币对的专题。

见: https://docs.kraken.com/websockets/#message-subscribe

/** @var \Butschster\Kraken\Contracts\WebsocketClient $client */

use Butschster\Kraken\Websocket\Connection;
use Butschster\Kraken\Websocket\Requests\Subscribe;

$client->connectToPublicServer(function (Connection $connection) {
    $connection->sendEvent(
        new Subscribe(
            'ticker',
            ["XBT/USD", "XBT/EUR"]
        )
    );
    
    $connection->onMessage(function (string $message) {
        // Handle message
    });
});

自定义事件

您可以创建您自己的事件

/** @var \Butschster\Kraken\Contracts\WebsocketClient $client */

// For public events you have to use \Butschster\Kraken\Contracts\WebsocketEvent interface
// For private events you have to use \Butschster\Kraken\Contracts\PrivateWebsocketEvent interface

class OwnTradesEvent implements \Butschster\Kraken\Contracts\PrivateWebsocketEvent {
    public string $event = 'subscribe';
    public array $subscription = [
        'name' => 'ownTrades'
    ];
    
    public function setToken(string $token) : void{
        $this->subscription['token'] = $toke;
    }
}

$client->connectToPrivateServer('token', function (Connection $connection) {
    $connection->sendEvent(
        new OwnTradesEvent()
    );
});

享受吧!