What is Pricing Simulation?
Pricing simulation helps you understand how different prices will impact your sales and revenue. By testing multiple price points, you can:- Predict demand at different price levels
- Find optimal pricing that maximizes revenue
1. Load Historical Sales Data
This dataset comes from a Fortune 500 company that sells a popular health product in a pharmacy. We’ll use their real sales and pricing history to uncover how data can drive smarter, more profitable pricing decisions.Copy
Ask AI
import asyncio
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
from synthefy.api_client import SynthefyAsyncAPIClient
# Load the historical sales data
history_df = pd.read_csv(
"https://drive.google.com/uc?export=download&id=1FtLW17XE1NHcV1bF8mLW_2WHVKzrHts_"
)
future_df = pd.read_csv(
"https://drive.google.com/uc?export=download&id=1l2zG7GNTcdDm_HzKhhwii3GTI0Z99a9h"
)
Data Format: Your CSV should have columns like
date, unit_price, and sales. The future_df represents the time periods you want to forecast for (without the sales column filled in yet).Step 2: Visualize Historical Data
Before running simulations, it’s important to understand your historical data. Let’s create visualizations to see how price and sales have changed over time, and whether there’s a correlation.Show plotting code for historical analysis
Show plotting code for historical analysis
Copy
Ask AI
def plot_historical_analysis(history_df):
"""
Create two plots to analyze historical price and sales data.
Plot 1: Time series showing both unit price and sales over time (dual-axis)
Plot 2: Correlation plot between unit price and sales
Args:
history_df: DataFrame with 'date', 'unit_price', and 'sales' columns
"""
# Create figure with 2 rows and 1 column (vertical layout)
fig = plt.figure(figsize=(14, 10))
# --- Plot 1: Historical Time Series Plot ---
ax1 = plt.subplot(2, 1, 1)
# Plot unit price as a line
sns.lineplot(
data=history_df,
x="date",
y="unit_price",
marker="o",
label="Unit Price",
color="C0",
ax=ax1,
)
ax1.set_ylabel("Unit Price", color="C0", fontsize=12)
ax1.tick_params(axis="y", labelcolor="C0")
ax1.set_xlabel("Date", fontsize=12)
# Create a twin axis for sales
ax2 = ax1.twinx()
sns.lineplot(
data=history_df,
x="date",
y="sales",
marker="s",
label="Sales",
color="C1",
ax=ax2,
)
ax2.set_ylabel("Sales", color="C1", fontsize=12)
ax2.tick_params(axis="y", labelcolor="C1")
# Only show a subset of date xtick labels for readability
n_dates = len(history_df["date"])
step = max(n_dates // 10, 1)
xticks_locs = history_df["date"].iloc[::step]
ax1.set_xticks(xticks_locs)
ax1.set_xticklabels(xticks_locs, rotation=45, ha="right")
# Combine legends from both axes
lns1, labs1 = ax1.get_legend_handles_labels()
lns2, labs2 = ax2.get_legend_handles_labels()
ax2.legend(lns1 + lns2, labs1 + labs2, loc="upper left", frameon=True)
ax1.set_title(
"Historical Unit Price and Sales Over Time",
fontsize=13,
weight="semibold",
)
# --- Plot 2: Correlation Plot ---
ax3 = plt.subplot(2, 1, 2)
corr_val = (
history_df[["unit_price", "sales"]]
.corr()
.loc["unit_price", "sales"]
)
sns.regplot(
x="unit_price",
y="sales",
data=history_df,
marker="o",
color="C2",
line_kws={"color": "C3", "lw": 2, "label": f"Corr={corr_val:.2f}"},
ax=ax3,
scatter_kws={"alpha": 1.0}, # No scatter shading, points fully opaque
ci=None, # Remove confidence interval shading (the red band)
)
ax3.set_xlabel("Unit Price ($)", fontsize=12)
ax3.set_ylabel("Sales", fontsize=12)
ax3.set_title(
"Correlation Between Unit Price and Sales",
fontsize=13,
weight="semibold",
)
ax3.legend()
ax3.grid(True, linestyle="--", alpha=0.4)
plt.tight_layout()
plt.savefig("pricing_data_visualization.png", dpi=300, bbox_inches="tight")
plt.show()
# Visualize the historical data
plot_historical_analysis(history_df)
The time series plot shows trends over time, while the correlation plot reveals if there’s a linear relationship between price and demand. A negative correlation suggests demand decreases as price increases (price sensitivity).
Example Output: Historical Data Analysis

- Top panels: How unit price and sales volume have varied over 2 years of weekly data
- Bottom panel: A clear negative correlation (-0.64) between price and sales, confirming price sensitivity
Step 3: Set Up Pricing Simulation
Now, let’s define the range of prices we want to test. We’ll create a range of 11 price points ranging from 85% to 115% of your historical average price. We’ll call this the “base” price, and use it as a basline for comparison.Copy
Ask AI
# Calculate base price from historical data
base_price = history_df["unit_price"].mean()
# Create price range (11 price points from 85% to 115% of base price)
price_simulation_range = np.linspace(base_price * 0.85, base_price * 1.15, 11)
print(f"Testing prices from ${price_simulation_range[0]:.2f} to ${price_simulation_range[-1]:.2f}")
Adjust the range: You can modify the
0.85 and 1.15 multipliers to test a wider or narrower price range. For example, use 0.7 and 1.3 to test 70% to 130% of the base price.Step 4: Prepare Data for Forecasting
For each price point, we need to create a separate forecast scenario. We’ll duplicate the future DataFrame and modify theunit_price column for each scenario.
Copy
Ask AI
# Data preparation for pricing simulation
target_dfs = []
for price in price_simulation_range:
modified_future = future_df.copy()
modified_future["unit_price"] = price
target_dfs.append(modified_future)
Step 5: Run AI Forecasts
Copy
Ask AI
async def get_forecasts():
async with SynthefyAsyncAPIClient() as api_client:
results = await api_client.forecast_dfs(
history_dfs=[history_df] * len(price_simulation_range),
target_dfs=target_dfs,
target_col="sales",
timestamp_col="date",
metadata_cols=["unit_price"],
leak_cols=["unit_price"],
model="sfm-moe-v1",
)
return results
# Run the async forecast function
results = asyncio.run(get_forecasts())
print(f"✓ Received {len(results)} forecast results")
Key parameters:
metadata_cols=["unit_price"]: Features the model can useleak_cols=["unit_price"]: Features that are known in advance (price is controllable)
Step 6: Create Time Series Forecast Visualization
First, let’s create a comprehensive time series visualization that shows all forecast scenarios overlaid on the historical data.Show time series visualization code
Show time series visualization code
Copy
Ask AI
def plot_forecast_time_series(
history_df,
future_df,
results,
price_simulation_range,
base_price,
optimal_price,
):
"""Plot historical data and all forecasts for different prices using swarm-visualizer."""
fig, ax = plt.subplots(figsize=(20, 6))
# Get future dates
future_dates = future_df["date"].tolist()
# Prepare data for swarm-visualizer - show only last 50% of history
history_cutoff = len(history_df) // 2
history_subset = history_df.iloc[history_cutoff:]
normalized_dict = {
"Historical Sales": {
"x": history_subset["date"],
"y": history_subset["sales"],
"lw": 3,
"linestyle": "-",
"color": "black",
"alpha": 0.8,
"zorder": 5,
}
}
# Plot ALL forecasts - every single price point!
# Orange gradient color scheme for all forecasts
import matplotlib.cm as cm
# Create orange gradient colors for all price points
orange_colors = cm.Oranges(
np.linspace(0.3, 0.9, len(price_simulation_range))
)
for i, (price, result) in enumerate(zip(price_simulation_range, results)):
forecast_values = result["sales"].tolist()
# Combine historical data with forecast for this price
# Historical data (same for all prices) - only last 50%
historical_dates = history_subset["date"].tolist()
historical_sales = history_subset["sales"].tolist()
# Combine historical + forecast dates and values
combined_dates = historical_dates + future_dates
combined_sales = historical_sales + forecast_values
# Determine styling based on price type - all using orange gradient
color = orange_colors[i] # Each price gets its own orange shade
if abs(price - optimal_price) < 0.01:
label = f"Optimal Price (${price:.2f})"
linewidth = 4
alpha = 1.0
elif abs(price - base_price) < 0.01:
label = f"Base Price (${price:.2f})"
linewidth = 4
alpha = 1.0
else:
label = f"${price:.2f}"
linewidth = 2.0
alpha = 0.8
normalized_dict[label] = {
"x": combined_dates,
"y": combined_sales,
"lw": linewidth,
"linestyle": "-",
"color": color,
"alpha": alpha,
"zorder": 4,
}
# Use swarm-visualizer plot_overlaid_lineplot
swarm_visualizer.plot_overlaid_lineplot(
ax=ax,
normalized_dict=normalized_dict,
title_str="Pricing Simulation: Complete Time Series with Forecasts by Price",
ylabel="Sales",
xlabel="Date",
legend_present=True,
)
# Add light blue background for the forecast region
last_historical_date = history_subset["date"].iloc[-1]
last_forecast_date = future_df["date"].iloc[-1]
# Add light blue background for the forecast region
ax.axvspan(
xmin=last_historical_date,
xmax=last_forecast_date,
ymin=0,
ymax=1,
color="lightblue",
alpha=0.2,
zorder=1,
label="Forecast Region",
)
# Add light blue vertical line to separate historical from forecast
ax.axvline(
x=last_historical_date,
color="lightblue",
linestyle="-",
alpha=0.8,
linewidth=3,
zorder=3,
)
ax.text(
last_historical_date,
ax.get_ylim()[1] * 0.95,
"Forecasts",
ha="left",
va="top",
fontsize=12,
color="black",
weight="bold",
zorder=6,
)
# Use swarm-visualizer set_axis_infos for consistent styling
from swarm_visualizer.utility import set_axis_infos
set_axis_infos(
ax=ax,
xlabel="Date",
ylabel="Sales",
title_str="Simulation: Forecasts for Different Prices",
grid=True,
)
# Rotate x-axis labels to prevent overlap and improve readability
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", fontsize=10)
plt.savefig("forecast_time_series.png", dpi=300, bbox_inches="tight")
plt.show()
# Create time series visualization showing all forecasts
print("📊 Creating time series visualization of all forecasts...")
plot_forecast_time_series(
history_df,
future_df,
results,
price_simulation_range,
base_price,
optimal_price,
)
Example Output: Time Series Forecast Visualization

- Black line: Historical sales data (last 50% for focus)
- Orange gradient lines: All forecast scenarios for different prices
- Light blue background: Highlights the forecast region
- Optimal & Base prices: Thicker lines for key scenarios
Step 7: Analyze Results
Extract the forecasts and calculate revenue for each price point. Then identify the optimal price that maximizes revenue.Copy
Ask AI
# Extract forecasts (mean sales for each price point)
forecasts = [int(round(result["sales"].mean())) for result in results]
# Calculate revenue for each price point
revenues = [price * forecast for price, forecast in zip(price_simulation_range, forecasts)]
# Find optimal price point
optimal_idx = np.argmax(revenues)
optimal_price = price_simulation_range[optimal_idx]
optimal_transactions = forecasts[optimal_idx]
optimal_revenue = revenues[optimal_idx]
# Find base price index (closest to current average price)
base_idx = np.argmin(np.abs(price_simulation_range - base_price))
base_transactions = forecasts[base_idx]
base_revenue = revenues[base_idx]
Step 8: Visualize Pricing Insights
Finally, let’s create comprehensive visualizations to understand the price-demand relationship and identify the optimal pricing strategy.Show visualization code
Show visualization code
Copy
Ask AI
# Create 3-plot visualization
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 5))
fig.suptitle(
"Pricing Simulation Analysis", fontsize=18, fontweight="bold", y=0.95
)
# Plot 1: Price vs Sales (Partial Dependence Plot)
ax1.plot(
price_simulation_range,
forecasts,
"x--",
linewidth=2.5,
markersize=8,
color="#4A90E2",
markeredgewidth=2,
label="Forecasted Sales",
)
ax1.axvline(
x=base_price,
color="black",
linestyle="--",
linewidth=2,
alpha=0.8,
label="Base Price",
)
ax1.set_xlabel("Sales Price ($)", fontsize=11)
ax1.set_ylabel("Avg Forecasted Sales", fontsize=11)
ax1.set_title(
"Partial Dependence Plot (Price vs Avg Forecasted Sales)", fontsize=12
)
ax1.grid(True, alpha=0.3, linestyle="-", linewidth=0.5)
ax1.legend(fontsize=9, loc="upper right")
ax1.spines["top"].set_visible(True)
ax1.spines["right"].set_visible(True)
# Plot 2: Price vs Revenue
ax2.plot(
price_simulation_range,
revenues,
"o--",
linewidth=2.5,
markersize=7,
color="#E24A90",
markeredgewidth=1.5,
markeredgecolor="white",
label="Expected Revenue",
)
ax2.axvline(
x=base_price,
color="black",
linestyle="--",
linewidth=2,
alpha=0.8,
label="Base Price",
)
ax2.axvline(
x=optimal_price,
color="#2ECC71",
linestyle="--",
linewidth=2,
alpha=0.8,
label="Optimal Price",
)
ax2.scatter(
[optimal_price],
[optimal_revenue],
color="#2ECC71",
s=200,
zorder=5,
marker="o",
edgecolors="white",
linewidth=2,
)
ax2.set_xlabel("Sales Price ($)", fontsize=11)
ax2.set_ylabel("Expected Revenue ($)", fontsize=11)
ax2.set_title("Price vs Revenue Optimization", fontsize=12)
ax2.grid(True, alpha=0.3, linestyle="-", linewidth=0.5)
ax2.legend(fontsize=9)
# Format y-axis for revenue
ax2.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"${x:,.0f}"))
# Plot 3: Revenue comparison bar chart
colors = ["#FF6B6B", "#51CF66"]
bars = ax3.bar(
[
"Base Price\n" + f"${base_price:.2f}",
"Optimal Price\n" + f"${optimal_price:.2f}",
],
[base_revenue, optimal_revenue],
color=colors,
alpha=0.8,
edgecolor="black",
linewidth=2,
)
ax3.set_ylabel("Expected Revenue ($)", fontsize=12, fontweight="bold")
ax3.set_title("Revenue Comparison", fontsize=14)
ax3.grid(True, alpha=0.3, axis="y")
# Add value labels on bars
for bar in bars:
height = bar.get_height()
ax3.text(
bar.get_x() + bar.get_width() / 2.0,
height,
f"${height:,.0f}",
ha="center",
va="bottom",
fontsize=11,
fontweight="bold",
)
ax3.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"${x:,.0f}"))
plt.tight_layout()
plt.savefig("pricing_simulation_results.png", dpi=300, bbox_inches="tight")
plt.show()
Example Output: Pricing Simulation Results

- How price-sensitive are my customers? → Look at Plot 1 (steeper slope = more sensitivity)
- What’s my optimal price? → Look at Plot 2 (green marker)
- How much revenue am I leaving on the table? → Look at Plot 3 (red vs green bars)
Complete Code
Here’s the full working example you can run:Show complete code
Show complete code
Copy
Ask AI
import asyncio
import matplotlib.cm as cm
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import seaborn as sns
import swarm_visualizer
from swarm_visualizer.utility import set_axis_infos
from synthefy.api_client import SynthefyAsyncAPIClient
# Step 1: Load Your Historical Sales Data
history_df = pd.read_csv(
"https://drive.google.com/uc?export=download&id=1FtLW17XE1NHcV1bF8mLW_2WHVKzrHts_"
)
future_df = pd.read_csv(
"https://drive.google.com/uc?export=download&id=1l2zG7GNTcdDm_HzKhhwii3GTI0Z99a9h"
)
def plot_historical_analysis(history_df):
"""Create two plots to analyze historical price and transaction data."""
# --- Historical Time Series Plot ---
fig, ax1 = plt.subplots(figsize=(13, 5))
sns.lineplot(
data=history_df, x="date", y="unit_price",
marker="o", label="Unit Price", color="C0", ax=ax1,
)
ax1.set_ylabel("Unit Price", color="C0", fontsize=12)
ax1.tick_params(axis="y", labelcolor="C0")
ax1.set_xlabel("Date", fontsize=12)
ax2 = ax1.twinx()
sns.lineplot(
data=history_df, x="date", y="sales",
marker="s", label="Sales", color="C1", ax=ax2,
)
ax2.set_ylabel("Sales", color="C1", fontsize=12)
ax2.tick_params(axis="y", labelcolor="C1")
n_dates = len(history_df["date"])
step = max(n_dates // 10, 1)
xticks_locs = history_df["date"].iloc[::step]
ax1.set_xticks(xticks_locs)
ax1.set_xticklabels(xticks_locs, rotation=45, ha="right")
lns1, labs1 = ax1.get_legend_handles_labels()
lns2, labs2 = ax2.get_legend_handles_labels()
ax2.legend(lns1 + lns2, labs1 + labs2, loc="upper left", frameon=True)
ax1.set_title("Historical Unit Price and Sales Over Time",
fontsize=15, weight="semibold")
plt.tight_layout()
plt.show()
# --- Correlation Plot ---
corr_val = (
history_df[["unit_price", "sales"]]
.corr().loc["unit_price", "sales"]
)
plt.figure(figsize=(7, 6))
sns.regplot(
x="unit_price", y="sales", data=history_df,
marker="o", color="C2",
line_kws={"color": "C3", "lw": 2, "label": f"Corr={corr_val:.2f}"},
)
plt.xlabel("Unit Price ($)", fontsize=12)
plt.ylabel("Sales", fontsize=12)
plt.title("Correlation Between Unit Price and Sales",
fontsize=15, weight="semibold")
plt.legend()
plt.grid(True, linestyle="--", alpha=0.4)
plt.tight_layout()
plt.show()
# Step 2: Visualize Historical Data
plot_historical_analysis(history_df)
# Step 3: Set Up Price Grid
base_price = history_df["unit_price"].mean()
price_simulation_range = np.linspace(base_price * 0.85, base_price * 1.15, 11)
print(f"Testing prices from ${price_simulation_range[0]:.2f} to ${price_simulation_range[-1]:.2f}")
# Step 4: Prepare Data for Forecasting
target_dfs = []
for price in price_simulation_range:
modified_future = future_df.copy()
modified_future["unit_price"] = price
target_dfs.append(modified_future)
# Step 5: Run AI Forecasts
async def get_forecasts():
async with SynthefyAsyncAPIClient() as api_client:
results = await api_client.forecast_dfs(
history_dfs=[history_df] * len(price_simulation_range),
target_dfs=target_dfs,
target_col="sales",
timestamp_col="date",
metadata_cols=["unit_price"],
leak_cols=["unit_price"],
model="sfm-moe-v1",
)
return results
results = asyncio.run(get_forecasts())
print(f"✓ Received {len(results)} forecast results")
# Step 6: Analyze Results
forecasts = [int(round(result["sales"].mean())) for result in results]
revenues = [price * forecast for price, forecast in zip(price_simulation_range, forecasts)]
optimal_idx = np.argmax(revenues)
optimal_price = price_simulation_range[optimal_idx]
optimal_revenue = revenues[optimal_idx]
base_idx = np.argmin(np.abs(price_simulation_range - base_price))
base_revenue = revenues[base_idx]
# Step 6: Create Time Series Forecast Visualization
def plot_forecast_time_series(
history_df,
future_df,
results,
price_simulation_range,
base_price,
optimal_price,
):
"""Plot historical data and all forecasts for different prices using swarm-visualizer."""
fig, ax = plt.subplots(figsize=(20, 6))
# Get future dates
future_dates = future_df["date"].tolist()
# Prepare data for swarm-visualizer - show only last 50% of history
history_cutoff = len(history_df) // 2
history_subset = history_df.iloc[history_cutoff:]
normalized_dict = {
"Historical Sales": {
"x": history_subset["date"],
"y": history_subset["sales"],
"lw": 3,
"linestyle": "-",
"color": "black",
"alpha": 0.8,
"zorder": 5,
}
}
# Plot ALL forecasts - every single price point!
# Orange gradient color scheme for all forecasts
# Create orange gradient colors for all price points
orange_colors = cm.Oranges(
np.linspace(0.3, 0.9, len(price_simulation_range))
)
for i, (price, result) in enumerate(zip(price_simulation_range, results)):
forecast_values = result["sales"].tolist()
# Combine historical data with forecast for this price
# Historical data (same for all prices) - only last 50%
historical_dates = history_subset["date"].tolist()
historical_sales = history_subset["sales"].tolist()
# Combine historical + forecast dates and values
combined_dates = historical_dates + future_dates
combined_sales = historical_sales + forecast_values
# Determine styling based on price type - all using orange gradient
color = orange_colors[i] # Each price gets its own orange shade
if abs(price - optimal_price) < 0.01:
label = f"Optimal Price (${price:.2f})"
linewidth = 4
alpha = 1.0
elif abs(price - base_price) < 0.01:
label = f"Base Price (${price:.2f})"
linewidth = 4
alpha = 1.0
else:
label = f"${price:.2f}"
linewidth = 2.0
alpha = 0.8
normalized_dict[label] = {
"x": combined_dates,
"y": combined_sales,
"lw": linewidth,
"linestyle": "-",
"color": color,
"alpha": alpha,
"zorder": 4,
}
# Use swarm-visualizer plot_overlaid_lineplot
swarm_visualizer.plot_overlaid_lineplot(
ax=ax,
normalized_dict=normalized_dict,
title_str="Pricing Simulation: Complete Time Series with Forecasts by Price",
ylabel="Sales",
xlabel="Date",
legend_present=True,
)
# Add light blue background for the forecast region
last_historical_date = history_subset["date"].iloc[-1]
last_forecast_date = future_df["date"].iloc[-1]
# Add light blue background for the forecast region
ax.axvspan(
xmin=last_historical_date,
xmax=last_forecast_date,
ymin=0,
ymax=1,
color="lightblue",
alpha=0.2,
zorder=1,
label="Forecast Region",
)
# Add light blue vertical line to separate historical from forecast
ax.axvline(
x=last_historical_date,
color="lightblue",
linestyle="-",
alpha=0.8,
linewidth=3,
zorder=3,
)
ax.text(
last_historical_date,
ax.get_ylim()[1] * 0.95,
"Forecasts",
ha="left",
va="top",
fontsize=12,
color="black",
weight="bold",
zorder=6,
)
# Use swarm-visualizer set_axis_infos for consistent styling
set_axis_infos(
ax=ax,
xlabel="Date",
ylabel="Sales",
title_str="Simulation: Forecasts for Different Prices",
grid=True,
)
# Rotate x-axis labels to prevent overlap and improve readability
plt.setp(ax.get_xticklabels(), rotation=45, ha="right", fontsize=10)
plt.savefig("forecast_time_series.png", dpi=300, bbox_inches="tight")
plt.show()
# Create time series visualization showing all forecasts
print("📊 Creating time series visualization of all forecasts...")
plot_forecast_time_series(
history_df,
future_df,
results,
price_simulation_range,
base_price,
optimal_price,
)
# Step 7: Analyze Results
forecasts = [int(round(result["sales"].mean())) for result in results]
revenues = [price * forecast for price, forecast in zip(price_simulation_range, forecasts)]
optimal_idx = np.argmax(revenues)
optimal_price = price_simulation_range[optimal_idx]
optimal_revenue = revenues[optimal_idx]
base_idx = np.argmin(np.abs(price_simulation_range - base_price))
base_revenue = revenues[base_idx]
# Step 8: Visualize Pricing Insights
fig, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(18, 5))
fig.suptitle("Pricing Simulation Analysis", fontsize=18, fontweight="bold", y=0.95)
# Plot 1: Price vs Sales
ax1.plot(price_simulation_range, forecasts, "x--", linewidth=2.5, markersize=8,
color="#4A90E2", markeredgewidth=2, label="Forecasted Sales")
ax1.axvline(x=base_price, color="black", linestyle="--",
linewidth=2, alpha=0.8, label="Base Price")
ax1.set_xlabel("Sales Price ($)", fontsize=11)
ax1.set_ylabel("Avg Forecasted Sales", fontsize=11)
ax1.set_title("Partial Dependence Plot (Price vs Avg Forecasted Sales)", fontsize=12)
ax1.grid(True, alpha=0.3, linestyle="-", linewidth=0.5)
ax1.legend(fontsize=9, loc="upper right")
# Plot 2: Price vs Revenue
ax2.plot(price_simulation_range, revenues, "o--", linewidth=2.5, markersize=7,
color="#E24A90", markeredgewidth=1.5, markeredgecolor="white",
label="Expected Revenue")
ax2.axvline(x=base_price, color="black", linestyle="--",
linewidth=2, alpha=0.8, label="Base Price")
ax2.axvline(x=optimal_price, color="#2ECC71", linestyle="--",
linewidth=2, alpha=0.8, label="Optimal Price")
ax2.scatter([optimal_price], [optimal_revenue], color="#2ECC71",
s=200, zorder=5, marker="o", edgecolors="white", linewidth=2)
ax2.set_xlabel("Sales Price ($)", fontsize=11)
ax2.set_ylabel("Expected Revenue ($)", fontsize=11)
ax2.set_title("Price vs Revenue Optimization", fontsize=12)
ax2.grid(True, alpha=0.3, linestyle="-", linewidth=0.5)
ax2.legend(fontsize=9)
ax2.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"${x:,.0f}"))
# Plot 3: Revenue Comparison
bars = ax3.bar(
[f"Base Price\n${base_price:.2f}", f"Optimal Price\n${optimal_price:.2f}"],
[base_revenue, optimal_revenue],
color=["#FF6B6B", "#51CF66"], alpha=0.8, edgecolor="black", linewidth=2,
)
ax3.set_ylabel("Expected Revenue ($)", fontsize=12, fontweight="bold")
ax3.set_title("Revenue Comparison", fontsize=14)
ax3.grid(True, alpha=0.3, axis="y")
for bar in bars:
height = bar.get_height()
ax3.text(bar.get_x() + bar.get_width() / 2.0, height,
f"${height:,.0f}", ha="center", va="bottom",
fontsize=11, fontweight="bold")
ax3.yaxis.set_major_formatter(plt.FuncFormatter(lambda x, p: f"${x:,.0f}"))
plt.tight_layout()
plt.savefig("pricing_simulation_results.png", dpi=300, bbox_inches="tight")
plt.show()
Next Steps
- Prepare your own data with historical prices and transactions
- Run the simulation with different price ranges
- Analyze the results to find your optimal price point
Pro tip: Run pricing simulations regularly (monthly or quarterly) as market conditions change. Your optimal price today might not be optimal tomorrow!