Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

I implemented combined streams #505

Open
enseitankado opened this issue Jul 26, 2024 · 0 comments
Open

I implemented combined streams #505

enseitankado opened this issue Jul 26, 2024 · 0 comments

Comments

@enseitankado
Copy link

enseitankado commented Jul 26, 2024

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant