import math from core.utils import * class Strategy(object): ''' @type epoch_len: int @epoch_len: epoch length @type airdrop_period: int @param airdrop_period: strategy grace period, during which strategy is HODL only ''' def __init__(self, epoch_len=0, airdrop_period=HEADSTART_AIRDROP): self.epoch_len = epoch_len self.airdrop_period=HEADSTART_AIRDROP self.staked_tokens_ratio = [1] self.target = TARGET_APR self.annual_return = [0] self.type = 'base' def set_ratio(self, slot, apr): return def staked_value(self, stake): return (self.staked_tokens_ratio[-1])*(stake) class Hodler(Strategy): def __init__(self, epoch_len): super().__init__(epoch_len) self.type = 'hodler' def set_ratio(self, slot, apr): if slot < HEADSTART_AIRDROP: self.staked_tokens_ratio += [1] self.annual_return +=[apr] return if slot%self.epoch_len==0: self.staked_tokens_ratio += [1] self.annual_return +=[apr] class LinearStrategy(Strategy): def __init__(self, epoch_len=0): super().__init__(epoch_len) self.type = 'linear' def set_ratio(self, slot, apr): if slot < HEADSTART_AIRDROP: self.staked_tokens_ratio += [1] self.annual_return +=[apr] return if slot%self.epoch_len==0: sr = (apr)/(self.target) if sr>1: sr = 1 elif sr<0: sr = 0 self.staked_tokens_ratio += [sr] self.annual_return += [apr] class LogarithmicStrategy(Strategy): def __init__(self, epoch_len=0): super().__init__(epoch_len) self.type = 'logarithmic' def set_ratio(self, slot, apr): if slot < HEADSTART_AIRDROP: self.staked_tokens_ratio += [1] self.annual_return +=[apr] return if slot%self.epoch_len==0: apr_ratio = math.fabs(apr/self.target) fn = lambda x: (math.log(x, 10)+1)/2 * 0.95 + 0.05 sr = (fn(apr_ratio) if apr_ratio != 0 else 0) if sr>1: sr = 1 elif sr<0: sr = 0 self.staked_tokens_ratio += [sr] self.annual_return += [apr] class SigmoidStrategy(Strategy): def __init__(self, epoch_len=0): super().__init__(epoch_len) self.type = 'sigmoid' def set_ratio(self, slot, apr): if slot < HEADSTART_AIRDROP: self.staked_tokens_ratio += [1] self.annual_return +=[apr] return if slot%self.epoch_len==0: apr_ratio = apr/self.target apr_ratio = max(apr_ratio, 0) sr = (2/(1+math.pow(math.e, -4*apr_ratio))-1) if sr>1: sr = 1 elif sr<0: sr = 0 self.staked_tokens_ratio += [sr] self.annual_return += [apr] def random_strategy(epoch_length=EPOCH_LENGTH): rnd = random.random() if rnd < 0.25: return Hodler(epoch_length) elif rnd < 0.5 and rnd >= 0.25: return LinearStrategy(epoch_length) elif rnd < 0.75 and rnd >= 0.5: return LogarithmicStrategy(epoch_length) else: return SigmoidStrategy(epoch_length) class Tip(object): def __init__(self): self.type = 'tip' def get_tip(self, last_reward, apr, size, last_tip): return 0 class ZeroTip(Tip): def __init__(self): super().__init__() self.type = 'zero' def get_tip(self, last_reward, apr, size, last_tip): return 0 class MilthOfReward(Tip): def __init__(self): super().__init__() self.type = '1000th' def get_tip(self, last_reward, apr, size, last_tip): return last_reward/1000 class RewardApr(Tip): def __init__(self): super().__init__() self.type = 'reward_apr' def get_tip(self, last_reward, apr, size, last_tip): apr_relu = max(apr, 0) apr_relu = min(apr_relu, 1) return last_reward*apr_relu class MilthCCApr(Tip): def __init__(self): super().__init__() self.type = "cc_apr_1000" def get_tip(self, last_reward, apr, size, last_tip): return size/MAX_BLOCK_SIZE/1000 class Conservative(Tip): def __init__(self): super().__init__() self.type = "cc_apr_1000" def get_tip(self, last_reward, apr, size, last_tip): return last_tip class Generous(Tip): def __init__(self): super().__init__() self.type = "cc_apr_1000" def get_tip(self, last_reward, apr, size, last_tip): return last_tip*2 def random_tip_strategy(): return random.choice([ZeroTip(), RewardApr(), MilthOfReward(), MilthCCApr(), Conservative(), Generous()])