stocks: 미국 주식 지원(개별 종목) + datacollect LLM 직접 호출 + 백엔드 기본 NAS

미국 주식 (개별 종목 조회 — add/check/judge/analysis/position):
- marketUtils: KR(6자리)/US(티커) 시장 판별, 통화·시총 포매팅($/원, B·T/억·조)
- yahooClient: US는 raw 티커(.KQ/.KS 미부착), 심볼 라우팅 분리
- yahooFundamentals: Yahoo quoteSummary(무키) cookie+crumb 핸드셰이크로 ROE/PER/PBR/마진/성장/부채 fetch (429·crumb 하드닝)
- fundamentalsRouter: 심볼별 Naver(KR)/Yahoo(US) 분기
- criteriaEval: market-aware — US는 유보율 미보고라 유동성·안정성을 부채비율(D/E)·시총($B)으로 대체
- types: Stock.market 필드; slashStocks/llmJudge: 통화·라우팅·프롬프트 US 대응
- 테스트: stocksMarket + criteriaEval US 케이스 (전체 통과)

datacollect/llm.ts: LLM을 확장(PC)에서 직접 호출(과거 bridge /api/lm 프록시 제거)
 → 백엔드 NAS 이전 시 PC→NAS→PC 실패 제거, 스크래핑=NAS·LLM 추론=PC 분리

package.json: datacollectBridge 기본값 nas + https://dc.koritips.com; 버전 2.2.261

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 18:43:04 +09:00
parent 4288b212d5
commit e6d780be61
13 changed files with 531 additions and 119 deletions
+47
View File
@@ -0,0 +1,47 @@
/**
* marketUtils — 시장 판별 + 통화/금액 포매팅 테스트.
*/
import {
detectMarket, marketOf, currencyOf, formatMoney,
formatMarketCapKR, formatMarketCapUS,
} from '../src/features/stocks/marketUtils';
describe('stocks marketUtils', () => {
test('detectMarket — 6자리 숫자 = KR, 알파벳 = US', () => {
expect(detectMarket('005930')).toBe('KR');
expect(detectMarket('005935')).toBe('KR');
expect(detectMarket('005930.KS')).toBe('KR');
expect(detectMarket('035720.KQ')).toBe('KR');
expect(detectMarket('AAPL')).toBe('US');
expect(detectMarket('aapl')).toBe('US');
expect(detectMarket('BRK.B')).toBe('US');
expect(detectMarket('TSLA')).toBe('US');
});
test('marketOf — 명시 market 우선, 없으면 심볼 판별', () => {
expect(marketOf({ : 'AAPL' })).toBe('US');
expect(marketOf({ : '005930' })).toBe('KR');
// 명시값이 심볼 판별을 덮어씀 (예: ADR 등 예외)
expect(marketOf({ : 'ABCDEF', market: 'KR' })).toBe('KR');
});
test('currencyOf', () => {
expect(currencyOf('KR')).toBe('KRW');
expect(currencyOf('US')).toBe('USD');
});
test('formatMoney — 원/달러 분기', () => {
expect(formatMoney(72000, 'KR')).toBe('72,000원');
expect(formatMoney(232.45, 'US')).toBe('$232.45');
expect(formatMoney(1234.5, 'US')).toBe('$1,235'); // ≥1000 은 정수 반올림
expect(formatMoney(undefined, 'US')).toBe('-');
});
test('formatMarketCap — KR 억/조, US B/T', () => {
expect(formatMarketCapKR(5000)).toBe('5,000억');
expect(formatMarketCapKR(12000)).toBe('1조 2,000억');
expect(formatMarketCapKR(20000)).toBe('2조');
expect(formatMarketCapUS(3.2e12)).toBe('$3.20T');
expect(formatMarketCapUS(5e9)).toBe('$5.00B');
});
});