feat: WBS-2.2 US 주식 가격 settings 수동입력 -> 자동 Weight_Pct 연동
This commit is contained in:
@@ -1998,6 +1998,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;
|
||||
|
||||
@@ -2024,6 +2056,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;
|
||||
@@ -2036,9 +2077,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';
|
||||
@@ -2066,6 +2112,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 컬럼
|
||||
|
||||
Reference in New Issue
Block a user