DATA/BYBIT/daemon/collection/bybit_total_striker.php
<?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);
}
// 퇴근