CORE TERMINAL
OLD BOY WORK : 올드보이 작업장
바이비트 몽땅 수집 데몬 작업 - 기본 500종목 이상 수집
DATE: 2026-03-08 12:54
* 바이비트 몽땅 수집 데몬 작업 - 기본 500종목 이상 수집
- 모든 변수 감안
1. 5초 600콜 : 아웃라인 컷 수집 데몬 제작
가. 기본 수집
나. 타격기 수집
다. 타이밍 수집
- 모든 변수 감안
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:041. 보안 무시 : 보안은 포트 보안 - 폐쇄형
2. 자체 관리 무시 : 관리는 툴로 관리
3. 기타 관리 : 구조 관리 -
2026-03-08 12:54:531. 더 간단하게 간다.
2. 주소 9개 넣는것이 파일 상단이다.
* 맞지
1. 코드 수 졸라 길고 복잡하거 부터 잡는다.
2. 현재 데몬 별도 디렉토리 관리.
* 파일명
* 호출 파일 들 파일명 정한다.
* 데몬 해부해서 부위별로 파일 나눈다.
1. 데몬 다이어트 시킨 다음 : 주소 정린다.
* 시작 자체를 깔끔한 생태에서 부위별로 작업한다. -
2026-03-08 12:55:30daemon_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:591. 일단 여기서 정리하고
2. 인클루드 하고
3. 각 호출 파일 작업한다. -
2026-03-08 14:52:471. 차 몸통 분리
daemon_bybit_total.php ← 몸통
bybit_total_env.php ← 환경기
bybit_total_striker.php ← 타격기
bybit_total_heartbeat.php ← heartbeat -
2026-03-08 20:46:00bybit_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:261번 주소에는 필수 항목 없다. 통과 : 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* 데몬 작업 완성
버전: 2.0