Merge pull request '[WBS-2.2] US 주식 가격 settings 수동입력 -> 자동 Weight_Pct 연동' (#7) from feature/wbs-2.2 into main

Reviewed-on: http://192.168.123.100:8418/KimJaeHyun/myfinance/pulls/7
This commit is contained in:
2026-06-13 14:18:53 +09:00
@@ -2002,6 +2002,38 @@ function parseAccountSnapshot_(ss, totalAssetKrw, dfMap) {
var sheet = ss.getSheetByName(AS_SHEET_NAME);
if (!sheet) { Logger.log('[HARNESS] account_snapshot 시트 없음'); return result; }
// ── 환율(USD_KRW) 로드 ──────────────────────────────────────────────────
var usdKrw = 1400; // default fallback
try {
var macroSheet = ss.getSheetByName("macro");
if (macroSheet) {
var mData = macroSheet.getDataRange().getValues();
var headerRowIdx = 0;
for (var r = 0; r < Math.min(5, mData.length); r++) {
var row = mData[r] ?? [];
if (row.indexOf("Symbol") >= 0 && row.indexOf("Name") >= 0) {
headerRowIdx = r;
break;
}
}
var nameIdx = mData[headerRowIdx].indexOf("Name");
var closeIdx = mData[headerRowIdx].indexOf("Close");
if (nameIdx >= 0 && closeIdx >= 0) {
for (var i = headerRowIdx + 1; i < mData.length; i++) {
if (String(mData[i][nameIdx]).trim() === "USD_KRW") {
var val = parseFloat(mData[i][closeIdx]);
if (Number.isFinite(val) && val > 0) {
usdKrw = val;
break;
}
}
}
}
}
} catch (e) {
Logger.log('[WARN] parseAccountSnapshot_ 환율 로드 실패: ' + e.message);
}
var data = sheet.getDataRange().getValues();
if (data.length <= AS_HEADER_ROW_IDX) return result;
@@ -2028,6 +2060,15 @@ function parseAccountSnapshot_(ss, totalAssetKrw, dfMap) {
var d2Cash = numCol_(row, c, 'settlement_cash_d2');
var openOrder = numCol_(row, c, 'open_order_amount');
var mktValue = numCol_(row, c, 'market_value');
var ticker = normTicker_(c['ticker'] !== undefined ? row[c['ticker']] : '');
var isUsTicker = /^[A-Z]+$/.test(ticker);
if (isUsTicker) {
var currPrice = numCol_(row, c, 'current_price');
if (currPrice > 0 && holdingQty > 0) {
mktValue = Math.round(currPrice * holdingQty * usdKrw);
}
}
if (!isRestrictedAcct) {
if (immCash > 0) result.immediateCashKrw += immCash;
@@ -2040,9 +2081,14 @@ function parseAccountSnapshot_(ss, totalAssetKrw, dfMap) {
if (holdingQty <= 0 || userConfirmed !== 'Y') continue;
// 보유 포지션 처리
var ticker = normTicker_(c['ticker'] !== undefined ? row[c['ticker']] : '');
var avgCost = numCol_(row, c, 'average_cost');
if (isUsTicker && avgCost > 0) {
avgCost = round2_(avgCost * usdKrw);
}
var stopPrice = numCol_(row, c, 'stop_price');
if (isUsTicker && stopPrice > 0) {
stopPrice = round2_(stopPrice * usdKrw);
}
var dfRow = dfMap[ticker] || {};
var atr20 = dfRow.atr20 || 0;
var stopSrc = 'MANUAL';
@@ -2070,6 +2116,10 @@ function parseAccountSnapshot_(ss, totalAssetKrw, dfMap) {
// stop_price 이탈 감지
var close = dfRow.close || 0;
if (isUsTicker) {
var currPrice = numCol_(row, c, 'current_price');
close = currPrice > 0 ? round2_(currPrice * usdKrw) : round2_(close * usdKrw);
}
var stopBreach = close > 0 && stopPrice > 0 && close <= stopPrice;
// weight_pct: settings의 total_asset 기준으로 계산, 없으면 account_snapshot 컬럼