| name | ipzitalk-price-trend |
| description | 단지 하나와 전용타입군 하나를 고정해 최근 N개월(기본 12) 매매 실거래의 월별 중위 평당가· 중위 거래가·표본 수 추이를 차트와 표로 만든다. "시세추이", "이 단지 시세 흐름", "OO아파트 최근 시세", "평당가 추이", "실거래가 추이", "요즘 얼마에 팔려" 등의 표현이 있으면 이 스킬을 사용한다. 지역 전체 비교는 최근 시장동향 스킬로 분리한다.
|
| version | 1.2.5 |
| license | proprietary |
실거래 추이 분석
tier: L2
단지 하나 + 전용타입군 하나를 고정해 월별 중위 평당가 추이를 낸다.
※ 참고 신호다. 현재 가격 감정이 아니다. 국토교통부에 신고된 매매의 중위 실거래가이며 신고가(최고가)가 아니다.
입력
| 파라미터 | 필수 | 기본 | 설명 |
|---|
complex_query | ✅ | - | 단지명 |
exclusive_area_sqm | ✕ | 자동 | 우세 전용타입군을 자동 선택. 84를 상수로 박지 말 것 |
months | ✕ | 12 | 조회 개월 수. N개월 = N크레딧 |
- 🚨 지역(
region_code) 단독 입력은 이 스킬 용도가 아니다. 전용타입을 통일할 수 없어
구성 편향으로 값이 널뛴다. → 최근 시장동향 스킬로 보낸다.
워크플로우
- 단지 교차검증 —
get_complex_info(complex_query) 로 지번 주소·세대수·면적 구성을 먼저 확인한다.
다지번 대단지는 실거래 매칭에서 일부가 누락될 수 있다.
- 전용타입군 결정 (아래 규칙)
- 월별 조회 —
get_complex_trades(complex_query, year_month, trade_type='sale') × N개월. 월 1콜.
- 집계 — 타입군에 속한 거래만 골라 월별 중위 평당가·중위 거래가·건수 산출.
- 렌더 — 고정 템플릿
templates/result.html 의 ipzi-data 비실행 JSON 블록 만 채운다.
기준월
최근 1~2개월은 신고 지연으로 과소집계된다. 최신 확정월은 조회 시점의 2개월 전이다.
지연 구간을 시계열에 넣으면 하락처럼 보인다. 넣어야 한다면 표에 신고 지연 꼬리표를 단다.
🚨 전용타입군은 밴드로 정한다 — 84를 상수로 쓰지 않는다
84㎡가 없는 단지가 실제로 있다. 대형만 있는 단지도, 소형만 있는 단지도 있다.
그런데도 84를 기본값으로 박으면 그 단지에서 실거래가 0건으로 나오거나, 엉뚱한 타입이 잡힌다.
결정 규칙
- 조회 기간의 거래에서 전용면적 분포를 모은다.
- ±1.5㎡ 밴드로 묶는다. 밴드폭 상한은
3㎡ 와 중앙값의 3% 중 작은 쪽.
- 누적 표본이 가장 많은 밴드를 우세 타입군으로 삼는다.
- 최신 확정월 거래가 0건인 밴드는 고르지 않는다. 추이가 끊긴 채로 시작한다.
- 🚨
Math.trunc 정수부 단독 매칭 금지. 106.4 / 107.9 / 108.2 가 세 그룹으로 쪼개져
최대 그룹조차 최신월 0건이 되는 일이 실제로 벌어진다. 같은 타입군을 갈라놓는다.
- 🚨 어떤 밴드를 골랐는지 화면에 반드시 적는다(
ipzi-data.areaNote). 근거 없이 숫자만 보이면 믿을 수 없다.
🚨 응답의 요약 평당가를 그대로 쓰지 않는다
도구가 주는 월 요약 평당가는 그 달의 모든 전용타입을 섞은 값이다.
타입군을 고정한 뒤 직접 다시 계산한다. 섞으면 실거래 가격 흐름이 아니라 거래 구성 변화가 그려진다.
편향은 단지마다 다르다. 실측에서 한 단지는 혼합값과 타입 고정값의 차이가 18%,
다른 단지는 0.6% 였다. 작다고 넘길 수 있는 크기가 아니다.
표본 규칙
| 월 표본 | 처리 |
|---|
≥8 | 정상 |
4~7 | 참고용. 표에 표본 부족 꼬리표 |
<4 | 판정 유보. 차트에서 속 빈 점. 추세·등급 단정 금지 |
0 | 거래 없음. 선을 끊고 회색 밴드로 표시 |
- 🚨 시작점 표본이 4건 미만인 달을 기준으로 변화율을 내지 않는다.
실측에서 시작월을 바꾸자 같은 기간 변화율이
−8.2% 와 −5.7% 로 갈렸다.
- 🚨 결측월을 0으로 채우지 않는다. 평균에도, 이동평균에도 넣지 않는다.
0으로 채우면 "거래 없음"이 "가장 싸다"로 뒤집힌다.
🚨 [PARTIAL] 지정 단지 미발견 은 오탐이 잦다
그달에 거래가 0건이어도 같은 문구가 붙는다. 해소 실패와 그달 거래 0건은 다른 상태다.
- 전 기간 매칭이 0건일 때만 중단한다. 한두 달 0건이면 그 달만 결측으로 두고 계속한다.
- 중단할 때도 값을 지어내지 않는다. "실거래 추이 생성 금지"를 그대로 지킨다.
필수 단서 · 금지 표현
- 필수: 중위 실거래가(신고가 아님) · 직전 1~2개월 신고 지연 · 전용타입군 고정 사실과 그 근거 ·
결측월 처리 방식 · 표본 수 · 출처(국토교통부 실거래가)와 조회일
- 금지: "현재 가격 감정", "적정가 OO원" 단정, 신고가를 대표 실거래 수준처럼 제시,
결측월을 0으로 채운 평균, 표본 4건 미만 시작점의 변화율
엣지 · 실패 처리
| 상황 | 처리 |
|---|
| 단지 해소 실패(전 기간 0건) | 중단. 실거래 추이 생성 금지 |
| 특정 월만 0건 | 그 달만 결측. 선 끊고 회색 밴드 |
| 우세 밴드의 최신월 0건 | 다음 밴드 검토. 그래도 없으면 판정 유보 |
| 표본 < 4 인 달이 절반 이상 | 전체 판정 유보 배지. 추세 단정 금지 |
| 다지번 대단지 | 단지 정보로 교차검증하고 누락 가능성을 hedge 에 명시 |
출력 포맷
- 히어로 → KPI 4 → 타입군 근거 콜아웃 → 추이 차트 → 월별 표 → 제외·유보한 달 → 유의사항·출처
- 사용자 노출 제목은
실거래 추이 분석, 차트는 월별 실거래 중위 평당가 추이, 표는 월별 실거래 상세로 쓴다. 사용자가 “시세”라고 요청해도 결과 제목을 “시세추이 분석”으로 되돌리지 않는다.
- 화면 표기는 사용자 용어만. 출처는 「국토교통부 실거래가」 · 「공동주택관리정보시스템(K-apt)」.
내부 필드명·도구명을 화면에 노출하지 않는다.
HTML 산출물 계약 🚨
- 렌더 데이터는
result.json에 저장하고, 사용자 전달 HTML은 고정 정본 templates/result.html의 ipzi-data 블록만 교체해 만든다. 새 HTML을 작성하거나 마크업·CSS·렌더 JS를 수정하지 않는다.
- 셸 사용이 허용된 환경에서는 스킬 기준
../../scripts/html_artifact_contract.mjs를 --file-name "<단지명>_실거래추이_<최신확정월>"과 함께 사용한다. 최종 사용자 파일명은 <단지명>_실거래추이_<최신확정월>.html이다.
- shell-free 환경에서는 같은 파일명으로 저장하고 교체 전후의 fixed template region이 원본과 같은지 비교한다.
- 내부 파일
result.json·audit.json은 고정 이름을 유지하되, 사용자 전달 HTML을 result.html이나 index.html이라는 고정 이름으로 내지 않는다.
🚨 차트 레이어 계약 — 색과 대시 패턴이 곧 의미다
형제 스킬 ipzitalk-complex-overview-all 과 같은 시각 언어를 쓴다. 임의로 바꾸면 두 산출물을 나란히 놓았을 때 오독한다.
| 레이어 | 스펙 | 의미 | ipzi-data JSON |
|---|
| 주계열 | --brand 실선 2.6px | 타입군 중위 평당가 | series (필수) |
| 이동평균 | --brand 실선 2px · stroke-opacity .35 | 주계열의 평활 → 계열색을 옅게 | maWindow |
| 대조선 | --x 파선 5 4 1.8px | 다른 전용타입을 섞은 값 | compareSeries (선택) |
| 기간 평균선 | 계열색 점선 2 3 1.2px + 우측 값 라벨 | 그 계열의 요약 통계 | avgPyeong · avgPyeongCompare |
| 신고지연 경계 | --o 세로 파선 3 3 + 라벨 | 이 오른쪽은 확정 아님 | provisionalFrom (선택) |
| 결측 밴드 | --x-s 사각형 + 거래없음 글자 | 거래 0건. 보간 금지 | series[].pyeong = null |
- 🚨
5 4 와 2 3 을 섞지 말 것. 5 4 는 대조선 전용이다. 기간 평균선에 5 4 를 쓰면
"다른 평형대 실거래"와 "평균값"이 같은 그림이 된다(v1.0.0 에서 실제로 그랬다).
- 🚨 이동평균을 회색으로 칠하지 말 것. 주계열의 평활인데 별개 계열처럼 읽힌다.
점의 채움과 테두리
| 점 | 뜻 |
|---|
| 채운 파란 점 | 표본 충분(n ≥ thinSampleUnder) |
| 속 빈 점 · 파란 테두리 | 표본 부족(n < 4) → 판정 유보 |
| 속 빈 점 · 주황 테두리 | 신고지연(확정 아님). 경계선과 같은 색 |
얇은 원 + 확정창 고점/저점 | 극점 표시 |
- 🚨 고점·저점은 확정창 + 정상 표본(
n ≥ 8) 안에서만 찾는다. 신고지연 달과 표본이 얇은 달을 뺀다.
안 그러면 아직 안 들어온 거래가 고점이 되고, 거래 1건짜리 달이 저점이 된다.
- 실측(위례): 신고지연 26.06(6,794)이 26.04(6,688)보다 높지만 26.06 은 후보가 아니다.
- 실측(헬리오시티):
n≥4 로 두면 26.02(11,806·N4)가 26.01(11,788·N7)을 0.15% 차이로 이겨 고점이 됐다.
n≥8 로 올리니 고점은 25.11(11,669·N9)로 바뀐다.
annotateExtremes: false 로 끌 수 있다. 후보가 2개 미만이면 자동으로 생략된다.
표본 문턱은 둘이다 — 하나로 합치지 말 것
| 필드 | 기본 | 뜻 |
|---|
thinSampleUnder | 4 | 미만 = 판정 유보. 차트에서 속 빈 점 |
normalSampleFrom | 8 | 미만 = 표본 부족(참고용) · 이상 = 정상 |
extremesMinSample | null | 극점 후보의 최소 표본. null 이면 normalSampleFrom 을 쓴다 |
- 🚨
thinSampleUnder 를 8 로 올려 극점을 막지 말 것. 그러면 4~7건인 달이 전부 속 빈 점이 되어
위 표본 규칙(4~7 = 참고용)과 충돌한다. 극점만 막으려면 extremesMinSample 을 쓴다.
- ⚠️ 표본이 얇은 단지에서는 고점·저점 라벨이 아예 사라진다. 후보가 2개 미만이기 때문이다.
실측: 위례(최대 N5) · 반포자이(최대 N4) 는
n≥8 인 달이 0개라 극점이 그려지지 않는다.
이건 버그가 아니라 의도다. 없는 확신을 그리지 않는다.
선택 필드 — 없으면 레이어를 통째로 생략한다
compareSeries · avgPyeongCompare · provisionalFrom · extremesMinSample 은 모두 선택이다. 없으면 그리지 않는다.
단일 평형 단지에는 compareSeries 를 넣지 말 것. 주계열과 겹쳐 그려져 의미가 없다.
compareSeries 는 series 와 같은 달·같은 길이여야 한다. 어긋나면 템플릿이 경고를 내고 대조선을 버린다.
- 🚨
provisionalFrom 은 series 안에 있는 달이어야 한다. 범위 밖이면 신고지연 달이 하나도 없다.
그때 템플릿은 경계선·라벨·범례 항목을 전부 생략한다(그리지 않은 레이어를 범례에 적지 않는다).
- 🚨 신고지연 달의 거래가 0건이면 주황 점도 0개다. 경계선은 그리되 범례의 점 견본은 뺀다.
실측(반포자이): 26.06 은 대형 2건만 있고 84㎡ 타입군 거래가 없어 점이 하나도 안 그려진다.
provisionalFrom 이 첫 달이면 경계선을 그을 자리가 없다. 대신 차트 왼쪽 위에
전 구간 신고지연 · 확정 아님 을 적는다. 침묵하면 화면에서 그 사실이 사라진다.
avgLabel · avgCompareLabel 로 평균선 라벨을 바꿀 수 있다. 기본값은 평균 · 혼합 평균.
🚨 KPI 앵커 · 고점 판정 · 태그 (2026-07-10 결정)
변화율은 첫 확정월 → 최신 확정월
저점에서 고점으로 재면 언제나 최대값이 나온다. 두 달을 라벨에 적어도 헤드라인은 상승으로 읽힌다.
실측(헬리오시티 84.98㎡ 타입군):
저점 → 고점 2025.06 → 2026.02 10,502 → 11,806 +12.4% ← 이렇게 쓰지 않는다
첫 → 최신 2025.06 → 2026.05 10,502 → 10,913 +3.9% ← 이것이 기간 변화율
고점 대비 현재 11,669 → 10,913 -6.5% ← 나란히 보인다
- 🚨 고점을 끝점으로 삼는 변화율을 헤드라인 KPI 로 쓰지 않는다.
- 고점을 보이겠다면
확정창 고점 대비 를 함께 낸다. 그래야 지금 위치를 안다.
고점·저점은 정상 표본에서만 찾는다
extremesMinSample(기본 normalSampleFrom = 8). 4건짜리 달의 중위값이 7건짜리를 0.15% 차이로
이기고 고점이 되는 일이 실제로 있었다. 그 차이로 고점을 선언할 수 없다.
표 태그는 n 과 provisionalFrom 에서 파생한다
tag 문자열 하나로는 "표본 부족"과 "신고지연"이 겹칠 때 하나가 지워진다.
실측에서 n=2 인 신고지연 달의 판정 유보 가 사라졌다. 두 사실은 서로를 대체하지 않는다.
| 조건 | 태그 |
|---|
n = 0 (거래 없음) | 태그 없음. 값 칸이 거래 없음 이라 말한다 |
0 < n < thinSampleUnder(4) | 판정 유보 |
4 ≤ n < normalSampleFrom(8) | 표본 부족 |
ym ≥ provisionalFrom | 신고지연 (위와 함께 붙는다. 거래 0건이어도 붙는다) |
- 🚨
n = 0 에 판정 유보 를 붙이지 말 것. 0 도 4 미만이지만 다른 상태다.
실측(방배롯데캐슬아르떼): 13개월 중 7개월이 거래 0건이라 13행 전부 같은 태그가 달렸다.
모든 행이 같은 태그면 태그는 정보를 잃는다.
ipzi-data.table[].tag 를 채우지 말 것. 템플릿이 n 에서 파생한다.
섹션마다 출처를 작게 단다
데이터 블록 하단에 .src 한 줄. 도구·API 이름은 쓰지 않는다. 사용자가 아는 기관명만.
| 블록 | 출처 표기 |
|---|
| 단지 개요·세대수·준공·주차·연차 | 공동주택관리정보시스템(K-apt) |
| 매매·전세·평당가·거래량 | 국토교통부 실거래가 |
| 학교·교통·생활·상권 등 장소 | 카카오맵 |
| 분양공고·분양가·주택형·입주월 | 청약홈 |
| 지도 (장소 마커) | 네이버 지도 · 카카오맵 |
| 지도 (분양공고 마커) | 네이버 지도 · 청약홈 |
- 🚨 출처 문자열은
ipzi-data JSON으로 받지 않고 템플릿 마크업에 직접 박는다.
어느 블록이 어디서 왔는지는 실행마다 달라지지 않는다. 데이터로 받으면 채우는 걸 잊거나 틀리게 쓸 여지만 생긴다.
- 🚨 한 블록에 두 출처가 섞이면 병기한다. 예:
세대수·주차 — 공동주택관리정보시스템(K-apt) · 위치 — 카카오맵.
하나로 뭉뚱그리면 어느 숫자가 어디서 왔는지 사용자가 알 수 없다.
- 🚨 쓰지 않은 기관을 출처로 적지 않는다. 우리가 부르는 곳은 위 다섯 곳뿐이다.
- 히어로·유의사항·푸터에는 달지 않는다. 데이터 블록에만.
디자인 정본
스킬 폴더 밖 문서에 의존하지 않도록 규칙을 여기 인라인으로 둔다.
- CDN·외부 폰트·이모지 금지. 아이콘은
<symbol> 인라인 + <use> 참조로 self-contained.
- 라이트/다크 양쪽.
prefers-color-scheme + :root[data-theme] 모두 대응.
- 토큰만 사용:
--g/--y/--o/--r/--x/--brand/--up/--down/--zebra (+ -s 배경 변형).
- 예외 상태:
null 은 "정보없음"(0 아님) · 표본 부족은 판정 유보.
★·☆ 는 활자 기호이며 이모지가 아니다.
- 차트 CSS:
.chartbox{overflow-x:auto} + .chartbox > svg{min-width:660px}.
🚨 .chartbox svg 로 쓰면 카드 안의 아이콘 SVG까지 최소 폭이 잡혀 아이콘이 거대해진다.
자식 선택자(>)를 반드시 쓸 것.
- 🚨 차트 좌표를 하드코딩하지 않는다. 달 수·값 범위가 바뀌면 조용히 깨진다.
series 에서 계산한다. 템플릿의 렌더 JS 가 그렇게 되어 있다.
검증된 사항 (운영 MCP 실호출)
get_complex_trades 월 1콜 × 12개월 정상. get_complex_info 로 면적 구성 교차검증 정상.
- 한 단지는 12개월 중 3개월이 거래 0건이었다. 결측 처리 없이는 시계열이 성립하지 않는다.
- 혼합 평당가와 타입 고정 평당가의 차이: 한 단지 18%, 다른 단지 0.6%.
- 정수부 매칭이 같은 타입군을 세 그룹으로 쪼개 최대 그룹의 최신월이 0건이 되는 사례를 확인했다.
MCP 도구 네임스페이스와 출처
ipzitalk MCP 도구의 네임스페이스는 실행 환경(Codex, Claude Code, Hermes, claude.ai 커넥터 등)에 따라 다르다.
이 문서에 적힌 도구 이름(search_announcement_info, get_geocode, get_map_embed_url 등)은 접두사 없는 기본 도구명(base tool name) 이다.
- 먼저 연결된 도구 목록에서 같은 기본 도구명을 찾는다.
- 그중
ipzitalk-remote 플러그인의 ipzitalk 서버 provenance가 확인되는 도구만 우선 사용한다. Codex에서는 실제 도구 호출 이벤트의 server: ipzitalk과 기본 도구명을 기준으로 확인한다.
presale-mcp 또는 다른 로컬 MCP provenance의 동명 도구는 Remote Skill의 대체 수단으로 사용하지 않는다.
- provenance를 확인할 수 없거나 같은 기본 도구명이 여러 서버에 있어 모호하면 임의 선택하지 말고 중단하여 필요한 Remote 도구명을 안내한다.
클라이언트가 연결 도구 목록에 plugin/server provenance를 구조적으로 제공하지 않을 때만 다음 명시적 fallback을 사용한다.
mcp__plugin_ipzitalk-remote_ipzitalk__<도구명>
mcp__ipzitalk_mcp__<도구명>
mcp__ipzitalk__<도구명>
mcp__claude_ai_ipzitalk__<도구명>
fallback으로도 Remote 출처를 유일하게 확인할 수 없으면 값을 추정하지 말고, 사용자에게 ipzitalk Remote MCP 연결 상태를 확인하도록 안내한 뒤 중단한다.