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 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 profitable_opportunities(self): """Identify all profitable arbitrage opportunities within given limits.""" entry_amount = Wad.min(self.base_token.balance_of(self.our_address), self.max_engagement) opportunity_finder = OpportunityFinder( conversions=self.all_conversions()) opportunities = opportunity_finder.find_opportunities( self.base_token.address, entry_amount) opportunities = filter( lambda op: op.total_rate() > Ray.from_number(1.000001), opportunities) opportunities = filter( lambda op: op.net_profit(self.base_token.address) > self. min_profit, opportunities) opportunities = sorted( opportunities, key=lambda op: op.net_profit(self.base_token.address), reverse=True) return opportunities
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 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_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"