darkie.py 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107
  1. from core.utils import *
  2. from core.strategy import *
  3. class Darkie():
  4. def __init__(self, airdrop, initial_stake=None, vesting=[], hp=False, commit=True, epoch_len=100, strategy=None, apy_window=EPOCH_LENGTH):
  5. self.vesting = [0] + vesting
  6. self.stake = (Num(airdrop) if hp else airdrop)
  7. self.initial_stake = [self.stake] # for debugging purpose
  8. self.finalized_stake = (Num(airdrop) if hp else airdrop)
  9. self.Sigma = None
  10. self.feedback = None
  11. self.f = None
  12. self.won=False
  13. self.epoch_len=epoch_len # epoch length during which the stake is static
  14. self.strategy = strategy if strategy is not None else Strategy(self.epoch_len)
  15. self.apy_window = apy_window
  16. self.slot = 0
  17. def clone(self):
  18. return Darkie(self.finalized_stake)
  19. '''
  20. def apy(self):
  21. staked_tokens = self.staked_tokens()
  22. apy = (Num(self.stake) - staked_tokens) / staked_tokens if self.stake>0 else 0
  23. #print('stake: {}, staked_tokens: {}'.format(self.stake, staked_tokens))
  24. return Num(apy)
  25. '''
  26. '''
  27. @rewards: array of reward per epoch
  28. '''
  29. def apy(self, rewards):
  30. avg_apy = 0
  31. for idx, reward in enumerate(rewards):
  32. #print('idx: {} of {}, staked tokens: {}, initial stake: {}'.format(idx, len(rewards), len(self.strategy.staked_tokens_ratio), len(self.initial_stake)))
  33. current_epoch_staked_tokens = (Num(self.strategy.staked_tokens_ratio[idx-1]) * Num(self.initial_stake[idx-1]))
  34. avg_apy += (Num(reward) / current_epoch_staked_tokens) if current_epoch_staked_tokens!=0 else 0
  35. return avg_apy/len(rewards) if len(rewards)>0 else 0
  36. def staked_tokens(self):
  37. '''
  38. the ratio of the staked tokens during the epochs
  39. of the total running time
  40. '''
  41. return Num(self.initial_stake[0])*self.staked_tokens_ratio()
  42. def staked_tokens_ratio(self):
  43. staked_ratio = Num(sum(self.strategy.staked_tokens_ratio)/len(self.strategy.staked_tokens_ratio))
  44. #print('type: {}, ratio: {}'.format(self.strategy.type, staked_ratio))
  45. #TODO (fix)
  46. assert(staked_ratio <= 100 and staked_ratio >=0)
  47. return staked_ratio
  48. def apy_percentage(self, rewards):
  49. return Num(self.apy(rewards)*100)
  50. def set_sigma_feedback(self, sigma, feedback, f, count, hp=True):
  51. self.Sigma = (Num(sigma) if hp else sigma)
  52. self.feedback = (Num(feedback) if hp else feedback)
  53. self.f = (Num(f) if hp else f)
  54. #self.initial_stake += [self.finalized_stake]
  55. self.slot = count
  56. def run(self, rewards, hp=True):
  57. k=N_TERM
  58. def target(tune_parameter, stake):
  59. x = (Num(1) if hp else 1) - (Num(tune_parameter) if hp else tune_parameter)
  60. c = (x.ln() if type(x)==Num else math.log(x))
  61. sigmas = [ c/((self.Sigma+EPSILON)**i) * ( ((L_HP if hp else L)/fact(i)) ) for i in range(1, k+1) ]
  62. scaled_target = approx_target_in_zk(sigmas, Num(stake)) #+ (BASE_L_HP if hp else BASE_L)
  63. return scaled_target
  64. if self.slot % EPOCH_LENGTH==0 and self.slot > EPOCH_LENGTH:
  65. self.initial_stake +=[self.finalized_stake]
  66. self.strategy.set_ratio(self.slot, self.apy_percentage(rewards))
  67. T = target(self.f, self.strategy.staked_value(self.finalized_stake))
  68. self.won = lottery(T, hp)
  69. def update_vesting(self):
  70. if self.slot >= len(self.vesting):
  71. return 0
  72. slot2vest_index = int(self.slot/28800.0)
  73. slot2vest_prev_index = int((self.slot-1)/28800.0)
  74. slot2vest_index_shifted = slot2vest_index - 1 # by end of month
  75. slot2vest_prev_index_shifted = slot2vest_prev_index - 1 # by end of month
  76. vesting_value = float(self.vesting[slot2vest_index_shifted]) - self.vesting[slot2vest_prev_index_shifted]
  77. self.stake+= vesting_value
  78. return vesting_value
  79. def update_stake(self, reward):
  80. if self.won:
  81. self.stake+=reward
  82. def finalize_stake(self):
  83. if self.won:
  84. self.finalized_stake = self.stake
  85. else:
  86. self.stake = self.finalized_stake
  87. def log_state_gain(self):
  88. # darkie started with self.initial_stake, self.initial_stake/self.Sigma percent
  89. # over the course of self.slot
  90. # current stake is self.stake, self.stake/self.Sigma percent
  91. pass