@forecast-manifesto/cli

需要予測・顧客資産分析のCLI。取引ログCSVからsummarize+CLV(区間付き)、K同定、Dirichlet市場構造をMarkdown/JSONで出力。


Keywords
cli, clv, bg-nbd, dirichlet, demand-forecast, start-x
License
Apache-2.0
Install
npm install @forecast-manifesto/cli@0.1.1

Documentation

Forecast Manifesto

需要予測の意思決定構造を、編集可能な素材として公開する。点ではなく、幅で語る。

Marketing-OS Manifesto に続く「設計と編集」シリーズ第 2 弾(需要予測編)。数理モデル(NBD + BP-10)による需要予測の計算方法メソッド選定の考え方を OSS として公開する。

森岡毅・今西聖貴『確率思考の戦略論』(KADOKAWA)のメソッドに基づく実装。公知の数式・モデル構造のみを実装し、書籍本文の転載はしない。


スタック:市場 → 顧客を同一の数学血統で貫く

A1  市場の NBD ✅ + Dirichlet ✅     A2  顧客の NBD ✅
    @forecast-manifesto/solver           @forecast-manifesto/clv
    NBD + BP-10                           BG/NBD + Gamma-Gamma
    @forecast-manifesto/dirichlet          浸透率×頻度×金額 → CLV
    多ブランド市場構造(DJ・重複の法則)
        │                                      │
        └──────── 同じ負の二項分布 ────────────┘
        森岡(市場の NBD)→ GEC(Dirichlet)→ Schmittlein/Fader(顧客の NBD)

market(solver)で「市場に何回買う人がどれだけいるか」を、customer(clv)で「この顧客が今後何回・いくら買うか」を、同じ分布で扱う。→ docs/05b-clv.md


3 層構造:どこまでが無料で、どこからが支援か

┌─ 公開層(本リポジトリ|OSS)───────────────────────┐
│  ソルバー実装・BP-10 テンプレ・メソッド選定決定木・思想        │
└──────────┬──────────────────┬──────────────┘
           ↓ 参照                    ↓ 参照
┌─ 診断ツール層 ─────┐   ┌─ サービス層(非公開)──────────┐
│ Marketing-OS         │   │ 顧問デリバラブル:                    │
│ 需要予測構造診断      │   │   業界別ベンチマーク K 値            │
│ = ソルバーの Web 版  │   │   Price Adjustment 実係数・個社予測  │
│                      │   │   外部データパイプライン              │
└──────────────┘   └──────────────────────────┘
  • 公開する:計算方法・選定の考え方(コモディティ化してよい知識)
  • 公開しない:顧問先データで蓄積するベンチマーク・係数・パイプライン(競争力の源泉)

詳細な線引き宣言:docs/05-boundaries.md


クイックスタート

npm install @forecast-manifesto/solver

観測された平均購入回数 M と浸透率 penetration から、NBD の形状パラメータ K を同定する:

import { identifyK } from "@forecast-manifesto/solver";

const { K } = identifyK(1372 / 279812, 0.004875);
console.log(K); // ≈ 0.75

新商品の売上予測(BP-10 → ユニットシェア → 売上):

import { conceptShare, unitShare, forecastRevenue } from "@forecast-manifesto/solver";

const cs = conceptShare([[4, 3, 3], [6, 2, 2], [3, 4, 3]]); // BP-10 集計
const share = unitShare(0.6, 0.7, cs, 1.0);                 // 認知×配荷×CS×価格調整
const revenue = forecastRevenue(2_000_000, share, 480);     // 市場規模×シェア×単価

顧客生涯価値(CLV)— 取引ログから BG/NBD + Gamma-Gamma で個客価値を出す:

import { toRfm, fitBgNbd, fitGammaGamma, clv } from "@forecast-manifesto/clv";

const rfm = toRfm(transactions, observationEnd);   // 取引ログ → RFM
const [p, gg] = [fitBgNbd(rfm), fitGammaGamma(rfm)]; // 生存・頻度/金額
const value = clv(rfm[0], p, gg, { horizonMonths: 12, monthlyDiscount: 0.01, margin: 0.3 });

幅で語る — 点推定に区間を付ける

import { identifyKWithInterval } from "@forecast-manifesto/solver";

const { K, ci } = identifyKWithInterval(1.4, 0.5461, { nCustomers: 2000 });
console.log(K, ci); // 0.75, [0.68, 0.83] — 母数 2,000 人ならこの幅がある

パラメトリック・ブートストラップ(シード固定・再現可能)。fitBgNbdWithInterval / clvWithInterval / summarizeWithInterval も同様。→ docs/08-uncertainty.md

検証する — 予測を当てるゲームにしない

import { splitCalibrationHoldout, trackingCumulative } from "@forecast-manifesto/validate";

const { calibration, holdout } = splitCalibrationHoldout(transactions, splitDate, observationEnd);
const track = trackingCumulative(calibration, transactions, fitBgNbd(calibration), { splitDate, observationEnd, bucket: "week" });

CDNOW 公開データで較正39週→検証39週の外挿誤差 4.1%(最終累積)を再現済み。

実行できる例:examples/


ドキュメント(読了 15 分)

# 内容
01 なぜ数理 × AI のハイブリッドか
02 メソッド選定の決定木
03 NBD モデル解説(M・K の意味、同定手順)
04 BP-10 設問テンプレート+集計方法
05 公開/非公開の線引き宣言
05b 顧客資産の思想(NBD の家系図:森岡 → Fader)
06 増分検証の設計(決定木・チェックリスト・iROAS の読み方)
07 多ブランド市場構造(ダブルジェパディ・購買重複の法則)
08 不確実性の定量化(点ではなく、幅で語る)
09 契約型の解約構造(リテンションは「上がって見える」)

パッケージ:@forecast-manifesto/solver

関数 役割
nbdPmf(r, M, K) NBD 確率質量関数 P_r
identifyK(M, penetration, opts?) K 同定(安全化 Newton 法)
zeroPurchaseProbability(M, K) / penetrationFromK(M, K) 非購入率/浸透率
conceptShare(votes, targetIndex?) BP-10 コンセプトシェア集計
unitShare(awareness, distribution, conceptShare, priceAdj) ユニットシェア
forecastRevenue(marketSize, unitShare, unitPrice) 売上予測

パッケージ:@forecast-manifesto/clv

関数 役割
toRfm(transactions, observationEnd, opts?) 取引ログ → 顧客別 RFM
fitBgNbd(rfm, opts?) BG/NBD 最尤推定(頻度・生存)
probAlive(c, p) / expectedTransactions(t, c, p) 生存確率/期待購買回数
fitGammaGamma(rfm, opts?) / expectedAvgValue(c, gg) 金額モデル(独立性チェック付き)
clv(c, p, gg, opts) CLV(割引現在価値)
summarize(rfm, p, gg) 診断サマリ(生存率・集中度・セグメント)
fitTruncatedNbd(m, repeatRate, opts?) ゼロ切断 NBD:購入者の平均回数とリピート率から (M, K) を同定
truncatedNbdDistribution(M, K, n) / expectedNextPeriodPurchases(r, M, K) P(r | r≥1)/翌年期待購買回数(逓減込み)
topBuyersRevenueShare(M, K, topFraction?) 上位 20% 購入者の売上集中度
fitTruncatedNbdWithInterval(m, repeatRate, opts?) ゼロ切断 NBD 同定+(M, K)・翌年期待購買回数の p5–p95 区間(シード固定)

CDNOW 公開データで Fader-Hardie-Lee (2005) の公表値を許容誤差 1e-2 で再現(packages/clv/tests)。

パッケージ:@forecast-manifesto/validate

関数 役割
splitCalibrationHoldout(transactions, splitDate, observationEnd) 較正/検証分割
conditionalExpectationByFrequency(calib, holdout, params, opts?) 頻度別 実測 vs 予測
trackingCumulative(calib, transactions, params, opts) 累積トラッキング(FHL 2005 Figure 3 方式)
mae(pairs) / rmse(pairs) / mape(pairs) 誤差指標(mape は actual=0 を除外)

不確実性 API:identifyKWithInterval(solver)/fitBgNbdWithIntervalclvWithIntervalsummarizeWithInterval(clv)→ docs/08

パッケージ:@forecast-manifesto/dirichlet

関数 役割
fitDirichlet(input) カテゴリ浸透率・購買頻度・ブランドシェアから M・K・S を同定
brandMetrics(model, brandName?) 理論浸透率・購買頻度・SCR・100%ロイヤル率
duplicationMatrix(model) ブランド間購買重複(重複購買の法則)
doubleJeopardyTable(model) シェア昇順の浸透率×頻度表(DJ線)

R NBDdirichlet 同梱の歯磨き粉市場で公表値(M=1.456, K=0.78, S=1.55)を再現 → docs/07

パッケージ:@forecast-manifesto/sbg

関数 役割
fitSbg(retention) コホート残存率から shifted-beta-geometric を最尤推定
survivalCurve / retentionCurve 生存カーブ/期次リテンション(漸増=生存者バイアス)
expectedTenure(params, horizon?) 期待在籍期間(α>1 は閉形式)
discountedExpectedLifetime / discountedExpectedResidualLifetime DEL/DERL(2F1 閉形式)

Fader & Hardie (2007) の High End / Regular 両セグメントで公表値(α=0.668/β=3.806、α=0.704/β=1.182)と7年先外挿を再現 → docs/09

CLI:@forecast-manifesto/cli

npx @forecast-manifesto/cli analyze transactions.csv \
  --observation-end 2026-06-30 --horizon 12 --margin 0.3 --bootstrap 200 --format md
npx @forecast-manifesto/cli identify-k --m 1.4 --penetration 0.5461 --n 2000
npx @forecast-manifesto/cli dirichlet --config market.json

入力 CSV は customerId,date,amount(UTF-8・ヘッダ必須・クオート対応)。不正行は行番号付きエラー。出力は --format md|json(md はそのまま顧問レポートに貼れる体裁)。


試す / 頼む


開発

npm install       # ワークスペース依存の導入
npm run build     # solver → clv をビルド
npm test          # Vitest(全ワークスペース)
npm run example:k         # K 同定の実例
npm run example:forecast  # 新商品売上予測の実例
npm run example:clv       # 顧客資産(RFM → BG/NBD → CLV)の実例
npm run example:validate  # 検証レポート(CDNOW 較正/検証)の実例
npm run example:interval  # 「幅で語る」不確実性の実例
npm run example:dirichlet # 多ブランド市場構造(DJ表・SCR)の実例
npm run example:sbg       # 契約型(サブスク)解約構造の実例

English summary

Forecast Manifesto publishes the decision structure of demand forecasting as an editable material. It open-sources the calculation methods (NBD + BP-10) and the method-selection reasoning behind demand forecasting — the second entry in the "design & edit" series after Marketing-OS Manifesto.

It is an implementation of the methodology in 確率思考の戦略論 (Morioka & Imanishi, KADOKAWA). Only publicly known formulas and model structures are implemented; no book text is reproduced.

  • Open (this repo): solver, BP-10 template, method-selection decision tree, philosophy — knowledge that is fine to commoditize.
  • Not open (advisory deliverables): industry benchmark K values, real Price-Adjustment coefficients, per-company forecasts, external data pipelines — the competitive edge accumulated from client data.
npm install @forecast-manifesto/solver
import { identifyK } from "@forecast-manifesto/solver";
const { K } = identifyK(1372 / 279812, 0.004875); // ≈ 0.75

License

Apache-2.0 — Marketing-OS エコシステムと同一。詳細は LICENSE / NOTICE