TradingTeaching Press · Dubai, UAE Trading is high-risk. Check local laws, your residency rules and your finances. Risk warning
🤖 Trading Automation

Building Multi-Currency Trading Systems

Learn to build automated trading systems that trade multiple currency pairs simultaneously with proper correlation and risk management.

7 min read TradingTeaching Team

Trading multiple currency pairs can diversify risk and increase opportunities. This guide covers building systems that manage a portfolio of currencies effectively.

Why Trade Multiple Pairs?

Advantages

  • Diversification: Spread risk across markets
  • More Opportunities: Signals from multiple pairs
  • Smoother Equity: Different pairs perform in different conditions
  • Correlation Benefits: Hedge related positions

Challenges

  • Correlation Risk: Pairs move together
  • Complexity: More logic to manage
  • Risk Management: Track total exposure
  • Execution: Multiple positions simultaneously

Understanding Currency Correlation

Correlation Basics

Correlation ranges from -1 to +1:

  • +1: Move perfectly together
  • 0: No relationship
  • -1: Move opposite

Common Correlations

Pair 1 Pair 2 Typical Correlation
EURUSD GBPUSD +0.85 quoted, +0.68 measured
EURUSD USDCHF -0.90 quoted, -0.76 measured
USDJPY EURJPY +0.70
AUDUSD NZDUSD +0.90

Calculating Correlation in MQL5

double CalculateCorrelation(string symbol1, string symbol2, int period)
{
    double close1[], close2[];
    ArraySetAsSeries(close1, true);
    ArraySetAsSeries(close2, true);

    CopyClose(symbol1, PERIOD_D1, 0, period, close1);
    CopyClose(symbol2, PERIOD_D1, 0, period, close2);

    // Calculate means
    double mean1 = 0, mean2 = 0;
    for(int i = 0; i < period; i++)
    {
        mean1 += close1[i];
        mean2 += close2[i];
    }
    mean1 /= period;
    mean2 /= period;

    // Calculate correlation
    double sum_xy = 0, sum_xx = 0, sum_yy = 0;
    for(int i = 0; i < period; i++)
    {
        double x = close1[i] - mean1;
        double y = close2[i] - mean2;
        sum_xy += x * y;
        sum_xx += x * x;
        sum_yy += y * y;
    }

    double correlation = sum_xy / MathSqrt(sum_xx * sum_yy);
    return correlation;
}

Multi-Currency EA Architecture

Core Components

// Input parameters
input string   TradingPairs = "EURUSD,GBPUSD,USDJPY,AUDUSD";
input double   RiskPerTrade = 1.0;       // Risk per trade %
input double   MaxTotalRisk = 5.0;       // Maximum total risk %
input double   MaxCorrelatedRisk = 3.0;  // Max risk in correlated pairs
input int      MagicNumber = 12345;

// Global arrays
string pairs[];
int pairCount;

Initialization

int OnInit()
{
    // Parse trading pairs
    pairCount = StringSplit(TradingPairs, ',', pairs);

    // Validate symbols
    for(int i = 0; i < pairCount; i++)
    {
        StringTrimLeft(pairs[i]);
        StringTrimRight(pairs[i]);

        if(!SymbolSelect(pairs[i], true))
        {
            Print("Symbol not available: ", pairs[i]);
            return(INIT_FAILED);
        }
    }

    Print("Trading ", pairCount, " pairs");
    return(INIT_SUCCEEDED);
}

Main Trading Loop

void OnTick()
{
    // Check each pair for signals
    for(int i = 0; i < pairCount; i++)
    {
        string symbol = pairs[i];

        // Skip if new bar hasn't formed
        if(!IsNewBar(symbol)) continue;

        // Check risk limits
        if(!CanOpenPosition(symbol)) continue;

        // Generate signal
        int signal = GenerateSignal(symbol);

        if(signal != 0)
        {
            ExecuteTrade(symbol, signal);
        }
    }

    // Manage all open positions
    ManageOpenPositions();
}

Signal Generation Per Pair

int GenerateSignal(string symbol)
{
    // Get indicator handles
    int maFastHandle = iMA(symbol, PERIOD_H1, 20, 0, MODE_EMA, PRICE_CLOSE);
    int maSlowHandle = iMA(symbol, PERIOD_H1, 50, 0, MODE_EMA, PRICE_CLOSE);

    double maFast[], maSlow[];
    ArraySetAsSeries(maFast, true);
    ArraySetAsSeries(maSlow, true);

    CopyBuffer(maFastHandle, 0, 0, 3, maFast);
    CopyBuffer(maSlowHandle, 0, 0, 3, maSlow);

    // Check for crossover
    if(maFast[1] > maSlow[1] && maFast[2] <= maSlow[2])
        return 1;  // Buy signal

    if(maFast[1] < maSlow[1] && maFast[2] >= maSlow[2])
        return -1; // Sell signal

    return 0;  // No signal
}

Portfolio Risk Management

Track Total Exposure

double GetTotalRisk()
{
    double totalRisk = 0;
    double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);

    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong ticket = PositionGetTicket(i);
        if(ticket > 0 && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
        {
            double positionRisk = CalculatePositionRisk(ticket);
            totalRisk += positionRisk;
        }
    }

    return (totalRisk / accountBalance) * 100;
}

double CalculatePositionRisk(ulong ticket)
{
    if(!PositionSelectByTicket(ticket)) return 0;

    double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
    double sl = PositionGetDouble(POSITION_SL);
    double volume = PositionGetDouble(POSITION_VOLUME);
    string symbol = PositionGetString(POSITION_SYMBOL);

    if(sl == 0) return 0;  // No stop loss

    double tickValue = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_VALUE);
    double tickSize = SymbolInfoDouble(symbol, SYMBOL_TRADE_TICK_SIZE);

    double priceDiff = MathAbs(openPrice - sl);
    double risk = (priceDiff / tickSize) * tickValue * volume;

    return risk;
}

Correlation-Aware Position Sizing

bool CanOpenPosition(string symbol)
{
    double currentRisk = GetTotalRisk();

    // Check total risk limit
    if(currentRisk >= MaxTotalRisk)
    {
        Print("Max total risk reached: ", currentRisk, "%");
        return false;
    }

    // Check correlated risk
    double correlatedRisk = GetCorrelatedRisk(symbol);
    if(correlatedRisk >= MaxCorrelatedRisk)
    {
        Print("Max correlated risk for ", symbol, ": ", correlatedRisk, "%");
        return false;
    }

    return true;
}

double GetCorrelatedRisk(string newSymbol)
{
    double correlatedRisk = 0;
    double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE);

    for(int i = PositionsTotal() - 1; i >= 0; i--)
    {
        ulong ticket = PositionGetTicket(i);
        if(ticket > 0 && PositionGetInteger(POSITION_MAGIC) == MagicNumber)
        {
            string existingSymbol = PositionGetString(POSITION_SYMBOL);

            // Calculate correlation
            double corr = CalculateCorrelation(newSymbol, existingSymbol, 30);

            // If highly correlated, add to risk
            if(MathAbs(corr) > 0.7)
            {
                double posRisk = CalculatePositionRisk(ticket);
                correlatedRisk += (posRisk / accountBalance) * 100 * MathAbs(corr);
            }
        }
    }

    return correlatedRisk;
}

Python Multi-Currency System

import pandas as pd
import numpy as np
from typing import Dict, List

class MultiCurrencyTrader:
    def __init__(self, pairs: List[str], risk_per_trade: float = 1.0,
                 max_total_risk: float = 5.0):
        self.pairs = pairs
        self.risk_per_trade = risk_per_trade
        self.max_total_risk = max_total_risk
        self.positions = {}
        self.correlation_matrix = None

    def calculate_correlation_matrix(self, data: Dict[str, pd.DataFrame],
                                    period: int = 30) -> pd.DataFrame:
        """Calculate correlation matrix for all pairs"""
        closes = pd.DataFrame()

        for pair in self.pairs:
            if pair in data:
                closes[pair] = data[pair]['close'].tail(period)

        self.correlation_matrix = closes.corr()
        return self.correlation_matrix

    def get_correlated_pairs(self, symbol: str,
                            threshold: float = 0.7) -> List[str]:
        """Find pairs highly correlated with symbol"""
        if self.correlation_matrix is None:
            return []

        correlated = []
        for pair in self.pairs:
            if pair != symbol:
                corr = self.correlation_matrix.loc[symbol, pair]
                if abs(corr) >= threshold:
                    correlated.append((pair, corr))

        return correlated

    def calculate_total_risk(self) -> float:
        """Calculate total portfolio risk"""
        total = 0
        for symbol, pos in self.positions.items():
            total += pos['risk_amount']
        return total

    def can_open_position(self, symbol: str) -> bool:
        """Check if new position is allowed"""
        current_risk = self.calculate_total_risk()

        if current_risk >= self.max_total_risk:
            print(f"Max total risk reached: {current_risk}%")
            return False

        # Check correlated exposure
        correlated = self.get_correlated_pairs(symbol)
        correlated_risk = 0

        for pair, corr in correlated:
            if pair in self.positions:
                correlated_risk += self.positions[pair]['risk_amount'] * abs(corr)

        if correlated_risk >= self.max_total_risk / 2:
            print(f"High correlated exposure for {symbol}")
            return False

        return True

    def generate_signals(self, data: Dict[str, pd.DataFrame]) -> Dict[str, int]:
        """Generate signals for all pairs"""
        signals = {}

        for pair in self.pairs:
            if pair not in data:
                continue

            df = data[pair]

            # Simple MA crossover signal
            fast_ma = df['close'].rolling(20).mean()
            slow_ma = df['close'].rolling(50).mean()

            if fast_ma.iloc[-1] > slow_ma.iloc[-1] and \
               fast_ma.iloc[-2] <= slow_ma.iloc[-2]:
                signals[pair] = 1

            elif fast_ma.iloc[-1] < slow_ma.iloc[-1] and \
                 fast_ma.iloc[-2] >= slow_ma.iloc[-2]:
                signals[pair] = -1

        return signals

    def run_portfolio(self, data: Dict[str, pd.DataFrame]):
        """Main portfolio trading logic"""
        # Update correlations
        self.calculate_correlation_matrix(data)

        # Generate signals
        signals = self.generate_signals(data)

        # Process signals
        for pair, signal in signals.items():
            if self.can_open_position(pair):
                self.execute_trade(pair, signal, data[pair])

    def execute_trade(self, symbol: str, signal: int, data: pd.DataFrame):
        """Execute trade with proper sizing"""
        direction = "BUY" if signal == 1 else "SELL"
        print(f"Opening {direction} on {symbol}")
        # Add broker execution logic

# Usage
trader = MultiCurrencyTrader(
    pairs=['EURUSD', 'GBPUSD', 'USDJPY', 'AUDUSD'],
    risk_per_trade=1.0,
    max_total_risk=5.0
)

Portfolio Performance Tracking

`mql5 struct PairPerformance { string symbol; int totalTrades; int wins; double totalProfit; double maxDrawdown; };

PairPerformance pairStats[];

void UpdatePairStats(string symbol, double profit, bool isWin) { for(int i = 0; i < ArraySize(pairStats); i++) { if(pairStats[i].symbol == symbol) { pairStats[i].totalTrades++; pairStats[i].totalProfit += profit; if(isWin) pairStats[i].wins++; return; } }

// New pair int size = ArraySize(pairStats); ArrayResize(pairStats, size + 1); pairStats[size].symbol = symbol; pairStats[size].totalTrades = 1; pairStats[size].wins = isWin ? 1 : 0; pairStats[size].totalProfit = profit; }

void PrintPortfolioReport() { Print("=== Portfolio Performance ===");

for(int i = 0; i < ArraySize(pairStats); i++) { double winRate = 0; if(pairStats[i].totalTrades > 0) winRate = (double)pairStats[i].wins / pairStats[i].totalTrades * 100;

Print(pairStats[i].symbol, ": ", "Trades=", pairStats[i].totalTrades, ", ", "Win Rate=", DoubleToString(winRate, 1), "%, ", "Profit=", DoubleToString(pairStats[i].totalProfit, 2)); } } ``

Key Takeaways

  • Multi-currency trading provides diversification
  • Understand and monitor pair correlations
  • Limit total and correlated risk exposure
  • Track performance per pair separately
  • Use proper position sizing across portfolio
  • Test thoroughly with multiple pairs
  • Consider execution timing across pairs

What's Next?

Explore machine learning techniques to enhance your trading system predictions.


This article is for educational purposes only and does not constitute financial advice.

Risk warning. This is education only, not financial, investment, tax or legal advice, and not a recommendation to buy or sell anything. Trading forex, CFDs, stocks, commodities, futures, options and crypto is high-risk; with leverage you can lose more than you deposit, and most retail traders lose money. Before you trade or invest in any form, check the local laws where you are and the rules of your country of residence, and consider your own financial situation; if in doubt, ask a licensed adviser. Past and tested results, and all examples, are for illustration only and do not guarantee future results.

Get the strategy right before you automate it

An automated system is only as good as the rules behind it. The book series covers building and testing those rules before a line of code is written.

Explore the books