I am working on a pricing optimization model for a product where the price depends on the competition as well as our costs. The current formulation of the model is:
logProfit = (fixed_effect + elasticity * (Price - competition_price)) + log(Price - costs)
Here, the first term models the log of sales volume as negatively proportional to the difference between our price and the competition's price, assuming a linear decrease in sales volume as our price exceeds the competition's. The second term, log(Price - costs)
, represents the log of profit margin.
This model works good in predicting and explaining volumes sold/lost. However, I’m encountering an issue with its constant derivative when integrated into an optimization process. The optimal solution always equates to -1/elasticity. To mitigate some aspects of this problem, I’ve introduced a quadratic penalty to the difference between the price and the competition price. This approach works well when competitors have low margins. Yet, a significant problem persists: at higher margins, the optimization yields very low prices compared to competition. This is because the theoretical optimal margin is absolute, constant, and equals -1/elasticity. While I could change the model, I’d prefer not to as it performs well in forecasting volumes and is easily explainable, and it took a lot of time to validate elasticities. I’m wondering if there’s a way to make the effect of elasticity effective just around competition prices and not starting from the costs. For instance, given that the costs are $1, the competitor’s price is \$ 2, and the elasticity is -2, I want the optimal solution to be around \$2 and not just \$ 1.5 because the optimal margin is 1/2. Using a penalty removes all elasticity effect as it significantly outweighs elasticity when margins are high. Conversely, when prices are low and the penalty is fixed with a low scale, it becomes non-existent, resulting in prices much higher than the competition. In short, it’s very complicated to adjust. Is there a modeling trick or approach that could help address this issue?