public function read(): Message
{
$msg = new Message();
do {
// Read header
$header = $this->stream->read(2);
$first = \ord($header[0]);
$second = \ord($header[1]);
$msg->type = $first & 0x0F; // 15/1111
$msg->fin = $first & 0x80; // 128/10000000
$msg->isMasked = $second & 0x80;
$msg->length = $second & 0x7F; // 127/1111111
// Get payload length extensions
if ($msg->length >= 0x7E) { // 126/1111110
$lengthExt = $msg->length == 0x7F ? 8 : 2;
$header = $this->stream->read($lengthExt);
// Set extented paylod length
$msg->length = 0;
for ($i = 0; $i < $lengthExt; $i++) {
$msg->length += \ord($header[$i]) << ($lengthExt - $i - 1) * 8;
}
}
// Get Mask key
if ($msg->isMasked) {
$mask = $this->stream->read(4);
}
// Get payload
$page = '';
while ($msg->length > 0) {
$frame = $this->stream->read($msg->length);
$msg->length -= \strlen($frame);
$page .= $frame;
}
switch ($msg->type) {
case Message::TYPE_PING:
$this->write(Message::create('', Message::TYPE_PONG, true));
break;
case Message::TYPE_CLOSE:
$this->stream->close();
break;
case Message::TYPE_BINARY:
case Message::TYPE_TEXT:
case Message::TYPE_CONTINUE:
if ($msg->isMasked) {
// Unmask data
for ($i = 0, $l = \strlen($page); $i < $l; $i++) {
$msg->data .= $page[$i] ^ $mask[$i % 4];
}
} else {
$msg->data .= $page;
}
break;
}
} while (!$msg->fin);
return $msg;
}
public function calc(array $charts, int $period = 14): array
{
$diff = [];
$smoothing = 2 / ($period + 1);
$posEma = $negEma = null;
$count = count($charts);
for ($n = 1; $n < $count; $n++) {
/* @var $chart \Trader\Chart */
$chart = $charts[$n];
$diff[$n] = $chart->close - $charts[$n - 1]->close;
if ($n >= $period) {
$batch = array_slice($diff, - $period);
$pos = $neg = array_fill(0, $period, 0);
foreach ($batch as $i => $val) {
if ($val > 0) {
$pos[$i] = $val;
} else {
$neg[$i] = - $val;
}
}
$posEma = $this->ema($pos, $posEma, $smoothing);
$negEma = $this->ema($neg, $negEma, $smoothing);
if (empty($negEma)) {
$chart->indicator->rsi = 100;
} else {
$chart->indicator->rsi = 100 - 100 / (1 + $posEma / $negEma);
}
}
}
return $charts;
}