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."
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_bullscan for specific trend phases (Strong, Strengthening, or Reversal) on the Linear Regression Degrees indicator (LRDegress) - 2. Magnet Mapping: Variables like
a_in_bullconfirm 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









