CORE TERMINAL
DAILY -M72 : 일상
세상일도 작업도 모든 것이 언제나 손이 많이 간다.
DATE: 2026-03-03 09:55
핵심 항목
일상
반신욕
중요
데몬 작업 & 디비 정리
필수
청결 & 위생
블럭 정리 - 지퍼백
* 세상일도 작업도 모든 것이 언제나 손이 많이 간다.
1. 데몬 작업을 완성하고 나니 코드의 시작이 구조가 잘못됐다는 것이 또 손이 간다.
가. 속도 문제 개선
ㄱ. 바이비트
ㄴ. 업비트
1. 데몬 작업을 완성하고 나니 코드의 시작이 구조가 잘못됐다는 것이 또 손이 간다.
가. 속도 문제 개선
ㄱ. 바이비트
ㄴ. 업비트
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\\\'] ?? \\\'\\\',
\\\'deliveryTime\\\' => $item[\\\'deliveryTime\\\'] ?? \\\'\\\',
\\\'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),
\\\'deliveryFeeRate\\\' => $item[\\\'deliveryFeeRate\\\'] ?? \\\'\\\',
\\\'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\\\'] ?? \\\'\\\',
\\\'predictedDeliveryPrice\\\' => $tk[\\\'predictedDeliveryPrice\\\'] ?? \\\'\\\',
\\\'basisRate\\\' => $tk[\\\'basisRate\\\'] ?? \\\'\\\',
\\\'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}, :deliveryTime_{$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},
:deliveryFeeRate_{$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}, :predictedDeliveryPrice_{$i}, :basisRate_{$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[\\\"deliveryTime_{$i}\\\"] = $d[\\\'deliveryTime\\\'];
$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[\\\"deliveryFeeRate_{$i}\\\"] = $d[\\\'deliveryFeeRate\\\'];
$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[\\\"predictedDeliveryPrice_{$i}\\\"] = $d[\\\'predictedDeliveryPrice\\\'];
$params[\\\"basisRate_{$i}\\\"] = $d[\\\'basisRate\\\'];
$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, deliveryTime, priceScale,
minLeverage, maxLeverage, leverageStep,
minPrice, maxPrice, tickSize,
minOrderQty, maxOrderQty, qtyStep,
fundingInterval, copyTrading, unifiedMarginTrade,
deliveryFeeRate, postOnlyMaxOrderQty, upperLimitPrice, lowerLimitPrice,
time, updated_at,
lastPrice, prevPrice24h, price24hPcnt,
highPrice24h, lowPrice24h, openInterest,
markPrice, indexPrice, fundingRate,
prevPrice1h, openInterestValue, turnover24h, volume24h,
nextFundingTime, predictedDeliveryPrice, basisRate,
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),
deliveryTime = VALUES(deliveryTime),
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),
deliveryFeeRate = VALUES(deliveryFeeRate),
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),
predictedDeliveryPrice = VALUES(predictedDeliveryPrice),
basisRate = VALUES(basisRate),
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(30);
}
?>
#!/usr/bin/php
<?php
/**
* ============================================================
* 업비트 전체 시세 수집 CLI 데몬
* - curl_multi 병렬 호출 방식
* - gnu DB 루프 밖 1회 연결
* - bulk INSERT 한방 쿼리
* - echo/flush 전부 제거
* ============================================================
*/
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\\\') {
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 병렬 호출
// ============================================================
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 => \\\'upbit-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 = require \\\'/home/www/DB/upbit_api_url.php\\\';
$API_TICKER = $api[\\\'ticker\\\'] . \\\'?markets=\\\';
$API_ORDERBOOK = \\\'https://api.upbit.com/v1/orderbook?markets=\\\';
$pdo = get_db_connection();
$pdo_gnu = get_gnu_connection();
$server_ip = \\\'CLI_DAEMON\\\';
$cycle_count = 0;
$last_market_refresh = 0;
$krw = [];
$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, \\\'UPBIT\\\', :pid, \\\'RUNNING\\\',
NOW(), :ip, NOW(), \\\'UPBIT BOARD ONLY TICKER 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($krw)) {
$tmp = [];
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_upbit
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, \\\'-\\\') === false) {
$sym = \\\'KRW-\\\' . $sym;
}
if (strpos($sym, \\\'KRW-\\\') !== 0) continue;
if (!in_array($sym, $tmp, true)) $tmp[] = $sym;
}
}
}
if ($tmp) {
$krw = $tmp;
$last_market_refresh = time();
} else {
$krw = [];
sleep(10);
continue;
}
}
if (!$krw) {
sleep(10);
continue;
}
$at = date(\\\'Y-m-d H:i:s\\\');
$ms = (int)(microtime(true) * 1000);
// 티커 + 호가 한방에 동시 호출
$market_str = implode(\\\',\\\', $krw);
$raw = http_multi_get([
\\\'ticker\\\' => $API_TICKER . $market_str,
\\\'orderbook\\\' => $API_ORDERBOOK . $market_str,
]);
$tks = $raw[\\\'ticker\\\'];
$obs = $raw[\\\'orderbook\\\'];
if (!$tks || !is_array($tks)) {
sleep(3);
continue;
}
// 호가 맵 구성
$ob_map = [];
if (is_array($obs)) {
foreach ($obs as $o) {
if (isset($o[\\\'market\\\'])) {
$ob_map[$o[\\\'market\\\']] = $o;
}
}
}
// bulk INSERT
$placeholders = [];
$params = [];
foreach ($tks as $i => $t) {
$market = $t[\\\'market\\\'] ?? \\\'\\\';
if ($market === \\\'\\\') continue;
$ob = $ob_map[$market] ?? [];
$placeholders[] = \\\"(
:market_{$i}, :trade_date_{$i}, :trade_time_{$i}, :trade_date_kst_{$i}, :trade_time_kst_{$i},
:opening_price_{$i}, :high_price_{$i}, :low_price_{$i}, :trade_price_{$i}, :prev_closing_price_{$i},
:change_{$i}, :change_price_{$i}, :change_rate_{$i}, :signed_change_price_{$i}, :signed_change_rate_{$i},
:trade_volume_{$i}, :acc_trade_volume_{$i}, :acc_trade_volume_24h_{$i}, :acc_trade_price_{$i}, :acc_trade_price_24h_{$i},
:highest_52_week_price_{$i}, :highest_52_week_date_{$i}, :lowest_52_week_price_{$i}, :lowest_52_week_date_{$i},
:collected_at_{$i}, :collected_ms_{$i},
:tr_trade_timestamp_{$i}, :tr_trade_price_{$i}, :tr_trade_volume_{$i}, :tr_ask_bid_{$i},
:tr_trade_date_utc_{$i}, :tr_trade_time_utc_{$i}, :tr_trade_date_kst_{$i}, :tr_trade_time_kst_{$i},
:tr_collected_at_{$i}, :tr_collected_ms_{$i},
:ob_timestamp_{$i}, :ob_total_ask_size_{$i}, :ob_total_bid_size_{$i}, :ob_units_{$i}
)\\\";
$params[\\\"market_{$i}\\\"] = $market;
$params[\\\"trade_date_{$i}\\\"] = $t[\\\'trade_date\\\'] ?? \\\'\\\';
$params[\\\"trade_time_{$i}\\\"] = $t[\\\'trade_time\\\'] ?? \\\'\\\';
$params[\\\"trade_date_kst_{$i}\\\"] = $t[\\\'trade_date_kst\\\'] ?? \\\'\\\';
$params[\\\"trade_time_kst_{$i}\\\"] = $t[\\\'trade_time_kst\\\'] ?? \\\'\\\';
$params[\\\"opening_price_{$i}\\\"] = $t[\\\'opening_price\\\'] ?? 0;
$params[\\\"high_price_{$i}\\\"] = $t[\\\'high_price\\\'] ?? 0;
$params[\\\"low_price_{$i}\\\"] = $t[\\\'low_price\\\'] ?? 0;
$params[\\\"trade_price_{$i}\\\"] = $t[\\\'trade_price\\\'] ?? 0;
$params[\\\"prev_closing_price_{$i}\\\"] = $t[\\\'prev_closing_price\\\'] ?? 0;
$params[\\\"change_{$i}\\\"] = $t[\\\'change\\\'] ?? \\\'\\\';
$params[\\\"change_price_{$i}\\\"] = $t[\\\'change_price\\\'] ?? 0;
$params[\\\"change_rate_{$i}\\\"] = $t[\\\'change_rate\\\'] ?? 0;
$params[\\\"signed_change_price_{$i}\\\"] = $t[\\\'signed_change_price\\\'] ?? 0;
$params[\\\"signed_change_rate_{$i}\\\"] = $t[\\\'signed_change_rate\\\'] ?? 0;
$params[\\\"trade_volume_{$i}\\\"] = $t[\\\'trade_volume\\\'] ?? 0;
$params[\\\"acc_trade_volume_{$i}\\\"] = $t[\\\'acc_trade_volume\\\'] ?? 0;
$params[\\\"acc_trade_volume_24h_{$i}\\\"] = $t[\\\'acc_trade_volume_24h\\\'] ?? 0;
$params[\\\"acc_trade_price_{$i}\\\"] = $t[\\\'acc_trade_price\\\'] ?? 0;
$params[\\\"acc_trade_price_24h_{$i}\\\"] = $t[\\\'acc_trade_price_24h\\\'] ?? 0;
$params[\\\"highest_52_week_price_{$i}\\\"] = $t[\\\'highest_52_week_price\\\'] ?? 0;
$params[\\\"highest_52_week_date_{$i}\\\"] = $t[\\\'highest_52_week_date\\\'] ?? \\\'\\\';
$params[\\\"lowest_52_week_price_{$i}\\\"] = $t[\\\'lowest_52_week_price\\\'] ?? 0;
$params[\\\"lowest_52_week_date_{$i}\\\"] = $t[\\\'lowest_52_week_date\\\'] ?? \\\'\\\';
$params[\\\"collected_at_{$i}\\\"] = $at;
$params[\\\"collected_ms_{$i}\\\"] = $ms;
$params[\\\"tr_trade_timestamp_{$i}\\\"] = $t[\\\'trade_timestamp\\\'] ?? 0;
$params[\\\"tr_trade_price_{$i}\\\"] = $t[\\\'trade_price\\\'] ?? 0;
$params[\\\"tr_trade_volume_{$i}\\\"] = $t[\\\'trade_volume\\\'] ?? 0;
$params[\\\"tr_ask_bid_{$i}\\\"] = $t[\\\'ask_bid\\\'] ?? \\\'\\\';
$params[\\\"tr_trade_date_utc_{$i}\\\"] = $t[\\\'trade_date\\\'] ?? \\\'\\\';
$params[\\\"tr_trade_time_utc_{$i}\\\"] = $t[\\\'trade_time\\\'] ?? \\\'\\\';
$params[\\\"tr_trade_date_kst_{$i}\\\"] = $t[\\\'trade_date_kst\\\'] ?? \\\'\\\';
$params[\\\"tr_trade_time_kst_{$i}\\\"] = $t[\\\'trade_time_kst\\\'] ?? \\\'\\\';
$params[\\\"tr_collected_at_{$i}\\\"] = $at;
$params[\\\"tr_collected_ms_{$i}\\\"] = $ms;
$params[\\\"ob_timestamp_{$i}\\\"] = $ob[\\\'timestamp\\\'] ?? 0;
$params[\\\"ob_total_ask_size_{$i}\\\"] = $ob[\\\'total_ask_size\\\'] ?? 0;
$params[\\\"ob_total_bid_size_{$i}\\\"] = $ob[\\\'total_bid_size\\\'] ?? 0;
$params[\\\"ob_units_{$i}\\\"] = isset($ob[\\\'orderbook_units\\\'])
? json_encode($ob[\\\'orderbook_units\\\'], JSON_UNESCAPED_UNICODE)
: null;
}
if (!empty($placeholders)) {
$sql = \\\"
INSERT INTO daemon_upbit_Ticker (
market, trade_date, trade_time, trade_date_kst, trade_time_kst,
opening_price, high_price, low_price, trade_price, prev_closing_price,
`change`, change_price, change_rate, signed_change_price, signed_change_rate,
trade_volume, acc_trade_volume, acc_trade_volume_24h, acc_trade_price, acc_trade_price_24h,
highest_52_week_price, highest_52_week_date, lowest_52_week_price, lowest_52_week_date,
collected_at, collected_ms,
tr_trade_timestamp, tr_trade_price, tr_trade_volume, tr_ask_bid,
tr_trade_date_utc, tr_trade_time_utc, tr_trade_date_kst, tr_trade_time_kst,
tr_collected_at, tr_collected_ms,
ob_timestamp, ob_total_ask_size, ob_total_bid_size, ob_units
) VALUES \\\" . implode(\\\',\\\', $placeholders) . \\\"
ON DUPLICATE KEY UPDATE
trade_date = VALUES(trade_date),
trade_time = VALUES(trade_time),
trade_date_kst = VALUES(trade_date_kst),
trade_time_kst = VALUES(trade_time_kst),
opening_price = VALUES(opening_price),
high_price = VALUES(high_price),
low_price = VALUES(low_price),
trade_price = VALUES(trade_price),
prev_closing_price = VALUES(prev_closing_price),
`change` = VALUES(`change`),
change_price = VALUES(change_price),
change_rate = VALUES(change_rate),
signed_change_price = VALUES(signed_change_price),
signed_change_rate = VALUES(signed_change_rate),
trade_volume = VALUES(trade_volume),
acc_trade_volume = VALUES(acc_trade_volume),
acc_trade_volume_24h = VALUES(acc_trade_volume_24h),
acc_trade_price = VALUES(acc_trade_price),
acc_trade_price_24h = VALUES(acc_trade_price_24h),
highest_52_week_price = VALUES(highest_52_week_price),
highest_52_week_date = VALUES(highest_52_week_date),
lowest_52_week_price = VALUES(lowest_52_week_price),
lowest_52_week_date = VALUES(lowest_52_week_date),
collected_at = VALUES(collected_at),
collected_ms = VALUES(collected_ms),
tr_trade_timestamp = VALUES(tr_trade_timestamp),
tr_trade_price = VALUES(tr_trade_price),
tr_trade_volume = VALUES(tr_trade_volume),
tr_ask_bid = VALUES(tr_ask_bid),
tr_trade_date_utc = VALUES(tr_trade_date_utc),
tr_trade_time_utc = VALUES(tr_trade_time_utc),
tr_trade_date_kst = VALUES(tr_trade_date_kst),
tr_trade_time_kst = VALUES(tr_trade_time_kst),
tr_collected_at = VALUES(tr_collected_at),
tr_collected_ms = VALUES(tr_collected_ms),
ob_timestamp = VALUES(ob_timestamp),
ob_total_ask_size = VALUES(ob_total_ask_size),
ob_total_bid_size = VALUES(ob_total_bid_size),
ob_units = VALUES(ob_units)
\\\";
$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(30);
}
?>
WORK LINE
-
2026-03-03 11:16:44* 방황 끝에 수정 완성인가?
- 일단 수정 완료
1. 바이비트
2. 업비트 -
2026-03-03 18:57:14* 뭐가 뭔지 모를 데몬 작업의 연속
1. 여하튼 그럭저럭 완성본은 만들어졌다.
2. 나머지 정리할 준비
확장 항목
루틴
- 커피
요일
월
화
수
목
금
토
일
월
· 산책
화
수
· 러스 & 이너스 관리
목
금
토
· 기본청소 & 대청소
· 정리 & 정돈
· 정리 & 정돈
일
버전: 1.0