IC Markets

Correlated Pairs = Correlated Risk

Master exponential money management, position sizing calculators, strict daily stop-loss limits, and overcoming FOMO on micro-timeframes.
Fairman
Posts: 606
Joined: Tue Jul 21, 2026 7:11 am
Location: Abuja

Correlated Pairs = Correlated Risk

Post by Fairman »

Running simultaneous scalps on EUR/USD and GBP/USD at the same time might feel like diversification. It isn't. Both pairs share heavy exposure to overall USD strength or weakness, which means you're not running two independent trades — you're running one trade, doubled, without necessarily realizing it.

This matters enormously for risk sizing. If you calculated 1% risk on each of those two positions separately, thinking you had 2% total exposure, the reality during a strong USD move might functionally be closer to 2% moving in the same direction at once — which is a very different risk profile than two genuinely uncorrelated 1% positions.

Before stacking multiple simultaneous trades, take a moment to actually check pair correlation. Some pairs move together consistently (EUR/USD and GBP/USD, for example, or AUD/USD and NZD/USD), while others tend to move in opposite directions (EUR/USD and USD/CHF historically, for instance). Correlation isn't static — it shifts with market conditions — so it's worth checking periodically rather than assuming last year's relationships still hold.

The core lesson: what looks like two "different" positions on your platform can quietly be one much larger risk in disguise. Always ask what's really driving each trade before assuming they're independent.
It’s Fairman :geek:
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Hi Fairman.

Spot on. The "illusion of diversification" is one of the most expensive lessons a trader can learn.

When you stack highly correlated pairs, you aren't just doubling your directional risk; you are also tying up twice as much margin to execute what is functionally the exact same trade. If the USD suddenly spikes due to unexpected macro news, both of those "independent" stop-losses are going to get hit at the exact same time.

As you pointed out, correlation is dynamic. A pair that was negatively correlated last quarter might synchronize this quarter due to shifting central bank policies or geopolitical events.

To help visualize this, I actually put together a lightweight MT4 Expert Advisor (EA) that dynamically monitors this. It scans your currently open positions, calculates the real-time Pearson correlation between the underlying symbols, and outputs the average portfolio correlation directly on your chart. It’s a great way to catch yourself before you accidentally over-leverage a single currency exposure. Happy to share the code if anyone wants to run it!
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

And i prepared some scripts, which will help to see corelation in your actual portfolio.

The MT4 Script (MQL4)

This script is built as an Expert Advisor (EA) so that it can run continuously using the OnTick() function, providing a live "Heads Up Display" (HUD) on your chart.

It works by:

Scanning your terminal for all open market trades.

Isolating the unique symbols you are currently trading.

Calculating the pairwise Pearson correlation coefficient between them.

Averaging them out to give you a "Medium Portfolio Correlation" score from -1.0 (perfectly inverse) to +1.0 (perfectly correlated).

Code snippet

Code: Select all

//+------------------------------------------------------------------+
//|                                    OpenPositionsCorrelation.mq4  |
//|                                                                  |
//+------------------------------------------------------------------+
#property strict

//--- Input parameters
extern int    CorrelationPeriods = 100;       // Number of bars to check
extern ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for calculation

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
     string symbols[];
     int totalOrders = OrdersTotal();
     int symbolCount = 0;

     // 1. Gather unique symbols of currently open positions
     for(int i = 0; i < totalOrders; i++)
       {
          if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderType() <= OP_SELL) // Only active market orders (Buy/Sell)
                 {
                    bool exists = false;
                    for(int j = 0; j < symbolCount; j++)
                      {
                         if(symbols[j] == OrderSymbol())
                           {
                              exists = true;
                              break;
                           }
                      }
                    if(!exists) // Add new unique symbol to array
                      {
                         ArrayResize(symbols, symbolCount + 1);
                         symbols[symbolCount] = OrderSymbol();
                         symbolCount++;
                      }
                 }
            }
       }

     // 2. Check if we have enough symbols to compare
     if(symbolCount < 2)
       {
          Comment("--- Live Position Correlation ---\n",
                  "Not enough distinct symbols traded.\n",
                  "Open positions on at least 2 different pairs to calculate.");
          return;
       }

     double totalCorrelation = 0;
     int pairCount = 0;
     string output = "--- Live Position Correlation ---\n";

     // 3. Calculate pairwise correlation for all open symbols
     for(int i = 0; i < symbolCount - 1; i++)
       {
          for(int j = i + 1; j < symbolCount; j++)
            {
               double corr = CalculatePearson(symbols[i], symbols[j], CorrelationPeriods, TimeFrame);
               totalCorrelation += corr;
               pairCount++;
               
               // Output individual pair correlations
               output += symbols[i] + " & " + symbols[j] + " : " + DoubleToStr(corr, 2) + "\n";
            }
       }

     // 4. Calculate and display the overall average correlation
     double avgCorrelation = totalCorrelation / pairCount;
     output += "---------------------------------\n";
     output += "Average Portfolio Correlation: " + DoubleToStr(avgCorrelation, 2);

     Comment(output);
  }

//+------------------------------------------------------------------+
//| Pearson Correlation Mathematical Function                        |
//+------------------------------------------------------------------+
double CalculatePearson(string sym1, string sym2, int periods, int tf)
  {
     double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0;
     int validBars = 0;

     for(int i = 1; i <= periods; i++)
       {
          // Fetch close prices for the specific historical bars
          double price1 = iClose(sym1, tf, i);
          double price2 = iClose(sym2, tf, i);

          // Skip if chart data isn't loaded yet
          if(price1 == 0 || price2 == 0) continue; 

          sumX  += price1;
          sumY  += price2;
          sumXY += (price1 * price2);
          sumX2 += MathPow(price1, 2);
          sumY2 += MathPow(price2, 2);
          validBars++;
       }

     if(validBars == 0) return 0;

     // Calculate Pearson coefficient
     double numerator = (validBars * sumXY) - (sumX * sumY);
     double denominator = MathSqrt(((validBars * sumX2) - MathPow(sumX, 2)) * ((validBars * sumY2) - MathPow(sumY, 2)));

     if(denominator == 0) return 0;

     return numerator / denominator;
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

How to install and use it:

1.Open MetaEditor:

In your MT4 terminal, press F4 to open the MetaQuotes Language Editor.

2.Create a new Expert Advisor:

Click New -> Expert Advisor (template). Name it something like PositionCorrelationMonitor.

3.Paste and Compile:

Delete the default code, paste the code provided above, and hit Compile (F7). Ensure there are no errors in the bottom log.

4.Attach to a chart:

Go back to MT4, find the EA in your Navigator panel, and drag it onto any open chart.Note: The EA defaults to checking the last 100 hours (H1 timeframe) to gauge the current short-term correlation, but you can adjust these settings in the EA's Input tab when you attach it to the chart.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Plus one of the best way how to improve it is add alerts:

To add alerts and push notifications, we need to introduce a few new input variables so you can control the threshold and toggle the alerts on or off.

More importantly, because this script runs inside the OnTick() function (which executes every single time the price changes—potentially dozens of times a second), we have to include a cooldown timer. Without a cooldown timer, your phone and MT4 terminal would be instantly bombarded with hundreds of notifications the second your correlation hit +0.81.

Here is the fully updated script with the new alert logic and a built-in anti-spam cooldown feature.

The Updated MT4 Script

You can copy and paste this directly over your existing code:

Code: Select all

//+------------------------------------------------------------------+
//|                                    OpenPositionsCorrelation.mq4  |
//|                                                                  |
//+------------------------------------------------------------------+
#property strict

//--- Core Input parameters
extern int    CorrelationPeriods = 100;       // Number of bars to check
extern ENUM_TIMEFRAMES TimeFrame = PERIOD_H1; // Timeframe for calculation

//--- Alert Input parameters
extern double AlertThreshold = 0.80;          // Alert when correlation exceeds this level
extern bool   EnablePopupAlert = true;        // Show MT4 popup alert
extern bool   EnablePushNotification = false; // Send mobile push notification
extern int    AlertCooldownMinutes = 60;      // Minimum minutes between alerts

//--- Global variables
datetime lastAlertTime = 0;                   // Tracks the time of the last alert

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
     string symbols[];
     int totalOrders = OrdersTotal();
     int symbolCount = 0;

     // 1. Gather unique symbols of currently open positions
     for(int i = 0; i < totalOrders; i++)
       {
          if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
            {
               if(OrderType() <= OP_SELL) // Only active market orders (Buy/Sell)
                 {
                    bool exists = false;
                    for(int j = 0; j < symbolCount; j++)
                      {
                         if(symbols[j] == OrderSymbol())
                           {
                              exists = true;
                              break;
                           }
                      }
                    if(!exists) // Add new unique symbol to array
                      {
                         ArrayResize(symbols, symbolCount + 1);
                         symbols[symbolCount] = OrderSymbol();
                         symbolCount++;
                      }
                 }
            }
       }

     // 2. Check if we have enough symbols to compare
     if(symbolCount < 2)
       {
          Comment("--- Live Position Correlation ---\n",
                  "Not enough distinct symbols traded.\n",
                  "Open positions on at least 2 different pairs to calculate.");
          return;
       }

     double totalCorrelation = 0;
     int pairCount = 0;
     string output = "--- Live Position Correlation ---\n";

     // 3. Calculate pairwise correlation for all open symbols
     for(int i = 0; i < symbolCount - 1; i++)
       {
          for(int j = i + 1; j < symbolCount; j++)
            {
               double corr = CalculatePearson(symbols[i], symbols[j], CorrelationPeriods, TimeFrame);
               totalCorrelation += corr;
               pairCount++;
               
               output += symbols[i] + " & " + symbols[j] + " : " + DoubleToStr(corr, 2) + "\n";
            }
       }

     // 4. Calculate and display the overall average correlation
     double avgCorrelation = totalCorrelation / pairCount;
     output += "---------------------------------\n";
     output += "Average Portfolio Correlation: " + DoubleToStr(avgCorrelation, 2);

     Comment(output);
     
     // 5. Trigger Alerts if Threshold is breached
     if(avgCorrelation >= AlertThreshold)
       {
          // Check if enough time has passed since the last alert to prevent spam
          if(TimeCurrent() >= lastAlertTime + (AlertCooldownMinutes * 60))
            {
               string alertMsg = "RISK WARNING: High portfolio correlation detected (" + DoubleToStr(avgCorrelation, 2) + ").";
               
               if(EnablePopupAlert) Alert(alertMsg);
               if(EnablePushNotification) SendNotification(alertMsg);
               
               // Record the time this alert was sent
               lastAlertTime = TimeCurrent();
            }
       }
  }

//+------------------------------------------------------------------+
//| Pearson Correlation Mathematical Function                        |
//+------------------------------------------------------------------+
double CalculatePearson(string sym1, string sym2, int periods, int tf)
  {
     double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0;
     int validBars = 0;

     for(int i = 1; i <= periods; i++)
       {
          double price1 = iClose(sym1, tf, i);
          double price2 = iClose(sym2, tf, i);

          if(price1 == 0 || price2 == 0) continue; 

          sumX  += price1;
          sumY  += price2;
          sumXY += (price1 * price2);
          sumX2 += MathPow(price1, 2);
          sumY2 += MathPow(price2, 2);
          validBars++;
       }

     if(validBars == 0) return 0;

     double numerator = (validBars * sumXY) - (sumX * sumY);
     double denominator = MathSqrt(((validBars * sumX2) - MathPow(sumX, 2)) * ((validBars * sumY2) - MathPow(sumY, 2)));

     if(denominator == 0) return 0;

     return numerator / denominator;
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

How to Enable Push Notifications in MT4

If you haven't used mobile push notifications in MT4 before, the SendNotification() function won't do anything until you link your phone to your desktop terminal.

1.Get your MetaQuotes ID:

Open the MT4 app on your mobile phone. Go to Settings -> Chat and Messages. At the bottom, you will see an 8-character string called your MetaQuotes ID.

2.Link your Desktop Terminal:

On your computer's MT4 terminal, go to Tools -> Options (or press Ctrl+O) and select the Notifications tab.

3.Enable Push:

Check the box for "Enable Push Notifications" and type your 8-character MetaQuotes ID into the box.

4.Test the Connection:

Click the "Test" button. Your phone should immediately receive a ping. Once confirmed, click OK.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Here is the fully converted script for MetaTrader 5 (MQL5). It includes the real-time correlation HUD, the +0.80 threshold alert, and the anti-spam cooldown timer you requested.

MQL5 is built quite differently from MQL4 under the hood. Here is what changed to make this run natively and efficiently in MT5:

Positions vs. Orders: In MT4, everything is an "Order". In MT5, pending trades are "Orders" but live trades are "Positions". The script now loops through PositionsTotal() and PositionGetSymbol() to fetch your live exposure.

Native Array Copying: Instead of looping backwards bar-by-bar using iClose(), MQL5 uses CopyClose() to grab the entire array of historical prices in a single, hyper-efficient block of memory.

Syntax Updates: extern has been modernized to input, and DoubleToStr is now DoubleToString.

The MT5 Script (MQL5)

Code: Select all

//+------------------------------------------------------------------+
//|                                    OpenPositionsCorrelation.mq5  |
//|                                                                  |
//+------------------------------------------------------------------+

//--- Core Input parameters
input int             CorrelationPeriods = 100;       // Number of bars to check
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;          // Timeframe for calculation

//--- Alert Input parameters
input double AlertThreshold = 0.80;          // Alert when correlation exceeds this level
input bool   EnablePopupAlert = true;        // Show MT5 popup alert
input bool   EnablePushNotification = false; // Send mobile push notification
input int    AlertCooldownMinutes = 60;      // Minimum minutes between alerts

//--- Global variables
datetime lastAlertTime = 0;                  // Tracks the time of the last alert

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
     string symbols[];
     int totalPositions = PositionsTotal();
     int symbolCount = 0;

     // 1. Gather unique symbols of currently open positions
     for(int i = 0; i < totalPositions; i++)
       {
          string currentSymbol = PositionGetSymbol(i);
          if(currentSymbol != "")
            {
               bool exists = false;
               for(int j = 0; j < symbolCount; j++)
                 {
                    if(symbols[j] == currentSymbol)
                      {
                         exists = true;
                         break;
                      }
                 }
               if(!exists) // Add new unique symbol to array
                 {
                    ArrayResize(symbols, symbolCount + 1);
                    symbols[symbolCount] = currentSymbol;
                    symbolCount++;
                 }
            }
       }

     // 2. Check if we have enough symbols to compare
     if(symbolCount < 2)
       {
          Comment("--- Live Position Correlation ---\n",
                  "Not enough distinct symbols traded.\n",
                  "Open positions on at least 2 different pairs to calculate.");
          return;
       }

     double totalCorrelation = 0;
     int pairCount = 0;
     string output = "--- Live Position Correlation ---\n";

     // 3. Calculate pairwise correlation for all open symbols
     for(int i = 0; i < symbolCount - 1; i++)
       {
          for(int j = i + 1; j < symbolCount; j++)
            {
               double corr = CalculatePearson(symbols[i], symbols[j], CorrelationPeriods, TimeFrame);
               totalCorrelation += corr;
               pairCount++;
               
               output += symbols[i] + " & " + symbols[j] + " : " + DoubleToString(corr, 2) + "\n";
            }
       }

     // 4. Calculate and display the overall average correlation
     double avgCorrelation = totalCorrelation / pairCount;
     output += "---------------------------------\n";
     output += "Average Portfolio Correlation: " + DoubleToString(avgCorrelation, 2);

     Comment(output);
     
     // 5. Trigger Alerts if Threshold is breached
     if(avgCorrelation >= AlertThreshold)
       {
          // Check if enough time has passed since the last alert to prevent spam
          if(TimeCurrent() >= lastAlertTime + (AlertCooldownMinutes * 60))
            {
               string alertMsg = "RISK WARNING: High portfolio correlation detected (" + DoubleToString(avgCorrelation, 2) + ").";
               
               if(EnablePopupAlert) Alert(alertMsg);
               if(EnablePushNotification) SendNotification(alertMsg);
               
               // Record the time this alert was sent
               lastAlertTime = TimeCurrent();
            }
       }
  }

//+------------------------------------------------------------------+
//| Pearson Correlation Mathematical Function                        |
//+------------------------------------------------------------------+
double CalculatePearson(string sym1, string sym2, int periods, ENUM_TIMEFRAMES tf)
  {
     double close1[], close2[];
     
     // In MQL5, CopyClose grabs data in bulk natively. 
     // '1' as the start position means we skip the current unclosed bar.
     int copied1 = CopyClose(sym1, tf, 1, periods, close1);
     int copied2 = CopyClose(sym2, tf, 1, periods, close2);

     // Ensure data was successfully loaded
     if(copied1 <= 0 || copied2 <= 0) return 0.0;
     
     int validBars = MathMin(copied1, copied2);
     if(validBars < 2) return 0.0;

     double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0;

     for(int i = 0; i < validBars; i++)
       {
          double price1 = close1[i];
          double price2 = close2[i];

          sumX  += price1;
          sumY  += price2;
          sumXY += (price1 * price2);
          sumX2 += MathPow(price1, 2);
          sumY2 += MathPow(price2, 2);
       }

     double numerator = (validBars * sumXY) - (sumX * sumY);
     double denominator = MathSqrt(((validBars * sumX2) - MathPow(sumX, 2)) * ((validBars * sumY2) - MathPow(sumY, 2)));

     if(denominator == 0.0) return 0.0;

     return numerator / denominator;
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

Installation in MT5

1.Open MetaEditor 5:

In your MT5 terminal, press F4 to open the MetaEditor.

2.Create a new Expert Advisor:

Click New -> Expert Advisor (template). Name it PositionCorrelationMonitor.

3.Paste and Compile:

Highlight all the default code, delete it, and paste the MQL5 code provided above. Press Compile (F7).

4.Run it:

Return to your MT5 terminal. Expand the Expert Advisors tab in your Navigator panel, find the new EA, and drag it onto your chart. Ensure you enable push notifications in MT5's tools if you toggled them on in the inputs.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

To filter out your smaller test trades, we need to introduce a new input variable for the minimum lot size and modify the position-scanning loop to check the volume of each trade using MQL5's PositionGetDouble(POSITION_VOLUME) function.

If a trade's volume is below your threshold, the script will simply skip it and not include that symbol in the correlation math.

Here is the fully updated script. I added a MinLotSize input so you can easily adjust this limit directly from the MT5 EA settings without needing to recompile the code every time.

The Updated MT5 Script (with Volume Filter)

Code: Select all

//+------------------------------------------------------------------+
//|                                    OpenPositionsCorrelation.mq5  |
//|                                                                  |
//+------------------------------------------------------------------+

//--- Core Input parameters
input int             CorrelationPeriods = 100;       // Number of bars to check
input ENUM_TIMEFRAMES TimeFrame = PERIOD_H1;          // Timeframe for calculation

//--- Position Filter Input
input double          MinLotSize = 0.50;              // Minimum position size to include (Lots)

//--- Alert Input parameters
input double AlertThreshold = 0.80;          // Alert when correlation exceeds this level
input bool   EnablePopupAlert = true;        // Show MT5 popup alert
input bool   EnablePushNotification = false; // Send mobile push notification
input int    AlertCooldownMinutes = 60;      // Minimum minutes between alerts

//--- Global variables
datetime lastAlertTime = 0;                  // Tracks the time of the last alert

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
     string symbols[];
     int totalPositions = PositionsTotal();
     int symbolCount = 0;

     // 1. Gather unique symbols of currently open positions
     for(int i = 0; i < totalPositions; i++)
       {
          string currentSymbol = PositionGetSymbol(i);
          double currentVolume = PositionGetDouble(POSITION_VOLUME);
          
          // Only process if the symbol is valid AND the position size meets the minimum requirement
          if(currentSymbol != "" && currentVolume >= MinLotSize)
            {
               bool exists = false;
               for(int j = 0; j < symbolCount; j++)
                 {
                    if(symbols[j] == currentSymbol)
                      {
                         exists = true;
                         break;
                      }
                 }
               if(!exists) // Add new unique symbol to array
                 {
                    ArrayResize(symbols, symbolCount + 1);
                    symbols[symbolCount] = currentSymbol;
                    symbolCount++;
                 }
            }
       }

     // 2. Check if we have enough valid symbols to compare
     if(symbolCount < 2)
       {
          Comment("--- Live Position Correlation ---\n",
                  "Not enough symbols meeting the minimum lot size (" + DoubleToString(MinLotSize, 2) + ").\n",
                  "Need eligible positions on at least 2 different pairs.");
          return;
       }

     double totalCorrelation = 0;
     int pairCount = 0;
     string output = "--- Live Position Correlation ---\n";
     output += "(Ignoring trades under " + DoubleToString(MinLotSize, 2) + " lots)\n\n";

     // 3. Calculate pairwise correlation for all eligible symbols
     for(int i = 0; i < symbolCount - 1; i++)
       {
          for(int j = i + 1; j < symbolCount; j++)
            {
               double corr = CalculatePearson(symbols[i], symbols[j], CorrelationPeriods, TimeFrame);
               totalCorrelation += corr;
               pairCount++;
               
               output += symbols[i] + " & " + symbols[j] + " : " + DoubleToString(corr, 2) + "\n";
            }
       }

     // 4. Calculate and display the overall average correlation
     double avgCorrelation = totalCorrelation / pairCount;
     output += "---------------------------------\n";
     output += "Average Portfolio Correlation: " + DoubleToString(avgCorrelation, 2);

     Comment(output);
     
     // 5. Trigger Alerts if Threshold is breached
     if(avgCorrelation >= AlertThreshold)
       {
          // Check if enough time has passed since the last alert to prevent spam
          if(TimeCurrent() >= lastAlertTime + (AlertCooldownMinutes * 60))
            {
               string alertMsg = "RISK WARNING: High portfolio correlation detected (" + DoubleToString(avgCorrelation, 2) + ").";
               
               if(EnablePopupAlert) Alert(alertMsg);
               if(EnablePushNotification) SendNotification(alertMsg);
               
               // Record the time this alert was sent
               lastAlertTime = TimeCurrent();
            }
       }
  }

//+------------------------------------------------------------------+
//| Pearson Correlation Mathematical Function                        |
//+------------------------------------------------------------------+
double CalculatePearson(string sym1, string sym2, int periods, ENUM_TIMEFRAMES tf)
  {
     double close1[], close2[];
     
     int copied1 = CopyClose(sym1, tf, 1, periods, close1);
     int copied2 = CopyClose(sym2, tf, 1, periods, close2);

     if(copied1 <= 0 || copied2 <= 0) return 0.0;
     
     int validBars = MathMin(copied1, copied2);
     if(validBars < 2) return 0.0;

     double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0, sumY2 = 0;

     for(int i = 0; i < validBars; i++)
       {
          double price1 = close1[i];
          double price2 = close2[i];

          sumX  += price1;
          sumY  += price2;
          sumXY += (price1 * price2);
          sumX2 += MathPow(price1, 2);
          sumY2 += MathPow(price2, 2);
       }

     double numerator = (validBars * sumXY) - (sumX * sumY);
     double denominator = MathSqrt(((validBars * sumX2) - MathPow(sumX, 2)) * ((validBars * sumY2) - MathPow(sumY, 2)));

     if(denominator == 0.0) return 0.0;

     return numerator / denominator;
  }
//+------------------------------------------------------------------+
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
PTScalper
Site Admin
Posts: 1114
Joined: Mon Jul 20, 2026 1:28 pm

Re: Correlated Pairs = Correlated Risk

Post by PTScalper »

What Changed:

Added input double MinLotSize = 0.50; at the top of the script.

In the OnTick() function, the script now retrieves the lot size of each trade using double currentVolume = PositionGetDouble(POSITION_VOLUME);.

The if statement logic now strictly checks currentVolume >= MinLotSize before validating that symbol for the calculation.

The on-chart Comment() HUD was updated so that it visibly reminds you that it is actively ignoring trades beneath your threshold.
Preserve your own money. Scale with the market's money. Exponential growth is the ultimate key.
Post Reply