first commit
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
# Currency Conversion Feature
|
||||
|
||||
## Overview
|
||||
|
||||
The Portfolio Tracker now supports automatic currency conversion for transactions that are in different currencies than the portfolio's base currency. This feature allows users to have a unified view of their investments across multiple currencies.
|
||||
|
||||
## How It Works
|
||||
|
||||
### Automatic Detection
|
||||
- When a transaction is added, the system automatically detects the stock's currency from Yahoo Finance
|
||||
- If the transaction currency differs from the portfolio's base currency, conversion rates are fetched
|
||||
- Converted values are displayed alongside original values for transparency
|
||||
|
||||
### Display Format
|
||||
The transaction table now includes additional columns when multi-currency transactions are present:
|
||||
|
||||
| Original Column | New Column | Description |
|
||||
|----------------|------------|-------------|
|
||||
| Preis | Preis (BASE_CURRENCY) | Shows converted price in portfolio base currency |
|
||||
| Gesamt | Gesamt (BASE_CURRENCY) | Shows converted total in portfolio base currency |
|
||||
|
||||
### Example Display
|
||||
```
|
||||
Original: 150.00 USD
|
||||
Converted: 135.50 EUR (when EUR is portfolio base currency)
|
||||
```
|
||||
|
||||
## Features
|
||||
|
||||
### 1. Real-time Currency Conversion
|
||||
- Exchange rates are fetched from `exchangerate-api.io`
|
||||
- Rates are cached for 1 hour to improve performance
|
||||
- Supports all major world currencies
|
||||
|
||||
### 2. Smart Display Logic
|
||||
- If transaction currency = portfolio currency: shows "-" in conversion columns
|
||||
- If currencies differ: shows converted amount
|
||||
- If conversion fails: shows "Conv. Error"
|
||||
|
||||
### 3. Portfolio Summary
|
||||
- Total invested amount is automatically converted to portfolio base currency
|
||||
- Summary shows "(converted)" indicator when multi-currency transactions exist
|
||||
|
||||
### 4. Currency Information Panel
|
||||
A new information panel explains:
|
||||
- That transactions in other currencies are automatically converted
|
||||
- Exchange rates are updated hourly
|
||||
- Conversion is for display purposes only
|
||||
|
||||
## Technical Implementation
|
||||
|
||||
### Currency Conversion Utility (`internal/util/currency.go`)
|
||||
|
||||
#### Key Functions:
|
||||
```go
|
||||
// Get exchange rate between two currencies
|
||||
GetExchangeRate(fromCurrency, toCurrency string) (float64, error)
|
||||
|
||||
// Convert amount from one currency to another
|
||||
ConvertCurrency(amount float64, fromCurrency, toCurrency string) (float64, error)
|
||||
|
||||
// Format currency with appropriate symbol
|
||||
FormatCurrencyWithSymbol(amount float64, currency string) string
|
||||
|
||||
// Batch convert multiple amounts efficiently
|
||||
BatchConvertCurrency(amounts []float64, fromCurrency, toCurrency string) ([]float64, error)
|
||||
```
|
||||
|
||||
#### Caching System:
|
||||
- **Cache Duration**: 1 hour per exchange rate
|
||||
- **Cache Key Format**: `FROM_TO` (e.g., "USD_EUR")
|
||||
- **Memory Usage**: Minimal - only stores rate and timestamp
|
||||
- **Thread Safe**: Uses RWMutex for concurrent access
|
||||
|
||||
### Template Helper Functions (`internal/web/templates/helpers.go`)
|
||||
|
||||
#### Key Helper Functions:
|
||||
```go
|
||||
// Get converted price for display
|
||||
getConvertedPrice(activity model.Activity, portfolioBaseCurrency string) string
|
||||
|
||||
// Get converted total for display
|
||||
getConvertedTotal(activity model.Activity, portfolioBaseCurrency string) string
|
||||
|
||||
// Calculate total invested in base currency
|
||||
calculateTotalInvestedInBaseCurrency(activities []model.Activity, baseCurrency string) float64
|
||||
|
||||
// Format total with conversion indicator
|
||||
formatTotalInvestedWithConversion(activities []model.Activity, baseCurrency string) string
|
||||
```
|
||||
|
||||
## Supported Currencies
|
||||
|
||||
The system supports all currencies provided by the exchange rate API, including:
|
||||
|
||||
| Currency | Code | Symbol |
|
||||
|----------|------|--------|
|
||||
| US Dollar | USD | $ |
|
||||
| Euro | EUR | € |
|
||||
| British Pound | GBP | £ |
|
||||
| Japanese Yen | JPY | ¥ |
|
||||
| Swiss Franc | CHF | CHF |
|
||||
| Canadian Dollar | CAD | C$ |
|
||||
| Australian Dollar | AUD | A$ |
|
||||
| And many more... | | |
|
||||
|
||||
## Error Handling
|
||||
|
||||
### API Failures
|
||||
- If exchange rate API is unavailable: shows "Conv. Error"
|
||||
- Original transaction data is always preserved
|
||||
- System continues to function normally
|
||||
|
||||
### Invalid Currencies
|
||||
- Unknown currency codes are handled gracefully
|
||||
- System falls back to displaying original amounts
|
||||
- No data loss occurs
|
||||
|
||||
### Network Issues
|
||||
- Cached rates are used when possible
|
||||
- Graceful degradation to original currency display
|
||||
- User is informed via "Conv. Error" message
|
||||
|
||||
## Performance Considerations
|
||||
|
||||
### Caching Strategy
|
||||
- **Hit Rate**: High due to 1-hour cache duration
|
||||
- **API Calls**: Minimized through intelligent caching
|
||||
- **Memory Usage**: Low - only active currency pairs cached
|
||||
- **Cleanup**: Automatic cache expiration
|
||||
|
||||
### Batch Operations
|
||||
- Multiple conversions use single API call when possible
|
||||
- Efficient for portfolios with many same-currency transactions
|
||||
- Reduces API rate limit consumption
|
||||
|
||||
## Configuration
|
||||
|
||||
### API Limits
|
||||
- **Free Tier**: 1,500 requests per month
|
||||
- **Rate Limiting**: Built-in request throttling
|
||||
- **Fallback**: Graceful degradation when limits exceeded
|
||||
|
||||
### Cache Management
|
||||
```go
|
||||
// Clear cache manually (for testing/debugging)
|
||||
util.ClearCache()
|
||||
|
||||
// Get cache statistics
|
||||
cacheInfo := util.GetCacheInfo()
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Adding Multi-Currency Transaction
|
||||
1. User adds transaction for Apple (AAPL) in USD to EUR portfolio
|
||||
2. System detects USD currency from Yahoo Finance
|
||||
3. Fetches USD/EUR exchange rate
|
||||
4. Displays both original (USD) and converted (EUR) amounts
|
||||
5. Caches exchange rate for future use
|
||||
|
||||
### Portfolio Summary
|
||||
```
|
||||
Portfolio: "My Investments" (EUR)
|
||||
Total Invested: 15,430.50 EUR (converted)
|
||||
|
||||
Recent Transactions:
|
||||
- AAPL: 150.00 USD (~135.50 EUR)
|
||||
- BMW.DE: 85.30 EUR (-)
|
||||
- NESN.SW: 110.20 CHF (~102.15 EUR)
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Unit Tests
|
||||
- All currency utilities have comprehensive test coverage
|
||||
- Tests include edge cases and error conditions
|
||||
- Performance benchmarks included
|
||||
|
||||
### Integration Tests
|
||||
- Test with real transaction data
|
||||
- Verify UI display logic
|
||||
- Cache behavior validation
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Planned Features
|
||||
1. **Historical Rates**: Use transaction date for accurate historical conversion
|
||||
2. **Multiple Rate Providers**: Fallback to alternative APIs
|
||||
3. **Custom Rate Override**: Allow manual exchange rate input
|
||||
4. **Currency Trends**: Show exchange rate history
|
||||
5. **Base Currency Change**: Convert entire portfolio to new base currency
|
||||
|
||||
### API Improvements
|
||||
1. **Rate Provider Selection**: Choose between multiple APIs
|
||||
2. **Custom Update Intervals**: Configurable cache duration
|
||||
3. **Offline Mode**: Store rates locally for offline use
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Common Issues
|
||||
|
||||
#### "Conv. Error" Displayed
|
||||
- **Cause**: Exchange rate API unavailable or rate limit exceeded
|
||||
- **Solution**: Wait and refresh, or check internet connection
|
||||
- **Impact**: Original data still visible and functional
|
||||
|
||||
#### Slow Loading
|
||||
- **Cause**: First-time rate fetching or cache expiration
|
||||
- **Solution**: Subsequent loads will be faster due to caching
|
||||
- **Mitigation**: Consider pre-warming cache for common currencies
|
||||
|
||||
#### Incorrect Rates
|
||||
- **Cause**: API data delay or temporary inconsistency
|
||||
- **Solution**: Rates update automatically within 1 hour
|
||||
- **Manual Fix**: Clear cache to force immediate refresh
|
||||
|
||||
### Debug Commands
|
||||
```bash
|
||||
# Clear currency cache
|
||||
curl -X POST http://localhost:8080/api/admin/clear-currency-cache
|
||||
|
||||
# Get cache status
|
||||
curl http://localhost:8080/api/admin/currency-cache-info
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- **No API Keys Required**: Uses free public API
|
||||
- **Rate Limiting**: Built-in protection against abuse
|
||||
- **Data Privacy**: No sensitive data sent to external APIs
|
||||
- **Fallback Security**: System functions without external dependencies
|
||||
Reference in New Issue
Block a user