augmented bonding curve version
This commit is contained in:
parent
3f3996ce78
commit
ff4fd7f953
File diff suppressed because one or more lines are too long
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,58 @@
|
||||||
|
|
||||||
|
|
||||||
|
default_kappa= 2
|
||||||
|
default_exit_tax = .02
|
||||||
|
|
||||||
|
#value function for a given state (R,S)
|
||||||
|
def invariant(R,S,kappa=default_kappa):
|
||||||
|
|
||||||
|
return (S**kappa)/R
|
||||||
|
|
||||||
|
#given a value function (parameterized by kappa)
|
||||||
|
#and an invariant coeficient V0
|
||||||
|
#return Supply S as a function of reserve R
|
||||||
|
def reserve(S, V0, kappa=default_kappa):
|
||||||
|
|
||||||
|
return (S**kappa)/V0
|
||||||
|
|
||||||
|
#given a value function (parameterized by kappa)
|
||||||
|
#and an invariant coeficient V0
|
||||||
|
#return Supply S as a function of reserve R
|
||||||
|
def supply(R, V0, kappa=default_kappa):
|
||||||
|
return (V0*R)**(1/kappa)
|
||||||
|
|
||||||
|
#given a value function (parameterized by kappa)
|
||||||
|
#and an invariant coeficient V0
|
||||||
|
#return a spot price P as a function of reserve R
|
||||||
|
def spot_price(R, V0, kappa=default_kappa):
|
||||||
|
return kappa*R**((kappa-1)/kappa)/V0**(1/kappa)
|
||||||
|
|
||||||
|
#for a given state (R,S)
|
||||||
|
#given a value function (parameterized by kappa)
|
||||||
|
#and an invariant coeficient V0
|
||||||
|
#deposit deltaR to Mint deltaS
|
||||||
|
#with realized price deltaR/deltaS
|
||||||
|
def mint(deltaR, R,S, V0, kappa=default_kappa):
|
||||||
|
deltaS = (V0*(R+deltaR))**(1/kappa)-S
|
||||||
|
realized_price = deltaR/deltaS
|
||||||
|
return deltaS, realized_price
|
||||||
|
|
||||||
|
#for a given state (R,S)
|
||||||
|
#given a value function (parameterized by kappa)
|
||||||
|
#and an invariant coeficient V0
|
||||||
|
#burn deltaS to Withdraw deltaR
|
||||||
|
#with realized price deltaR/deltaS
|
||||||
|
def withdraw(deltaS, R,S, V0, kappa=default_kappa):
|
||||||
|
deltaR = R-((S-deltaS)**kappa)/V0
|
||||||
|
realized_price = deltaR/deltaS
|
||||||
|
return deltaR, realized_price
|
||||||
|
|
||||||
|
def withdraw_with_tax(deltaS, R,S, V0, exit_tax = default_exit_tax, kappa=default_kappa):
|
||||||
|
deltaR = R-((S-deltaS)**kappa)/V0
|
||||||
|
|
||||||
|
quantity_taxed = exit_tax*deltaR
|
||||||
|
quantity_recieved = (1-exit_tax)*deltaR
|
||||||
|
|
||||||
|
realized_price = quantity_recieved/deltaS
|
||||||
|
|
||||||
|
return quantity_recieved, quantity_taxed, realized_price
|
||||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
|
@ -1,6 +1,7 @@
|
||||||
import networkx as nx
|
import networkx as nx
|
||||||
from scipy.stats import expon, gamma
|
from scipy.stats import expon, gamma
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
from bonding_curve_eq import reserve, invariant,spot_price
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import matplotlib.colors as colors
|
import matplotlib.colors as colors
|
||||||
import matplotlib.cm as cmx
|
import matplotlib.cm as cmx
|
||||||
|
|
@ -12,13 +13,30 @@ def get_nodes_by_type(g, node_type_selection):
|
||||||
def get_edges_by_type(g, edge_type_selection):
|
def get_edges_by_type(g, edge_type_selection):
|
||||||
return [edge for edge in g.edges if g.edges[edge]['type']== edge_type_selection ]
|
return [edge for edge in g.edges if g.edges[edge]['type']== edge_type_selection ]
|
||||||
|
|
||||||
def total_funds_given_total_supply(total_supply):
|
default_theta = .25
|
||||||
|
default_initial_price = .1
|
||||||
|
default_kappa = 2
|
||||||
|
|
||||||
#can put any bonding curve invariant here for initializatio!
|
def total_funds_given_total_supply(total_supply, theta = default_theta, initial_price = default_initial_price):
|
||||||
total_funds = total_supply**2/1000
|
|
||||||
|
S = total_supply
|
||||||
|
total_funds = theta*reserve(S, S*initial_price)
|
||||||
|
|
||||||
return total_funds
|
return total_funds
|
||||||
|
|
||||||
|
def initialize_bonding_curve(initial_supply, initial_price = default_initial_price, kappa =default_kappa, theta = default_theta):
|
||||||
|
|
||||||
|
S = initial_supply
|
||||||
|
R = reserve(S, S*initial_price)*(1-theta)
|
||||||
|
|
||||||
|
V0 = invariant(R,S,kappa)
|
||||||
|
|
||||||
|
initial_reserve = R
|
||||||
|
|
||||||
|
hatch_price = spot_price(R, V0, kappa)
|
||||||
|
|
||||||
|
return initial_reserve, V0, hatch_price
|
||||||
|
|
||||||
#maximum share of funds a proposal can take
|
#maximum share of funds a proposal can take
|
||||||
default_beta = .2 #later we should set this to be param so we can sweep it
|
default_beta = .2 #later we should set this to be param so we can sweep it
|
||||||
# tuning param for the trigger function
|
# tuning param for the trigger function
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,554 @@
|
||||||
|
import numpy as np
|
||||||
|
from conviction_helpers import get_nodes_by_type, get_edges_by_type, social_affinity_booster
|
||||||
|
from bonding_curve_eq import reserve, spot_price, withdraw_with_tax
|
||||||
|
#import networkx as nx
|
||||||
|
from scipy.stats import expon, gamma
|
||||||
|
|
||||||
|
|
||||||
|
#functions for partial state update block 1
|
||||||
|
|
||||||
|
#Driving processes: arrival of participants, proposals and funds
|
||||||
|
##-----------------------------------------
|
||||||
|
def gen_new_participant(network, new_participant_holdings):
|
||||||
|
|
||||||
|
i = len([node for node in network.nodes])
|
||||||
|
|
||||||
|
network.add_node(i)
|
||||||
|
network.nodes[i]['type']="participant"
|
||||||
|
|
||||||
|
s_rv = np.random.rand()
|
||||||
|
network.nodes[i]['sentiment'] = s_rv
|
||||||
|
network.nodes[i]['holdings']=new_participant_holdings
|
||||||
|
|
||||||
|
for j in get_nodes_by_type(network, 'proposal'):
|
||||||
|
network.add_edge(i, j)
|
||||||
|
|
||||||
|
rv = np.random.rand()
|
||||||
|
a_rv = 1-4*(1-rv)*rv #polarized distribution
|
||||||
|
network.edges[(i, j)]['affinity'] = a_rv
|
||||||
|
network.edges[(i,j)]['tokens'] = a_rv*network.nodes[i]['holdings']
|
||||||
|
network.edges[(i, j)]['conviction'] = 0
|
||||||
|
network.edges[(i,j)]['type'] = 'support'
|
||||||
|
|
||||||
|
return network
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def gen_new_proposal(network, funds, supply, trigger_func, scale_factor = 1.0/100):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
j = len([node for node in network.nodes])
|
||||||
|
network.add_node(j)
|
||||||
|
network.nodes[j]['type']="proposal"
|
||||||
|
|
||||||
|
network.nodes[j]['conviction']=0
|
||||||
|
network.nodes[j]['status']='candidate'
|
||||||
|
network.nodes[j]['age']=0
|
||||||
|
|
||||||
|
rescale = funds*scale_factor
|
||||||
|
r_rv = gamma.rvs(3,loc=0.001, scale=rescale)
|
||||||
|
network.node[j]['funds_requested'] = r_rv
|
||||||
|
|
||||||
|
network.nodes[j]['trigger']= trigger_func(r_rv, funds, supply)
|
||||||
|
|
||||||
|
participants = get_nodes_by_type(network, 'participant')
|
||||||
|
proposing_participant = np.random.choice(participants)
|
||||||
|
|
||||||
|
for i in participants:
|
||||||
|
network.add_edge(i, j)
|
||||||
|
if i==proposing_participant:
|
||||||
|
network.edges[(i, j)]['affinity']=1
|
||||||
|
else:
|
||||||
|
rv = np.random.rand()
|
||||||
|
a_rv = 1-4*(1-rv)*rv #polarized distribution
|
||||||
|
network.edges[(i, j)]['affinity'] = a_rv
|
||||||
|
|
||||||
|
network.edges[(i, j)]['conviction'] = 0
|
||||||
|
network.edges[(i,j)]['tokens'] = 0
|
||||||
|
network.edges[(i,j)]['type'] = 'support'
|
||||||
|
|
||||||
|
return network
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def driving_process(params, step, sL, s):
|
||||||
|
|
||||||
|
#placeholder plumbing for random processes
|
||||||
|
arrival_rate = 10/s['sentiment']
|
||||||
|
rv1 = np.random.rand()
|
||||||
|
new_participant = bool(rv1<1/arrival_rate)
|
||||||
|
supporters = get_edges_by_type(s['network'], 'support')
|
||||||
|
if new_participant:
|
||||||
|
h_rv = expon.rvs(loc=0.0, scale=1000)
|
||||||
|
new_participant_holdings = h_rv
|
||||||
|
else:
|
||||||
|
new_participant_holdings = 0
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
affinities = [network.edges[e]['affinity'] for e in supporters ]
|
||||||
|
median_affinity = np.median(affinities)
|
||||||
|
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
fund_requests = [network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='candidate' ]
|
||||||
|
|
||||||
|
funds = s['funds']
|
||||||
|
total_funds_requested = np.sum(fund_requests)
|
||||||
|
|
||||||
|
proposal_rate = 10/median_affinity * total_funds_requested/funds
|
||||||
|
rv2 = np.random.rand()
|
||||||
|
new_proposal = bool(rv2<1/proposal_rate)
|
||||||
|
|
||||||
|
sentiment = s['sentiment']
|
||||||
|
funds = s['funds']
|
||||||
|
scale_factor = funds*sentiment**2/10000
|
||||||
|
|
||||||
|
#this shouldn't happen but expon is throwing domain errors
|
||||||
|
if sentiment>.4:
|
||||||
|
funds_arrival = expon.rvs(loc = 0, scale = scale_factor )
|
||||||
|
else:
|
||||||
|
funds_arrival = 0
|
||||||
|
|
||||||
|
return({'new_participant':new_participant,
|
||||||
|
'new_participant_holdings':new_participant_holdings,
|
||||||
|
'new_proposal':new_proposal,
|
||||||
|
'funds_arrival':funds_arrival})
|
||||||
|
|
||||||
|
|
||||||
|
#Mechanisms for updating the state based on driving processes
|
||||||
|
##---
|
||||||
|
def update_network(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
funds = s['funds']
|
||||||
|
supply = s['supply']
|
||||||
|
trigger_func = params['trigger_func']
|
||||||
|
#print(trigger_func)
|
||||||
|
|
||||||
|
new_participant = _input['new_participant'] #T/F
|
||||||
|
new_proposal = _input['new_proposal'] #T/F
|
||||||
|
|
||||||
|
if new_participant:
|
||||||
|
new_participant_holdings = _input['new_participant_holdings']
|
||||||
|
network = gen_new_participant(network, new_participant_holdings)
|
||||||
|
|
||||||
|
if new_proposal:
|
||||||
|
network= gen_new_proposal(network,funds,supply,trigger_func )
|
||||||
|
|
||||||
|
#update age of the existing proposals
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
|
||||||
|
for j in proposals:
|
||||||
|
network.nodes[j]['age'] = network.nodes[j]['age']+1
|
||||||
|
if network.nodes[j]['status'] == 'candidate':
|
||||||
|
requested = network.nodes[j]['funds_requested']
|
||||||
|
network.nodes[j]['trigger'] = trigger_func(requested, funds, supply)
|
||||||
|
else:
|
||||||
|
network.nodes[j]['trigger'] = np.nan
|
||||||
|
|
||||||
|
key = 'network'
|
||||||
|
value = network
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def increment_funds(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
funds = s['funds']
|
||||||
|
funds_arrival = _input['funds_arrival']
|
||||||
|
|
||||||
|
#increment funds
|
||||||
|
funds = funds + funds_arrival
|
||||||
|
|
||||||
|
key = 'funds'
|
||||||
|
value = funds
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def increment_supply(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
supply = s['supply']
|
||||||
|
supply_arrival = _input['new_participant_holdings']
|
||||||
|
|
||||||
|
#increment funds
|
||||||
|
supply = supply + supply_arrival
|
||||||
|
|
||||||
|
key = 'supply'
|
||||||
|
value = supply
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
#functions for partial state update block 2
|
||||||
|
|
||||||
|
#Driving processes: completion of previously funded proposals
|
||||||
|
##-----------------------------------------
|
||||||
|
|
||||||
|
def check_progress(params, step, sL, s):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
|
||||||
|
completed = []
|
||||||
|
failed = []
|
||||||
|
for j in proposals:
|
||||||
|
if network.nodes[j]['status'] == 'active':
|
||||||
|
grant_size = network.nodes[j]['funds_requested']
|
||||||
|
base_completion_rate=params['base_completion_rate']
|
||||||
|
likelihood = 1.0/(base_completion_rate+np.log(grant_size))
|
||||||
|
|
||||||
|
base_failure_rate = params['base_failure_rate']
|
||||||
|
failure_rate = 1.0/(base_failure_rate+np.log(grant_size))
|
||||||
|
if np.random.rand() < likelihood:
|
||||||
|
completed.append(j)
|
||||||
|
elif np.random.rand() < failure_rate:
|
||||||
|
failed.append(j)
|
||||||
|
|
||||||
|
return({'completed':completed, 'failed':failed})
|
||||||
|
|
||||||
|
|
||||||
|
#Mechanisms for updating the state based on check progress
|
||||||
|
##---
|
||||||
|
def complete_proposal(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
participants = get_nodes_by_type(network, 'participant')
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
competitors = get_edges_by_type(network, 'conflict')
|
||||||
|
|
||||||
|
completed = _input['completed']
|
||||||
|
for j in completed:
|
||||||
|
network.nodes[j]['status']='completed'
|
||||||
|
|
||||||
|
for c in proposals:
|
||||||
|
if (j,c) in competitors:
|
||||||
|
conflict = network.edges[(j,c)]['conflict']
|
||||||
|
for i in participants:
|
||||||
|
network.edges[(i,c)]['affinity'] = network.edges[(i,c)]['affinity'] *(1-conflict)
|
||||||
|
|
||||||
|
for i in participants:
|
||||||
|
force = network.edges[(i,j)]['affinity']
|
||||||
|
sentiment = network.node[i]['sentiment']
|
||||||
|
network.node[i]['sentiment'] = get_sentimental(sentiment, force, decay=0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
failed = _input['failed']
|
||||||
|
for j in failed:
|
||||||
|
network.nodes[j]['status']='failed'
|
||||||
|
for i in participants:
|
||||||
|
force = -network.edges[(i,j)]['affinity']
|
||||||
|
sentiment = network.node[i]['sentiment']
|
||||||
|
network.node[i]['sentiment'] = get_sentimental(sentiment, force, decay=0)
|
||||||
|
|
||||||
|
key = 'network'
|
||||||
|
value = network
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def update_sentiment_on_completion(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
completed = _input['completed']
|
||||||
|
failed = _input['failed']
|
||||||
|
|
||||||
|
grants_outstanding = np.sum([network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='active'])
|
||||||
|
|
||||||
|
grants_completed = np.sum([network.nodes[j]['funds_requested'] for j in completed])
|
||||||
|
grants_failed = np.sum([network.nodes[j]['funds_requested'] for j in failed])
|
||||||
|
|
||||||
|
sentiment = s['sentiment']
|
||||||
|
|
||||||
|
if grants_outstanding>0:
|
||||||
|
force = (grants_completed-grants_failed)/grants_outstanding
|
||||||
|
else:
|
||||||
|
force=1
|
||||||
|
mu = params['sentiment_decay']
|
||||||
|
if (force >=0) and (force <=1):
|
||||||
|
sentiment = get_sentimental(sentiment, force, mu)
|
||||||
|
else:
|
||||||
|
sentiment = get_sentimental(sentiment, 0, mu)
|
||||||
|
|
||||||
|
|
||||||
|
key = 'sentiment'
|
||||||
|
value = sentiment
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def get_sentimental(sentiment, force, decay=0):
|
||||||
|
mu = decay
|
||||||
|
sentiment = sentiment*(1-mu) + force
|
||||||
|
|
||||||
|
if sentiment > 1:
|
||||||
|
sentiment = 1
|
||||||
|
|
||||||
|
return sentiment
|
||||||
|
|
||||||
|
#functions for partial state update block 3
|
||||||
|
|
||||||
|
#Decision processes: trigger function policy
|
||||||
|
##-----------------------------------------
|
||||||
|
|
||||||
|
def trigger_function(params, step, sL, s):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
funds = s['funds']
|
||||||
|
supply = s['supply']
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
tmin = params['tmin']
|
||||||
|
trigger_func = params['trigger_func']
|
||||||
|
|
||||||
|
accepted = []
|
||||||
|
triggers = {}
|
||||||
|
for j in proposals:
|
||||||
|
if network.nodes[j]['status'] == 'candidate':
|
||||||
|
requested = network.nodes[j]['funds_requested']
|
||||||
|
age = network.nodes[j]['age']
|
||||||
|
threshold = trigger_func(requested, funds, supply)
|
||||||
|
if age > tmin:
|
||||||
|
conviction = network.nodes[j]['conviction']
|
||||||
|
if conviction >threshold:
|
||||||
|
accepted.append(j)
|
||||||
|
else:
|
||||||
|
threshold = np.nan
|
||||||
|
|
||||||
|
triggers[j] = threshold
|
||||||
|
|
||||||
|
return({'accepted':accepted, 'triggers':triggers})
|
||||||
|
|
||||||
|
#functions for partial state update block 3
|
||||||
|
|
||||||
|
#state updates
|
||||||
|
##---
|
||||||
|
|
||||||
|
def decrement_funds(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
funds = s['funds']
|
||||||
|
network = s['network']
|
||||||
|
accepted = _input['accepted']
|
||||||
|
|
||||||
|
#decrement funds
|
||||||
|
for j in accepted:
|
||||||
|
funds = funds - network.nodes[j]['funds_requested']
|
||||||
|
|
||||||
|
key = 'funds'
|
||||||
|
value = funds
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def update_proposals(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
accepted = _input['accepted']
|
||||||
|
triggers = _input['triggers']
|
||||||
|
participants = get_nodes_by_type(network, 'participant')
|
||||||
|
proposals = get_nodes_by_type(network, 'proposals')
|
||||||
|
sensitivity = params['sensitivity']
|
||||||
|
|
||||||
|
for j in proposals:
|
||||||
|
network.nodes[j]['trigger'] = triggers[j]
|
||||||
|
|
||||||
|
#bookkeeping conviction and participant sentiment
|
||||||
|
for j in accepted:
|
||||||
|
network.nodes[j]['status']='active'
|
||||||
|
network.nodes[j]['conviction']=np.nan
|
||||||
|
#change status to active
|
||||||
|
for i in participants:
|
||||||
|
|
||||||
|
#operating on edge = (i,j)
|
||||||
|
#reset tokens assigned to other candidates
|
||||||
|
network.edges[(i,j)]['tokens']=0
|
||||||
|
network.edges[(i,j)]['conviction'] = np.nan
|
||||||
|
|
||||||
|
#update participants sentiments (positive or negative)
|
||||||
|
affinities = [network.edges[(i,p)]['affinity'] for p in proposals if not(p in accepted)]
|
||||||
|
if len(affinities)>1:
|
||||||
|
max_affinity = np.max(affinities)
|
||||||
|
force = network.edges[(i,j)]['affinity']-sensitivity*max_affinity
|
||||||
|
else:
|
||||||
|
force = 0
|
||||||
|
|
||||||
|
#based on what their affinities to the accepted proposals
|
||||||
|
network.nodes[i]['sentiment'] = get_sentimental(network.nodes[i]['sentiment'], force, False)
|
||||||
|
|
||||||
|
|
||||||
|
key = 'network'
|
||||||
|
value = network
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def update_sentiment_on_release(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
accepted = _input['accepted']
|
||||||
|
|
||||||
|
proposals_outstanding = np.sum([network.nodes[j]['funds_requested'] for j in proposals if network.nodes[j]['status']=='candidate'])
|
||||||
|
|
||||||
|
proposals_accepted = np.sum([network.nodes[j]['funds_requested'] for j in accepted])
|
||||||
|
|
||||||
|
sentiment = s['sentiment']
|
||||||
|
force = proposals_accepted/proposals_outstanding
|
||||||
|
if (force >=0) and (force <=1):
|
||||||
|
sentiment = get_sentimental(sentiment, force, False)
|
||||||
|
else:
|
||||||
|
sentiment = get_sentimental(sentiment, 0, False)
|
||||||
|
|
||||||
|
key = 'sentiment'
|
||||||
|
value = sentiment
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
|
||||||
|
#functions for partial state update block 4
|
||||||
|
|
||||||
|
#Decision processes: trigger function policy
|
||||||
|
##---
|
||||||
|
def participants_decisions(params, step, sL, s):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
participants = get_nodes_by_type(network, 'participant')
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
candidates = [j for j in proposals if network.nodes[j]['status']=='candidate']
|
||||||
|
sensitivity = params['sensitivity']
|
||||||
|
|
||||||
|
gain = .01
|
||||||
|
delta_holdings={}
|
||||||
|
proposals_supported ={}
|
||||||
|
for i in participants:
|
||||||
|
|
||||||
|
engagement_rate = .3*network.nodes[i]['sentiment']
|
||||||
|
if np.random.rand()<engagement_rate:
|
||||||
|
|
||||||
|
force = network.nodes[i]['sentiment']-sensitivity
|
||||||
|
delta_holdings[i] = network.nodes[i]['holdings']*gain*force
|
||||||
|
|
||||||
|
support = []
|
||||||
|
for j in candidates:
|
||||||
|
affinity = network.edges[(i, j)]['affinity']*.5+.5*social_affinity_booster(network, j, i)
|
||||||
|
cutoff = sensitivity*np.max([network.edges[(i,p)]['affinity'] for p in candidates])
|
||||||
|
if cutoff <.5:
|
||||||
|
cutoff = .5
|
||||||
|
|
||||||
|
if affinity > cutoff:
|
||||||
|
support.append(j)
|
||||||
|
|
||||||
|
proposals_supported[i] = support
|
||||||
|
else:
|
||||||
|
delta_holdings[i] = 0
|
||||||
|
proposals_supported[i] = [j for j in candidates if network.edges[(i,j)]['tokens']>0 ]
|
||||||
|
|
||||||
|
return({'delta_holdings':delta_holdings, 'proposals_supported':proposals_supported})
|
||||||
|
|
||||||
|
#functions for partial state update block 4
|
||||||
|
|
||||||
|
#state updates
|
||||||
|
##---
|
||||||
|
|
||||||
|
def update_tokens(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
network = s['network']
|
||||||
|
delta_holdings = _input['delta_holdings']
|
||||||
|
proposals = get_nodes_by_type(network, 'proposal')
|
||||||
|
candidates = [j for j in proposals if network.nodes[j]['status']=='candidate']
|
||||||
|
proposals_supported = _input['proposals_supported']
|
||||||
|
participants = get_nodes_by_type(network, 'participant')
|
||||||
|
alpha = params['alpha']
|
||||||
|
min_support = params['min_supp']
|
||||||
|
|
||||||
|
for i in participants:
|
||||||
|
network.nodes[i]['holdings'] = network.nodes[i]['holdings']+delta_holdings[i]
|
||||||
|
supported = proposals_supported[i]
|
||||||
|
total_affinity = np.sum([ network.edges[(i, j)]['affinity'] for j in supported])
|
||||||
|
for j in candidates:
|
||||||
|
if j in supported:
|
||||||
|
normalized_affinity = network.edges[(i, j)]['affinity']/total_affinity
|
||||||
|
network.edges[(i, j)]['tokens'] = normalized_affinity*network.nodes[i]['holdings']
|
||||||
|
else:
|
||||||
|
network.edges[(i, j)]['tokens'] = 0
|
||||||
|
|
||||||
|
prior_conviction = network.edges[(i, j)]['conviction']
|
||||||
|
current_tokens = network.edges[(i, j)]['tokens']
|
||||||
|
network.edges[(i, j)]['conviction'] =current_tokens+alpha*prior_conviction
|
||||||
|
|
||||||
|
for j in candidates:
|
||||||
|
network.nodes[j]['conviction'] = np.sum([ network.edges[(i, j)]['conviction'] for i in participants])
|
||||||
|
total_tokens = np.sum([network.edges[(i, j)]['tokens'] for i in participants ])
|
||||||
|
if total_tokens < min_support:
|
||||||
|
network.nodes[j]['status'] = 'killed'
|
||||||
|
|
||||||
|
key = 'network'
|
||||||
|
value = network
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
#organizing the bonding curve into a nested state would
|
||||||
|
#make this code more efficient, lots of duplicated logic here
|
||||||
|
|
||||||
|
def update_supply(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
supply = s['supply']
|
||||||
|
delta_holdings = _input['delta_holdings']
|
||||||
|
delta_supply = np.sum([v for v in delta_holdings.values()])
|
||||||
|
|
||||||
|
supply = supply + delta_supply
|
||||||
|
|
||||||
|
key = 'supply'
|
||||||
|
value = supply
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def update_reserve(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
supply = s['supply']
|
||||||
|
delta_holdings = _input['delta_holdings']
|
||||||
|
delta_supply = np.sum([v for v in delta_holdings.values()])
|
||||||
|
supply = supply + delta_supply
|
||||||
|
|
||||||
|
kappa = params['kappa']
|
||||||
|
V0 = params['invariant']
|
||||||
|
|
||||||
|
R = reserve(supply, V0, kappa)
|
||||||
|
|
||||||
|
key = 'reserve'
|
||||||
|
value = R
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def update_price(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
supply = s['supply']
|
||||||
|
delta_holdings = _input['delta_holdings']
|
||||||
|
delta_supply = np.sum([v for v in delta_holdings.values()])
|
||||||
|
supply = supply + delta_supply
|
||||||
|
|
||||||
|
kappa = params['kappa']
|
||||||
|
V0 = params['invariant']
|
||||||
|
|
||||||
|
R = reserve(supply, V0, kappa)
|
||||||
|
price = spot_price(R, V0, kappa)
|
||||||
|
|
||||||
|
key = 'spot_price'
|
||||||
|
value = price
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
|
|
||||||
|
def update_funds(params, step, sL, s, _input):
|
||||||
|
|
||||||
|
delta_holdings = _input['delta_holdings']
|
||||||
|
S = s['supply']
|
||||||
|
R = s['reserve']
|
||||||
|
V0=params['invariant']
|
||||||
|
kappa = params['kappa']
|
||||||
|
exit_tax = params['tax_rate']
|
||||||
|
#to avoid overestimating taxes well treat all withdraw before mint
|
||||||
|
wDS = np.sum([v for v in delta_holdings.values() if v<0])
|
||||||
|
|
||||||
|
_,tax, _ = withdraw_with_tax(wDS, R,S, V0, exit_tax, kappa)
|
||||||
|
|
||||||
|
funds = s['funds']+ tax
|
||||||
|
|
||||||
|
key = 'funds'
|
||||||
|
value = funds
|
||||||
|
|
||||||
|
return (key, value)
|
||||||
Loading…
Reference in New Issue