|
...
|
...
|
@@ -10,6 +10,9 @@ require_once __DIR__ . '/../../../jytools/func.php'; |
|
|
|
use trader\struct\ApiInfo;
|
|
|
|
use trader\exchange\binance\Api as BnApi;
|
|
|
|
use jytools\Websocket;
|
|
|
|
use Swoole\Coroutine;
|
|
|
|
|
|
|
|
use function jytools\getMicrotime;
|
|
|
|
use function jytools\output;
|
|
|
|
|
|
|
|
class ExBroker
|
|
...
|
...
|
@@ -20,6 +23,15 @@ class ExBroker |
|
|
|
private BnApi $api;
|
|
|
|
private ?Websocket $wsAcc;
|
|
|
|
private ?Websocket $wsKline;
|
|
|
|
private ?Websocket $wsDepth;
|
|
|
|
private array $depthData = [
|
|
|
|
'lid' => 0, //lastUpdateId
|
|
|
|
'bids' => [],
|
|
|
|
'asks' => [],
|
|
|
|
'uts' => 0, //updateTime
|
|
|
|
];
|
|
|
|
private array $depthCache = [];
|
|
|
|
private bool $gettingDepth = false;
|
|
|
|
|
|
|
|
public function __construct(?ApiInfo $apiInfo)
|
|
|
|
{
|
|
...
|
...
|
@@ -181,4 +193,92 @@ class ExBroker |
|
|
|
$res = $this->api->klines($params);
|
|
|
|
return $res;
|
|
|
|
}
|
|
|
|
public function subDepth($symbol, callable $onData)
|
|
|
|
{
|
|
|
|
var_dump($this->host . $this->path);
|
|
|
|
$this->wsDepth = new Websocket($this->host . $this->path);
|
|
|
|
$this->wsDepth->connect(
|
|
|
|
$onOpen = function () use ($symbol) {
|
|
|
|
$symbol = strtolower($symbol);
|
|
|
|
$subData = json_encode(['method' => 'SUBSCRIBE', 'params' => [$symbol . '@depth@100ms'], 'id' => 1]);
|
|
|
|
$this->wsDepth->push($subData);
|
|
|
|
},
|
|
|
|
$onMessage = function ($data) use ($onData) {
|
|
|
|
$data = json_decode($data, true);
|
|
|
|
if (!$data || !isset($data['data'])) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
$startTs = getMicrotime();
|
|
|
|
$this->updateDepthData($data['data']);
|
|
|
|
$endTs = getMicrotime();
|
|
|
|
$cost = $endTs - $startTs;
|
|
|
|
output($data['data']['s'] . ' depth update cost(ms):' . $cost);
|
|
|
|
$onData($this->depthData);
|
|
|
|
},
|
|
|
|
$onClose = null,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
private function updateDepthData($data)
|
|
|
|
{
|
|
|
|
if ($this->depthData['lid'] == 0 && !$this->gettingDepth) {
|
|
|
|
Coroutine::create(function () use ($data) {
|
|
|
|
$this->gettingDepth = true;
|
|
|
|
$data = $this->api->depth(['symbol' => $data['s'], 'limit' => 1000]);
|
|
|
|
if ($data) {
|
|
|
|
$this->depthData['lid'] = $data['lastUpdateId'];
|
|
|
|
$this->depthData['bids'] = $this->formatDepthData($data['bids']);
|
|
|
|
$this->depthData['asks'] = $this->formatDepthData($data['asks']);
|
|
|
|
$this->depthData['uts'] = $data['T'];
|
|
|
|
}
|
|
|
|
$this->gettingDepth = false;
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($this->depthData['lid'] == 0) {
|
|
|
|
$this->depthCache[] = $data;
|
|
|
|
while (count($this->depthCache) > 20) {
|
|
|
|
array_shift($this->depthCache);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
if (count($this->depthCache) != 0) {
|
|
|
|
foreach ($this->depthCache as $v) {
|
|
|
|
if ($v['pu'] == $this->depthData['lid'] || $v['T'] > $this->depthData['uts']) {
|
|
|
|
$this->addDepthData($v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$this->depthCache = [];
|
|
|
|
}
|
|
|
|
$this->addDepthData($data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
private function formatDepthData($data)
|
|
|
|
{
|
|
|
|
$newData = [];
|
|
|
|
foreach ($data as $item) {
|
|
|
|
$price = ($item[0]);
|
|
|
|
$qty = ($item[1]);
|
|
|
|
$newData[$price] = $qty;
|
|
|
|
}
|
|
|
|
return $newData;
|
|
|
|
}
|
|
|
|
private function addDepthData($data)
|
|
|
|
{
|
|
|
|
$data['a'] = $this->formatDepthData($data['a']);
|
|
|
|
$data['b'] = $this->formatDepthData($data['b']);
|
|
|
|
$this->depthData['asks'] = array_merge($this->depthData['asks'], $data['a']);
|
|
|
|
$this->depthData['bids'] = array_merge($this->depthData['bids'], $data['b']);
|
|
|
|
//保留值不为0的数据
|
|
|
|
$this->depthData['asks'] = array_filter($this->depthData['asks'], function ($v) {
|
|
|
|
return floatval($v) != 0;
|
|
|
|
});
|
|
|
|
$this->depthData['bids'] = array_filter($this->depthData['bids'], function ($v) {
|
|
|
|
return floatval($v) != 0;
|
|
|
|
});
|
|
|
|
//从大到小排序
|
|
|
|
krsort($this->depthData['asks']);
|
|
|
|
//从小到大排序
|
|
|
|
ksort($this->depthData['bids']);
|
|
|
|
$this->depthData['lid'] = $data['u'];
|
|
|
|
$this->depthData['uts'] = $data['T'];
|
|
|
|
}
|
|
|
|
} |
...
|
...
|
|