clvkit.CLV#
- class CLV(transaction_model=None, monetary_model=None, *, check_independence=True)[source]#
Bases:
objectThe one-shot composition — a transaction model and a monetary model.
>>> clv = CLV().fit(cb).predict(horizon=12, discount_rate=0.01) >>> clv.to_pandas()["clv"]
Defaults to BGNBD() for the transaction flow and GammaGamma() for spend; pass either to swap it, e.g. CLV(transaction_model=MBGNBD()).
- Parameters:
transaction_model (TransactionModel | None)
monetary_model (MonetaryModel | None)
check_independence (bool)
- fit(cb)[source]#
Fit both sub-models on cb, and assess the assumption joining them.
Lifetime value needs amounts, so a CustomerBase built without an amount_col is refused here rather than several frames deep inside the monetary model.
- Parameters:
cb (CustomerBase)
- Return type:
- predict(*, horizon, discount_rate=0.0, margin=1.0, cb=None)[source]#
Discounted expected residual lifetime value over horizon periods.
horizon is a whole number of the fitted base’s own time_unit; the DET sum runs one term per period, so half a period has no increment.
discount_rate is d in the DET sum: the rate per `time_unit`, not per year. At weekly granularity 0.01 is 1% a week, ~68% a year.
margin is the contribution margin of equation (1). The default of 1.0 makes the result revenue-based lifetime value; pass your gross margin to get contribution-based CLV (see opinions.md).
- Parameters:
horizon (int)
discount_rate (float)
margin (float)
cb (CustomerBase | None)
- Return type:
- independence_check(cb=None)[source]#
The §2.2 assessment of the assumption this composition rests on.
Defaults to the base the model was fitted on. Read .holds() for the verdict and .plot() for the paper’s Figure 4 on your own data.
- Parameters:
cb (CustomerBase | None)
- Return type:
IndependenceCheck