Page 1 of 1

Using the PCA (Principal Component Analysis) Trend Vector for High-Probability Scalping

Posted: Mon Aug 10, 2026 3:35 pm
by PTScalper
Hi scalpers/traders,

I’ve been experimenting heavily with quantitative concepts lately, and I wanted to share a highly effective way to filter out market noise when scalping the lower timeframes (M1 and M5). It involves a concept borrowed from data science called Principal Component Analysis (PCA).

What is a PCA Trend Vector?
In data science, PCA is used to reduce the dimensions of a massive dataset while preserving its core variance. In simple terms, it finds the "path of least resistance" or the strongest underlying pattern in a chaotic scatterplot of data.

When we apply a simplified 2D PCA (Price vs. Time) to Forex, the First Principal Component gives us a Trend Vector. Instead of looking at erratic, noisy candlesticks that constantly fake out, this vector calculates the exact mathematical line of maximum variance over a given period.

If you are scalping, you don't care about the noise; you only care about the core vector of the market at that exact moment.

How to Use it for Scalping
The strategy here is not to use the PCA vector as an entry trigger, but as a strict directional filter.

Timeframe: M1 or M5.

The Rule: When the PCA Vector histogram is green (positive slope), you only look for long setups. When it is red (negative slope), you only look for short setups.

The Entry: Wait for price to pull back against the vector, and use an oscillator (like a stochastic dipping below 20 in an upward vector) to snipe the entry.

Because the PCA vector mathematically cuts out the random walk of the market, you'll find that your pullbacks result in far fewer stop-outs.

The MT4 Code
True multi-dimensional PCA requires matrix algebra libraries (usually via Python integration), but in a 2-variable environment (Price and Time), the 1st Principal Component mathematically converges with the slope of a Linear Regression line.

Here is a lightweight custom indicator I wrote for MT4. It calculates the core vector slope and plots it as a histogram.

How to install: Open MetaEditor, create a new Custom Indicator named PCA_TrendVector, paste this code, and compile.

Code: Select all

//+------------------------------------------------------------------+
//|                                              PCA_TrendVector.mq4 |
//|                             Approximation of 1D PCA (Regression) |
//+------------------------------------------------------------------+
#property copyright "Forum Community"
#property strict
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_color1 clrLime
#property indicator_color2 clrRed
#property indicator_width1 2
#property indicator_width2 2

input int PCAPeriod = 20; // Period for the PCA Vector

double UpVector[];
double DnVector[];

int OnInit() {
    SetIndexBuffer(0, UpVector);
    SetIndexStyle(0, DRAW_HISTOGRAM);
    SetIndexBuffer(1, DnVector);
    SetIndexStyle(1, DRAW_HISTOGRAM);
    IndicatorShortName("PCA Trend Vector (" + IntegerToString(PCAPeriod) + ")");
    return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total, const int prev_calculated,
                const datetime &time[], const double &open[],
                const double &high[], const double &low[],
                const double &close[], const long &tick_volume[],
                const long &volume[], const int &spread[]) {
                
    int limit = rates_total - prev_calculated;
    if(limit == 0) limit = 1;
    if(prev_calculated == 0) limit = rates_total - PCAPeriod - 1;

    for(int i = limit; i >= 0; i--) {
        double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
        
        // Loop backwards to align time logically (oldest to newest in the period)
        for(int j = 0; j < PCAPeriod; j++) {
            double y = close[i + PCAPeriod - 1 - j];
            double x = j;
            
            sumX += x;
            sumY += y;
            sumXY += x * y;
            sumX2 += x * x;
        }
        
        // Calculate the Primary Component Vector (Slope)
        double denominator = (PCAPeriod * sumX2) - (sumX * sumX);
        double vector_slope = 0;
        
        if(denominator != 0) {
            vector_slope = ((PCAPeriod * sumXY) - (sumX * sumY)) / denominator;
        }

        UpVector[i] = 0;
        DnVector[i] = 0;

        if(vector_slope > 0) {
            UpVector[i] = vector_slope;
        } else if(vector_slope < 0) {
            DnVector[i] = vector_slope;
        }
    }
    return(rates_total);
}
Give it a test on your M1 charts and let me know how it filters out the chop for your specific setups. Happy trading!

Re: Using the PCA (Principal Component Analysis) Trend Vector for High-Probability Scalping

Posted: Mon Aug 10, 2026 3:37 pm
by PTScalper
And here is my implementation for MT5:

The MT5 (MQL5) Code
True multi-dimensional PCA requires matrix algebra libraries, but in a 2-variable environment (Price and Time), the 1st Principal Component mathematically converges with the slope of a Linear Regression line.

Here is the custom indicator ported specifically for MT5.

How to install: Open MetaEditor 5, create a new Custom Indicator named PCA_TrendVector, paste this code, and compile.

Code: Select all

//+------------------------------------------------------------------+
//|                                              PCA_TrendVector.mq5 |
//|                             Approximation of 1D PCA (Regression) |
//+------------------------------------------------------------------+
#property copyright "Forum Community"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2

//--- plot UpVector
#property indicator_label1  "Up Vector"
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_color1  clrLime
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2

//--- plot DnVector
#property indicator_label2  "Down Vector"
#property indicator_type2   DRAW_HISTOGRAM
#property indicator_color2  clrRed
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2

input int PCAPeriod = 20; // Period for the PCA Vector

double UpVectorBuffer[];
double DnVectorBuffer[];

int OnInit()
  {
   // Indicator buffers mapping
   SetIndexBuffer(0, UpVectorBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, DnVectorBuffer, INDICATOR_DATA);
   
   IndicatorSetString(INDICATOR_SHORTNAME, "PCA Trend Vector (" + IntegerToString(PCAPeriod) + ")");
   
   return(INIT_SUCCEEDED);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
   // Wait until we have enough bars
   if(rates_total < PCAPeriod)
      return(0);

   // Set arrays as series (index 0 = current newest bar)
   ArraySetAsSeries(close, true);
   ArraySetAsSeries(UpVectorBuffer, true);
   ArraySetAsSeries(DnVectorBuffer, true);

   int limit = rates_total - prev_calculated;
   if(prev_calculated == 0)
      limit = rates_total - PCAPeriod - 1;

   // Prevent out of bounds on first run
   if(limit >= rates_total - PCAPeriod)
      limit = rates_total - PCAPeriod - 1;

   for(int i = limit; i >= 0; i--)
     {
      double sumX = 0, sumY = 0, sumXY = 0, sumX2 = 0;
      
      // Loop backwards to align time logically (oldest to newest in the period)
      for(int j = 0; j < PCAPeriod; j++)
        {
         double y = close[i + PCAPeriod - 1 - j];
         double x = j;
         
         sumX += x;
         sumY += y;
         sumXY += x * y;
         sumX2 += x * x;
        }
      
      // Calculate the Primary Component Vector (Slope)
      double denominator = (PCAPeriod * sumX2) - (sumX * sumX);
      double vector_slope = 0;
      
      if(denominator != 0)
        {
         vector_slope = ((PCAPeriod * sumXY) - (sumX * sumY)) / denominator;
        }

      UpVectorBuffer[i] = 0.0;
      DnVectorBuffer[i] = 0.0;

      if(vector_slope > 0)
        {
         UpVectorBuffer[i] = vector_slope;
        }
      else if(vector_slope < 0)
        {
         DnVectorBuffer[i] = vector_slope;
        }
     }
     
   return(rates_total);
  }
//+------------------------------------------------------------------+
Load this up on your MT5 charts and see how it cleans up the price action for your specific setups. Let me know if you run into any questions!

Re: Using the PCA (Principal Component Analysis) Trend Vector for High-Probability Scalping

Posted: Mon Aug 10, 2026 3:40 pm
by PTScalper
And finally for IC traders in Ctrader :-)

The cTrader (C#) Code
True multi-dimensional PCA requires matrix algebra libraries, but in a 2-variable environment (Price and Time), the 1st Principal Component mathematically converges with the slope of a Linear Regression line.

Here is the lightweight C# version for cTrader. It calculates the core vector slope and plots it as a histogram using the modern Bars API.

How to install: Open the cTrader Automate (cAlgo) tab, create a new Indicator named PCATrendVector, paste this code, and build it.

Code: Select all

using System;
using cAlgo.API;
using cAlgo.API.Internals;
using cAlgo.API.Indicators;
using cAlgo.Indicators;

namespace cAlgo
{
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class PCATrendVector : Indicator
    {
        [Parameter("PCA Period", DefaultValue = 20, MinValue = 2)]
        public int PCAPeriod { get; set; }

        [Output("Up Vector", LineColor = "Lime", PlotType = PlotType.Histogram, Thickness = 2)]
        public IndicatorDataSeries UpVector { get; set; }

        [Output("Down Vector", LineColor = "Red", PlotType = PlotType.Histogram, Thickness = 2)]
        public IndicatorDataSeries DnVector { get; set; }

        protected override void Initialize()
        {
            // Initialization handled via attributes
        }

        public override void Calculate(int index)
        {
            // Wait until we have enough data
            if (index < PCAPeriod)
            {
                UpVector[index] = 0;
                DnVector[index] = 0;
                return;
            }

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

            // Loop to align time logically (oldest to newest in the period)
            for (int j = 0; j < PCAPeriod; j++)
            {
                double y = Bars.ClosePrices[index - PCAPeriod + 1 + j];
                double x = j;
                
                sumX += x;
                sumY += y;
                sumXY += x * y;
                sumX2 += x * x;
            }

            // Calculate the Primary Component Vector (Slope)
            double denominator = (PCAPeriod * sumX2) - (sumX * sumX);
            double vectorSlope = 0;

            if (denominator != 0)
            {
                vectorSlope = ((PCAPeriod * sumXY) - (sumX * sumY)) / denominator;
            }

            // Reset current index
            UpVector[index] = 0;
            DnVector[index] = 0;

            // Assign to appropriate histogram buffer
            if (vectorSlope > 0)
            {
                UpVector[index] = vectorSlope;
            }
            else if (vectorSlope < 0)
            {
                DnVector[index] = vectorSlope;
            }
        }
    }
}
Load this up on your cTrader M1 charts and see how it visually cleans up the raw price action. It’s an incredibly efficient filter if you're building automated bots, too. Let me know how it handles your specific setups!

Take a care, enjoy your trading and i wish you lot of profitable trades :-)

Re: Using the PCA (Principal Component Analysis) Trend Vector for High-Probability Scalping

Posted: Sat Sep 12, 2026 9:46 am
by LondonScalper
PTScalper wrote:When we apply a simplified 2D PCA (Price vs. Time) to Forex, the First Principal Component gives us a Trend Vector.
Useful framing — though as your MT5 note implies, 2D price-vs-time PCA collapses toward a regression slope. That is fine; just call it what it is so nobody expects magic dimensionality reduction.

As a noise filter on M1/M5 I treat a steep, stable slope as “permission to look for with-trend scalps,” and a flat/unstable vector as “stand down.” It will not outperform a well-chosen regression or Kalman on its own; the value is discipline — fewer counter-slope heroes.

Watch parameter churn: if you retune the window every losing day, you have a narrative, not a filter.

Do you combine the vector with a hard session filter, or run it all day and only skip when the slope is flat?

Re: Using the PCA (Principal Component Analysis) Trend Vector for High-Probability Scalping

Posted: Sun Sep 27, 2026 7:35 pm
by PropScalpDesk
Small correction on the maths, and it's actually good news for the indicator. The first principal component of price-vs-time points isn't the OLS regression slope. PCA fits the line that minimises perpendicular distance (total least squares), and its answer depends on the units of the two axes. Measure time in bars and price in raw quotes and it changes if you just switch EURUSD to pips. The code computes plain OLS on close against bar number, which doesn't have that scaling problem, so it's the better choice. Just call it a 20-bar regression slope.

Two practical points if people use it as a filter. The histogram is in price per bar, so the same bar height means very different things on EURUSD and XAUUSD; dividing the slope by ATR(20) makes it comparable across symbols and sessions. And on M1 a 20-bar slope flips sign constantly around zero, so I'd add a dead band, something like |slope| below 0.05 × ATR per bar counts as flat and allows no trades in either direction.