EDIT:
You could use the weight approach above but I also discovered much simpler one. If you are just fine assuming prices can be continuous (which from point of economic theory is fine 0.01c is really just practical limit in real life), then what you can do is skip the creation of deltas at the start:
import numpy as np
import matplotlib.pyplot as plt
buyers = [3.25 - 0.25*n for n in range(0, 11)]
sellers = [3.25 - 0.25*n for n in range(0, 11)]
Next what you can do is to replace random.choice()
with some distribution that has most mass at zero - like the exponential distribution. In python this can be done using random.exponential()
, the code would thus change only minimally, and will generate deltas that are closer to the actual valuation of the traders:
trading_prices = []
trading_counts = []
for _ in range(5):
buyers_still_in_market = list(range(len(buyers)))
sellers_still_in_market = list(range(len(sellers)))
transactions = []
for _ in range(1000):
# First, a random buyer offers to buy at some price below their number on
# their card
b = np.random.choice(buyers_still_in_market)
delta = np.random.exponential(400)
buyer_price = max(0, buyers[b] - abs(delta))
s = np.random.choice(sellers_still_in_market)
if buyer_price >= sellers[s]:
transactions.append((b, buyers[b], s, sellers[s], buyer_price))
buyers_still_in_market.remove(b)
sellers_still_in_market.remove(s)
trading_prices.append(buyer_price)
# Then, a random seller offers to sell at some price above their number on
# their card. #0.65 - for log normal
s = np.random.choice(sellers_still_in_market)
delta = np.random.exponential(400)
seller_price = sellers[s] + abs(delta)
b = np.random.choice(buyers_still_in_market)
if seller_price <= buyers[b]:
transactions.append((b, buyers[b], s, sellers[s], seller_price))
buyers_still_in_market.remove(b)
sellers_still_in_market.remove(s)
trading_prices.append(seller_price)
trading_counts.append(len(trading_prices))
print(len(transactions), "transactions")
plt.plot(list(range(len(trading_prices))), trading_prices)
plt.ylim(0, 4.00)
for x in trading_counts:
plt.axvline(x=x-1, ymin=0, ymax=4.0, color='red')
print("line drawn at x =", x)
plt.show()
print(trading_prices)
This new code produces results that are much less 'jagged'. Here are some examples, of behavior of price with the exponential distribution (possibly different types of distribution would yield better result but its beyond scope of SE answer to examine that). For example, here are 8 graphs generated when the prices depend on exponential distribution: