Skip to content

Retail and consumer goodsBI, AI and ML for the business

Price elasticity and the price-list proposal

A price rise can cost a third of the units or almost nothing, and you find out after the fact. In Muvia a model your team writes estimates every item's elasticity each week and prepares the price-list proposal: what to raise, what to cut and how much margin it brings.

Illustrative scenario: it describes a typical case, not a customer project.

On the price list, a rise that holds and one that drives customers away look the same.

When costs go up, the price list is usually adjusted across the board: a few points more on the whole category. But every item reacts in its own way. On some a rise goes unnoticed, on others it costs one unit in three, and that only shows in the sales of the weeks that follow.

Estimating price sensitivity means separating the effect of price from that of flyers and season, item by item, and doing it again whenever new data arrives. In a spreadsheet, nobody really does.

Who it's for
Pricing and category managers, sales management, management accounting.
List prices, purchase costs and shelf prices from the ERP on SQL Server, units sold from the till files and the flyer calendar in Excel flow into Muvia, where a Python function estimates every item's elasticity each Monday; out come an analysis of prices and units, a scenario dashboard, the notebook with the price-list proposal and Athena's answers.

In Muvia, step by step

Real product screens, recorded on a project with sample data.

1 of 5

The video · A price rise can cost a third of the units or almost nothing, and you find out after the fact. In Muvia a model your team writes estimates every item's elasticity each week and prepares the price-list proposal: what to raise, what to cut and how much margin it brings.

What you get

Every item its own price
Rises go where demand can take them and cuts where they bring back units and margin, instead of one adjustment for all.
Price told apart from the flyer
The model does not mistake the effect of a promotion or of the season for the effect of price.
The proposal updates itself
Every Monday the elasticity is recomputed on the new data and the price-list proposal follows.
The reason written alongside
Every proposed price carries its explanation in words, readable by people who did not build the model.

For the technical team

How it is built in Muvia

  1. 1

    Bring prices and sales together

    The ERP on SQL Server brings prices and costs, the till files bring units sold, an Excel file the flyer calendar. A query joins them into one series per item and day, saved as a dataset.

  2. 2

    Look before you model

    In Analysis, stack price and units, annotate the day of a price rise and compare two items in the XY chart: the one that collapses and the one that stays flat show up before any model.

  3. 3

    Estimate elasticity in Python

    A Python function runs a log-log regression for every item, with flyers and season among the variables: the price coefficient is the elasticity. Your team writes it, starting from an Athena draft if it likes.

  4. 4

    Schedule the proposal

    A flow runs it every Monday morning and writes to managed tables each item's elasticity and the expected margin for price changes from −5% to +5%, with the proposed price and the reason.

  5. 5

    Take the proposal to the decision

    A dashboard shows which items can take a rise and which should come down; the price-list notebook, with text and figures that stay current, is ready for Monday's meeting.

Python function

import numpy as np
import pandas as pd

def _elasticity(g):
    day = pd.to_datetime(g["day"]).dt.dayofyear.to_numpy(float)
    X = np.column_stack([
        np.ones(len(g)),
        np.log(g["shelf_price"]),
        g["on_flyer"],
        np.sin(2 * np.pi * day / 365.25),
        np.cos(2 * np.pi * day / 365.25),
    ])
    beta, *_ = np.linalg.lstsq(X, np.log(g["units"]), rcond=None)
    return beta[1]

def transform(inputs, params, ctx):
    d = inputs["rows"]
    rows = []
    for code, g in d[d["units"] > 0].groupby("item_code"):
        e = _elasticity(g)
        last = g.sort_values("day").iloc[-1]
        weekly_units = g["units"].tail(28).mean() * 7
        for v in range(-5, 6):
            price = last["list_price"] * (1 + v / 100)
            units = weekly_units * (1 + v / 100) ** e
            rows.append({"item_code": code, "elasticity": round(e, 2),
                         "change_pct": v,
                         "weekly_margin": round((price - last["purchase_cost"]) * units, 2)})
    return {"rows": pd.DataFrame(rows)}
Each item's elasticity from a log-log regression, and the expected weekly margin from −5% to +5% on price.
The data it needs
  • List and shelf prices per item, day by day, from the ERP on SQL Server
  • Purchase costs per item, from the same ERP
  • Units sold per item and day, from the till files
  • Flyer and promotion calendar, from an Excel file
Parts of Muvia used

Bring us a question you can't answer today.

We start from a real question your business has and walk the path from source to dashboard with your systems, not a demo dataset.