= 2) {
$status = 'RUNNING';
}
}
?>
PID 파일 경로:
PID 파일 존재:
PID 값:
[]
DAEMON RUNNING
🔴
DAEMON STOPPED
setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (Throwable $e) {}
// API
$api = require '/home/www/DB/upbit_api_url.php';
$API_MARKETS = $api['market_all'] . '?isDetails=false';
$API_TICKER = $api['ticker'] . '?markets=';
function http_get_json($url){
$ctx = stream_context_create([
'http'=>[
'timeout'=>6,
'header'=>"User-Agent: upbit-daemon\r\n",
]
]);
$raw = @file_get_contents($url,false,$ctx);
if ($raw === false) return null;
$j = json_decode($raw,true);
return is_array($j) ? $j : null;
}
$krw = [];
$last_market_refresh = 0;
$load_markets = function() use (&$krw, &$last_market_refresh, $API_MARKETS) {
$m = http_get_json($API_MARKETS);
if (!$m) return false;
$tmp = [];
foreach ($m as $v) {
if (isset($v['market']) && strpos($v['market'], 'KRW-') === 0) {
$tmp[] = $v['market'];
}
}
if (!$tmp) return false;
$krw = $tmp;
$last_market_refresh = time();
return true;
};
$load_markets();
// ===============================
// SQL
// ===============================
$stmt = $pdo->prepare("
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,
ob_collected_at,
ob_collected_ms,
day_of_week,
daemon_id,
daemon_pid,
daemon_heartbeat
) VALUES (
: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,
:ob_collected_at,
:ob_collected_ms,
:day_of_week,
:daemon_id,
:daemon_pid,
:daemon_heartbeat
)
ON DUPLICATE KEY UPDATE
trade_price=VALUES(trade_price),
change_rate=VALUES(change_rate),
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),
ob_collected_at=VALUES(ob_collected_at),
ob_collected_ms=VALUES(ob_collected_ms),
day_of_week=VALUES(day_of_week),
daemon_id=VALUES(daemon_id),
daemon_pid=VALUES(daemon_pid),
daemon_heartbeat=VALUES(daemon_heartbeat),
collected_at=VALUES(collected_at),
collected_ms=VALUES(collected_ms)
");
// ===============================
// LOOP
// ===============================
while (true) {
if (time() - $last_market_refresh >= 600) {
$load_markets();
}
if (!$krw) {
usleep(500000);
continue;
}
$ms = (int)(microtime(true) * 1000);
$at = date('Y-m-d H:i:s');
foreach (array_chunk($krw, 100) as $c) {
$tks = http_get_json($API_TICKER . implode(',', $c));
if (!$tks) continue;
foreach ($tks as $t) {
// Trades
$trs = http_get_json(
'https://api.upbit.com/v1/trades/ticks?market=' . $t['market'] . '&count=1'
);
$tr = (is_array($trs) && isset($trs[0])) ? $trs[0] : null;
// Orderbook
$obs = http_get_json(
'https://api.upbit.com/v1/orderbook?markets=' . $t['market']
);
$ob = (is_array($obs) && isset($obs[0])) ? $obs[0] : null;
// --- 수정 구간: 체결 시각(timestamp) 기준 데이터 산출 ---
// timestamp는 밀리초 단위이므로 1000으로 나눔
$tr_time_ref = (isset($tr['timestamp'])) ? (int)($tr['timestamp'] / 1000) : time();
$target_date_kst = date('Ymd', $tr_time_ref);
$target_time_kst = date('His', $tr_time_ref);
$target_dow = (int)date('w', $tr_time_ref);
// ---------------------------------------------------
$stmt->execute([
':market'=>$t['market']??'',
':trade_date'=>$t['trade_date']??'',
':trade_time'=>$t['trade_time']??'',
':trade_date_kst'=>$t['trade_date_kst']??'',
':trade_time_kst'=>$t['trade_time_kst']??'',
':opening_price'=>$t['opening_price']??0,
':high_price'=>$t['high_price']??0,
':low_price'=>$t['low_price']??0,
':trade_price'=>$t['trade_price']??0,
':prev_closing_price'=>$t['prev_closing_price']??0,
':change'=>$t['change']??'',
':change_price'=>$t['change_price']??0,
':change_rate'=>$t['change_rate']??0,
':signed_change_price'=>$t['signed_change_price']??0,
':signed_change_rate'=>$t['signed_change_rate']??0,
':trade_volume'=>$t['trade_volume']??0,
':acc_trade_volume'=>$t['acc_trade_volume']??0,
':acc_trade_volume_24h'=>$t['acc_trade_volume_24h']??0,
':acc_trade_price'=>$t['acc_trade_price']??0,
':acc_trade_price_24h'=>$t['acc_trade_price_24h']??0,
':highest_52_week_price'=>$t['highest_52_week_price']??0,
':highest_52_week_date'=>$t['highest_52_week_date']??'',
':lowest_52_week_price'=>$t['lowest_52_week_price']??0,
':lowest_52_week_date'=>$t['lowest_52_week_date']??'',
':collected_at'=>$at,
':collected_ms'=>$ms,
// Trades
':tr_trade_timestamp'=>$tr['timestamp'] ?? 0,
':tr_trade_price'=>$tr['trade_price'] ?? 0,
':tr_trade_volume'=>$tr['trade_volume'] ?? 0,
':tr_ask_bid'=>$tr['ask_bid'] ?? '',
':tr_trade_date_utc'=>$tr['trade_date_utc'] ?? '',
':tr_trade_time_utc'=>$tr['trade_time_utc'] ?? '',
':tr_trade_date_kst'=>$target_date_kst, // 수정됨 (체결기준)
':tr_trade_time_kst'=>$target_time_kst, // 수정됨 (체결기준)
':tr_collected_at'=>$at,
':tr_collected_ms'=>$ms,
// Orderbook
':ob_timestamp'=>$ob['timestamp'] ?? 0,
':ob_total_ask_size'=>$ob['total_ask_size'] ?? 0,
':ob_total_bid_size'=>$ob['total_bid_size'] ?? 0,
':ob_units'=>isset($ob['orderbook_units'])
? json_encode($ob['orderbook_units'], JSON_UNESCAPED_UNICODE)
: null,
':ob_collected_at'=>$at,
':ob_collected_ms'=>$ms,
// 관리
':day_of_week'=>$target_dow, // 수정됨 (체결기준 요일)
':daemon_id'=>$DAEMON_ID,
':daemon_pid'=>getmypid(),
':daemon_heartbeat'=>$ms,
]);
}
}
usleep(1000000);
}
}
// ===============================
// 웹 영역
// ===============================
extract($_GET, EXTR_SKIP);
// 실행
if (isset($start) && $start === 'yes') {
$cmd = 'nohup php ' . escapeshellarg(__FILE__) . ' --daemon > /dev/null 2>&1 &';
@exec($cmd);
?>
데몬 실행 요청 완료
유령데몬 삭제 페이지 : 무당 부적 부착 -> 데몬 실행
데몬 삭제 완료";
}
?>
유령데몬 관리 페이지 : 플렛폼 0S 테이블