-
Notifications
You must be signed in to change notification settings - Fork 497
Description
The current library version does not support combined streams. Binance did not offer this feature when the library was written. kline can listen to many streams at the same time, but it does this by opening a separate socket connection for each stream.
I think that doing the same job with a single socket connection is healthier in terms of manageability and stability. Moreover, Binance must have thought the same thing and introduced combined streams. (By the way; I noticed that the Binance load balancer resolves the stream.binance.com domain name to a different server each time. I would not have expected it to be different). Below is the combined URI of the two pairs. I recommend that you subscribe to pairs so that the length of the URL does not exceed 2000 characters (it is recommended not to exceed 2000 characters in many places. However, it can work with longer ones without any problems).
$combined_endpoint = "wss://stream.binance.com/stream?streams=bnbusdt@kline_1m/btcusdt@kline_1m";
The combined URI above subscribes to bnbusdt and btcusdt's 1 minute frames and receives a data stream over a single socket.
public function kline($symbols, string $interval = "30m", callable $callback = null)
{
if (is_null($callback)) {
throw new Exception("You must provide a valid callback");
}
if (!is_array($symbols)) {
$symbols = [
$symbols,
];
}
$loop = \React\EventLoop\Factory::create();
$react = new \React\Socket\Connector($loop);
$connector = new \Ratchet\Client\Connector($loop, $react);
foreach ($symbols as $symbol)
$endpoints[] = strtolower($symbol) . '@kline_' . $interval;
//Ex: $combined_endpoint = "wss://stream.binance.com/stream?streams=bnbusdt@kline_1m/btcusdt@kline_1m";
$combined_endpoint = "wss://stream.binance.com/stream?streams=" . implode('/', $endpoints);
$endpoint = 'combined_kline';
$this->subscriptions[$endpoint] = true;
$connector($combined_endpoint)->then(function ($ws) use ($callback, $symbol, $loop, $endpoint, $interval) {
$ws->on('message', function ($data) use ($ws, $loop, $callback, $endpoint) {
if ($this->subscriptions[$endpoint] === false) {
$loop->stop();
return;
}
$json = json_decode($data);
$chart = $json->data->k;
$symbol = $json->data->s;
$interval = $chart->data->i;
call_user_func($callback, $this, $symbol, $chart);
});
$ws->on('close', function ($code = null, $reason = null) use ($symbol, $loop, $interval) {
echo "Combined kline() WebSocket Connection closed! ({$code} - {$reason})" . PHP_EOL;
$loop->stop();
});
}, function ($e) use ($loop, $symbol, $interval) {
echo "Combined kline() Could not connect: {$e->getMessage()}" . PHP_EOL;
$loop->stop();
});
$loop->run();
}
After patching the library with the code above, you can use it as in the example below.
$api = new Binance\API('', '', $useTestnet = false);
$api->useServerTime();
$api->kline($arr['bnbusdt','btcusdt'], "1m", function ($api, $symbol, $chart) {
print_r($chart);
});
I hope it helps