BayesianBLP.counterfactual_shares#
- BayesianBLP.counterfactual_shares(price_change=None, *, periods=None, regions=None, n_samples=200)[source]#
Posterior shares under a counterfactual price intervention.
Holds the posterior
ξ_jt(the structural shock) fixed and recomputes the share equation at the new price. This is the BLP-correct structural counterfactual: “what would shares have been if price for product X had been Y, given the realised demand shocks?”.- Parameters:
- price_change
dict,ndarray, orNone dict {product_name: relative_change}— multiplicative shift (e.g.{"sku_a": 0.10}raisessku_aprice by 10%). Combine withperiods=/regions=to scope the intervention.ndarrayof shape(M, J)is accepted only whentime_colwas not supplied at construction (the flat-ndarray semantics are ambiguous whenM = R*T).None— no change (canary; should reproduce fitted shares).- periodssequence of
periodlabelsorslice, optional Restrict the price change to these periods (coord labels, not integer positions). Only valid when
time_colis set.- regionssequence of
regionlabels, optional Restrict the price change to these regions (coord labels).
- n_samples
int, optional Number of posterior samples to draw the counterfactual at.
Noneuses every chain × draw.
- price_change
- Returns:
xr.Datasetwiths_inside (sample, market, inside_product)ands_outside (sample, market).Whentime_colwassetonthemodel,thedatasetalsocarriesnon-dimensionalperiodandregioncoordinatesalignedwithmarketsocallerscan.set_index(market=("region", "period"))fortidyslicing.
Notes
We do not route this through
pm.do+sample_posterior_predictive. Because the model uses the conditional decompositionξ̃ = ρ·(σ_ξ/σ_η)·η + σ_ξ·sqrt(1-ρ²)·rawfor sampler geometry,ξwould silently shift when price changes (sinceη = price - μ_pand the conditional mean ofξ̃depends onη). The numpy path used here pulls the assembledxiDeterministic from the posterior and treats it as fixed, which gives the structural elasticity semantics.