chore: simple surge pricer

This commit is contained in:
2025-12-05 12:44:21 +01:00
parent 951b08d65e
commit a38fac9d2b
4 changed files with 52 additions and 8 deletions

View File

@@ -79,7 +79,7 @@ def get_price(mode: Literal['hotel', 'airline'], productId: str, sessionId: Opti
elasticity=None
)
optimal_price = float(product_price_row['predicted_price'].iloc[0])
optimal_price = float(product_price_row['optimal_price'].iloc[0]) # TODO: use optimal_price everywhere as aresult
# get elasticity if available
product_elasticity = None

View File

@@ -12,4 +12,5 @@ graphviz
python-dotenv>=1.0.0
requests>=2.31.0
typing-extensions>=4.8.0
pickle5>=0.0.11; python_version < '3.8'
pypickle
pymc

View File

@@ -292,12 +292,7 @@ async def get_products(
# filter by exact date_index if provided
# dateIndex from frontend is days from today, convert to days since epoch
if dateIndex is not None:
from datetime import datetime
epoch = datetime(1970, 1, 1)
today = datetime.now().replace(hour=0, minute=0, second=0, microsecond=0)
today_index = int((today - epoch).total_seconds() / 86400)
actual_date_index = today_index + dateIndex
query = query.eq('date_index', actual_date_index)
query = query.eq('date_index', dateIndex)
response = query.execute()
results = response.data

View File

@@ -46,3 +46,51 @@ class RandomPricer(PricingFunction):
if self.n_products is None:
self.n_products = len(state_space.demand)
return self.rng.uniform(self.price_min, self.price_max, size=self.n_products)
class SimpleSurgePricer(PricingFunction):
"""
Rule-based surge pricer adjusting prices via demand thresholds.
Logic: if demand > high_threshold -> surge, if demand < low_threshold -> discount.
Simpler and more controllable than curve fitting approaches.
"""
def __init__(self,
base_prices: np.ndarray = None,
high_threshold: int = 10,
low_threshold: int = 2,
surge_multiplier: float = 1.2,
discount_multiplier: float = 0.9):
self.base_prices = base_prices
self.high_threshold = high_threshold
self.low_threshold = low_threshold
self.surge_multiplier = surge_multiplier
self.discount_multiplier = discount_multiplier
def fit(self, historical_data: pd.DataFrame):
"""Extract base prices from product catalog or historical averages"""
if 'base_price' in historical_data.columns:
self.base_prices = historical_data['base_price'].values
elif 'price' in historical_data.columns:
self.base_prices = historical_data.groupby('productId')['price'].mean().values
else:
raise ValueError("historical_data must contain 'base_price' or 'price'")
return self
def predict(self, state_space) -> np.ndarray:
"""
Adjust prices based on current demand using surge rules.
state_space.demand: demand counts per product
state_space.prices: current prices (fallback if base_prices not set)
"""
current_prices = self.base_prices if self.base_prices is not None else state_space.prices
demand = state_space.demand
new_prices = current_prices.copy()
high_mask = demand >= self.high_threshold
new_prices[high_mask] *= self.surge_multiplier
low_mask = demand <= self.low_threshold
new_prices[low_mask] *= self.discount_multiplier
return new_prices