CORE TERMINAL
OLD BOY WORK : 올드보이 작업장

바이비트 몽땅 수집 데몬 작업 - 기본 500종목 이상 수집

DATE: 2026-03-08 12:54
시작
바이비트 DB
* 바이비트 몽땅 수집 데몬 작업 - 기본 500종목 이상 수집
- 모든 변수 감안
1. 5초 600콜 : 아웃라인 컷 수집 데몬 제작
가. 기본 수집
나. 타격기 수집
다. 타이밍 수집
ADDITIONAL SOURCE CODE
#!/usr/bin/php
<?php
/**
 * ============================================================
 * 바이비트 무기한 선물(linear) 종목 정보 수집 CLI 데몬
 * - curl_multi 병렬 호출 방식 (전체 종목 동시 호출)
 * - 그누보드(g5_write_daemon_kind_bybit) x2_run=1 종목만 수집
 * - 저장 테이블: daemon_bybit_Ticker
 * ============================================================
 */

error_reporting(E_ALL);
ini_set('display_errors', 1);
date_default_timezone_set('Asia/Seoul');

$DAEMON_ID = pathinfo(__FILE__, PATHINFO_FILENAME);

if (php_sapi_name() !== 'cli') {
    echo "CLI 전용 데몬입니다.\n";
    exit;
}

function get_db_connection() {
    try {
        $db_upbit = null;
        @include '/home/www/DB/db_upbit.php';
        if (!($db_upbit instanceof PDO)) return null;
        $pdo = $db_upbit;
        $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
        return $pdo;
    } catch (Throwable $e) {
        return null;
    }
}

function get_gnu_connection() {
    try {
        $db_gnu  = null;
        $pdo_gnu = null;
        $pdo     = null;
        @include '/home/www/DB/db_gnu.php';
        if ($db_gnu instanceof PDO) {
            $db_gnu->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $db_gnu;
        }
        if ($pdo_gnu instanceof PDO) {
            $pdo_gnu->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $pdo_gnu;
        }
        if ($pdo instanceof PDO) {
            $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
            return $pdo;
        }
        return null;
    } catch (Throwable $e) {
        return null;
    }
}

// ============================================================
// curl_multi 병렬 호출 - URL 배열 한번에 날리고 결과 반환
// ============================================================
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;
}

// ============================================================
// 전체 종목 한번에 병렬 호출 후 데이터 파싱
// ============================================================
function collectAll(array $symbols): array {
    $API_INSTRUMENTS   = 'https://api.bybit.com/v5/market/instruments-info?category=linear&symbol=';
    $API_TICKERS       = 'https://api.bybit.com/v5/market/tickers?category=linear&symbol=';
    $API_KLINE         = 'https://api.bybit.com/v5/market/kline?category=linear&interval=1&limit=1&symbol=';
    $API_RECENT_TRADE  = 'https://api.bybit.com/v5/market/recent-trade?category=linear&limit=1&symbol=';
    $API_RISK_LIMIT    = 'https://api.bybit.com/v5/market/risk-limit?category=linear&symbol=';
    $API_ACCOUNT_RATIO = 'https://api.bybit.com/v5/market/account-ratio?category=linear&period=1d&limit=1&symbol=';
    $API_MARK_KLINE    = 'https://api.bybit.com/v5/market/mark-price-kline?category=linear&interval=1&limit=1&symbol=';
    $API_INDEX_KLINE   = 'https://api.bybit.com/v5/market/index-price-kline?category=linear&interval=1&limit=1&symbol=';
    $API_PREMIUM_KLINE = 'https://api.bybit.com/v5/market/premium-index-price-kline?category=linear&interval=1&limit=1&symbol=';

    // 전체 종목 × 9개 URL 한번에 구성
    $urls = [];
    foreach ($symbols as $sym) {
        $s = urlencode($sym);
        $urls["{$sym}__info"]    = $API_INSTRUMENTS   . $s;
        $urls["{$sym}__ticker"]  = $API_TICKERS       . $s;
        $urls["{$sym}__kline"]   = $API_KLINE         . $s;
        $urls["{$sym}__trade"]   = $API_RECENT_TRADE  . $s;
        $urls["{$sym}__risk"]    = $API_RISK_LIMIT    . $s;
        $urls["{$sym}__ratio"]   = $API_ACCOUNT_RATIO . $s;
        $urls["{$sym}__mark"]    = $API_MARK_KLINE    . $s;
        $urls["{$sym}__index"]   = $API_INDEX_KLINE   . $s;
        $urls["{$sym}__premium"] = $API_PREMIUM_KLINE . $s;
    }

    // 한방에 병렬 호출
    $raw = http_multi_get($urls);

    // 종목별 파싱
    $result = [];
    foreach ($symbols as $sym) {

        // instruments-info
        $res  = $raw["{$sym}__info"] ?? null;
        $item = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? []) : [];
        $lf = $item['leverageFilter'] ?? [];
        $pf = $item['priceFilter']    ?? [];
        $ls = $item['lotSizeFilter']  ?? [];

        // 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;

        // recent-trade
        $res = $raw["{$sym}__trade"] ?? null;
        $t   = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? null) : null;

        // risk-limit
        $res = $raw["{$sym}__risk"] ?? null;
        $r   = ($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;

        // mark-price-kline
        $res = $raw["{$sym}__mark"] ?? null;
        $mk  = ($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;

        // premium-index-price-kline
        $res = $raw["{$sym}__premium"] ?? null;
        $pk  = ($res && ($res['retCode'] ?? -1) === 0) ? ($res['result']['list'][0] ?? null) : null;

        $result[$sym] = [
            'symbol'               => $sym,
            'status'               => $item['status']                          ?? '',
            'baseCoin'             => $item['baseCoin']                        ?? '',
            'quoteCoin'            => $item['quoteCoin']                       ?? '',
            'settleCoin'           => $item['settleCoin']                      ?? '',
            'launchTime'           => $item['launchTime']                      ?? '',
      
            'priceScale'           => $item['priceScale']                      ?? '',
            'minLeverage'          => $lf['minLeverage']                       ?? '',
            'maxLeverage'          => $lf['maxLeverage']                       ?? '',
            'leverageStep'         => $lf['leverageStep']                      ?? '',
            'minPrice'             => $pf['minPrice']                          ?? '',
            'maxPrice'             => $pf['maxPrice']                          ?? '',
            'tickSize'             => $pf['tickSize']                          ?? '',
            'minOrderQty'          => $ls['minOrderQty']                       ?? '',
            'maxOrderQty'          => $ls['maxOrderQty']                       ?? '',
            'qtyStep'              => $ls['qtyStep']                           ?? '',
            'fundingInterval'      => $item['fundingInterval']                 ?? '',
            'copyTrading'          => $item['copyTrading']                     ?? '',
            'unifiedMarginTrade'   => ($item['unifiedMarginTrade'] ? 1 : 0),
            'postOnlyMaxOrderQty'  => $item['lotSizeFilter']['postOnlyMaxOrderQty'] ?? '',
            'upperLimitPrice'      => $item['upperFundingRate']                ?? '',
            'lowerLimitPrice'      => $item['lowerFundingRate']                ?? '',
            'time'                 => (int)(microtime(true) * 1000),
            'lastPrice'            => $tk['lastPrice']                         ?? '',
            'prevPrice24h'         => $tk['prevPrice24h']                      ?? '',
            'price24hPcnt'         => $tk['price24hPcnt']                      ?? '',
            'highPrice24h'         => $tk['highPrice24h']                      ?? '',
            'lowPrice24h'          => $tk['lowPrice24h']                       ?? '',
            'openInterest'         => $tk['openInterest']                      ?? '',
            'markPrice'            => $tk['markPrice']                         ?? '',
            'indexPrice'           => $tk['indexPrice']                        ?? '',
            'fundingRate'          => $tk['fundingRate']                       ?? '',
            'prevPrice1h'          => $tk['prevPrice1h']                       ?? '',
            'openInterestValue'    => $tk['openInterestValue']                 ?? '',
            '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]                                    ?? '',
            'execId'               => $t['execId']                             ?? '',
            'price'                => $t['price']                              ?? '',
            'size'                 => $t['size']                               ?? '',
            'side'                 => $t['side']                               ?? '',
            'isBlockTrade'         => ($t['isBlockTrade'] ? 1 : 0),
            'isAdlTrade'           => ($t['isBlockTrade'] ? 1 : 0),
            'mPnL'                 => $t['mPnL']                               ?? '',
            'riskId'               => $r['id']                                 ?? '',
            'isLowestRisk'         => $r['isLowestRisk']                       ?? 0,
            'maintenanceMargin'    => $r['maintenanceMargin']                  ?? '',
            'initialMargin'        => $r['initialMargin']                      ?? '',
            'limit'                => $r['riskLimitValue']                     ?? '',
            'buyRatio'             => $a['buyRatio']                           ?? '',
            'sellRatio'            => $a['sellRatio']                          ?? '',
            'period'               => 1,
            'm_close'              => $mk[4]                                   ?? '',
            'i_close'              => $ik[4]                                   ?? '',
            'p_close'              => $pk[4]                                   ?? '',
        ];
    }

    return $result;
}



$pdo     = get_db_connection();
$pdo_gnu = get_gnu_connection();
$server_ip = 'CLI_DAEMON';

$cycle_count         = 0;
$last_market_refresh = 0;
$symbols             = [];

$stmt_hb   = null;
$stmt_kill = null;
$stmt_stop = null;
$stmt_best = null;

while (true) {
    $cycle_count++;

    try {
        $reconnected = false;
        if (!$pdo) {
            $pdo = get_db_connection();
            $reconnected = true;
        } else {
            try { $pdo->query("SELECT 1"); }
            catch (Throwable $e) {
                $pdo = get_db_connection();
                $reconnected = true;
            }
        }
        if ($reconnected) {
            $stmt_hb = $stmt_kill = $stmt_stop = $stmt_best = null;
        }

        if ($pdo) {
            if (!$stmt_hb) {
                $stmt_hb = $pdo->prepare("
                    INSERT INTO daemon_record (
                        d_id, d_category, d_pid, d_status,
                        d_heartbeat, d_ip, d_start_time, d_memo, d_kill_flag
                    )
                    VALUES (
                        :id, 'BYBIT', :pid, 'RUNNING',
                        NOW(), :ip, NOW(), 'BYBIT LINEAR FUTURES GHOST', 0
                    )
                    ON DUPLICATE KEY UPDATE
                        d_pid       = VALUES(d_pid),
                        d_status    = 'RUNNING',
                        d_heartbeat = NOW(),
                        d_ip        = VALUES(d_ip),
                        d_memo      = VALUES(d_memo)
                ");
            }
            if (!$stmt_kill) {
                $stmt_kill = $pdo->prepare("SELECT d_kill_flag FROM daemon_record WHERE d_id = :id LIMIT 1");
            }
            if (!$stmt_stop) {
                $stmt_stop = $pdo->prepare("
                    UPDATE daemon_record
                    SET d_status='STOPPED', d_heartbeat=NOW(), d_pid=0
                    WHERE d_id=:id
                ");
            }

            $stmt_hb->execute([':id' => $DAEMON_ID, ':pid' => getmypid(), ':ip' => $server_ip]);

            $stmt_kill->execute([':id' => $DAEMON_ID]);
            $kill_flag = (int)($stmt_kill->fetchColumn() ?: 0);
            if ($kill_flag === 1) {
                $stmt_stop->execute([':id' => $DAEMON_ID]);
                exit(0);
            }

            // 종목 갱신 (1초마다)
            if (time() - $last_market_refresh >= 1 || empty($symbols)) {
                $tmp = [];
                // pdo_gnu 끊겼을 때만 재연결
                if (!$pdo_gnu) {
                    $pdo_gnu   = get_gnu_connection();
                    $stmt_best = null;
                } else {
                    try { $pdo_gnu->query("SELECT 1"); }
                    catch (Throwable $e) {
                        $pdo_gnu   = get_gnu_connection();
                        $stmt_best = null;
                    }
                }
                if ($pdo_gnu instanceof PDO) {
                    if (!$stmt_best) {
                        $stmt_best = $pdo_gnu->prepare("
                            SELECT wr_subject FROM g5_write_daemon_kind_bybit
                            WHERE (x2_run = 1 OR x2_run = '1')
                        ");
                    }
                    $stmt_best->execute();
                    $best_rows = $stmt_best->fetchAll(PDO::FETCH_COLUMN);
                    if (is_array($best_rows)) {
                        foreach ($best_rows as $sym) {
                            $sym = strtoupper(trim((string)$sym));
                            if ($sym === '') continue;
                            if (strpos($sym, 'USDT') === false && strpos($sym, '-') === false) {
                                $sym .= 'USDT';
                            }
                            if (!in_array($sym, $tmp, true)) $tmp[] = $sym;
                        }
                    }
                }
                if ($tmp) {
                    $symbols = $tmp;
                    $last_market_refresh = time();
                } else {
                    $symbols = [];
                    sleep(10);
                    continue;
                }
            }

            if (!$symbols) {
                sleep(10);
                continue;
            }

            $at = date('Y-m-d H:i:s');

            // 전체 종목 한번에 병렬 호출
            $all_data = collectAll($symbols);
            $rows = array_values(array_filter($all_data, fn($d) => !empty($d)));

            if (empty($rows)) {
                // 수집 데이터 없음 - 그냥 통과
            } else {
                // bulk INSERT - 전체 종목 한방 쿼리
                $placeholders = [];
                $params       = [];
                foreach ($rows as $i => $d) {
                    $placeholders[] = "(
                        :symbol_{$i}, :status_{$i}, :baseCoin_{$i}, :quoteCoin_{$i}, :settleCoin_{$i},
                        :launchTime_{$i}, :priceScale_{$i},
                        :minLeverage_{$i}, :maxLeverage_{$i}, :leverageStep_{$i},
                        :minPrice_{$i}, :maxPrice_{$i}, :tickSize_{$i},
                        :minOrderQty_{$i}, :maxOrderQty_{$i}, :qtyStep_{$i},
                        :fundingInterval_{$i}, :copyTrading_{$i}, :unifiedMarginTrade_{$i},
                        :postOnlyMaxOrderQty_{$i}, :upperLimitPrice_{$i}, :lowerLimitPrice_{$i},
                        :time_{$i}, NOW(),
                        :lastPrice_{$i}, :prevPrice24h_{$i}, :price24hPcnt_{$i},
                        :highPrice24h_{$i}, :lowPrice24h_{$i}, :openInterest_{$i},
                        :markPrice_{$i}, :indexPrice_{$i}, :fundingRate_{$i},
                        :prevPrice1h_{$i}, :openInterestValue_{$i}, :turnover24h_{$i}, :volume24h_{$i},
                        :nextFundingTime_{$i},
                        :ask1Size_{$i}, :bid1Price_{$i}, :ask1Price_{$i}, :bid1Size_{$i},
                        :start_{$i}, :open_{$i}, :high_{$i}, :low_{$i}, :close_{$i}, :volume_{$i}, :turnover_{$i},
                        :execId_{$i}, :price_{$i}, :size_{$i}, :side_{$i}, :isBlockTrade_{$i}, :isAdlTrade_{$i}, :mPnL_{$i},
                        :riskId_{$i}, :isLowestRisk_{$i}, :maintenanceMargin_{$i}, :initialMargin_{$i}, :limit_{$i},
                        :buyRatio_{$i}, :sellRatio_{$i}, :period_{$i},
                        :m_close_{$i}, :i_close_{$i}, :p_close_{$i}
                    )";
                    $params["symbol_{$i}"]              = $d['symbol'];
                    $params["status_{$i}"]              = $d['status'];
                    $params["baseCoin_{$i}"]            = $d['baseCoin'];
                    $params["quoteCoin_{$i}"]           = $d['quoteCoin'];
                    $params["settleCoin_{$i}"]          = $d['settleCoin'];
                    $params["launchTime_{$i}"]          = $d['launchTime'];
                    $params["priceScale_{$i}"]          = $d['priceScale'];
                    $params["minLeverage_{$i}"]         = $d['minLeverage'];
                    $params["maxLeverage_{$i}"]         = $d['maxLeverage'];
                    $params["leverageStep_{$i}"]        = $d['leverageStep'];
                    $params["minPrice_{$i}"]            = $d['minPrice'];
                    $params["maxPrice_{$i}"]            = $d['maxPrice'];
                    $params["tickSize_{$i}"]            = $d['tickSize'];
                    $params["minOrderQty_{$i}"]         = $d['minOrderQty'];
                    $params["maxOrderQty_{$i}"]         = $d['maxOrderQty'];
                    $params["qtyStep_{$i}"]             = $d['qtyStep'];
                    $params["fundingInterval_{$i}"]     = $d['fundingInterval'];
                    $params["copyTrading_{$i}"]         = $d['copyTrading'];
                    $params["unifiedMarginTrade_{$i}"]  = $d['unifiedMarginTrade'];
                    $params["postOnlyMaxOrderQty_{$i}"] = $d['postOnlyMaxOrderQty'];
                    $params["upperLimitPrice_{$i}"]     = $d['upperLimitPrice'];
                    $params["lowerLimitPrice_{$i}"]     = $d['lowerLimitPrice'];
                    $params["time_{$i}"]                = $d['time'];
                    $params["lastPrice_{$i}"]           = $d['lastPrice'];
                    $params["prevPrice24h_{$i}"]        = $d['prevPrice24h'];
                    $params["price24hPcnt_{$i}"]        = $d['price24hPcnt'];
                    $params["highPrice24h_{$i}"]        = $d['highPrice24h'];
                    $params["lowPrice24h_{$i}"]         = $d['lowPrice24h'];
                    $params["openInterest_{$i}"]        = $d['openInterest'];
                    $params["markPrice_{$i}"]           = $d['markPrice'];
                    $params["indexPrice_{$i}"]          = $d['indexPrice'];
                    $params["fundingRate_{$i}"]         = $d['fundingRate'];
                    $params["prevPrice1h_{$i}"]         = $d['prevPrice1h'];
                    $params["openInterestValue_{$i}"]   = $d['openInterestValue'];
                    $params["turnover24h_{$i}"]         = $d['turnover24h'];
                    $params["volume24h_{$i}"]           = $d['volume24h'];
                    $params["nextFundingTime_{$i}"]     = $d['nextFundingTime'];
                    $params["ask1Size_{$i}"]            = $d['ask1Size'];
                    $params["bid1Price_{$i}"]           = $d['bid1Price'];
                    $params["ask1Price_{$i}"]           = $d['ask1Price'];
                    $params["bid1Size_{$i}"]            = $d['bid1Size'];
                    $params["start_{$i}"]               = $d['start'];
                    $params["open_{$i}"]                = $d['open'];
                    $params["high_{$i}"]                = $d['high'];
                    $params["low_{$i}"]                 = $d['low'];
                    $params["close_{$i}"]               = $d['close'];
                    $params["volume_{$i}"]              = $d['volume'];
                    $params["turnover_{$i}"]            = $d['turnover'];
                    $params["execId_{$i}"]              = $d['execId'];
                    $params["price_{$i}"]               = $d['price'];
                    $params["size_{$i}"]                = $d['size'];
                    $params["side_{$i}"]                = $d['side'];
                    $params["isBlockTrade_{$i}"]        = $d['isBlockTrade'];
                    $params["isAdlTrade_{$i}"]          = $d['isAdlTrade'];
                    $params["mPnL_{$i}"]                = $d['mPnL'];
                    $params["riskId_{$i}"]              = $d['riskId'];
                    $params["isLowestRisk_{$i}"]        = $d['isLowestRisk'];
                    $params["maintenanceMargin_{$i}"]   = $d['maintenanceMargin'];
                    $params["initialMargin_{$i}"]       = $d['initialMargin'];
                    $params["limit_{$i}"]               = $d['limit'];
                    $params["buyRatio_{$i}"]            = $d['buyRatio'];
                    $params["sellRatio_{$i}"]           = $d['sellRatio'];
                    $params["period_{$i}"]              = $d['period'];
                    $params["m_close_{$i}"]             = $d['m_close'];
                    $params["i_close_{$i}"]             = $d['i_close'];
                    $params["p_close_{$i}"]             = $d['p_close'];
                }

                $sql = "
                    INSERT INTO daemon_bybit_Ticker (
                        symbol, status, baseCoin, quoteCoin, settleCoin,
                        launchTime, priceScale,
                        minLeverage, maxLeverage, leverageStep,
                        minPrice, maxPrice, tickSize,
                        minOrderQty, maxOrderQty, qtyStep,
                        fundingInterval, copyTrading, unifiedMarginTrade,
                        postOnlyMaxOrderQty, upperLimitPrice, lowerLimitPrice,
                        time, updated_at,
                        lastPrice, prevPrice24h, price24hPcnt,
                        highPrice24h, lowPrice24h, openInterest,
                        markPrice, indexPrice, fundingRate,
                        prevPrice1h, openInterestValue, turnover24h, volume24h,
                        nextFundingTime, 
                        ask1Size, bid1Price, ask1Price, bid1Size,
                        `start`, `open`, `high`, `low`, `close`, volume, turnover,
                        execId, price, size, side, isBlockTrade, isAdlTrade, mPnL,
                        riskId, isLowestRisk, maintenanceMargin, initialMargin, `limit`,
                        buyRatio, sellRatio, period,
                        m_close, i_close, p_close
                    ) VALUES " . implode(',', $placeholders) . "
                    ON DUPLICATE KEY UPDATE
                        status               = VALUES(status),
                        baseCoin             = VALUES(baseCoin),
                        quoteCoin            = VALUES(quoteCoin),
                        settleCoin           = VALUES(settleCoin),
                        launchTime           = VALUES(launchTime),
                        priceScale           = VALUES(priceScale),
                        minLeverage          = VALUES(minLeverage),
                        maxLeverage          = VALUES(maxLeverage),
                        leverageStep         = VALUES(leverageStep),
                        minPrice             = VALUES(minPrice),
                        maxPrice             = VALUES(maxPrice),
                        tickSize             = VALUES(tickSize),
                        minOrderQty          = VALUES(minOrderQty),
                        maxOrderQty          = VALUES(maxOrderQty),
                        qtyStep              = VALUES(qtyStep),
                        fundingInterval      = VALUES(fundingInterval),
                        copyTrading          = VALUES(copyTrading),
                        unifiedMarginTrade   = VALUES(unifiedMarginTrade),
                        postOnlyMaxOrderQty  = VALUES(postOnlyMaxOrderQty),
                        upperLimitPrice      = VALUES(upperLimitPrice),
                        lowerLimitPrice      = VALUES(lowerLimitPrice),
                        time                 = VALUES(time),
                        updated_at           = NOW(),
                        lastPrice            = VALUES(lastPrice),
                        prevPrice24h         = VALUES(prevPrice24h),
                        price24hPcnt         = VALUES(price24hPcnt),
                        highPrice24h         = VALUES(highPrice24h),
                        lowPrice24h          = VALUES(lowPrice24h),
                        openInterest         = VALUES(openInterest),
                        markPrice            = VALUES(markPrice),
                        indexPrice           = VALUES(indexPrice),
                        fundingRate              = VALUES(fundingRate),
                        prevPrice1h              = VALUES(prevPrice1h),
                        openInterestValue        = VALUES(openInterestValue),
                        turnover24h              = VALUES(turnover24h),
                        volume24h                = VALUES(volume24h),
                        nextFundingTime          = VALUES(nextFundingTime),
                        ask1Size                 = VALUES(ask1Size),
                        bid1Price                = VALUES(bid1Price),
                        ask1Price                = VALUES(ask1Price),
                        bid1Size                 = VALUES(bid1Size),
                        `start`              = VALUES(`start`),
                        `open`               = VALUES(`open`),
                        `high`               = VALUES(`high`),
                        `low`                = VALUES(`low`),
                        `close`              = VALUES(`close`),
                        volume               = VALUES(volume),
                        turnover             = VALUES(turnover),
                        execId               = VALUES(execId),
                        price                = VALUES(price),
                        size                 = VALUES(size),
                        side                 = VALUES(side),
                        isBlockTrade         = VALUES(isBlockTrade),
                        isAdlTrade           = VALUES(isAdlTrade),
                        mPnL                 = VALUES(mPnL),
                        riskId               = VALUES(riskId),
                        isLowestRisk         = VALUES(isLowestRisk),
                        maintenanceMargin    = VALUES(maintenanceMargin),
                        initialMargin        = VALUES(initialMargin),
                        `limit`              = VALUES(`limit`),
                        buyRatio             = VALUES(buyRatio),
                        sellRatio            = VALUES(sellRatio),
                        period               = VALUES(period),
                        m_close              = VALUES(m_close),
                        i_close              = VALUES(i_close),
                        p_close              = VALUES(p_close)
                ";

                $stmt = $pdo->prepare($sql);
                $stmt->execute($params);
            }

        } else {
                sleep(5);
        }

        if ($cycle_count % 50 === 0 && function_exists('gc_collect_cycles')) {
            gc_collect_cycles();
        }

    } catch (Throwable $e) {
        sleep(3);
    }

    sleep(6);
}
WORK LINE
  • 2026-03-08 12:52:04
    1. 보안 무시 : 보안은 포트 보안 - 폐쇄형
    2. 자체 관리 무시 : 관리는 툴로 관리
    3. 기타 관리 : 구조 관리
  • 2026-03-08 12:54:53
    1. 더 간단하게 간다.
    2. 주소 9개 넣는것이 파일 상단이다.
    * 맞지
    1. 코드 수 졸라 길고 복잡하거 부터 잡는다.
    2. 현재 데몬 별도 디렉토리 관리.
    * 파일명
    * 호출 파일 들 파일명 정한다.
    * 데몬 해부해서 부위별로 파일 나눈다.
    1. 데몬 다이어트 시킨 다음 : 주소 정린다.
    * 시작 자체를 깔끔한 생태에서 부위별로 작업한다.
  • 2026-03-08 12:55:30
    daemon_bybit_total.php ← 몸통
    bybit_total_env.php ← 환경기
    bybit_total_striker.php ← 타격기
  • 2026-03-08 12:58:13
    일단 여기서 루프 속에 넣을 부분 짤라서 타격기에 넣는다.
    구분은 간단하다.
    1. 단발
    2. 루프
    3. 즉 타격기에 루프 안 내장만 뽁아서 올린다.
  • 2026-03-08 13:06:56
    // ============================================================
    // 몸통 : daemon_bybit_total.php
    // 루프만 돈다. 봉인.
    // ============================================================

    error_reporting(E_ALL);
    ini_set(\\'display_errors\\', 1);
    date_default_timezone_set(\\'Asia/Seoul\\');

    $DAEMON_ID = pathinfo(__FILE__, PATHINFO_FILENAME);

    if (php_sapi_name() !== \\'cli\\') {
    echo \\\"CLI 전용 데몬입니다.\\\\n\\\";
    exit;
    }

    include __DIR__ . \\'/bybit_total_env.php\\';

    while (true) {
    try {
    include __DIR__ . \\'/bybit_total_striker.php\\';
    } catch (Throwable $e) {
    sleep(3);
    }
    sleep(1);
    }
  • 2026-03-08 13:07:59
    1. 일단 여기서 정리하고
    2. 인클루드 하고
    3. 각 호출 파일 작업한다.
  • 2026-03-08 14:52:47
    1. 차 몸통 분리
    daemon_bybit_total.php ← 몸통
    bybit_total_env.php ← 환경기
    bybit_total_striker.php ← 타격기
    bybit_total_heartbeat.php ← heartbeat
  • 2026-03-08 20:46:00
    bybit_total_heartbeat.php 이게 파일명이지 이데로 서버에 올린다.
    이후 타격기든 몸통이든 깔끔한 것에 박는다.
    일단 bybit_total_query.php 이 파일 체워야지 그리고 서버에 올리고 다음 타격기 수술.
    bybit_total_query.php 아파일 복붙을 올리던 파일을 올리던 한다.
    그냥 몽땅 가져와라 그게 간단하지.
    1. 코드가 간단한다.
    2. 컬럼이 바뀌면 자동으로 수정 반영된다.
    그긴 코드가 47라인 코드로 줄었군.
  • 2026-03-08 20:46:59
    이제 정리하고 간다. 아주 무난하게 쉽게 가고 있다. 구조를 확실히 잡으니까.
    1. 구조로 일단 본다.
    2. 현재 타격기 내장 부분 방식을 살핀다.
    3. 현재 남아 있는 타격기 내장 우리가 원하는 방식이 아니다.
    4. 이건 수정 부분이 아니다. 그냥 다 통으로 다시 타격기 천천히 하나씩 꼼꼼히 만드는게 빠르다.
    일단 아주 얇게 구조를 만든다.
    즉 뼈대를 만들고 조형 미대생틀처럼 거기에 살을 붙인다. 이게 안전하고 튼튼다.
    살은 최대한 근육으로 붙인다. 쓸 때 없는 지방은 무조건 뺀다.
    위험 요소는 외부에서 툴로 컨트롤한다.
    즉 영향제는 외부에서 감당하고 뼈대와 근육으로 만든다. 우선 뼈대를 만든다.
  • 2026-03-08 20:50:37
    그누보드를 호출하는게 순서.
    타격기 다 날리고
    타격기 다 날리고
    <?php
    // 타격기 뼈대
    // API 주소 정의 (단발)
    // collectAll() 함수
    // foreach 묶음 순회
    foreach ($symbol_chunks as $chunk) {
    // API 호출
    // DB 저장
    // sleep
    }
    // 퇴근
    이것만 박았따。
    이제 환경기
    작업한다.
    bybit_total_env.php
  • 2026-03-08 20:53:22
    우리는 bybit_total_env.php 이 파일 만들었다.
    그게 기본 환경이다. 맞나. 현재 그것이 기본 환경이라면 기본적인 구조는 현재 맞다. 이전 파일부분 동일성의 원칙에 따라.
    다르다면 바뀐 환경이다. 즉 호출하는 그누보드 테이블 외 달리 수정할 부분이있나.
    이미 반영되었다면, 일단 현재까지 이 파일 손댈 이유가 없다.
    그럼 바로 타격기 작업한다.
    일단 구조 확인하고 작업한다.
    주소는 이후 우리가 정한데로 정한다.
    주소는 4~5개로 일단 5개로 하기로 결정햇다.
    이 부분 미리 주소 정리해야 하나 그럼 몸통 작업이다.
    미리 정해야 타격기 작업에 혼선이 없다.
    1. 이중 간단하게 필수라고 한다면 어떤 값을 주는지 봐야 한다.
    2. 즉 각 컬럼과 간략 설명을 리스트 형태로 올린다. 그럼 내가 확인하고 바로 결정한다.
  • 2026-03-08 21:14:26
    1번 주소에는 필수 항목 없다. 통과 : 1번은 소위 말하는 게임 규칙이다.
    2번 주소 : 그냥 현재가 하나로도 필요하다. [필요]
    3번 주소 : [필요]
    4번 주소 : 통과
    5번 주소 : 통과
    6번 주소: 포지션 비율 필요 : [필요]
    7번 주소 : 비교값 : 통과
    8번 주소 : 차트용 : [필요]
    9번 주소 : 프리미엄 즉 거품 수치 : 통과
    2,3,6,8번 4개 가져온다.
    이외 중요 칼럼이 있는데 빠진 주소 있나.
    최근 체결가/방향 (price, size, side) → 4번에만 있음.
    이건 필요하다. 그런데 황당한게 현재 주소. 2,3,6,8.
    이거 4개랑 5개는 콜 600에 아주 큰 영향을 준다.
    허접 코인에게 까지 저게 필요한가. 이게 문제다.
    지금 컷도 1분 컷으로 가는데 저건 실시간이다.
    즉 59초간 방향이 상인데 마지막 방향이 하면 이건 오염을 떠나 재난이다.
    차라리 이후 이벤트로 1분 이전값 비교 거래량 비교 방향성 강제로 때려박는게 더 효율적이다.
    그럼4번 째고 딸랑 저 4개로 가면 되지.
    * 2번 tickers
    * 3번 kline
    * 6번 account-ratio
    * 8번 index-price-kline
  • 2026-03-08 21:35:55
    우선 우리가 해야 할 것이 환경기 수정이다.
    그럼 거기서 심볼 불러다. 현재는 그냥 타격기에게 준다.
    1. 그럼 타격기에서 연산해야 한다. 루프 안에서 매번 계속 맞지.
    2. 환경기에서 한번 배열정리해서 던져 주면 타격기는 그냥 연산 없다.
    3. 순서나 기타 없다. 그냥 받은거 다 때리고 퇴근이다.
    그럼 몇번 작업하고 퇴근이지? 이것도 생각 안한다. 준거 다 때리면 퇴근! 이 마인드다.
    그걸 타격기서 계산하면 루프에서 매번 한다. 즉 이건 환경기에서 코드 작업한다.
    현재 환경기에 그거 없다.
    1. 즉 환경기에서 그누보드 모든 행을 읽어다. 배열로 묶는다.
    2. 그 묶은 배열 세트를 타격기에 던져준다.
    죽 갸덩 60갸 씩 묶어서 준다. 이거지. 즉 120개면 2개 묶음.
    그럼 현재 봉인이고 환경기.
    타격기는 글머 가져와서 때리면 끝이다.
  • 2026-03-09 00:17:21
    * 데몬 작업 완성
바이비트 몽땅 수집 데몬 작업 기본 500종목 수집
버전: 2.0