State Representation Learning vs. Regime Detection for MT5 EAs

What Is State Representation Learning?

State Representation Learning is a research topic focused on converting observed data into a more useful “state” for decision-making and control instead of using raw observations as they are.

In a MetaTrader 5 Expert Advisor, prices, volume, spreads, indicator values, time of day, and recent volatility are observed data. If these values are fed directly into trading logic, the input can become too large, market meanings can get mixed together, and the logic can overfit historical data. State Representation Learning takes these observations and turns them into easier-to-use internal states such as “trend is strong,” “volatility is high,” “close to a range,” or “not enough information for a trading decision.”

This idea is often used in reinforcement learning, robotics, and time-series modeling, but it is also useful for EA development. Before trying to learn trading signals directly, organizing how the market should be represented as a state makes the design easier to validate.

Conclusion

State Representation Learning is a way to create state vectors from market data that an EA can handle more easily. In MQL5, the basic flow is to create indicator handles in OnInit, read observed values with CopyBuffer in OnTick, and build a state through normalization or categorization. In live use, you must evaluate not only the quality of the state representation but also spreads, execution, lot limits, drawdown, and forward-test degradation as separate issues.

Key Takeaways

State Representation Learning organizes observed values such as prices and indicators into a “market state” that an EA can use for decisions.

In an MT5 EA, this state representation should not be connected immediately to a “buy” or “sell” conclusion. First, use it as input for judging the market environment. For example, trend strength, volatility, distance from a moving average, and spread condition can be combined and used for entry permission or filter decisions.

When applying it to EA development, do not judge only by the apparent accuracy of the state representation. Use time-series splits, out-of-sample validation, walk-forward validation, and evaluation that includes spreads and execution differences before turning it into a live-trading design.

Beginner-Friendly Explanation

When designing an EA, it is often easier to first judge the current market state instead of trading only because the price moved up or down.

For example, the same moving-average crossover has a different meaning during a strong trend than it does in a directionless range. State Representation Learning expresses this difference as a “state” rather than as raw price data.

Examples of state representation include the following.

State ElementDescriptionHow to Use in an EA
Trend strengthUse ADX or moving-average slope to check directionUse as a condition for trend-following
VolatilityUse ATR or standard deviation to measure price movementUse for lot size, stop-loss width, and stop conditions
DeviationMeasure the distance between the current price and the moving averageCheck for overheating or pullback candidates
Spread ConditionCheck whether trading cost is within a normal rangeUse as an entry-stop condition
Time of daySeparate sessions and liquidity conditionsAvoid low-liquidity periods

In this sense, State Representation Learning is easier to understand as a model that creates a readable map, not as a model that predicts the answer by itself.

How It Differs From Regime Detection

Regime Detection classifies the market into states such as trend, range, high volatility, and low volatility. State Representation Learning is the broader idea of creating the inputs or internal representation used for that classification and for other decisions.

ViewpointState Representation LearningRegime Detection
Main PurposeConvert observed data into a usable stateClassify the market environment
OutputContinuous vectors, scores, or featuresState labels or classes
How to Use in an EAFilters, model inputs, and risk adjustmentSwitching trading rules
NotesA representation is not always useful for tradingClassification can lag

For EA implementation, it is practical to start with handcrafted state representations. By combining ADX, ATR, moving averages, spreads, and time of day, you can build the foundation of a state representation without using complex deep learning.

State representation learning workflow for MT5 EA design showing MQL5 CopyBuffer logic, Python validation, a regime state map, and risk controls

How to Use It in EA Development

When adding State Representation Learning to an EA, you do not need to put a deep learning model into MQL5 from the start. For beginner-to-intermediate developers, the following stages are easier to handle.

  1. Get observed values in MQL5
  2. Normalize the observed values
  3. Create state scores
  4. Change trading filters based on the state
  5. Validate in Python and bring a simplified version back to MQL5

Even separating the state into only three parts, trend strength, volatility, and trading cost, can make an EA design easier to organize.

StateWhen LowWhen High
Trend strengthConsider mean reversion or pausingConsider trend-following
VolatilityProfit targets can become smallAdjust stop-loss width and lot size
Trading CostsNormal operation is easierConsider pausing entries

The key point is that creating a state representation alone does not make an EA profitable. A state representation is input for trading decisions, and it can only be evaluated together with entries, exits, lot management, stop losses, and shutdown conditions.

MQL5 Implementation Example

In MQL5, the usual structure is to create indicator handles in OnInit and retrieve the needed buffers in OnTick, rather than recalculating indicator values directly every time. The values read with CopyBuffer are then used to update the EA’s internal state.

//+------------------------------------------------------------------+
//| State Representation Learning style filter sample for MT5 EA     |
//+------------------------------------------------------------------+
#property strict

input int    InpFastMAPeriod = 20;
input int    InpSlowMAPeriod = 80;
input int    InpATRPeriod    = 14;
input int    InpADXPeriod    = 14;
input double InpMaxSpreadPts = 30.0;

int fast_ma_handle = INVALID_HANDLE;
int slow_ma_handle = INVALID_HANDLE;
int atr_handle     = INVALID_HANDLE;
int adx_handle     = INVALID_HANDLE;

struct MarketState
{
   double trend_score;
   double volatility_score;
   double cost_score;
   bool   tradable;
};

int OnInit()
{
   fast_ma_handle = iMA(_Symbol, _Period, InpFastMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
   slow_ma_handle = iMA(_Symbol, _Period, InpSlowMAPeriod, 0, MODE_EMA, PRICE_CLOSE);
   atr_handle     = iATR(_Symbol, _Period, InpATRPeriod);
   adx_handle     = iADX(_Symbol, _Period, InpADXPeriod);

   if(fast_ma_handle == INVALID_HANDLE ||
      slow_ma_handle == INVALID_HANDLE ||
      atr_handle     == INVALID_HANDLE ||
      adx_handle     == INVALID_HANDLE)
   {
      return INIT_FAILED;
   }

   return INIT_SUCCEEDED;
}

void OnDeinit(const int reason)
{
   if(fast_ma_handle != INVALID_HANDLE) IndicatorRelease(fast_ma_handle);
   if(slow_ma_handle != INVALID_HANDLE) IndicatorRelease(slow_ma_handle);
   if(atr_handle     != INVALID_HANDLE) IndicatorRelease(atr_handle);
   if(adx_handle     != INVALID_HANDLE) IndicatorRelease(adx_handle);
}

bool ReadLatestValue(const int handle, const int buffer_index, double &value)
{
   double data[];
   ArraySetAsSeries(data, true);

   if(CopyBuffer(handle, buffer_index, 0, 1, data) != 1)
      return false;

   value = data[0];
   return true;
}

bool BuildMarketState(MarketState &state)
{
   double fast_ma, slow_ma, atr_value, adx_value;

   if(!ReadLatestValue(fast_ma_handle, 0, fast_ma))   return false;
   if(!ReadLatestValue(slow_ma_handle, 0, slow_ma))   return false;
   if(!ReadLatestValue(atr_handle,     0, atr_value)) return false;
   if(!ReadLatestValue(adx_handle,     0, adx_value)) return false;

   MqlTick tick;
   if(!SymbolInfoTick(_Symbol, tick))
      return false;

   double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
   if(point <= 0.0)
      return false;

   double spread_points = (tick.ask - tick.bid) / point;
   double price = (tick.ask + tick.bid) * 0.5;

   state.trend_score      = MathAbs(fast_ma - slow_ma) / MathMax(point, price * 0.001);
   state.volatility_score = atr_value / MathMax(point, price * 0.001);
   state.cost_score       = spread_points / InpMaxSpreadPts;
   state.tradable         = (spread_points <= InpMaxSpreadPts && adx_value >= 20.0);

   return true;
}

void OnTick()
{
   MarketState state;
   if(!BuildMarketState(state))
      return;

   if(!state.tradable)
      return;

   // Check entry conditions, OrderCheck, and lot limits before OrderSend separately here
}

This code is a simplified example of applying the State Representation Learning idea as an internal state representation in an EA. In real trading logic, pre-checks with OrderCheck, minimum lot, maximum lot, lot step, margin, slippage, and position-count limits should be implemented separately.

How to Connect It to Python Validation

For serious validation of State Representation Learning, an effective workflow is to build the state representation in Python and check performance by period.

For the first validation pass, start with simple features rather than deep learning. For example, create columns like these.

Column NameDescription
return_1Return from one bar earlier
ma_gapGap between the short-term and long-term moving averages
atr_normATR ratio relative to price
adxTrend strength
spread_normRatio to the normal spread
hourTime of day

Using this state representation, you can run validation like the following.

import pandas as pd

def build_state_features(df: pd.DataFrame) -> pd.DataFrame:
    out = df.copy()
    out["return_1"] = out["close"].pct_change()
    out["ma_fast"] = out["close"].rolling(20).mean()
    out["ma_slow"] = out["close"].rolling(80).mean()
    out["ma_gap"] = (out["ma_fast"] - out["ma_slow"]) / out["close"]
    out["range_norm"] = (out["high"] - out["low"]) / out["close"]
    out["volatility_20"] = out["return_1"].rolling(20).std()
    out["hour"] = out.index.hour
    return out.dropna()

def split_by_time(df: pd.DataFrame, train_end: str, test_start: str) -> tuple[pd.DataFrame, pd.DataFrame]:
    train = df.loc[:train_end].copy()
    test = df.loc[test_start:].copy()
    return train, test

What you should avoid is selecting the features that look best across the entire period and then evaluating them on that same period. This easily leads to over-optimization and often fails in live operation. Validation should separate the training period, tuning period, out-of-sample period, and forward-test period.

How to Evaluate a State Representation

It is hard to judge whether a state representation is good only from backtest profit. Results can change greatly depending on trading rules, commissions, spreads, execution conditions, and the validation period.

Separate the following viewpoints during evaluation.

Evaluation TargetWhat to CheckNotes
Representation StabilityWhether state scores fluctuate too sharplyToo much noise sensitivity can increase trade count
SeparabilityWhether trend periods and range periods can be separatedCheck that the classification is not only hindsight
GeneralizationWhether similar tendencies appear in other periodsCheck by shifting the period
TradabilityWhether it still works after costsInclude spreads and execution
Ease of ImplementationWhether it can be implemented in MQL5Overly complex representations are hard to maintain

In an EA, a state representation can look clean but still be unusable in real trading. Examples include delayed state switching, signals clustering during spread widening, or lot management failing to keep up with sudden volatility changes.

Backtesting vs. Forward Testing

A backtest runs an EA on historical data to review results. A forward test checks behavior on a period not used for optimization or in an environment close to real time.

When using State Representation Learning in an EA, backtesting alone is not enough. Because the state representation is built from past market structure, it may not work the same way in future markets.

ValidationPurposeMain Checks
BacktestFind implementation mistakes and broad tendenciesTrade count, drawdown, and cost tolerance
Out-of-SampleCheck degradation in an unused periodHow it breaks after optimization
Walk ForwardRe-evaluate across shifted periodsStability of the state representation
Forward TestCheck behavior close to live operationExecution, spreads, and stop conditions

Even if a state representation looks effective on historical data, live operation can be affected by server latency, order rejection, slippage, account type, and symbol specifications. Therefore, it is risky to treat backtest results as future outcomes.

Risks to Check Before Live Use

State Representation Learning is a way to organize the inputs used by an EA for decisions. Creating a state representation alone does not stabilize trading performance.

When considering live use, prioritize validation that includes trading conditions over the model’s apparent accuracy. Check the following items separately from the backtest stage.

Check ItemCommon ProblemHow to Check
Over-OptimizationFits historical data too closelyCheck with OOS and walk-forward validation
Trading CostsUnderestimates spreads or commissionsSet costs conservatively
Execution DifferencesExecution conditions differ between backtests and live tradingObserve behavior on a demo account or with small lots
DrawdownLosing streaks or losses exceed assumptionsDefine maximum loss and shutdown conditions
LeverageLosses can expand in a short timeCheck lot caps and margin level

In an EA, the more complex the state representation becomes, the harder it is to identify which factor changed the results. The more complex the model is, the more important it is to define period splits, symbol diversification, fixed parameters, trading costs, and lot limits before evaluation.

Design Pattern for Implementation

For beginner-to-intermediate developers, the following design is manageable.

Design StageDescriptionMQL5 Implementation
ObservationGet price, MA, ATR, ADX, and spreadiMA, iATR, iADX, SymbolInfoTick
State BuildingConvert into scores or categoriesManage with structs or functions
FilterJudge whether trading is allowedReturn early inside OnTick
Trading DecisionCheck entry conditionsSeparate signal functions
Pre-Order CheckCheck lots, margin, and limitsUse OrderCheck
ValidationEvaluate across separated periodsMT5 Strategy Tester and Python

This separation makes it easier to isolate state-representation problems from trading-logic problems. If trading performance is poor, it becomes easier to check whether the issue is the state representation, entry conditions, or lot management.

Common Mistakes

When applying State Representation Learning to an EA, many failures come from validation design rather than from the technique itself.

MistakeProblemImprovement
Using too many statesBecomes hard to interpret and easy to over-optimizeStart with about three to five states
Selecting only by profitCan fit a lucky periodCheck drawdown, trade count, and OOS results
Ignoring spreadsPerformance often breaks in live useInclude a spread limit in the state
Making the model too complexMQL5 implementation and maintenance become difficultValidate in Python and move a simplified version into the EA
Skipping forward testingMakes historical overfitting harder to detectCheck with small lots or on a demo account

State Representation Learning is not simply a matter of adding a complex AI model. When using it in an EA, the meaning of the state representation, how it is obtained, how it is validated, and how orders are controlled must be designed consistently.

Related Research Materials

Summary

State Representation Learning creates state representations that make the market easier for an EA to handle. Instead of using prices or indicators directly as trading conditions, it organizes trend, volatility, trading cost, time of day, and similar factors as an internal state.

In MQL5, a practical design is to create indicator handles in OnInit, read values with CopyBuffer in OnTick, and store them in a state struct. In Python, use time-series splits, out-of-sample validation, and walk-forward validation to check whether the state representation only fits a specific period.

The important point is not that the state representation is advanced, but that it can be validated for live use. By evaluating spreads, execution, lot limits, drawdown, and forward-test degradation, this research topic can be translated into practical EA development.

FAQ

Does State Representation Learning increase EA profit?

It does not directly increase profit. It is a way to convert prices and indicators into states that an EA can use more easily. Trading results depend on entries, exits, lot management, trading costs, and validation conditions.

Does an MT5 EA need a deep learning model?

No. For beginner-to-intermediate developers, it is easier to validate handcrafted state representations built from MA, ATR, ADX, spreads, time of day, and similar inputs.

Are Regime Detection and State Representation Learning the same?

No. Regime Detection classifies market states, while State Representation Learning is the broader idea of creating the state representation used for that classification or other decisions.

Which MQL5 functions are important?

The important functions are iMA, iATR, and iADX for creating indicator handles, CopyBuffer for reading values, and SymbolInfoTick for checking price and spread. Before sending orders, OrderCheck is also needed.

Is a good backtest enough for live trading?

No. Judging by a backtest alone is risky. Out-of-sample validation, walk-forward validation, and forward testing are needed to check overfitting and the impact of trading costs.