資金繰り予測をPythonで自動化する|コードと設計の考え方

資金繰り予測をPythonで自動化する|コードと設計の考え方 経理・数字の自動化

「来月の支払いは足りるのか」を、月に何度も電卓で確かめていました。

私は清掃業の会社を経営しています。売上は取れているのに、入金と支払いの時期がずれるせいで、月によって手元が薄くなる。この確認が毎回面倒でした。

これをPythonで自動化しています。コードを載せますが、いちばん重要なのはコードではなく、設計の考え方です。

前提の数字は、1つのファイルに集めてください。
これを守るかどうかで、資金繰り表が「使えるもの」になるか「信用できないもの」になるかが決まります。

※以下の数値はすべて、説明用の架空のものです。


資金繰り表の中身は、意外と単純

やっていることは、この繰り返しだけです。

今月末の残高 = 前月末の残高 + 今月の入金 - 今月の出金

難しいのは計算ではありません。「今月の入金」と「今月の出金」をどう置くかです。

ここに現実がぶつかってきます。

  • 売上が立つ月と、入金される月が違う(回収サイト)
  • 支払いも、発生した月と払う月が違う
  • 毎月同じ額のもの(家賃・保険)と、売上に連動するもの(人件費・外注費)が混ざる
  • 年に数回だけ大きく出るもの(税金・賞与)がある

この4つを表現できれば、資金繰り表は作れます。


設計:前提を1ファイルに集める

最初に作ったとき、私は前提の数字をあちこちに書いてしまいました。

入金サイトを計算のところに直接書き、固定費を別のファイルにも書き、グラフを出すファイルにも同じ数字を書く。

結果、家賃が変わったときに直し漏れが出て、資金繰り表と実績が合わなくなりました。 そうなると、その表はもう誰も信用しません。

今はこうしています。

zaimu/
├── 前提.py              ← 数字はここにしか書かない
├── 資金繰り表.py         ← 前提.py を読んで計算する
└── グラフ.py            ← 前提.py を読んで描く

同じ数字が2か所に書いてあったら、それは必ずいつかずれます。
プログラムの良し悪しではなく、運用が破綻するかどうかの問題です。


前提.py

数字を置くだけのファイルです。計算は一切書きません。

# -*- coding: utf-8 -*-
"""資金繰りの前提。数字を変えるときはここだけ触る。"""

# 期首(開始時点)の現金残高
KISHU_GENKIN = 8_000_000

# 月ごとの売上見込み(税抜・12ヶ月分)
URIAGE = [
    12_000_000, 11_500_000, 13_000_000, 12_500_000,
    12_000_000, 12_800_000, 13_500_000, 12_000_000,
    11_800_000, 12_200_000, 13_000_000, 14_000_000,
]

# 入金は「売上の何ヶ月後か」
NYUKIN_OKURE = 1          # 翌月末入金なら 1

# 売上に連動する費用(売上に対する割合)
JINKENHI_RITSU = 0.55     # 人件費
GAICHU_RITSU   = 0.08     # 外注費

# 毎月固定でかかる費用
KOTEIHI = {
    "家賃":      620_000,
    "保険料":    340_000,
    "リース":    150_000,
    "通信費":     90_000,
}

# 年に数回だけ出るもの {月: 金額}
SUPOTTO = {
    3: 2_000_000,   # 決算関連
    7: 1_500_000,   # 賞与
    12: 1_500_000,  # 賞与
}

この形にしておくと、数字を変えたい人がプログラムを読めなくても直せます。 実際、私は毎月ここだけを触っています。


資金繰り表.py

前提を読んで、12ヶ月分を並べるだけです。

# -*- coding: utf-8 -*-
import 前提 as z

def keisan():
    zandaka = z.KISHU_GENKIN
    kekka = []

    for tsuki in range(1, 13):
        i = tsuki - 1

        # 入金:NYUKIN_OKURE ヶ月前の売上が入ってくる
        moto = i - z.NYUKIN_OKURE
        nyukin = z.URIAGE[moto] if moto >= 0 else 0

        # 出金:当月の売上に連動する費用 + 固定費 + スポット
        uriage = z.URIAGE[i]
        shukkin = (
            uriage * z.JINKENHI_RITSU
            + uriage * z.GAICHU_RITSU
            + sum(z.KOTEIHI.values())
            + z.SUPOTTO.get(tsuki, 0)
        )

        zandaka += nyukin - shukkin
        kekka.append({
            "月": tsuki,
            "入金": nyukin,
            "出金": shukkin,
            "収支": nyukin - shukkin,
            "残高": zandaka,
        })
    return kekka


def hyoji(kekka):
    print(f"{'月':>3} {'入金':>12} {'出金':>12} {'収支':>12} {'残高':>13}")
    print("-" * 58)
    for r in kekka:
        shirushi = "  ← 注意" if r["残高"] < 0 else ""
        print(f"{r['月']:>2}月 {r['入金']:>12,.0f} {r['出金']:>12,.0f} "
              f"{r['収支']:>12,.0f} {r['残高']:>13,.0f}{shirushi}")

    soko = min(kekka, key=lambda r: r["残高"])
    print("-" * 58)
    print(f"最も薄くなるのは {soko['月']}月:残高 {soko['残高']:,.0f}円")


if __name__ == "__main__":
    hyoji(keisan())

出てくる表

  月           入金           出金           収支            残高
----------------------------------------------------------
 1月            0     8,760,000   -8,760,000      -760,000  ← 注意
 2月   12,000,000     8,445,000    3,555,000     2,795,000
 3月   11,500,000    11,390,000      110,000     2,905,000
 4月   13,000,000     9,075,000    3,925,000     6,830,000
 ...
12月   13,000,000    11,520,000    1,480,000    30,211,000
----------------------------------------------------------
最も薄くなるのは 1月:残高 -760,000円

見るべきは12月末の残高ではなく、「いちばん薄くなる月」です。

この例では、1年を通せば3,000万円まで積み上がります。それでも1月に一度、残高がマイナスになります。 前月の売上が入金される前に、その月の支払いが先に出ていくためです。

年間で黒字でも、途中で現金が尽きればそこで止まります。 期末の数字だけを見ていると、この谷が見えません。


作ってみて分かったこと

① 精度より、前提を動かせることが重要

資金繰り表に完璧な精度は求めていません。「入金が1ヶ月遅れたらどうなるか」を10秒で試せることのほうが役に立ちます。

NYUKIN_OKURE = 2 に変えて実行し直すだけで、答えが出ます。これは電卓ではできません。

② 完了した月で検算する

作った直後にやるべきことがあります。すでに終わった月の数字を入れて、予測が実績と合うか確かめてください。

合わなければ、前提のどれかが間違っています。この検算をせずに未来の予測だけ見るのは危険です。

⚠️ 私はこれを一度怠りました。もっともらしい表が出ていたのに、ある拠点だけ前提が実態と違っており、その拠点の数字が丸ごとおかしくなっていました。

③ 悪いほうに寄せて置く

入金は遅めに、支出は多めに置いています。資金繰りは外したときの被害が非対称だからです。多めに見て残るのは困りませんが、少なく見て足りないのは事故になります。


この方法が向かないケース

状況 判断
取引先ごとに回収条件がバラバラ 1つの割合では表せない。会計ソフトの資金繰り機能を使う
金融機関に提出する資料が必要 税理士に相談すべき。自作の表は社内判断用と割り切る
仕訳データから自動で作りたい 会計ソフトの範囲。自作でつなぐ手間に見合わない

私が自作しているのは、会計ソフトが出してくれない「自社の見方」の部分だけです。

この線引きは 経理はスプレッドシート自作と会計ソフト、どちらがいいか に書いています。


まとめ

  • 資金繰り表の計算式は「前月残高+入金-出金」だけ。難しいのは前提の置き方
  • 前提の数字は1ファイルに集める。2か所に書いた数字は必ずずれる
  • 見るべきは期末残高ではなく「いちばん薄くなる月」
  • 完了した月で検算する。予測が実績と合わないなら前提が間違っている
  • 入金は遅めに、支出は多めに悪いほうへ寄せて置く
  • 金融機関提出用は自作しない。社内判断用と割り切る

電卓でやっていた頃と比べていちばん変わったのは、精度ではありません。「条件を変えて試せるようになったこと」でした。

コメント

タイトルとURLをコピーしました