Files
openclaw/agents/stock/workspace/memory/2026-05-04.md
T
hyowons 549545bde6 Initial commit: OpenClaw 워크스페이스 버전관리 시작
설정·스크립트·스킬·문서·큐레이션 메모리 추적.
시크릿(credentials/identity)·런타임 상태(state/logs/sessions/sqlite)·
백업(clobbered/bak)·dream 캐시는 .gitignore로 제외.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-04 15:10:57 +09:00

44 lines
4.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 2026-05-04
- 키움 REST 조회 중 `일반` 계좌에서 `8005: Token이 유효하지 않습니다` 오류 재현.
- 원인 확인: 토큰 캐시 만료시각은 남아 있었지만 키움 서버에서 해당 토큰을 무효 처리한 상태.
- 즉시 조치: `python3 scripts/kiwoom_client.py token 일반`로 재발급 후 `balance 일반` 정상 조회 확인.
- 코드 보강: `scripts/kiwoom_client.py``_call()`에서 `8005` 또는 `Token이 유효하지 않습니다` 응답 시 해당 계좌 토큰을 `force=True`로 재발급하고 동일 요청 1회 자동 재시도하도록 수정.
- 검증: `state/kiwoom_tokens/일반.json`에 의도적으로 가짜 토큰을 넣은 뒤 `python3 scripts/kiwoom_client.py balance 일반` 실행 → 자동 재발급 후 정상 조회 성공.
## behive_web.py 대공사 (코디 작업)
기존 워치리스트 단일 페이지 → **감시종목 / 관리자 / 가희 3개 탭** 구조로 전면 개편. 세부 변경:
### 데이터 레이어
- `_fetch_all_data()` 도입 — `kt00018(보유)·kt00001(예수금)×4계좌·ka10170(당일매매일지)·ka10001(워치리스트 시세)`를 단일 ThreadPoolExecutor로 병렬 호출. 한 분기 실패해도 다른 분기 계속.
- `_build_owner_data()``stock_portfolio_report`에서 `consolidate / aggregate_journal / group_by_owner / OWNER_LABELS / SNAPSHOT_FILE / _normalize_prev_snap / load_json` 임포트 재활용. 단일 진실 출처.
- 보유 종목의 `day_change`는 web 경로에선 ka10001 보정 생략 (rate limit·렌더 속도). kt00018 raw 사용 — 장마감 후엔 0으로 채워지는 한계 인지.
### 당일 평가손익 (KPI 카드)
- 첫 시도였던 `Σ(day_change×qty for held) + Σ(pl_amt for phantoms)` 방식은 보유 종목의 round-trip 실현분 누락 + 신규 매수분 과대계상으로 부정확 → **`portfolio_daily_snapshot.json`의 prev day 값 기반 `total_net - prev_net`**로 변경. 미실현+실현+현금흐름 모두 포함.
- 비교 일자(`YYYY-MM-DD 대비`)도 함께 표시. 스냅샷 없으면 `'전날 스냅샷 없음'` graceful.
- 즉, **stock.briefing 메일의 일일 P&L과 동일한 ground truth 사용**. 메일·웹 수치 일치.
### 탭 구현 (FOUC 방지 v3)
- v1 라디오 버튼 → v2 `:target/:has` → v3 **`html[data-tab]` attribute selector**로 정착.
- `<head>` 안 sync inline script가 `location.hash` 읽어 body 렌더 **전**에 `documentElement.dataset.tab` 설정 → 첫 paint부터 정답 탭. 새로고침해도 깜빡임 없음.
- `hashchange` 리스너로 탭 클릭 후 즉시 동기화. URL fragment 기반이라 `https://stock.hyowons.net/#tab-self` 직링크도 가능.
### topbar + pull-to-refresh
- 헤더+nav를 `.topbar` 단일 sticky div로 통합. 기존 `top:57px` 하드코딩 의존 제거 (iOS notch 환경에서 헤더 높이가 더 길어져도 nav가 헤더 뒤로 숨던 버그 해결).
- `.page` wrapper로 topbar+컨텐츠 전체 묶음 → 당김 제스처 시 통째로 `translateY` → 타이틀까지 같이 내려옴, 그 위로 빈공간 노출.
- `.page.dragging .topbar { position: static }`으로 당기는 동안만 topbar sticky 일시 해제.
- ptr 인디케이터: 노치 회피 위해 `top: calc(-52px + env(safe-area-inset-top, 0px))`, `z-index:25`로 topbar(z:20)보다 위. 기본 opacity:0, 당김 d/25로 빠른 페이드인.
- 당김 인터랙션: resistance 0.55, 임계 70px 넘으면 `↓` 화살표 → 빨강 spinner(원호 70%, 0.7s linear infinite) 전환 + `location.reload()`. 못 넘으면 cubic-bezier로 spring back.
- `overscroll-behavior-y: none`으로 iOS rubber band 차단해 시각 충돌 제거.
- 헤더 타이틀에 `refresh-flash` keyframe (빨강→평상색 0.8s) — 페이지 로드 1회 발동으로 "방금 갱신됨" 신호.
### 새로고침 버튼
- 기존 `href="/"` (URL fragment 손실) → `<a href="#" onclick="event.preventDefault();location.reload();">`로 변경. 현재 탭 유지하며 데이터만 재요청.
### 영향 범위
- launchd plist 변경 없음. 데몬 재기동만 (`ai.openclaw.stock.behive-web` bootout/bootstrap)으로 새 코드 로드.
- 키움 호출량 약간 증가: 페이지 GET 1회당 `kt00018×1 + kt00001×4 + ka10170×4 + ka10001×N(워치리스트)`. 평소 사용 빈도 고려 시 무시 가능 수준.
- 외부 노출 URL `https://stock.hyowons.net/`는 그대로. 인증 없음·read-only 원칙 유지 (`scripts/behive_web.py`에 주문 함수 부재).