{"record":{"id":"0223dce99d3c57f7","repo":"nautechsystems/nautilus_trader","slug":"account-report-contains-multiple-currencies","errorCode":null,"errorMessage":"account report contains multiple currencies","messagePattern":"account report contains multiple currencies","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/nautilus_trader/analysis/tearsheet.py","lineNumber":920,"sourceCode":"                currency_report[\"total\"].iloc[-1],\n            )\n\n    return account_info\n\n\ndef _extract_account_balance_series(\n    report: pd.DataFrame,\n    target_currency: str | None,\n) -> tuple[pd.Series | None, str | None]:\n    if report.empty or \"currency\" not in report or \"total\" not in report:\n        return None, None\n\n    observed_currency: str | None = None\n\n    if target_currency is None:\n        account_currencies = set(report[\"currency\"].dropna())\n        if len(account_currencies) != 1:\n            raise ValueError(\"account report contains multiple currencies\")\n        observed_currency = next(iter(account_currencies))\n    else:\n        report = report[report[\"currency\"] == target_currency]\n\n    if report.empty:\n        return None, observed_currency\n\n    totals = pd.to_numeric(report[\"total\"], errors=\"coerce\")\n    totals.index = report.index\n    totals = totals.dropna().sort_index()\n    if totals.empty:\n        return None, observed_currency\n\n    return totals.groupby(level=0).last(), observed_currency\n\n\ndef _calculate_daily_balance_returns(total_balance: pd.Series) -> pd.Series | None:\n    account_returns = (","sourceCodeStart":902,"sourceCodeEnd":938,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/python/nautilus_trader/analysis/tearsheet.py#L902-L938","documentation":"_calculate_account_returns derives an account balance/returns series from an account report DataFrame. When no target_currency is given, the code requires the report to be single-currency; a report containing rows in more than one currency cannot be aggregated into one balance series without exchange-rate conversion, so it raises ValueError.","triggerScenarios":"Calling _calculate_account_returns (via create_tearsheet's account-returns path) with an account report whose 'currency' column has multiple distinct values (e.g. a multi-currency account) and target_currency=None.","commonSituations":"Multi-currency backtest accounts (USD deposits plus EUR/JPY instruments); producing a tearsheet across a portfolio spanning several account currencies; forgetting to pass target_currency after changing the strategy's instruments.","solutions":["Pass target_currency explicitly (e.g. target_currency='USD') so the report is filtered to one currency before series extraction.","Split the tearsheet generation per account/currency, calling it once per currency.","Configure the backtest with a single-currency account or a currency conversion setup so the account report is single-currency."],"exampleFix":"// before\nreturns = _calculate_account_returns(report, target_currency=None)\n// after\nreturns = _calculate_account_returns(report, target_currency='USD')","handlingStrategy":"validation","validationCode":"currencies = set(report['currency'].dropna())\nif len(currencies) > 1 and target_currency is None:\n    raise ValueError(f'Multi-currency report {currencies}: pass target_currency')","typeGuard":null,"tryCatchPattern":"try:\n    acct_returns = _calculate_account_returns(report, target_currency=None)\nexcept ValueError as e:\n    if 'multiple currencies' in str(e):\n        acct_returns = _calculate_account_returns(report, target_currency=base_currency)\n    else:\n        raise","preventionTips":["Pass target_currency explicitly whenever the account may hold multiple currencies.","Check set(report['currency'].dropna()) before generating account-based tearsheets.","Configure backtests with a single account currency or convert balances to a base currency upstream."],"tags":["python","backtesting","multi-currency"],"backgroundTag":"invalid-argument-value","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}