Multi-Currency Portfolio Examples
Portfolio Toolkit provides comprehensive support for multi-currency portfolios with automatic currency conversion and FIFO cost calculation.
Multi-Currency Portfolio Setup
Here’s an example of a portfolio with transactions in multiple currencies:
{
"name": "Multi Currency Portfolio",
"currency": "EUR",
"transactions": [
{
"ticker": null,
"date": "2025-06-10",
"type": "deposit",
"quantity": 2000.00,
"price": 1.00,
"currency": "EUR",
"total": 2000.00,
"exchange_rate": 1.00,
"subtotal_base": 2000.00,
"fees_base": 0.00,
"total_base": 2000.00
},
{
"ticker": "AAPL",
"date": "2025-06-12",
"type": "buy",
"quantity": 10,
"price": 100.00,
"currency": "USD",
"total": 1000.00,
"exchange_rate": 1.056,
"subtotal_base": 947.00,
"fees_base": 0.50,
"total_base": 947.50
},
{
"ticker": "SHOP",
"date": "2025-06-13",
"type": "buy",
"quantity": 5,
"price": 85.00,
"currency": "CAD",
"total": 425.00,
"exchange_rate": 0.639,
"subtotal_base": 271.58,
"fees_base": 10.12,
"total_base": 281.70
}
]
}
Working with Multi-Currency Data
from portfolio_toolkit.portfolio.portfolio import Portfolio
from portfolio_toolkit.data_provider.yf_data_provider import YFDataProvider
# Load multi-currency portfolio
data_provider = YFDataProvider()
portfolio = Portfolio('examples/multi_currency_portfolio.json', data_provider)
# Print positions (all values converted to base currency)
portfolio.print_current_positions()
CLI Usage for Multi-Currency Portfolios
You can also analyze multi-currency portfolios using the Portfolio Toolkit CLI:
# Display current positions with automatic currency conversion
portfolio-toolkit portfolio open-positions -f examples/multi_currency_portfolio.json
# Plot portfolio evolution (all in base currency)
portfolio-toolkit portfolio plot -f examples/multi_currency_portfolio.json
# Export multi-currency data
portfolio-toolkit portfolio export -f examples/multi_currency_portfolio.json --format csv
Exchange Rate Handling
The system automatically handles currency conversion using the exchange rates specified in each transaction:
EUR/USD: 1.056 (1 EUR = 1.056 USD)
EUR/CAD: 0.639 (1 EUR = 0.639 CAD)
# The DataFrame shows both original and base currency values
df = portfolio.df_portfolio
# Check price columns
print("Original Currency Prices:")
print(df[['Ticker', 'Price', 'Currency']].drop_duplicates())
print("\\nBase Currency Prices:")
print(df[['Ticker', 'Price_Base', 'Value_Base']].drop_duplicates())
Expected Output:
Current positions as of 2025-07-14:
| Ticker | Price Base | Cost | Quantity | Value Base | Return (%) |
|---------|-----------|-----------|---------|-----------|-----------|
| AAPL | 197.56 | 947.50 | 10.00 | 1975.57 | 108.50 |
| SHOP | 81.92 | 281.70 | 5.00 | 409.61 | 45.41 |
| __EUR | 1.00 | 770.80 | 770.80 | 770.80 | 0.00 |
|---------|-----------|-----------|---------|-----------|-----------|
| TOTAL | | 2000.00 | | 3155.98 | 57.80 |
Currency Conversion Mechanics
Understanding how currency conversion works:
Transaction Level: Each transaction specifies its original currency and exchange rate
Automatic Conversion: All amounts are automatically converted to the portfolio’s base currency
Fee Handling: Fees are converted and included in the total cost basis
Cash Tracking: The system automatically creates synthetic cash transactions
# Example of how conversion works
# Original: 10 AAPL @ $100 USD = $1000 USD
# Exchange Rate: 1.056 (EUR/USD)
# Converted: €947.00 EUR (before fees)
# With fees: €947.50 EUR total cost
# This is automatically handled by the preprocesador
transaction = {
"ticker": "AAPL",
"quantity": 10,
"price": 100.00, # USD
"currency": "USD",
"total": 1000.00, # USD
"exchange_rate": 1.056,
"subtotal_base": 947.00, # EUR
"fees_base": 0.50, # EUR
"total_base": 947.50 # EUR (final cost)
}
FIFO Cost Calculation with Multiple Currencies
The FIFO calculation works seamlessly across currencies:
# Example: Buy AAPL in USD, then sell in USD
# All costs are tracked in base currency (EUR)
from datetime import datetime
# Check FIFO calculation after partial sale
remaining_quantity = portfolio.calculate_current_quantity("AAPL", datetime(2025, 7, 14))
print(f"Remaining AAPL shares: {remaining_quantity}")
# The cost basis is maintained in EUR regardless of transaction currency
Advanced Multi-Currency Analysis
def analyze_currency_exposure(portfolio):
"""Analyze currency exposure in the portfolio."""
# Get the underlying DataFrame
df = portfolio.df_portfolio
# Group by currency (from original transactions)
currency_exposure = {}
for asset in portfolio.assets:
ticker = asset["ticker"]
if not portfolio.is_cash_ticker(ticker):
# Get the original currency for this asset
transactions = asset["transactions"]
if transactions:
currency = transactions[0]["currency"]
current_qty = portfolio.calculate_current_quantity(ticker, datetime.now())
# Get current value in base currency
latest_data = df[df['Ticker'] == ticker].iloc[-1]
current_value = latest_data['Value_Base']
if currency not in currency_exposure:
currency_exposure[currency] = 0
currency_exposure[currency] += current_value
return currency_exposure
# Usage
exposure = analyze_currency_exposure(portfolio)
print("Currency Exposure (in base currency):")
for currency, value in exposure.items():
print(f"{currency}: {value:.2f} {portfolio.currency}")
Custom Exchange Rates
You can specify custom exchange rates for each transaction:
{
"ticker": "TSM",
"date": "2025-06-14",
"type": "buy",
"quantity": 100,
"price": 25.50,
"currency": "TWD",
"total": 2550.00,
"exchange_rate": 0.031,
"subtotal_base": 79.05,
"fees_base": 0.95,
"total_base": 80.00
}
Tips for Multi-Currency Portfolios
Consistent Base Currency: Always use the same base currency for your portfolio
Accurate Exchange Rates: Use accurate exchange rates from the transaction date
Fee Conversion: Convert fees to the base currency for accurate cost tracking
Regular Updates: Update exchange rates regularly for current valuations
Migration from Single Currency
If you have an existing single-currency portfolio and want to add multi-currency support:
# Original single-currency transaction
old_transaction = {
"ticker": "AAPL",
"date": "2025-06-12",
"type": "buy",
"quantity": 10,
"price": 100.00,
"fees": 0.50
}
# Convert to multi-currency format
new_transaction = {
"ticker": "AAPL",
"date": "2025-06-12",
"type": "buy",
"quantity": 10,
"price": 100.00,
"currency": "USD", # Add currency
"total": 1000.00,
"exchange_rate": 1.056, # Add exchange rate
"subtotal_base": 947.00, # Calculate base amounts
"fees_base": 0.47, # Convert fees
"total_base": 947.47
}
Use the migration script provided to automate this conversion:
python migrate_v1_to_v2.py old_portfolio.json new_portfolio.json --add-cash --currency EUR