"""#30 骨格★:(1) H28〜R8 11回の決め手の数 (2) 積み上げの差(改定率の累積 − 物価の累積)を ①物価と使われた賃金の差 ②調整 ③据え置き に分ける。 入力=calc.py と同じ年表(Issue #30 本文の検証官合格の表)。各年の改定率 r = 決め手の率 base − 適用された調整 adj(発動の年)、据え置きの年は r=0。""" import itertools, os from math import prod, log # 年度: (物価p, 賃金w, 決め手(新規), 決め手(既裁定), r新規, r既裁定) %。H28〜R8 のみ(H27 は起点の外) T = [("H28", 0.8, -0.2, "据", "据", 0.0, 0.0), ("H29", -0.1, -1.1, "物価", "物価", -0.1, -0.1), ("H30", 0.5, -0.4, "据", "据", 0.0, 0.0), ("R1", 1.0, 0.6, "賃金", "賃金", 0.1, 0.1), ("R2", 0.5, 0.3, "賃金", "賃金", 0.2, 0.2), ("R3", 0.0, -0.1, "賃金", "賃金", -0.1, -0.1), ("R4", -0.2, -0.4, "賃金", "賃金", -0.4, -0.4), ("R5", 2.5, 2.8, "賃金", "物価", 2.2, 1.9), ("R6", 3.2, 3.1, "賃金", "賃金", 2.7, 2.7), ("R7", 2.7, 2.3, "賃金", "賃金", 1.9, 1.9), ("R8", 3.2, 2.1, "賃金", "賃金", 1.9, 1.9)] out = []; P = out.append P("# #30 骨格★(計算検証役 2026-09-30)") P("## 1. H28〜R8 の11回の決め手の数(年表の「決め手」欄から数えた)") for lab, col in (("新規裁定者", 3), ("既裁定者", 4)): n = {k: [t[0] for t in T if t[col] == k] for k in ("賃金", "物価", "据")} P(f"- {lab}:賃金 {len(n['賃金'])}({'・'.join(n['賃金'])})/物価 {len(n['物価'])}({'・'.join(n['物価'])})/スライドなし(据え置き){len(n['据'])}({'・'.join(n['据'])})=計 {sum(len(v) for v in n.values())}") P("- 新規と既裁定で決め手が違うのは R5 だけ(新規=賃金・既裁定=物価)。まとめて書くと:賃金 7/物価 1/R5 は新規=賃金・既裁定=物価/据え置き 2。calc.py の12年度の数(賃金 8・物価 1・R5 1・据え置き 2)から H27(賃金)を外した数と一致") P("- 発動(調整が掛かった)年:R1・R2・R5・R6・R7・R8 の6回(H27 を含む12年度では7回)") def stage_rates(t, who): y, p, w, dn, de, rn, re_ = t; d = dn if who == 0 else de; r = rn if who == 0 else re_ base = w if d == "賃金" else p if d == "物価" else p # 据え置きの年は ① では動かさない r1 = base # ① 物価→決め手の率 r2 = r if d != "据" else base # ② 調整(発動の年 r=base−adj。調整なしの年は r=base で動かない) r3 = r # ③ 据え置きの年を 0 に return p, {"①": base, "②": (r if d != "据" else base), "③": (0.0 if d == "据" else None)}, r, d def path(who, on): rates = [] for t in T: y, p, w, dn, de, rn, re_ = t; d = dn if who == 0 else de; r = rn if who == 0 else re_ base = w if d == "賃金" else p x = p if d == "据": x = 0.0 if "③" in on else p else: adj = base - r # 適用された調整(発動でない年は0) x = (base if "①" in on else p) - (adj if "②" in on else 0.0) rates.append(x) return (prod(1 + x / 100 for x in rates) - 1) * 100 for who, lab in ((1, "既裁定者"), (0, "新規裁定者")): P(f"\n## 2. 差の分け方:{lab}(H28〜R8)") p_cum = path(who, set()); r_cum = path(who, {"①", "②", "③"}) P(f"物価の累積 {p_cum:.2f}% − 改定率の累積 {r_cum:.2f}% = {p_cum - r_cum:.2f}ポイント(表の丸めの範囲で calc.py と一致)") P("\n年ごとの分け(%ポイント。各年の 改定率 − 物価 = ① 決め手の率−物価 + ② −調整 + ③ 据え置きで0にした分):") P("| 年度 | 物価 | 決め手 | 決め手の率 | 適用された調整 | 改定率 | ①物価と使われた賃金の差 | ②調整 | ③据え置き | 合計 |"); P("|---|---|---|---|---|---|---|---|---|---|") for t in T: y, p, w, dn, de, rn, re_ = t; d = dn if who == 0 else de; r = rn if who == 0 else re_ if d == "据": a = b = 0.0; c = r - p; base = None; adj = None else: base = w if d == "賃金" else p; adj = base - r; a = base - p; b = -adj; c = 0.0 P(f"| {y} | {p:+.1f} | {d if d!='据' else 'スライドなし'} | {'' if base is None else f'{base:+.1f}'} | {'' if adj is None else f'{adj:.1f}'} | {r:+.1f} | {a:+.1f} | {b:+.1f} | {c:+.1f} | {a+b+c:+.1f} |") # 順番別(掛け算の順) res = {} for order in itertools.permutations(["①", "②", "③"]): on = set(); prev = p_cum; contrib = {} for k in order: on.add(k); cur = path(who, on); contrib[k] = prev - cur; prev = cur # 積み上げが下がった分(=差に足される分) res[order] = contrib P("\n積み上げの差(ポイント)を3つに分けた値。掛け算なので、どれを先に外すかで変わる(6通り):") P("| 順番 | ①物価と使われた賃金の差 | ②調整 | ③据え置き | 合計 |"); P("|---|---|---|---|---|") for o, c in res.items(): P(f"| {'→'.join(o)} | {c['①']:.2f} | {c['②']:.2f} | {c['③']:.2f} | {sum(c.values()):.2f} |") for k in ("①", "②", "③"): v = [c[k] for c in res.values()]; P(f"- {k}:最小 {min(v):.2f}〜最大 {max(v):.2f}(6通りの平均 {sum(v)/6:.2f})") # 対数での分け(順番によらない) L = {"①": 0.0, "②": 0.0, "③": 0.0} for t in T: y, p, w, dn, de, rn, re_ = t; d = dn if who == 0 else de; r = rn if who == 0 else re_ if d == "据": L["③"] += log((1 + r / 100) / (1 + p / 100)) else: base = w if d == "賃金" else p L["①"] += log((1 + base / 100) / (1 + p / 100)); L["②"] += log((1 + r / 100) / (1 + base / 100)) tot = sum(L.values()); gap = p_cum - r_cum P("\n順番によらない分け方(各年の 改定率÷物価 の対数を①②③に分けて足し、差 %.2f ポイントを対数の比で按分):" % gap) P("| ①物価と使われた賃金の差 | ②調整 | ③据え置き |"); P("|---|---|---|") P("| " + " | ".join(f"{gap * L[k] / tot:.2f}({L[k]/tot*100:.0f}%)" for k in ("①", "②", "③")) + " |") open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "out_骨格★_決め手の数と差の分け方_2026-09-30.md"), "w", encoding="utf-8").write("\n".join(out)) print("\n".join(out)) # ---- ★ 骨格改定1(#issuecomment-5911260282):賃金の積み上げ・賃金<物価の回数・厚生年金(報酬比例)の積み上げ ---- def cum(x): return (prod(1 + v / 100 for v in x) - 1) * 100 W = [t[2] for t in T]; Pp = [t[1] for t in T] out2 = ["# #30 骨格 改定1 ★(計算検証役 2026-09-30)入力=年表(decompose.py の T)", f"- 賃金の伸び(名目手取り賃金変動率)の積み上げ H28〜R8:{cum(W):.2f}%({prod(1+v/100 for v in W):.4f}倍)。単純合計 {sum(W):.1f}%。物価の積み上げ {cum(Pp):.2f}%", f"- 賃金 < 物価の回数:{sum(1 for t in T if t[2] < t[1])}/11(賃金 ≥ 物価:" + "・".join(f"{t[0]}(賃金{t[2]:+.1f}・物価{t[1]:+.1f})" for t in T if t[2] >= t[1]) + ")", " - 賃金 < 物価の年:" + "・".join(f"{t[0]}" for t in T if t[2] < t[1])] rn = [t[5] for t in T]; re_ = [t[6] for t in T] kn = [2.0 if t[0] == "R8" else t[5] for t in T]; ke = [2.0 if t[0] == "R8" else t[6] for t in T] out2 += ["", "## 厚生年金(報酬比例部分)の改定率の積み上げ H28〜R8(R8 だけ 2.0%、ほかの年は基礎年金と同じ率)", f"- 1956年4月1日以前に生まれた人(既裁定):{cum(ke):.2f}%(基礎年金の系列 {cum(re_):.2f}%、差 {cum(ke)-cum(re_):+.2f})", f"- それより後に生まれた人(新規):{cum(kn):.2f}%(基礎年金の系列 {cum(rn):.2f}%、差 {cum(kn)-cum(rn):+.2f})", f"- 物価の積み上げ {cum(Pp):.2f}%との差(報酬比例):既裁定 {cum(ke)-cum(Pp):+.2f}/新規 {cum(kn)-cum(Pp):+.2f} ポイント(基礎年金は {cum(re_)-cum(Pp):+.2f}/{cum(rn)-cum(Pp):+.2f})", "- 根拠:報道発表 R8 p1 に『厚生年金(報酬比例部分)が2.0%』(基礎年金は1.9%)。H28・R7 の報道発表は率を1つだけ載せる(R7 p1『1.9%の引上げ』)。**ほかの年(H29〜R6)の報道発表の文言で、厚年と基礎の率が同じかは、私は年表の値を使っており報道発表の本文までは見ていない**(検証官の年表が合格=改定率は年で1つ)"] open(os.path.join(os.path.dirname(os.path.abspath(__file__)), "out_骨格改定1★_賃金の積み上げ_2026-09-30.md"), "w", encoding="utf-8").write("\n".join(out2)) print("\n".join(out2))