def test_should_adjust_amounts_based_on_max_source_amount( self, token1, token2, token3, token4): # given conversion1 = Conversion(token1, token2, Ray.from_number(2.0), Wad.from_number(10000), 'met1') conversion2 = Conversion(token2, token3, Ray.from_number(1.6), Wad.from_number(10000), 'met2') conversion3 = Conversion(token3, token4, Ray.from_number(1.2), Wad.from_number(100), 'met3') conversion4 = Conversion(token4, token1, Ray.from_number(1.1), Wad.from_number(10000), 'met4') conversions = [conversion1, conversion4, conversion3, conversion2] base_token = token1 # when opportunities = OpportunityFinder(conversions).find_opportunities( base_token, Wad.from_number(100)) # then assert len(opportunities) == 1 assert len(opportunities[0].steps) == 4 assert opportunities[0].steps[0].method == "met1" assert opportunities[0].steps[0].source_amount == Wad.from_number( 31.25) assert opportunities[0].steps[0].target_amount == Wad.from_number(62.5) assert opportunities[0].steps[1].method == "met2" assert opportunities[0].steps[1].source_amount == Wad.from_number(62.5) assert opportunities[0].steps[1].target_amount == Wad.from_number(100) assert opportunities[0].steps[2].method == "met3" assert opportunities[0].steps[2].source_amount == Wad.from_number(100) assert opportunities[0].steps[2].target_amount == Wad.from_number(120) assert opportunities[0].steps[3].method == "met4" assert opportunities[0].steps[3].source_amount == Wad.from_number(120) assert opportunities[0].steps[3].target_amount == Wad.from_number(132)
def test_should_ignore_irrelevant_conversions(self, token1, token2, token3, token4): # given conversion1 = Conversion(token1, token2, Ray.from_number(1.02), Wad.from_number(10000), 'met1') conversion2 = Conversion(token2, token1, Ray.from_number(1.03), Wad.from_number(10000), 'met2') conversion3 = Conversion(token1, token3, Ray.from_number(1.04), Wad.from_number(10000), 'met3') conversion4 = Conversion(token1, token4, Ray.from_number(1.07), Wad.from_number(10000), 'met4') conversion5 = Conversion(token2, token4, Ray.from_number(1.08), Wad.from_number(10000), 'met5') conversions = [ conversion1, conversion2, conversion3, conversion4, conversion5 ] base_token = token1 # when opportunities = OpportunityFinder(conversions).find_opportunities( base_token, Wad.from_number(100)) # then assert len(opportunities) == 1 assert len(opportunities[0].steps) == 2 assert opportunities[0].steps[0].method == "met1" assert opportunities[0].steps[1].method == "met2"
def __init__(self): super().__init__() self.liquidation_ratio = self.tub.mat() self.minimum_ratio = self.liquidation_ratio + Ray.from_number( self.arguments.min_margin) self.target_ratio = self.liquidation_ratio + Ray.from_number( self.arguments.top_up_margin)
def test_jar_bid_and_ask(self, sai: SaiDeployment): # when sai.tub.jar_jump(Wad.from_number(1.05)).transact() # then assert sai.tub.jar_bid() == Ray.from_number(0.95) assert sai.tub.jar_ask() == Ray.from_number(1.05)
def test_should_identify_multi_step_opportunities(self, token1, token2, token3, token4): # given conversion1 = Conversion(token1, token2, Ray.from_number(1.02), Wad.from_number(10000), 'met1') conversion2 = Conversion(token2, token3, Ray.from_number(1.03), Wad.from_number(10000), 'met2') conversion3 = Conversion(token3, token4, Ray.from_number(1.05), Wad.from_number(10000), 'met3') conversion4 = Conversion(token4, token1, Ray.from_number(1.07), Wad.from_number(10000), 'met4') conversions = [conversion1, conversion2, conversion3, conversion4] base_token = token1 # when opportunities = OpportunityFinder(conversions).find_opportunities( base_token, Wad.from_number(100)) # then assert len(opportunities) == 1 assert len(opportunities[0].steps) == 4 assert opportunities[0].steps[0].method == "met1" assert opportunities[0].steps[1].method == "met2" assert opportunities[0].steps[2].method == "met3" assert opportunities[0].steps[3].method == "met4"
def test_divide(self): assert Ray.from_number(4) / Ray.from_number(2) == Ray.from_number(2) assert Ray(4) / Ray.from_number(2) == Ray(2) assert Ray(3) / Ray.from_number(2) == Ray(1) assert Ray(39) / Ray.from_number(20) == Ray(1) assert Ray(40) / Ray.from_number(20) == Ray(2) assert Ray.from_number(0.2) / Ray.from_number(0.1) == Ray.from_number( 2)
def test_cuff_and_mat(self, sai: SaiDeployment): # given assert sai.tub.mat() == Ray.from_number(1) # when sai.tub.cuff(Ray.from_number(1.5)).transact() # then assert sai.tub.mat() == Ray.from_number(1.5)
def test_chop_and_axe(self, sai: SaiDeployment): # given assert sai.tub.axe() == Ray.from_number(1) sai.tub.cuff(Ray.from_number(1.5)).transact() # when sai.tub.chop(Ray.from_number(1.2)).transact() # then assert sai.tub.axe() == Ray.from_number(1.2)
def test_safe(self, sai: SaiDeployment): # given sai.tub.cuff(Ray.from_number(1.5)).transact() sai.tub.chop(Ray.from_number(1.2)).transact() DSValue(web3=sai.web3, address=sai.tub.pip()).poke_with_int( Wad.from_number(250).value).transact() # when sai.tub.open().transact() # then assert sai.tub.safe(1)
def test_should_calculate_total_rate(self, token1, token2): # given step1 = Conversion(token1, token2, Ray.from_number(1.01), Wad.from_number(1000), 'met1') step2 = Conversion(token2, token1, Ray.from_number(1.02), Wad.from_number(1000), 'met2') # when sequence = Sequence([step1, step2]) # then assert sequence.total_rate() == Ray.from_number(1.0302)
def test_multiply_by_ray(self): assert Wad.from_number(2) * Ray.from_number(3) == Wad.from_number(6) assert Wad.from_number(2) * Ray(3) == Wad(0) assert Wad(2) * Ray(499999999999999999999999999) == Wad(0) assert Wad(2) * Ray(500000000000000000000000000) == Wad(1) assert Wad(2) * Ray(999999999999999999999999999) == Wad(1) assert Wad(2) * Ray(1000000000000000000000000000) == Wad(2)
def total_rate(self) -> Ray: """Calculates the multiplication of all conversion rates forming this sequence. A `total_rate` > 1.0 is a general indication that executing this sequence may be profitable. """ return reduce(operator.mul, map(lambda step: step.rate, self.steps), Ray.from_number(1.0))
def test_should_recognize_if_there_are_no_opportunities( self, token1, token2, token3): # given conversion1 = Conversion(token1, token2, Ray.from_number(1.02), Wad.from_number(10000), 'met1') conversion2 = Conversion(token2, token3, Ray.from_number(1.03), Wad.from_number(10000), 'met2') conversions = [conversion1, conversion2] base_token = token1 # when opportunities = OpportunityFinder(conversions).find_opportunities( base_token, Wad.from_number(100)) # then assert len(opportunities) == 0
def __init__(self, tub: Tub, tap: Tap): self.tub = tub self.tap = tap super().__init__(source_token=self.tub.sai(), target_token=self.tub.skr(), rate=(Ray.from_number(1) / Ray(tap.ask())), max_source_amount=self.bustable_amount_in_sai(tap), method="tub.bust()")
def test_should_identify_opportunity(self, token1, token2): # given conversion1 = Conversion(token1, token2, Ray.from_number(1.02), Wad.from_number(10000), 'met1') conversion2 = Conversion(token2, token1, Ray.from_number(1.03), Wad.from_number(10000), 'met2') conversions = [conversion1, conversion2] base_token = token1 # when opportunities = OpportunityFinder(conversions).find_opportunities( base_token, Wad.from_number(100)) # then assert len(opportunities) == 1 assert len(opportunities[0].steps) == 2 assert opportunities[0].steps[0].method == "met1" assert opportunities[0].steps[1].method == "met2"
def test_crop_and_tax(self, sai: SaiDeployment): # given assert sai.tub.tax() == Ray.from_number(1) # when sai.tub.crop(Ray(1000000000000000020000000000)).transact() # then assert sai.tub.tax() == Ray(1000000000000000020000000000)
def test_nicely_convert_to_string_without_amounts(token1, token2): # given conversion = Conversion(token1, token2, Ray.from_number(1.01), Wad.from_number(1000), 'met()') # expect assert str( conversion ) == "[TK1 -> TK2 @1.010000000000000000000000000 by met() (max=1000.000000000000000000 TK1)]"
def __init__(self, tub: Tub): self.tub = tub super().__init__( source_token=self.tub.gem(), target_token=self.tub.skr(), rate=(Ray.from_number(1) / tub.jar_ask()), max_source_amount=Wad.from_number( 1000000), #1 mio ETH = infinity ;) method="tub.join()")
def test_coax_and_way(self, sai: SaiDeployment): # given assert sai.tub.way() == Ray.from_number(1) # when sai.tub.coax(Ray(1000000000000000070000000000)).transact() # then assert sai.tub.way() == Ray(1000000000000000070000000000)
def test_should_identify_all_opportunities_regardless_whether_they_are_profitable( self, token1, token2): # given conversion1 = Conversion(token1, token2, Ray.from_number(1.1), Wad.from_number(10000), 'met1') conversion2 = Conversion(token2, token1, Ray.from_number(0.6), Wad.from_number(10000), 'met2') conversions = [conversion1, conversion2] base_token = token1 # when opportunities = OpportunityFinder(conversions).find_opportunities( base_token, Wad.from_number(100)) # then assert len(opportunities) == 1 assert len(opportunities[0].steps) == 2 assert opportunities[0].steps[0].method == "met1" assert opportunities[0].steps[1].method == "met2"
def test_nicely_convert_to_string_with_amounts(token1, token2): # given conversion = Conversion(token1, token2, Ray.from_number(1.01), Wad.from_number(1000), 'met()') conversion.source_amount = Wad.from_number(50) conversion.target_amount = Wad.from_number(50.5) # expect assert str(conversion) == "[50.000000000000000000 TK1 -> 50.500000000000000000 TK2 @1.010000000000000000000000000" \ " by met() (max=1000.000000000000000000 TK1)]"
def test_should_calculate_profit_and_net_profit(self, token1, token2): # given step1 = Conversion(token1, token2, Ray.from_number(1.01), Wad.from_number(1000), 'met1') step1.source_amount = Wad.from_number(100) step1.target_amount = Wad.from_number(101) step2 = Conversion(token2, token1, Ray.from_number(1.02), Wad.from_number(1000), 'met2') step2.source_amount = Wad.from_number(101) step2.target_amount = Wad.from_number(103.02) # when sequence = Sequence([step1, step2]) # then assert sequence.profit(token1) == Wad.from_number(3.02) assert sequence.profit(token2) == Wad.from_number(0) assert sequence.net_profit( token1) == sequence.profit(token1) - sequence.tx_costs() assert sequence.net_profit( token2) == sequence.profit(token2) - sequence.tx_costs()
def test_should_cast_to_int(self): assert int(Ray.from_number(-4.5)) == -4 assert int(Ray.from_number(0.99)) == 0 assert int(Ray.from_number(1)) == 1 assert int(Ray.from_number(1.0)) == 1 assert int(Ray.from_number(1.5)) == 1 assert int(Ray.from_number(1.9999999999)) == 1
def test_should_cast_to_float(self): assert float(Ray.from_number(-4.5)) == -4.5 assert float(Ray.from_number(0.99)) == 0.99 assert float(Ray.from_number(1)) == 1.0 assert float(Ray.from_number(1.0)) == 1.0 assert float(Ray.from_number(1.5)) == 1.5 assert float(Ray.from_number(1.9999999999)) == 1.9999999999
def test_round(self): assert round(Ray.from_number(123.4567), 2) == Ray.from_number(123.46) assert round(Ray.from_number(123.4567), 0) == Ray.from_number(123.0) assert round(Ray.from_number(123.4567), -2) == Ray.from_number(100.0)
def test_should_have_nice_printable_representation(self): for ray in [Ray(1), Ray(100), Ray.from_number(2.5), Ray(-1)]: assert repr(ray) == f"Ray({ray.value})"
def test_multiply(self): assert Ray.from_number(2) * Ray.from_number(3) == Ray.from_number(6) assert Ray.from_number(2) * Ray(3) == Ray(6) assert Ray.from_number(2.5) * Ray(3) == Ray(7) assert Ray.from_number(2.99999) * Ray(3) == Ray(8)
def test_multiply_by_wad(self): assert Ray.from_number(2) * Wad.from_number(3) == Ray.from_number(6) assert Ray.from_number(2) * Wad(3) == Ray(6000000000) assert Ray(2) * Wad(3) == Ray(0) assert Ray(2) * Wad(999999999999999999) == Ray(1) assert Ray(2) * Wad(1000000000000000000) == Ray(2)
def test_multiply_by_int(self): assert Ray.from_number(2) * 3 == Ray.from_number(6) assert Ray.from_number(2) * 1 == Ray.from_number(2)
def test_per(self, sai: SaiDeployment): assert sai.tub.per() == Ray.from_number(1.0)