Skip to content

Instantly share code, notes, and snippets.

@ethDreamer
Created December 21, 2023 14:48
Show Gist options
  • Save ethDreamer/aff25ca271710363d0aedc4bf796b33d to your computer and use it in GitHub Desktop.
Save ethDreamer/aff25ca271710363d0aedc4bf796b33d to your computer and use it in GitHub Desktop.
PID Ticket Pricing Simulation
#!/usr/bin/env python3
import matplotlib.pyplot as plt
# The fair market value of a ticket above which people sell and below which people buy
def V_function(block_num):
if block_num < 8000:
return 0.05
elif block_num < 16000:
return 0.08
elif block_num < 20000:
return 0.06
elif block_num < 30000:
return 0.10
else:
return 0.09
def PID_controller(Kp, Ki, Kd, setpoint, pv, previous_errors, delta_time, window_size=256):
error = pv - setpoint
previous_errors.append(error)
# Ensure only the most recent 'window_size' errors are kept
if len(previous_errors) > window_size:
previous_errors.pop(0)
integral = sum(previous_errors) * delta_time
derivative = (error - previous_errors[-2]) / delta_time if len(previous_errors) > 1 else 0
return 0.00001 * ((Kp * error) + (Ki * integral) + (Kd * derivative))
def simulate_market(O_t, V, Kp, Ki, Kd, t_0, t_min, max_ticket_change, num_blocks):
t_n = t_0
O_n = 0
previous_errors = []
history = []
V_values = []
for block in range(num_blocks):
V = V_function(block)
V_values.append(V)
# Calculate PID adjustment
pid_adjustment = PID_controller(Kp, Ki, Kd, O_t, O_n, previous_errors, 1)
# Adjust ticket price
t_n_plus_1 = max(t_min, t_n + pid_adjustment)
# Determine tickets bought or sold based on price
if t_n_plus_1 < V:
s_n = max_ticket_change
elif t_n_plus_1 > V:
s_n = -max_ticket_change
else:
s_n = 0
O_n += s_n - 1 # Account for one ticket burned per block
t_n = t_n_plus_1
history.append((block, t_n, O_n))
print(f"Block {block}: Price = {t_n:.4f} ETH, Outstanding Tickets = {O_n}")
return history, V_values
# PID Parameters
Kp = 0.0000001 # Proportional gain
Ki = 0.0000001 # Integral gain
Kd = 0.15 # Derivative gain
# Simulation parameters
O_t = 180000 # Target number of outstanding tickets
V = 0.05 # Market equillibrium ticket price
t_0 = 0.01 # Initial ticket price
t_min = 0.001 # Minimum ticket price
max_ticket_change = 128 # maximum number of tickets that can be purchased in a block
num_blocks = 50000
# Run the simulation
simulation_results, V_values = simulate_market(O_t, V, Kp, Ki, Kd, t_0, t_min, max_ticket_change, num_blocks)
# Plotting
blocks = [result[0] for result in simulation_results]
prices = [result[1] for result in simulation_results]
tickets = [result[2] for result in simulation_results]
fig, ax1 = plt.subplots(figsize=(12, 6))
ax1.plot(blocks, prices, label='Price per Ticket (ETH)', color='blue')
ax1.plot(blocks, V_values, label='Market Equilibrium Price', color='green', linestyle='--')
ax1.set_xlabel('Block Number')
ax1.set_ylabel('Price per Ticket (ETH)', color='blue')
ax1.tick_params(axis='y', labelcolor='blue')
ax1.set_ylim([0, 0.14])
ax2 = ax1.twinx()
ax2.plot(blocks, tickets, label='Outstanding Tickets', color='orange')
ax2.set_ylabel('Outstanding Tickets', color='orange')
ax2.tick_params(axis='y', labelcolor='orange')
ax2.axhline(y=O_t, color='red', linestyle='--', label='Target Outstanding Tickets')
#ax2.set_ylim([0, 30000])
plt.title('Simulation of Ticket Pricing, Outstanding Tickets, and Market Equilibrium Price Over Time')
fig.tight_layout()
ax1.legend(loc='upper left')
ax2.legend(loc='best')
plt.show()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment