Using Game Theory to Find Optimal Strategies in a Competitive Market

In competitive markets, companies often face strategic dilemmas:

  • How much to produce?
  • How much to spend on advertising?
  • How should they respond to a rival’s pricing?

Game theory offers a powerful toolkit for analyzing such questions.
In this post, we’ll look at a simple but insightful example of Cournot competition — a duopoly model — and solve it using Python.


🎯 Problem Overview: Cournot Duopoly

Imagine two firms, Firm A and Firm B, competing by choosing the quantity of output to produce, $q_A$ and $q_B$, respectively.
The price in the market depends on the total quantity produced:

$$
P(Q) = a - bQ \quad \text{where} \quad Q = q_A + q_B
$$

Each firm aims to maximize profit:

$$
\pi_i = q_i \cdot P(Q) - c q_i
$$

Where:

  • $a$: maximum price consumers will pay when quantity is 0
  • $b$: how price drops with increased quantity
  • $c$: marginal cost of production

Each firm’s decision affects the other’s profit, so it’s a strategic setting — perfect for game theory!


🔢 Solving Cournot Equilibrium in Python

Let’s consider:

  • $a = 100$
  • $b = 1$
  • $c = 10$

We’ll solve for the Nash equilibrium: the quantities $q_A^*, q_B^*$ such that neither firm can increase profit by changing its own output unilaterally.

Here’s the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize

# Parameters
a = 100 # market max price
b = 1 # price sensitivity
c = 10 # marginal cost

# Profit function for Firm A given q_A and q_B
def profit_A(q_A, q_B):
Q = q_A + q_B
return q_A * (a - b * Q) - c * q_A

# Profit function for Firm B given q_B and q_A
def profit_B(q_B, q_A):
Q = q_A + q_B
return q_B * (a - b * Q) - c * q_B

# Best response function for Firm A
def best_response_A(q_B):
result = minimize(lambda q_A: -profit_A(q_A[0], q_B), x0=[10], bounds=[(0, a/b)])
return result.x[0]

# Best response function for Firm B
def best_response_B(q_A):
result = minimize(lambda q_B: -profit_B(q_B[0], q_A), x0=[10], bounds=[(0, a/b)])
return result.x[0]

# Find Nash equilibrium by iterating best responses
def find_nash_equilibrium(tol=1e-5, max_iter=1000):
q_A = 10.0
q_B = 10.0
for _ in range(max_iter):
new_q_A = best_response_A(q_B)
new_q_B = best_response_B(new_q_A)
if np.abs(new_q_A - q_A) < tol and np.abs(new_q_B - q_B) < tol:
break
q_A, q_B = new_q_A, new_q_B
return q_A, q_B

q_A_star, q_B_star = find_nash_equilibrium()
print(f"Nash Equilibrium:\n Firm A: {q_A_star:.2f} units\n Firm B: {q_B_star:.2f} units")
Nash Equilibrium:
  Firm A: 30.00 units
  Firm B: 30.00 units

🔍 Code Explanation

  • profit_A and profit_B define each firm’s profit as a function of its output and the rival’s output.
  • best_response_A and best_response_B find the profit-maximizing quantity given the other firm’s output using numerical optimization (scipy.optimize.minimize).
  • find_nash_equilibrium alternates between best responses until the output quantities converge — this gives us the Nash equilibrium.

📊 Visualizing Best Response Functions

To better understand the strategic interaction, let’s plot the best response functions:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
q_vals = np.linspace(0, 100, 100)
br_A = [best_response_A(q) for q in q_vals]
br_B = [best_response_B(q) for q in q_vals]

plt.figure(figsize=(10, 6))
plt.plot(q_vals, br_A, label="Firm A's Best Response", color='blue')
plt.plot(br_B, q_vals, label="Firm B's Best Response", color='green')
plt.plot(q_A_star, q_B_star, 'ro', label='Nash Equilibrium')
plt.xlabel('Firm B Quantity')
plt.ylabel('Firm A Quantity')
plt.title('Best Response Functions and Nash Equilibrium')
plt.legend()
plt.grid(True)
plt.show()


📈 Graph Explanation

  • The blue curve shows Firm A’s best response for every output level of Firm B.
  • The green curve shows Firm B’s best response for every output level of Firm A (we flip axes for visualization).
  • The red dot is where both best responses intersect — the Nash equilibrium.

This visualization makes it clear: each firm’s output is optimal given the other’s output at the intersection point.


✅ Conclusion

In this blog post, we’ve:

  • Modeled a Cournot duopoly using game theory.
  • Solved for the Nash equilibrium numerically with Python.
  • Visualized strategic interactions with best response curves.

Such models help economists and strategists understand competitive behaviors, predict outcomes, and guide decision-making in real markets.