How to Code a Prop Firm EA: 5 Steps to Challenge-Compliant MQL Code

Step 1: Code a Global Equity-Based Kill Switch

Building an EA for prop firm challenge compliance starts with the most critical protection layer: an equity-based kill switch. Before you write a single order entry function, you need to understand that prop firms monitor equity-to-equity drawdown, not just your closed balance. Floating losses count. And when your live equity breaches the daily drawdown threshold, the account is in violation — even if no trade has been closed.

That distinction changes everything about how your Expert Advisor must behave.

Here is how to implement the logic correctly in MQL5:

  1. Declare a global DailyStartEquity variable at the top of your EA file. This stores the account equity at 00:00 server time each trading day and becomes the reference point for all drawdown calculations.
  2. Capture the opening equity value inside OnTick() by checking whether the current server day has changed. When it has, assign AccountInfoDouble(ACCOUNT_EQUITY) to DailyStartEquity.
  3. Calculate the current drawdown on every tick using the formula: double drawdown = DailyStartEquity - AccountInfoDouble(ACCOUNT_EQUITY); This reflects both closed and floating losses simultaneously.
  4. Trigger the shutdown sequence when drawdown reaches your configured limit. Iterate through all open positions using PositionSelect() and close each one before halting execution — leaving positions open during shutdown violates most prop firm EA rules.
  5. Call ExpertRemove() after all positions are closed. This physically detaches the EA from the chart rather than simply pausing it, ensuring no further orders can be placed during the current session.
double DailyStartEquity = 0;
datetime LastDay = 0;

void OnTick()
{
   datetime today = StringToTime(TimeToString(TimeCurrent(), TIME_DATE));
   if(today != LastDay) { DailyStartEquity = AccountInfoDouble(ACCOUNT_EQUITY); LastDay = today; }

   double drawdown = DailyStartEquity - AccountInfoDouble(ACCOUNT_EQUITY);
   if(drawdown >= MaxDailyLoss)
   {
      CloseAllPositions();
      ExpertRemove();
   }
}

Prop firms typically fail accounts based on equity drawdown relative to the start of the day, which makes this initialization step non-negotiable. A kill switch that only reads balance will miss every floating loss scenario.

With the equity shield in place, the next critical layer is ensuring every order carries a hard stop loss from the moment it is sent to the broker server — and that is exactly what Step 2 covers.

Step 2: Implement Mandatory Hard Stop Losses

With your equity kill switch in place, the next layer of challenge-compliant code addresses one of the most common disqualification triggers: trading without a stop loss attached to the broker server. Understanding this rule is essential to how to code a prop firm EA that survives a manual review.

The "Naked Position" Rule prohibits open trades that carry no server-side stop loss. Many firms disqualify accounts that have "naked" positions without a Stop Loss attached to the order, meaning a stop loss managed only inside your EA's logic — a virtual or hidden SL — does not count. If the platform disconnects, that position is unprotected, and the firm flags it as a rule violation.

Accomplish the following to ensure every order your EA places includes a hard SL from the moment of execution:

  1. Decide on your SL calculation method. Use ATR-based points (e.g., 1.5 × ATR(14)) for adaptive risk, or a fixed pip value for simpler strategies. Either approach must produce a concrete point distance before the order is placed.
  2. Calculate the SL price level before calling OrderSend or Trade.Buy. For a buy: slPrice = entryPrice - (slPoints * Point);
  3. Pass the SL directly inside the order call — never as a separate modification afterward. A two-step approach (open, then modify) creates a brief naked window that compliance reviews can detect.
  4. Verify the SL distance meets the broker’s minimum stop level. Use SymbolInfoInteger(Symbol(), SYMBOL_TRADE_STOPS_LEVEL) and add a buffer to avoid invalid SL rejections.
  5. Confirm the SL is server-confirmed by checking the returned ticket and logging the attached SL price. If the SL is missing on confirmation, close the trade immediately rather than leaving it exposed.

Example order structure in MQL5:

double slPoints = iATR(_Symbol, PERIOD_H1, 14, 0) * 1.5;
double slPrice  = Ask - slPoints;
trade.Buy(lotSize, _Symbol, Ask, slPrice, 0, "PropFirmEA");

Hard stop losses and correct position sizing work together — which leads directly to normalizing your lot sizes for consistent, reviewable risk.

Step 3: Normalize Lot Sizes for Risk Consistency

With hard stop losses enforced, the next critical layer of your MQL4 prop firm risk management code addresses how lot sizes are calculated. Fixed lot sizes are a significant red flag during prop firm manual reviews because prop firms flag "gambling" patterns, which are often identified by inconsistent or static lot sizes relative to account equity. An EA that trades 0.10 lots regardless of whether the account sits at $10,000 or $8,500 signals mechanical rigidity — not disciplined risk management.

Dynamic position sizing solves this. The formula you need is:

Lot Size = (AccountBalance × RiskPercent) / (StopLossPoints × TickValue)

Here is how to implement it correctly in MQL4:

  1. Declare your input variables at the top of the EA — set RiskPercent (e.g., 1.0 for 1%) and StopLossPoints as editable inputs so they can be adjusted without recompiling.
  2. Retrieve the live account balance using AccountBalance() rather than AccountEquity(), so lot sizing scales against realized capital, not floating positions.
  3. Fetch the TickValue dynamically using SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE). This ensures cross-asset compatibility — the formula produces accurate results whether the EA is running on EUR/USD, gold, or indices.
  4. Calculate the raw lot size by dividing the dollar risk amount (AccountBalance × RiskPercent / 100) by (StopLossPoints × TickValue).
  5. Normalize the result with NormalizeDouble(rawLots, 2) and clamp it between SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN) and SYMBOL_VOLUME_MAX to avoid broker rejections.
  6. Pass the normalized lot size directly into your order placement function — never hard-code a fallback value that bypasses this calculation.

Scaling with account balance is what satisfies the Consistency Rule that most prop firms enforce. As the account grows through profits, position sizes grow proportionally. As drawdown reduces the balance, the EA automatically trades smaller — exactly the behavior a funded trading desk expects to see. This proportional approach also keeps daily dollar risk within the maximum thresholds established by your kill switch in Step 1.

With lot sizing normalized, the focus shifts to another layer of review risk: the behavioral patterns your EA produces over many trades. Step 4 covers the filters that prevent toxic trading signatures from triggering automated flags.

Step 4: Add Filters to Prevent Toxic Trading Patterns

With position sizing and stop loss logic now handled, the next challenge for any MQL5 challenge compliant Expert Advisor is avoiding the behavioral patterns that trigger automated ban systems. Firms like FTMO and Apex flag specific patterns like HFT and Grid trading as exploitative, and their detection systems operate at the order level — meaning intent does not matter. Only behavior does.

Follow these steps to filter out the patterns that disqualify accounts before profits are ever paid out:

  1. Implement a MinHoldSeconds variable set to 60 and check elapsed time before any position closes. Calculate the difference between the current server time and OrderOpenTime(); if the result falls below your threshold, suppress the close signal entirely. This single guard prevents your EA from matching the order-frequency fingerprint of high-frequency trading.
  2. Remove all Grid and Martingale lot-scaling logic from your EA unconditionally. Any code that increases lot size following a losing trade — regardless of how the multiplier is labeled — creates cascading exposure that violates drawdown rules and triggers pattern-based flags. Fixed or volatility-normalized lot sizes, as covered in Step 3, are the compliant alternative.
  3. Integrate a time-based News Filter by defining a BlockedStartHour and BlockedEndHour for known high-impact release windows. A more robust approach connects to an Economic Calendar API and reads event data directly, pausing trade entry automatically. In practice, a simple hardcoded time block covering major sessions tends to satisfy most firm requirements without added infrastructure complexity.
  4. Declare a MaxDailyTrades integer and increment a counter each time a new order opens. Before any entry, check that the counter has not reached the limit; if it has, suppress the signal for the remainder of the trading day and reset at midnight. This satisfies consistency requirements that penalize accounts for extreme trade-volume spikes on isolated days.

Each of these filters addresses a distinct disqualification vector. Once they are in place, verifying that the EA behaves correctly under all conditions becomes the next critical step — which requires a structured compliance checklist before any live challenge attempt.

How to Verify Your EA for Challenge Compliance

Building compliant MQL4 and MQL5 logic is only half the job. Before you submit a challenge account, run through this structured verification sequence to confirm every rule is enforced at the code level.

  1. Confirm drawdown is calculated on equity, not balance. Automated drawdown protection MT4 logic that reads only the balance will miss floating losses entirely. Pull AccountEquity() on every tick and compare it against the day-open equity snapshot — not AccountBalance(). A 5% daily limit breached mid-trade will not appear in balance until positions close.
  2. Verify that every order carries a hard stop loss at submission. Log each OrderSend() call and confirm the sl parameter is non-zero. Prop firms that [audit order history](https://alfatactix.com/academy/mql5-ea/ea-prop-firm-rules-mt5) can disqualify accounts where stop losses were added after entry, even by milliseconds.
  3. Time-stamp trade duration and enforce the minimum hold period. Most prop firms require trades to remain open for 30 to 60 seconds. Store the open time at order entry and block early closes with a tick-level guard. [EAs that work on 1:500 leverage often fail on prop accounts](https://www.jptradingcapital.com/blog/en/mt5-expert-advisor-prop-firm-challenge) running 1:30 or 1:100, and inadequate demo testing is the leading cause — time-restriction failures rank closely behind.
  4. Activate news filters and test them against a live calendar feed. Confirm the filter pauses new entries and, where required, closes open positions within the specified window. Run the EA in demo during a scheduled high-impact event to verify the pause actually fires.
  5. Mount a UI dashboard and do a final visual audit. A custom trading dashboard that surfaces equity drawdown percentage, current stop loss values, trade duration, and news-window status makes rule violations visible at a glance. Professionalizing the EA with this layer is not cosmetic — it is the fastest way to catch a misconfigured parameter before it costs a funded account.

An EA that passes each step above is genuinely challenge-compliant, not just functionally complete. If your current build cannot surface these metrics in a readable interface, MQL UI Studio can help design the full system — from risk logic to the trading dashboard that keeps every compliance rule visible during live execution.