Created
December 21, 2023 14:48
-
-
Save ethDreamer/aff25ca271710363d0aedc4bf796b33d to your computer and use it in GitHub Desktop.
PID Ticket Pricing Simulation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/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