Skip to content

Repository files navigation

KBO Analyst

test

"잘하네"에서 멈추지 않고, "왜 잘하는지"까지 설명하는 KBO 데이터 엔진

KBO 경기를 투구 하나 단위(145만 구+)로 내 컴퓨터의 데이터베이스 파일 하나에 쌓고, 검증된 지표 계산식 45종과 분석 도구 28종(MCP)으로 팬의 "왜?"에 숫자 근거가 붙은 답을 만든다. 서버도, 인증키도, 비용도 필요 없다.

네이버 스포츠 투구 데이터 → 내 컴퓨터 DB → 검증된 지표 계산 → 표 · 차트 · AI 답변

이런 답이 나온다

아래는 전부 이 저장소의 실제 조회 결과다 (2026-07-10 기준 DB).

"A 선수, 올해 왜 잘해?" — 타자의 공 고르기

2025 → 2026, 한가운데 높이 코스에 방망이가 나가는 비율이 −9~11%p. 스트라이크존 밖 유인구에 손대는 비율(Chase%)도 30.9 → 27.7%. 스윙 자체는 줄었는데(47.7 → 45.5%) 타격 종합 지표 wOBA는 .370 → .430으로 올랐다. 덜 치는데 더 잘 친다 — 나쁜 공을 골라내기 시작했다는 뜻이다. — kbo_approach_change (2025년 1,658구 vs 2026년 1,189구)

"ERA 3점대던데, 아직 괜찮은 거지?" — 투수 노쇠화 신호

겉보기 평균자책점은 3.91로 멀쩡하다. 그런데 평균 구속 133.6 → 132.3km/h, 헛스윙 유도율(Whiff%) 20.0 → 14.8%, 삼진 비율 14.2%로 구위 지표가 전부 같은 방향으로 내려갔다. 수비 도움을 걷어내고 투수 실력만 남긴 지표(FIP)는 5.39다. 이럴 때는 ERA보다 먼저 경고를 읽어야 한다. — pitcher_overview 시즌 비교 (2026년 1,366구)

"배트 스피드 죽었다던데, 진짜야?" — 잴 수 없는 것을 간접 지표로.

배트 스피드는 KBO 어디에도 공개되지 않아 직접 잴 수 없다. 대신 145km/h 이상 빠른 공을 상대했을 때의 헛스윙률을 본다: 2025년 17.5% → 2026년 25.2% (417구 → 356구). "빠른 공에 방망이가 늦는다"는 신호는 이렇게 숫자로 남는다. — batter_velo_band (계산 방식은 아래 표 참고)

"저러다 갈리는 거 아니야?" — 불펜 운용 · LG

2026년 불펜 등판 42회로 리그 최상위권. 이틀 연속 등판 9회, 한 주 최대 5등판. 3연투 / 7일간 4등판 이상 / 14일간 200구 이상 같은 기준을 넘기면 자동으로 경고 표시가 붙는다. — kbo_usage_pattern

"무사 1루, 번트가 맞아?" — 작전 판단 · 리그 전체

무사 1루에서는 이닝이 끝날 때까지 평균 0.96점이 난다. 번트가 성공해 1사 2루가 되면 이 기대치는 0.85점으로 줄어든다 — 성공해도 평균 0.11점 손해라는 뜻이다. 올해 실제로 시도된 희생번트 337회의 평균 득점 기여도 −0.05점이었다. "번트는 밑지는 장사"가 이 DB의 실제 수치로 확인된다. — re24_matrix · kbo_linear_weights_season

모든 답에는 근거가 된 데이터 양(표본)과 지표의 뜻이 함께 붙는다.

선수 대시보드 예시

어떤 질문에 답하나

궁금한 것 데이터로 확인하는 것 기능
"요즘 왜 좋아졌어?" 최근 경기 흐름 vs 시즌 전체, 구종·구속 변화 kbo_trend_report
"올해 왜 터졌어?" 코스별 스윙 선택 변화, 볼카운트·좌우투수 상대 기록 kbo_approach_change
"쟤 주무기가 뭐야?" 구종별 사용 비율, 구속, 헛스윙 유도율 kbo_pitch_arsenal
"어느 코스가 약해?" 스트라이크존을 칸으로 나눈 성적 히트맵 kbo_batter_zone_chart
"감독이 불펜 혹사하나?" 연투, 휴식일, 최근 7/14일 등판·투구 수 kbo_usage_pattern
"그 번트/교체가 맞았나?" 주자·아웃 상황별 기대 점수, 타석 하나의 점수 가치 re24_matrix · pa_run_value
"배트 스피드 줄었대?" 빠른 공 상대 성적 (간접 지표) batter_velo_band
"구장 덕 아니야?" 구장이 성적을 부풀리는 정도(파크팩터)와 보정 성적 park_factor

3분 시작

git clone https://github.com/SNGCHN/kbo-analyst && cd kbo-analyst
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt        # requests lxml numpy matplotlib

경기 데이터는 저장소에 들어 있지 않다. 네이버 공개 API에서 직접 받는다 (가입·인증 필요 없음):

python3 collector.py 2026-06-10 2026-07-10       # 최근 한 달 — 몇 분
python3 collector.py 2026-03-21 2026-07-10 --workers=10   # 시즌 전체
python3 collector.py 2026-03-21 2026-07-10 --team=LG      # 한 팀만 (~5배 빠름)

이미 받은 경기는 알아서 건너뛰기 때문에, 중간에 끊고 다시 실행해도 이어서 받는다. 받은 다음:

python3 analysis.py validate --season 2026    # 공식 기록과 맞는지 대조
python3 analysis.py batters --season 2026 --min-pitches 20
python3 savant.py dashboard 최정 2026          # PNG 대시보드 생성

Claude Code / MCP로 쓰기

이 폴더를 Claude Code로 열면 .mcp.json이 로컬 분석 서버(kbo-local)를 자동 등록한다. 질문을 던지면 Claude가 아래처럼 도구를 골라 답한다. 해설 규칙·수집 운영·시각화·용어집 스킬까지 함께 쓰려면 .claude-plugin/plugin.json 기준으로 플러그인을 설치하면 된다.

"A 선수 2026 시즌, 작년보다 뭐가 달라졌어?"
"A팀 불펜이 최근 30일 혹사였는지 근거 보여줘"
"시즌 카드 만들어줘"

조회할 때 auto_collect=true를 주면 빠진 경기가 적을 때(15경기 이하)는 자동으로 채우고, 많이 빠졌으면 어느 범위를 받아야 하는지 알려준다. 모든 응답에는 데이터가 얼마나 완전한지 경고가 함께 붙는다. 더 깊은 분석은 kbo_sql(읽기 전용 SQL)로 지표 뷰 45종을 직접 조회한다.

잴 수 없는 것에 답하는 방법

KBO 공개 데이터에는 배트 스피드, 타구 속도, 타구 각도, 공 회전수가 없다 (유료 사이트에도 없다 — 구단만 가진 장비 데이터라서). 이런 질문을 받으면 숫자를 지어내는 대신, 가지고 있는 측정값을 조합해 "대신 볼 수 있는 간접 지표"를 만들고, 간접 지표라는 사실을 답에 함께 밝힌다.

질문 대신 이렇게 본다
배트 스피드 공 빠르기와 스윙 결과는 기록에 있다. 그래서 빠른 공(145km/h 이상)만 골라 헛스윙이 얼마나 늘었는지 본다. 빠른 공에만 헛스윙이 급증하면 "방망이가 늦어졌다"는 신호다. 방망이 움직임 자체는 알 수 없다.
공 회전(무브먼트) 공이 손을 떠난 순간의 속도·가속도 기록은 있다. 여기서 중력 효과를 빼면 "회전 때문에 공이 얼마나 덜 떨어졌는지 / 옆으로 휘었는지"가 계산된다. 회전의 결과는 보이지만 회전수(RPM) 자체는 아니라서, 차트에도 "계산값"으로 표기한다.
타구 방향 타구 추적 장비 데이터가 없어서, 중계 문자 기록의 수비 위치(좌익수/유격수/우전…)를 읽어 좌/중/우로 나눈다. 타자가 좌타인지 우타인지를 반영해 당겨쳤는지/밀어쳤는지 비율을 만든다. 정밀도는 외야 3구역 수준이다.
기대 타격 성적(xwOBA) 타구 속도·각도가 없어 "잘 맞았는데 운이 없었다"를 직접 계산할 수 없다. 대신 실제 결과 성적에, 인플레이 타구가 안타가 된 비율(BABIP)을 나란히 붙여 운·수비 영향이 섞였을 가능성을 따로 보여준다.
몸쪽/바깥쪽 판정 투구 위치 좌표는 측정값이고, 좌우 방향을 타자 기준으로 뒤집기만 하면 된다. 이 방향 기준이 맞는지는 좌·우타자 140만 구의 평균 위치로 확인했다(양쪽 모두 바깥쪽으로 치우침 — 투수가 바깥쪽 승부를 많이 한다는 상식과 일치).

답변은 "직접 잰 값 / 계산으로 얻은 값 / 추정"을 구분해서 말하도록 규칙이 잡혀 있다. 각 지표의 정확한 정의와 계산식은 METRICS.md에 있다.

숫자 검증

  • 수집한 데이터를 경기마다 투수별 공식 기록(삼진/볼넷/피안타/홈런/투구 수)과 빠짐없이 대조한다(validate). 대조에 실패한 시즌은 답변에 경고가 붙는다.
  • 기대 점수(RE24) 계산의 검산: 이 방식으로 더한 팀 득점이 공식 득점과 847/848 경기-팀에서 일치(총 오차 1점), 타석의 99.7%에 점수 기록이 붙어 있다 (2026-07-10 기준 424경기).
  • 안타·홈런이 각각 몇 점 가치인지 실제 데이터로 계산한 결과가 야구 통계학의 표준 순서와 일치: 홈런 +1.72, 3루타 +1.51, 2루타 +1.15, 안타 +0.80, 볼넷 +0.66, 아웃 ≈ 0 (2026시즌, 평균적인 아웃 대비).
  • python3 test_core.py — 자동 테스트 7종. push마다 CI로 돈다.

알려진 한계: wOBA/wRC+는 근사치다. 특히 wRC+ 뷰 두 개는 계산 기준이 달라 서로 비교하면 안 된다(METRICS.md 참고). RE24는 점수가 수집된 경기(2026-07 이후 수집분)만 반영한다. 승리 확률(WE/WPA)은 아직 없다.

시각화

python3 plot.py 후라도 2026-06-03        # 특정일 투구 위치맵
python3 card.py 김건우 2026              # 시즌 카드
python3 zone.py 최정 2026 --metric woba  # 존 히트맵
python3 savant.py dashboard 김건우 2026  # 종합 대시보드

PNG는 charts/에 생성되고, MCP로 요청하면 이미지가 답변에 바로 포함된다. 한글 폰트는 macOS·Windows·Linux에 설치된 폰트를 순서대로 찾는다.

저장소 구성

경로 역할
collector.py 네이버 스포츠 API → SQLite. 다시 실행해도 안전(받은 경기 건너뜀)
metrics.sql 지표 계산식 45종 — 모든 지표의 계산 로직이 이 파일 한 곳에
kbo_mcp.py 추가 설치 없이 도는 로컬 분석 서버 (도구 28개)
analysis.py 표 조회 · 공식 기록 대조(validate) · 파크팩터 · SQL CLI
kbo_official.py KBO 공식 사이트: 구단·로스터·등말소·퓨처스
plot.py card.py zone.py savant.py PNG 시각화
skills/ Claude 스킬: 해설 규칙 · 수집 운영 · 시각화 · 용어집
METRICS.md 지표 정의·계산식·검증 규칙·한계 상세

로드맵

  • 2020~2025 시즌 점수 다시 받기 → 시즌별 기대 점수(RE24) 완성
  • 승리 확률(WE/WPA) — 점수·이닝·주자 상황이 모두 있어 자체 계산 가능
  • wRC+ 두 뷰의 계산 기준 통일
  • 연봉·계약 데이터 수집 (프런트 평가용)

주의사항

원본 데이터는 네이버 스포츠 공개 API와 KBO 공식 사이트에서 수집한다. 이 저장소는 코드만 배포하며 수집된 kbo.db는 배포하지 않는다. 개인 분석과 교육 목적으로 쓰고, 수집기의 기본 대기·재시도 설정을 그대로 둘 것.

License

MIT

About

KBO 세이버메트릭스 해설 엔진 — 투구 단위 공개 데이터로 '왜?'에 답하는 MCP 서버 + Claude 스킬

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages