이 스킬
외국인·기관·개인 순매수 imbalance z-score
일별 외국인·기관·개인 순매수 row 에서 imbalance (외인 - 기관 - 개인 또는 외인+기관 vs 개인) 시계열을 만들고 20 거래일 z-score 산출. 추론 라벨 (긍정/부정) 없이 *수급 비대칭* 정량만. gather L1 단일. 트리거 — '수급 imbalance', '외인 기관 z-score', 'flow sentiment'.
연계 절차
이 절차의 단계
- 1 공매도 잔고 변화율 모멘텀
recipes.sentiment.shortBalanceMomentum공매도 잔고와 같이 보면 *매도 측 sentiment* 확인.
- 2 내부자 매수/매도 cluster + 가격 lag
recipes.sentiment.insiderClusterTimingimbalance 와 내부자 cluster 시점 비교.
절차
실행 순서
- 1
일별 외인·기관·개인 순매수 row (Company.gather('flow'))
- 2
imbalance = (foreignNet + institutionNet) - retailNet
- 3
직전 20거래일 rolling mean + stdev → z-score
- 4
20거래일 rolling baseline 짧음 — regime shift 시 z-score 후행.
- 5
외인 vs 기관 분리 안 함 — 외인 매도 + 기관 매수 동시면 imbalance 작아 보임.
- 6
single-day spike (대규모 block deal) 영향 큼.
- 7
분기 조정 (MSCI 리밸런싱 · 배당락) 시점 noise.
- 8
z ≥ 2 cluster 다수: `recipes.sentiment.foreignBuyMomentum` 으로 외인 가속도 cross-check.
- 9
z ≤ -2 + 가격 상승: `recipes.sentiment.retailFlowReversal` 로 개인 매수 추격 신호 확인.
- 10
z 부호 빈번 전환 (±2 사이 oscillation): `recipes.industry.sectorFlowConcentration` 으로 자금 집중도 확인.
- 11
거래일 < 30 이면 z-score 결론 X, *coverage 한계* 만 명시.
- 12
z-score 단일값 → sentiment 라벨 변환 금지.
예시
이런 질문이 들어오면 이 skill 을 쓴다
- 005930 외인 기관 개인 수급 비대칭 z-score
- 최근 외인 매수 - 개인 매도 imbalance 어디까지
- 수급 sentiment 정량 신호 표 — 20일 z-score
- flow rows
출력
기대 결과
- 일별 외인·기관·개인 순매수 표
- imbalance 시계열 + 20일 z-score
- z ≥ 2 또는 ≤ -2 row 카운트
공개 호출 방식
import dartlab
import polars as pl
import statistics
target = "005930"
c = dartlab.Company(target)
def rows(value, limit=120):
if hasattr(value, "head") and hasattr(value, "to_dicts"):
return value.head(limit).to_dicts()
if isinstance(value, list):
return value[:limit]
return []
flow_rows = rows(c.gather("flow"), limit=120)
series = []
for r in flow_rows:
f = float(r.get("foreignNet") or r.get("foreign_net") or 0)
i = float(r.get("institutionNet") or r.get("inst_net") or 0)
p = float(r.get("individualNet") or r.get("indiv_net") or 0)
series.append({
"date": r.get("date") or r.get("tradeDate"),
"foreign": f,
"inst": i,
"indiv": p,
"imbalance": (f + i) - p,
})
series.sort(key=lambda x: str(x["date"] or ""))
imbal = [s["imbalance"] for s in series]
WINDOW = 20
for idx, s in enumerate(series):
if idx < WINDOW:
s["z"] = None
continue
window = imbal[idx-WINDOW:idx]
mu = statistics.mean(window)
sd = statistics.stdev(window) if len(window) > 1 else 0
s["z"] = (s["imbalance"] - mu) / sd if sd > 0 else None
table = pl.DataFrame(series) if series else pl.DataFrame(
schema={"date": pl.Utf8, "foreign": pl.Float64, "inst": pl.Float64,
"indiv": pl.Float64, "imbalance": pl.Float64, "z": pl.Float64}
)
extreme_pos = int((table["z"].fill_null(0) >= 2).sum()) if table.height else 0
extreme_neg = int((table["z"].fill_null(0) <= -2).sum()) if table.height else 0
emit_result(
table=table,
values={"rows": table.height, "extremePos": extreme_pos, "extremeNeg": extreme_neg},
date=str(table["date"].max()) if table.height else None,
sources=["dartlab://gather/flow"],
) 호출 동작
1. 결론 도출
외인+기관 vs 개인 imbalance z-score cluster 단정. 예: “20거래일 imbalance row 중 z ≥ 2 인 day 5건 (모두 양수 — 외인+기관 매수 우세), z ≤ -2 인 day 1건 → 스마트머니 매수 cluster 강함.”
2. 핵심 근거 수집
- 일별 외인·기관·개인 순매수 row (Company.gather(‘flow’))
- imbalance = (foreignNet + institutionNet) - retailNet
- 직전 20거래일 rolling mean + stdev → z-score
3. 메커니즘 분석
일별 imbalance 시계열 60+거래일
↓
20거래일 rolling mean/stdev → z = (imb[t] - rolling_mean) / rolling_std
↓
z ≥ +2 → 스마트머니 매수 cluster 후보 (외인+기관 ↑, 개인 ↓ 또는 매수 동기 약)
z ≤ -2 → 스마트머니 매도 cluster 후보 (외인+기관 ↓, 개인 ↑)
±2 안 → 정상 imbalance z ≥ 2 row 다수 발생 + 가격 상승 = 스마트머니 매수 신호 강함. z ≤ -2 + 가격 상승 = 개인 매수 추격 (역사적 고점 후보).
4. 반례·한계
- 20거래일 rolling baseline 짧음 — regime shift 시 z-score 후행.
- 외인 vs 기관 분리 안 함 — 외인 매도 + 기관 매수 동시면 imbalance 작아 보임.
- single-day spike (대규모 block deal) 영향 큼.
- 분기 조정 (MSCI 리밸런싱 · 배당락) 시점 noise.
5. 후속 모니터링
- z ≥ 2 cluster 다수:
recipes.sentiment.foreignBuyMomentum으로 외인 가속도 cross-check. - z ≤ -2 + 가격 상승:
recipes.sentiment.retailFlowReversal로 개인 매수 추격 신호 확인. - z 부호 빈번 전환 (±2 사이 oscillation):
recipes.industry.sectorFlowConcentration으로 자금 집중도 확인.
대표 반환 형태
| column | 의미 |
|---|---|
date | 거래일 |
foreign | 외국인 순매수 |
inst | 기관 순매수 |
indiv | 개인 순매수 |
imbalance | (외인+기관) − 개인 |
z | 20 거래일 rolling z-score |
연계 절차
- recipes.sentiment.shortBalanceMomentum - 공매도 잔고와 같이 보면 매도 측 sentiment 확인.
- recipes.sentiment.insiderClusterTiming - imbalance 와 내부자 cluster 시점 비교.
기본 검증
- 거래일 < 30 이면 z-score 결론 X, coverage 한계 만 명시.
- z-score 단일값 → sentiment 라벨 변환 금지.
- MSCI 리밸런싱·IPO 록업 해제 등 정기 이벤트 와 겹친 row 는 한계로 분리.
런타임
실행 환경별 호환성
| 환경 | 상태 | 비고 / 제한 |
|---|---|---|
| Local Python | supported | · |
| Server | supported | · |
| MCP | supported | · |
| Web AI | limited | · |
| Pyodide | limited | · |
실패 회피
흔한 실패 · 절대 금지
- 거래일 수 < 30 인 신규 상장주에 z-score 적용
- 외국인 순매수 / 보유율 변화 혼동 (둘은 다른 row)
- 20 일 window 가 짧아 정기 IPO·MSCI 리밸런싱 노이즈
- z-score 단일값으로 sentiment 라벨 (긍정/부정) 단정
- 외인 순매수 단독으로 사건 결론