diff --git a/addons/account/models/account_bank_statement.py b/addons/account/models/account_bank_statement.py
index 31a0c162023b7bb7f42688e6d2c2b7f0605432d9..71d6f336dacbf3e8352d19b9c2d8834e31da30e9 100644
--- a/addons/account/models/account_bank_statement.py
+++ b/addons/account/models/account_bank_statement.py
@@ -611,11 +611,20 @@ class AccountBankStatementLine(models.Model):
         and 'move_line' will be used to create the counterpart of an existing account.move.line to which
         the newly created journal item will be reconciled.
         :param counterpart_vals:    A python dictionary containing:
-            'balance':              Optional amount to consider during the reconciliation. If a foreign currency is set on the
-                                    counterpart line in the same foreign currency as the statement line, then this amount is
-                                    considered as the amount in foreign currency. If not specified, the full balance is took.
-                                    This value must be provided if move_line is not.
-            **kwargs:               Additional values that need to land on the account.move.line to create.
+            'balance':                  Optional amount to consider during the reconciliation. If a foreign currency is set on the
+                                        counterpart line in the same foreign currency as the statement line, then this amount is
+                                        considered as the amount in foreign currency. If not specified, the full balance is took.
+                                        This value must be provided if move_line is not.
+            'amount_residual':          The residual amount to reconcile expressed in the company's currency.
+                                        /!\ This value should be equivalent to move_line.amount_residual except we want
+                                        to avoid browsing the record when the only thing we need in an overview of the
+                                        reconciliation, for example in the reconciliation widget.
+            'amount_residual_currency': The residual amount to reconcile expressed in the foreign's currency.
+                                        Using this key doesn't make sense without passing 'currency_id' in vals.
+                                        /!\ This value should be equivalent to move_line.amount_residual_currency except
+                                        we want to avoid browsing the record when the only thing we need in an overview
+                                        of the reconciliation, for example in the reconciliation widget.
+            **kwargs:                   Additional values that need to land on the account.move.line to create.
         :param move_line:           An optional account.move.line move_line representing the counterpart line to reconcile.
         :return:                    The values to create a new account.move.line move_line.
         '''
@@ -627,6 +636,12 @@ class AccountBankStatementLine(models.Model):
         journal_currency = journal.currency_id if journal.currency_id != company_currency else False
         statement_line_rate = self.amount_currency / (self.amount or 1.0)
 
+        balance_to_reconcile = counterpart_vals.pop('balance', None)
+        amount_residual = -counterpart_vals.pop('amount_residual', move_line.amount_residual if move_line else 0.0) \
+            if balance_to_reconcile is None else balance_to_reconcile
+        amount_residual_currency = -counterpart_vals.pop('amount_residual_currency', move_line.amount_residual_currency if move_line else 0.0)\
+            if balance_to_reconcile is None else balance_to_reconcile
+
         if 'currency_id' in counterpart_vals:
             currency_id = counterpart_vals['currency_id']
         elif move_line:
@@ -648,7 +663,7 @@ class AccountBankStatementLine(models.Model):
                     # There is also a foreign currency set on the journal so the journal item to create will
                     # use the foreign currency set on the statement line.
 
-                    amount_currency = counterpart_vals.pop('balance', -move_line.amount_residual_currency if move_line else 0.0)
+                    amount_currency = amount_residual_currency
                     balance = journal_currency._convert(amount_currency / statement_line_rate, company_currency, journal.company_id, self.date)
 
                 elif currency_id == journal_currency.id and self.foreign_currency_id == company_currency:
@@ -657,7 +672,7 @@ class AccountBankStatementLine(models.Model):
                     # There is also a foreign currency set on the statement line that is the same as the company one.
                     # Then, the journal item to create will use the company's currency.
 
-                    amount_currency = counterpart_vals.pop('balance', -move_line.amount_residual_currency if move_line else 0.0)
+                    amount_currency = amount_residual_currency
                     balance = amount_currency * statement_line_rate
                     currency_id = False
                     amount_currency = 0.0
@@ -668,7 +683,7 @@ class AccountBankStatementLine(models.Model):
                     # There is also a foreign currency set on the statement line.
                     # The residual amount will be convert to the foreign currency set on the statement line.
 
-                    amount_currency = counterpart_vals.pop('balance', -move_line.amount_residual_currency if move_line else 0.0)
+                    amount_currency = amount_residual_currency
                     balance = journal_currency._convert(amount_currency, company_currency, journal.company_id, self.date)
                     amount_currency *= statement_line_rate
                     currency_id = self.foreign_currency_id.id
@@ -678,7 +693,7 @@ class AccountBankStatementLine(models.Model):
                     # Whatever the currency set on the journal item passed as parameter, the counterpart line
                     # will be expressed in the foreign currency set on the statement line.
 
-                    balance = counterpart_vals.pop('balance', -move_line.amount_residual if move_line else 0.0)
+                    balance = amount_residual
                     amount_currency = company_currency._convert(balance, journal_currency, journal.company_id, self.date)
                     amount_currency *= statement_line_rate
                     currency_id = self.foreign_currency_id.id
@@ -690,10 +705,10 @@ class AccountBankStatementLine(models.Model):
                 # and is used as conversion rate between the company's currency and the foreign currency.
 
                 if currency_id == self.foreign_currency_id.id:
-                    amount_currency = counterpart_vals.pop('balance', -move_line.amount_residual_currency if move_line else 0.0)
+                    amount_currency = amount_residual_currency
                     balance = amount_currency / statement_line_rate
                 else:
-                    balance = counterpart_vals.pop('balance', -move_line.amount_residual if move_line else 0.0)
+                    balance = amount_residual
                     amount_currency = balance * statement_line_rate
                     currency_id = self.foreign_currency_id.id
 
@@ -703,10 +718,10 @@ class AccountBankStatementLine(models.Model):
                 # Everything will be expressed in the journal's currency.
 
                 if currency_id == journal_currency.id:
-                    amount_currency = counterpart_vals.pop('balance', -move_line.amount_residual_currency if move_line else 0.0)
+                    amount_currency = amount_residual_currency
                     balance = journal_currency._convert(amount_currency, company_currency, journal.company_id, self.date)
                 else:
-                    balance = counterpart_vals.pop('balance', -move_line.amount_residual if move_line else 0.0)
+                    balance = amount_residual
                     amount_currency = company_currency._convert(balance, journal_currency, journal.company_id, self.date)
                     currency_id = journal_currency.id
 
@@ -715,12 +730,12 @@ class AccountBankStatementLine(models.Model):
                 # Only a foreign currency set on the counterpart line.
                 # Ignore it and record the line using the company's currency.
 
-                balance = counterpart_vals.pop('balance', -move_line.amount_residual if move_line else 0.0)
+                balance = amount_residual
                 amount_currency = 0.0
                 currency_id = False
 
         else:
-            balance = counterpart_vals.pop('balance', -move_line.amount_residual if move_line else 0.0)
+            balance = amount_residual
 
             if self.foreign_currency_id and journal_currency:
 
diff --git a/addons/account/models/account_reconcile_model.py b/addons/account/models/account_reconcile_model.py
index 3630a0557b2e97481b322b5b3206dbe8b178e93a..524082e1b47f5907461a1e65443f959c78351216 100644
--- a/addons/account/models/account_reconcile_model.py
+++ b/addons/account/models/account_reconcile_model.py
@@ -796,35 +796,30 @@ class AccountReconcileModel(models.Model):
         if not candidates:
             return False
 
+        reconciliation_overview, open_balance_vals = statement_line._prepare_reconciliation([{
+            'currency_id': aml['aml_currency_id'],
+            'amount_residual': aml['aml_amount_residual'],
+            'amount_residual_currency': aml['aml_amount_residual_currency'],
+        } for aml in candidates])
+
         # Match total residual amount.
         line_currency = statement_line.foreign_currency_id or statement_line.currency_id
+        line_residual = statement_line.amount_residual
+        line_residual_after_reconciliation = line_residual
 
-        candidate_currencies = set(candidate['aml_currency_id'] or statement_line.company_currency_id.id for candidate in candidates)
-        if candidate_currencies != {line_currency.id}:
-            # We don't apply any automatic match based on residual amount if candidates have differenct currencies
-            return False
-
-        total_residual = 0.0
-        for aml in candidates:
-            if aml['account_internal_type'] == 'liquidity':
-                total_residual += aml['aml_currency_id'] and aml['aml_amount_currency'] or aml['aml_balance']
+        for reconciliation_vals in reconciliation_overview:
+            line_vals = reconciliation_vals['line_vals']
+            if line_vals['currency_id']:
+                line_residual_after_reconciliation -= line_vals['amount_currency']
             else:
-                total_residual += aml['aml_currency_id'] and aml['aml_amount_residual_currency'] or aml['aml_amount_residual']
+                line_residual_after_reconciliation -= line_vals['debit'] - line_vals['credit']
 
         # Statement line amount is equal to the total residual.
-        if float_is_zero(total_residual + statement_line.amount_residual, precision_rounding=line_currency.rounding):
+        if line_currency.is_zero(line_residual_after_reconciliation):
             return True
 
-        line_residual_to_compare = abs(statement_line.amount_residual)
-        total_residual_to_compare = abs(total_residual)
-
-        if line_residual_to_compare > total_residual_to_compare:
-            amount_percentage = (total_residual_to_compare / line_residual_to_compare) * 100
-        elif total_residual:
-            amount_percentage = (line_residual_to_compare / total_residual_to_compare) * 100 if total_residual_to_compare else 0.0
-        else:
-            return False
-        return amount_percentage >= self.match_total_amount_param
+        reconciled_percentage = (abs(line_residual) - abs(line_residual_after_reconciliation)) / abs(line_residual) * 100
+        return reconciled_percentage >= self.match_total_amount_param
 
     def _filter_candidates(self, candidates, aml_ids_to_exclude, reconciled_amls_ids):
         """ Sorts reconciliation candidates by priority and filters them so that only
diff --git a/addons/account/tests/test_reconciliation_matching_rules.py b/addons/account/tests/test_reconciliation_matching_rules.py
index 3688d47cfb4da9c823d9321528137675be233941..15c86f2ea2b0aa2db4df4d8e551951afbbcc4fb8 100644
--- a/addons/account/tests/test_reconciliation_matching_rules.py
+++ b/addons/account/tests/test_reconciliation_matching_rules.py
@@ -12,6 +12,13 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
     def setUpClass(cls, chart_template_ref=None):
         super().setUpClass(chart_template_ref=chart_template_ref)
 
+        cls.currency_data_2 = cls.setup_multi_currency_data({
+            'name': 'Dark Chocolate Coin',
+            'symbol': '🍫',
+            'currency_unit_label': 'Dark Choco',
+            'currency_subunit_label': 'Dark Cacao Powder',
+        }, rate2016=10.0, rate2017=20.0)
+
         cls.company = cls.company_data['company']
 
         cls.account_pay = cls.company_data['default_account_payable']
@@ -434,7 +441,9 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
         self.bank_line_2.unlink()
         self.bank_line_1.write({'partner_id': partner.id, 'foreign_currency_id': currency_statement.id, 'amount_currency': 100, 'payment_ref': 'test'})
         self.env['account.reconcile.model'].flush()
-        self._check_statement_matching(self.rule_1, {self.bank_line_1.id: {'aml_ids': []}}, statements=self.bank_st)
+        self._check_statement_matching(self.rule_1, {
+            self.bank_line_1.id: {'aml_ids': invoice_line.ids, 'model': self.rule_1},
+        }, statements=self.bank_st)
 
     def test_invoice_matching_rule_no_partner(self):
         """ Tests that a statement line without any partner can be matched to the
@@ -510,4 +519,98 @@ class TestReconciliationMatchingRules(AccountTestInvoicingCommon):
         self._check_statement_matching(self.rule_1, {
             self.bank_line_1.id: {'aml_ids': [self.invoice_line_1.id], 'model': self.rule_1},
             self.bank_line_2.id: {'aml_ids': []},
-        }, self.bank_st)
\ No newline at end of file
+        }, self.bank_st)
+
+    def test_match_multi_currencies(self):
+        ''' Ensure the matching of candidates is made using the right statement line currency.
+
+        In this test, the value of the statement line is 100 USD = 300 GOL = 900 DAR and we want to match two journal
+        items of:
+        - 100 USD = 200 GOL (= 600 DAR from the statement line point of view)
+        - 14 USD = 280 DAR
+
+        Both journal items should be suggested to the user because they represents 98% of the statement line amount
+        (DAR).
+        '''
+        partner = self.env['res.partner'].create({'name': 'Bernard Perdant'})
+
+        journal = self.env['account.journal'].create({
+            'name': 'test_match_multi_currencies',
+            'code': 'xxxx',
+            'type': 'bank',
+            'currency_id': self.currency_data['currency'].id,
+        })
+
+        matching_rule = self.env['account.reconcile.model'].create({
+            'name': 'test_match_multi_currencies',
+            'rule_type': 'invoice_matching',
+            'match_partner': True,
+            'match_partner_ids': [(6, 0, partner.ids)],
+            'match_total_amount': True,
+            'match_total_amount_param': 95.0,
+            'match_same_currency': False,
+            'company_id': self.company_data['company'].id,
+        })
+
+        statement = self.env['account.bank.statement'].create({
+            'name': 'test_match_multi_currencies',
+            'journal_id': journal.id,
+            'line_ids': [
+                (0, 0, {
+                    'journal_id': journal.id,
+                    'date': '2016-01-01',
+                    'payment_ref': 'line',
+                    'partner_id': partner.id,
+                    'foreign_currency_id': self.currency_data_2['currency'].id,
+                    'amount': 300.0,            # Rate is 3 GOL = 1 USD in 2016.
+                    'amount_currency': 900.0,   # Rate is 10 DAR = 1 USD in 2016 but the rate used by the bank is 9:1.
+                }),
+            ],
+        })
+        statement_line = statement.line_ids
+
+        statement.button_post()
+
+        move = self.env['account.move'].create({
+            'move_type': 'entry',
+            'date': '2017-01-01',
+            'journal_id': self.company_data['default_journal_sale'].id,
+            'line_ids': [
+                # Rate is 2 GOL = 1 USD in 2017.
+                # The statement line will consider this line equivalent to 600 DAR.
+                (0, 0, {
+                    'account_id': self.company_data['default_account_receivable'].id,
+                    'partner_id': partner.id,
+                    'currency_id': self.currency_data['currency'].id,
+                    'debit': 100.0,
+                    'credit': 0.0,
+                    'amount_currency': 200.0,
+                }),
+                # Rate is 20 GOL = 1 USD in 2017.
+                (0, 0, {
+                    'account_id': self.company_data['default_account_receivable'].id,
+                    'partner_id': partner.id,
+                    'currency_id': self.currency_data_2['currency'].id,
+                    'debit': 14.0,
+                    'credit': 0.0,
+                    'amount_currency': 280.0,
+                }),
+                # Line to balance the journal entry:
+                (0, 0, {
+                    'account_id': self.company_data['default_account_revenue'].id,
+                    'debit': 0.0,
+                    'credit': 114.0,
+                }),
+            ],
+        })
+        move.post()
+
+        move_line_1 = move.line_ids.filtered(lambda line: line.debit == 100.0)
+        move_line_2 = move.line_ids.filtered(lambda line: line.debit == 14.0)
+
+        self.env['account.reconcile.model'].flush()
+
+        with self.mocked_today('2017-01-01'):
+            self._check_statement_matching(matching_rule, {
+                statement_line.id: {'aml_ids': (move_line_1 + move_line_2).ids, 'model': matching_rule}
+            }, statements=statement)