#ForexHomeExpert_image_slider1 #ForexHomeExpert_image_slider2 #ForexHomeExpert_image_slider3 #ForexHomeExpert_image_slider4

Tuesday, February 17, 2026

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert

The Genesis of GMM

The idea to create the GMM Master Dashboard LR Magnet was born from a simple yet ambitious goal: I wanted a standalone price monitoring system that functions independently from the MetaTrader 5 (MT5) terminal interface. While I was aware that MQL5 offers a powerful bridge to integrate Python, I faced a significant hurdle—I wasn't a Python expert.

Driven by the desire to bring this vision to life, I turned to Google AI Gemini for collaboration. I named this project GMM, which stands for "Gemini Mantap Mentong!". This name is a tribute to my roots in Makassar (one of the largest ethnic groups in South Sulawesi, Indonesia). In our local dialect, "Mantap Mentong" translates to "Sungguh-sungguh Mantap" in Indonesian, or in English, it conveys a sense of being "Really Steadfast" or "Truly Excellent."

GMM_MASTER_DASHBOARD_LR_MAGNET_01 Figure 1: Main Dashboard: BASE PAIRS: MAJOR - JPY CROSS AND METALS
GMM_MASTER_DASHBOARD_LR_MAGNET_02 Figure 2: Pair list dashboard: FULL 30 PAIRS LOGIC LIST

Merging Legend with Modern AI

With Gemini's assistance, I successfully translated years of manual observation into a sophisticated automated dashboard. The system integrates two core pillars:

  • 1. Linear Regression Degrees: This is based on the LRDegrees Indicator for MT5, a tool I have shared with the global trading community on the MQL5 CodeBase since 2017.
  • 2. The 2014 Magnet Theory: This logic is derived from my continuous market observations since 2014. I discovered a recurring price behavior: whenever a bar's open price is below the EMA2 (Weighted Close), the price is inevitably "magnetized" back up towards the EMA2. Conversely, if it opens above, it is drawn back down. This phenomenon occurs consistently across all market conditions, whether in a bullish or bearish trend.

Today, the GMM Master Dashboard stands as a "Really Steadfast" decision support system, bridging nearly a decade of trading wisdom with the cutting-edge power of Artificial Intelligence.

Convert MQL5 Code to Python

In the GMM Master Dashboard program, I converted several functions from MQL5 to Python.

ExponentialMA

You can see the ExponentialMA program in MQL5 in the MQL5/Include folder in the MovingAverages.mqh file


//+------------------------------------------------------------------+
//|  Exponential moving average on price array                       |
//+------------------------------------------------------------------+
int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,const int period,const double& price[],double& buffer[])
  {
//--- check period
   if(period<=1 || period>(rates_total-begin))
      return(0);
//--- save and clear 'as_series' flags
   bool as_series_price=ArrayGetAsSeries(price);
   bool as_series_buffer=ArrayGetAsSeries(buffer);

   ArraySetAsSeries(price,false);
   ArraySetAsSeries(buffer,false);
//--- calculate start position
   int    start_position;
   double smooth_factor=2.0/(1.0+period);

   if(prev_calculated==0)  // first calculation or number of bars was changed
     {
      //--- set empty value for first bars
      for(int i=0; i<begin; i++)
         buffer[i]=0.0;
      //--- calculate first visible value
      start_position=period+begin;
      buffer[begin] =price[begin];

      for(int i=begin+1; i<start_position; i++)
         buffer[i]=price[i]*smooth_factor+buffer[i-1]*(1.0-smooth_factor);
     }
   else
      start_position=prev_calculated-1;
//--- main loop
   for(int i=start_position; i<rates_total; i++)
      buffer[i]=price[i]*smooth_factor+buffer[i-1]*(1.0-smooth_factor);
//--- restore as_series flags
   ArraySetAsSeries(price,as_series_price);
   ArraySetAsSeries(buffer,as_series_buffer);
//---
   return(rates_total);
  }

Once converted to Python, ExponentialMA becomes very simple.


def GMM_ExponentialMA(price_array, period):
    if period <= 0 or len(price_array) == 0: return price_array
    pr = 2.0 / (period + 1.0)
    result_ema = np.zeros_like(price_array)
    result_ema[0] = price_array[0] 
    for i in range(1, len(price_array)):
        result_ema[i] = (price_array[i] * pr) + (result_ema[i-1] * (1.0 - pr))
    return result_ema

Key Advantages of NumPy:

  • Vectorization: Operations run in optimized C, making them much faster than MQL5 loops.
  • Conciseness: Complex formulas become single-line expressions.
  • Integration: Easily integrates with pandas for further technical analysis.
  • Moving Average (Rolling Window): In MQL5, you use a for loop with a backward index. In Python, the most efficient way is to use the sliding_window_view function or a companion library like Pandas.

Linear Regression Degree

In the LRDegrees indicator for MT5, I created the following code for calculating linear regression and calculating the degree of linear regression position:


   //--
   for(j=0; j<barsCountLine2; j++)
     {
      suma+=MABuffers[j];
      sumab+=MABuffers[j]*j;
      sumb1+=j;
      sumb2+=j*j;
     }
   //--
   a=sumb2*barsCountLine2-sumb1*sumb1;
   b=(sumab*barsCountLine2-sumb1*suma)/a;
   c=(suma-sumb1*b)/barsCountLine2;
   //--
   //-- Linear regression MA trend 2
   for(l=0; l<barsCountLine2; l++) LRBuffers2[l]=c+b*l;
   //---
   for(int i=bar_count-1; i>=0; i--)
     {
       //--
       if(i==0)
         {
           switch(degress)
             {
               case 0:
                 {
                   cur_degrees=NormalizeDouble(270+(((LRBuffers2[0]-lmin)/(hmax-lmin))*180),2);
                   prev1_degrees=NormalizeDouble(270+(((LRBuffers2[1]-lmin)/(hmax-lmin))*180),2);
                   prev2_degrees=NormalizeDouble(270+(((LRBuffers2[2]-lmin)/(hmax-lmin))*180),2);
                   div1_degrees=prev1_degrees - prev2_degrees;
                   div0_degrees=cur_degrees - prev2_degrees;
                   break;
                 }
               //--
               case 1:
                 {
                   cur_degrees=NormalizeDouble(270+(((LRBuffers1[0]-lmin)/(hmax-lmin))*180),2);
                   prev1_degrees=NormalizeDouble(270+(((LRBuffers1[1]-lmin)/(hmax-lmin))*180),2);
                   prev2_degrees=NormalizeDouble(270+(((LRBuffers1[2]-lmin)/(hmax-lmin))*180),2);
                   div1_degrees=prev1_degrees - prev2_degrees;
                   div0_degrees=cur_degrees - prev2_degrees;
                   break;
                 }
             }
           //--
           if(cur_degrees>360.0) {cur_degrees=NormalizeDouble(cur_degrees-360.0,2);}
           if(cur_degrees==360.0) {cur_degrees=NormalizeDouble(0.0,2);}
           //- To give a value of 90.0 degrees to the indicator, when the price moves up very quickly and make a New Windows Price Max.
           if(cur_degrees==90.0) {cur_degrees=NormalizeDouble(90.0,2);}
           //- To give a value of 270.0 degrees to the indicator, when the price moves down very quickly and make a New Windows Price Min.
           if(cur_degrees==270.0) {cur_degrees=NormalizeDouble(270.0,2);}
           //--
           if(div0_degrees>div1_degrees) {dgrsUp=true; dgrsDn=false; DegreesUp[i]=cur_degrees; DegreesDn[i]=0.0;}
           if(div0_degrees<div1_degrees) {dgrsDn=true; dgrsUp=false; DegreesDn[i]=cur_degrees; DegreesUp[i]=0.0;}
           //---
           if((cur_degrees>=270.0 && cur_degrees<315.0)&&(dgrsDn==true)) {rndclr=stgBear; arrclr=stgBear; txtclr=txtrbl; posalert=11;}
           if((cur_degrees>=270.0 && cur_degrees<315.0)&&(dgrsUp==true)) {rndclr=stgBear; arrclr=stsBear; txtclr=txtrbl; posalert=12;}
           if((cur_degrees>=315.0 && cur_degrees<360.0)&&(dgrsDn==true)) {rndclr=stsBear; arrclr=stgBear; txtclr=txtblk; posalert=21;}
           if((cur_degrees>=315.0 && cur_degrees<360.0)&&(dgrsUp==true)) {rndclr=stsBear; arrclr=stsBull; txtclr=txtblk; posalert=23;}
           if((cur_degrees>=0.0 && cur_degrees<45.0)&&(dgrsUp==true)) {rndclr=stsBull; arrclr=stgBull; txtclr=txtblk; posalert=34;}
           if((cur_degrees>=0.0 && cur_degrees<45.0)&&(dgrsDn==true)) {rndclr=stsBull; arrclr=stsBear; txtclr=txtblk; posalert=32;}
           if((cur_degrees>=45.0 && cur_degrees<=90.0)&&(dgrsUp==true)) {rndclr=stgBull; arrclr=stgBull; txtclr=txtrbl; posalert=44;}
           if((cur_degrees>=45.0 && cur_degrees<=90.0)&&(dgrsDn==true)) {rndclr=stgBull; arrclr=stsBull; txtclr=txtrbl; posalert=43;}
           //---  

After converting into Python, the program looks like this:


def GMM_Get_Data(symbol, timeframe_id):
    rates = mt5.copy_rates_from_pos(symbol, timeframe_id, 0, 100)
    if rates is None or len(rates) < 10: return None
    
    popen, phigh, plow, pclose = np.array([r['open'] for r in rates]), np.array([r['high'] for r in rates]), np.array([r['low'] for r in rates]), np.array([r['close'] for r in rates])
    pweighted = (phigh + plow + pclose + pclose) / 4.0
    ema2_pm = GMM_ExponentialMA(pweighted, 2)
    
    y, j = ema2_pm[-3:], np.arange(3)
    suma, sumab, sumb1, sumb2 = np.sum(y), np.sum(y * j), np.sum(j), np.sum(j**2)
    denom = (sumb2 * 3) - (sumb1**2)
    b = ((sumab * 3) - (sumb1 * suma)) / denom
    c = (suma - (sumb1 * b)) / 3
    lr_buffers = c + (b * j)

    hmax, lmin = np.max(phigh), np.min(plow)
    cur_degrees = round(270 + ((lr_buffers[-1] - lmin) / (hmax - lmin)) * 180, 2)
    prev1_degrees = round(270 + ((lr_buffers[-2] - lmin) / (hmax - lmin)) * 180, 2)
    prev2_degrees = round(270 + ((lr_buffers[-3] - lmin) / (hmax - lmin)) * 180, 2)
    div1_degrees, div0_degrees = round(prev1_degrees - prev2_degrees, 2), round(cur_degrees - prev2_degrees, 2)

    if cur_degrees > 360.0: cur_degrees -= 360.0
    if cur_degrees == 360.0: cur_degrees = 0.0
    dgrs_up, dgrs_dn = div0_degrees > div1_degrees, div0_degrees < div1_degrees

    status_lr = "SIDEWAY"
    if (270.0 <= cur_degrees < 315.0 and dgrs_dn):   status_lr = "DN_Strong▼▼"
    elif (270.0 <= cur_degrees < 315.0 and dgrs_up): status_lr = "DN_Weakened▼"
    elif (315.0 <= cur_degrees < 360.0 and dgrs_dn): status_lr = "DN_Strengthened▼▼"
    elif (315.0 <= cur_degrees < 360.0 and dgrs_up): status_lr = "DN_Reversal▲"
    elif (0.0 <= cur_degrees < 45.0 and dgrs_up):    status_lr = "UP_Strengthened▲▲"
    elif (0.0 <= cur_degrees < 45.0 and dgrs_dn):    status_lr = "UP_Reversal▼"
    elif (45.0 <= cur_degrees <= 90.0 and dgrs_up):  status_lr = "UP_Strong▲▲"
    elif (45.0 <= cur_degrees <= 90.0 and dgrs_dn):  status_lr = "UP_Weakened▲"

Key Changes Explained:

  • np.arange(bars_count): Instantly creates a sequence array of numbers (0, 1, 2, etc.). This replaces the loop variables j and l. Element-wise Operations: In MQL5, you perform MABuffers[j]*j one at a time. In NumPy, y * j multiplies the entire array in a single hardware operation.
  • np.sum(): Replaces manual accumulators like suma += .... NumPy uses a CPU-optimized summation algorithm. No Second Loop: Filling LRBuffers2 is done directly with c + (b * j). If j is the array [0, 1, 2], the result is automatically the array [c + b * 0, c + b * 1, c + b * 2].

Note: Gemini AI says that "If you want more "Pythonic" results for linear regression, you can also use np.polyfit(j, y, 1), but the manual method above is the most accurate translation of your MQL5 logic."

Price Magnetism Theory

As I explained above, this logic is derived from my continuous market observations since 2014. I discovered a recurring price behavior: whenever a bar's open price is below the EMA2 (PRICE WEIGHTED), the price is always "magnetized" back up towards the EMA2. Conversely, if it opens above, it is drawn back down.

The most powerful feature of this system is the detection of Magnet Rejection. This occurs when the price attempts to breach the Magnet but fails, creating a high-conviction reversal signal:

  • ⚠️ DN-REJ-UP (Bullish Rejection): Occurs when the price OPEN below the Magnet, spikes above it (HIGH > EMA2), but closes back below the OPEN price (CLOSE < OPEN).
  • .
  • ⚠️ UP-REJ-DN (Bearish Rejection): Occurs when the price OPEN above the Magnet, dips below it (LOW < EMA2), but reverses to close above the OPEN price (CLOSE > OPEN).

The implementation of this logic, in a Python program would be:

  
    mid = ema2_pm[-1]
    O, H, L, C = popen[-1], phigh[-1], plow[-1], pclose[-1]
    magnet, mag_col = "FLAT", Fore.WHITE
    if O <= mid and C > mid: magnet = "🧲 UP"; mag_col = Fore.CYAN
    elif O >= mid and C < mid: magnet = "🧲 DN"; mag_col = Fore.RED
    elif O <= mid and H > mid and C < O: magnet = "⚠️ DN-REJ-UP"; mag_col = Fore.MAGENTA
    elif O >= mid and L < mid and C > O: magnet = "⚠️ UP-REJ-DN"; mag_col = Fore.GREEN  

The Core Logic: Linear Regression Meets Price Magnetism

In the world of professional trading, standard indicators often lag behind real-time price action. The GMM Master Dashboard was engineered to bridge this gap by combining advanced mathematics with a legendary price action discovery from 2014: The EMA2 Weighted Magnet. This system doesn't just track where the price is; it anticipates where the price is being "drawn" to.


if __name__ == "__main__":
    if not mt5.initialize(): quit()
    selected_tf_id, tf_name = GMM_Select_TF()
    
    try:
        while True:
            data_results = {m: GMM_Get_Data(m, selected_tf_id) for m in majors}
            os.system('cls' if os.name == 'nt' else 'clear')
            
            print(Fore.YELLOW + "="*65 + Style.RESET_ALL)
            print(Fore.YELLOW + f" GMM MASTER DASHBOARD LR MAGNET | TF: {tf_name} | FULL SCAN (30 PAIRS) " + Style.RESET_ALL)
            print(Fore.YELLOW + "="*65 + Style.RESET_ALL)
            print(f"{' SYMBOL':<11} | {' DEGREE':<8} | {'LR STATUS':<18} | {'PRICE MAGNET'}")
            print("-" * 65)
            
            for m in majors:
                res = data_results[m]
                if res:
                    print(f"{' '}{m:<10} | {res['deg']:>7.2f}° | {Fore.WHITE}{res['status']:<18}{Style.RESET_ALL} | {res['mag_col']}{res['magnet']}{Style.RESET_ALL}")
            
            print(Fore.YELLOW + "="*65 + Style.RESET_ALL)
            print(Fore.YELLOW + " GMM CORRELATION & ENTRY STRATEGY :" + Style.RESET_ALL)
            print("-" * 65)
            
            for l in logic_list:
                rA, rB = data_results[l["A"]], data_results[l["B"]]
                if rA and rB:
                    signal, col = "Wait...", Fore.WHITE
                    bull_status = ["UP_Strong▲▲", "UP_Strengthened▲▲", "DN_Reversal▲"]
                    bear_status = ["DN_Strong▼▼", "DN_Strengthened▼▼", "UP_Reversal▼"]
                    bull_magnet = ["🧲 UP", "⚠️ UP-REJ-DN"]
                    bear_magnet = ["🧲 DN", "⚠️ DN-REJ-UP"]

                    a_is_bull, a_is_bear = any(s == rA["status"] for s in bull_status), any(s == rA["status"] for s in bear_status)
                    b_is_bull, b_is_bear = any(s == rB["status"] for s in bull_status), any(s == rB["status"] for s in bear_status)
                    a_in_bull, a_in_bear = any(s == rA["magnet"] for s in bull_magnet), any(s == rA["magnet"] for s in bear_magnet)
                    b_in_bull, b_in_bear = any(s == rB["magnet"] for s in bull_magnet), any(s == rB["magnet"] for s in bear_magnet)

                    if l["Type"] == "self":
                        is_buy, is_sell = (a_is_bull and a_in_bull), (a_is_bear and a_in_bear)
                    elif l["Type"] == "kali":
                        is_buy, is_sell = ((a_is_bull and b_is_bull) and (a_in_bull and b_in_bull)), ((a_is_bear and b_is_bear) and (a_in_bear and b_in_bear))
                    else: # Type bagi
                        is_buy, is_sell = ((a_is_bull and b_is_bear) and (a_in_bull and b_in_bear)), ((a_is_bear and b_is_bull) and (a_in_bear and b_in_bull))

                   # --- GMM_ LOGIC ENTRY STRATEGY WITH MANTAP MENTONG COLORS ---
                    if is_buy:
                        if "🧲 UP" in rA["magnet"]:
                            signal, col = "🚀 STRONG BUY", Fore.GREEN     # Hijau Segar: Tren Sehat
                        elif "⚠️ UP-REJ-DN" in rA["magnet"]:
                            signal, col = "🔥 BUY NOW!", Fore.CYAN        # Biru Elektrik: Reversal Cepat (Favorit!)
                        else:
                            signal, col = "Wait...", Fore.WHITE
                            
                    elif is_sell:
                        if "🧲 DN" in rA["magnet"]:
                            signal, col = "🚨 STRONG SELL", Fore.RED      # Merah Berani: Konfirmasi Bearish
                        elif "⚠️ DN-REJ-UP" in rA["magnet"]:
                            signal, col = "🔥 SELL NOW!", Fore.MAGENTA    # Ungu Magenta: Rejection Tajam
                        else:
                            signal, col = "Wait...", Fore.WHITE
                            
                    else:
                        signal, col = "Wait...", Fore.WHITE
                    
                    print(f"{' '}{l['A']} x {l['B']} => {l['Cross']:<8} | {col}{signal}{Style.RESET_ALL}")

            print("-" * 65)
            print(Fore.WHITE + " GMM_ Info: 🔥 NOW! = Trend + Magnet Alignment (Best Entry)")
            print(" GMM_ Info: ⚠️ REJ = Strong Rejection at Magnet Median")
            print(" GMM_ Info: Press Ctrl+C to stop." + Style.RESET_ALL)
            time.sleep(20)

As you can see, the dashboard operates on two sophisticated analytical layers. First, it calculates the LRDegrees (Linear Regression Degrees) to identify the dominant market trend with mathematical precision. Second, it applies the 2014 Magnet Logic, which utilizes the EMA2 of the WEIGHTED PRICE = ((HIGH + LOW + CLOSE + CLOSE) / 4). This act as a Price Magnet, identifying the equilibrium point that the market constantly seeks to revisit.

The Power of Boolean Aggregation

The decision engine using Python's any() function combined with Dual-Condition Mapping.

  • 1. Status Mapping: Variables like a_is_bull scan for specific trend phases (Strong, Strengthening, or Reversal) on the Linear Regression Degrees indicator (LRDegress)
  • 2. Magnet Mapping: Variables like a_in_bull confirm the price proximity to the EMA2 Weighted Magnet.

By requiring both conditions to be True, the GMM Dashboard effectively filters out high-risk trades, ensuring that every "STRONG BUY" or "NOW!" signal is backed by both mathematical trend strength and physical price alignment. This is the secret behind the dashboard's high-precision entries.

Multi-Pair Correlation: The "Entry Now" Signal

To ensure maximum accuracy, the dashboard monitors 30 currency pairs simultaneously through complex correlation matrices (Multiplication and Division types). An "🔥 ENTRY NOW!" signal is only triggered when the market trend (LRDegrees), the correlation alignment, and the Magnet Rejection occur in perfect synchronization. This multi-layered filter is designed to protect capital while capturing the most explosive market moves.

A Professional Tool for Modern Traders

The GMM_ Master Dashboard is more than just a script; it is a comprehensive trading station. By integrating the 2014 Discovery Logic with modern Python-based automation, we provide traders with a clear, color-coded roadmap to navigate the complexities of the Forex market with confidence.

How to Install and Activate the GMM Master Dashboard

To experience the power of the 2014 Magnet Discovery and Linear Regression Degrees indicator in real-time, you must set up the Python environment on your local machine. Follow these steps to get started:

  • 1. Prerequisites and Installation:
    • Install Python: Ensure you have the latest version of Python installed from python.org.
    • MetaTrader 5 Terminal: You must have the MT5 Desktop terminal installed and logged into your trading account.
    • Required Libraries: Open your terminal or CMD and install the necessary dependencies using the following command: pip install MetaTrader5 numpy colorama
  • 2. Once your environment is set up, launching the dashboard is incredibly simple. You don't need to be a coding expert to keep it running.
  • 3. Direct Launch (Double-Click Method):
    • Locate your GMM_MASTER_DASHBOARD_LR_MAGNET.py file in its folder.
    • Simply double-click the file.
    • The Windows Python Launcher (`py.exe`) will automatically open a Command Prompt window and start the live stream.
  • 4. Upon launch, the GMM Master Dashboard will prompt the user to select the timeframe to use. Options include M1, M5, M15, M30, H1, H4, and D1.
  • 5. Visual Confirmation:
    • You will see a black terminal window displaying real-time Linear Rergession Degrees and the Price Magnet Status.
    • Keep this window open while you trade; it acts as your Radar for 30 currency and metals pairs.
  • 6. To Stop the Program: Simply close the CMD window or press Ctrl + C on your keyboard to safely shut down the MT5 connection.

⚠️ Important: Risk Disclaimer

  • Demo Testing: You are strongly advised to test this GMM Master Dashboard on MT5 Demo Account first to to synchronize your trading style with the GMM logic.
  • Real Account Trading: If you proceed to use this GMM Master Dashboard for automated trading on a Real Account, you do so at your own risk. Algorithmic trading involves substantial risk to your capital.
  • Always remember the rules: Never trade with money you cannot afford to lose.
  • Trading foreign exchange on margin carries a high level of risk and may not be suitable for all investors. The high degree of leverage can work against you as well as for you. Before deciding to invest in foreign exchange, you should carefully consider your investment objectives, level of experience, and risk appetite. The GMM Master Dashboard logic provided in this article are for educational purposes and do not guarantee profits. Past performance is not indicative of future results.

Vital Records

If you think the GMM Master Dashboard is worthy of being used for automated trading as an Expert Advisor, please leave a comment below this article.

If at least 25 people agree that this indicator is worthy of being used as an Expert Advisor, I will create an Expert Advisor based on its signals and share it on this blog.

We hope that this article and the GMM Master Dashboard program will be useful for traders in learning and generating new ideas, which is ultimately expected to be successful in forex trading.

The GMM Master Dashboard is just an idea and tool for trading and still needs further development.

See you in the next article on Expert Advisor programs or indicators for MetaTrader 4 and MetaTrader 5.

If you have any ideas for developing this GMM Master Dashboard program or have a new ideas, please leave your comments below this article.

Thanks for reading this article.

Note: Please see the source program and download at the bottom of this article.

Risk Warning: Trading Forex and CFDs involves significant risk and may not be suitable for all investors. All content provided is for educational purposes only.


# --- Copyright: 3rjfx @ https://www.forexhomeexpert.com
# --- Created  : 2026/02/06 ---
# --- GMM : GEMINI MANTAP MENTONG!
import MetaTrader5 as mt5
import numpy as np
import time
import os
from colorama import init, Fore, Style

init()

# --- 1. GMM_ FUNCTIONS ---
def GMM_ExponentialMA(price_array, period):
    if period <= 0 or len(price_array) == 0: return price_array
    pr = 2.0 / (period + 1.0)
    result_ema = np.zeros_like(price_array)
    result_ema[0] = price_array[0] 
    for i in range(1, len(price_array)):
        result_ema[i] = (price_array[i] * pr) + (result_ema[i-1] * (1.0 - pr))
    return result_ema

def GMM_Select_TF():
    os.system('cls' if os.name == 'nt' else 'clear')
    print(Fore.CYAN + "====================================================" + Style.RESET_ALL)
    print(Fore.YELLOW + "   GMM TIMEFRAME SELECTOR | COMMANDER, Select TF:" + Style.RESET_ALL)
    print(Fore.CYAN + "====================================================" + Style.RESET_ALL)
    print(" 1. M1  | 2. M5  | 3. M15 | 4. M30 | 5. H1 | 6. H4 | 7. D1")
    print("-" * 52)
    choice = input(Fore.YELLOW + " Type your preferred number (1-7): " + Style.RESET_ALL)
    tf_map = {
        "1": (mt5.TIMEFRAME_M1, "M1"),   "2": (mt5.TIMEFRAME_M5, "M5"),
        "3": (mt5.TIMEFRAME_M15, "M15"), "4": (mt5.TIMEFRAME_M30, "M30"),
        "5": (mt5.TIMEFRAME_H1, "H1"),   "6": (mt5.TIMEFRAME_H4, "H4"), "7": (mt5.TIMEFRAME_D1, "D1")
    }
    return tf_map.get(choice, (mt5.TIMEFRAME_M30, "M30"))

# --- 2. GMM_ DATA ENGINE (LOGIC AREA 4 + MAGNET PRICE) ---
def GMM_Get_Data(symbol, timeframe_id):
    rates = mt5.copy_rates_from_pos(symbol, timeframe_id, 0, 100)
    if rates is None or len(rates) < 10: return None
    
    popen, phigh, plow, pclose = np.array([r['open'] for r in rates]), np.array([r['high'] for r in rates]), np.array([r['low'] for r in rates]), np.array([r['close'] for r in rates])
    pweighted = (phigh + plow + pclose + pclose) / 4.0
    ema2_pm = GMM_ExponentialMA(pweighted, 2)
    
    y, j = ema2_pm[-3:], np.arange(3)
    suma, sumab, sumb1, sumb2 = np.sum(y), np.sum(y * j), np.sum(j), np.sum(j**2)
    denom = (sumb2 * 3) - (sumb1**2)
    b = ((sumab * 3) - (sumb1 * suma)) / denom
    c = (suma - (sumb1 * b)) / 3
    lr_buffers = c + (b * j)

    hmax, lmin = np.max(phigh), np.min(plow)
    cur_degrees = round(270 + ((lr_buffers[-1] - lmin) / (hmax - lmin)) * 180, 2)
    prev1_degrees = round(270 + ((lr_buffers[-2] - lmin) / (hmax - lmin)) * 180, 2)
    prev2_degrees = round(270 + ((lr_buffers[-3] - lmin) / (hmax - lmin)) * 180, 2)
    div1_degrees, div0_degrees = round(prev1_degrees - prev2_degrees, 2), round(cur_degrees - prev2_degrees, 2)

    if cur_degrees > 360.0: cur_degrees -= 360.0
    if cur_degrees == 360.0: cur_degrees = 0.0
    dgrs_up, dgrs_dn = div0_degrees > div1_degrees, div0_degrees < div1_degrees

    status_lr = "SIDEWAY"
    if (270.0 <= cur_degrees < 315.0 and dgrs_dn):   status_lr = "DN_Strong▼▼"
    elif (270.0 <= cur_degrees < 315.0 and dgrs_up): status_lr = "DN_Weakened▼"
    elif (315.0 <= cur_degrees < 360.0 and dgrs_dn): status_lr = "DN_Strengthened▼▼"
    elif (315.0 <= cur_degrees < 360.0 and dgrs_up): status_lr = "DN_Reversal▲"
    elif (0.0 <= cur_degrees < 45.0 and dgrs_up):    status_lr = "UP_Strengthened▲▲"
    elif (0.0 <= cur_degrees < 45.0 and dgrs_dn):    status_lr = "UP_Reversal▼"
    elif (45.0 <= cur_degrees <= 90.0 and dgrs_up):  status_lr = "UP_Strong▲▲"
    elif (45.0 <= cur_degrees <= 90.0 and dgrs_dn):  status_lr = "UP_Weakened▲"

    mid = ema2_pm[-1]
    O, H, L, C = popen[-1], phigh[-1], plow[-1], pclose[-1]
    magnet, mag_col = "FLAT", Fore.WHITE
    if O <= mid and C > mid: magnet = "🧲 UP"; mag_col = Fore.CYAN
    elif O >= mid and C < mid: magnet = "🧲 DN"; mag_col = Fore.RED
    elif O <= mid and H > mid and C < O: magnet = "⚠️ DN-REJ-UP"; mag_col = Fore.MAGENTA
    elif O >= mid and L < mid and C > O: magnet = "⚠️ UP-REJ-DN"; mag_col = Fore.GREEN

    return {"deg": cur_degrees, "status": status_lr, "magnet": magnet, "mag_col": mag_col}

# --- 3. BASE PAIRS: MAJOR - JPY CROSS AND METALS ---
majors = ["AUDUSD", "EURUSD", "GBPUSD", "NZDUSD", "USDCAD", "USDCHF", "USDJPY", 
          "AUDJPY", "CADJPY", "CHFJPY","EURJPY", "GBPJPY","NZDJPY", "XAGUSD", "XAUUSD"]

# --- 4. FULL 30 PAIRS LOGIC LIST ---
logic_list = [
    {"A": "EURUSD", "B": "AUDUSD", "Cross": "EURAUD", "Type": "bagi"},
    {"A": "EURUSD", "B": "USDCAD", "Cross": "EURCAD", "Type": "kali"},
    {"A": "EURUSD", "B": "USDCHF", "Cross": "EURCHF", "Type": "kali"},    
    {"A": "EURUSD", "B": "GBPUSD", "Cross": "EURGBP", "Type": "bagi"},
    {"A": "EURJPY", "B": "EURJPY", "Cross": "EURJPY", "Type": "self"},
    {"A": "EURUSD", "B": "NZDUSD", "Cross": "EURNZD", "Type": "bagi"},
    {"A": "EURUSD", "B": "EURUSD", "Cross": "EURUSD", "Type": "self"},
    {"A": "GBPUSD", "B": "AUDUSD", "Cross": "GBPAUD", "Type": "bagi"},
    {"A": "GBPUSD", "B": "USDCAD", "Cross": "GBPCAD", "Type": "kali"},
    {"A": "GBPUSD", "B": "USDCHF", "Cross": "GBPCHF", "Type": "kali"},    
    {"A": "GBPJPY", "B": "GBPJPY", "Cross": "GBPJPY", "Type": "self"},
    {"A": "GBPUSD", "B": "NZDUSD", "Cross": "GBPNZD", "Type": "bagi"},
    {"A": "GBPUSD", "B": "GBPUSD", "Cross": "GBPUSD", "Type": "self"},
    {"A": "AUDUSD", "B": "USDCAD", "Cross": "AUDCAD", "Type": "kali"},
    {"A": "AUDUSD", "B": "USDCHF", "Cross": "AUDCHF", "Type": "kali"},    
    {"A": "AUDJPY", "B": "AUDJPY", "Cross": "AUDJPY", "Type": "self"},
    {"A": "AUDUSD", "B": "NZDUSD", "Cross": "AUDNZD", "Type": "bagi"},
    {"A": "AUDUSD", "B": "AUDUSD", "Cross": "AUDUSD", "Type": "self"},
    {"A": "NZDUSD", "B": "USDCAD", "Cross": "NZDCAD", "Type": "kali"},
    {"A": "NZDUSD", "B": "USDCHF", "Cross": "NZDCHF", "Type": "kali"},    
    {"A": "NZDJPY", "B": "NZDJPY", "Cross": "NZDJPY", "Type": "self"},
    {"A": "NZDUSD", "B": "NZDUSD", "Cross": "NZDUSD", "Type": "self"},
    {"A": "USDCAD", "B": "USDCHF", "Cross": "CADCHF", "Type": "bagi"},
    {"A": "CADJPY", "B": "CADJPY", "Cross": "CADJPY", "Type": "self"},
    {"A": "USDCAD", "B": "USDCAD", "Cross": "USDCAD", "Type": "self"},    
    {"A": "CHFJPY", "B": "CHFJPY", "Cross": "CHFJPY", "Type": "self"},
    {"A": "USDCHF", "B": "USDCHF", "Cross": "USDCHF", "Type": "self"},
    {"A": "USDJPY", "B": "USDJPY", "Cross": "USDJPY", "Type": "self"},
    {"A": "XAGUSD", "B": "XAGUSD", "Cross": "XAGUSD", "Type": "self"},
    {"A": "XAUUSD", "B": "XAUUSD", "Cross": "XAUUSD", "Type": "self"}
]

# --- 5. MAIN LOOP ---
if __name__ == "__main__":
    if not mt5.initialize(): quit()
    selected_tf_id, tf_name = GMM_Select_TF()
    
    try:
        while True:
            data_results = {m: GMM_Get_Data(m, selected_tf_id) for m in majors}
            os.system('cls' if os.name == 'nt' else 'clear')
            
            print(Fore.YELLOW + "="*65 + Style.RESET_ALL)
            print(Fore.YELLOW + f" GMM MASTER DASHBOARD LR MAGNET | TF: {tf_name} | FULL SCAN (30 PAIRS) " + Style.RESET_ALL)
            print(Fore.YELLOW + "="*65 + Style.RESET_ALL)
            print(f"{' SYMBOL':<11} | {' DEGREE':<8} | {'LR STATUS':<18} | {'PRICE MAGNET'}")
            print("-" * 65)
            
            for m in majors:
                res = data_results[m]
                if res:
                    print(f"{' '}{m:<10} | {res['deg']:>7.2f}° | {Fore.WHITE}{res['status']:<18}{Style.RESET_ALL} | {res['mag_col']}{res['magnet']}{Style.RESET_ALL}")
            
            print(Fore.YELLOW + "="*65 + Style.RESET_ALL)
            print(Fore.YELLOW + " GMM CORRELATION & ENTRY STRATEGY :" + Style.RESET_ALL)
            print("-" * 65)
            
            for l in logic_list:
                rA, rB = data_results[l["A"]], data_results[l["B"]]
                if rA and rB:
                    signal, col = "Wait...", Fore.WHITE
                    bull_status = ["UP_Strong▲▲", "UP_Strengthened▲▲", "DN_Reversal▲"]
                    bear_status = ["DN_Strong▼▼", "DN_Strengthened▼▼", "UP_Reversal▼"]
                    bull_magnet = ["🧲 UP", "⚠️ UP-REJ-DN"]
                    bear_magnet = ["🧲 DN", "⚠️ DN-REJ-UP"]

                    a_is_bull, a_is_bear = any(s == rA["status"] for s in bull_status), any(s == rA["status"] for s in bear_status)
                    b_is_bull, b_is_bear = any(s == rB["status"] for s in bull_status), any(s == rB["status"] for s in bear_status)
                    a_in_bull, a_in_bear = any(s == rA["magnet"] for s in bull_magnet), any(s == rA["magnet"] for s in bear_magnet)
                    b_in_bull, b_in_bear = any(s == rB["magnet"] for s in bull_magnet), any(s == rB["magnet"] for s in bear_magnet)

                    if l["Type"] == "self":
                        is_buy, is_sell = (a_is_bull and a_in_bull), (a_is_bear and a_in_bear)
                    elif l["Type"] == "kali":
                        is_buy, is_sell = ((a_is_bull and b_is_bull) and (a_in_bull and b_in_bull)), ((a_is_bear and b_is_bear) and (a_in_bear and b_in_bear))
                    else: # Type bagi
                        is_buy, is_sell = ((a_is_bull and b_is_bear) and (a_in_bull and b_in_bear)), ((a_is_bear and b_is_bull) and (a_in_bear and b_in_bull))

                   # --- GMM_ LOGIC ENTRY STRATEGY WITH MANTAP MENTONG COLORS ---
                    if is_buy:
                        if "🧲 UP" in rA["magnet"]:
                            signal, col = "🚀 STRONG BUY", Fore.GREEN     # Fresh Green: A Healthy Trend
                        elif "⚠️ UP-REJ-DN" in rA["magnet"]:
                            signal, col = "🔥 BUY NOW!", Fore.CYAN        # Electric Blue: Quick Reversal (Favorite!)
                        else:
                            signal, col = "Wait...", Fore.WHITE
                            
                    elif is_sell:
                        if "🧲 DN" in rA["magnet"]:
                            signal, col = "🚨 STRONG SELL", Fore.RED      # Bold Red: Bearish Confirmation
                        elif "⚠️ DN-REJ-UP" in rA["magnet"]:
                            signal, col = "🔥 SELL NOW!", Fore.MAGENTA    # Magenta Purple: Sharp Rejection
                        else:
                            signal, col = "Wait...", Fore.WHITE
                            
                    else:
                        signal, col = "Wait...", Fore.WHITE
                    
                    print(f"{' '}{l['A']} x {l['B']} => {l['Cross']:<8} | {col}{signal}{Style.RESET_ALL}")

            print("-" * 65)
            print(Fore.WHITE + " GMM_ Info: 🔥 NOW! = Trend + Magnet Alignment (Best Entry)")
            print(" GMM_ Info: ⚠️ REJ = Strong Rejection at Magnet Median")
            print(" GMM_ Info: Press Ctrl+C to stop." + Style.RESET_ALL)
            time.sleep(20)
            
    except KeyboardInterrupt:
        print(Fore.RED + "\nDashboard Stopped." + Style.RESET_ALL)
    finally:
        mt5.shutdown()
        
//----------//

//+------------------------------------------------------------------+
//|                                                    LRDegrees.mq5 |
//|                           Copyright 2017, Roberto Jacobs (3rjfx) |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "https://www.mql5.com/en/users/3rjfx. ~ By 3rjfx ~ Created: 2017/01/12"
#property link      "http://www.mql5.com"
#property link      "https://www.mql5.com/en/users/3rjfx"
#property version   "1.00"
#property strict
/*
== Last Update: 2026/02/10 ==
*/
//--
#property description "MetaTrader 5 Forex Indicator Double Line of LinearRegression with Degrees and Trend Alerts."
//---
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   4
#property indicator_style1  DRAW_NONE
#property indicator_style2  DRAW_NONE
#property indicator_style3  DRAW_NONE
#property indicator_style4  DRAW_NONE
//--
enum SetDegree
  {
    Line2,
    Line1
  };
//--
//---
input SetDegree           degress = Line2;         // Set Linear Degrees Line
input int          barsCountLine1 = 25;            // Linear Regression 1 Bars to count
input int          barsCountLine2 = 3;             // Linear Regression 2 Bars to count
input color          LRLineColor1 = clrRed;        // Linear Regression Line1 Color
input color          LRLineColor2 = clrBlue;       // Linear Regression Line2 Color
input color          RoundedColor = clrAqua;       // Rounded Color
input color              UpsColor = clrAqua;       // Arrow Up Color
input color              DnsColor = clrOrangeRed;  // Arrow Down Color
input color            PriceColor = clrSnow;       // Arrow Right Price  Color
input ENUM_LINE_STYLE LRLineStyle = STYLE_SOLID;   // Linear Regression Line style
input int             LRLineWidth = 2;             // Linear Regression Line width
//--
input bool              MsgAlerts = true;
input bool            SoundAlerts = true;
input bool            eMailAlerts = false;
input string       SoundAlertFile = "alert.wav";
//--
//--- buffers
double MABuffers[];
double DegreesUp[];
double DegreesDn[];
double LRBuffers1[];
double LRBuffers2[];
//--
ENUM_BASE_CORNER corner=CORNER_RIGHT_UPPER;
int dist_x=144;
int dist_xt=104;
int dist_y=125;
//--
int hMA;
int cmal,xmal;
int posalert;
int prevalert;
int bar_count;
int bars_calculated=0;
//--
color stgBull=clrBlue;
color stsBull=clrAqua;
color stsBear=clrYellow;
color stgBear=clrRed;
color txtrbl=clrWhite;
color txtblk=clrBlack;
color rndclr;
color arrclr;
color txtclr;
//--
long Chart_Id;
//--
string name;
string dtext;
string Albase,AlSubj,AlMsg;
//---------//
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//--- indicator buffers mapping
//---
   Chart_Id=ChartID();
   bar_count=120;
   name="LR Degrees";
   IndicatorSetString(INDICATOR_SHORTNAME,name);
   IndicatorSetInteger(INDICATOR_DIGITS,3);
//--- indicator buffers mapping
   //---
   SetIndexBuffer(0,DegreesUp,INDICATOR_DATA);
   SetIndexBuffer(1,DegreesDn,INDICATOR_DATA);
   SetIndexBuffer(2,LRBuffers1,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,LRBuffers2,INDICATOR_CALCULATIONS);
//--- indicator labels
   PlotIndexSetString(0,PLOT_LABEL,"UpDegrees");
   PlotIndexSetString(1,PLOT_LABEL,"DnDegrees");
   PlotIndexSetString(2,PLOT_LABEL,"LR_Line1");
   PlotIndexSetString(3,PLOT_LABEL,"LR_Line2");
   //--
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0.0);
   PlotIndexSetDouble(1,PLOT_EMPTY_VALUE,0.0);
   //--
   hMA=iMA(Symbol(),Period(),2,0,MODE_EMA,PRICE_WEIGHTED);
   //---
//--- initialization done
   return(INIT_SUCCEEDED);
  }
//---------//
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//----
   //--
   IndicatorRelease(hMA);
   ObjectsDeleteAll(Chart_Id,0,-1);
//----
   return;
  }
//---------//
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
  {
//------
   if(rates_total<bar_count) return(0);
   //--
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(time,true);
//------
//--- Set Last error value to Zero
   ResetLastError();
   ChartRedraw(0);
   //---
   //--
   int l,r,j,
       dtxt=0;
   //---
   bool dgrsUp=false;
   bool dgrsDn=false;
   //--
   double x,y,z,
          a,b,c;
   double sumy=0.0,
          sumx1=0.0,
          sumxy=0.0,
          sumx2=0.0;
   double suma=0.0,
          sumb1=0.0,
          sumab=0.0,
          sumb2=0.0;
   //--
   double hmax=0.0,
          lmin=0.0;
   //--
   double cur_degrees=0.0,
          prev1_degrees=0.0,
          prev2_degrees=0.0,
          div1_degrees=0.0,
          div0_degrees=0.0;
   //--
   //-- prepare the Highest and Lowest Price
   int HL=100;
   int Hi=iHighest(_Symbol,0,MODE_HIGH,HL,0);
   int Lo=iLowest(_Symbol,0,MODE_LOW,HL,0);
   if(Hi!=-1) hmax=high[Hi];
   if(Lo!=-1) lmin=low[Lo];
   //--
   double rangetb=(hmax-lmin);
   double toplevel1=lmin+(rangetb/1000*838);
   double toplevel2=lmin+(rangetb/1000*618);
   double midlevel=lmin+(rangetb/1000*500);
   double botlevel2=lmin+(rangetb/1000*382);
   double botlevel1=lmin+(rangetb/1000*162);
   //--
//--- number of values copied from the iMA indicator
   int values_to_copy;
//--- determine the number of values calculated in the indicator
   int calculated=BarsCalculated(hMA);
   if(calculated<=0)
     {
      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
     }
//--- if it is the first start of calculation of the indicator or if the number of values in the iMA indicator changed
//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history)
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
     {
      //--- if the MABuffer array is greater than the number of values in the iMA indicator for symbol/period, then we don't copy everything
      //--- otherwise, we copy less than the size of indicator buffers
      if(calculated>rates_total)
         values_to_copy=rates_total;
      else
         values_to_copy=calculated;
     }
   else
     {
      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate()
      //--- for calculation not more than one bar is added
      values_to_copy=(rates_total-prev_calculated)+1;
     }
   //--
   ArrayResize(DegreesUp,calculated);
   ArrayResize(DegreesDn,calculated);
   ArrayResize(MABuffers,calculated);
   ArraySetAsSeries(DegreesUp,true);
   ArraySetAsSeries(DegreesDn,true);   
   ArraySetAsSeries(MABuffers,true);
//----
   CopyBuffer(hMA,0,0,values_to_copy,MABuffers);
   //--
   for(r=0; r<barsCountLine1; r++)
     {
      sumy+=MABuffers[r];
      sumxy+=MABuffers[r]*r;
      sumx1+=r;
      sumx2+=r*r;
     }
   //--
   x=sumx2*barsCountLine1-sumx1*sumx1;
   y=(sumxy*barsCountLine1-sumx1*sumy)/x;
   z=(sumy-sumx1*y)/barsCountLine1;
   //--
   //-- Linear regression MA trend 1
   for(l=0; l<barsCountLine1; l++) LRBuffers1[l]=z+y*l; 
   //--
   for(j=0; j<barsCountLine2; j++)
     {
      suma+=MABuffers[j];
      sumab+=MABuffers[j]*j;
      sumb1+=j;
      sumb2+=j*j;
     }
   //--
   a=sumb2*barsCountLine2-sumb1*sumb1;
   b=(sumab*barsCountLine2-sumb1*suma)/a;
   c=(suma-sumb1*b)/barsCountLine2;
   //--
   //-- Linear regression MA trend 2
   for(l=0; l<barsCountLine2; l++) LRBuffers2[l]=c+b*l;
   //---
   for(int i=bar_count-1; i>=0; i--)
     {
       //--
       if(i==0)
         {
           switch(degress)
             {
               case 0:
                 {
                   cur_degrees=NormalizeDouble(270+(((LRBuffers2[0]-lmin)/(hmax-lmin))*180),2);
                   prev1_degrees=NormalizeDouble(270+(((LRBuffers2[1]-lmin)/(hmax-lmin))*180),2);
                   prev2_degrees=NormalizeDouble(270+(((LRBuffers2[2]-lmin)/(hmax-lmin))*180),2);
                   div1_degrees=prev1_degrees - prev2_degrees;
                   div0_degrees=cur_degrees - prev2_degrees;
                   break;
                 }
               //--
               case 1:
                 {
                   cur_degrees=NormalizeDouble(270+(((LRBuffers1[0]-lmin)/(hmax-lmin))*180),2);
                   prev1_degrees=NormalizeDouble(270+(((LRBuffers1[1]-lmin)/(hmax-lmin))*180),2);
                   prev2_degrees=NormalizeDouble(270+(((LRBuffers1[2]-lmin)/(hmax-lmin))*180),2);
                   div1_degrees=prev1_degrees - prev2_degrees;
                   div0_degrees=cur_degrees - prev2_degrees;
                   break;
                 }
             }
           //--
           if(cur_degrees>360.0) {cur_degrees=NormalizeDouble(cur_degrees-360.0,2);}
           if(cur_degrees==360.0) {cur_degrees=NormalizeDouble(0.0,2);}
           //- To give a value of 90.0 degrees to the indicator, when the price moves up very quickly and make a New Windows Price Max.
           if(cur_degrees==90.0) {cur_degrees=NormalizeDouble(90.0,2);}
           //- To give a value of 270.0 degrees to the indicator, when the price moves down very quickly and make a New Windows Price Min.
           if(cur_degrees==270.0) {cur_degrees=NormalizeDouble(270.0,2);}
           //--
           if(div0_degrees>div1_degrees) {dgrsUp=true; dgrsDn=false; DegreesUp[i]=cur_degrees; DegreesDn[i]=0.0;}
           if(div0_degrees<div1_degrees) {dgrsDn=true; dgrsUp=false; DegreesDn[i]=cur_degrees; DegreesUp[i]=0.0;}
           //---
           if((cur_degrees>=270.0 && cur_degrees<315.0)&&(dgrsDn==true)) {rndclr=stgBear; arrclr=stgBear; txtclr=txtrbl; posalert=11;}
           if((cur_degrees>=270.0 && cur_degrees<315.0)&&(dgrsUp==true)) {rndclr=stgBear; arrclr=stsBear; txtclr=txtrbl; posalert=12;}
           if((cur_degrees>=315.0 && cur_degrees<360.0)&&(dgrsDn==true)) {rndclr=stsBear; arrclr=stgBear; txtclr=txtblk; posalert=21;}
           if((cur_degrees>=315.0 && cur_degrees<360.0)&&(dgrsUp==true)) {rndclr=stsBear; arrclr=stsBull; txtclr=txtblk; posalert=23;}
           if((cur_degrees>=0.0 && cur_degrees<45.0)&&(dgrsUp==true)) {rndclr=stsBull; arrclr=stgBull; txtclr=txtblk; posalert=34;}
           if((cur_degrees>=0.0 && cur_degrees<45.0)&&(dgrsDn==true)) {rndclr=stsBull; arrclr=stsBear; txtclr=txtblk; posalert=32;}
           if((cur_degrees>=45.0 && cur_degrees<=90.0)&&(dgrsUp==true)) {rndclr=stgBull; arrclr=stgBull; txtclr=txtrbl; posalert=44;}
           if((cur_degrees>=45.0 && cur_degrees<=90.0)&&(dgrsDn==true)) {rndclr=stgBull; arrclr=stsBull; txtclr=txtrbl; posalert=43;}
           //---
           dtext=DoubleToString(cur_degrees,1)+CharToString(176);
           if(StringLen(dtext)>5) {dtxt=24;}
           else if(StringLen(dtext)==5) {dtxt=20;}
           else {dtxt=17;}
           //--
           //---
           CreateRoundDegrees(Chart_Id,"RoundedDegrees","Wingdings",(string)CharToString(108),67,rndclr,corner,dist_x,dist_y,true);
           //--
           CreateRoundDegrees(Chart_Id,"TextDegrees","Bodoni MT Black",dtext,8,txtclr,corner,dist_xt+dtxt,dist_y+41,true);    
           //--
           if(dgrsUp) 
              CreateArrowDegrees(Chart_Id,"ArrUpDegrees","ArrDnDegrees","Wingdings",(string)CharToString(217),23,arrclr,corner,dist_xt+20,dist_y-2,true);
           //--
           if(dgrsDn) 
              CreateArrowDegrees(Chart_Id,"ArrDnDegrees","ArrUpDegrees","Wingdings",(string)CharToString(218),23,arrclr,corner,dist_xt+20,dist_y+63,true);
           //---
           color clinear1=LRBuffers1[0]>=LRBuffers1[barsCountLine1-1] ? LRLineColor2 : LRLineColor1;
           CreateLRTrendLine(Chart_Id,"LRTrendLine1",time[0],LRBuffers1[0],time[barsCountLine1-1],LRBuffers1[barsCountLine1-1],
                             LRLineWidth,LRLineStyle,clinear1,false,true);
           //--
           color clinear2=LRBuffers2[0]>=LRBuffers2[barsCountLine2-1] ? LRLineColor2 : LRLineColor1;
           CreateLRTrendLine(Chart_Id,"LRTrendLine2",time[0],LRBuffers2[0],time[barsCountLine2-1],LRBuffers2[barsCountLine2-1],
                             LRLineWidth,LRLineStyle,clinear2,false,true);
           //--
           CreateArrowPrice(Chart_Id,"FiboLabelPrice_t1",time[0],toplevel1,PriceColor,STYLE_SOLID,1,ANCHOR_LEFT,true);
           //--
           CreateArrowPrice(Chart_Id,"FiboLabelPrice_t2",time[0],toplevel2,PriceColor,STYLE_SOLID,1,ANCHOR_LEFT,true);
           //--
           CreateArrowPrice(Chart_Id,"FiboLabelPrice_m",time[0],midlevel,PriceColor,STYLE_SOLID,1,ANCHOR_LEFT,true);
           //--
           CreateArrowPrice(Chart_Id,"FiboLabelPrice_b2",time[0],botlevel2,PriceColor,STYLE_SOLID,1,ANCHOR_LEFT,true);
           //--
           CreateArrowPrice(Chart_Id,"FiboLabelPrice_b1",time[0],botlevel1,PriceColor,STYLE_SOLID,1,ANCHOR_LEFT,true);
           //--
         }
     }
   //--
   ChartRedraw(0);
   PosAlerts(posalert);
   //---
//--- done
   return(rates_total);
  }
//--- end OnCalculate()
//---------//

void CreateRoundDegrees(long   chartid, 
                        string lable_name, 
                        string lable_font_model,
                        string lable_obj_text,
                        int    lable_font_size,
                        color  lable_color,
                        int    lable_corner,
                        int    lable_xdist,
                        int    lable_ydist,
                        bool   lable_hidden)
  {  
    //--
    ObjectDelete(chartid,lable_name);
    //--
    ObjectCreate(chartid,lable_name,OBJ_LABEL,0,0,0,0,0); // create rounded degrees
    ObjectSetInteger(chartid,lable_name,OBJPROP_FONTSIZE,lable_font_size); 
    ObjectSetString(chartid,lable_name,OBJPROP_FONT,lable_font_model);
    ObjectSetString(chartid,lable_name,OBJPROP_TEXT,lable_obj_text);
    ObjectSetInteger(chartid,lable_name,OBJPROP_COLOR,lable_color);
    ObjectSetInteger(chartid,lable_name,OBJPROP_CORNER,lable_corner);
    ObjectSetInteger(chartid,lable_name,OBJPROP_XDISTANCE,lable_xdist);
    ObjectSetInteger(chartid,lable_name,OBJPROP_YDISTANCE,lable_ydist);
    ObjectSetInteger(chartid,lable_name,OBJPROP_HIDDEN,lable_hidden);
    //--
  }   
//---------//

void CreateArrowDegrees(long   chartid, 
                        string lable_name1,
                        string lable_name2,
                        string lable_font_model,
                        string lable_obj_text,
                        int    lable_font_size,
                        color  lable_color,
                        int    lable_corner,
                        int    lable_xdist,
                        int    lable_ydist,
                        bool   lable_hidden)
  {  
    //--
    ObjectDelete(chartid,lable_name2);
    ObjectDelete(chartid,lable_name1);
    //--
    ObjectCreate(chartid,lable_name1,OBJ_LABEL,0,0,0,0,0); // create arrow degrees
    ObjectSetInteger(chartid,lable_name1,OBJPROP_FONTSIZE,lable_font_size); 
    ObjectSetString(chartid,lable_name1,OBJPROP_FONT,lable_font_model);
    ObjectSetString(chartid,lable_name1,OBJPROP_TEXT,lable_obj_text);
    ObjectSetInteger(chartid,lable_name1,OBJPROP_COLOR,lable_color);
    ObjectSetInteger(chartid,lable_name1,OBJPROP_CORNER,lable_corner);
    ObjectSetInteger(chartid,lable_name1,OBJPROP_XDISTANCE,lable_xdist);
    ObjectSetInteger(chartid,lable_name1,OBJPROP_YDISTANCE,lable_ydist);
    ObjectSetInteger(chartid,lable_name1,OBJPROP_HIDDEN,lable_hidden);
    //--
  }   
//---------//

void CreateLRTrendLine(long     chartid, 
                       string   line_name,
                       datetime line_time1,
                       double   line_price1,
                       datetime line_time2,
                       double   line_price2,
                       int      line_width,
                       int      line_style,
                       color    line_color,
                       bool     ray_right,
                       bool     line_hidden)
  {  
    //--
    ObjectDelete(chartid,line_name);
    //--
    ObjectCreate(chartid,line_name,OBJ_TREND,0,line_time1,line_price1,line_time2,line_price2); // create trend line
    ObjectSetInteger(chartid,line_name,OBJPROP_WIDTH,line_width);
    ObjectSetInteger(chartid,line_name,OBJPROP_STYLE,line_style);
    ObjectSetInteger(chartid,line_name,OBJPROP_COLOR,line_color);
    ObjectSetInteger(chartid,line_name,OBJPROP_RAY_RIGHT,ray_right);
    ObjectSetInteger(chartid,line_name,OBJPROP_HIDDEN,line_hidden);
    //--
  }   
//---------//

void CreateArrowPrice(long     chart_id,
                      string   arrow_name, 
                      datetime arrow_time,
                      double   arrow_pos,
                      color    arrow_color,
                      int      arrow_style,
                      int      arrow_width,
                      int      anchor,
                      bool     hidden)
  {
    //--
    ObjectDelete(chart_id,arrow_name);
    //--
    ObjectCreate(chart_id,arrow_name,OBJ_ARROW_RIGHT_PRICE,0,arrow_time,arrow_pos); // create arrow right price
    ObjectSetInteger(chart_id,arrow_name,OBJPROP_COLOR,arrow_color);
    ObjectSetInteger(chart_id,arrow_name,OBJPROP_STYLE,arrow_style);
    ObjectSetInteger(chart_id,arrow_name,OBJPROP_WIDTH,arrow_width);
    ObjectSetInteger(chart_id,arrow_name,OBJPROP_ANCHOR,anchor);
    ObjectSetInteger(chart_id,arrow_name,OBJPROP_HIDDEN,hidden);
    //--
  }
//---------//

enum TimeReturn
  {
    year        = 0,   // Year 
    mon         = 1,   // Month 
    day         = 2,   // Day 
    hour        = 3,   // Hour 
    min         = 4,   // Minutes 
    sec         = 5,   // Seconds 
    day_of_week = 6,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
    day_of_year = 7    // Day number of the year (January 1st is assigned the number value of zero) 
  };
//---------//

int MqlReturnDateTime(datetime reqtime,
                      const int mode) 
  {
    MqlDateTime mqltm;
    TimeToStruct(reqtime,mqltm);
    int valdate=0;
    //--
    switch(mode)
      {
        case 0: valdate=mqltm.year; break;        // Return Year 
        case 1: valdate=mqltm.mon;  break;        // Return Month 
        case 2: valdate=mqltm.day;  break;        // Return Day 
        case 3: valdate=mqltm.hour; break;        // Return Hour 
        case 4: valdate=mqltm.min;  break;        // Return Minutes 
        case 5: valdate=mqltm.sec;  break;        // Return Seconds 
        case 6: valdate=mqltm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
        case 7: valdate=mqltm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero) 
      }
    return(valdate);
  }
//---------//

void DoAlerts(string msgText,string eMailSub)
  {
     if (MsgAlerts) Alert(msgText);
     if (SoundAlerts) PlaySound(SoundAlertFile);
     if (eMailAlerts) SendMail(eMailSub,msgText);
  }
//---------//

string StrTF(int period)
  {
   switch(period)
     {
       //--
       case PERIOD_M1: return("M1");
       case PERIOD_M5: return("M5");
       case PERIOD_M15: return("M15");
       case PERIOD_M30: return("M30");
       case PERIOD_H1: return("H1");
       case PERIOD_H4: return("H4");
       case PERIOD_D1: return("D1");
       case PERIOD_W1: return("W1");
       case PERIOD_MN1: return("MN");
       //--
     }
   return(string(period));
  }  
//---------//

void PosAlerts(int curalerts)
   {
    //---
    cmal=MqlReturnDateTime(TimeCurrent(),TimeReturn(min));
    if(cmal!=xmal)
      {
        //--
        if((curalerts!=prevalert)&&(curalerts==43))
          {
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend Began to Fall, Bulish Weakened";
            AlMsg=AlSubj+" @ "+TimeToString(TimeLocal(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //---
        if((curalerts!=prevalert)&&(curalerts==32))
          {     
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend was Down, Bulish Reversal";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //---
        if((curalerts!=prevalert)&&(curalerts==21))
          {     
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend was Down, Bearish Strengthened";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }              
        //---
        if((curalerts!=prevalert)&&(curalerts==11))
          {     
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend was Down, Strong Bearish";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //---
        if((curalerts!=prevalert)&&(curalerts==12))
          {
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend Began to Rise, Bearish Weakened";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //---
        if((curalerts!=prevalert)&&(curalerts==23))
          {
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend was Up, Bearish Reversal";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //---
        if((curalerts!=prevalert)&&(curalerts==34))
          {
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend was Up, Bulish Strengthened";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //---
        if((curalerts!=prevalert)&&(curalerts==44))
          {
            Albase=name+" "+_Symbol+", TF: "+StrTF(_Period)+", Position "+dtext;
            AlSubj=Albase+" Trend was Up, Strong Bulish";
            AlMsg=AlSubj+" @ "+TimeToString(TimeCurrent(),TIME_SECONDS);
            DoAlerts(AlMsg,AlSubj);
            prevalert=curalerts;
          }
        //--
        xmal=cmal;
      }
    //---
    return;
   //----
   } //-end PosAlerts()
//---------//
//+------------------------------------------------------------------+

Please download the GMM Master Dashboard: GMM Master Dashboard and Indicator: LRDegrees


© 2026 GMM Master Dashboard - Developed by Roberto Jacobs (3rjfx)

Saturday, February 7, 2026

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert

1. Introduction

In the world of automated trading, the biggest challenge is filtering out market "noise" while maintaining enough trade frequency to grow an account. Today, we are proud to introduce a sophisticated solution: the ZigZag_OsMA_EMA_MCEA.

The quest for a stable and reliable automated trading system often leads traders to overly complex indicators that fail in real market conditions. Today, we introduce the ZigZag_OsMA_EMA_MCEA, a professional-grade Expert Advisor designed for MetaTrader 5 that brings institutional-level discipline to your retail trading account.

XAGUSDM30_ZigZag_OsMA_EMA_MCEA Figure 1: ZigZag_OsMA_EMA_MCEA chart display

2. Expert Advisor Input Parameters

To give you full control over the trading engine, here are the customizable parameters available in the ZigZag_OsMA_EMA_MCEA input properties:


//---
input group               "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
input TFUSE             Timeframe = TFM30;             // Select Expert TimeFrame, default TFM30
//---
input group               "=== ZigZag Indicator Input Properties ===";  // ZigZag Indicator Input Properties
input int                 zzDepth = 12;               // Input ZigZag Depth, default 12
input int                 zzDevia = 5;                // Input ZigZag Deviation, default 5
input int                 zzBackS = 3;                // Input ZigZag Back Step, default 3
//---
input group               "=== OsMA Indicator Input Properties ===";  // OsMA Indicator Input Properties
input int                  f_ema = 12;                // Period of Fast MA 
input int                  s_ema = 26;                // Period of Slow MA
input int                  sig_p = 9;                 // Period of Averaging of Difference 
input ENUM_APPLIED_PRICE   app_p = PRICE_CLOSE;       // type of Applied Price    
//---
input group               "=== EMA Indicator Input Properties ===";  // EMA Indicator Input Properties
input int              ma_period = 50;                // Averaging Period 
input int               ma_shift = 0;                 // Horizontal MA shift 
input ENUM_MA_METHOD     ma_meth = MODE_EMA;          // Smoothing Type 
input ENUM_APPLIED_PRICE  appl_p = PRICE_CLOSE;       // Type of price or handle 
//---
input group               "=== Select Pairs to Trade ===";  // Selected Pairs to trading
input MS                trademode = MP;              // Select Trading Pairs Mode (Multi or Single)
input PairsTrade         usepairs = All30;           // Select Pairs to Use
input string         traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma
//--
input group               "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter
input mmt                  mmlot = DynamLot;         // Money Management Type
input double                Risk = 10.0;             // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%)
input double                Lots = 0.01;             // Input Manual Lot Size FixedLot
//--Trade on Specific Time
input group               "=== Trade on Specific Time ==="; // Trade on Specific Time
input YN           trd_time_zone = Yes;              // Select If You Like to Trade on Specific Time Zone
input tm_zone            session = Cus_Session;      // Select Trading Time Zone
input swhour            stsescuh = hr_00;            // Time Hour to Start Trading Custom Session (0-23)
input inmnt             stsescum = mn_15;            // Time Minute to Start Trading Custom Session (0-55)
input swhour            clsescuh = hr_23;            // Time Hour to Stop Trading Custom Session (0-23)
input inmnt             clsescum = mn_55;            // Time Minute to Stop Trading Custom Session (0-55)
//--Day Trading On/Off
input group               "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN                    ttd0 = No;               // Select Trading on Sunday (Yes) or (No)
input YN                    ttd1 = Yes;              // Select Trading on Monday (Yes) or (No)
input YN                    ttd2 = Yes;              // Select Trading on Tuesday (Yes) or (No)
input YN                    ttd3 = Yes;              // Select Trading on Wednesday (Yes) or (No)
input YN                    ttd4 = Yes;              // Select Trading on Thursday (Yes) or (No)
input YN                    ttd5 = Yes;              // Select Trading on Friday (Yes) or (No)
input YN                    ttd6 = No;               // Select Trading on Saturday (Yes) or (No)
//--Trade & Order management Parameter
input group               "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
input YN                  use_sl = No;               // Use Order Stop Loss (Yes) or (No)
input YN                  autosl = Yes;              // Use Automatic Calculation Stop Loss (Yes) or (No)
input double               SLval = 30.0;             // If Not Use Automatic SL - Input SL value in Pips
input YN                  use_tp = Yes;              // Use Order Take Profit (Yes) or (No)
input YN                  autotp = No;               // Use Automatic Calculation Take Profit (Yes) or (No)
input double               TPval = 60.0;             // If Not Use Automatic TP - Input TP value in Pips
input YN            TrailingSLTP = Yes;              // Use Trailing SL/TP (Yes) or (No)
input TrType               trlby = byprice;           // Select Trailing Stop Type
input double               TSval = 25.0;             // If Use Trailing Stop by Price Input value in Pips
input double               TSmin = 5.0;              // Minimum Pips to start Trailing Stop
input double               TPmin = 25.0;             // Input Trailing Profit Value in Pips
input YN           Close_by_Opps = Yes;              // Close Trade By Opposite Signal (Yes) or (No)
input YN               SaveOnRev = Yes;              // Close Trade and Save profit due to weak signal (Yes) or (No)
//--Others Expert Advisor Parameter
input group               "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
input YN                  alerts = Yes;              // Display Alerts / Messages (Yes) or (No)
input YN           UseEmailAlert = No;               // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;               // Send Notification (Yes) or (No)
input YN      trade_info_display = Yes;              // Select Display Trading Info on Chart (Yes) or (No)
input ulong              magicEA = 20260204;         // Expert ID (Magic Number)
//---
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***

3. The Core Strategy: Triple-Layer Filtering

This MCEA (Multi-Currency Expert Advisor) is built on a foundation of trend-following and momentum acceleration. Operating primarily by default on the M30 timeframe, it filters out market noise while capturing significant intraday moves across up to 30 currency pairs simultaneously.

The EA operates optimally by default on the M30 timeframe , providing a perfect balance between trend reliability and signal frequency. It utilizes three legendary indicators with their time-tested default parameters

Why Default Parameters and M30?

We believe in universal logic. Default parameters are used because they are the benchmarks used by institutional algorithms. By staying on the M30 timeframe, the EA avoids the chaotic fluctuations of lower timeframes while avoiding the extreme lag found in H1 and above timeframes or Daily charts.

Technical Indicators & Parameters

  • ZigZag (Default: 12,5,3): Used to identify structural support and resistance (Highs and Lows).
    • ZigZag (Price Structure): Identifies the true support and resistance levels. The EA waits for a confirmed Lowest Line for Buys or a Highest Line for Sells.
  • EMA 50: Serving as the "Trend Filter." The EA only looks for Buy setups when the price is above the EMA and Sell setups when below.
    • EMA 50 (The Trend Guard): Acts as the ultimate safety filter. No trade is executed unless the price closes above the EMA (for Buys) or below the EMA (for Sells).
  • OsMA (12, 26, 9): The "Execution Trigger." By measuring the moving average of the oscillator, the EA identifies the exact moment momentum shifts in favor of the trend.
    • OsMA (Momentum Trigger): Unlike standard MACD, OsMA (Moving Average of Oscillator) captures the acceleration of momentum. We enter when the OsMA histogram shows a clear reversal (current Bar vs previous Bar), confirming the new trend has the fuel to move.

How it Works (The Signal Logic):

  • Trend: Price must close on the correct side of the EMA (default set: 50).
  • Structure: ZigZag must confirm a recent High or Low.
  • Momentum: The OsMA histogram must show a directional shift (Currenct Bar --with positive values-- > Previous Bar --with negative values-- for Buy, or Current Bar --with negative values-- < Previous Bar --with positive values-- for Sell).
  • Execution: Once all three align, the EA opens the trade with a unique Magic Number per pair to ensure precise tracking and management.

int MCEA::OsMASignal(const string symbol) // formula for OsMA signal
  {
//---
   int ret=0;
   int rise=1,
       down=-1;
    int bar=arper;
    //--
    int x=PairsIdxArray(symbol);
    //--
    double OsMABuffer[];
    //--
    ArrayResize(OsMABuffer,bar,bar);
    ArraySetAsSeries(OsMABuffer,true);
    //--
    CopyBuffer(hOsMA[x],0,0,bar,OsMABuffer);
    //--
    if(OsMABuffer[1]<=0.0 && OsMABuffer[0]>0.0) ret=rise;
    if(OsMABuffer[1]>=0.0 && OsMABuffer[0]<0.0) ret=down;
//--
   return(ret);
//---
  } //-end OsMASignal()
//---------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***
USDJPYM30_Open_Buy_Order Figure 2: Condition of indicators and price trend when EA opens BUY order
USDJPYM30_Open_Sell_Order Figure 3: Condition of indicators and price trend when EA opens SELL order

4. Inside the Engine: Professional Features

What sets this MCEA apart from standard bots is its sophisticated core logic, as seen in the source code:

  • 1. Intelligent Multi-Currency Handling: The EA features an automated Symbol Name Detection system. Whether your broker uses prefixes (e.g., "mEURUSD") or suffixes (e.g., "EURUSDpro"), the EA automatically parses the names to ensure seamless trading across all selected pairs.
  • 2. Dynamic Risk Management: Security is baked into the code. The EA calculates:
    • Dynamic Lot Sizing: Automatically adjusts position sizes based on your account equity and risk settings.
    • Margin Validation: Before any trade is executed, the CheckMargin() function ensures your account has sufficient breathing room, preventing over-leveraging.
    • Total Market Control: The dashboard provides real-time data on Nett Profit, Floating Money, and Total Orders across the entire portfolio.
  • 3. Advanced Multi-Currency Management: The backbone of this EA is our proprietary MCEA Engine. It doesn't just trade; it manages a whole portfolio. Key features include:
    • Intelligent Symbol Parsing: Automatically detects broker prefixes and suffixes (e.g., "mEURUSDpro") for seamless operation across different brokers.
    • Versatile Trading Options: Traders can choose from several pre-set groups: All 30 Major/Minor Pairs, Currency Specific Groups (USD, EUR, GBP, JPY, etc.), or the new Metal option for XAUUSD (Gold) and XAGUSD (Silver).
    • Trader Wishes: A custom input field where you can define exactly which pairs you want to trade by typing their names.
  • 4. Optimized for Metals and Forex: With the newly added Metal Option, users can now instantly switch the EA to focus exclusively on Gold (XAUUSD) and Silver (XAGUSD), or choose from specific currency groups like JPY pairs,USD pairs, or the full 30-pair major/minor set.

5. Exclusive Built-in Dashboard Panel

To make this MCEA more powerful and easy to use, I have integrated the built-in Dashboard Panel with dedicated "M", "C", and "R" buttons, under the name of expert advisor.

How it Works:

  • The "M" (Manual) Button: Displays a manual control panel to Set SL/TP for All Orders, Close All Orders, or Close All Profits instantly.
  • The "C" (Change) Button: Opens a symbol panel with your 30 selected pairs. Clicking any pair name will instantly switch the current chart to that symbol via the ChangeChartSymbol() function.
  • The "R" (Remove) Button: Safely detaches the ZigZag_OsMA_EMA_MCEA from the chart, stopping all automated processes.

Note: These interactive features are hard-coded directly into the MCEA class for maximum stability and responsiveness.

6. How to Use the ZigZag_OsMA_EMA_MCEA

  • Installation: Place the file in your MetaTrader Experts folder.
  • Chart Setup: Open any chart—M30 is highly recommended—and attach the EA.
  • Enable Auto Trading: Ensure the "Auto Trading" button is green. The EA will alert you if it's disabled.
  • Select Your Portfolio: Use the usepairs input to choose between Forex groups or the Metal option.

7. Conclusion

The ZigZag_OsMA_EMA_MCEA is not just an indicator; it is a complete trading business in a single file. By using time-tested default parameters and a robust multi-pair engine, it offers a diversified approach to the markets that is both safe and powerful.

⚠️ Important: Risk Disclaimer

  • Demo Testing: You are strongly advised to test this EA on an MT5 Demo Account first to witness how it manages 30 pairs simultaneously.
  • Real Account Trading: If you proceed to use this EA for automated trading on a Real Account, you do so at your own risk. Algorithmic trading involves substantial risk to your capital.
  • Always remember the rules: Never trade with money you cannot afford to lose.
  • Trading foreign exchange on margin carries a high level of risk and may not be suitable for all investors. The high degree of leverage can work against you as well as for you. Before deciding to invest in foreign exchange, you should carefully consider your investment objectives, level of experience, and risk appetite. This MCEA (Multi-Currency Expert Advisor) ZigZag_OsMA_EMA_MCEA logic provided in this article are for educational purposes and do not guarantee profits. Past performance is not indicative of future results.

Vital Records

We hope that this article and the ZigZag_OsMA_EMA_MCEA - MQL5 Multi-Currency Expert Advisor program will be useful for traders in learning and generating new ideas for forex trading.

The ZigZag_OsMA_EMA_MCEA represents the pinnacle of my development in MT5. By combining the structural stability of ZigZag, OsMA and EMA and the Advanced Trend Convergence Filter, we create an automated trading system that is it offers a diversified approach to the markets that is both safe and powerful.

This Expert Advisor is merely an idea for multi-currency trading automation and still requires further development.

See you in the next article on Expert Advisor programs or indicators for MetaTrader 4 and MetaTrader 5.

If you have any ideas for developing this EA program or have a new ideas, please leave your comments below this article.

Thanks for reading this article.

Note: Please see the source program and download at the bottom of this article.

Risk Warning: Trading Forex and CFDs involves significant risk and may not be suitable for all investors. All content provided is for educational purposes only.


//+------------------------------------------------------------------+
//|                                         ZigZag_OsMA_EMA_MCEA.mq5 |
//|        Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-02-04 |
//|                              https://www.mql5.com/en/users/3rjfx |
//+------------------------------------------------------------------+
#property copyright "Copyright 2026, Roberto Jacobs (3rjfx) ~ Date: 2026-02-04"
#property link      "https://www.mql5.com/en/users/3rjfx"
#property version   "1.00"
#property strict
#property description "The Expert ZigZag_OsMA_EMA_MCEA is the Automated Trading Multi Currency Forex Expert Advisor"
#property description "for Meta Trader 5 by using ZigZag, OsMA and MA which trade Multiple Pairs in one Chart."
#property description "version: 1.00 ~ Update number: 1 ~ Last update: 2026/02/04 @22:55 (PM) WIT (Western Indonesian Time)"
//#property icon "\\Images\\ZigZag_OsMA_EMA_MCEA.ico";
//+------------------------------------------------------------------+
//|                             Include                              |
//+------------------------------------------------------------------+
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\SymbolInfo.mqh>
#include <Trade\AccountInfo.mqh>
//--
CTrade              mc_trade;
CSymbolInfo         mc_symbol;
CPositionInfo       mc_position; 
CAccountInfo        mc_account;
//---
//--
enum tm_zone
 {
   Cus_Session,        // Trading on Custom Session
   New_Zealand,        // Trading on New Zealand Session
   Australia,          // Trading on Autralia Sydney Session
   Asia_Tokyo,         // Trading on Asia Tokyo Session
   Europe_London,      // Trading on Europe London Session
   US_New_York         // Trading on US New York Session
 };
//--
enum swhour
  {
    hr_00=0,   // 00:00
    hr_01=1,   // 01:00
    hr_02=2,   // 02:00
    hr_03=3,   // 03:00
    hr_04=4,   // 04:00
    hr_05=5,   // 05:00
    hr_06=6,   // 06:00
    hr_07=7,   // 07:00
    hr_08=8,   // 08:00
    hr_09=9,   // 09:00
    hr_10=10,  // 10:00
    hr_11=11,  // 11:00
    hr_12=12,  // 12:00
    hr_13=13,  // 13:00
    hr_14=14,  // 14:00
    hr_15=15,  // 15:00
    hr_16=16,  // 16:00
    hr_17=17,  // 17:00
    hr_18=18,  // 18:00
    hr_19=19,  // 19:00
    hr_20=20,  // 20:00
    hr_21=21,  // 21:00
    hr_22=22,  // 22:00
    hr_23=23   // 23:00
  };
//--
enum inmnt
  {
    mn_00=0,   // Minute 0
    mn_05=5,   // Minute 5
    mn_10=10,  // Minute 10
    mn_15=15,  // Minute 15
    mn_20=20,  // Minute 20
    mn_25=25,  // Minute 25
    mn_30=30,  // Minute 30
    mn_35=35,  // Minute 35
    mn_40=40,  // Minute 40
    mn_45=45,  // Minute 45
    mn_50=50,  // Minute 50
    mn_55=55   // Minute 55
  };
//--
enum PairsTrade
 {
   All30,  // All Forex 30 Pairs
   TrdWi,  // Trader Wishes Pairs 
   Usds,   // Forex USD Pairs
   Eurs,   // Forex EUR Pairs
   Gbps,   // Forex GBP Pairs
   Auds,   // Forex AUD Pairs
   Nzds,   // Forex NZD Pairs
   Cads,   // Forex CDD Pairs
   Chfs,   // Forex CHF Pairs
   Jpys,   // Forex JPY Pairs
   Metal   // Metal Pairs
 };   
//--
enum YN
  {
   No,
   Yes
  };
//--
enum mmt
  {
   FixedLot,   // Fixed Lot Size
   DynamLot    // Dynamic Lot Size
  };
//--
enum TFUSE // There are 10 Timeframe options available
  {
   TFM15,    // PERIOD_M15
   TFM30,    // PERIOD_M30
   TFH1,     // PERIOD_H1
   TFH2,     // PERIOD_H2
   TFH3,     // PERIOD_H3
   TFH4,     // PERIOD_H4
   TFH6,     // PERIOD_H6
   TFH8,     // PERIOD_H8
   TFH12,    // PERIOD_H12
   TFD1      // PERIOD_D1
  };
//--
enum TrType
  {
    byprice, // Trailing Stop by Price
    byindi   // Trailing Stop by Indicator
  };
//--
enum MS
 {
   SP, // Single Pair
   MP  // Multi Pairs
 };
//--
//---
input group               "=== Global Strategy EA Parameter ==="; // Global Strategy EA Parameter
input TFUSE             Timeframe = TFM30;             // Select Expert TimeFrame, default TFM30
//---
input group               "=== ZigZag Indicator Input Properties ===";  // ZigZag Indicator Input Properties
input int                 zzDepth = 12;               // Input ZigZag Depth, default 12
input int                 zzDevia = 5;                // Input ZigZag Deviation, default 5
input int                 zzBackS = 3;                // Input ZigZag Back Step, default 3
//---
input group               "=== OsMA Indicator Input Properties ===";  // OsMA Indicator Input Properties
input int                  f_ema = 12;                // Period of Fast MA 
input int                  s_ema = 26;                // Period of Slow MA
input int                  sig_p = 9;                 // Period of Averaging of Difference 
input ENUM_APPLIED_PRICE   app_p = PRICE_CLOSE;       // type of Applied Price    
//---
input group               "=== EMA Indicator Input Properties ===";  // EMA Indicator Input Properties
input int              ma_period = 50;                // Averaging Period 
input int               ma_shift = 0;                 // Horizontal MA shift 
input ENUM_MA_METHOD     ma_meth = MODE_EMA;          // Smoothing Type 
input ENUM_APPLIED_PRICE  appl_p = PRICE_CLOSE;       // Type of price or handle 
//---
input group               "=== Select Pairs to Trade ===";  // Selected Pairs to trading
input MS                trademode = MP;              // Select Trading Pairs Mode (Multi or Single)
input PairsTrade         usepairs = All30;           // Select Pairs to Use
input string         traderwishes = "eg. eurusd,usdchf"; // If Use Trader Wishes Pairs, input pair name here, separate by comma
//--
input group               "=== Money Management Lot Size Parameter ==="; // Money Management Lot Size Parameter
input mmt                  mmlot = DynamLot;         // Money Management Type
input double                Risk = 10.0;             // Percent Equity Risk per Trade (Min=1.0% / Max=10.0%)
input double                Lots = 0.01;             // Input Manual Lot Size FixedLot
//--Trade on Specific Time
input group               "=== Trade on Specific Time ==="; // Trade on Specific Time
input YN           trd_time_zone = Yes;              // Select If You Like to Trade on Specific Time Zone
input tm_zone            session = Cus_Session;      // Select Trading Time Zone
input swhour            stsescuh = hr_00;            // Time Hour to Start Trading Custom Session (0-23)
input inmnt             stsescum = mn_15;            // Time Minute to Start Trading Custom Session (0-55)
input swhour            clsescuh = hr_23;            // Time Hour to Stop Trading Custom Session (0-23)
input inmnt             clsescum = mn_55;            // Time Minute to Stop Trading Custom Session (0-55)
//--Day Trading On/Off
input group               "=== Day Trading On/Off ==="; // Day Trading On/Off
input YN                    ttd0 = No;               // Select Trading on Sunday (Yes) or (No)
input YN                    ttd1 = Yes;              // Select Trading on Monday (Yes) or (No)
input YN                    ttd2 = Yes;              // Select Trading on Tuesday (Yes) or (No)
input YN                    ttd3 = Yes;              // Select Trading on Wednesday (Yes) or (No)
input YN                    ttd4 = Yes;              // Select Trading on Thursday (Yes) or (No)
input YN                    ttd5 = Yes;              // Select Trading on Friday (Yes) or (No)
input YN                    ttd6 = No;               // Select Trading on Saturday (Yes) or (No)
//--Trade & Order management Parameter
input group               "=== Trade & Order management Parameter ==="; // Trade & Order management Parameter
input YN                  use_sl = No;               // Use Order Stop Loss (Yes) or (No)
input YN                  autosl = Yes;              // Use Automatic Calculation Stop Loss (Yes) or (No)
input double               SLval = 30.0;             // If Not Use Automatic SL - Input SL value in Pips
input YN                  use_tp = Yes;              // Use Order Take Profit (Yes) or (No)
input YN                  autotp = No;               // Use Automatic Calculation Take Profit (Yes) or (No)
input double               TPval = 60.0;             // If Not Use Automatic TP - Input TP value in Pips
input YN            TrailingSLTP = Yes;              // Use Trailing SL/TP (Yes) or (No)
input TrType               trlby = byprice;           // Select Trailing Stop Type
input double               TSval = 25.0;             // If Use Trailing Stop by Price Input value in Pips
input double               TSmin = 5.0;              // Minimum Pips to start Trailing Stop
input double               TPmin = 25.0;             // Input Trailing Profit Value in Pips
input YN           Close_by_Opps = Yes;              // Close Trade By Opposite Signal (Yes) or (No)
input YN               SaveOnRev = Yes;              // Close Trade and Save profit due to weak signal (Yes) or (No)
//--Others Expert Advisor Parameter
input group               "=== Others Expert Advisor Parameter ==="; // Others EA Parameter
input YN                  alerts = Yes;              // Display Alerts / Messages (Yes) or (No)
input YN           UseEmailAlert = No;               // Email Alert (Yes) or (No)
input YN           UseSendnotify = No;               // Send Notification (Yes) or (No)
input YN      trade_info_display = Yes;              // Select Display Trading Info on Chart (Yes) or (No)
input ulong              magicEA = 20260204;         // Expert ID (Magic Number)
//---
//---------//
//+------------------------------------------------------------------+
//| Class for working Expert Advisor                                 |
//+------------------------------------------------------------------+
class MCEA
  {
//---
    private:
    //---- 
    int              x_year;       // Year 
    int              x_mon;        // Month 
    int              x_day;        // Day of the month 
    int              x_hour;       // Hour in a day 
    int              x_min;        // Minutes 
    int              x_sec;        // Seconds
    //--
    int              oBm,
                     oSm,
                     ldig;
    //--- Variables used in prefix and suffix symbols
    int              posCur1,
                     posCur2;
    int              inpre,
                     insuf;
    bool             symbfix;
    string           pre,suf;
    string           prefix,suffix;       
    //--- Variables are used in Trading Time Zone
    int              ishour,
                     onhour;
    int              tftrlst,
                     tfcinws;
    datetime         rem,
                     znop,
                     zncl,
                     zntm;
    datetime         SesCuOp,
                     SesCuCl,
                     Ses01Op,
                     Ses01Cl,
                     Ses02Op,
                     Ses02Cl,
                     Ses03Op,
                     Ses03Cl,
                     Ses04Op,
                     Ses04Cl,
                     Ses05Op,
                     Ses05Cl,
                     SesNoOp,
                     SesNoCl;
    //--
    string           tz_ses,
                     tz_opn,
                     tz_cls;
    //--
    string           tmopcu,
                     tmclcu,
                     tmop01,
                     tmcl01,
                     tmop02,
                     tmcl02,
                     tmop03,
                     tmcl03,
                     tmop04,
                     tmcl04,
                     tmop05,
                     tmcl05,
                     tmopno,
                     tmclno;      
    //----------------------
    //--
    double           LotPS;
    double           point;
    double           slv,
                     tpv,
                     pip,
                     xpip;
    double           floatprofit,
                     fixclprofit;
    //--
    string           pairs,
                     hariini,
                     daytrade,
                     trade_mode;
    //--
    double           OPEN[],
                     HIGH[],
                     LOW[],
                     CLOSE[];
    datetime         TIME[];
    datetime         closetime;
    //--
    //------------
     
    //------------
    void             SetSymbolNamePS(void);
    void             HandlingSymbolArrays(void);
    void             Set_Time_Zone(void);
    void             Time_Zone(void);
    bool             Trade_session(void);
    string           PosTimeZone(void);
    int              ThisTime(const int reqmode);
    int              ReqTime(datetime reqtime,const int reqmode);
    //--
    int              DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf);
    int              ZigZagSignal(const string symbol);
    int              OsMASignal(const string symbol);
    int              EMASignal(const string symbol);
    int              LotDig(const string symbol);
    //--
    bool             CheckProfit(const string symbol,ENUM_POSITION_TYPE intype);
    bool             CheckLoss(const string symbol,ENUM_POSITION_TYPE intype);
    //--
    double           MLots(const string symbx);
    double           NonZeroDiv(double val1,double val2);
    double           OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
    double           OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice);
    double           SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
    double           SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice);
    double           TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type);
    double           WPRPlus(const string symbol,const ENUM_TIMEFRAMES stf);
    //--
    string           ReqDate(int d,int h,int m);
    string           TF2Str(ENUM_TIMEFRAMES period);
    string           timehr(int hr,int mn);
    string           TradingDay(void);
    string           AccountMode();
    string           GetCommentForOrder(void)             { return(expname); }
    //------------

    public:
    //---
    
    //-- ZigZag_OsMA_EMA_MCEA Config --
    string           DIRI[],
                     AS30[],
                     VSym[];
    string           SPC[];    
    //--                 
    string           expname;
    string           indiname;
    //--
    int              hZigZag[],
                     hOsMA[],
                     hEMA[];
    int              hVIDyAv[];
    int              ALO,
                     dgts,
                     arrsar,
                     arrsymbx;
    int              sall,
                     arusd,
                     areur,
                     aretc,
                     arspc,
                     armet,
                     arper;
    ulong            slip;        
    //--
    double           profitb[],
                     profits[];
    double           minprofit;
    //--
    int              Buy,
                     Sell;
    int              ccur,
                     psec,
                     xtto,
                     checktml;
    int              OpOr[],xob[],xos[];         
    //--
    int              year,  // Year 
                     mon,   // Month 
                     day,   // Day 
                     hour,  // Hour 
                     min,   // Minutes 
                     sec,   // Seconds 
                     dow,   // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
                     doy;   // Day number of the year (January 1st is assigned the number value of zero)
    //--
    ENUM_TIMEFRAMES  TFt;
    datetime         PbarB[],
                     TbarB[],
                     PbarS[],
                     TbarS[];
    //--
    bool             PanelExtra;
    //------------
                     MCEA(void);
                     ~MCEA(void);            
    //------------
    //--
    virtual void     ZigZag_OsMA_EMA_MCEA_Config(void);
    virtual void     ExpertActionTrade(void);
    //--
    void             ArraySymbolResize(void);
    void             CurrentSymbolSet(const string symbol);
    void             Pips(const string symbol);
    void             TradeInfo(void);
    void             Do_Alerts(const string symbx,string msgText);
    void             CheckOpenPMx(const string symbx);
    void             SetSLTPOrders(void);
    void             CloseAllOrders(void);
    void             CheckClose(const string symbx);
    void             TodayOrders(void);
    void             UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf);
    void             RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars);
    //--
    bool             RefreshTick(const string symbx);  
    bool             TradingToday(void);
    bool             OpenBuy(const string symbol);
    bool             OpenSell(const string symbol);
    bool             ModifyOrderSLTP(double mStop,double ordtp);
    bool             ModifySLTP(const string symbx,int TS_type);          
    bool             CloseAllProfit(void);
    bool             ManualCloseAllProfit(void);
    bool             CheckProfitLoss(const string symbol);
    bool             CloseBuyPositions(const string symbol);
    bool             CloseSellPositions(const string symbol);
    bool             IFNewBarsB(const string symbol);
    bool             IFNewBarsS(const string symbol);
    //--
    int              PairsIdxArray(const string symbol);
    int              ValidatePairs(const string symbol);
    int              GetOpenPosition(const string symbol);
    int              GetCloseInWeakSignal(const string symbol,int exis);
    //--
    string           getUninitReasonText(int reasonCode);
    //--
    //------------
//---
  }; //-end class MCEA
//---------//
 
MCEA mc;

//---------//

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
MCEA::MCEA(void): x_year(0),
                  x_mon(0),
                  x_day(0),
                  x_hour(0),
                  x_min(0),
                  x_sec(0),
                  year(0),
                  mon(1),
                  day(2),
                  hour(3),
                  min(4),
                  sec(5),
                  dow(6),
                  doy(7),
                  psec(0),
                  Buy(1),
                  Sell(-1),
                  slip(16),
                  arper(25),
                  checktml(0),
                  expname("ZigZag_OsMA_EMA_MCEA"),
                  indiname("\\Indicators\\Examples\\ZigZag.ex5"),
                  closetime(TimeCurrent())
  {
  }
//---------//

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
MCEA::~MCEA(void)
  {
  }
//---------//

//+------------------------------------------------------------------+
//| Expert Configuration                                             |
//+------------------------------------------------------------------+
void MCEA::ZigZag_OsMA_EMA_MCEA_Config(void) 
  {
//---
    //--
    HandlingSymbolArrays(); // With this function we will handle all pairs that will be traded
    //--
    ENUM_TIMEFRAMES TFs[]={PERIOD_M15,PERIOD_M30,PERIOD_H1,PERIOD_H2,PERIOD_H3,PERIOD_H4,PERIOD_H6,PERIOD_H8,PERIOD_H12,PERIOD_D1};
    int arTFs=ArraySize(TFs);
    //--
    for(int x=0; x<arTFs; x++) if(Timeframe==x) TFt=TFs[x]; // TF for calculation signal
    //-- Indicators handle for all symbol
    for(int x=0; x<arrsymbx; x++) 
      {
        hZigZag[x] = iCustom(DIRI[x],TFt,indiname,zzDepth,zzDevia,zzBackS);  //-- Handle for the ZigZag in condition indicator
        hOsMA[x]   = iOsMA(DIRI[x],TFt,f_ema,s_ema,sig_p,app_p);             //-- Handle for the OsMA indicator in condition Timeframe
        hEMA[x]    = iMA(DIRI[x],TFt,ma_period,ma_shift,ma_meth,appl_p);     //-- Handle for the EMA indicator in condition Timeframe
        hVIDyAv[x] = iVIDyA(DIRI[x],TFt,9,12,0,PRICE_WEIGHTED);              //-- Handle for the VIDYA indicator for Trailing Stop
        //--
      }
    //--
    TesterHideIndicators(true);
    minprofit=NormalizeDouble(TSmin/100.0,2);
    //--
    ALO=(int)mc_account.LimitOrders()>sall ? sall : (int)mc_account.LimitOrders();
    if(Close_by_Opps==No) 
      {
        if((int)mc_account.LimitOrders()>=(sall*2)) ALO=sall*2;
        else 
        ALO=(int)(mc_account.LimitOrders()/2);
      }
    //--
    LotPS=(double)ALO;
    //--
    mc_trade.SetExpertMagicNumber(magicEA);
    mc_trade.SetDeviationInPoints(slip);
    mc_trade.SetMarginMode();
    Set_Time_Zone();
    //--
    return;
//---
  } //-end Heiken_Ashi_MCEA_Config()
//---------//

void MCEA::HandlingSymbolArrays(void)
  {
//---
    string All30[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY","EURGBP",
                    "EURAUD","EURNZD","EURCAD","EURCHF","EURJPY","GBPAUD","GBPNZD","GBPCAD",
                    "GBPCHF","GBPJPY","AUDNZD","AUDCAD","AUDCHF","AUDJPY","NZDCAD","NZDCHF",
                    "NZDJPY","CADCHF","CADJPY","CHFJPY","XAUUSD","XAGUSD"}; // 30 pairs
    string USDs[]={"USDCAD","USDCHF","USDJPY","AUDUSD","EURUSD","GBPUSD","NZDUSD","XAUUSD","XAGUSD"}; // USD pairs
    string EURs[]={"EURAUD","EURCAD","EURCHF","EURGBP","EURJPY","EURNZD","EURUSD"}; // EUR pairs
    string GBPs[]={"GBPAUD","GBPCAD","GBPCHF","EURGBP","GBPJPY","GBPNZD","GBPUSD"}; // GBP pairs
    string AUDs[]={"AUDCAD","AUDCHF","EURAUD","GBPAUD","AUDJPY","AUDNZD","AUDUSD"}; // AUD pairs
    string NZDs[]={"AUDNZD","NZDCAD","NZDCHF","EURNZD","GBPNZD","NZDJPY","NZDUSD"}; // NZD pairs
    string CADs[]={"AUDCAD","CADCHF","EURCAD","GBPCAD","CADJPY","NZDCAD","USDCAD"}; // CAD pairs
    string CHFs[]={"AUDCHF","CADCHF","EURCHF","GBPCHF","NZDCHF","CHFJPY","USDCHF"}; // CHF pairs
    string JPYs[]={"AUDJPY","CADJPY","CHFJPY","EURJPY","GBPJPY","NZDJPY","USDJPY"}; // JPY pairs
    string MTLs[]={"XAUUSD","XAGUSD"}; // METAL pairs
    //--
    sall=ArraySize(All30);
    arusd=ArraySize(USDs);
    areur=ArraySize(EURs);
    aretc=ArraySize(JPYs);
    armet=ArraySize(MTLs);
    ArrayResize(VSym,sall,sall);
    ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
    //--
    if(usepairs==TrdWi && StringFind(traderwishes,"eg.",0)<0)
      {
        string to_split=traderwishes; // A string to split into substrings pairs name
        string sep=",";               // A separator as a character 
        ushort u_sep;                 // The code of the separator character 
        //--- Get the separator code 
        u_sep=StringGetCharacter(sep,0);
        //--- Split the string to substrings 
        int p=StringSplit(to_split,u_sep,SPC); 
        if(p>0)
          {
            for(int i=0; i<p; i++) StringToUpper(SPC[i]);
            //--
            for(int i=0; i<p; i++)
              {
                if(ValidatePairs(SPC[i])<0) ArrayRemove(SPC,i,1);
              }
          }
        arspc=ArraySize(SPC);
      }
    //--
    SetSymbolNamePS();      // With this function we will detect whether the Symbol Name has a prefix and/or suffix
    //--
    if(inpre>0 || insuf>0)
      {
        if(usepairs==TrdWi && arspc>0)
          {
            for(int t=0; t<arspc; t++)
              {
                SPC[t]=pre+SPC[t]+suf;
              }
          }
        //--
        for(int t=0; t<sall; t++)
          {
            All30[t]=pre+All30[t]+suf;
          }
        for(int t=0; t<arusd; t++)
          {
            USDs[t]=pre+USDs[t]+suf;
          }
        for(int t=0; t<areur; t++)
          {
            EURs[t]=pre+EURs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            GBPs[t]=pre+GBPs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            AUDs[t]=pre+AUDs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            NZDs[t]=pre+NZDs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            CADs[t]=pre+CADs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            CHFs[t]=pre+CHFs[t]+suf;
          }
        for(int t=0; t<aretc; t++)
          {
            JPYs[t]=pre+JPYs[t]+suf;
          }
      }
    //--
    ArrayCopy(VSym,All30,0,0,WHOLE_ARRAY);
    ArrayResize(AS30,sall,sall);
    ArrayCopy(AS30,All30,0,0,WHOLE_ARRAY);
    for(int x=0; x<sall; x++) {SymbolSelect(AS30[x],true);}
    if(ValidatePairs(Symbol())>=0) symbfix=true;
    if(!symbfix) 
      {
        Alert("Expert Advisors will not trade on pairs "+Symbol());
        Alert("-- "+expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
        ExpertRemove();
      }
    //--
    switch(usepairs)
      {
        case 0: // All Forex & Metal 30 Pairs
          {
            ArrayResize(DIRI,sall,sall);
            arrsymbx=sall;
            ArraySymbolResize();
            ArrayCopy(DIRI,All30,0,0,WHOLE_ARRAY);
            pairs="Multi Currency "+string(sall)+" Pairs";
            //--
            break;
          }
        case 1: // Trader wishes pairs
          {
            ArrayResize(DIRI,arspc,arspc);
            arrsymbx=arspc;
            ArraySymbolResize();
            ArrayCopy(DIRI,SPC,0,0,WHOLE_ARRAY);
            pairs="("+string(arspc)+") Trader Wishes Pairs";
            //--
            break;
          }
        case 2: // USD pairs
          {
            ArrayResize(DIRI,arusd,arusd);
            arrsymbx=arusd;
            ArraySymbolResize();
            ArrayCopy(DIRI,USDs,0,0,WHOLE_ARRAY);
            pairs="("+string(arusd)+") Multi Currency USD Pairs";
            //--
            break;
          }
        case 3: // EUR pairs
          {
            ArrayResize(DIRI,areur,areur);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,EURs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex EUR Pairs";
            //--
            break;
          }
        case 4: // GBP pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,GBPs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex GBP Pairs";
            //--
            break;
          }
        case 5: // AUD pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,AUDs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex AUD Pairs";
            //--
            break;
          }
        case 6: // NZD pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,NZDs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex NZD Pairs";
            //--
            break;
          }
        case 7: // CAD pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,CADs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex CAD Pairs";
            //--
            break;
          }
        case 8: // CHF pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,CHFs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex CHF Pairs";
            //--
            break;
          }
        case 9: // JPY pairs
          {
            ArrayResize(DIRI,aretc,aretc);
            arrsymbx=aretc;
            ArraySymbolResize();
            ArrayCopy(DIRI,JPYs,0,0,WHOLE_ARRAY);
            pairs="("+string(aretc)+") Forex JPY Pairs";
            //--
            break;
          }
        case 10: // Metal pairs
          {
            ArrayResize(DIRI,armet,armet);
            arrsymbx=armet;
            ArraySymbolResize();
            ArrayCopy(DIRI,MTLs,0,0,WHOLE_ARRAY);
            pairs="("+string(armet)+") Metal Pairs";
            //--
            break;
          }
      }
    //--
    return;
//---
  } //-end HandlingSymbolArrays()
//---------//

void MCEA::SetSymbolNamePS(void)
  {
//---
   int sym_Lenpre=0;
   int sym_Lensuf=0;
   string sym_pre="";
   string sym_suf="";
   SymbolSelect(Symbol(),true);
   string insymbol=Symbol();
   int inlen=StringLen(insymbol);
   int toseek=-1;
   string dep="";
   string bel="";
   string sym_use ="";
   int pairx=-1;
   string xcur[]={"EUR","GBP","AUD","NZD","USD","CAD","CHF"}; // 7 major currency
   int xcar=ArraySize(xcur);
   //--
   for(int x=0; x<xcar; x++)
     {
       toseek=StringFind(insymbol,xcur[x],0);
       if(toseek>=0)
         {
           pairx=x;
           break;
         }
     }
   if(pairx>=0)
     {
       int awl=toseek-3 <0 ? 0 : toseek-3;
       int sd=StringFind(insymbol,"SD",0);
       if(toseek==0 && sd<4)
         {
           dep=StringSubstr(insymbol,toseek,3);
           bel=StringSubstr(insymbol,toseek+3,3);
           sym_use=dep+bel;
         }
       else
       if(toseek>0)
         {
           dep=StringSubstr(insymbol,toseek,3);
           bel=StringSubstr(insymbol,toseek+3,3);
           sym_use=dep+bel;
         }
       else
         {
           dep=StringSubstr(insymbol,awl,3);
           bel=StringSubstr(insymbol,awl+3,3);
           sym_use=dep+bel;
         }
     }
   //--
   string sym_nmx=sym_use;
   int lensx=StringLen(sym_nmx);
   //--
   if(inlen>lensx && lensx==6)
     {
       sym_Lenpre=StringFind(insymbol,sym_nmx,0);
       sym_Lensuf=inlen-lensx-sym_Lenpre;
       //--
       if(sym_Lenpre>0)
         {
           sym_pre=StringSubstr(insymbol,0,sym_Lenpre);
           for(int i=0; i<xcar; i++)
             if(StringFind(sym_pre,xcur[i],0)>=0) sym_pre="";
         }
       if(sym_Lensuf>0)
         {
           sym_suf=StringSubstr(insymbol,sym_Lenpre+lensx,sym_Lensuf);
           for(int i=0; i<xcar; i++)
             if(StringFind(sym_suf,xcur[i],0)>=0) sym_suf="";
         }
     }
   //--
   pre=sym_pre;
   suf=sym_suf;
   inpre=StringLen(pre);
   insuf=StringLen(suf);
   posCur1=inpre;
   posCur2=posCur1+3;
   //--
   return;
//---
  } //-end SetSymbolNamePS()
//---------//

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit(void)
  {
//---
   mc.ZigZag_OsMA_EMA_MCEA_Config();
   //--
   return(INIT_SUCCEEDED);
//---
  } //-end OnInit()
//---------//
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   Comment("");
   //-- Release all handle indicators for all symbols
   for(int x=0; x<mc.arrsymbx; x++) 
     {
       IndicatorRelease(mc.hZigZag[x]);
       IndicatorRelease(mc.hOsMA[x]);
       IndicatorRelease(mc.hVIDyAv[x]);
     }
   //--
   PrintFormat("%s: Deinitialization reason code=%d",__FUNCTION__,reason);
   Print(mc.getUninitReasonText(reason));
   ObjectsDeleteAll(0,0,OBJ_BUTTON);
   ObjectsDeleteAll(0,0,OBJ_LABEL);
   ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
   //--
   return;
//---
  } //-end OnDeinit()
//---------//
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick(void)
  {
//---
    mc.ExpertActionTrade();
    //--
    return;
//---
  } //-end OnTick()
//---------//
//+------------------------------------------------------------------+

void MCEA::ExpertActionTrade(void)
  {
//---
    //--Check Trading Terminal
    ResetLastError();
    //--
    if(!MQLInfoInteger(MQL_TRADE_ALLOWED) && mc.checktml==0) //-- Check whether MT5 Algorithmic trading is Allow or Prohibit
      {
        mc.Do_Alerts(Symbol(),"Trading Expert at "+Symbol()+" are NOT Allowed by Setting.");
        mc.checktml=1;  //-- Variable checktml is given a value of 1, so that the alert is only done once.
        return;
      }
    //--
    if(!DisplayManualButton("M","C","R")) DisplayManualButton(); //-- Show the expert manual button panel
    //--
    if(trade_info_display==Yes) mc.TradeInfo(); //-- Displayed Trading Info on Chart
    //---
    //--
    int mcsec=mc.ThisTime(mc.sec); 
    //--
    if(fmod((double)mcsec,5.0)==0) mc.ccur=mcsec;
    //--
    if(mc.ccur!=mc.psec)
      {
        string symbol;
        //-- Here we start with the rotation of the name of all symbol or pairs to be traded
        for(int x=0; x<mc.arrsymbx && !IsStopped(); x++) 
          {
            //--
            switch(trademode)
              {
                case SP:
                  {
                    if(mc.DIRI[x]!=Symbol()) continue;
                    symbol=Symbol();
                    mc.pairs=mc.pairs+" ("+symbol+")";
                    break;
                  }
                case MP:
                  {
                    if(mc.DIRI[x]==Symbol()) symbol=Symbol();
                    else symbol=mc.DIRI[x];
                    break;
                  }
              }
            //--
            mc.CurrentSymbolSet(symbol);
            //--
            if(mc.TradingToday() && mc.Trade_session())
              {
                //--
                mc.OpOr[x]=mc.GetOpenPosition(symbol); //-- Get trading signals to open positions
                //--                                   //-- and store in the variable OpOr[x]
                if(mc.OpOr[x]==mc.Buy) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Buy" (value=1)
                  {
                    //--
                    mc.CheckOpenPMx(symbol);
                    //--
                    if(Close_by_Opps==Yes && mc.xos[x]>0) mc.CloseSellPositions(symbol);
                    //--
                    if(mc.xob[x]==0 && mc.xtto<mc.ALO && mc.IFNewBarsB(symbol)) mc.OpenBuy(symbol);
                    else
                    if(mc.xtto>=mc.ALO)
                      {
                        //--
                        mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
                                            "\n the limit = "+string(mc.ALO)+" Orders ");
                        //--
                        mc.CheckOpenPMx(symbol);
                        //--
                        if(mc.xos[x]>0 && mc.profits[x]<-1.02 && mc.xob[x]==0) {mc.CloseSellPositions(symbol); mc.OpenBuy(symbol);}
                        else
                        if(SaveOnRev==Yes)
                          mc.CloseAllProfit();
                      }
                  }
                if(mc.OpOr[x]==mc.Sell) //-- If variable OpOr[x] get result of GetOpenPosition(symbol) as "Sell" (value=-1)
                  {
                    //--
                    mc.CheckOpenPMx(symbol);
                    //--
                    if(Close_by_Opps==Yes && mc.xob[x]>0) mc.CloseBuyPositions(symbol);
                    //--
                    if(mc.xos[x]==0 && mc.xtto<mc.ALO && mc.IFNewBarsS(symbol)) mc.OpenSell(symbol);
                    else
                    if(mc.xtto>=mc.ALO)
                      {
                        //--
                        mc.Do_Alerts(symbol,"Maximum amount of open positions and active pending orders has reached"+
                                            "\n the limit = "+string(mc.ALO)+" Orders ");
                        //--
                        mc.CheckOpenPMx(symbol);
                        //--
                        if(mc.xob[x]>0 && mc.profitb[x]<-1.02 && mc.xos[x]==0) {mc.CloseBuyPositions(symbol); mc.OpenSell(symbol);}
                        else
                        if(SaveOnRev==Yes) 
                          mc.CloseAllProfit();
                      }
                  }
              }
            //--
            mc.CheckOpenPMx(symbol);
            //--
            if(mc.xtto>0)
              {
                //--
                if(SaveOnRev==Yes) //-- Close Trade and Save profit due to weak signal (Yes)
                  {
                    mc.CheckOpenPMx(symbol);
                    if(mc.profitb[x]>mc.minprofit && mc.xob[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Buy)==mc.Sell) 
                      {
                        mc.CloseBuyPositions(symbol); 
                        mc.Do_Alerts(symbol,"Close BUY order "+symbol+" to save profit due to weak signal.");
                      }
                    if(mc.profits[x]>mc.minprofit && mc.xos[x]>0 && mc.GetCloseInWeakSignal(symbol,mc.Sell)==mc.Buy)
                      {
                        mc.CloseSellPositions(symbol); 
                        mc.Do_Alerts(symbol,"Close SELL order "+symbol+" to save profit due to weak signal.");
                      }
                  }
                //--
                if(TrailingSLTP==Yes) //-- Use Trailing SL/TP (Yes)
                  {
                    mc.ModifySLTP(symbol,trlby);
                  }
              }
            //--
            mc.CheckOpenPMx(symbol);
            if(Close_by_Opps==No && (mc.xob[x]+mc.xos[x]>1))
              {
                mc.CheckProfitLoss(symbol);
                mc.Do_Alerts(symbol,"Close order due stop in loss.");
              }
            //--
            mc.CheckClose(symbol);
          }
        //--
        mc.psec=mc.ccur;
      }
    //--
    return;
//---
  } //-end ExpertActionTrade()
//---------//

int MCEA::PairsIdxArray(const string symbol)
  {
//---
    int pidx=-1;
    //--
    for(int x=0; x<arrsymbx; x++)
      {
        if(DIRI[x]==symbol)
          {
            pidx=x;
            break;
          }
      } 
    //--
    return(pidx);
//---
  } //-end PairsIdxArray()
//---------//

int MCEA::ValidatePairs(const string symbol)
  {
//---
    int pidx=-1;
    //--
    for(int x=0; x<sall; x++)
      {
        if(VSym[x]==symbol)
          {
            pidx=x;
            break;
          }
      } 
    //--
    return(pidx);
//---
  } //-end ValidatePairs()
//---------//

void MCEA::ArraySymbolResize(void)
  {
//---
    ArrayFree(DIRI);
    ArrayFree(xob);
    ArrayFree(xos);
    ArrayFree(OpOr);
    ArrayFree(profitb);
    ArrayFree(profits);
    ArrayFree(hZigZag);
    ArrayFree(hOsMA);
    ArrayFree(hEMA);
    ArrayFree(hVIDyAv);
    ArrayFree(PbarB);
    ArrayFree(TbarB);
    ArrayFree(PbarS);
    ArrayFree(TbarS);
    //--
    ArrayResize(DIRI,arrsymbx,arrsymbx);
    ArrayResize(xob,arrsymbx,arrsymbx);
    ArrayResize(xos,arrsymbx,arrsymbx);
    ArrayResize(OpOr,arrsymbx,arrsymbx);
    ArrayResize(profitb,arrsymbx,arrsymbx);
    ArrayResize(profits,arrsymbx,arrsymbx);
    ArrayResize(hZigZag,arrsymbx,arrsymbx);
    ArrayResize(hOsMA,arrsymbx,arrsymbx);
    ArrayResize(hEMA,arrsymbx,arrsymbx);
    ArrayResize(hVIDyAv,arrsymbx,arrsymbx);
    ArrayResize(PbarB,arrsymbx,arrsymbx);
    ArrayResize(TbarB,arrsymbx,arrsymbx);
    ArrayResize(PbarS,arrsymbx,arrsymbx);
    ArrayResize(TbarS,arrsymbx,arrsymbx);
    //--
    return;
//---
  } //-end ArraySymbolResize()
//---------//

void MCEA::UpdatePrice(const string symbol,ENUM_TIMEFRAMES xtf)
  {
//---
    //--
    ArrayFree(OPEN);
    ArrayFree(HIGH);
    ArrayFree(LOW);
    ArrayFree(CLOSE);
    ArrayFree(TIME);
    //--
    ArrayResize(OPEN,arper,arper);
    ArrayResize(HIGH,arper,arper);
    ArrayResize(LOW,arper,arper);
    ArrayResize(CLOSE,arper,arper);
    ArrayResize(TIME,arper,arper);
    //--
    ArraySetAsSeries(OPEN,true);
    ArraySetAsSeries(HIGH,true);
    ArraySetAsSeries(LOW,true);
    ArraySetAsSeries(CLOSE,true);
    ArraySetAsSeries(TIME,true);
    //--
    ArrayInitialize(OPEN,0.0);
    ArrayInitialize(HIGH,0.0);
    ArrayInitialize(LOW,0.0);
    ArrayInitialize(CLOSE,0.0);
    ArrayInitialize(TIME,0);    
    //--
    RefreshPrice(symbol,xtf,arper);
    //--
    int co=CopyOpen(symbol,xtf,0,arper,OPEN);
    int ch=CopyHigh(symbol,xtf,0,arper,HIGH);
    int cl=CopyLow(symbol,xtf,0,arper,LOW);
    int cc=CopyClose(symbol,xtf,0,arper,CLOSE);
    int ct=CopyTime(symbol,xtf,0,arper,TIME);
   //--
   return;
//---
  } //-end UpdatePrice()
//---------//

void MCEA::RefreshPrice(const string symbx,ENUM_TIMEFRAMES xtf,int bars)
  {
//---
    MqlRates parray[]; 
    ArraySetAsSeries(parray,true); 
    int copied=CopyRates(symbx,xtf,0,bars,parray);
    //--
    return;
//---
  } //-end RefreshPrice()
//---------//

bool MCEA::RefreshTick(const string symbx)
  {
//---
    mc_symbol.Name(symbx); 
    if(mc_symbol.RefreshRates()) return(true);
    //--
    return(false);
//---
  } //-end RefreshTick()
//---------//

void MCEA::CurrentSymbolSet(const string symbol)
  {
//---
   mc_symbol.Name(symbol);
   mc_symbol.CheckMarketWatch();
   mc_symbol.IsSynchronized();
   mc_trade.SetTypeFillingBySymbol(symbol);
   mc_symbol.Refresh();
   mc_symbol.RefreshRates();
   //--
   return;
//---
  } //-end CurrentSymbolSet()
//---------//

void MCEA::Pips(const string symbol)
  {
//---
   CurrentSymbolSet(symbol);
   //--
   point=mc_symbol.Point();
   dgts=(int)mc_symbol.Digits();
   //--
   xpip=10.0; 
   pip=point*xpip;
   //--
   return;
//---
  } //-end Pips()
//---------//

bool MCEA::IFNewBarsB(const string symbol) // New bar check buy order
  {
//---
    bool Nb=false;
    int xs=PairsIdxArray(symbol);
    //--
    TbarB[xs]=iTime(symbol,TFt,0);
    if(TbarB[xs]!=PbarB[xs]) Nb=true;
    //--
    return(Nb);
//---
  } //-end IFNewBarsB()
//---------//

bool MCEA::IFNewBarsS(const string symbol) // New bar check sell order
  {
//---
    bool Nb=false;
    int xs=PairsIdxArray(symbol);
    //--
    TbarS[xs]=iTime(symbol,TFt,0);
    if(TbarS[xs]!=PbarS[xs]) Nb=true;
    //--
    return(Nb);
//---
  } //-end IFNewBarsS()
//---------//

int MCEA::DirectionMove(const string symbol,const ENUM_TIMEFRAMES stf) // Bar Price Direction 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    Pips(symbol);
    double difud=mc_symbol.NormalizePrice(1.5*pip);
    UpdatePrice(symbol,stf);
    //--
    if(CLOSE[0]>OPEN[0]+difud) ret=rise;
    if(CLOSE[0]<OPEN[0]-difud) ret=down;
    //--
    return(ret);
//---
  } //-end DirectionMove()
//---------//

double MCEA::WPRPlus(const string symbol,const ENUM_TIMEFRAMES stf)
  {
//---
    double wprpos=0.0;
    int wperiod=14;
    //--
    UpdatePrice(symbol,stf);
    //--
    double WPRP[];
    double RANGEP[];
    ArrayResize(WPRP,arper,arper);
    ArrayResize(RANGEP,arper,arper);
    ArraySetAsSeries(WPRP,true);
    ArraySetAsSeries(RANGEP,true);
    //--
    for(int i=arper-2; i>=0; i--)
      {
        double RHigh = HIGH[ArrayMaximum(HIGH,i,wperiod)];
        double RLow  = LOW[ArrayMinimum(LOW,i,wperiod)];
        RANGEP[i]=NonZeroDiv((RHigh-CLOSE[i]),(RHigh-RLow))*100;
        WPRP[i]=100-fabs(RANGEP[i]);
        if(i==0) wprpos=WPRP[i];
      }
    //--
    return(wprpos);
//---
  } //-end WPRPlus()
//---------//

int MCEA::EMASignal(const string symbol) // formula for EMA signal
  {
//---
   int ret=0;
   int rise=1,
       down=-1;
    int bar=arper;
    //--
    int x=PairsIdxArray(symbol);
    //--
    double EMABuffer[];
    //--
    ArrayResize(EMABuffer,bar,bar);
    ArraySetAsSeries(EMABuffer,true);
    //--
    CopyBuffer(hEMA[x],0,0,bar,EMABuffer);
    UpdatePrice(symbol,TFt);
    //--
    if(CLOSE[0]>EMABuffer[0]) ret=rise;
    if(CLOSE[0]<EMABuffer[0]) ret=down;
//--
   return(ret);
//---
  } //-end EMASignal()
//---------//

int MCEA::OsMASignal(const string symbol) // formula for OsMA signal
  {
//---
   int ret=0;
   int rise=1,
       down=-1;
    int bar=arper;
    //--
    int x=PairsIdxArray(symbol);
    //--
    double OsMABuffer[];
    //--
    ArrayResize(OsMABuffer,bar,bar);
    ArraySetAsSeries(OsMABuffer,true);
    //--
    CopyBuffer(hOsMA[x],0,0,bar,OsMABuffer);
    //--
    if(OsMABuffer[1]<=0.0 && OsMABuffer[0]>0.0) ret=rise;
    if(OsMABuffer[1]>=0.0 && OsMABuffer[0]<0.0) ret=down;
//--
   return(ret);
//---
  } //-end OsMASignal()
//---------//

int MCEA::ZigZagSignal(const string symbol) // ZigZag Signal for Open Position
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    int ZH=-1,
        ZL=-1;
    int barcalc=arper;
    bool ZZrise=false;
    bool ZZdown=false;
    //--
    double ZZBuffer[];
    ArrayResize(ZZBuffer,barcalc,barcalc);
    ArraySetAsSeries(ZZBuffer,true);
    //--  
    int x=PairsIdxArray(symbol);
    UpdatePrice(symbol,TFt);
    //--    
    CopyBuffer(hZigZag[x],0,0,barcalc,ZZBuffer);
    //--
    for(int i=barcalc-1; i>=0; i--)
      {
        if(ZZBuffer[i]==HIGH[i]) ZH=i;
        if(ZZBuffer[i]==LOW[i])  ZL=i;
      }
    //--
    ZZrise=(ZL<ZH && ZL>0)||(ZL>ZH && ZH==0);
    ZZdown=(ZH<ZL && ZH>0)||(ZH>ZL && ZL==0);
    //--
    if(ZZrise) ret=rise; // for open Buy order
    if(ZZdown) ret=down; // for open Sell order
    //--
    return(ret);
//---
  } //-end ZigZagSignal()
//---------//

int MCEA::GetOpenPosition(const string symbol) // Signal Open Position 
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    int Dirmv    = DirectionMove(symbol,TFt);
    int S_ZigZag = ZigZagSignal(symbol);
    int S_OsMA   = OsMASignal(symbol);
    int S_EMA    = EMASignal(symbol);
    //--
    if((Dirmv==rise) && (S_ZigZag==rise) && (S_OsMA==rise) && (S_EMA==rise)) ret=rise;
    if((Dirmv==down) && (S_ZigZag==down) && (S_OsMA==down) && (S_EMA==down)) ret=down;
    //--
    return(ret);
//---
  } //-end GetOpenPosition()
//---------//

int MCEA::GetCloseInWeakSignal(const string symbol,int exis) // Signal Indicator Position Close in profit
  {
//---
    int ret=0;
    int rise=1,
        down=-1;
    //--
    int OsMAx=OsMASignal(symbol);
    int EMAx =EMASignal(symbol);
    //--
    if(exis==down && (OsMAx==rise && EMAx==rise)) ret=rise;
    if(exis==rise && (OsMAx==down && EMAx==down)) ret=down;
    //--
    return(ret);
//---
  } //-end GetCloseInWeakSignal()
//---------//

bool MCEA::OpenBuy(const string symbol) 
  {
//---
    ResetLastError();
    //--
    bool buyopen      = false;
    string ldComm     = GetCommentForOrder()+"_Buy";
    double ldLot      = MLots(symbol);
    ENUM_ORDER_TYPE type_req = ORDER_TYPE_BUY;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    CurrentSymbolSet(symbol);
    double SL=OrderSLSet(symbol,type_req,mc_symbol.Bid());
    double TP=OrderTPSet(symbol,type_req,mc_symbol.Ask());
    //--
    if(RefreshTick(symbol))
       buyopen=mc_trade.Buy(ldLot,symbol,mc_symbol.Ask(),SL,TP,ldComm);
    //--
    int error=GetLastError();
    if(buyopen||error==0)
      {
        string bsopen="Open BUY Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        Do_Alerts(symbol,bsopen);
        int xi=PairsIdxArray(symbol);
        PbarB[xi]=iTime(symbol,TFt,0);
      }
    else
      {
        mc_trade.CheckResult(check);
        Do_Alerts(Symbol(),"Open BUY order for "+symbol+" FAILED!!. Return code= "+
                 (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
        return(false);   
      }
    //--
    return(buyopen);
    //--
//---
  } //-end OpenBuy
//---------//

bool MCEA::OpenSell(const string symbol) 
  {
//---
    ResetLastError();
    //--
    bool selopen      = false;
    string sdComm     = GetCommentForOrder()+"_Sell";
    double sdLot      = MLots(symbol);
    ENUM_ORDER_TYPE type_req = ORDER_TYPE_SELL;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //-- structure is set to zero
    ZeroMemory(req);
    ZeroMemory(res);
    ZeroMemory(check);
    //--
    CurrentSymbolSet(symbol);
    double SL=OrderSLSet(symbol,type_req,mc_symbol.Ask());
    double TP=OrderTPSet(symbol,type_req,mc_symbol.Bid());
    //--
    if(RefreshTick(symbol))
       selopen=mc_trade.Sell(sdLot,symbol,mc_symbol.Bid(),SL,TP,sdComm);
    //--
    int error=GetLastError();
    if(selopen||error==0)
      {
        string bsopen="Open SELL Order for "+symbol+" ~ Ticket= ["+(string)mc_trade.ResultOrder()+"] successfully..!";
        Do_Alerts(symbol,bsopen);
        int xi=PairsIdxArray(symbol);
        PbarS[xi]=iTime(symbol,TFt,0);
      }
    else
      {
        mc_trade.CheckResult(check);
        Do_Alerts(Symbol(),"Open SELL order for "+symbol+" FAILED!!. Return code= "+
                 (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
        return(false);   
      }
    //--
    return(selopen);
    //--
//---
  } //-end OpenSell
//---------//

double MCEA::OrderSLSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
  {
//---
    slv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (ORDER_TYPE_BUY):
         {
           if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice-38*pip);
           else
           if(use_sl==Yes && autosl==No)  slv=mc_symbol.NormalizePrice(atprice-SLval*pip);
           else slv=0.0;
           //--
           break;
         }
       case (ORDER_TYPE_SELL):
         {
           if(use_sl==Yes && autosl==Yes) slv=mc_symbol.NormalizePrice(atprice+38*pip);
           else
           if(use_sl==Yes && autosl==No)  slv=mc_symbol.NormalizePrice(atprice+SLval*pip);
           else slv=0.0;
         }
      }
    //---
    return(slv);
//---
  } //-end OrderSLSet()
//---------//

double MCEA::OrderTPSet(const string xsymb,ENUM_ORDER_TYPE type,double atprice)
  {
//---
    tpv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (ORDER_TYPE_BUY):
         {
           if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice+50*pip);
           else
           if(use_tp==Yes && autotp==No)  tpv=mc_symbol.NormalizePrice(atprice+TPval*pip);
           else tpv=0.0;
           //--
           break;
         }
       case (ORDER_TYPE_SELL):
         {
           if(use_tp==Yes && autotp==Yes) tpv=mc_symbol.NormalizePrice(atprice-50*pip);
           else
           if(use_tp==Yes && autotp==No)  tpv=mc_symbol.NormalizePrice(atprice-TPval*pip);
           else tpv=0.0;
         }
      }
    //---
    return(tpv);
//---
  } //-end OrderTPSet()
//---------//

void MCEA::CheckOpenPMx(const string symbx) //-- function: CheckOpenTrade.
  {
//---
    int totalorder=PositionsTotal();
    xtto=totalorder;
    //--
    int xi=PairsIdxArray(symbx);
    xob[xi]=0;
    xos[xi]=0;
    profitb[xi]=0;
    profits[xi]=0;
    double pos_profit = 0.0;
    double pos_swap   = 0.0;
    double pos_comm   = 0.0;
    //--    
    for(int i=0; i<totalorder && !IsStopped(); i++)
      {
        string position_symbol=PositionGetSymbol(i);
        long magic = mc_position.Magic();
        if(position_symbol==symbx && magic==magicEA)
          {
            //--
            ENUM_POSITION_TYPE opstype = mc_position.PositionType();
            if(opstype == POSITION_TYPE_BUY)
              {
                xob[xi]++;
                pos_profit   = mc_position.Profit();
                pos_swap     = mc_position.Swap();
                pos_comm     = mc_position.Commission();
                profitb[xi]  = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                PbarB[xi]=iTime(symbx,TFt,0);
              }
            if(opstype == POSITION_TYPE_SELL) 
              {
                xos[xi]++;
                pos_profit   = mc_position.Profit();
                pos_swap     = mc_position.Swap();
                pos_comm     = mc_position.Commission();
                profits[xi]  = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                PbarS[xi]=iTime(symbx,TFt,0);
              }
            //--
          }
      }
    //---
    return;
//---
  } //-end CheckOpenPMx()
//---------//

double MCEA::TSPrice(const string xsymb,ENUM_POSITION_TYPE ptype,int TS_type)
  {
//---
    int br=2;
    double pval=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    //--
    switch(TS_type)
      {
        case 0:
          {
            RefreshTick(xsymb);
            if(ptype==POSITION_TYPE_BUY)  pval=mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip);
            if(ptype==POSITION_TYPE_SELL) pval=mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip);
            break;
          }
        case 1:
          {
            double VIDyAv[];
            ArrayResize(VIDyAv,br,br);
            ArraySetAsSeries(VIDyAv,true);
            CopyBuffer(hVIDyAv[x],0,0,br,VIDyAv);
            RefreshPrice(xsymb,TFt,br);
            //--
            if(ptype==POSITION_TYPE_BUY  && (VIDyAv[0]<mc_symbol.NormalizePrice(mc_symbol.Bid()-TSval*pip)))
               pval=VIDyAv[0];
            if(ptype==POSITION_TYPE_SELL && (VIDyAv[0]>mc_symbol.NormalizePrice(mc_symbol.Ask()+TSval*pip)))
               pval=VIDyAv[0];
            break;
          }
      }
    //--
    return(pval);
//---
  } //-end TSPrice()
//---------//

bool MCEA::ModifySLTP(const string symbx,int TS_type)
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   int TRSP=(Close_by_Opps==No && TS_type==1) ? 0 : TS_type;
   bool modist=false;
   int x=PairsIdxArray(symbx);
   Pips(symbx);
   //--
   int total=PositionsTotal();
   //--        
   for(int i=total-1; i>=0; i--) 
     {
       string symbol=PositionGetSymbol(i);
       if(symbol==symbx && mc_position.Magic()==magicEA)
         {
           ENUM_POSITION_TYPE opstype = mc_position.PositionType();
           if(opstype==POSITION_TYPE_BUY) 
             {
               RefreshTick(symbol);
               double price = mc_position.PriceCurrent();
               double vtrsb = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
               double pos_open   = mc_position.PriceOpen();
               double pos_stop   = mc_position.StopLoss();
               double pos_profit = mc_position.Profit();
               double pos_swap   = mc_position.Swap();
               double pos_comm   = mc_position.Commission();
               double netp=pos_profit+pos_swap+pos_comm;
               double modstart=mc_symbol.NormalizePrice(pos_open+TSmin*pip);
               double modminsl=mc_symbol.NormalizePrice(vtrsb+((TSmin-1.0)*pip));
               double modbuysl=vtrsb;
               double modbuytp=mc_symbol.NormalizePrice(price+TPval*pip);
               bool modbuy = (price>modminsl && modbuysl>modstart && (pos_stop==0.0||modbuysl>pos_stop));
               //--
               if(modbuy && netp>minprofit)
                 {
                   modist=mc_trade.PositionModify(symbol,modbuysl,modbuytp);
                 }  
             }
           if(opstype==POSITION_TYPE_SELL) 
             {
               RefreshTick(symbol);
               double price = mc_position.PriceCurrent();
               double vtrss = mc_symbol.NormalizePrice(TSPrice(symbx,opstype,TRSP));
               double pos_open   = mc_position.PriceOpen();
               double pos_stop   = mc_position.StopLoss();
               double pos_profit = mc_position.Profit();
               double pos_swap   = mc_position.Swap();
               double pos_comm   = mc_position.Commission();
               double netp=pos_profit+pos_swap+pos_comm;
               double modstart=mc_symbol.NormalizePrice(pos_open-TSmin*pip);
               double modminsl=mc_symbol.NormalizePrice(vtrss-((TSmin+1.0)*pip));
               double modselsl=vtrss;
               double modseltp=mc_symbol.NormalizePrice(price-TPval*pip);
               bool modsel = (price<modminsl && modselsl<modstart && (pos_stop==0.0||modselsl<pos_stop)); 
               //--
               if(modsel && netp>minprofit)
                 {
                   modist=mc_trade.PositionModify(symbol,modselsl,modseltp);
                 }  
             }
         }
     }
    //--
    return(modist);
//---
  } //-end ModifySLTP()
//---------//

void MCEA::SetSLTPOrders(void) 
  {
//---
   ResetLastError();
   MqlTradeRequest req={};
   MqlTradeResult  res={};
   MqlTradeCheckResult check={};
   //--
   double modbuysl=0;
   double modselsl=0;
   double modbuytp=0;
   double modseltp=0;
   string position_symbol;
   int totalorder=PositionsTotal();
   //--    
   for(int i=totalorder-1; i>=0; i--) 
     {
       string symbol=PositionGetSymbol(i);
       position_symbol=symbol;
       if(mc_position.Magic()==magicEA)
         {
           ENUM_POSITION_TYPE opstype = mc_position.PositionType();
           if(opstype==POSITION_TYPE_BUY) 
             {
               Pips(symbol);
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_take = mc_position.TakeProfit();
               modbuysl=SetOrderSL(symbol,opstype,pos_open);
               if(price<modbuysl) modbuysl=mc_symbol.NormalizePrice(price-slip*pip);
               modbuytp=SetOrderTP(symbol,opstype,pos_open);
               if(price>modbuytp) modbuytp=mc_symbol.NormalizePrice(price+slip*pip);
               //--
               if(pos_stop==0.0 || pos_take==0.0)
                 {
                   if(!mc_trade.PositionModify(position_symbol,modbuysl,modbuytp))
                     {
                       mc_trade.CheckResult(check);
                       Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
                                (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
                     }
                 }
             }
           if(opstype==POSITION_TYPE_SELL) 
             {
               Pips(symbol);
               RefreshTick(symbol);
               double price    = mc_position.PriceCurrent();
               double pos_open = mc_position.PriceOpen();
               double pos_stop = mc_position.StopLoss();
               double pos_take = mc_position.TakeProfit();
               modselsl=SetOrderSL(symbol,opstype,pos_open);
               if(price>modselsl) modselsl=mc_symbol.NormalizePrice(price+slip*pip);
               modseltp=SetOrderTP(symbol,opstype,pos_open);
               if(price<modseltp) modseltp=mc_symbol.NormalizePrice(price-slip*pip);
               //--
               if(pos_stop==0.0 || pos_take==0.0)
                 {
                   if(!mc_trade.PositionModify(position_symbol,modselsl,modseltp))
                     {
                       mc_trade.CheckResult(check);
                       Do_Alerts(symbol,"Set SL and TP for "+EnumToString(opstype)+" on "+symbol+" FAILED!!. Return code= "+
                                (string)mc_trade.ResultRetcode()+". Code description: ["+mc_trade.ResultRetcodeDescription()+"]");
                     }
                 }
             }
         }
     }
    //--
    return;
//---
  } //-end SetSLTPOrders
//---------//

double MCEA::SetOrderSL(const string xsymb,ENUM_POSITION_TYPE type,double atprice)
  {
//---
    slv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (POSITION_TYPE_BUY):
         {
           slv=mc_symbol.NormalizePrice(atprice-SLval*pip);
           //--
           break;
         }
       case (POSITION_TYPE_SELL):
         {
           slv=mc_symbol.NormalizePrice(atprice+SLval*pip);
           //--
           break;
         }
      }
    //---
    return(slv);
//---
  } //-end SetOrderSL()
//---------//

double MCEA::SetOrderTP(const string xsymb,ENUM_POSITION_TYPE type,double atprice)
  {
//---
    tpv=0.0;
    int x=PairsIdxArray(xsymb);
    Pips(xsymb);
    RefreshTick(xsymb);
    //--
    switch(type) 
      { 
       case (POSITION_TYPE_BUY):
         {
           tpv=mc_symbol.NormalizePrice(atprice+TPval*pip);
           //--
           break;
         }
       case (POSITION_TYPE_SELL):
         {
           tpv=mc_symbol.NormalizePrice(atprice-TPval*pip);
         }
      }
    //---
    return(tpv);
//---
  } //-end SetOrderTP()
//---------//

bool MCEA::CloseBuyPositions(const string symbol)
   {
 //---
    //--
    ResetLastError();
    bool buyclose=false;
    int total=PositionsTotal(); // number of open positions
    ENUM_POSITION_TYPE closetype = POSITION_TYPE_BUY;
    ENUM_ORDER_TYPE     type_req = ORDER_TYPE_SELL;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int x=PairsIdxArray(symbol);
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        if(mc_position.SelectByIndex(i))
          {
            //--- Parameters of the order
            string position_Symbol   = PositionGetSymbol(i);
            ulong  position_ticket   = PositionGetTicket(i);
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            //--- if the MagicNumber matches
            if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
              { 
                //--
                if(type==closetype)
                  {
                    RefreshTick(position_Symbol);
                    buyclose=mc_trade.PositionClose(position_Symbol,slip);
                    //--- output information about the closure
                    PrintFormat("Close Buy #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                    if(buyclose) PbarB[x]=iTime(symbol,TFt,0);
                  }
              }
          }
      }
   //---
   return(buyclose);
//----
   } //-end CloseBuyPositions()
//---------//

bool MCEA::CloseSellPositions(const string symbol)
  {
    //---
    ResetLastError();
    bool sellclose=false;
    int total=PositionsTotal(); // number of open positions
    ENUM_POSITION_TYPE closetype = POSITION_TYPE_SELL;
    ENUM_ORDER_TYPE     type_req = ORDER_TYPE_BUY;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int x=PairsIdxArray(symbol);
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        if(mc_position.SelectByIndex(i))
          {
            //--- Parameters of the order
            string position_Symbol   = PositionGetSymbol(i);
            ulong  position_ticket   = PositionGetTicket(i);
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            //--- if the MagicNumber matches
            if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
              { 
                //--
                if(type==closetype)
                  {
                    RefreshTick(position_Symbol);
                    sellclose=mc_trade.PositionClose(position_Symbol,slip);
                    //--- output information about the closure
                    PrintFormat("Close Sell #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                    if(sellclose) PbarS[x]=iTime(symbol,TFt,0);
                  }
              }
          }
      }
   //---
   return(sellclose);
//----
   } //-end CloseSellPositions()
//---------//

bool MCEA::CloseAllProfit(void)
   {
//----
    ResetLastError();
    //--
    int up=1,
        dw=-1;
    bool orclose=false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int ttlorder=PositionsTotal(); // number of open positions
    //--
    for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         orclose=false;
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double pos_profit = mc_position.Profit();
                  double pos_swap   = mc_position.Swap();
                  double pos_comm   = mc_position.Commission();
                  double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                  ulong  position_ticket = PositionGetTicket(i);
                  //---
                  if(type==POSITION_TYPE_BUY && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                      if(orclose) PbarB[x]=iTime(symbol,TFt,0);
                    }
                  if(type==POSITION_TYPE_SELL && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                      if(orclose) PbarS[x]=iTime(symbol,TFt,0);
                    }
                }
            }
       }
     //--
     return(orclose);
//----
   } //-end CloseAllProfit()
//---------//

bool MCEA::ManualCloseAllProfit(void)
   {
//----
    ResetLastError();
    //--
    bool orclose=false;
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int ttlorder=PositionsTotal(); // number of open positions
    //--
    for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         orclose=false;
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double pos_profit = mc_position.Profit();
                  double pos_swap   = mc_position.Swap();
                  double pos_comm   = mc_position.Commission();
                  double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                  ulong  position_ticket = PositionGetTicket(i);
                  //---
                  if(type==POSITION_TYPE_BUY && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                      if(orclose) PbarB[x]=iTime(symbol,TFt,0);
                    }
                  if(type==POSITION_TYPE_SELL && cur_profit>0.02)
                    {
                      RefreshTick(position_Symbol);
                      orclose = mc_trade.PositionClose(position_Symbol,slip);
                      //--- output information about the closure
                      PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
                      if(orclose) PbarS[x]=iTime(symbol,TFt,0);
                    }
                }
            }
       }
     //--
     return(orclose);
//----
   } //-end ManualCloseAllProfit()
//---------//

bool MCEA::CheckProfit(const string symbol,ENUM_POSITION_TYPE intype)
   {
//---
     Pips(symbol);
     double posprofit=mc_symbol.NormalizePrice(5*pip);
     bool inprofit=false;
     //--
     int ttlorder=PositionsTotal(); // number of open positions
     //--
     for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double pos_profit = mc_position.Profit();
                  double pos_swap   = mc_position.Swap();
                  double pos_comm   = mc_position.Commission();
                  double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                  //---
                  if(type==intype && cur_profit>posprofit) inprofit=true;
                }
            }
       }
     //--
     return(inprofit);
//----
   } //-end CheckProfit()
//---------//

bool MCEA::CheckLoss(const string symbol,ENUM_POSITION_TYPE intype)
   {
//---
     Pips(symbol);
     double posloss=mc_symbol.NormalizePrice(5*pip);
     bool inloss=false;
     int ttlorder=PositionsTotal(); // number of open positions
     //--
     for(int x=0; x<arrsymbx; x++)
       {
         string symbol=DIRI[x];
         //--
         for(int i=ttlorder-1; i>=0; i--)
            {
              string position_Symbol   = PositionGetSymbol(i);
              ENUM_POSITION_TYPE  type = mc_position.PositionType();
              if((position_Symbol==symbol) && (mc_position.Magic()==magicEA))
                {
                  double pos_profit = mc_position.Profit();
                  double pos_swap   = mc_position.Swap();
                  double pos_comm   = mc_position.Commission();
                  double cur_profit = NormalizeDouble(pos_profit+pos_swap+pos_comm,2);
                  //---
                  if(type==intype && cur_profit<-posloss) inloss=true;
                }
            }
       }
     //--
     return(inloss);
//----
   } //-end CheckLoss()
//---------//

bool MCEA::CheckProfitLoss(const string symbol)
   {
//----
     ResetLastError();
     //--
     bool closeinloss=false;
     string isloss="due stop in loss.";
     //--
     int xx=PairsIdxArray(symbol);
     //--
     bool BuyProfitSellLoss=(xob[xx]>0 && CheckProfit(symbol,POSITION_TYPE_BUY)) && (xos[xx]>0 && CheckLoss(symbol,POSITION_TYPE_SELL));
     bool SellProfitBuyLoss=(xos[xx]>0 && CheckProfit(symbol,POSITION_TYPE_SELL)) && (xob[xx]>0 && CheckLoss(symbol,POSITION_TYPE_BUY));
     //--
     if(BuyProfitSellLoss && !SellProfitBuyLoss)
       {
         if(CloseSellPositions(symbol))
           {
             PrintFormat("Close Sell %s %s %s",symbol,EnumToString(POSITION_TYPE_BUY),isloss);
             closeinloss=true;
           }
       }
     if(SellProfitBuyLoss && !BuyProfitSellLoss)
       {
         if(CloseBuyPositions(symbol))
           {
             PrintFormat("Close Buy %s %s %s",symbol,EnumToString(POSITION_TYPE_SELL),isloss);
             closeinloss=true;
           }
       }
     //--
     return(closeinloss);
//----
   } //-end CheckProfitLoss()
//---------//

void MCEA::CloseAllOrders(void) //-- function: close all order
   {
//----
    ResetLastError();
    //--
    MqlTradeRequest req={};
    MqlTradeResult  res={};
    MqlTradeCheckResult check={};
    //--
    int total=PositionsTotal(); // number of open positions
    //--- iterate over all open positions
    for(int i=total-1; i>=0; i--)
      {
        //--- if the MagicNumber matches
        if(mc_position.Magic()==magicEA)
          { 
            //--
            string position_Symbol   = PositionGetSymbol(i);  // symbol of the position
            ulong  position_ticket   = PositionGetTicket(i);  // ticket of the the opposite position
            ENUM_POSITION_TYPE  type = mc_position.PositionType();
            RefreshTick(position_Symbol);
            bool closepos = mc_trade.PositionClose(position_Symbol,slip);
            if(closepos && type==POSITION_TYPE_BUY)  PbarB[i]=iTime(position_Symbol,TFt,0);
            if(closepos && type==POSITION_TYPE_SELL) PbarS[i]=iTime(position_Symbol,TFt,0);
            //--- output information about the closure
            PrintFormat("Close #%I64d %s %s",position_ticket,position_Symbol,EnumToString(type));
            //---
          }
      }
   //---
   return;
//----
   } //-end CloseAllOrders()
//---------//

void MCEA::CheckClose(const string symbx)
   {
//---
    //--
    ResetLastError();
    Pips(symbx);
    //--
    datetime to=TimeCurrent();
    datetime from=to-(60);
    closetime=TimeCurrent()-(3); // 3 seconds ago
//--- request the entire history 
    HistorySelect(from,to);
    //--- total number in the list of deals
    int deals=HistoryDealsTotal();
    //--
    datetime deal_time  =0;     // time of a deal execution
    ulong  deal_ticket  =0;     // deal ticket 
    long   deal_magic   =0;     // deal magic number
    long   deal_type    =0;     // Order Type
    double deal_price   =0.0;   // deal/order CLOSE price
    double deal_profit  =0.0;   // deal profit
    double deal_swap    =0.0;   // position swap
    double deal_comm    =0.0;   // position commission
    string deal_symbol  ="";    // symbol of the deal
    ENUM_DEAL_ENTRY deal_entry =0; // enum deal entry
    double profit_loss  =0.0;   // Order profit or loss 
    //--
//--- go through deals in a loop 
    for(int z=deals-1; z>=0 && !IsStopped(); z--)
      {
        deal_ticket = HistoryDealGetTicket(z);
        deal_symbol = HistoryDealGetString(deal_ticket,DEAL_SYMBOL);
        deal_magic  = HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
        deal_entry  = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
        deal_type   = (ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
        //--
        if(deal_symbol==symbx && deal_magic==magicEA)
          {
            if((deal_entry==DEAL_ENTRY_OUT)||(deal_entry==DEAL_ENTRY_OUT_BY))
              {
                deal_time = (datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
                if((deal_time>0) && (deal_time>=closetime))
                  {
                    deal_price  = HistoryDealGetDouble(deal_ticket,DEAL_PRICE);
                    deal_profit = HistoryDealGetDouble(deal_ticket,DEAL_PROFIT); 
                    deal_swap   = HistoryDealGetDouble(deal_ticket,DEAL_SWAP); 
                    deal_comm   = HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);                  
                    profit_loss = NormalizeDouble(deal_profit+deal_swap+deal_comm,2);
                    string xtype = deal_type==DEAL_TYPE_BUY ? "SELL" : deal_type==DEAL_TYPE_SELL ? "BUY": "";
                    //--
                    if(profit_loss>0) 
                      {
                        string ckclose="Close "+xtype+" Position on "+symbx+" at price : "+DoubleToString(deal_price,dgts)+
                                       " OrderCloseTime(): "+TimeToString(deal_time,TIME_DATE|TIME_MINUTES)+
                                       " in profit : "+DoubleToString(profit_loss,2);
                        Do_Alerts(symbx,ckclose);    
                      }
                    if(profit_loss<=0) 
                      {  
                        string ckclose="Close "+xtype+" Position on "+symbx+" at price : "+DoubleToString(deal_price,dgts)+
                                       " OrderCloseTime(): "+TimeToString(deal_time,TIME_DATE|TIME_MINUTES)+
                                       " in loss : "+DoubleToString(profit_loss,2);
                        Do_Alerts(symbx,ckclose);
                      }
                    //--
                    break;
                  }
              }
          }
      }
    //---
    return;
//----
  } //-end CheckClose()
//---------//

void MCEA::TodayOrders(void)
  {
//---
    //--
    ResetLastError();
    //--
    datetime from=StringToTime(ReqDate(ThisTime(day),0,0));
    datetime to=TimeCurrent();
//--- request the entire history
    HistorySelect(from,to);
    //--- total number in the list of deals
    int deals=HistoryDealsTotal();
    //--
    datetime deal_time  =0;     // time of a deal execution
    ulong  deal_ticket  =0;     // deal ticket 
    long   deal_magic   =0;     // deal magic number
    long   deal_type    =0;     // Order Type
    double deal_price   =0.0;   // deal/order CLOSE price
    double deal_profit  =0.0;   // deal profit
    double deal_swap    =0.0;   // position swap
    double deal_comm    =0.0;   // position commission
    ENUM_DEAL_ENTRY deal_entry =0; // enum deal entry
    //--
    string pos_symbol   ="";    // Position symbol
    fixclprofit         =0.0;   // Order Close profit
    floatprofit         =0.0;   // float position profit
    oBm=0;                      // Order buy 
    oSm=0;                      // Order sell
    //--
    int totalorder=PositionsTotal();
    //--    
    for(int i=0; i<totalorder && !IsStopped(); i++)
      {
        pos_symbol = PositionGetSymbol(i);
        long magic = mc_position.Magic();
        if(mc_position.Symbol() == pos_symbol && magic==magicEA)
          {
            //--
            ENUM_POSITION_TYPE opstype = mc_position.PositionType();
            if(opstype == POSITION_TYPE_BUY)  {oBm++; floatprofit += mc_position.Profit();}
            if(opstype == POSITION_TYPE_SELL) {oSm++; floatprofit += mc_position.Profit();}
            //--
          }
      }
    xtto=oBm+oSm;
    //--
//--- go through deals in a loop 
    for(int z=0; z<deals && !IsStopped(); z++)
      {
        deal_ticket = HistoryDealGetTicket(z); 
        deal_magic  = HistoryDealGetInteger(deal_ticket,DEAL_MAGIC);
        deal_entry  = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(deal_ticket,DEAL_ENTRY);
        deal_type   = (ENUM_DEAL_TYPE)HistoryDealGetInteger(deal_ticket,DEAL_TYPE);
        if(deal_magic==magicEA)
          {
            if((deal_entry==DEAL_ENTRY_OUT)||(deal_entry==DEAL_ENTRY_OUT_BY))
              {
                deal_time = (datetime)HistoryDealGetInteger(deal_ticket,DEAL_TIME);
                //--
                if((deal_time>0) && (deal_time>=from))
                  {
                    deal_profit = HistoryDealGetDouble(deal_ticket,DEAL_PROFIT); 
                    deal_swap   = HistoryDealGetDouble(deal_ticket,DEAL_SWAP); 
                    deal_comm   = HistoryDealGetDouble(deal_ticket,DEAL_COMMISSION);                  
                    //--
                    fixclprofit += NormalizeDouble(deal_profit+deal_swap+deal_comm,2);
                  }
              }
          }
      }
    //---
    return;
//----
  } //-end TodayOrders()
//---------//

double MCEA::MLots(const string symbx) // function: calculation lots size
  {
//----
   double Lsize=0.0;
   double sym_Lm=0.0;
   string sym_use ="";
   int pil;
   int Lpair;
   int xsym=-1;
   //--
   string sCur1=StringSubstr(symbx,posCur1,3);
   string sCur2=StringSubstr(symbx,posCur2,3);
   //--
   if(sCur1=="EUR"||sCur1=="GBP"||sCur1=="AUD"||sCur1=="NZD") pil=0;
   if(sCur1=="CAD"||sCur1=="CHF") pil=1;
   if(sCur1=="XAU"||sCur1=="XAG") pil=2;
   if(sCur1=="USD") pil=3;
   //--
   switch(pil)
     {
       case 0: sym_use=sCur1+"USD"; break;
       case 1: sym_use="USD"+sCur1; break;
       case 2: sym_use=symbx;       break;
       case 3: sym_use=symbx;       break;
     }
   //--
   xsym=PairsIdxArray(sym_use);
   if(xsym!=-1) sym_use=DIRI[xsym];
   Lpair = StringFind(sym_use,"USD",0);
   //--
   CurrentSymbolSet(sym_use);
   double csize  = mc_symbol.ContractSize();
   double AFMar  = mc_account.FreeMargin();
   double AFLev  = (double)mc_account.Leverage();
   double symbid = mc_symbol.Bid();
   //--
   double Lmaxs  = SymbolInfoDouble(symbx,SYMBOL_VOLUME_MAX);
   double Lmins  = SymbolInfoDouble(symbx,SYMBOL_VOLUME_MIN);
   //--
   double useRisk = (Risk/100.0);
   double PctUse  = ((100.0-Risk)/100.0);
   //--
   double NZ1=NonZeroDiv(AFMar*AFLev,csize);
   double NZ2=NonZeroDiv(AFMar*AFLev,symbid);
   //--
   if(Lpair>=0 && Lpair<posCur2) {sym_Lm = fmin(Lmaxs,NZ1);}
   else {sym_Lm = fmin(Lmaxs,NonZeroDiv(NZ2,csize));}
   //--
   double sym_Lc = NormalizeDouble(sym_Lm*useRisk,LotDig(symbx));
   double asize  = NormalizeDouble(sym_Lc/(double)LotPS,LotDig(symbx));
   //--
   if(mmlot==DynamLot) 
     {
       Lsize = NormalizeDouble(asize*PctUse,LotDig(symbx));
     } 
   else {Lsize = Lots;}
   //--
   if(Lsize < Lmins) Lsize = Lmins;
   if(Lsize > Lmaxs) Lsize = Lmaxs;
   //--
   double lotsize=NormalizeDouble(Lsize,LotDig(symbx));
   //--
   return(lotsize);
//----
  } //-end MLots()
//---------//

int MCEA::LotDig(const string symbx)
  {
//---
   double lots_step=SymbolInfoDouble(symbx,SYMBOL_VOLUME_STEP);
   //--
   if(lots_step==0.01)
      ldig=2;
   //--
   if(lots_step==0.1)
      ldig=1;
   //--
   if(lots_step==1.0)
      ldig=0;
     //---
     return(ldig);
//----
  } //-end LotDig()
//---------//

double MCEA::NonZeroDiv(double val1,double val2)
  {
//---
   double resval=0.0;
   if(val1==0.0 || val2==0.0) resval=0.00;
   else
   resval=val1/val2;
   //--
   return(resval);
//---
  } //-end NonZeroDiv()
//---------//

void MCEA::TradeInfo(void) // function: write comments on the chart
  {
//----
   Pips(Symbol());
   double spread=SymbolInfoInteger(Symbol(),SYMBOL_SPREAD)/xpip;
   rem=zntm-TimeCurrent();
   string postime=PosTimeZone();
   string eawait=" - Waiting for active time..!";
   //--
   string comm="";
   TodayOrders();
   //--
   comm="\n     :: Server Date Time : "+string(ThisTime(year))+"."+string(ThisTime(mon))+"."+string(ThisTime(day))+ "   "+TimeToString(TimeCurrent(),TIME_SECONDS)+
        "\n     ------------------------------------------------------------"+
        "\n      :: Broker               :  "+ TerminalInfoString(TERMINAL_COMPANY)+
        "\n      :: Expert Name      :  "+ expname+
        "\n      :: Acc. Name         :  "+ mc_account.Name()+
        "\n      :: Acc. Number      :  "+ (string)mc_account.Login()+
        "\n      :: Acc. TradeMode :  "+ AccountMode()+
        "\n      :: Acc. Leverage    :  1 : "+ (string)mc_account.Leverage()+
        "\n      :: Acc. Equity       :  "+ DoubleToString(mc_account.Equity(),2)+
        "\n      :: Margin Mode     :  "+ (string)mc_account.MarginModeDescription()+
        "\n      :: Magic Number   :  "+ string(magicEA)+
        "\n      :: Trade on TF      :  "+ EnumToString(TFt)+
        "\n      :: Today Trading   :  "+ TradingDay()+" : "+hariini+
        "\n      :: Trading Session :  "+ tz_ses+
        "\n      :: Trading Time    :  "+ postime;
        if(TimeCurrent()<zntm)
          {
            comm=comm+
            "\n      :: Time Remaining :  "+(string)ReqTime(rem,hour)+":"+(string)ReqTime(rem,min)+":"+(string)ReqTime(rem,sec) + eawait;
          }
        comm=comm+
        "\n     ------------------------------------------------------------"+
        "\n      :: Trading Pairs     :  "+pairs+
        "\n      :: BUY Market      :  "+string(oBm)+
        "\n      :: SELL Market     :  "+string(oSm)+
        "\n      :: Total Order       :  "+string(oBm+oSm)+
        "\n      :: Order Profit      :  "+DoubleToString(floatprofit,2)+
        "\n      :: Fixed Profit       :  "+DoubleToString(fixclprofit,2)+
        "\n      :: Float Money     :  "+DoubleToString(floatprofit,2)+
        "\n      :: Nett Profit        :  "+DoubleToString(floatprofit+fixclprofit,2);
   //--
   Comment(comm);
   ChartRedraw(0);
   return;
//----
  } //-end TradeInfo()  
//---------//

string MCEA::PosTimeZone(void)
  {
//---
    string tzpos="";
    //--
    if(ReqTime(zntm,day)>ThisTime(day))
     {
       tzpos=tz_opn+ " Next day to " +tz_cls + " Next day";
     }
    else
    if(TimeCurrent()<znop)
      {
        if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)==ReqTime(zncl,day))
          tzpos=tz_opn+" to " +tz_cls+ " Today";
        //else
        if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
          tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
      }
    else
    if(TimeCurrent()>=znop && TimeCurrent()<zncl)
      {
        if(ThisTime(day)<ReqTime(zncl,day))
          tzpos=tz_opn+ " Today to " +tz_cls+ " Next day";
        else
        if(ThisTime(day)==ReqTime(zncl,day))
          tzpos=tz_opn+" to " +tz_cls+ " Today";
      }
    else
    if(ThisTime(day)==ReqTime(znop,day) && ThisTime(day)<ReqTime(zncl,day))
      {
        tzpos=tz_opn+" Today to " +tz_cls+ " Next day";
      }
    //--
    return(tzpos);
//----
  } //-end PosTimeZone()
//---------//

void MCEA::Set_Time_Zone(void)
  {
//---
    //-- Server Time==TimeCurrent()
    datetime TTS=TimeTradeServer();
    datetime GMT=TimeGMT();
    //--
    MqlDateTime svrtm,gmttm; 
    TimeToStruct(TTS,svrtm); 
    TimeToStruct(GMT,gmttm); 
    int svrhr=svrtm.hour;  // Server time hour
    int gmthr=gmttm.hour;  // GMT time hour
    int difhr=svrhr-gmthr; // Time difference Server time to GMT time
    //--
    int NZSGMT=12;  // New Zealand Session GMT/UTC+12
    int AUSGMT=10;  // Australia Sydney Session GMT/UTC+10
    int TOKGMT=9;   // Asia Tokyo Session GMT/UTC+9
    int EURGMT=0;   // Europe London Session GMT/UTC 0
    int USNGMT=-5;  // US New York Session GMT/UTC-5
    //--
    int NZSStm=8;   // New Zealand Session time start: 08:00 Local Time
    int NZSCtm=17;  // New Zealand Session time close: 17:00 Local Time 
    int AUSStm=7;   // Australia Sydney Session time start: 07:00 Local Time 
    int AUSCtm=17;  // Australia Sydney Session time close: 17:00 Local Time  
    int TOKStm=9;   // Asia Tokyo Session time start: 09:00 Local Time 
    int TOKCtm=18;  // Asia Tokyo Session time close: 18:00 Local Time  
    int EURStm=9;   // Europe London Session time start: 09:00 Local Time 
    int EURCtm=19;  // Europe London Session time close: 19:00 Local Time  
    int USNStm=8;   // US New York Session time start: 08:00 Local Time 
    int USNCtm=17;  // US New York Session time close: 17:00 Local Time  
    //--
    int nzo = (NZSStm+difhr-NZSGMT)<0 ? 24+(NZSStm+difhr-NZSGMT) : (NZSStm+difhr-NZSGMT);
    int nzc = (NZSCtm+difhr-NZSGMT)<0 ? 24+(NZSCtm+difhr-NZSGMT) : (NZSCtm+difhr-NZSGMT);
    //--
    int auo = (AUSStm+difhr-AUSGMT)<0 ? 24+(AUSStm+difhr-AUSGMT) : (AUSStm+difhr-AUSGMT);
    int auc = (AUSCtm+difhr-AUSGMT)<0 ? 24+(AUSCtm+difhr-AUSGMT) : (AUSCtm+difhr-AUSGMT);
    //--
    int tko = (TOKStm+difhr-TOKGMT)<0 ? 24+(TOKStm+difhr-TOKGMT) : (TOKStm+difhr-TOKGMT);
    int tkc = (TOKCtm+difhr-TOKGMT)<0 ? 24+(TOKCtm+difhr-TOKGMT) : (TOKCtm+difhr-TOKGMT);
    //--
    int euo = (EURStm+difhr-EURGMT)<0 ? 24+(EURStm+difhr-EURGMT) : (EURStm+difhr-EURGMT);
    int euc = (EURCtm+difhr-EURGMT)<0 ? 24+(EURCtm+difhr-EURGMT) : (EURCtm+difhr-EURGMT);
    //--
    int uso = (USNStm+difhr-USNGMT)<0 ? 24+(USNStm+difhr-USNGMT) : (USNStm+difhr-USNGMT);
    int usc = (USNCtm+difhr-USNGMT)<0 ? 24+(USNCtm+difhr-USNGMT) : (USNCtm+difhr-USNGMT);
    if(usc==0||usc==24) usc=23;
    //--
    //---Trading on Custom Session
    int _days00=ThisTime(day);
    int _days10=ThisTime(day);
    if(stsescuh>clsescuh) _days10=ThisTime(day)+1;
    tmopcu=ReqDate(_days00,stsescuh,stsescum); 
    tmclcu=ReqDate(_days10,clsescuh,clsescum); 
    //--
    //--Trading on New Zealand Session GMT/UTC+12
    int _days01=ThisTime(hour)<nzc ? ThisTime(day)-1 : ThisTime(day);
    int _days11=ThisTime(hour)<nzc ? ThisTime(day) : ThisTime(day)+1;
    tmop01=ReqDate(_days01,nzo,0);    // start: 08:00 Local Time == 20:00 GMT/UTC
    tmcl01=ReqDate(_days11,nzc-1,59); // close: 17:00 Local Time == 05:00 GMT/UTC
    //--
    //--Trading on Australia Sydney Session GMT/UTC+10
    int _days02=ThisTime(hour)<auc ? ThisTime(day)-1 : ThisTime(day);
    int _days12=ThisTime(hour)<auc ? ThisTime(day) : ThisTime(day)+1;
    tmop02=ReqDate(_days02,auo,0);    // start: 07:00 Local Time == 21:00 GMT/UTC
    tmcl02=ReqDate(_days12,auc-1,59); // close: 17:00 Local Time == 07:00 GMT/UTC
    //--
    //--Trading on Asia Tokyo Session GMT/UTC+9
    int _days03=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
    int _days13=ThisTime(hour)<tkc ? ThisTime(day) : ThisTime(day)+1;
    tmop03=ReqDate(_days03,tko,0);    // start: 09:00 Local Time == 00:00 GMT/UTC
    tmcl03=ReqDate(_days13,tkc-1,59); // close: 18:00 Local Time == 09:00 GMT/UTC
    //--
    //--Trading on Europe London Session GMT/UTC 00:00
    int _days04=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
    int _days14=ThisTime(hour)<euc ? ThisTime(day) : ThisTime(day)+1;
    tmop04=ReqDate(_days04,euo,0);     // start: 09:00 Local Time == 09:00 GMT/UTC
    tmcl04=ReqDate(_days14,euc-1,59);  // close: 19:00 Local Time == 19:00 GMT/UTC
    //--
    //--Trading on US New York Session GMT/UTC-5
    int _days05=ThisTime(hour)<usc  ? ThisTime(day) : ThisTime(day)+1;
    int _days15=ThisTime(hour)<=usc ? ThisTime(day) : ThisTime(day)+1;
    tmop05=ReqDate(_days05,uso,0);  // start: 08:00 Local Time == 13:00 GMT/UTC
    tmcl05=ReqDate(_days15,usc,59); // close: 17:00 Local Time == 22:00 GMT/UTC
    //--
    //--Not Use Trading Time Zone
    if(trd_time_zone==No)
      {
        tmopno=ReqDate(ThisTime(day),0,15); 
        tmclno=ReqDate(ThisTime(day),23,59);
      }
    //--
    Time_Zone();
    //--
    return;
//---
  } //-end Set_Time_Zone()
//---------//

void MCEA::Time_Zone(void)
  {
//---
   //--
   tz_ses="";
   //--
   switch(session)
     {
       case Cus_Session:
         {
           SesCuOp=StringToTime(tmopcu);
           SesCuCl=StringToTime(tmclcu);
           zntm=SesCuOp;
           znop=SesCuOp;
           zncl=SesCuCl;
           tz_ses="Custom_Session";
           tz_opn=timehr(stsescuh,stsescum);
           tz_cls=timehr(clsescuh,clsescum);
           break;
         }
       case New_Zealand:
         {
           Ses01Op=StringToTime(tmop01);
           Ses01Cl=StringToTime(tmcl01);
           zntm=Ses01Op;
           znop=Ses01Op;
           zncl=Ses01Cl;
           tz_ses="New_Zealand/Oceania";
           tz_opn=timehr(ReqTime(Ses01Op,hour),ReqTime(Ses01Op,min));
           tz_cls=timehr(ReqTime(Ses01Cl,hour),ReqTime(Ses01Cl,min));
           break;
         }
       case Australia:
         {
           Ses02Op=StringToTime(tmop02);
           Ses02Cl=StringToTime(tmcl02);
           zntm=Ses02Op;
           znop=Ses02Op;
           zncl=Ses02Cl;
           tz_ses="Australia Sydney";
           tz_opn=timehr(ReqTime(Ses02Op,hour),ReqTime(Ses02Op,min));
           tz_cls=timehr(ReqTime(Ses02Cl,hour),ReqTime(Ses02Cl,min));
           break;
         }
       case Asia_Tokyo:
         {
           Ses03Op=StringToTime(tmop03);
           Ses03Cl=StringToTime(tmcl03);
           zntm=Ses03Op;
           znop=Ses03Op;
           zncl=Ses03Cl;
           tz_ses="Asia/Tokyo";
           tz_opn=timehr(ReqTime(Ses03Op,hour),ReqTime(Ses03Op,min));
           tz_cls=timehr(ReqTime(Ses03Cl,hour),ReqTime(Ses03Cl,min));
           break;
         }
       case Europe_London:
         {
           Ses04Op=StringToTime(tmop04);
           Ses04Cl=StringToTime(tmcl04);
           zntm=Ses04Op;
           znop=Ses04Op;
           zncl=Ses04Cl;
           tz_ses="Europe/London";
           tz_opn=timehr(ReqTime(Ses04Op,hour),ReqTime(Ses04Op,min));
           tz_cls=timehr(ReqTime(Ses04Cl,hour),ReqTime(Ses04Cl,min));
           break;
         }
       case US_New_York:
         {
           Ses05Op=StringToTime(tmop05);
           Ses05Cl=StringToTime(tmcl05);
           zntm=Ses05Op;
           znop=Ses05Op;
           zncl=Ses05Cl;
           tz_ses="US/New_York";
           tz_opn=timehr(ReqTime(Ses05Op,hour),ReqTime(Ses05Op,min));
           tz_cls=timehr(ReqTime(Ses05Cl,hour),ReqTime(Ses05Cl,min));
           break;
         }
     }
   //--
   if(trd_time_zone==No)
     {
       SesNoOp=StringToTime(tmopno);
       SesNoCl=StringToTime(tmclno);
       zntm=SesNoOp;
       znop=SesNoOp;
       zncl=SesNoCl;
       tz_ses="Not Use Time Zone";
       tz_opn=timehr(ReqTime(SesNoOp,hour),ReqTime(SesNoOp,min));
       tz_cls=timehr(ReqTime(SesNoCl,hour),ReqTime(SesNoCl,min));
     }
   //--
   return;
//---
  } //-end Time_Zone()
//---------//

bool MCEA::Trade_session(void)
  {
//---
   bool trd_ses=false;
   ishour=ThisTime(hour);
   if(ishour!=onhour) Set_Time_Zone();
   datetime tcurr=TimeCurrent(); // Server Time
   //--
   switch(session)
     {
       case Cus_Session:
         {
           if(tcurr>=SesCuOp && tcurr<=SesCuCl) trd_ses=true;
           break;
         }
       case New_Zealand:
         {
           if(tcurr>=Ses01Op && tcurr<=Ses01Cl) trd_ses=true;
           break;
         }
       case Australia:
         {
           if(tcurr>=Ses02Op && tcurr<=Ses02Cl) trd_ses=true;
           break;
         }
       case Asia_Tokyo:
         {
           if(tcurr>=Ses03Op && tcurr<=Ses03Cl) trd_ses=true;
           break;
         }
       case Europe_London:
         {
           if(tcurr>=Ses04Op && tcurr<=Ses04Cl) trd_ses=true;
           break;
         }
       case US_New_York:
         {
           if(tcurr>=Ses05Op && tcurr<=Ses05Cl) trd_ses=true;
           break;
         }
     }
   //--
   if(trd_time_zone==No) 
     {
      if(tcurr>=SesNoOp && tcurr<=SesNoCl) trd_ses=true;
     }
   //--
   onhour=ishour;
   //--
   return(trd_ses);
//---  
  } //-end Trade_session()
//---------//

string MCEA::TradingDay(void)
  {
//---
   int trdday=ThisTime(dow);
   switch(trdday)
     {
        case 0: daytrade="Sunday";    break;
        case 1: daytrade="Monday";    break;
        case 2: daytrade="Tuesday";   break;
        case 3: daytrade="Wednesday"; break;
        case 4: daytrade="Thursday";  break;
        case 5: daytrade="Friday";    break;
        case 6: daytrade="Saturday";  break;
     }
   return(daytrade);
//---
  } //-end TradingDay()  
//---------//

bool MCEA::TradingToday(void)
  {
//---
    bool tradetoday=false;
    int trdday=ThisTime(dow);
    hariini="No";
    //--
    int ttd[];
    ArrayResize(ttd,7);
    ttd[0]=ttd0;
    ttd[1]=ttd1;
    ttd[2]=ttd2;
    ttd[3]=ttd3;
    ttd[4]=ttd4;
    ttd[5]=ttd5;
    ttd[6]=ttd6;
    //--
    if(ttd[trdday]==Yes) {tradetoday=true; hariini="Yes";}
   //--
   return(tradetoday);
//---
  } //-end TradingToday()
//---------//

string MCEA::timehr(int hr,int mn)
  {
//---
    string scon="";
    string men=mn==0 ? "00" : string(mn);
    int shr=hr==24 ? 0 : hr;
    if(shr<10) scon="0"+string(shr)+":"+men;
    else scon=string(shr)+":"+men;
    //--
    return(scon);
//---
  } //-end timehr()
//---------//

string MCEA::ReqDate(int d,int h,int m) 
  { 
//---
   MqlDateTime mdt; 
   datetime t=TimeCurrent(mdt); 
   x_year=mdt.year; 
   x_mon=mdt.mon; 
   x_day=d; 
   x_hour=h; 
   x_min=m;
   x_sec=mdt.sec;
   //--
   string mdr=string(x_year)+"."+string(x_mon)+"."+string(x_day)+"   "+timehr(x_hour,x_min);
   return(mdr);
//---
  } //-end ReqDate()
//---------//

int MCEA::ThisTime(const int reqmode) 
  {
//---
    MqlDateTime tm;
    TimeCurrent(tm);
    int valtm=0;
    //--
    switch(reqmode)
      {
        case 0: valtm=tm.year; break;        // Return Year 
        case 1: valtm=tm.mon;  break;        // Return Month 
        case 2: valtm=tm.day;  break;        // Return Day 
        case 3: valtm=tm.hour; break;        // Return Hour 
        case 4: valtm=tm.min;  break;        // Return Minutes 
        case 5: valtm=tm.sec;  break;        // Return Seconds 
        case 6: valtm=tm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
        case 7: valtm=tm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero) 
      }
    //--
    return(valtm);
//---
  } //-end ThisTime()
//---------//

int MCEA::ReqTime(datetime reqtime,
                  const int reqmode) 
  {
    MqlDateTime tm;
    TimeToStruct(reqtime,tm);
    int valtm=0;
    //--
    switch(reqmode)
      {
        case 0: valtm=tm.year; break;        // Return Year 
        case 1: valtm=tm.mon;  break;        // Return Month 
        case 2: valtm=tm.day;  break;        // Return Day 
        case 3: valtm=tm.hour; break;        // Return Hour 
        case 4: valtm=tm.min;  break;        // Return Minutes 
        case 5: valtm=tm.sec;  break;        // Return Seconds 
        case 6: valtm=tm.day_of_week; break; // Return Day of week (0-Sunday, 1-Monday, ... ,6-Saturday) 
        case 7: valtm=tm.day_of_year; break; // Return Day number of the year (January 1st is assigned the number value of zero) 
      }
    //--
    return(valtm);
//---
  } //-end ReqTime()
//---------//

string MCEA::AccountMode() // function: to known account trade mode
  {
//----
//--- Demo, Contest or Real account 
   ENUM_ACCOUNT_TRADE_MODE account_type=(ENUM_ACCOUNT_TRADE_MODE)AccountInfoInteger(ACCOUNT_TRADE_MODE);
 //---
   trade_mode="";
   //--
   switch(account_type) 
     { 
      case  ACCOUNT_TRADE_MODE_DEMO: 
         trade_mode="Demo"; 
         break; 
      case  ACCOUNT_TRADE_MODE_CONTEST: 
         trade_mode="Contest"; 
         break; 
      default: 
         trade_mode="Real"; 
         break; 
     }
   //--
   return(trade_mode);
//----
  } //-end AccountMode()
//---------//

void MCEA::Do_Alerts(const string symbol,string msgText)
  {
//---
    //--
    Print("--- "+symbol+": "+msgText+
          "\n--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
    //--
    if(alerts==Yes)
      {
        Alert("--- "+symbol+": "+msgText+
              "--- at: ",TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
      }
    //--
    if(UseEmailAlert==Yes) 
      SendMail(expname,"--- "+symbol+" "+TF2Str(PERIOD_CURRENT)+": "+msgText+
                       "\n--- at: "+TimeToString(TimeCurrent(),TIME_DATE|TIME_MINUTES));
    //--
    if(UseSendnotify==Yes) 
      SendNotification(expname+"--- "+symbol+" "+TF2Str(PERIOD_CURRENT)+": "+msgText+
                      "\n--- at: "+TimeToString(iTime(symbol,0,0),TIME_DATE|TIME_MINUTES));
    //--
    return;
    //--
//---
  } //-end Do_Alerts()
//---------//

string MCEA::TF2Str(ENUM_TIMEFRAMES period)
  {
//---
   switch(period)
     {
       //--
       case PERIOD_M1:   return("M1");
       case PERIOD_M2:   return("M2");
       case PERIOD_M3:   return("M3");
       case PERIOD_M4:   return("M4");
       case PERIOD_M5:   return("M5");
       case PERIOD_M6:   return("M6");
       case PERIOD_M10:  return("M10");
       case PERIOD_M12:  return("M12");
       case PERIOD_M15:  return("M15");
       case PERIOD_M20:  return("M20");
       case PERIOD_M30:  return("M30");
       case PERIOD_H1:   return("H1");
       case PERIOD_H2:   return("H2");
       case PERIOD_H3:   return("H3");
       case PERIOD_H4:   return("H4");
       case PERIOD_H6:   return("H6");
       case PERIOD_H8:   return("H8");
       case PERIOD_H12:  return("H12");
       case PERIOD_D1:   return("D1");
       case PERIOD_W1:   return("W1");
       case PERIOD_MN1:  return("MN1");
       //--
     }
   return(string(period));
//---
  } //-end TF2Str()
//---------//

string MCEA::getUninitReasonText(int reasonCode) 
  { 
//---
   string text=""; 
   //--- 
   switch(reasonCode) 
     { 
       case REASON_PROGRAM:
            text="The EA has stopped working calling by remove function."; break;
       case REASON_REMOVE: 
            text="Program "+__FILE__+" was removed from chart"; break;
       case REASON_RECOMPILE:
            text="Program recompiled."; break;    
       case REASON_CHARTCHANGE: 
            text="Symbol or timeframe was changed"; break;
       case REASON_CHARTCLOSE: 
            text="Chart was closed"; break; 
       case REASON_PARAMETERS: 
            text="Input-parameter was changed"; break;            
       case REASON_ACCOUNT: 
            text="Account was changed"; break; 
       case REASON_TEMPLATE: 
            text="New template was applied to chart"; break; 
       case REASON_INITFAILED:
            text="The OnInit() handler returned a non-zero value."; break;
       case REASON_CLOSE: 
            text="Terminal closed."; break;
       default: text="Another reason"; break;
     } 
   //--
   return text;
//---
  } //-end getUninitReasonText()
//---------//

//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
//---
//--- handling CHARTEVENT_CLICK event ("Clicking the chart")
   ResetLastError();
   //--
   ENUM_TIMEFRAMES CCS=mc.TFt;
   //--
   if(id==CHARTEVENT_OBJECT_CLICK) 
     {
       int lensymbol=StringLen(Symbol());
       int lensparam=StringLen(sparam);
       //--
       //--- if "Set SL All Orders" button is click
       if(sparam=="Set SL/TP All Orders") 
         { 
           mc.SetSLTPOrders();
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Set SL/TP All Orders");
           //--- unpress the button 
           ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_STATE,false);
           ObjectSetInteger(0,"Set SL/TP All Orders",OBJPROP_ZORDER,0);
           CreateManualPanel();
         }
       //--- if "Close All Order" button is click
       if(sparam=="Close All Order") 
         { 
           mc.CloseAllOrders();
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Orders");
           //--- unpress the button 
           ObjectSetInteger(0,"Close All Order",OBJPROP_STATE,false);
           ObjectSetInteger(0,"Close All Order",OBJPROP_ZORDER,0);
           CreateManualPanel();
         }
       //--- if "Close All Profit" button is click
       if(sparam=="Close All Profit") 
         { 
           mc.ManualCloseAllProfit();
           Alert("-- "+mc.expname+" -- ",Symbol()," -- Close All Profit");
           //--- unpress the button 
           ObjectSetInteger(0,"Close All Profit",OBJPROP_STATE,false);
           ObjectSetInteger(0,"Close All Profit",OBJPROP_ZORDER,0);
           CreateManualPanel();
         }
       //--- if "X" button is click
       if(sparam=="X") 
         { 
           ObjectsDeleteAll(0,0,OBJ_BUTTON);
           ObjectsDeleteAll(0,0,OBJ_LABEL);
           ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
           //--- unpress the button 
           ObjectSetInteger(0,"X",OBJPROP_STATE,false);
           ObjectSetInteger(0,"X",OBJPROP_ZORDER,0);
           //--
           DeleteButtonX();
           mc.PanelExtra=false;
           DisplayManualButton();
         }
       //--- if "M" button is click
       if(sparam=="M") 
         { 
           //--- unpress the button 
           ObjectSetInteger(0,"M",OBJPROP_STATE,false);
           ObjectSetInteger(0,"M",OBJPROP_ZORDER,0);
           mc.PanelExtra=true;
           CreateManualPanel();
         }
       //--- if "C" button is click
       if(sparam=="C") 
         { 
           //--- unpress the button 
           ObjectSetInteger(0,"C",OBJPROP_STATE,false);
           ObjectSetInteger(0,"C",OBJPROP_ZORDER,0);
           mc.PanelExtra=true;
           CreateSymbolPanel();
         }
       //--- if "R" button is click
       if(sparam=="R") 
         { 
           Alert("-- "+mc.expname+" -- ",Symbol()," -- expert advisor will be Remove from the chart.");
           ExpertRemove();
           //--- unpress the button 
           ObjectSetInteger(0,"R",OBJPROP_STATE,false);
           ObjectSetInteger(0,"R",OBJPROP_ZORDER,0);
           if(!ChartSetSymbolPeriod(0,Symbol(),Period()))
             ChartSetSymbolPeriod(0,Symbol(),Period());
           DeletePanelButton();
           ChartRedraw(0);
         }
       //--- if Symbol button is click
       if(lensparam==lensymbol)
         {
           int sx=mc.ValidatePairs(sparam);
           ChangeChartSymbol(mc.AS30[sx],CCS);
           mc.PanelExtra=false;
         }
       //--
     }
    //--
    return;
//---
  } //-end OnChartEvent()
//---------//

void ChangeChartSymbol(string c_symbol,ENUM_TIMEFRAMES cstf)
  {
//---
   //--- unpress the button 
   ObjectSetInteger(0,c_symbol,OBJPROP_STATE,false);
   ObjectSetInteger(0,c_symbol,OBJPROP_ZORDER,0);
   ObjectsDeleteAll(0,0,OBJ_BUTTON);
   ObjectsDeleteAll(0,0,OBJ_LABEL);
   ObjectsDeleteAll(0,0,OBJ_RECTANGLE_LABEL);
   //--
   ChartSetSymbolPeriod(0,c_symbol,cstf);
   //--
   ChartRedraw(0);
   //--
   return;
//---
  } //-end ChangeChartSymbol()
//---------//

int WS(int width) // Width Scaling factor wide button
  {
//---
    int res=0;
    int reswidth=0;
    //--- Calculating the scaling factor wide button on a screen
    int scale_factor=(TerminalInfoInteger(TERMINAL_SCREEN_DPI));
    //--- Use of the scaling factor 
    reswidth=(width * scale_factor) / 96;
    double res1=NormalizeDouble(reswidth*1.25,0);
    res=int(res1);
    //--
    return(res);
//---
  } //-end WS()
//---------//

void CreateManualPanel()
  {
//---
    //--
    CreateButtonTemplate(0,"TemplateSL",160,35,STYLE_SOLID,5,BORDER_RAISED,clrNONE,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,170,45,true);
    CreateButtonTemplate(0,"TempStatSL",154,30,STYLE_SOLID,3,BORDER_RAISED,clrNONE,clrGreen,clrWhite,CORNER_RIGHT_UPPER,167,48,true);
    CreateButtonClick(0,"Set SL/TP All Orders",143,21,"Bodoni MT Black",10,BORDER_RAISED,"Set SL/TP All Orders",clrNONE,clrRed,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,162,56,true,"Set SL/TP All Orders");
//--
    CreateButtonTemplate(0,"TemplateS",160,35,STYLE_SOLID,5,BORDER_RAISED,clrNONE,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,170,77,true);
    CreateButtonTemplate(0,"TempStats",154,30,STYLE_SOLID,3,BORDER_RAISED,clrNONE,clrGreen,clrWhite,CORNER_RIGHT_UPPER,167,79,true);
    CreateButtonClick(0,"Close All Order",143,21,"Bodoni MT Black",10,BORDER_RAISED,"Close All Order",clrNONE,clrRed,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,162,88,true,"Close All Order");
//--
    CreateButtonTemplate(0,"TemplateC",160,35,STYLE_SOLID,5,BORDER_RAISED,clrNONE,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,170,109,true);
    CreateButtonTemplate(0,"TempStatC",154,30,STYLE_SOLID,3,BORDER_RAISED,clrNONE,clrGreen,clrWhite,CORNER_RIGHT_UPPER,167,111,true);
    CreateButtonClick(0,"Close All Profit",143,21,"Bodoni MT Black",10,BORDER_RAISED,"Close All Profit",clrNONE,clrRed,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,162,120,true,"Close All Profit");
//--
    DeletePanelButton();
    CreateButtonClick(0,"X",17,15,"Arial Black",12,BORDER_RAISED,"X",clrNONE,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,27,31,true,"Close panel");
    //--
    ChartRedraw(0);
    //--
    return;
//---
   } //-end CreateManualPanel()
//---------//

void DisplayManualButton(void)
  {
//--
    DeleteButtonX();
    CreateButtonClick(0,"M",17,16,"Arial Black",11,BORDER_FLAT,"M",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,61,21,true,"Open Manual Panel");
    CreateButtonClick(0,"C",17,16,"Arial Black",11,BORDER_FLAT,"C",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,41,21,true,"Change Chart Symbol");
    CreateButtonClick(0,"R",17,16,"Arial Black",11,BORDER_FLAT,"R",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,21,21,true,"Expert Remove");
    ChartRedraw(0);
    //--
    return;
//--
  } //-end DisplayManualButton()
//---------//

bool DisplayManualButton(string a,string b,string c)
  {
//--
   if(ObjectFind(0,a)<0 && ObjectFind(0,b)<0 && ObjectFind(0,c)<0 && !mc.PanelExtra)
      return(false);
   return(true);
//--
  } //-end DisplayManualButton()
//---------//

void DeleteButtonX(void)
  {
//--
    ObjectDelete(0,"X");
    //--
    ChartRedraw(0);
    //--
    return;
//--
  } //-end DeleteButtonX()
//---------//

void DeletePanelButton(void)
  {
//--
    ObjectDelete(0,"M");
    ObjectDelete(0,"C");
    ObjectDelete(0,"R");
    //--
    return;
//--
  } //-end DeletePanelButton()
//---------//

void CreateSymbolPanel()
  {
//---    
    //--
    ResetLastError();
    DeletePanelButton();
    int sydis=83;
    int tsatu=int(mc.sall/2);
    //--
    CreateButtonTemplate(0,"Template",180,367,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBurlyWood,clrWhite,CORNER_RIGHT_UPPER,187,45,true);
    CreateButtonTemplate(0,"TempCCS",167,25,STYLE_SOLID,5,BORDER_RAISED,clrYellow,clrBlue,clrWhite,CORNER_RIGHT_UPPER,181,50,true);
    CreateButtonClick(0,"X",14,14,"Arial Black",10,BORDER_FLAT,"X",clrWhite,clrWhite,clrRed,ANCHOR_CENTER,CORNER_RIGHT_UPPER,22,48,true,"Close Symbol Panel");
    //--
    string chsym="Change SYMBOL";
    int cspos=int(181/2)+int(StringLen(chsym)/2);
    CreateButtontLable(0,"CCS","Bodoni MT Black",chsym,11,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,cspos,62,true,"Change Chart Symbol");
    //--
    for(int i=0; i<tsatu; i++)
      CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,180,sydis+(i*22),true,"Change to "+mc.AS30[i]);
    //--
    for(int i=tsatu; i<mc.sall; i++)
      CreateButtonClick(0,mc.AS30[i],80,17,"Bodoni MT Black",8,BORDER_RAISED,mc.AS30[i],clrYellow,clrBlue,clrWhite,ANCHOR_CENTER,CORNER_RIGHT_UPPER,94,sydis+((i-tsatu)*22),true,"Change to "+mc.AS30[i]);
    //--
    ChartRedraw(0);
    //--
    return;
//---
   } //-end CreateSymbolPanel()
//---------//

void CreateButtonClick(long   chartid, 
                       string button_name,
                       int    button_x_size,
                       int    button_y_size,
                       string button_font_model,
                       int    button_font_size,
                       int    button_border,
                       string button_name_text,
                       color  button_bord_color,
                       color  button_bg_color,
                       color  button_color,
                       int    button_anchor,
                       int    button_corner,
                       int    button_xdist,
                       int    button_ydist,
                       bool   button_hidden,
                       string tooltip)
  {
//---
    ObjectCreate(chartid,button_name,OBJ_BUTTON,0,0,0); // create button
    ObjectSetInteger(chartid,button_name,OBJPROP_XSIZE,WS(button_x_size)); 
    ObjectSetInteger(chartid,button_name,OBJPROP_YSIZE,button_y_size); 
    ObjectSetString(chartid,button_name,OBJPROP_TEXT,button_name_text); 
    ObjectSetString(chartid,button_name,OBJPROP_FONT,button_font_model);
    ObjectSetInteger(chartid,button_name,OBJPROP_FONTSIZE,button_font_size);
    ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_TYPE,button_border);
    ObjectSetInteger(chartid,button_name,OBJPROP_BORDER_COLOR,button_bord_color);
    ObjectSetInteger(chartid,button_name,OBJPROP_BGCOLOR,button_bg_color); 
    ObjectSetInteger(chartid,button_name,OBJPROP_COLOR,button_color);
    ObjectSetInteger(chartid,button_name,OBJPROP_ANCHOR,button_anchor);
    ObjectSetInteger(chartid,button_name,OBJPROP_CORNER,button_corner); 
    ObjectSetInteger(chartid,button_name,OBJPROP_XDISTANCE,WS(button_xdist));
    ObjectSetInteger(chartid,button_name,OBJPROP_YDISTANCE,button_ydist);
    ObjectSetInteger(chartid,button_name,OBJPROP_HIDDEN,button_hidden);
    ObjectSetString(chartid,button_name,OBJPROP_TOOLTIP,tooltip);
    ChartRedraw(0);
    //--
    return;
//---
  } //-end CreateButtonClick()
//---------//

void CreateButtonTemplate(long chartid,
                          string obj_name,
                          int    x_size,
                          int    y_size,
                          int    style,
                          int    width,
                          int    border,
                          color  bordcolor,
                          color  bgcolor,
                          color  objcolor,
                          int    corner,
                          int    x_dist,
                          int    y_dist,
                          bool   hidden)
  {
//---
    ObjectCreate(chartid,obj_name,OBJ_RECTANGLE_LABEL,0,0,0); // create Rectangle Label
    ObjectSetInteger(chartid,obj_name,OBJPROP_XSIZE,WS(x_size)); 
    ObjectSetInteger(chartid,obj_name,OBJPROP_YSIZE,y_size);
    ObjectSetInteger(chartid,obj_name,OBJPROP_STYLE,style);
    ObjectSetInteger(chartid,obj_name,OBJPROP_WIDTH,width);
    ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_TYPE,border);
    ObjectSetInteger(chartid,obj_name,OBJPROP_BORDER_COLOR,bordcolor);
    ObjectSetInteger(chartid,obj_name,OBJPROP_BGCOLOR,bgcolor); 
    ObjectSetInteger(chartid,obj_name,OBJPROP_COLOR,objcolor);
    ObjectSetInteger(chartid,obj_name,OBJPROP_CORNER,corner); 
    ObjectSetInteger(chartid,obj_name,OBJPROP_XDISTANCE,WS(x_dist));
    ObjectSetInteger(chartid,obj_name,OBJPROP_YDISTANCE,y_dist);
    ObjectSetInteger(chartid,obj_name,OBJPROP_HIDDEN,hidden);
    ChartRedraw(0);
    //--
    return;
//---
   } //-end CreateButtonTemplate()
//---------//

void CreateButtontLable(long   chartid, 
                        string lable_name, 
                        string lable_font_model,
                        string lable_obj_text,
                        int    lable_font_size,
                        color  lable_color,
                        int    lable_anchor,
                        int    lable_corner,
                        int    lable_xdist,
                        int    lable_ydist,
                        bool   lable_hidden,
                        string tooltip)
  {  
//---
    ObjectDelete(chartid,lable_name);
    ObjectCreate(chartid,lable_name,OBJ_LABEL,0,0,0,0,0); // create Lable 
    ObjectSetInteger(chartid,lable_name,OBJPROP_FONTSIZE,lable_font_size); 
    ObjectSetString(chartid,lable_name,OBJPROP_FONT,lable_font_model);
    ObjectSetString(chartid,lable_name,OBJPROP_TEXT,lable_obj_text);
    ObjectSetInteger(chartid,lable_name,OBJPROP_COLOR,lable_color);
    ObjectSetInteger(chartid,lable_name,OBJPROP_ANCHOR,lable_anchor);
    ObjectSetInteger(chartid,lable_name,OBJPROP_CORNER,lable_corner);
    ObjectSetInteger(chartid,lable_name,OBJPROP_XDISTANCE,WS(lable_xdist));
    ObjectSetInteger(chartid,lable_name,OBJPROP_YDISTANCE,lable_ydist);
    ObjectSetInteger(chartid,lable_name,OBJPROP_HIDDEN,lable_hidden);
    ObjectSetString(chartid,lable_name,OBJPROP_TOOLTIP,tooltip);
    ChartRedraw(0);
    //--
    return;
//---
  } //-end CreateButtontLable()   
//---------//
//--------------------------------------------------------------------//
***Copyright © 2026 3rjfx ~ For educational purposes only.***

Please download the ZigZag_OsMA_EMA_MCEA expert advisor: ZigZag_OsMA_EMA_MCEA


© 2026 ZigZag_OsMA_EMA_MCEA - Developed by Roberto Jacobs (3rjfx)

Featured Post

A Comprehensive Guide to FiboPivotCandleBar: Functions and Performance of the Expert Advisor for MT5

Author: Roberto Jacobs (3rjfx) | Featured on Forex Home Expert FiboPivotCandleBar is a sophisticated trading tool designed to prov...