外貨建ての売上の請求と回収の実績から、通貨別・月別の外貨の入金額を幅で見込み、為替予約の量の案を財務担当に示す
外貨建ての請求と回収の実績から、まだ入金されていない請求ごとに、どの月に入金されるかの確率を見込みます。それを通貨別・月別に積み上げて入金額の幅を出し、社内規程の割合に照らした為替予約の追加量の案を財務担当に示します。
- 連携・自動化
- Python
- 対象業界
- IT・SaaS/商社/製造
- 対象部門
- 財務
- 対象業務
- 集計・分析
- 主な課題
- データ分析に時間がかかる/判断に時間がかかる/属人化している
- AIで行う処理
- 予測
- 主な効果
- 判断支援/属人化解消/工数削減
- 導入難易度
- ★★★★☆
- 実装レベル
- 本格構成
- 費用感
- 個別開発(大)
- 人間の確認
- 条件付き
01導入前 / 導入後の業務フロー
- 月次の締めのあと、販売管理システムから外貨建ての未入金の請求の一覧を出す
- 取引先ごとに、未入金の請求と支払の期日、過去の入金の遅れ方を確かめる
- 請求ごとに、入金されそうな月を置く。遅れそうな取引先は営業に様子を聞く
- 通貨別・月別に入金の見込みを積み上げる
- 為替予約の台帳から、通貨別・月別の予約の残高を出す
- 見込みに社内規程の割合を掛け、予約の残高との差から追加の量を出す
- 会議の資料にまとめ、財務部長に説明する
- 自動月次の締めの翌営業日の朝に、販売管理システムから請求と入金の記録、為替予約の台帳を取り込む
- 自動未入金の請求ごとに、入金が「期日の月」「翌月」「翌々月」「それ以降」のどれになるかの確率を出す
- 自動請求ごとの確率から、通貨別・月別の入金額の分布を作り、下側・中央・上側の額を出す
- 自動社内規程の割合を下側の額に当て、予約の残高との差から、追加の量の案を出す
- 自動見込みが割れている大口の請求と、過去の実績が足りない取引先を「要確認」として一覧にする
- 人財務の担当が「要確認」の取引先について、営業に入金の予定を確かめ、見込みを上書きする
- 人担当が追加の量の案と根拠を確かめ、会議の資料にする
- 人会議で、予約を結ぶ量と時期を決める
各工程の詳しい説明を読む
- 月次の締めのあと、販売管理システムから外貨建ての未入金の請求の一覧を出す
- 取引先ごとに、未入金の請求と支払の期日、過去の入金の遅れ方を確かめる
- 請求ごとに、入金されそうな月を置く。遅れそうな取引先は営業に様子を聞く
- 通貨別・月別に入金の見込みを積み上げる
- 為替予約の台帳から、通貨別・月別の予約の残高を出す
- 見込みに社内規程の割合を掛け、予約の残高との差から追加の量を出す
- 会議の資料にまとめ、財務部長に説明する
(a)入金の月の読みが人によって違う。 同じ取引先でも、ある担当者は「期日の翌月」と置き、別の担当者は「期日の月」と置きます。どちらの読みが当たってきたかは、記録に残っていません。 外れても、なぜ外れたかを振り返る材料がありません。
(b)見込みが1点の数字で、外れる幅が分からない。 見込みの表には「来月の米ドルの入金 120万」とだけ書かれ、それがどれくらい下振れしうるかは書かれていません。 規程の割合を掛けるのも、この1点の数字です。入金が遅れた月に、予約の受け渡しの外貨が足りず、急いで外貨を買い戻したことがあります。
(c)300社の積み上げに時間がかかる。 1社6分でも月30時間で、締めから会議までの4営業日に詰め込まれます。取引先が多い月ほど、遅れそうな取引先を見る時間が削られます。
(d)既に遅れている請求の扱いがばらばら。 期日を過ぎた請求を「来月入る」と置くか、見込みから外すかが、担当者によって違います。期日を過ぎた請求は、入る月の見込みがいちばん揺れるところです。
- 【自動】 月次の締めの翌営業日の朝に、販売管理システムから請求と入金の記録、為替予約の台帳を取り込む
- 【自動】 未入金の請求ごとに、入金が「期日の月」「翌月」「翌々月」「それ以降」のどれになるかの確率を出す
- 【自動】 請求ごとの確率から、通貨別・月別の入金額の分布を作り、下側・中央・上側の額を出す
- 【自動】 社内規程の割合を下側の額に当て、予約の残高との差から、追加の量の案を出す
- 【自動】 見込みが割れている大口の請求と、過去の実績が足りない取引先を「要確認」として一覧にする
- 【人】 財務の担当が「要確認」の取引先について、営業に入金の予定を確かめ、見込みを上書きする
- 【人】 担当が追加の量の案と根拠を確かめ、会議の資料にする
- 【人】 会議で、予約を結ぶ量と時期を決める
6番目で人が見るのは、300社のうち一部です。 確率が1つの月に集まっている取引先は、見込みをそのまま使います。時間を使うのは、確率が2つ以上の月に割れていて金額の大きい請求と、取引を始めたばかりの取引先です。
4番目の案は、規程の割合をそのまま当てた機械の計算です。 相場の見方、予約の時期、銀行ごとの枠は入っていません。案を出すのは「規程の内側にいるかを毎月同じ方法で確かめる」ためで、結ぶ量を決めるためではありません。
02今回想定するシステム構成
販売管理システム(外貨建ての請求・入金の消込)/為替予約の台帳/取引先マスタ │ CSV の出力(読み取りのみ) ▼【トリガー】月次の締めの翌営業日の朝 Python(pandas・scikit-learn) ├──▶ 請求と入金を結び付け、遅れの区分を作る(学習用) ├──▶ HistGradientBoostingClassifier で、請求ごとの入金の月の確率を出す ├──▶ 取引先ごとにまとめて揺らすシミュレーションで、通貨別・月別の分布を作る ├──▶ 下側(P10)・中央(P50)・上側(P90)の額を出す └──▶ 規程の割合と予約の残高から、追加の量の案を出す ▼ 見込みの表(通貨別・月別)と要確認の一覧(共有フォルダ) ▼ 【人が要確認の取引先を確かめ、会議で予約の量を決める】
| 役割 | 想定する製品 | 代替候補 |
|---|---|---|
| 実行環境 | Python(pandas・scikit-learn の HistGradientBoostingClassifier と確率の較正の確認) | R、BigQuery ML |
| データの取得元 | 販売管理システムの CSV の出力、為替予約の台帳 | 販売管理システムのデータベースの読み取り専用の口 |
| 結果の出力先 | 財務部の共有フォルダの見込みの表 | 社内の BI の画面 |
| 定時実行 | OS のタスクスケジューラ | クラウドの定時実行 |
新しく入れるものは、Python の処理だけです。 販売管理システムにも為替予約の台帳にも書き込みません。最初の準備は、入金の記録をどの請求に充てたかが分かる形で出せるかを確かめることです。 消込が請求と結び付いていないと、遅れを数えられません。
入金の月の確率は、scikit-learn の HistGradientBoostingClassifier で出します。 公式の説明では、この推定器は欠損値(NaN)をそのまま扱え、学習のときに欠損のある行を分岐の左右どちらに送るかを学ぶとされています。取引を始めたばかりで「過去の遅れの中央値」が無い取引先も、そのまま入れられます。
カテゴリの特徴量も扱えます。 categorical_features の既定は 'from_dtype' で、データの型からカテゴリの列を決めるとされています。通貨、決済の条件、国は、カテゴリの型にしておきます。predict_proba で、請求ごとに区分それぞれの確率が返ります。
学習と評価は、時間の順に分けます。 公式の説明では、TimeSeriesSplit は時間の順のデータを分けるためのもので、ほかの分け方は未来のデータで学習して過去を評価することになるとされています。入金の遅れ方は年によって変わるので、この分け方にします。gap の引数で、学習の終わりと評価の始まりのあいだに空きを置けます。入金の区分が決まるまで数か月かかるので、空きを置いて、評価の月の答えが学習に漏れないようにします。
なぜ請求ごとに見込み、取引先ごとや通貨ごとの合計を直接見込まないのか。 通貨別・月別の合計を時系列として見込むと、来月の売掛金の中身(どの取引先の、期日がいつの請求か)が反映されません。今月の残高に遅れがちな取引先の大口の請求が入っていれば、来月の入金は下がるはずです。 請求ごとに見込んで積み上げれば、この中身の違いがそのまま見込みに出ます。担当者がいまやっている「取引先ごとに請求を見て月を置く」作業を、そのまま数に置き換えた形です。
03どうやって実装するのか
処理の起点を決める
月次の締めの翌営業日の朝6時に、タスクスケジューラで動かします。 会議は第5営業日なので、担当者が要確認の取引先を確かめる時間を3営業日残すためです。締めの前の残高で動かすと、月末に入った入金が消し込まれておらず、入った請求を「未入金」として見込むことになります。
消込の終わりを確かめてから動かします。 販売管理システムの CSV に、締めの処理を終えた日時の列があれば、それが前月末より後かを見ます。終わっていなければ処理を止め、担当者に通知します。 1日遅れても、半端な残高で見込むよりよいからです。
月の途中でも、担当者が手で動かせるようにします。 大口の入金が月の半ばに入ったときや、取引先の支払の延期の連絡があったときに、会議の前に見込みを出し直すためです。 手で動かしたときも、同じ記録を残します。
入力データを集める
| データ | 中身 | 取得元 |
|---|---|---|
| 外貨建ての請求 | 請求番号、取引先、通貨、金額、請求日、支払の期日、決済の条件 | 販売管理システムの CSV |
| 入金の記録 | 入金日、入金額、充てた請求番号、銀行の手数料の差し引き | 販売管理システムの消込の CSV |
| 取引先マスタ | 取引先コード、国、支払の条件、与信の区分、取引の開始日 | 販売管理システムの CSV |
| 為替予約の台帳 | 通貨、売りの予約、受渡の月、残高 | 為替予約の台帳 |
| 社内規程の割合 | 何か月先かごとの、見込みに対する予約の上限の割合 | 財務部が持つ設定の表 |
| 人の上書き | 担当者が営業に確かめて置き直した入金の月 | 財務部の上書きの表 |
質を決めるのは、入金の記録が請求に充てられているかです。 1回の送金で複数の請求をまとめて払う取引先は多く、どの請求に充てたかが消込に残っていれば、請求ごとの遅れが数えられます。 残っていなければ、その取引先は取引先単位でしか遅れを数えられません。
一部入金は、充てた額ごとに分けて扱います。 請求額の8割だけ入金され、残りが翌月に入る取引先があります。請求を「入金済み」か「未入金」かの2つで扱うと、残りの2割の遅れが消えます。
人の上書きの表も入力です。 前の月に担当者が営業に確かめて置き直した入金の月は、その請求が入金されるまで、モデルの見込みより優先します。
データの取得方法を決める
| 取るもの | どこから | 何に使うか |
|---|---|---|
| 過去2年分の請求と入金 | 販売管理システムの CSV | 学習用の遅れの区分を作る |
| 前月末の未入金の請求 | 同上 | 見込みの対象 |
| 取引先マスタ | 同上 | 国、条件、取引の開始日の特徴量 |
| 予約の残高 | 為替予約の台帳 | 追加の量の案の計算 |
| 規程の割合と上書き | 財務部の設定の表 | 案の計算と、見込みの置き換え |
販売管理システムからは CSV の出力だけを使います。 データベースに直接つなぐ口があれば読み取り専用で使えますが、まずは画面からの出力で始め、出力の列の並びを固定します。 列の並びが変わったら処理を止めます。
学習用のデータは、入金が済んだ請求だけから作ります。 まだ入金されていない請求を学習に入れると、遅れの区分が決まっていないので、「遅れている請求」が「それ以降」として数えられず、遅れが少なく見えます。 ただし直近の数か月は、期日から日が浅い請求ほど入金済みが多いという偏りがあるので、学習に使うのは、期日から4か月以上たった請求までにします。
AIへ渡す前に整形する
- 請求と入金の結び付け … 消込の記録で、入金を請求ごとに充てます。一部入金は充てた額ごとの行にします
- 遅れの区分の作成 … 入金日の月が、支払の期日の月から見て「同じ月」「翌月」「翌々月」「それ以降」のどれかを付けます
- 除くものの印 … 前受金、相殺、貸倒れの処理をした請求、取引先との係争中の請求に印を付け、学習と見込みから外します
- 取引先の履歴の特徴量 … 取引先ごとの直近12件の遅れの日数の中央値、期日どおりの割合、最後の入金からの日数を、見込む時点より前の記録だけで作ります
- 請求の特徴量 … 通貨、金額(対数)、決済の条件、請求から期日までの日数、期日の月、期日を過ぎた日数を作ります
- 為替予約の台帳の整理 … 通貨別・受渡の月別に、売りの予約の残高を集計します
4番目の「見込む時点より前の記録だけで」を守らないと、評価がよく見えすぎます。 学習のときに、その請求より後の入金の記録から「取引先の遅れの中央値」を作ると、答えの一部を特徴量に入れたことになります。 本番では未来の記録は無いので、評価の成績どおりには当たりません。
3番目の係争中の請求は、見込みの表の外に別の一覧で出します。 品質の不具合で支払を止められている請求は、払われる月の見込みが立ちません。見込みに入れると、入らない外貨に予約を当てることになります。
AIに処理させる
させるのは、未入金の請求ごとに、どの月に入金されるかの確率を出すことです。 通貨別・月別の積み上げと、予約の量の案は、その確率から決まった手順で計算します。
| 見込むもの | 出し方 | 判断できないときの扱い |
|---|---|---|
| 請求ごとの入金の月の確率 | 4区分(同じ月・翌月・翌々月・それ以降)の predict_proba | 取引先の履歴が3件未満なら low_history の印 |
| 通貨別・月別の入金額の分布 | 確率から1万回のシミュレーション | 係争中の請求は外して別の一覧 |
| 下側・中央・上側の額 | 分布の10%点・50%点・90%点 | - |
| 予約の追加量の案 | 下側の額 × 規程の割合 - 予約の残高 | 0未満なら0とし、「予約が規程の上限を超えている」と印 |
シミュレーションは、取引先ごとにまとめて揺らします。 同じ取引先の請求は、遅れるときは一緒に遅れます。請求ごとにばらばらに揺らすと、遅れが打ち消し合って幅が狭く出ます。 そこで1回の試行ごとに、取引先ごとに1つの乱数を引き、その取引先のすべての請求の区分を同じ乱数で決めます。
予約の量の案に下側の額を使うのは、第1章で書いた理由です。 中央の額に割合を掛けると、入金が遅れた月に、受け渡す外貨が足りなくなる確率が高くなります。 どの点を使うかは規程で決めることなので、設定の表で10%点から変えられるようにしておきます。
| させないこと | 理由 |
|---|---|
| 為替の相場の予想 | 見込むのは外貨の入金の量だけで、円に直した額は扱わない |
| 予約を結ぶかの判断 | 相場の見方と銀行の枠を含めて会議が決める |
| 係争中の請求の入金の月 | 交渉の結果しだいで、過去の実績から見込めない |
| 人の上書きの書き換え | 営業に確かめた入金の月は、入金されるまで優先する |
| 規程の割合を超える案 | 上限を超える量は案として出さない |
1行目を入れていないことを、資料にも明記します。 見込みの表を見た人が、円に直した額や、相場の見通しが入っていると思わないようにです。この構成が見込むのは「何月に何ドル入るか」だけです。
指示内容を固定する
この構成は生成AIに指示を出しません。 モデルへの指示にあたるのは、Python の処理の設定と、学習と評価の手順です。
【学習のデータ】
- 対象:外貨建ての請求のうち、入金が済み、支払の期日から4か月以上たったもの
- 除く:前受金、相殺、貸倒れの処理、係争中の印があるもの
- 目的の変数:遅れの区分(0=期日の月、1=翌月、2=翌々月、3=それ以降)
- 期間:直近24か月
【特徴量】(見込む時点より前の記録だけで作る)
- 取引先の直近12件の遅れの日数の中央値(履歴が無ければ NaN)
- 取引先の期日どおりの割合(履歴が無ければ NaN)
- 最後の入金からの日数
- 通貨(カテゴリ)、決済の条件(カテゴリ)、国(カテゴリ)
- 金額(対数)、請求から期日までの日数、期日の月、期日を過ぎた日数
【モデル】
- HistGradientBoostingClassifier
categorical_features="from_dtype"
early_stopping="auto"
- 評価:TimeSeriesSplit(n_splits=5, gap=1)。請求の期日の月の順に並べて分ける
【確率の確かめ方】
- 区分ごとに、出した確率と実際にその区分になった割合を10の階級で比べる
- 確率が0.7前後の請求のうち、実際にその区分になったのが7割前後かを見る
- ずれが大きければ、CalibratedClassifierCV(method="sigmoid")で較正する
【見込みの出力】
- 未入金の請求ごとに4区分の確率
- 取引先ごとに同じ乱数で区分を決める1万回のシミュレーション
- 通貨別・月別の10%点・50%点・90%点
- 過去6か月の見込みで、実際の入金額が10%点と90%点のあいだに入った割合
「確率の確かめ方」を入れておかないと、確率の数字が独り歩きします。 公式の説明では、較正された分類器とは、predict_proba の値をそのまま確からしさとして読めるもので、0.8前後と出した標本のおよそ8割が実際にその区分になる状態とされています。シミュレーションは確率をそのまま使うので、確率がずれていれば、幅もずれます。
較正の方法は、まず sigmoid にします。 公式の説明では、isotonic はデータが十分にある(およそ1,000件を超える)ときには sigmoid と同じかよい成績になる一方、少ないデータでは過学習しやすいとされています。通貨によっては請求の件数が少ないので、sigmoid から始めます。
最後の行が、見込みの幅を信じてよいかの目安です。 10%点から90%点のあいだには、本来8割の月が入るはずです。過去6か月で半分しか入っていなければ、幅が狭すぎます。 取引先ごとにまとめて揺らす処理が効いていないことが多い理由です。
出力形式を固定する
見込みの表は、通貨別・月別の行で出します。
| 通貨 | 入金の月 | 下側(P10) | 中央(P50) | 上側(P90) | 予約の残高 | 規程の割合 | 追加の量の案 | 係争中の額(別枠) |
|---|---|---|---|---|---|---|---|---|
| USD | 翌月 | (額) | (額) | (額) | (額) | (割合) | (額) | (額) |
要確認の一覧は、取引先ごとの行で出します。
{
"run_id": "",
"as_of": "YYYY-MM-DD",
"customer_code": "",
"currency": "",
"open_amount": 0,
"invoices": [
{ "invoice_no": "", "due_date": "", "amount": 0,
"proba": { "due_month": 0.0, "plus1": 0.0, "plus2": 0.0, "later": 0.0 },
"flags": ["split_probability", "low_history", "overdue"] }
],
"history_summary": { "median_delay_days": 0, "on_time_ratio": 0.0, "n_history": 0 },
"override": { "month": "", "by": "", "note": "" }
}
1つ目の理由は、確率と人の上書きを別の項目に置けることです。 proba はモデルが埋め、override は担当者が営業に確かめて書きます。上書きがあればそちらを使い、無ければ確率を使う、という規則が処理の側で決まります。
2つ目は、flags で要確認の理由が分かることです。 split_probability は、いちばん高い区分の確率が0.5未満で金額が上位の請求、low_history は履歴が3件未満の取引先、overdue は期日を過ぎた請求です。担当者は理由ごとに、営業に何を聞けばよいかが分かります。
3つ目は、history_summary で根拠を説明できることです。 会議で「なぜこの取引先は翌月に置いたのか」と聞かれたときに、過去の遅れの中央値と期日どおりの割合で答えられます。
システムへ連携する
| つなぎ先 | 方式 | 内容 |
|---|---|---|
| 販売管理システム | CSV の出力(読み取りのみ) | 請求、入金の消込、取引先マスタ |
| 為替予約の台帳 | ファイルの読み取り | 通貨別・受渡の月別の予約の残高 |
| 財務部の設定の表 | ファイルの読み取り | 規程の割合、下側に使う点、上書き |
| 共有フォルダ | ファイルの書き出し | 見込みの表、要確認の一覧、評価の結果 |
| 社内チャット | 通知 | 処理の完了と、要確認の件数 |
どのシステムにも書き込みません。 見込みの表は共有フォルダに置くだけで、為替予約の台帳には、会議で決めて実際に結んだ予約だけが、従来の手順で入ります。 案が台帳に紛れ込む経路を作りません。
規程の割合は、コードに書かずに設定の表に置きます。 規程が改まったときに、財務部の手で直せるようにするためです。設定の表を誰がいつ変えたかは、ファイルの版の履歴で残します。
人が確認する
人が確かめるのは、要確認の一覧と、追加の量の案の根拠です。 要確認でない取引先は、見込みの表の数字として使います。
split_probabilityの大口の請求を先に見る … 入金の月が割れていて、額が大きいもの。営業に入金の予定を確かめ、overrideに書きますoverdueの請求を見る … 期日を過ぎたもの。遅れの理由が係争なら、係争中の印を付けて見込みから外しますlow_historyの取引先を見る … 取引を始めたばかりの取引先。契約の条件と、初回の入金の様子を営業に確かめます- 追加の量の案を確かめる … 下側の額、規程の割合、予約の残高を並べ、計算の筋を確かめます
- 会議で決める … 相場の見方と銀行の枠を含めて、結ぶ量と時期を決めます
2番目を省かないでください。 期日を過ぎた請求は、モデルが「翌月」に高い確率を付けることがありますが、遅れの理由が品質の不具合なら、翌月に入る見込みはありません。 理由はモデルの外にあります。
目標は、300社をならして1社2分です。 要確認に回るのは3割前後という想定で、それより多い月は、消込の遅れか、新しい取引先の増加が起きています。
例外に対処する
| 起きること | 対応 |
|---|---|
| 締めの処理が終わっていない | 処理を止めて担当者に通知する。半端な残高で見込まない |
| CSV の列の並びが変わった | 処理を止める。販売管理システムの改修の有無を確かめる |
| 入金が請求に充てられていない | その取引先は取引先単位の遅れで見込み、low_history を付ける |
| 取引を始めたばかりの取引先 | 履歴の特徴量を NaN のまま入れ、low_history を付けて要確認へ |
| 係争中の請求 | 見込みから外し、別の一覧に額を出す |
| 一部入金の残りがある | 残りの額を1つの未入金の請求として見込む |
| 新しい通貨の請求が出た | 学習のデータに無い通貨は見込まず、担当者に回す |
| 予約の残高が下側の額 × 割合を超える | 追加の量の案を0とし、「上限を超えている」と印を付ける |
| 過去6か月の幅に入った割合が5割を下回る | 見込みの表に注意書きを付け、モデルの見直しを担当に通知する |
下から2行目は、会議でいちばん大事な行になることがあります。 入金が遅れて見込みが下がると、すでに結んだ予約が規程の上限を超える月が出ます。 案が0というだけでなく、超えていることを示すのは、その手当てを会議で話すためです。
記録を残す
- 処理を動かした日時、使った CSV のファイルと行数
- 学習に使った期間、特徴量の一覧、モデルの版と設定
- 評価の結果(区分ごとの確率と実際の割合、幅に入った割合)
- 請求ごとの確率、通貨別・月別の分布の点、追加の量の案
- そのときの規程の割合と予約の残高
- 人の上書きの記録 … どの請求を、どの月に、誰が、何を根拠に置き直したか
- 会議で決めた予約の量と、案との差
5つ目で「そのときの規程の割合と予約の残高」を残すのは、後から案を検算できるようにするためです。 規程が改まったり予約を結んだりすると、同じ見込みからでも案が変わります。
最後の行は、モデルの見直しの材料になります。 案と決めた量の差が毎月同じ方向にずれていれば、会議が見込みを信じていない理由が、どこかにあります。
04実装レベルの3段階
最小構成では幅が出ません。 1点の見込みしか出ないので、第3章の(b)は解けません。確かめるための段階です。 半自動化で、1社6分が3分程度になります。 遅れの確認と積み上げは自動になりますが、どの取引先を確かめるかの選び出しと、予約の量の計算が残ります。本格構成で2分になり、この段階が本記事の想定です。 差が大きいのは、要確認の取引先が理由付きで絞られ、担当者が300社を自分で見て回らなくてよくなるからです。 段階を飛ばさないでください。 半自動化を3か月回すと、確率と実際の割合のずれが分かります。確率がずれたまま幅のシミュレーションに進むと、もっともらしい幅が出るだけで、当たりません。
05工数削減シミュレーション
導入後 300件 × 2分 ÷ 60 = 10 時間/月
自社条件で導入効果を整理したい方へ
このユースケースを自社に当てはめた場合の前提値と削減見込みを、業務ヒアリングをもとに整理します。
06向いている企業・向いていない企業
- 輸出の売上が米ドル・ユーロなど複数の通貨で立ち、取引先が数百社ある商社・メーカー・海外向けのソフトウェアの販売会社。毎月の為替予約の会議の前に、財務の担当が取引先ごとの入金の月を経験で読み、通貨別・月別の入金の見込みを表計算で積み上げている場合。販売管理システムに外貨建ての請求と入金の記録が2年分ほど残っている場合。社内規程で、入金の見込みに対して予約してよい割合が決まっている場合。
- 外貨建ての取引先が十数社で、入金の月を担当者が見てすぐ答えられる場合。ほとんどの取引が前払いか一覧払いの信用状で、入金の月がほぼ揺れない場合。入金の記録が請求と結び付いておらず、どの請求の入金かが分からない場合(消込の整備が先)。なお、為替予約を結ぶか、いくら結ぶか、ヘッジ会計をどう適用するかの判断は、この構成では代替できません。
07最小構成で試す方法
- 販売管理システムから、過去2年分の外貨建ての請求と入金の消込を CSV で出す
- 取引先ごとに、入金日と期日の差(遅れの日数)の中央値と、期日どおりの割合を表計算で出す
- 半年前の月末の時点の未入金の請求について、その中央値で入金の月を置き、通貨別・月別に積み上げる
- 当時の担当者の見込みの表と、実際の入金額を並べる
- 遅れの中央値で置いた見込みと、担当者の見込みの、どちらが実際に近かったかを月ごとに見る
機械学習のモデルを組む前に、「過去の遅れ方で、入金の月がどれだけ読めるか」を確かめます。 中央値で置くだけでも、担当者の見込みと同じくらい当たるなら、その先のモデルに意味があります。
| 出てきた内容 | 判断 |
|---|---|
| 中央値の見込みが担当者と同じくらい当たる | モデルと幅のシミュレーションに進む |
| 大口の数社だけ大きく外れる | その数社は人の上書きで扱う。構成は有効 |
| 入金が請求に充てられておらず、遅れが数えられない | 消込の整備が先。 モデルの問題ではない |
3行目が出ることは珍しくありません。 失敗ではなく、担当者が経験で読むしかなかった理由が1つ分かったということです。 まとめて払う取引先の消込のしかたを経理と相談してから、もう一度試してください。
08実装時につまずきやすいポイント
| 問題 | 対策 |
|---|---|
| 評価が良いのに本番で外れる | 見込む時点より後の記録を特徴量に入れていないか確かめる |
| 遅れが少なく見える | 未入金の請求と、期日から日が浅い請求を学習から外す |
| 幅が狭すぎる | 取引先ごとに同じ乱数で揺らす。請求ごとにばらばらに揺らさない |
| 確率が実際の割合とずれる | 区分ごとに10の階級で比べ、ずれれば sigmoid で較正する |
| 一部入金の残りが消える | 充てた額ごとの行にし、残りを未入金として見込む |
| 係争中の請求に予約を当てる | 係争中の印を付けて見込みから外し、別の一覧に出す |
| 新しい取引先の見込みが極端になる | 履歴を NaN で入れ、low_history で要確認へ |
| 中央の額で予約の量を考えてしまう | 案は下側の額で計算し、資料に点を明記する |
| 円に直した額が入っていると誤解される | 見込みは外貨の量だけと資料に明記する |
| 規程の割合がコードに埋め込まれる | 設定の表に置き、財務部が直せるようにする |
| 案がそのまま予約になる | 台帳には会議で決めて結んだ予約だけを入れる |
上の3行が、この構成の失敗のほとんどです。 どれも「もっともらしい数字が出るが当たらない」という同じ見た目をしています。評価の手順と、過去6か月で幅に入った割合の確認を、毎月の処理から外さないでください。
下の2行も、同じくらい早く効いてきます。 規程の割合を変えるたびに開発者を呼ぶ形にすると、規程と処理がずれたまま回ります。案が台帳に紛れ込むと、結んでいない予約が残高に見えます。
09セキュリティ・AIガバナンス上の注意点
この構成で扱うデータ: 取引先ごとの売上と売掛金、入金の遅れ方、与信の区分、為替予約の残高です。取引先の資金繰りの様子と、自社の為替の持ち高が推し量れる情報です。
- データを社外に出さない … 処理は社内の Python で完結させます。外部のAIサービスにデータを渡す構成にはしません
- 出力の閲覧を財務部に限る … 取引先ごとの遅れ方は、営業部門に見せると取引先への見方を変える材料になります。 要確認の一覧で営業に聞くときも、聞く取引先の分だけを伝えます
- 人の上書きに根拠を残す … 誰が、何を根拠に入金の月を置き直したかを残します。根拠の無い上書きが続くと、見込みが担当者の希望に戻ります
- 規程の割合の変更を記録する … 設定の表の版の履歴を残し、誰がいつ変えたかを追えるようにします
- 予約の判断を代替しない … 結ぶ量と時期、ヘッジ会計をどう適用するかは、財務部と経理部と監査人が決めます
- モデルの見直しの記録を残す … 特徴量や学習の期間を変えたときは、変える前と後の評価の結果を並べて残します
誤りが起きた場合のリスクは、見込みを上振れさせて予約を積みすぎることと、幅を狭く見て安心することの2つです。 前者は中央の額で案を作ると起き、後者は取引先ごとに揺らさないと起きます。どちらも幅の作り方から出ているので、そこだけは設計で守ります。
10まず何から始めるか
1週目:入金が請求に充てられているかを確かめる
販売管理システムから過去2年分の外貨建ての請求と消込を出し、入金がどの請求に充てられたかが分かるかを、取引先ごとに確かめます。 まとめて払う取引先の消込のしかたを、経理と確かめます。
2週目:遅れの中央値で過去を振り返る
第8章のとおり、半年前の時点の未入金の請求を遅れの中央値で置き、担当者の見込みと実際の入金を並べます。どの取引先で外れたかを財務の担当と見ます。
3週目:規程の割合と点を決める
社内規程の割合を、何か月先かごとの表にします。予約の量の案に下側のどの点(10%点など)を使うかを、財務部長と決めます。
4週目:請求ごとの確率を出す
Python で遅れの区分と特徴量を作り、HistGradientBoostingClassifier で確率を出します。この時点ではシミュレーションをせず、確率と実際の割合のずれだけを見ます。
2か月目: 取引先ごとに揺らすシミュレーションと、追加の量の案、要確認の一覧を足します。会議の資料は従来の見込みと並べて出します。3か月目以降: 過去6か月で幅に入った割合を毎月確かめ、1社6分が何分になったかを実測します。幅に入った割合が8割前後で安定し、会議が下側の額で予約の量を話すようになった時点で、この構成は完成です。
11関連ユースケース
12この仕組みを理解するための記事
13技術仕様の確認日・参考情報
| 確認した内容 | 情報源 | 確認日 |
|---|---|---|
HistGradientBoostingClassifier が欠損値(NaN)をそのまま扱い、学習のときに欠損のある行を分岐の左右どちらに送るかを学ぶこと。categorical_features の既定が 'from_dtype' であること。predict_proba でクラスごとの確率を返すこと。early_stopping の既定が 'auto' で、標本が1万件を超えるときに有効になること | scikit-learn: HistGradientBoostingClassifier | 2026-10-08 |
TimeSeriesSplit が時間の順のデータを分けるためのもので、ほかの分け方は未来のデータで学習して過去を評価することになること。n_splits・gap・test_size・max_train_size の引数 | scikit-learn: TimeSeriesSplit | 2026-10-08 |
較正された分類器では predict_proba の値を確からしさとして読め、0.8前後の標本のおよそ8割が実際にそのクラスになること。CalibratedClassifierCV の sigmoid と isotonic の違いと、isotonic がおよそ1,000件を超えるデータで sigmoid と同じかよく、少ないデータでは過学習しやすいこと | scikit-learn: Probability calibration | 2026-10-08 |
予約を結ぶ量と時期、ヘッジ会計の適用は、財務部と経理部と監査人で決めてください。 本記事は scikit-learn の公開ドキュメントで確認できた範囲だけを扱っています。
実装ステータス:構成例。 公開仕様に基づいて設計した構成であり、当社で実際に構築・検証したものではありません。工数の数値はモデル条件による試算です。
自社の業務に使えるAI活用候補を整理します
このユースケース(UC-1022)についてのご相談はこちらから。
