{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "8c19c1d4",
   "metadata": {},
   "source": [
    "# 01 데이터 입수 — BOKDPM 관측 20변수와 시나리오 입력\n",
    "\n",
    "**목적.** 3장의 계산에 필요한 입력을 불러오고, 고정해 둔 스냅샷이 기록된 파일과 같은지 검증한다.\n",
    "\n",
    "**2026-10 정비판.** 이 패키지는 기준선을 정비한 판이다. 정상상태(장기 수렴값) 13개를 현재 여건에 맞게 바꾸어 BOKDPM을 다시 추정했으므로,\n",
    "사후 표본·평활값·전망값 스냅샷은 2026-10 재추정 결과이다. 관측 20변수 자료파일은 이전 판과 같다. 이전 판(2026-10-08) 패키지는 포털의 보관본으로 남아 있다.\n",
    "\n",
    "| 입력 | 내용 | 출처 |\n",
    "|---|---|---|\n",
    "| `BOKDPM_data_2025.m` | BOKDPM 관측 20변수, 2000Q1–2025Q4(104분기). 추정에 실제로 쓴 Dynare 자료파일(유가 = 두바이유) | ECOS·FRED(원천 계열은 2절) |\n",
    "| `bokdpm_posterior_draws.csv.gz` | 메트로폴리스–헤이스팅스 사후 표본(2블록 × 21,000개, 번인 제외) | 본 연구 Dynare 재추정(2026-10) |\n",
    "| `bokdpm_smoothed_2000_2025.csv` | 내생변수 70개의 칼만 평활값 | 본 연구 Dynare 재추정(2026-10) |\n",
    "| `bokdpm_forecast_2026_2035.csv` | 내생변수 70개의 40분기 기준선 전망 | 본 연구 Dynare 전망(2026-10) |\n",
    "| `bokdpm_posterior_mode.csv` | 사후최빈값(추정 실행·전망 실행) | 본 연구 Dynare 결과(2026-10) |\n",
    "| `ecos_labor_force.csv` | 경제활동인구·취업자, 1999Q3–2026Q2 | ECOS 901Y027 |\n",
    "| `keis_labor_supply_2024_2034.csv` | 경제활동인구·취업자 증감 전망(2024–2029, 2029–2034) | 고용노동부·한국고용정보원 「2024~2034 중장기 인력수급 전망」(2026-02) |\n",
    "| `kosis_생산연령인구.csv` | 생산연령인구(15–64세) 추계 저위·중위·고위 | KOSIS 장래인구추계(DT_1BPA003) |\n",
    "| `cpi_kor_1999_2000.csv` | 소비자물가지수 1999–2000 | 원본 BOKDPM 워크북(ECOS 소비자물가지수) |\n",
    "\n",
    "원천 경로·계열 코드·입수일은 `data/inputs/PROVENANCE.md`에 정리하였다.\n",
    "\n",
    "**실행 방식.** 기본 실행은 스냅샷의 SHA-256과 형태를 검증한다. 환경변수 `ONLINE=1`을 주면 4절에서 ECOS·FRED로 관측 20변수를 다시 받아 스냅샷과 비교한다(인증키 `API_KEY_BOK`·`API_KEY_FRED` 필요).\n",
    "\n",
    "**산출물.** `data/interim/obs20_2000_2025.csv`(관측 20변수 표). `ONLINE=1`이면 `online_obs20.csv`·`online_compare.csv`를 추가로 만든다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "8cdc594f",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:02.772953Z",
     "iopub.status.busy": "2026-10-08T00:09:02.772953Z",
     "iopub.status.idle": "2026-10-08T00:09:03.237172Z",
     "shell.execute_reply": "2026-10-08T00:09:03.237172Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Python 3.12.10 · pandas 2.2.3 · numpy 2.4.6 · scipy 1.18.0 · matplotlib 3.11.0\n",
      "  실행 방식   ONLINE=0 (ECOS·FRED 재수집) · FULL=0 (Dynare 재추정)\n",
      "  ECOS 키     없음 · FRED 키 없음  (ONLINE=0이면 쓰지 않는다)\n",
      "  Octave      있음 · Dynare 있음  (FULL=0이면 쓰지 않는다)\n",
      "  BOKDPM_data_2025.m               있음      23,440 bytes\n",
      "  bokdpm_forecast_2026_2035.csv    있음      56,135 bytes\n",
      "  bokdpm_posterior_draws.csv.gz    있음   5,426,716 bytes\n",
      "  bokdpm_posterior_mode.csv        있음       2,909 bytes\n",
      "  bokdpm_smoothed_2000_2025.csv    있음     142,828 bytes\n",
      "  cpi_kor_1999_2000.csv            있음         146 bytes\n",
      "  ecos_labor_force.csv             있음       2,620 bytes\n",
      "  keis_labor_supply_2024_2034.csv  있음         353 bytes\n",
      "  kosis_생산연령인구.csv                 있음         735 bytes\n"
     ]
    }
   ],
   "source": [
    "import os, time\n",
    "import numpy as np, pandas as pd\n",
    "import config as C\n",
    "import bokdpm_macro as B\n",
    "pd.set_option(\"display.float_format\", lambda v: f\"{v:,.4f}\")\n",
    "pd.set_option(\"display.width\", 160)\n",
    "env = C.setup()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "554426cb",
   "metadata": {},
   "source": [
    "## 1. 스냅샷 무결성\n",
    "\n",
    "입력 파일 9개의 SHA-256을 `config.py`에 기록한 값과 대조한다. 하나라도 다르면 이후 계산이 기록된 산출물과 달라질 수 있으므로 여기서 멈춘다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "7f603c90",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:03.238683Z",
     "iopub.status.busy": "2026-10-08T00:09:03.238683Z",
     "iopub.status.idle": "2026-10-08T00:09:03.253751Z",
     "shell.execute_reply": "2026-10-08T00:09:03.253247Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>크기(bytes)</th>\n",
       "      <th>SHA-256(앞 16자리)</th>\n",
       "      <th>기록값과 일치</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>파일</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>BOKDPM_data_2025.m</th>\n",
       "      <td>23440</td>\n",
       "      <td>79c7586814e92f71</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>bokdpm_forecast_2026_2035.csv</th>\n",
       "      <td>56135</td>\n",
       "      <td>9e2a288dace40f09</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>bokdpm_posterior_draws.csv.gz</th>\n",
       "      <td>5426716</td>\n",
       "      <td>30b3d2d62740f235</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>bokdpm_posterior_mode.csv</th>\n",
       "      <td>2909</td>\n",
       "      <td>79d9f736deb6bdc2</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>bokdpm_smoothed_2000_2025.csv</th>\n",
       "      <td>142828</td>\n",
       "      <td>a6355022bba39ead</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>cpi_kor_1999_2000.csv</th>\n",
       "      <td>146</td>\n",
       "      <td>b64596b28c504fe0</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>ecos_labor_force.csv</th>\n",
       "      <td>2620</td>\n",
       "      <td>b647956255276a61</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>keis_labor_supply_2024_2034.csv</th>\n",
       "      <td>353</td>\n",
       "      <td>a3d0d4e92f5ac218</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>kosis_생산연령인구.csv</th>\n",
       "      <td>735</td>\n",
       "      <td>a51389439be67d17</td>\n",
       "      <td>True</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                 크기(bytes)   SHA-256(앞 16자리)  기록값과 일치\n",
       "파일                                                                   \n",
       "BOKDPM_data_2025.m                   23440  79c7586814e92f71     True\n",
       "bokdpm_forecast_2026_2035.csv        56135  9e2a288dace40f09     True\n",
       "bokdpm_posterior_draws.csv.gz      5426716  30b3d2d62740f235     True\n",
       "bokdpm_posterior_mode.csv             2909  79d9f736deb6bdc2     True\n",
       "bokdpm_smoothed_2000_2025.csv       142828  a6355022bba39ead     True\n",
       "cpi_kor_1999_2000.csv                  146  b64596b28c504fe0     True\n",
       "ecos_labor_force.csv                  2620  b647956255276a61     True\n",
       "keis_labor_supply_2024_2034.csv        353  a3d0d4e92f5ac218     True\n",
       "kosis_생산연령인구.csv                       735  a51389439be67d17     True"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "rows = []\n",
    "for name, expect in C.INPUT_SHA256.items():\n",
    "    p = os.path.join(C.INPUTS, name)\n",
    "    h = B.sha256(p)\n",
    "    rows.append({\"파일\": name, \"크기(bytes)\": os.path.getsize(p), \"SHA-256(앞 16자리)\": h[:16], \"기록값과 일치\": h == expect})\n",
    "chk = pd.DataFrame(rows).set_index(\"파일\")\n",
    "assert chk[\"기록값과 일치\"].all(), \"스냅샷 파일이 기록된 SHA-256과 다르다 — data/inputs/를 원래 상태로 되돌린다\"\n",
    "chk"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "719b4974",
   "metadata": {},
   "source": [
    "## 2. 관측 20변수 — 재추정에 쓴 자료파일\n",
    "\n",
    "관측변수는 한국 14개, 미국 6개(유가 포함), 합계 20개이다. 지수형 변수는 100×자연로그, 금리·비율은 원계열을 쓰며, 원천 계열과 변환은 아래 표와 같다.\n",
    "\n",
    "세 가지 사항을 밝혀 둔다.\n",
    "\n",
    "- **유가(`LOIL_us`)는 두바이유(FRED `POILDUBUSDM`) 분기 평균의 100×자연로그이다.** 국내 도입 원유의 대부분이 중동산이므로 두바이유를 쓴다. 2026-10 정비에서 수집 노트북(`bokdpm_pipeline/01_데이터입수.ipynb`)·자료 원천 기록(`used_data_sources.json`)·관측자료 파일을 모두 이 자료파일과 같은 두바이유 기준으로 정리하였다(이전에는 수집 코드와 문서가 서부텍사스유로 적혀 있었다).\n",
    "- **미국 대출태도(`BLT_us`)의 원천은 확정되지 않았다.** FRED 선임대출담당자 서베이(`DRTSCILM`)와의 상관은 0.90이며, 단순 조합·시차·평활로도 재현되지 않는다. 자료파일 값을 그대로 고정한다.\n",
    "- **ECOS가 제공하지 않는 구간**(국내 대출태도 2000–2001년, 정부지출 증감률 2000년)은 원본 BOKDPM 자료의 값이다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "ce4e0e2a",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:03.254751Z",
     "iopub.status.busy": "2026-10-08T00:09:03.254751Z",
     "iopub.status.idle": "2026-10-08T00:09:03.261161Z",
     "shell.execute_reply": "2026-10-08T00:09:03.261161Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "관측자료: 104분기(2000Q1–2025Q4) × 20변수, 결측 없음\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>원천·변환</th>\n",
       "      <th>2000Q1</th>\n",
       "      <th>2025Q4</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>UNR_kor</th>\n",
       "      <td>ECOS 901Y027/I61BC 실업률</td>\n",
       "      <td>4.8000</td>\n",
       "      <td>2.9000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>RS_kor</th>\n",
       "      <td>ECOS 722Y001/0101000 콜금리(월→분기 평균)</td>\n",
       "      <td>4.9167</td>\n",
       "      <td>2.5000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LCPI_kor</th>\n",
       "      <td>ECOS 901Y009/0 소비자물가지수(월→분기 평균), 100·ln</td>\n",
       "      <td>413.8175</td>\n",
       "      <td>476.5559</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LGDP_kor</th>\n",
       "      <td>ECOS 200Y108/10101 실질GDP(계절조정), 100·ln</td>\n",
       "      <td>1,206.7517</td>\n",
       "      <td>1,286.5561</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Y_kor</th>\n",
       "      <td>ECOS 200Y108/10101 실질GDP의 HP 순환성분(λ=1600)</td>\n",
       "      <td>-0.8543</td>\n",
       "      <td>0.1015</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>BLT_kor</th>\n",
       "      <td>ECOS 514Y001/AA 대출태도(2002Q1~), 2000–2001은 원본 B...</td>\n",
       "      <td>27.8021</td>\n",
       "      <td>-21.0000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>GE_kor</th>\n",
       "      <td>ECOS 901Y013/B01 통합재정 총지출(누계→분기 흐름), 4분기 로그차분,...</td>\n",
       "      <td>-10.0017</td>\n",
       "      <td>-0.7459</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CA_kor</th>\n",
       "      <td>ECOS 301Y013/000000 경상수지 ÷ 명목GDP × 100</td>\n",
       "      <td>-0.2477</td>\n",
       "      <td>8.7614</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LS_kor</th>\n",
       "      <td>ECOS 731Y004/0000001 원/달러 환율(월→분기 평균), 100·ln</td>\n",
       "      <td>702.1739</td>\n",
       "      <td>727.3069</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LDEF_kor</th>\n",
       "      <td>ECOS 200Y107/10101 명목GDP ÷ 실질GDP, 100·ln</td>\n",
       "      <td>412.5399</td>\n",
       "      <td>475.0039</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>RS_us</th>\n",
       "      <td>FRED FEDFUNDS(월→분기 평균)</td>\n",
       "      <td>5.6767</td>\n",
       "      <td>3.8967</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LCPI_us</th>\n",
       "      <td>FRED CPIAUCSL(월→분기 평균), 100·ln</td>\n",
       "      <td>513.6386</td>\n",
       "      <td>578.5507</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LGDP_us</th>\n",
       "      <td>FRED GDPC1, 100·ln</td>\n",
       "      <td>953.8071</td>\n",
       "      <td>1,008.8129</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>Y_us</th>\n",
       "      <td>FRED GDPC1·GDPPOT, 100·ln(실질/잠재)</td>\n",
       "      <td>1.6680</td>\n",
       "      <td>1.0217</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>BLT_us</th>\n",
       "      <td>원천 미확정 합성 대출태도 지수(2026-08-01 자료파일 값 고정; 참고 계열 ...</td>\n",
       "      <td>5.6000</td>\n",
       "      <td>-7.1000</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CD_kor</th>\n",
       "      <td>ECOS 817Y002/010502000 CD(91일)(일→분기 평균)</td>\n",
       "      <td>7.1337</td>\n",
       "      <td>2.6988</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>CB_kor</th>\n",
       "      <td>ECOS 817Y002/010300000 회사채(3년, AA−)(일→분기 평균)</td>\n",
       "      <td>10.0836</td>\n",
       "      <td>3.2923</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LHOUSE_kor</th>\n",
       "      <td>ECOS 901Y062/P63A 주택매매가격지수(월→분기 평균), 100·ln</td>\n",
       "      <td>372.5750</td>\n",
       "      <td>460.0315</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>LOIL_us</th>\n",
       "      <td>FRED POILDUBUSDM 두바이유(월→분기 평균), 100·ln</td>\n",
       "      <td>319.4262</td>\n",
       "      <td>415.2531</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>TB_kor</th>\n",
       "      <td>ECOS 817Y002/010200000 국고채(3년)(일→분기 평균)</td>\n",
       "      <td>9.1082</td>\n",
       "      <td>2.8437</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "                                                        원천·변환     2000Q1     2025Q4\n",
       "UNR_kor                                ECOS 901Y027/I61BC 실업률     4.8000     2.9000\n",
       "RS_kor                      ECOS 722Y001/0101000 콜금리(월→분기 평균)     4.9167     2.5000\n",
       "LCPI_kor              ECOS 901Y009/0 소비자물가지수(월→분기 평균), 100·ln   413.8175   476.5559\n",
       "LGDP_kor               ECOS 200Y108/10101 실질GDP(계절조정), 100·ln 1,206.7517 1,286.5561\n",
       "Y_kor               ECOS 200Y108/10101 실질GDP의 HP 순환성분(λ=1600)    -0.8543     0.1015\n",
       "BLT_kor     ECOS 514Y001/AA 대출태도(2002Q1~), 2000–2001은 원본 B...    27.8021   -21.0000\n",
       "GE_kor      ECOS 901Y013/B01 통합재정 총지출(누계→분기 흐름), 4분기 로그차분,...   -10.0017    -0.7459\n",
       "CA_kor                 ECOS 301Y013/000000 경상수지 ÷ 명목GDP × 100    -0.2477     8.7614\n",
       "LS_kor          ECOS 731Y004/0000001 원/달러 환율(월→분기 평균), 100·ln   702.1739   727.3069\n",
       "LDEF_kor             ECOS 200Y107/10101 명목GDP ÷ 실질GDP, 100·ln   412.5399   475.0039\n",
       "RS_us                                  FRED FEDFUNDS(월→분기 평균)     5.6767     3.8967\n",
       "LCPI_us                        FRED CPIAUCSL(월→분기 평균), 100·ln   513.6386   578.5507\n",
       "LGDP_us                                    FRED GDPC1, 100·ln   953.8071 1,008.8129\n",
       "Y_us                         FRED GDPC1·GDPPOT, 100·ln(실질/잠재)     1.6680     1.0217\n",
       "BLT_us      원천 미확정 합성 대출태도 지수(2026-08-01 자료파일 값 고정; 참고 계열 ...     5.6000    -7.1000\n",
       "CD_kor                ECOS 817Y002/010502000 CD(91일)(일→분기 평균)     7.1337     2.6988\n",
       "CB_kor           ECOS 817Y002/010300000 회사채(3년, AA−)(일→분기 평균)    10.0836     3.2923\n",
       "LHOUSE_kor        ECOS 901Y062/P63A 주택매매가격지수(월→분기 평균), 100·ln   372.5750   460.0315\n",
       "LOIL_us                FRED POILDUBUSDM 두바이유(월→분기 평균), 100·ln   319.4262   415.2531\n",
       "TB_kor                ECOS 817Y002/010200000 국고채(3년)(일→분기 평균)     9.1082     2.8437"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "obs = B.read_dynare_data(C.DATAFILE)\n",
    "assert obs.shape == (C.PUBLISHED[\"관측자료_분기\"], C.PUBLISHED[\"관측변수\"]), obs.shape\n",
    "assert list(obs.columns) == B.VAROBS and obs.notna().all().all()\n",
    "print(f\"관측자료: {obs.shape[0]}분기({obs.index[0]}–{obs.index[-1]}) × {obs.shape[1]}변수, 결측 없음\")\n",
    "src = pd.DataFrame({\"원천·변환\": B.SOURCES}).loc[B.VAROBS]\n",
    "src[\"2000Q1\"], src[\"2025Q4\"] = obs.iloc[0], obs.iloc[-1]\n",
    "src"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5a246b74",
   "metadata": {},
   "source": [
    "### 추정에 쓴 자료인지 확인\n",
    "\n",
    "관측방정식에 측정오차가 없으므로, 추정 결과의 칼만 평활값은 관측변수에서 자료와 같아야 한다. 평활값(`bokdpm_smoothed_2000_2025.csv`)과 자료파일의 차이가 수치 오차 범위(10⁻⁶ 미만)이면 이 자료파일이 추정에 쓰인 것이다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "79babfe0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:03.262164Z",
     "iopub.status.busy": "2026-10-08T00:09:03.262164Z",
     "iopub.status.idle": "2026-10-08T00:09:03.273480Z",
     "shell.execute_reply": "2026-10-08T00:09:03.273480Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "평활값 − 자료파일: 최대 2.88e-09 (BLT_us)\n"
     ]
    }
   ],
   "source": [
    "sm = B.read_exact(C.SMOOTHED, index_col=0)\n",
    "gap = pd.Series({v: float((sm[v] - obs[v]).abs().max()) for v in B.VAROBS}, name=\"최대절대차\")\n",
    "print(f\"평활값 − 자료파일: 최대 {gap.max():.2e} ({gap.idxmax()})\")\n",
    "assert gap.max() < 1e-6, \"평활값이 자료파일과 다르다 — 추정에 다른 자료가 쓰였다\"\n",
    "obs.to_csv(os.path.join(C.INTERIM, \"obs20_2000_2025.csv\"), encoding=\"utf-8-sig\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "0a3498bc",
   "metadata": {},
   "source": [
    "## 3. 시나리오·외생 구성 입력\n",
    "\n",
    "- **경제활동인구**는 산업 외생 '취업자 수'(= 경제활동인구 × (1 − 실업률/100))를 만드는 데 쓴다. 외생 6종 가운데 BOKDPM 밖에서 가져오는 유일한 계열이다. 관측 구간(2026Q2까지) 이후는 **중장기 인력수급 전망(2024–2034)의 기간별 증가율**로 잇는다(02 6절). 이전 판은 최근 20분기 로그 선형추세(연 0.86%)로 연장하여, 생산연령인구 감소가 반영되지 않았다.\n",
    "- **생산연령인구 추계**(통계청 장래인구추계, 2022년 기준)의 저위·중위·고위 경로는 시나리오의 인구 레버이다. 2026-10 정비부터 이 레버가 경제활동인구에 곱해져 외생 '취업자 수'에 전달된다.\n",
    "- **1999–2000년 소비자물가지수**는 2000년 실질금리(회사채 수익률 − 전년동기 물가상승률)를 계산하는 데만 쓴다. 관측자료가 2000Q1에 시작하므로 2000년의 전년동기 상승률을 구하려면 1999년 지수가 필요하다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "072bd9c1",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:03.274486Z",
     "iopub.status.busy": "2026-10-08T00:09:03.274486Z",
     "iopub.status.idle": "2026-10-08T00:09:03.284346Z",
     "shell.execute_reply": "2026-10-08T00:09:03.283842Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "경제활동인구·취업자: 1999Q3–2026Q2 (108분기), 2025Q4 취업자 28,792천 명\n",
      "2000년 전년동기 CPI 상승률(%, 소수 둘째 자리): [1.91, 1.57, 2.94, 2.51]\n",
      "인력수급 전망 경제활동인구 증가율(연, %): 2024–2029 +0.234 · 2029–2034 -0.142\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>경제활동인구_증감_천명</th>\n",
       "      <th>취업자_증감_천명</th>\n",
       "      <th>출처</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>구간</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2024-2029</th>\n",
       "      <td>346</td>\n",
       "      <td>367</td>\n",
       "      <td>고용노동부·한국고용정보원, 「2024~2034 중장기 인력수급 전망」(2026-02...</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2029-2034</th>\n",
       "      <td>-210</td>\n",
       "      <td>-303</td>\n",
       "      <td>고용노동부·한국고용정보원, 「2024~2034 중장기 인력수급 전망」(2026-02...</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "           경제활동인구_증감_천명  취업자_증감_천명                                                 출처\n",
       "구간                                                                                   \n",
       "2024-2029           346        367  고용노동부·한국고용정보원, 「2024~2034 중장기 인력수급 전망」(2026-02...\n",
       "2029-2034          -210       -303  고용노동부·한국고용정보원, 「2024~2034 중장기 인력수급 전망」(2026-02..."
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style scoped>\n",
       "    .dataframe tbody tr th:only-of-type {\n",
       "        vertical-align: middle;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: right;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>중위(천 명)</th>\n",
       "      <th>고위(천 명)</th>\n",
       "      <th>저위(천 명)</th>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>연도</th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "      <th></th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>2025</th>\n",
       "      <td>35912</td>\n",
       "      <td>36039</td>\n",
       "      <td>35785</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2030</th>\n",
       "      <td>34166</td>\n",
       "      <td>34568</td>\n",
       "      <td>33758</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2035</th>\n",
       "      <td>31878</td>\n",
       "      <td>32532</td>\n",
       "      <td>31219</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "</div>"
      ],
      "text/plain": [
       "      중위(천 명)  고위(천 명)  저위(천 명)\n",
       "연도                             \n",
       "2025    35912    36039    35785\n",
       "2030    34166    34568    33758\n",
       "2035    31878    32532    31219"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "lab = pd.read_csv(C.LABOR, index_col=0, encoding=\"utf-8-sig\")\n",
    "pop = pd.read_csv(C.POP, encoding=\"utf-8-sig\")\n",
    "cpi = pd.read_csv(C.CPI, encoding=\"utf-8-sig\")\n",
    "keis = pd.read_csv(C.KEIS, encoding=\"utf-8-sig\")\n",
    "infl = B.inflation_2000(cpi)\n",
    "print(f\"경제활동인구·취업자: {lab.index[0]}–{lab.index[-1]} ({len(lab)}분기), 2025Q4 취업자 {lab.loc['2025Q4', '취업자']:,.0f}천 명\")\n",
    "print(\"2000년 전년동기 CPI 상승률(%, 소수 둘째 자리):\", infl)\n",
    "g = B.keis_growth(lab, keis)\n",
    "print(f\"인력수급 전망 경제활동인구 증가율(연, %): 2024–2029 {g[2029]:+.3f} · 2029–2034 {g[2030]:+.3f}\")\n",
    "display(keis.set_index(\"구간\"))\n",
    "p = pop.set_index(\"연도\").loc[[2025, 2030, 2035]]\n",
    "p.columns = [\"중위(천 명)\", \"고위(천 명)\", \"저위(천 명)\"]\n",
    "p.astype(int)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "10338891",
   "metadata": {},
   "source": [
    "## 4. (선택) ECOS·FRED 재수집과 스냅샷 비교 — `ONLINE=1`\n",
    "\n",
    "`bokdpm_pipeline/01_데이터입수.ipynb`의 수집·변환 절차를 그대로 따르며, 유가는 추정 자료와 같은 두바이유로 받는다. HP 필터는 원본과 같이 수집 시점까지의 전 표본에 적용하므로, 새 분기가 공표되면 표본 끝 부근의 산출갭(`Y_kor`)이 조금씩 달라진다. 미국 국민계정의 연간 개정도 `LGDP_us`·`Y_us`의 차이로 나타난다. 이러한 차이는 자료 개정으로 보고 허용한다. 원천이 확정되지 않은 `BLT_us`와 ECOS 미제공 구간은 스냅샷 값을 쓰므로 비교 대상이 아니다(표의 마지막 열).\n",
    "\n",
    "경제활동인구·취업자(ECOS 901Y027)와 1999–2000년 소비자물가(ECOS 901Y009)도 다시 받아 비교한다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "396d8cd0",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:03.285345Z",
     "iopub.status.busy": "2026-10-08T00:09:03.284846Z",
     "iopub.status.idle": "2026-10-08T00:09:03.288609Z",
     "shell.execute_reply": "2026-10-08T00:09:03.288609Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "ONLINE=1이 아니므로 재수집을 건너뛴다. 이 실행은 스냅샷의 무결성과 추정 자료와의 일치만 확인하였다.\n"
     ]
    }
   ],
   "source": [
    "if C.ONLINE:\n",
    "    assert C.API_KEY_BOK and C.API_KEY_FRED, \"ONLINE=1에는 환경변수 API_KEY_BOK·API_KEY_FRED가 필요하다\"\n",
    "    new, drtscilm = B.refetch_observables(C.API_KEY_BOK, C.API_KEY_FRED, obs)\n",
    "    cmp = B.compare_observables(new, obs)\n",
    "    new.to_csv(os.path.join(C.INTERIM, \"online_obs20.csv\"), encoding=\"utf-8-sig\")\n",
    "    cmp.to_csv(os.path.join(C.INTERIM, \"online_compare.csv\"), encoding=\"utf-8-sig\")\n",
    "    print(f\"재수집 시각 {time.strftime('%Y-%m-%d %H:%M')} · 동일 {int((cmp['판정'] == '동일').sum())}개, 그 밖 {int((cmp['판정'] != '동일').sum())}개\")\n",
    "    print(f\"BLT_us 참고: FRED DRTSCILM과의 상관 {np.corrcoef(drtscilm, obs['BLT_us'])[0, 1]:.3f}, 최대 차이 {np.abs(drtscilm - obs['BLT_us']).max():.1f}\")\n",
    "    lab_new = B.refetch_labor(C.API_KEY_BOK)\n",
    "    print(f\"경제활동인구·취업자: 최신 {lab_new.index[-1]}, 스냅샷 구간 최대 차이 {(lab_new.reindex(lab.index) - lab).abs().max().max():.1f}천 명\")\n",
    "    infl_new = B.refetch_inflation_2000(C.API_KEY_BOK)\n",
    "    print(f\"2000년 CPI 상승률: ECOS 재계산 {infl_new} · 스냅샷 {infl} → {'일치' if infl_new == infl else '불일치'}\")\n",
    "    display(cmp)\n",
    "else:\n",
    "    print(\"ONLINE=1이 아니므로 재수집을 건너뛴다. 이 실행은 스냅샷의 무결성과 추정 자료와의 일치만 확인하였다.\")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c88db36b",
   "metadata": {},
   "source": [
    "## 5. 산출물\n",
    "\n",
    "다음 노트북(`02_분석.ipynb`)은 스냅샷 입력을 직접 읽는다. `data/interim/`에는 관측 20변수 표(와 `ONLINE=1`이면 재수집 비교표)가 남는다."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1c892ef4",
   "metadata": {
    "execution": {
     "iopub.execute_input": "2026-10-08T00:09:03.289619Z",
     "iopub.status.busy": "2026-10-08T00:09:03.289619Z",
     "iopub.status.idle": "2026-10-08T00:09:03.292561Z",
     "shell.execute_reply": "2026-10-08T00:09:03.292058Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "obs20_2000_2025.csv              19,663 bytes\n"
     ]
    }
   ],
   "source": [
    "for f in sorted(os.listdir(C.INTERIM)):\n",
    "    p = os.path.join(C.INTERIM, f)\n",
    "    if os.path.isfile(p):\n",
    "        print(f\"{f:<28} {os.path.getsize(p):>10,d} bytes\")"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.10"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
