Viewing the resource: MA STOCH EA: Navigate Trends with MA and Stochastic

MA STOCH EA: Navigate Trends with MA and Stochastic

Allan Munene Mutiiria 2025-06-21 01:23:36 77 Views
Join our fun, beginner-friendly guide to the MA STOCH EA MQL5 code! We’ll explain every function i...

Introduction

Ahoy, future forex navigator! Picture the forex market as a bustling trade port, with prices docking and departing like ships in a harbor. The MA STOCH EA is your expert harbor pilot, using a 100-period Moving Average (MA) and Stochastic oscillator to steer buy and sell trades through trend reversals. Built with elegant object-oriented programming, this EA spots momentum shifts with precision, executing trades with controlled risk. This article is your captain’s log, guiding you through the MQL5 code on MetaTrader 5 with vivid detail. We’ll unpack every major function with clarity for beginners, weaving humor and flow like a shanty sung by a crew. By the end, you’ll be ready to let this Expert Advisor (EA) chart your trades to profit. Let’s weigh anchor!

Strategy Blueprint

The MA STOCH EA combines two indicators for trend reversals:

  • Moving Average (MA): A 100-period Simple Moving Average (SMA) filters trends—prices below indicate bearish, above suggest bullish.

  • Stochastic Oscillator: An 8-period, 3,3 SMA-based indicator (low/high prices) measures momentum. Below 20 signals oversold; above 80 signals overbought.

A buy signal triggers when Stochastic crosses above 20 from below and the candle’s low is below the MA, confirming a bullish reversal in a bearish context. A sell signal fires when Stochastic crosses below 80 from above and the candle’s high is above the MA, confirming a bearish reversal in a bullish context. Trades use a 0.01-lot size with 300-pip stop loss and take profit, executed on new candles with alternating buy/sell logic to prevent consecutive same-direction trades. It’s like guiding a ship into port when the tide turns, ensuring a steady docking. See below.

Code Implementation

Let’s navigate the MQL5 code like harbor pilots steering through busy channels, unfolding the logic as a seamless voyage. Our journey starts with rigging the ship via class definitions, setting up indicators, detecting signals, executing trades, and docking safely. Each function builds on the last, with transitions that keep the narrative flowing like a steady current. We’ll explain every major function in detail, quoting variables (e.g., "maDATA") and functions (e.g., "OnInit()") for clarity, keeping it beginner-friendly with a navigation theme.

Rigging the Galleon: Header, Classes, and Initialization

Our expedition begins by outfitting the ship, defining classes and initializing the EA.

//+------------------------------------------------------------------+
//|      Copyright 2025, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader. |
//|                           https://youtube.com/@ForexAlgo-Trader? |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, ALLAN MUNENE MUTIIRIA. #@Forex Algo-Trader"
#property link      "https://youtube.com/@ForexAlgo-Trader?"
#property description "======= IMPORTANT =======\n"
#property description "1. This is a FREE EA."
#property description "2. To get the source code of the EA, follow the Copyright link."
#property description "3. Incase of anything, contact developer via the link provided."
                      "Hope you will enjoy the EA Logic.\n"
#property description "*** HAPPY TRADING! ***"
#property version   "1.00"

#include <Trade/Trade.mqh>

bool isLastBuy = false, isLastSell = false;

class CLASS_MA_STOCH{
   private:
      CTrade obj_Trade;
      double maDATA[], stochDATA[];
      string symbol;
      ENUM_TIMEFRAMES period;
      double lotsize;
      string message;
      void print_msg(string msg);
      int stoch_upper_level;
      int stoch_lower_level;
   protected:
      int handleMA, handleSTOCH;
      int MA_Period;
      ENUM_MA_METHOD MA_Method;
      ENUM_MA_METHOD STOCH_Method;
      ENUM_STO_PRICE STOCH_App_Price;
      string getMessage(){return (message);}
      double Ask(){ return (SymbolInfoDouble(symbol,SYMBOL_ASK));}
      double Bid(){ return (SymbolInfoDouble(symbol,SYMBOL_BID));}
   public:
      void CLASS_MA_STOCH();
      ~CLASS_MA_STOCH(){};
      double getHigh(int shift){ return (iHigh(symbol,period,shift));}
      double getLow(int shift){ return (iLow(symbol,period,shift));}
      datetime getTime(int shift){ return (iTime(symbol,period,shift));}
      int get_UP_L(){ return (stoch_upper_level);}
      int get_DN_L(){ return (stoch_lower_level);}
      void set_stoch_up(int up_level){stoch_upper_level = up_level;}
      void set_stoch_dn(int dn_level){stoch_lower_level = dn_level;}
      void set_ma_period(int ma_prd){MA_Period = ma_prd;}
      void set_ma_method(ENUM_MA_METHOD ma_mtd){MA_Method = ma_mtd;}
      void set_stoch_method(ENUM_MA_METHOD stoch_mtd){STOCH_Method = stoch_mtd;}
      void set_stoch_app_price(ENUM_STO_PRICE stoch_app){STOCH_App_Price = stoch_app;}
      int init(string symb,ENUM_TIMEFRAMES tf,double lot_size);
      virtual void getBuffers(int buf_no,int start_pos,int count);
      bool checkBuy();
      bool checkSell();
      virtual ulong OpenPosition(ENUM_POSITION_TYPE pos_type,double lots,int sl_pts,int tp_pts);
};

class NEW_CLASS_MA_STOCH : public CLASS_MA_STOCH{
   public:
      void NEW_CLASS_MA_STOCH(){};
      ~NEW_CLASS_MA_STOCH(){};
      void deinit();
};

CLASS_MA_STOCH OBJECT_EA;
NEW_CLASS_MA_STOCH OBJECT_DERIVED_EA;

int OnInit(){
   OBJECT_EA.set_ma_method(MODE_SMA);
   OBJECT_EA.set_ma_period(100);
   OBJECT_EA.set_stoch_app_price(STO_LOWHIGH);
   OBJECT_EA.set_stoch_method(MODE_SMA);
   OBJECT_EA.set_stoch_dn(20);
   OBJECT_EA.set_stoch_up(80);
   
   OBJECT_EA.init(_Symbol,_Period,0.01);
   
   return(INIT_SUCCEEDED);
}

The header declares the EA as a free offering by Allan in 2025, with a YouTube link and version 1.00, setting the port’s bustling tone.

  • Globals: "isLastBuy", "isLastSell" (false) track the last trade direction, preventing consecutive same-direction trades, like a port logbook.

  • Base Class ("CLASS_MA_STOCH"): Defines:

    • Private Members: "obj_Trade", "maDATA[]", "stochDATA[]", "symbol", "period", "lotsize", "message", "stoch_upper_level", "stoch_lower_level".

    • Protected Members: "handleMA", "handleSTOCH", "MA_Period", "MA_Method", "STOCH_Method", "STOCH_App_Price", and getters ("getMessage()", "Ask()", "Bid()").

    • Public Methods: Constructor, getters ("getHigh()", "getLow()", "getTime()", "get_UP_L()", "get_DN_L()"), setters, "init()", virtual "getBuffers()", "checkBuy()", "checkSell()", "OpenPosition()".

  • Derived Class ("NEW_CLASS_MA_STOCH"): Inherits from "CLASS_MA_STOCH", adding "deinit()".

  • Objects: "OBJECT_EA" (base class) and "OBJECT_DERIVED_EA" (derived class) instantiate the EA.

  • "OnInit()": The EA’s launch, called when attached:

    • Sets MA to SMA ("MODE_SMA"), period 100, Stochastic to low/high ("STO_LOWHIGH"), SMA, levels 20/80 via setters ("set_ma_method()", etc.).

    • Calls "OBJECT_EA.init()" with "_Symbol", "_Period", 0.01 lots.

    • Returns INIT_SUCCEEDED, like docking the ship with a clear berth.

This rigs the galleon, preparing the EA’s class-based structure to navigate signals.

Setting the Sails: CLASS_MA_STOCH Constructor and init Function

With the ship rigged, we set the sails, initializing indicators and resources.

void CLASS_MA_STOCH::CLASS_MA_STOCH(void){
   handleMA = INVALID_HANDLE;
   handleSTOCH = INVALID_HANDLE;
   ZeroMemory(maDATA);
   ZeroMemory(stochDATA);
   message = "";
}
int CLASS_MA_STOCH::init(string symb,ENUM_TIMEFRAMES tf,double lot_size){
   symbol = symb;
   period = tf;
   lotsize = lot_size;
   
   handleMA = iMA(symbol,period,MA_Period,0,MA_Method,PRICE_CLOSE);
   if (handleMA == INVALID_HANDLE){
      message = "ERROR: FAILED TO CREATE THE MA IND HANDLE. REVERTING";
      print_msg(getMessage());
      return (INIT_FAILED);
   }
   handleSTOCH = iStochastic(symbol,period,8,3,3,STOCH_Method,STOCH_App_Price);
   if (handleSTOCH == INVALID_HANDLE){
      message = "ERROR: FAILED TO CREATE THE STOCH IND HANDLE. REVERTING";
      print_msg(getMessage());
      return (INIT_FAILED);
   }
   
   ArraySetAsSeries(maDATA,true);
   ArraySetAsSeries(stochDATA,true);
   
   return (INIT_SUCCEEDED);
}
void CLASS_MA_STOCH::print_msg(string msg){
   Print(msg);
}

These functions prepare the sails:

  • Constructor ("CLASS_MA_STOCH()"): Initializes "handleMA", "handleSTOCH" to "INVALID_HANDLE", clears "maDATA[]" and "stochDATA[]" with "ZeroMemory()", and sets "message" empty, like prepping the ship’s instruments.

  • "init()": Sets "symbol", "period", "lotsize", and initializes:

    • "iMA()": Creates a "MA_Period"-period SMA ("MA_Method", "PRICE_CLOSE"), storing in "handleMA".

    • "iStochastic()": Creates an 8,3,3 Stochastic ("STOCH_Method", "STOCH_App_Price"), storing in "handleSTOCH".

    • "print_msg()": Logs errors via "Print()" and "getMessage()".

    • "ArraySetAsSeries()": Configures "maDATA[]" and "stochDATA[]" as time series.

    • Returns INIT_SUCCEEDED or INIT_FAILED based on handle validity.

  • "print_msg()": Outputs messages to the journal, like a captain’s log.

This sets the sails, ensuring indicators are ready to catch market winds.

Spotting the Tide: getBuffers, checkBuy, and checkSell Functions

With sails up, we scan for signals, like spotting favorable tides in the port.

void CLASS_MA_STOCH::getBuffers(int buf_no,int start_pos,int count){
   if (CopyBuffer(handleMA,buf_no,start_pos,count,maDATA) < count){
      message = "ERROR: NOT ENOUGH DATA FROM MA IND FOR FURTHER ANALYSIS";
      print_msg(getMessage());
      return;
   }
   if (CopyBuffer(handleSTOCH,0,0,3,stochDATA) < 3){
      message = "ERROR: NOT ENOUGH DATA FROM STOCH IND FOR FURTHER ANALYSIS";
      print_msg(getMessage());
      return;
   }
}
bool CLASS_MA_STOCH::checkBuy(void){
   getBuffers(0,0,3);
   double low0 = getLow(0);
   double high0 = getHigh(0);
   datetime currBarTime0 = getTime(0);
   static datetime signalTime = currBarTime0;
   
   if (stochDATA[0] > get_DN_L() && stochDATA[1] < get_DN_L() && low0 < maDATA[0]
      && signalTime != currBarTime0){
      message = "BUY SIGNAL @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
      print_msg(getMessage());
      signalTime = currBarTime0;
      return (true);
   }
   else {return (false);}
}
bool CLASS_MA_STOCH::checkSell(void){
   getBuffers(0,0,3);
   double low0 = getLow(0);
   double high0 = getHigh(0);
   datetime currBarTime0 = getTime(0);
   static datetime signalTime = currBarTime0;
   
   if (stochDATA[0] < get_UP_L() && stochDATA[1] > get_UP_L() && high0 > maDATA[0]
      && signalTime != currBarTime0){
      message = "SELL SIGNAL @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
      print_msg(getMessage());
      signalTime = currBarTime0;
      return (true);
   }
   else {return (false);}
}

These functions spot the tide:

  • "getBuffers()": Fetches three values for MA ("maDATA[]", buffer "buf_no") and Stochastic ("stochDATA[]", buffer 0) using "CopyBuffer()". Logs errors if insufficient data, like checking tide charts.

  • "checkBuy()": Calls "getBuffers()", checks if Stochastic crosses above "get_DN_L()" (20), candle low ("getLow(0)") is below MA ("maDATA[0]"), and it’s a new candle ("signalTime != getTime(0)"). Logs “BUY SIGNAL” with "TimeToString()", "TimeCurrent()", updates "signalTime", returns true.

  • "checkSell()": Similar, checking Stochastic crossing below "get_UP_L()" (80), high ("getHigh(0)") above MA, new candle, logging “SELL SIGNAL”.

This scans the port’s tides, signaling trades like spotting a ship ready to sail.

Launching the Ship: OpenPosition Function

With signals spotted, the EA launches trades, like guiding a ship out of port.

ulong CLASS_MA_STOCH::OpenPosition(ENUM_POSITION_TYPE pos_type,double lots,int sl_pts,int tp_pts){
   lots = lotsize;
   double price = NULL;
   ulong ticket = NULL;
   
   if (pos_type == POSITION_TYPE_BUY){
      price = Ask();
      double sl = price - sl_pts*_Point;
      double tp = price + tp_pts*_Point;
      if (obj_Trade.Buy(lots,symbol,price,sl,tp)){
         ticket = obj_Trade.ResultOrder();
      }
   }
   else if (pos_type == POSITION_TYPE_SELL){
      price = Bid();
      double sl = price + sl_pts*_Point;
      double tp = price - tp_pts*_Point;
      if (obj_Trade.Sell(lots,symbol,price,sl,tp)){
         ticket = obj_Trade.ResultOrder();
      }
   }
   else {ticket = -1;}
   
   string type = pos_type == POSITION_TYPE_BUY ? "BUY" : "SELL";
   message = "OPENED "+type+" POSITION WITH TICKET # "+IntegerToString(ticket);
   print_msg(getMessage());
   
   return (ticket);
}

The "OpenPosition()" function launches trades:

  • Inputs: "pos_type" ("POSITION_TYPE_BUY"/"SELL"), "lots" (set to "lotsize"), "sl_pts", "tp_pts" (300).

  • Logic: For buys, uses "Ask()", sets stop loss ("sl") 300 pips below, take profit ("tp") 300 pips above, calls "obj_Trade.Buy()". For sells, uses "Bid()", adjusts accordingly, calls "obj_Trade.Sell()". Logs the ticket ("ResultOrder()") or -1 if failed, using "IntegerToString()".

  • "Buy()", "Sell()": Open trades with "lots", "symbol", price, stop loss, take profit.

  • "_Point": Pip size for calculations.

This guides the ship out, executing trades like a pilot docking at the right moment.

Steering the Course: OnTick Function

The EA’s heart, "OnTick()", steers trades based on signals.

void OnTick(){
   if (OBJECT_EA.checkBuy()){
      if (isLastBuy == false){
         OBJECT_EA.OpenPosition(POSITION_TYPE_BUY,0.01,300,300);
         isLastBuy = true; isLastSell = false;
      }
   }
   else if (OBJECT_EA.checkSell()){
      if (!isLastSell){
         OBJECT_EA.OpenPosition(POSITION_TYPE_SELL,0.01,300,300);
         isLastBuy = false; isLastSell = true;
      }
   }
}

The "OnTick()" function runs on every tick:

  • Calls "checkBuy()". If true and "isLastBuy" is false, opens a buy with "OpenPosition()", sets "isLastBuy" true, "isLastSell" false.

  • Calls "checkSell()". If true and "isLastSell" is false, opens a sell, sets "isLastSell" true, "isLastBuy" false.

This steers the course, ensuring alternating trades like a pilot switching docks.

Docking the Ship: OnDeinit and deinit Functions

When the voyage ends, these functions dock the ship.

void NEW_CLASS_MA_STOCH::deinit(void){
   double high = OBJECT_DERIVED_EA.getHigh(0);
   Print(high);
   IndicatorRelease(handleMA);
   IndicatorRelease(handleSTOCH);
   Print("INDICATOR HANDLES DEINITIALISED");
}
void OnDeinit(const int reason){
   OBJECT_DERIVED_EA.deinit();
}

  • "deinit()": Logs current high ("getHigh(0)"), frees "handleMA" and "handleSTOCH" with "IndicatorRelease()", and logs deinitialization, like storing gear.

  • "OnDeinit()": Calls "OBJECT_DERIVED_EA.deinit()", docking the ship cleanly.

This ensures a tidy port, freeing resources for the next sail. See below.

Putting It All Together

To launch this EA:

  1. Open MetaEditor in MetaTrader 5.

  2. Paste the code into a new Expert Advisor file.

  3. Compile (F5). If errors appear, check your copy-paste.

  4. Drag the EA onto your chart, enable AutoTrading, and watch for alternating buy/sell trades.

  5. Trade smart—don’t bet your galleon on one tide!

Conclusion

The MA STOCH EA is your harbor pilot, navigating trend reversals with MA and Stochastic signals. We’ve charted its MQL5 code with clear, detailed explanations, so you understand every move like a seasoned navigator. Now you’re set to automate your trades and sail market currents. Want to see it in action? Check our video guide on the website!

Disclaimer: Trading’s like navigating a busy port—exciting but risky. Losses can exceed deposits. Test on a demo account before going live.

Disclaimer: The ideas and strategies presented in this resource are solely those of the author and are intended for informational and educational purposes only. They do not constitute financial advice, and past performance is not indicative of future results. All materials, including but not limited to text, images, files, and any downloadable content, are protected by copyright and intellectual property laws and are the exclusive property of Forex Algo-Trader or its licensors. Reproduction, distribution, modification, or commercial use of these materials without prior written consent from Forex Algo-Trader is strictly prohibited and may result in legal action. Users are advised to exercise extreme caution, perform thorough independent research, and consult with qualified financial professionals before implementing any trading strategies or decisions based on this resource, as trading in financial markets involves significant risk of loss.

Recent Comments

Go to discussion to Comment or View other Comments

No comments yet. Be the first to comment!