Understanding the intricacies of price elasticity and leveraging advanced econometric models can significantly enhance your pricing strategies. In this blog post, we will estimate the price elasticity of demand using a linear demand function. The process is largely the same for other types of demand functions. We will then use this information to derive the revenue-maximizing price and visualize the revenue price curve using Python.
Step 1: Setting Up the Environment
First, ensure your Python environment is set up with the necessary libraries:
pip install pandas numpy statsmodels matplotlib seaborn
Next you will need to make sure that you import all of these libraries to python:
import pandas as pd
import numpy as np
import statsmodels.api as sm
import matplotlib.pyplot as plt
import seaborn as sns
sns.set()
Now, let’s generate some fake data to work with. Obviously, you will want to derive insights from some real data that you have access to.
# Set the random seed for reproducibility
np.random.seed(42)
# Generate 100 data points
num_points = 100
# Generate random prices between 10 and 100
prices = np.random.uniform(10, 100, num_points)
# Assume a log-linear relationship with some noise
# Quantity = exp(alpha + beta * log(price)) + noise
alpha = 500
beta = -1.5
noise = np.random.normal(0, 0.5, num_points)
quantities = alpha + beta * prices + noise
# Create a DataFrame
data = pd.DataFrame({'Price': prices, 'Quantity': quantities})
# Save to CSV
data.to_csv('fake_price_quantity_data.csv', index=False)
Step 2: Loading and Exploring the Dataset
Load the dataset that we have created. We’re going to explore the columns of Price
and Quantity
.
# Load the dataset
data = pd.read_csv('fake_price_quantity_data.csv')
# Display the first few rows of the dataset
print(data.head())
# Plot the data to visualize the relationship between price and quantity
plt.figure(figsize=(10, 6))
sns.scatterplot(data=data, x='Price', y='Quantity')
plt.title('Price vs Quantity')
plt.xlabel('Price')
plt.ylabel('Quantity')
plt.show()
Step 3: Estimating Price Elasticity
So for this step, we will use ordinary least squares to estimate a demand function. Note, that we are using an extremely simple model of demand, linear demand, and that there are not any other factors complicating the model. Some factors that could demand a more complicated model are time series data, multiple products, seasonal factors, geographic differences, etc. It also isn’t necessarily the best model of demand from a microeconomic point of view. One of the main advantages of linear demand functions is it is not in the family of constant elasticity. This is important, because these demand curves imply that one does not have market power to adjust prices. The linear model of demand leads to a non-constant elasticity of demand.
# Define the dependent and independent variables
X = data['Price']
y = data['Quantity']
# Add a constant to the independent variable (intercept term)
X = sm.add_constant(X)
# Fit the linear regression model
model = sm.OLS(y, X).fit()
# Display the summary of the regression model
x = np.linspace(2,2*data['Price'].max(),100)
elasticity = model.params['Price']*data['Price']/demand(data['Price'],model.params['const'],model.params['Price'])
print(f'Estimated Price Elasticity of Demand: {np.mean(elasticity)}')
elasticity = model.params['Price']*x/demand(x,model.params['const'],model.params['Price'])
plt.figure(figsize=(10, 6))
plt.plot(x,elasticity,label='Price Elasticity of Demand')
closest = x[elasticity.tolist().index(elasticity[int((np.abs(elasticity +1)).argmin())])]
plt.axvline(closest,color='red',linestyle='--',label='Revenue Maximizing Price: ${}'.format(round(closest,2)))
plt.axhline(-1,color='black',linestyle='--', label='Unit Elasticity')
plt.title('Price vs Elasticity of Demand')
plt.xlabel('Price')
plt.ylabel('Elasticity of Demand')
plt.legend()
plt.show()
model.summary()
The output of our model gives an estimated average price elasticity of demand of -0.23. Since the elasticity of demand is greater than -1.0, this indicates that you will likely be able to raise prices above the average prices in the dataset. In fact, in our dataset, prices only goes up to $100 per unit. This analysis indicates that we can increase our prices as high as $146.26, well above what is in our dataset!
Step 4: Deriving the Revenue-Maximizing Price
In the previous step, we found the revenue maximizing price by finding the price that led to unit elasticity of demand. That method will always work, but the code to do it isn’t exactly intuitive. Go ahead and try to parse out how we did that. We can explicitly maximize the revenue function.
# Define the demand function
def demand(price,alpha,beta):
quantity = alpha + beta * price
return quantity
#Define the revenue function
def revenue(price, alpha, beta):
return price * demand(price, alpha, beta)
#Take the negative of the revenue function (minimizing the negative of a function is maximizing the original)
def negrevenue(price,alpha,beta):
return -revenue(price,alpha,beta)
# Extract the intercept (alpha) and slope (beta) from the model
alpha = model.params['const']
beta = model.params['Price']
print(revenue(10,alpha,beta))
result = minimize(negrevenue,100,args=(alpha,beta,),method='L-BFGS-B', bounds=[(0.01,2*data['Price'].max())])
price_star = result.x[0]
result
We find that the maximization procedure yields the same answer as finding the price that gives unit elasticity, $146.26.
Step 5: Visualizing the Revenue Price Curve
We will now visualize the revenue price curve using the derived elasticity. Note that due to the randomness our point estimate from the OLS regression of the maximizing price is a little low.
true_alpha = 500
true_beta = -1.5
price_range = np.linspace(data['Price'].min(), 2*data['Price'].max(), 100)
revenue_values = [revenue(p, true_alpha, true_beta) for p in price_range]
# Find the price that maximizes revenue
max_revenue_price = price_range[np.argmax(revenue_values)]
max_revenue = max(revenue_values)
print(f'Revenue-Maximizing Price: {max_revenue_price}')
print(f'Estimated Revenue-Maximizing Price: {price_star}')
print(f'Maximum Revenue: {max_revenue}')
# Plot the revenue price curve
plt.figure(figsize=(10, 6))
plt.plot(price_range, revenue_values, label='Revenue')
plt.axvline(max_revenue_price, color='red', linestyle='--', label='Revenue-Maximizing Price')
plt.axvline(price_star, color='Black', linestyle='--', label='Estimated Revenue-Maximizing Price')
plt.title('True Revenue Price Curve')
plt.xlabel('Price')
plt.ylabel('Revenue')
plt.legend()
plt.show()
At Barnes Analytics, we specialize in data-driven pricing strategies. Contact us today to learn how we can help your business optimize prices and achieve its full potential.