New EA and Indi

This commit is contained in:
Kunthawat Greethong
2026-01-25 10:34:54 +07:00
parent 39ce46877e
commit 04aa2eb2e6
37 changed files with 17051 additions and 0 deletions

View File

@@ -0,0 +1,753 @@
//+------------------------------------------------------------------+
//| Base_EMA_Reversal.mq5 |
//| Multi-Stage EMA Reversal Signal Indicator |
//+------------------------------------------------------------------+
#property copyright "Copyright 2025"
#property link ""
#property version "1.00"
#property indicator_chart_window
// Properties
#property indicator_buffers 15
#property indicator_plots 6
// Plot configurations - Signal plots (6)
#property indicator_label1 "BUY_SIGNAL"
#property indicator_type1 DRAW_ARROW
#property indicator_color1 clrLime
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
#property indicator_label2 "SELL_SIGNAL"
#property indicator_type2 DRAW_ARROW
#property indicator_color2 clrRed
#property indicator_style2 STYLE_SOLID
#property indicator_width2 2
#property indicator_label3 "BUY_SL"
#property indicator_type3 DRAW_ARROW
#property indicator_color3 clrGray
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
#property indicator_label4 "SELL_SL"
#property indicator_type4 DRAW_ARROW
#property indicator_color4 clrGray
#property indicator_style4 STYLE_SOLID
#property indicator_width4 1
#property indicator_label5 "BUY_TP"
#property indicator_type5 DRAW_ARROW
#property indicator_color5 clrBlue
#property indicator_style5 STYLE_SOLID
#property indicator_width5 1
#property indicator_label6 "SELL_TP"
#property indicator_type6 DRAW_ARROW
#property indicator_color6 clrBlue
#property indicator_style6 STYLE_SOLID
#property indicator_width6 1
// EMA Line plots (7)
#property indicator_label7 "EMA_50"
#property indicator_type7 DRAW_LINE
#property indicator_color7 clrRed
#property indicator_style7 STYLE_SOLID
#property indicator_width7 1
#property indicator_label8 "EMA_100"
#property indicator_type8 DRAW_LINE
#property indicator_color8 clrOrange
#property indicator_style8 STYLE_SOLID
#property indicator_width8 1
#property indicator_label9 "EMA_200"
#property indicator_type9 DRAW_LINE
#property indicator_color9 clrYellow
#property indicator_style9 STYLE_SOLID
#property indicator_width9 1
#property indicator_label10 "EMA_300"
#property indicator_type10 DRAW_LINE
#property indicator_color10 clrGreen
#property indicator_style10 STYLE_SOLID
#property indicator_width10 1
#property indicator_label11 "EMA_400"
#property indicator_type11 DRAW_LINE
#property indicator_color11 clrBlue
#property indicator_style11 STYLE_SOLID
#property indicator_width11 1
#property indicator_label12 "EMA_500"
#property indicator_type12 DRAW_LINE
#property indicator_color12 clrPurple
#property indicator_style12 STYLE_SOLID
#property indicator_width12 1
#property indicator_label13 "EMA_600"
#property indicator_type13 DRAW_LINE
#property indicator_color13 clrMagenta
#property indicator_style13 STYLE_SOLID
#property indicator_width13 1
//+------------------------------------------------------------------+
//| Input Parameters |
//+------------------------------------------------------------------+
input group "=== EMA Settings ==="
input int InpEMA50_Period = 50;
input int InpEMA100_Period = 100;
input int InpEMA200_Period = 200;
input int InpEMA300_Period = 300;
input int InpEMA400_Period = 400;
input int InpEMA500_Period = 500;
input int InpEMA600_Period = 600;
input group "=== Setup Settings ==="
input int InpLookbackPeriod = 100; // Lookback bars for base detection
input double InpBaseThreshold = 50; // Pullback threshold (points)
input int InpPullbackBars = 2; // Max bars to wait for pullback
input int InpSkipBars = 50; // Bars to skip at startup
input group "=== ATR Settings ==="
input int InpATRPeriod = 14; // ATR period for TP fallback
input group "=== Display Settings ==="
input bool InpShowStageLabels = true; // Show stage labels on chart
//+------------------------------------------------------------------+
//| Indicator Buffers |
//+------------------------------------------------------------------+
double BuySignalBuffer[];
double SellSignalBuffer[];
double BuySLBuffer[];
double SellSLBuffer[];
double BuyTPBuffer[];
double SellTPBuffer[];
double BuyStateBuffer[];
double SellStateBuffer[];
// EMA Line buffers for display
double EMA50_Buffer[];
double EMA100_Buffer[];
double EMA200_Buffer[];
double EMA300_Buffer[];
double EMA400_Buffer[];
double EMA500_Buffer[];
double EMA600_Buffer[];
//+------------------------------------------------------------------+
//| EMA Handles |
//+------------------------------------------------------------------+
int h_ema50, h_ema100, h_ema200;
int h_ema300, h_ema400, h_ema500, h_ema600;
int h_atr;
//+------------------------------------------------------------------+
//| State Tracking Variables |
//+------------------------------------------------------------------+
int buy_state = 0;
int sell_state = 0;
double BaseLow = 0;
double BaseHigh = 0;
datetime last_signal_time = 0;
// EMA touch tracking
bool buy_ema_touched = false;
bool sell_ema_touched = false;
int ema_touch_bar = -1;
int buy_touch_ema_count = 0;
int sell_touch_ema_count = 0;
//+------------------------------------------------------------------+
//| OnInit |
//+------------------------------------------------------------------+
int OnInit()
{
// Create EMA handles
h_ema50 = iMA(_Symbol, _Period, InpEMA50_Period, 0, MODE_EMA, PRICE_CLOSE);
h_ema100 = iMA(_Symbol, _Period, InpEMA100_Period, 0, MODE_EMA, PRICE_CLOSE);
h_ema200 = iMA(_Symbol, _Period, InpEMA200_Period, 0, MODE_EMA, PRICE_CLOSE);
h_ema300 = iMA(_Symbol, _Period, InpEMA300_Period, 0, MODE_EMA, PRICE_CLOSE);
h_ema400 = iMA(_Symbol, _Period, InpEMA400_Period, 0, MODE_EMA, PRICE_CLOSE);
h_ema500 = iMA(_Symbol, _Period, InpEMA500_Period, 0, MODE_EMA, PRICE_CLOSE);
h_ema600 = iMA(_Symbol, _Period, InpEMA600_Period, 0, MODE_EMA, PRICE_CLOSE);
h_atr = iATR(_Symbol, _Period, InpATRPeriod);
// Validate handles
if(h_ema50 == INVALID_HANDLE || h_ema100 == INVALID_HANDLE || h_ema200 == INVALID_HANDLE ||
h_ema300 == INVALID_HANDLE || h_ema400 == INVALID_HANDLE || h_ema500 == INVALID_HANDLE ||
h_ema600 == INVALID_HANDLE || h_atr == INVALID_HANDLE)
{
Print("Error creating indicator handles");
return(INIT_FAILED);
}
// Set buffers
SetIndexBuffer(0, BuySignalBuffer, INDICATOR_DATA);
SetIndexBuffer(1, SellSignalBuffer, INDICATOR_DATA);
SetIndexBuffer(2, BuySLBuffer, INDICATOR_DATA);
SetIndexBuffer(3, SellSLBuffer, INDICATOR_DATA);
SetIndexBuffer(4, BuyTPBuffer, INDICATOR_DATA);
SetIndexBuffer(5, SellTPBuffer, INDICATOR_DATA);
SetIndexBuffer(6, BuyStateBuffer, INDICATOR_CALCULATIONS);
SetIndexBuffer(7, SellStateBuffer, INDICATOR_CALCULATIONS);
// EMA Line buffers
SetIndexBuffer(8, EMA50_Buffer, INDICATOR_DATA);
SetIndexBuffer(9, EMA100_Buffer, INDICATOR_DATA);
SetIndexBuffer(10, EMA200_Buffer, INDICATOR_DATA);
SetIndexBuffer(11, EMA300_Buffer, INDICATOR_DATA);
SetIndexBuffer(12, EMA400_Buffer, INDICATOR_DATA);
SetIndexBuffer(13, EMA500_Buffer, INDICATOR_DATA);
SetIndexBuffer(14, EMA600_Buffer, INDICATOR_DATA);
// Configure plots
PlotIndexSetInteger(0, PLOT_ARROW, 233); // Up arrow for buy
PlotIndexSetInteger(1, PLOT_ARROW, 234); // Down arrow for sell
PlotIndexSetInteger(2, PLOT_ARROW, 159); // Dot for SL
PlotIndexSetInteger(3, PLOT_ARROW, 159); // Dot for SL
PlotIndexSetInteger(4, PLOT_ARROW, 160); // Plus for TP
PlotIndexSetInteger(5, PLOT_ARROW, 160); // Plus for TP
// Set empty values for all plots
for(int i = 0; i < 14; i++)
{
PlotIndexSetDouble(i, PLOT_EMPTY_VALUE, EMPTY_VALUE);
}
Print("Base_EMA_Reversal initialized successfully");
Print("EMA Periods: ", InpEMA50_Period, ", ", InpEMA100_Period, ", ", InpEMA200_Period, ", ",
InpEMA300_Period, ", ", InpEMA400_Period, ", ", InpEMA500_Period, ", ", InpEMA600_Period);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| OnDeinit |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Release handles
if(h_ema50 != INVALID_HANDLE) IndicatorRelease(h_ema50);
if(h_ema100 != INVALID_HANDLE) IndicatorRelease(h_ema100);
if(h_ema200 != INVALID_HANDLE) IndicatorRelease(h_ema200);
if(h_ema300 != INVALID_HANDLE) IndicatorRelease(h_ema300);
if(h_ema400 != INVALID_HANDLE) IndicatorRelease(h_ema400);
if(h_ema500 != INVALID_HANDLE) IndicatorRelease(h_ema500);
if(h_ema600 != INVALID_HANDLE) IndicatorRelease(h_ema600);
if(h_atr != INVALID_HANDLE) IndicatorRelease(h_atr);
// Delete all stage label objects
ObjectsDeleteAll(0, "EMA_Stage_");
Print("Base_EMA_Reversal deinitialized");
}
//+------------------------------------------------------------------+
//| OnCalculate |
//+------------------------------------------------------------------+
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[])
{
// Set arrays as series (index 0 = current bar)
ArraySetAsSeries(time, true);
ArraySetAsSeries(open, true);
ArraySetAsSeries(high, true);
ArraySetAsSeries(low, true);
ArraySetAsSeries(close, true);
ArraySetAsSeries(BuySignalBuffer, true);
ArraySetAsSeries(SellSignalBuffer, true);
ArraySetAsSeries(BuySLBuffer, true);
ArraySetAsSeries(SellSLBuffer, true);
ArraySetAsSeries(BuyTPBuffer, true);
ArraySetAsSeries(SellTPBuffer, true);
ArraySetAsSeries(BuyStateBuffer, true);
ArraySetAsSeries(SellStateBuffer, true);
// Check minimum data requirement
if(rates_total < InpSkipBars + InpLookbackPeriod + InpEMA600_Period)
{
return(0);
}
// Copy EMA data
double ema50[], ema100[], ema200[];
double ema300[], ema400[], ema500[], ema600[];
double atr[];
ArraySetAsSeries(ema50, true);
ArraySetAsSeries(ema100, true);
ArraySetAsSeries(ema200, true);
ArraySetAsSeries(ema300, true);
ArraySetAsSeries(ema400, true);
ArraySetAsSeries(ema500, true);
ArraySetAsSeries(ema600, true);
ArraySetAsSeries(atr, true);
ArraySetAsSeries(EMA50_Buffer, true);
ArraySetAsSeries(EMA100_Buffer, true);
ArraySetAsSeries(EMA200_Buffer, true);
ArraySetAsSeries(EMA300_Buffer, true);
ArraySetAsSeries(EMA400_Buffer, true);
ArraySetAsSeries(EMA500_Buffer, true);
ArraySetAsSeries(EMA600_Buffer, true);
if(CopyBuffer(h_ema50, 0, 0, rates_total, ema50) <= 0) return(0);
if(CopyBuffer(h_ema100, 0, 0, rates_total, ema100) <= 0) return(0);
if(CopyBuffer(h_ema200, 0, 0, rates_total, ema200) <= 0) return(0);
if(CopyBuffer(h_ema300, 0, 0, rates_total, ema300) <= 0) return(0);
if(CopyBuffer(h_ema400, 0, 0, rates_total, ema400) <= 0) return(0);
if(CopyBuffer(h_ema500, 0, 0, rates_total, ema500) <= 0) return(0);
if(CopyBuffer(h_ema600, 0, 0, rates_total, ema600) <= 0) return(0);
if(CopyBuffer(h_atr, 0, 0, rates_total, atr) <= 0) return(0);
// Copy EMA values to display buffers
if(CopyBuffer(h_ema50, 0, 0, rates_total, EMA50_Buffer) <= 0) return(0);
if(CopyBuffer(h_ema100, 0, 0, rates_total, EMA100_Buffer) <= 0) return(0);
if(CopyBuffer(h_ema200, 0, 0, rates_total, EMA200_Buffer) <= 0) return(0);
if(CopyBuffer(h_ema300, 0, 0, rates_total, EMA300_Buffer) <= 0) return(0);
if(CopyBuffer(h_ema400, 0, 0, rates_total, EMA400_Buffer) <= 0) return(0);
if(CopyBuffer(h_ema500, 0, 0, rates_total, EMA500_Buffer) <= 0) return(0);
if(CopyBuffer(h_ema600, 0, 0, rates_total, EMA600_Buffer) <= 0) return(0);
// Calculate start position
int bars_to_process;
int start_bar;
if(prev_calculated == 0)
{
// First calculation - initialize base levels
bars_to_process = rates_total - InpSkipBars - 1;
start_bar = InpSkipBars;
// Initialize BaseLow/BaseHigh from lookback period
int lookback_start = InpSkipBars + InpLookbackPeriod;
int lookback_end = InpSkipBars + 1;
BaseLow = low[lookback_start];
BaseHigh = high[lookback_start];
for(int i = lookback_start; i >= lookback_end; i--)
{
if(low[i] < BaseLow) BaseLow = low[i];
if(high[i] > BaseHigh) BaseHigh = high[i];
}
// Initialize states
buy_state = 1;
sell_state = 1;
buy_ema_touched = false;
sell_ema_touched = false;
ema_touch_bar = -1;
Print("Initialization: BaseLow = ", BaseLow, ", BaseHigh = ", BaseHigh);
// Clear buffers
ArrayInitialize(BuySignalBuffer, EMPTY_VALUE);
ArrayInitialize(SellSignalBuffer, EMPTY_VALUE);
ArrayInitialize(BuySLBuffer, EMPTY_VALUE);
ArrayInitialize(SellSLBuffer, EMPTY_VALUE);
ArrayInitialize(BuyTPBuffer, EMPTY_VALUE);
ArrayInitialize(SellTPBuffer, EMPTY_VALUE);
ArrayInitialize(BuyStateBuffer, 0);
ArrayInitialize(SellStateBuffer, 0);
ArrayInitialize(EMA50_Buffer, EMPTY_VALUE);
ArrayInitialize(EMA100_Buffer, EMPTY_VALUE);
ArrayInitialize(EMA200_Buffer, EMPTY_VALUE);
ArrayInitialize(EMA300_Buffer, EMPTY_VALUE);
ArrayInitialize(EMA400_Buffer, EMPTY_VALUE);
ArrayInitialize(EMA500_Buffer, EMPTY_VALUE);
ArrayInitialize(EMA600_Buffer, EMPTY_VALUE);
}
else if(rates_total > prev_calculated)
{
// New bars added - process only new bars
bars_to_process = rates_total - prev_calculated;
start_bar = 0;
}
else
{
// Recalculate last bar only
bars_to_process = 1;
start_bar = 0;
}
// Process bars
for(int i = start_bar; i < start_bar + bars_to_process && i < rates_total - InpSkipBars; i++)
{
// Skip initialization area
if(i >= rates_total - InpSkipBars) continue;
// Default buffer values (EMPTY_VALUE for all signal/SL/TP buffers)
BuySignalBuffer[i] = EMPTY_VALUE;
SellSignalBuffer[i] = EMPTY_VALUE;
BuySLBuffer[i] = EMPTY_VALUE;
SellSLBuffer[i] = EMPTY_VALUE;
BuyTPBuffer[i] = EMPTY_VALUE;
SellTPBuffer[i] = EMPTY_VALUE;
// Copy EMA values to display buffers
EMA50_Buffer[i] = ema50[i];
EMA100_Buffer[i] = ema100[i];
EMA200_Buffer[i] = ema200[i];
EMA300_Buffer[i] = ema300[i];
EMA400_Buffer[i] = ema400[i];
EMA500_Buffer[i] = ema500[i];
EMA600_Buffer[i] = ema600[i];
// Update state buffers
BuyStateBuffer[i] = buy_state;
SellStateBuffer[i] = sell_state;
// State 1: Finding Base (continuous tracking)
if(buy_state == 1 || buy_state == 0)
{
if(low[i] < BaseLow)
{
BaseLow = low[i];
}
buy_state = 1;
}
if(sell_state == 1 || sell_state == 0)
{
if(high[i] > BaseHigh)
{
BaseHigh = high[i];
}
sell_state = 1;
}
// Check for EMA touch (State 1 -> State 2)
// BUY SIDE: Price touches EMA from below (close below -> close above)
if(buy_state == 1 && !buy_ema_touched)
{
// Find lowest EMA (most resistance from below)
double lowest_ema = ema50[i];
if(ema100[i] < lowest_ema) lowest_ema = ema100[i];
if(ema200[i] < lowest_ema) lowest_ema = ema200[i];
// Previous bar close
double prev_close = (i < rates_total - 1) ? close[i + 1] : close[i];
// EMA touch from below (previous close at/below, current close above)
if(prev_close <= lowest_ema && close[i] > lowest_ema)
{
buy_ema_touched = true;
ema_touch_bar = i;
// Count EMAs crossed
buy_touch_ema_count = 0;
if(close[i] > ema50[i]) buy_touch_ema_count++;
if(close[i] > ema100[i]) buy_touch_ema_count++;
if(close[i] > ema200[i]) buy_touch_ema_count++;
buy_state = 2;
BuyStateBuffer[i] = 2;
}
}
// SELL SIDE: Price touches EMA from above (close above -> close below)
if(sell_state == 1 && !sell_ema_touched)
{
// Find highest EMA (most support from above)
double highest_ema = ema50[i];
if(ema100[i] > highest_ema) highest_ema = ema100[i];
if(ema200[i] > highest_ema) highest_ema = ema200[i];
// Previous bar close
double prev_close = (i < rates_total - 1) ? close[i + 1] : close[i];
// EMA touch from above (previous close at/above, current close below)
if(prev_close >= highest_ema && close[i] < highest_ema)
{
sell_ema_touched = true;
ema_touch_bar = i;
// Count EMAs crossed
sell_touch_ema_count = 0;
if(close[i] < ema50[i]) sell_touch_ema_count++;
if(close[i] < ema100[i]) sell_touch_ema_count++;
if(close[i] < ema200[i]) sell_touch_ema_count++;
sell_state = 2;
SellStateBuffer[i] = 2;
}
}
// State 3: Decision (within pullback window)
// BUY SIDE DECISION
if(buy_ema_touched)
{
int bars_since_touch = ema_touch_bar - i;
// Timeout check - if more than pullback bars passed, cancel
if(bars_since_touch > InpPullbackBars)
{
buy_ema_touched = false;
buy_state = 1;
BuyStateBuffer[i] = 1;
continue;
}
// Cancel condition: crossed EMA below again
double lowest_ema_current = ema50[i];
if(ema100[i] < lowest_ema_current) lowest_ema_current = ema100[i];
if(ema200[i] < lowest_ema_current) lowest_ema_current = ema200[i];
if(close[i] < lowest_ema_current)
{
buy_ema_touched = false;
buy_state = 1;
BuyStateBuffer[i] = 1;
continue;
}
// Pullback check
double pullback_distance = MathAbs(low[i] - BaseLow) / _Point;
if(pullback_distance <= InpBaseThreshold)
{
// GENERATE BUY SIGNAL
BuySignalBuffer[i] = close[i];
BuySLBuffer[i] = BaseLow;
BuyTPBuffer[i] = CalculateBuyTP(close[i], ema300[i], ema400[i], ema500[i], ema600[i], atr[i]);
BuyStateBuffer[i] = 3;
// Create signal label
if(InpShowStageLabels)
{
UpdateStageLabels(time[i], 3, sell_state, low[i] - 50 * _Point, i);
}
// Reset
buy_ema_touched = false;
buy_state = 1;
last_signal_time = time[i];
// Recalculate BaseLow from bar before signal
RecalculateBaseBuy(i, rates_total, low);
Print("BUY SIGNAL at ", TimeToString(time[i]), " Price: ", close[i], " SL: ", BaseLow,
" TP: ", BuyTPBuffer[i]);
}
}
// SELL SIDE DECISION
if(sell_ema_touched)
{
int bars_since_touch = ema_touch_bar - i;
// Timeout check - if more than pullback bars passed, cancel
if(bars_since_touch > InpPullbackBars)
{
sell_ema_touched = false;
sell_state = 1;
SellStateBuffer[i] = 1;
continue;
}
// Cancel condition: crossed EMA above again
double highest_ema_current = ema50[i];
if(ema100[i] > highest_ema_current) highest_ema_current = ema100[i];
if(ema200[i] > highest_ema_current) highest_ema_current = ema200[i];
if(close[i] > highest_ema_current)
{
sell_ema_touched = false;
sell_state = 1;
SellStateBuffer[i] = 1;
continue;
}
// Pullback check
double pullback_distance = MathAbs(high[i] - BaseHigh) / _Point;
if(pullback_distance <= InpBaseThreshold)
{
// GENERATE SELL SIGNAL
SellSignalBuffer[i] = close[i];
SellSLBuffer[i] = BaseHigh;
SellTPBuffer[i] = CalculateSellTP(close[i], ema300[i], ema400[i], ema500[i], ema600[i], atr[i]);
SellStateBuffer[i] = 3;
// Create signal label
if(InpShowStageLabels)
{
UpdateStageLabels(time[i], 3, sell_state, high[i] + 50 * _Point, i);
}
// Reset
sell_ema_touched = false;
sell_state = 1;
last_signal_time = time[i];
// Recalculate BaseHigh from bar before signal
RecalculateBaseSell(i, rates_total, high);
Print("SELL SIGNAL at ", TimeToString(time[i]), " Price: ", close[i], " SL: ", BaseHigh,
" TP: ", SellTPBuffer[i]);
}
}
}
return(rates_total);
}
//+------------------------------------------------------------------+
//| Calculate Buy Take Profit |
//+------------------------------------------------------------------+
double CalculateBuyTP(double entry_price, double ema300, double ema400,
double ema500, double ema600, double atr)
{
double tp = 0;
// Find lowest valid EMA ABOVE price (closest = best risk/reward)
if(ema300 > entry_price)
{
if(tp == 0 || ema300 < tp) tp = ema300;
}
if(ema400 > entry_price)
{
if(tp == 0 || ema400 < tp) tp = ema400;
}
if(ema500 > entry_price)
{
if(tp == 0 || ema500 < tp) tp = ema500;
}
if(ema600 > entry_price)
{
if(tp == 0 || ema600 < tp) tp = ema600;
}
// ATR fallback: if no valid EMA above price
if(tp == 0 && atr > 0)
{
tp = entry_price + atr * 2;
}
return NormalizeDouble(tp, _Digits);
}
//+------------------------------------------------------------------+
//| Calculate Sell Take Profit |
//+------------------------------------------------------------------+
double CalculateSellTP(double entry_price, double ema300, double ema400,
double ema500, double ema600, double atr)
{
double tp = 0;
// Find highest valid EMA BELOW price (closest = best risk/reward)
if(ema300 < entry_price)
{
if(tp == 0 || ema300 > tp) tp = ema300;
}
if(ema400 < entry_price)
{
if(tp == 0 || ema400 > tp) tp = ema400;
}
if(ema500 < entry_price)
{
if(tp == 0 || ema500 > tp) tp = ema500;
}
if(ema600 < entry_price)
{
if(tp == 0 || ema600 > tp) tp = ema600;
}
// ATR fallback: if no valid EMA below price
if(tp == 0 && atr > 0)
{
tp = entry_price - atr * 2;
}
return NormalizeDouble(tp, _Digits);
}
//+------------------------------------------------------------------+
//| Recalculate Buy Base Level After Signal |
//+------------------------------------------------------------------+
void RecalculateBaseBuy(int signal_bar, int total_bars, const double &low_arr[])
{
// Start from bar before signal
BaseLow = low_arr[signal_bar + 1];
// Find new base from that point forward
for(int j = signal_bar + 1; j < total_bars - InpSkipBars; j++)
{
if(low_arr[j] < BaseLow)
{
BaseLow = low_arr[j];
}
}
// Print("BaseLow recalculated: ", BaseLow, " after buy signal");
}
//+------------------------------------------------------------------+
//| Recalculate Sell Base Level After Signal |
//+------------------------------------------------------------------+
void RecalculateBaseSell(int signal_bar, int total_bars, const double &high_arr[])
{
// Start from bar before signal
BaseHigh = high_arr[signal_bar + 1];
// Find new base from that point forward
for(int j = signal_bar + 1; j < total_bars - InpSkipBars; j++)
{
if(high_arr[j] > BaseHigh)
{
BaseHigh = high_arr[j];
}
}
// Print("BaseHigh recalculated: ", BaseHigh, " after sell signal");
}
//+------------------------------------------------------------------+
//| Update Stage Labels |
//+------------------------------------------------------------------+
void UpdateStageLabels(datetime label_time, int buy_st, int sell_st, double price, int bar_index)
{
string label_name = "EMA_Stage_" + IntegerToString(bar_index);
string text = "";
color label_color;
// Format: "BUY/SELL" for signal bars
if(buy_st == 3)
{
text = "BUY SIGNAL";
label_color = clrLime;
}
else if(sell_st == 3)
{
text = "SELL SIGNAL";
label_color = clrRed;
}
else
{
// Show state only when not in signal
text = StringFormat("B:%d S:%d", buy_st, sell_st);
label_color = clrGray;
switch(buy_st)
{
case 0: label_color = clrGray; break;
case 1: label_color = clrBlue; break;
case 2: label_color = clrOrange; break;
case 3: label_color = clrGreen; break;
default: label_color = clrGray;
}
}
// Create or update label
if(ObjectFind(0, label_name) < 0)
{
ObjectCreate(0, label_name, OBJ_TEXT, 0, label_time, price);
}
ObjectSetString(0, label_name, OBJPROP_TEXT, text);
ObjectSetInteger(0, label_name, OBJPROP_COLOR, label_color);
ObjectSetInteger(0, label_name, OBJPROP_FONTSIZE, 14);
ObjectSetInteger(0, label_name, OBJPROP_ANCHOR, ANCHOR_UPPER);
ObjectSetInteger(0, label_name, OBJPROP_SELECTABLE, false);
}
//+------------------------------------------------------------------+

148
EMA Indi/README.md Normal file
View File

@@ -0,0 +1,148 @@
# Base-EMA Multi-Stage Reversal Signal Indicator
## Overview
The Base-EMA Reversal Indicator is a sophisticated trading tool that identifies potential reversal opportunities using a multi-stage state machine approach with EMA confluence. The indicator tracks both buy and sell opportunities through a systematic process of base formation, EMA confirmation, and pullback detection.
## Features
### 8 Indicator Buffers
1. **BUY_SIGNAL** (Buffer 0): Price level for buy entry (up arrow)
2. **SELL_SIGNAL** (Buffer 1): Price level for sell entry (down arrow)
3. **BUY_SL** (Buffer 2): Stop Loss level for buy positions (from base low)
4. **SELL_SL** (Buffer 3): Stop Loss level for sell positions (from base high)
5. **BUY_TP** (Buffer 4): Take Profit level for buy positions (EMA 600)
6. **SELL_TP** (Buffer 5): Take Profit level for sell positions (EMA 600)
7. **BUY_STATE** (Buffer 6): Current buy state (0-3) for EA consumption
8. **SELL_STATE** (Buffer 7): Current sell state (0-3) for EA consumption
### Input Parameters
#### EMA Settings
- **EMA 50 Period**: Fast EMA period (default: 50)
- **EMA 100 Period**: Medium-fast EMA period (default: 100)
- **EMA 200 Period**: Medium EMA period (default: 200)
- **EMA 300 Period**: Medium-slow EMA period (default: 300)
- **EMA 400 Period**: Slow EMA period (default: 400)
- **EMA 500 Period**: Very slow EMA period (default: 500)
- **EMA 600 Period**: Target EMA for TP (default: 600)
#### Setup Settings
- **Lookback Period**: Bars to look back for base detection (default: 20)
- **Base Threshold**: Points tolerance for pullback to base (default: 50)
- **State Reset Period**: Bars before resetting state if no signal (default: 50)
#### Display Settings
- **Show Dashboard**: Toggle dashboard display (default: true)
- **Show Stage Labels**: Toggle stage label display (default: true)
- **Show EMA Lines**: Toggle EMA lines display (default: true)
## Logic Workflow
### Buy Side State Machine (Looking for reversal up to EMA 600)
#### State 0: Idle/Reset
- Waiting for new low formation
#### State 1: Find Base
- Price makes new low in `InpLookback` bars (at frist install then use last signal as a start of lookback)
- Store `BaseLow = Low[i]`
- Transition to State 2
#### State 2: Confirm Test
- Price touches or crosses EMA 50, 100, or 200 from below
- Wait for pullback opportunity
- Transition to State 3
#### State 3: Wait Pullback
- Price pulls back to `BaseLow` within `InpBaseThreshold` points
- Generate buy signal at current close
- Set SL at `BaseLow`
- Set TP at EMA 600
- Reset to State 0
### Sell Side State Machine (Looking for reversal down to EMA 600)
#### State 0: Idle/Reset
- Waiting for new high formation
#### State 1: Find Base
- Price makes new high in `InpLookback` bars (at frist install then use last signal as a start of lookback)
- Store `BaseHigh = High[i]`
- Transition to State 2
#### State 2: Confirm Test
- Price touches or crosses EMA 50, 100, or 200 from above
- Wait for bounce back opportunity
- Transition to State 3
#### State 3: Wait Pullback
- Price bounces back to `BaseHigh` within `InpBaseThreshold` points
- Generate sell signal at current close
- Set SL at `BaseHigh`
- Set TP at EMA 600
- Reset to State 0
## Visual Elements
### Color Scheme
- **EMA 50**: Red
- **EMA 100**: Orange
- **EMA 200**: Yellow
- **EMA 300**: Green
- **EMA 400**: Blue
- **EMA 500**: Purple
- **EMA 600**: Magenta
- **Buy Signals**: Lime green arrows (↑)
- **Sell Signals**: Red arrows (↓)
- **SL Lines**: Gray dashed lines
- **TP Lines**: Blue dotted lines
- **Stage Labels**: Color-coded by state
### Stage Labels
Located in top-right corner, shows:
- Current buy stage with colored background
- Current sell stage with colored background
- State descriptions for active states
## State Descriptions
| State | Value | Description | Color |
|-------|-------|-------------|-------|
| Idle/Reset | 0 | Waiting for setup | Gray |
| Finding Base | 1 | Looking for new high/low | Blue |
| Confirm Test | 2 | EMA touch/cross detected | Orange |
| Wait Pullback | 3 | Waiting for pullback to base | Green |
### For EA Developers
The indicator provides two key buffers for automated trading systems:
- `BUY_STATE_BUFFER` (6): Current buy state (0-3)
- `SELL_STATE_BUFFER` (7): Current sell state (0-3)
These buffers can be accessed programmatically to:
- Monitor setup progression
- Trigger automated entries at State 3
- Implement custom risk management
- Build multi-timeframe strategies
## Technical Details
### Buffer Configuration
```mql5
#property indicator_buffers 8
#property indicator_plots 6
```
### Performance Considerations
- Uses iMA() handles for efficient EMA calculation
- Implements series arrays for optimal memory usage
- Minimal repainting - signals generated on bar close
- Efficient object management for dashboard and labels
### Error Handling
- Validates EMA handle creation
- Checks array bounds before access
- Graceful cleanup on deinitialization
- Proper series array management

372
EMA Indi/USER_GUIDE.md Normal file
View File

@@ -0,0 +1,372 @@
# Base EMA Reversal Indicator - User Guide
**Version**: 1.0
**Date**: 2025-01-22
**File**: Base_EMA_Reversal.mq5
---
## 📋 Overview
The Base EMA Reversal Indicator identifies potential reversal opportunities using a multi-stage state machine approach with EMA confluence. The indicator tracks both buy and sell opportunities through base formation, EMA confirmation, and pullback detection.
---
## 🎯 Strategy Logic
### Core Concept
When price touches EMA (50/100/200), TWO possible outcomes:
1. **Pullback**: Price revisits previous high/low → SIGNAL
2. **Breakthrough**: Price makes new high/low → Continue watching
### State Machine (States 0-3)
#### Buy Side
- **State 0**: Startup/Reset (only at initialization)
- **State 1**: Finding Base - Track lowest price continuously
- **State 2**: EMA Touched - Price closed ABOVE EMA 50/100/200
- **State 3**: Decision/Signal - Within 2 bars of EMA touch
- Pullback to BaseLow (within 50 points) → **BUY SIGNAL**
- Cross EMA below again → Cancel, back to State 1
#### Sell Side (Mirror of Buy Side)
- **State 0**: Startup/Reset (only at initialization)
- **State 1**: Finding Base - Track highest price continuously
- **State 2**: EMA Touched - Price closed BELOW EMA 50/100/200
- **State 3**: Decision/Signal - Within 2 bars of EMA touch
- Pullback to BaseHigh (within 50 points) → **SELL SIGNAL**
- Cross EMA above again → Cancel, back to State 1
### TP Selection Logic
- **Buy Signals**: Find LOWEST valid EMA ABOVE price from [300, 400, 500, 600]
- **Sell Signals**: Find HIGHEST valid EMA BELOW price from [300, 400, 500, 600]
- **ATR Fallback**: If no valid EMA position, use ATR × 2
---
## 📊 Buffer Structure (8 Buffers)
| Index | Buffer Name | Purpose | Value Type | When Populated |
|-------|-------------|---------|------------|----------------|
| 0 | BUY_SIGNAL | Buy entry price | Price | Signal bars only |
| 1 | SELL_SIGNAL | Sell entry price | Price | Signal bars only |
| 2 | BUY_SL | Buy stop loss | Price (BaseLow) | Signal bars only |
| 3 | SELL_SL | Sell stop loss | Price (BaseHigh) | Signal bars only |
| 4 | BUY_TP | Buy take profit | Price (EMA or ATR) | Signal bars only |
| 5 | SELL_TP | Sell take profit | Price (EMA or ATR) | Signal bars only |
| 6 | BUY_STATE | Buy state tracker | 0-3 | Every bar |
| 7 | SELL_STATE | Sell state tracker | 0-3 | Every bar |
**Important**: Signal buffers (0-5) = EMPTY_VALUE when not applicable. EA will check for non-EMPTY_VALUE to detect signals.
---
## ⚙️ Input Parameters
### EMA Settings
| Parameter | Default | Description |
|-----------|----------|-------------|
| EMA 50 Period | 50 | Fast EMA (confirmation) |
| EMA 100 Period | 100 | Medium-fast EMA (confirmation) |
| EMA 200 Period | 200 | Medium EMA (confirmation) |
| EMA 300 Period | 300 | TP1 target |
| EMA 400 Period | 400 | TP2 target |
| EMA 500 Period | 500 | TP3 target |
| EMA 600 Period | 600 | TP4 target |
### Setup Settings
| Parameter | Default | Description |
|-----------|----------|-------------|
| Lookback Period | 100 | Bars for initial base detection |
| Base Threshold | 50 | Pullback tolerance (points) |
| Pullback Bars | 2 | Max bars to wait for pullback |
| Skip Bars | 50 | Bars skipped at startup |
### ATR Settings
| Parameter | Default | Description |
|-----------|----------|-------------|
| ATR Period | 14 | ATR period for TP fallback |
### Display Settings
| Parameter | Default | Description |
|-----------|----------|-------------|
| Show Stage Labels | true | Display state labels on chart |
---
## 🚀 Installation
### Step 1: Copy Files to MetaTrader 5
1. Navigate to your MetaTrader 5 data folder:
- **Windows**: `C:\Users\{Username}\AppData\Roaming\MetaQuotes\Terminal\{TerminalID}\MQL5\`
- **Mac**: Open MetaTrader 5 → File → Open Data Folder
2. Copy `Base_EMA_Reversal.mq5` to: `MQL5/Indicators/`
### Step 2: Compile the Indicator
1. Open MetaEditor 5 (press F4 in MetaTrader 5)
2. File → Open → Select `Base_EMA_Reversal.mq5`
3. Press F7 or click "Compile"
4. Verify **0 errors** in "Errors" tab (warnings are OK)
5. Close MetaEditor 5
### Step 3: Install Indicator on Chart
1. In MetaTrader 5, right-click on "Navigator" → "Refresh"
2. Drag `Base EMA Reversal` from Navigator → Indicators to EURUSD H1 chart
3. Configure parameters if needed
4. Click OK
### Step 4: Enable Visual Elements
Ensure you can see:
-**7 EMA lines** (Red, Orange, Yellow, Green, Blue, Purple, Magenta)
-**Stage labels** "B:X S:Y" on each bar (color-coded)
-**Buy signals** (Lime ↑ arrows)
-**Sell signals** (Red ↓ arrows)
-**SL markers** (Gray dots)
-**TP markers** (Blue +)
---
## 🎨 Visual Elements
### EMA Lines (7 EMAs) - NOW VISIBLE!
- **EMA 50**: Red (Plot 7)
- **EMA 100**: Orange (Plot 8)
- **EMA 200**: Yellow (Plot 9)
- **EMA 300**: Green (Plot 10)
- **EMA 400**: Blue (Plot 11)
- **EMA 500**: Purple (Plot 12)
- **EMA 600**: Magenta (Plot 13)
### Signal Arrows
- **Buy Signal**: Arrow code 233 (↑), Lime color
- **Sell Signal**: Arrow code 234 (↓), Red color
### Signal Labels (Only on Signal Bars - Large Font)
- **Buy Signal Labels**: "BUY SIGNAL" - Lime color, Font Size 14
- **Sell Signal Labels**: "SELL SIGNAL" - Red color, Font Size 14
- **No labels on non-signal bars** (reduced clutter)
### SL/TP Markers
- **SL**: Gray dot (code 159)
- **TP**: Blue plus sign (code 160)
---
## 🔧 Integration with Universal Buffer Reader EA
### EA Configuration
Configure the Universal Buffer Reader EA with these parameters:
| EA Parameter | Value |
|-------------|--------|
| IndicatorName | "Base_EMA_Reversal" |
| BuySignalBuffer | 0 |
| SellSignalBuffer | 1 |
| BuySLBuffer | 2 |
| SellSLBuffer | 3 |
| SellSLBuffer | 6 |
| BuyTPBuffer | 4 |
| SellTPBuffer | 5 |
### How EA Reads Signals
The EA's `SignalDetector.mqh` checks:
```mql5
bool has_buy = (buy_signal != EMPTY_VALUE && buy_signal != 0);
bool has_sell = (sell_signal != EMPTY_VALUE && sell_signal != 0);
```
Our indicator:
- Sets **signal price** when signal occurs at bar close
- Sets **EMPTY_VALUE** on all other bars
- EA will only execute trades when buffers have valid values
---
## 🧪 Testing Recommendations
### 1. Demo Account Testing (REQUIRED)
**Always test on a demo account first!**
- Test for at least 1-2 weeks
- Monitor all trades closely
- Check all features are working:
- EMA touch detection
- Pullback identification
- Signal generation
- SL/TP levels
- State transitions
- ATR fallback
### 2. Visual Verification
On EURUSD H1 chart:
1. Check EMA lines are smooth and correct colors
2. Verify stage labels change colors as states progress
3. Watch for signal arrows at appropriate locations
4. Monitor Experts tab for signal print messages
### 3. Backtesting
1. Open Strategy Tester (press F4 or View → Strategy Tester)
2. Select `Base EMA Reversal`
3. Select symbol (EURUSD) and timeframe (H1)
4. Select test period (last 6 months recommended)
5. Click "Start"
6. Review results:
- Signal frequency
- Win rate
- Risk/reward ratio
- ATR fallback usage
### 4. Forward Testing
After successful backtesting:
- Test on demo account with live data
- Monitor for 2-4 weeks
- Compare results with backtest
- Adjust parameters if needed
---
## 📊 Monitoring and Analysis
### Experts Tab
Watch for these messages:
- `BUY SIGNAL at [timestamp] Price: [price] SL: [sl] TP: [tp]`
- `SELL SIGNAL at [timestamp] Price: [price] SL: [sl] TP: [tp]`
- `Initialization: BaseLow = [value], BaseHigh = [value]`
- `BaseLow recalculated: [value] after buy signal`
- `BaseHigh recalculated: [value] after sell signal`
### Signal Quality Indicators
Monitor:
- **State Transitions**: Should flow smoothly 1 → 2 → 3 → 1
- **Timeout Frequency**: How often signals cancel due to timeout?
- **Pullback Success Rate**: What % of EMA touches result in signals?
- **ATR Fallback Usage**: How often is TP calculated via ATR?
---
## ⚠️ Common Issues and Solutions
### Issue: No Signals Appearing
**Symptoms**: Indicator loads but no arrows appear
**Solutions**:
1. Check minimum data requirement (need 600+ bars)
2. Verify EMA touch detection is working (watch Experts tab)
3. Confirm base levels are updating (check print messages)
4. Increase Lookback Period parameter
### Issue: Too Many False Signals
**Symptoms**: Signals appearing frequently but price doesn't reverse
**Solutions**:
1. Increase Base Threshold (from 50 to 100+)
2. Reduce Pullback Bars (from 2 to 1)
3. Add additional confirmation logic (e.g., close above EMA for 2 bars)
### Issue: Stage Labels Too Cluttered
**Symptoms**: Chart difficult to read due to too many labels
**Solutions**:
1. Set `Show Stage Labels = false` to disable
2. Use smaller timeframe (H4 instead of M15)
3. Filter by state (only show State 2-3 labels)
### Issue: EA Not Executing Trades
**Symptoms**: Universal Buffer Reader EA sees indicator but no trades
**Solutions**:
1. Verify EA parameters match buffer indices (0-5)
2. Check AutoTrading is enabled (green button)
3. Verify EA has permission to trade
4. Enable debug prints in EA to see signal detection
---
## 🔒 Risk Management
### Important Considerations
1. **No Stop Loss Warning**: If SL hits immediately, BaseLow/High may be too close to entry
2. **TP Verification**: If EMA TP seems unrealistic, ATR fallback will activate
3. **Pullback Window**: 2 bars is narrow - may miss valid setups
4. **Base Threshold**: 50 points may be too tight for volatile symbols
### Recommended Settings by Symbol
| Symbol | Base Threshold | Pullback Bars |
|--------|---------------|----------------|
| EURUSD (Majors) | 30-50 | 2 |
| GBPUSD (Volatile) | 50-80 | 2-3 |
| XAUUSD (Gold) | 100-200 | 3 |
| Crypto (BTC/ETH) | 200-500 | 5 |
---
## 📝 Code Summary
### File Statistics
- **Lines**: 641
- **Functions**: 7 (OnInit, OnDeinit, OnCalculate, CalculateBuyTP, CalculateSellTP, RecalculateBaseBuy, RecalculateBaseSell, UpdateStageLabels)
- **State Variables**: 9 (buy_state, sell_state, BaseLow, BaseHigh, last_signal_time, buy_ema_touched, sell_ema_touched, ema_touch_bar, buy_touch_ema_count, sell_touch_ema_count)
- **Indicator Handles**: 8 (7 EMAs + 1 ATR)
### Key Logic Patterns
- Array indexing: Series (index 0 = current bar)
- State machine: Event-driven (EMA touch → Decision → Reset)
- Buffer clearing: EMPTY_VALUE on non-signal bars
- Object management: Unique prefix "EMA_Stage_"
---
## 🎓 Next Steps
After initial testing:
1.**Optimize Parameters**: Use Strategy Tester to find optimal values
2.**Add Filters**: Consider time filters, trend filters
3.**Multi-Timeframe**: Test on H4, D1 timeframes
4.**Performance Tuning**: Reduce object count for faster chart
5.**Backtest Extensively**: 6-12 months of data minimum
---
## 📞 Getting Help
### Debug Mode
If experiencing issues, enable `InpShowStageLabels = false` to reduce visual clutter and check Experts tab for print messages.
### Print Messages
Key messages to watch:
- Initialization messages
- Signal generation messages
- Base recalculation messages
- Any error messages
### Log Analysis
Review Strategy Tester logs to:
- Count total signals
- Analyze win/loss ratio
- Check SL/TP effectiveness
- Identify best performing timeframes
---
**Last Updated**: 2025-01-22
**Version**: 1.0
**Happy Trading! 📈**