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"
Example #4
0
 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"