Skip to content

Adaptive pricing system for profit maximisation featuring frontend adapters, user modelling, APIs, and model evaluation.

Notifications You must be signed in to change notification settings

chrisayyildiz/dynamic-pricing-engine

Repository files navigation

Adaptive Pricing System

This project is a full stack pricing model designed for airline ticketing to showcase and practice business understanding, development, data processing, API work, and system evaluation knowledge.

The overarching aim is to maximise revenue with respect to baseline pricing and wtp whilst constrained by competitor pricing. I've taken this system further by implementing frontend web adapters which display when WTP is high and recommended price > competitor price to aid conversion rates.

To ensure the system worked rapidly, a combination of SQLite3 and Redis Caching was utilised. The output is an efficient and lightweight pricing algorithm which can plug into a live site, run at the user level, and output outcomes data to BigQuery for further evaluation and model improvement.

As I've tailored this project towards data analysis, you'll see a wide range of analytical methods applied to the outcomes data which aid in improving the algorithm and subsequently revenue.

Architecture

The system runs on several microservices which come together to form the pricing engine:

  • Core Engine: A Python service responsible for the central pricing logic. It ingests user data, competitor prices, and business goals to compute the optimal price using a combination of ML models and heuristics.
  • Willingness To Pay: Gathers user device information through a FastAPI with inputs including userID, userIP, local_time, and device_type, all used to calculate a pre-weighted WTP score.
  • Baseline Pricing: Database updated with minimum pricing for flight routes organised by origin, destionation, and date.
  • Competitor Pricing: Utilises the Amedeus API to fetch average pricing across pre-defined competitors based on origin, destination, and travel dates.
  • Adapters: Enables application of behavioural nudges (e.g., "Only 3 seats left at this price!") on the frontend.

Pricing Algorithm

Inputs:

  • $B = \text{Baseline price}$
  • $C = \text{Competitor price}$
  • $s = \text{Willingness to Pay (WTP)}, \ s \in [0, 1]$
  • $\mu = \text{WTP uplift multiplier}$
  • $\tau = \text{WTP threshold to go above competitor}$
  • $\rho = \text{Exit multiplier (premium rate)}$
  • $\pi_{\text{max}} = \text{Maximum allowed premium}$
  • $\varepsilon = \text{Rounding step (e.g. £0.01)}$

Step 1: Uplift price
$P_{\text{uplift}} = B \cdot (1 + \mu \cdot s)$

Step 2: Applying competitive logic
If no $C$: $P = P_{\text{uplift}}$
Else if $P_{\text{uplift}} \leq C$: $P = P_{\text{uplift}}$
Else if $s < \tau$: $P = C$
Else:
$\quad \pi = \min\left( \rho \cdot \frac{s - \tau}{1 - \tau}, \ \pi_{\text{max}} \right)$
$\quad P = C \cdot (1 + \pi)$

Step 3: Final price (rounded)
$P = \max(P, B)$
$P_{\text{final}} = \text{round}(P, \varepsilon)$

Algorithm Function

  1. Start with the baseline price for specified route.
  2. Multiply baseline slightly based on WTP.
  3. If the new price is cheaper than competitors leave it untouched.
  4. Leave new price cheaper than competitor when WTP isn't very high (>0.9).
  5. If WTP is very high, prices can rise above competitor pricing (bound by a price ceiling to avoid extreme values).
  6. Round to the nearest pence to avoid 1-p fractions.

Tech Stack

  • Backend: Python 3.12.2, FastAPI, Pydantic
  • Frontend:
  • Data Stores: PostgreSQL, Redis
  • Infrastructure: Docker
  • CI/CD: GitHub Actions
  • Monitoring: Grafana

Outcomes Data Analytics

Process

  • Utilising BigQuery for it's efficiency at larger dataset sizes (future-planning), I segmented the outcomes data where wtp_score < threshold and sale_made = 1. This gave me a clear indication of when conversion was achieved despite WTP being low.
SELECT * FROM pricing_outcomes
WHERE wtp_score < 0.5 AND sale_made = 1;
  • Next, to reduce noise and identify where conversion rates started to decline, I used a window function to calculate a rolling average conversion rate across increased wtp_score values.
SELECT
  wtp_score,
  sale_made,
  AVG(sale_made) OVER (
    ORDER BY wtp_score
    ROWS BETWEEN 10 PRECEDING AND CURRENT ROW
  ) AS rolling_conversion_rate
FROM
  pricing_outcomes
ORDER BY
  wtp_score;
  • This output gave me a clearer view of conversion rates where I identified a conversion drop off whereby rates were below 10% and remained consistently low from there on.

  • This provided me with a section in the data where conversions were likely nearly made but just missed.

  • Here, I implemented behavioural nudge triggers with the aim to recover these missed conversions

Examples included:

  • Social Proofs: "18 others are booking this right now"
  • Urgency Indicators: "Only a few tickets left at this price"
  • Value Add-Ons: "Includes free change flexibility"

Frontend Adapter Testing

  • To evaluate the impacts of the new approach, a further dataset was created simulating the predicted impacts of the nudge. Here, the nudges were shown at previous drop off points and were implemented into the outcome simulation by leading to a 0.2 increase in wtp_score values.

  • The results indicated an average 18% uplift in revenue when these frontend adapters were applied, converting significantly more users where sales were otherwise just missed.

About

Adaptive pricing system for profit maximisation featuring frontend adapters, user modelling, APIs, and model evaluation.

Topics

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages