diff --git a/agents/stock/workspace/scripts/behive_web.py b/agents/stock/workspace/scripts/behive_web.py index 78f471f..8e1e469 100644 --- a/agents/stock/workspace/scripts/behive_web.py +++ b/agents/stock/workspace/scripts/behive_web.py @@ -9464,7 +9464,8 @@ window.openPinModal = openPinModal; if(v.trigger_price) L.push('발동가: '+Number(v.trigger_price).toLocaleString()+'원'); if(v.trigger_pct!=null&&v.trigger_pct!==0) L.push('발동 등락률: '+(v.trigger_pct>=0?'+':'')+v.trigger_pct+'%'); if(v.count) L.push('당일 발동: '+v.count+'회'); - if(v.release_time) L.push('해제 예정: '+_fmtViTime(v.release_time)); + if(v.trigger_time&&v.trigger_time!=='000000') L.push('발동시각: '+_fmtViTime(v.trigger_time)); + if(v.release_time&&v.release_time!=='000000') L.push('해제: '+_fmtViTime(v.release_time)); head=L.join('\n')+'\n\n─────\n'; } var desc='⚡VI (변동성완화장치)\n\n주가가 짧은 시간에 급변하면 약 2분간\n단일가매매로 전환해 과열을 식히는 장치예요.\n\n• 동적VI: 직전 체결가 대비\n• 정적VI: 당일 기준가 대비\n(코스피200 3%·그 외 6% 등에서 발동)'; diff --git a/agents/stock/workspace/scripts/realtime_hub.py b/agents/stock/workspace/scripts/realtime_hub.py index 9e78e97..01a6352 100644 --- a/agents/stock/workspace/scripts/realtime_hub.py +++ b/agents/stock/workspace/scripts/realtime_hub.py @@ -349,19 +349,22 @@ class RealtimeHub: 'ts': datetime.now(KST).isoformat(), } elif typ == '1h': # VI 발동/해제 - # active 판정: 9068 VI발동구분. 해제시각(1224) 유무와 함께 실증 확인 예정(A단계). - # 실증 로그 — VI는 드물어 부담 없음. 2026-06-11 관찰: 발동 후 해제 1h가 안 오고 - # 1224(해제시각)가 발동시각과 동일 → 읽기 시점 TTL 만료(_vi_expired)로 방어 중. - print(f'[1h raw] {code} {vals}', file=sys.stderr, flush=True) + # 매핑 실증 완료 (2026-06-12 사이드카 날 VI 폭주 ~1,000건 관찰): + # - 9068 = VI 종류 (1=정적, 2=동적, 3=동적+정적) — 발동/해제 구분 아님 + # - 1223 = 발동시각, 1224 = 해제시각. 발동 이벤트는 1224='000000', 해제 이벤트는 시각이 참 + # - 1h는 구독 무관 시장 전역 broadcast (모든 종목 VI가 들어옴) + # 해제 메시지 유실 대비 백스톱으로 읽기 시점 TTL(_vi_expired)은 유지. kind_raw = (vals.get('9068') or '').strip() + release_t = (vals.get('1224') or '').strip() with self._lock: self._vi[code] = { - 'active': kind_raw not in ('', '0', '2'), # ⚠️ 매핑 실증 확인 필요 - 'vi_gubun': kind_raw, + 'active': release_t in ('', '000000'), # 해제시각 없음 = 발동 중 + 'vi_gubun': kind_raw, # VI 종류 (1정적/2동적/3동적+정적) 'apply_kind': (vals.get('1225') or '').strip(), # 정적/동적/동적+정적 'trigger_price': _abs_int(vals.get('1221')), 'trigger_pct': kc._to_float(vals.get('1489')), - 'release_time': (vals.get('1224') or '').strip(), + 'trigger_time': (vals.get('1223') or '').strip(), + 'release_time': release_t, 'direction': (vals.get('9069') or '').strip(), 'count': kc._to_int(vals.get('1490')), # 당일 VI 발동 횟수 'ts': datetime.now(KST).isoformat(),