<?php
// ============================================================
// 타격기 : bybit_total_striker.php
// 받은거 몽땅 때리고 저장하고 퇴근
// ============================================================
// ============================================================
// curl_multi 병렬 호출
// ============================================================
if (!function_exists('http_multi_get')) {
function http_multi_get(array $urls): array {
$mh = curl_multi_init();
$handles = [];
foreach ($urls as $key => $url) {
$ch = curl_init($url);
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => 8,
CURLOPT_USERAGENT => 'bybit-ghost',
CURLOPT_SSL_VERIFYPEER => false,
]);
curl_multi_add_handle($mh, $ch);
$handles[$key] = $ch;
}
$running = null;
do {
curl_multi_exec($mh, $running);
curl_multi_select($mh);
} while ($running > 0);
$results = [];
foreach ($handles as $key => $ch) {
$raw = curl_multi_getcontent($ch);
$results[$key] = $raw ? json_decode($raw, true) : null;
curl_multi_remove_handle($mh, $ch);
curl_close($ch);
}
curl_multi_close($mh);
return $results;
}
}
// ============================================================
// 묶음 받아서 API 호출 + 파싱
// ============================================================
if (!function_exists('collectAll')) {
function collectAll(array $symbols, $API_TICKERS, $API_KLINE, $API_ACCOUNT_RATIO, $API_INDEX_KLINE): array {
$urls = [];
foreach ($symbols as $sym) {
$s = urlencode($sym);
$urls["{$sym}__ticker"] = $API_TICKERS . $s;
$urls["{$sym}__kline"] = $API_KLINE . $s;
$urls["{$sym}__ratio"] = $API_ACCOUNT_RATIO . $s;
$urls["{$sym}__index"] = $API_INDEX_KLINE . $s;
}
$raw = http_multi_get($urls);
$result = [];
foreach ($symbols as $sym) {
// tickers
$res = $raw["{$sym}__ticker"] ?? null;
$tk = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? null) : null;
// kline
$res = $raw["{$sym}__kline"] ?? null;
$k = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? null) : null;
// account-ratio
$res = $raw["{$sym}__ratio"] ?? null;
$a = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? null) : null;
// index-price-kline
$res = $raw["{$sym}__index"] ?? null;
$ik = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? null) : null;
$result[$sym] = [
'symbol' => $sym,
'time' => (int)(microtime(true) * 1000),
'lastPrice' => $tk['lastPrice'] ?? '',
'prevPrice24h' => $tk['prevPrice24h'] ?? '',
'price24hPcnt' => $tk['price24hPcnt'] ?? '',
'highPrice24h' => $tk['highPrice24h'] ?? '',
'lowPrice24h' => $tk['lowPrice24h'] ?? '',
'openInterest' => $tk['openInterest'] ?? '',
'openInterestValue' => $tk['openInterestValue'] ?? '',
'markPrice' => $tk['markPrice'] ?? '',
'indexPrice' => $tk['indexPrice'] ?? '',
'fundingRate' => $tk['fundingRate'] ?? '',
'prevPrice1h' => $tk['prevPrice1h'] ?? '',
'turnover24h' => $tk['turnover24h'] ?? '',
'volume24h' => $tk['volume24h'] ?? '',
'nextFundingTime' => $tk['nextFundingTime'] ?? '',
'ask1Size' => $tk['ask1Size'] ?? '',
'bid1Price' => $tk['bid1Price'] ?? '',
'ask1Price' => $tk['ask1Price'] ?? '',
'bid1Size' => $tk['bid1Size'] ?? '',
'start' => $k[0] ?? '',
'open' => $k[1] ?? '',
'high' => $k[2] ?? '',
'low' => $k[3] ?? '',
'close' => $k[4] ?? '',
'volume' => $k[5] ?? '',
'turnover' => $k[6] ?? '',
'buyRatio' => $a['buyRatio'] ?? '',
'sellRatio' => $a['sellRatio'] ?? '',
'period' => 1,
'i_close' => $ik[4] ?? '',
];
}
return $result;
}
}
// ============================================================
// 묶음 순회 → 때리고 → 저장 → sleep → 퇴근
// ============================================================
foreach ($symbol_chunks as $chunk) {
$rows = array_values(array_filter(
collectAll($chunk, $API_TICKERS, $API_KLINE, $API_ACCOUNT_RATIO, $API_INDEX_KLINE),
fn($d) => !empty($d)
));
echo "rows count: " . count($rows) . "\n";
print_r($rows[0] ?? "EMPTY");
include __DIR__ . "/bybit_total_query.php";
sleep(5);
}
// 퇴근