-
|
I am attempting to back-test on FX spot currency pairs, and for a non-USD pair, such as EUR/CHF, it gives me this error: 2024-06-13T05:03:00.000000000Z [ERROR] BACKTESTER-001.Cache: Cannot calculate exchange rate: ValueError('Quote maps must not be empty') My account balance is USD. |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
|
I've done a PR for supporting cross currency pairs, it will likely get merged at some point after the next release. |
Beta Was this translation helpful? Give feedback.
-
|
Ok, thank you. |
Beta Was this translation helpful? Give feedback.
-
Response to GitHub Discussion #3358Solution: Backtesting Non-USD Spot FX with USD Account BalanceGood news! Recent changes have added support for cross-currency pairs in the portfolio. The system now has two mechanisms for handling currency conversions:
The exchange rate system can automatically find conversion paths like:
There are two recommended approaches to solve this: Solution 1: Add Conversion Pair Quote Data (Recommended)Add a currency pair instrument that provides a conversion path from CHF to USD. You have two options: Option A: Direct path - Add CHF/USD: from nautilus_trader.model.currencies import CHF, USD
from nautilus_trader.model.identifiers import InstrumentId, Symbol, Venue
from nautilus_trader.model.instruments import CurrencyPair
from nautilus_trader.model.objects import Price, Quantity
# Create CHF/USD conversion pair
venue = Venue("SIM") # or your venue
chfusd = CurrencyPair(
instrument_id=InstrumentId(Symbol("CHF/USD"), venue),
raw_symbol=Symbol("CHF/USD"),
base_currency=CHF,
quote_currency=USD,
price_precision=5,
size_precision=2,
price_increment=Price.from_str("0.00001"),
size_increment=Quantity.from_str("0.01"),
lot_size=None,
max_quantity=None,
)
# Add the instrument to the engine
engine.add_instrument(chfusd)
# Add quote data for CHF/USD (can be daily bars or ticks)
chfusd_bars = load_chfusd_bars() # Your data loading logic
engine.add_data(chfusd_bars)Option B: Indirect path - Add EUR/USD (since you already have EUR/CHF): from nautilus_trader.model.currencies import EUR, USD
from nautilus_trader.model.identifiers import InstrumentId, Symbol, Venue
from nautilus_trader.model.instruments import CurrencyPair
from nautilus_trader.model.objects import Price, Quantity
# Create EUR/USD conversion pair
venue = Venue("SIM") # or your venue
eurusd = CurrencyPair(
instrument_id=InstrumentId(Symbol("EUR/USD"), venue),
raw_symbol=Symbol("EUR/USD"),
base_currency=EUR,
quote_currency=USD,
price_precision=5,
size_precision=2,
price_increment=Price.from_str("0.00001"),
size_increment=Quantity.from_str("0.01"),
lot_size=None,
max_quantity=None,
)
# Add the instrument to the engine
engine.add_instrument(eurusd)
# Add quote data for EUR/USD
eurusd_bars = load_eurusd_bars() # Your data loading logic
engine.add_data(eurusd_bars)The system will automatically find the conversion path: CHF → EUR → USD (via EUR/CHF and EUR/USD quotes). Solution 2: Use Mark Exchange RatesIf you have static exchange rates or want to set them manually, you can use mark exchange rates: from nautilus_trader.model.currencies import CHF, USD
from nautilus_trader.portfolio.config import PortfolioConfig
# Configure portfolio to use mark exchange rates
portfolio_config = PortfolioConfig(
use_mark_xrates=True,
convert_to_account_base_currency=True,
)
# After creating the engine, set the mark exchange rate
cache = engine.cache
# Set CHF/USD exchange rate (e.g., 1 CHF = 1.10 USD)
cache.set_mark_xrate(
from_currency=CHF,
to_currency=USD,
xrate=1.10, # Your CHF/USD rate
)
# The inverse rate (USD/CHF) is automatically setNote: With mark exchange rates, you don't need to provide quote data for the conversion pair, but you'll need to update the rates manually if they change over time. How It WorksRecent changes (commit
The key addition is the RecommendationFor backtesting, Solution 1 is generally preferred because:
If you only have static rates or want to simplify, Solution 2 works well and requires less data preparation. Both approaches will resolve the |
Beta Was this translation helpful? Give feedback.
-
|
I was curious about your question so I asked cursor about it using my PR branch as context. |
Beta Was this translation helpful? Give feedback.
I've done a PR for supporting cross currency pairs, it will likely get merged at some point after the next release.