feat(maea): migrate from MQL4 to MQL5 and simplify strategy
Migrate MAEA Expert Advisor from MetaTrader 4 to MetaTrader 5 platform with significant strategy simplification and architectural improvements. Key changes: - Platform: MQL4 → MQL5 - Indicators: Reduced from 5 lines (3 EMAs + 2 borders) to 2 EMAs with zone fill - Strategy: Removed pullback signals and dynamic lot sizing - Lot sizing: Changed from dynamic (0.01/0.02) to fixed 0.01 lot - Stop loss: Changed from Border Lines to opposite EMA (Buy: EMA Low, Sell: EMA High) - Signal logic: Added opposite signal close for reversal protection - New filter: Added minimum zone width filter (100 points) - Documentation: Updated implementation plans and project summary - New files: Added AGENTS.md, MAEA_Indicator.mq5, and opencode.jsonc BREAKING CHANGE: Complete rewrite from MQL4 to MQL5 with simplified strategy. Previous MAEA.mq4 and README.md deleted. New implementation requires MetaTrader 5.
This commit is contained in:
162
AGENTS.md
Normal file
162
AGENTS.md
Normal file
@@ -0,0 +1,162 @@
|
||||
# MAEA Development Guidelines
|
||||
|
||||
## Build and Test Commands
|
||||
|
||||
### Compilation
|
||||
- Use MetaEditor (MT5 built-in editor) to compile the EA
|
||||
- Press F7 or click Compile button in MetaEditor
|
||||
- Check "Errors" tab in Toolbox for compilation issues
|
||||
- All MQL5 files must compile with 0 errors before testing
|
||||
|
||||
### Testing
|
||||
- Use MT5 Strategy Tester (Ctrl+T or View → Strategy Tester)
|
||||
- Select "MAEA" from Expert Advisor dropdown
|
||||
- Set testing parameters:
|
||||
- Symbol: Desired currency pair
|
||||
- Model: "Every tick" for accurate testing
|
||||
- Period: H1 (recommended timeframe)
|
||||
- Spread: Use current or specify fixed value
|
||||
- Run single test: Click Start button in Strategy Tester
|
||||
- Run optimization: Enable Genetic Algorithm or slow complete algorithm
|
||||
- Optimization criteria: Balance, Profit Factor, Drawdown, or Sharpe Ratio
|
||||
|
||||
### Key Testing Scenarios
|
||||
- Test EMA calculations accuracy by comparing with manual calculations
|
||||
- Test breakthrough signals on historical data
|
||||
- Test pullback detection on ranging markets
|
||||
- Test all filters individually (enable one at a time)
|
||||
- Test risk management (TP, SL, breakeven, trailing stop)
|
||||
- Test max drawdown protection with aggressive parameters
|
||||
|
||||
## Code Style Guidelines
|
||||
|
||||
### File Naming and Organization
|
||||
- EA file: `MAEA.mq5` (root directory)
|
||||
- Use #include for external functions if needed
|
||||
- Keep single file structure preferred for portability
|
||||
|
||||
### Naming Conventions
|
||||
- **Input parameters**: PascalCase (e.g., `EMAPeriod`, `LotSizeNormal`, `TakeProfitUSD`)
|
||||
- **Global variables**: g_PascalCase (e.g., `g_EMAHighBuffer`, `g_PullbackBuyDetected`)
|
||||
- **Local variables**: camelCase (e.g., `currentClose`, `signalDetected`)
|
||||
- **Functions**: PascalCase (e.g., `CalculateEMA()`, `CheckFilters()`, `OpenOrder()`)
|
||||
- **Constants**: UPPER_CASE with underscore prefix (e.g., `_MAX_ORDERS`, `_DEFAULT_TP`)
|
||||
|
||||
### Imports and Includes
|
||||
- MQL5 standard headers:
|
||||
```mql5
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Indicators\Indicators.mqh>
|
||||
#include <Arrays\ArrayDouble.mqh>
|
||||
```
|
||||
(Required for MT5 position management and indicator handling)
|
||||
- Use MT5 standard functions and objects:
|
||||
- CTrade class for position operations
|
||||
- Indicator handles via iMA()
|
||||
- Position operations: PositionSelect(), PositionGetSymbol()
|
||||
- Use <Trade\Trade.mqh> as it's essential for MT5 trading operations
|
||||
|
||||
### Code Formatting
|
||||
- Indentation: 4 spaces (no tabs)
|
||||
- Braces: K&R style (opening brace on same line)
|
||||
- Line length: Max 120 characters
|
||||
- Blank line between functions
|
||||
- Comment section headers like `// === INDICATOR CALCULATIONS ===`
|
||||
|
||||
### Variable Types
|
||||
- Use explicit types, not auto
|
||||
- Integer counts: `int`
|
||||
- Prices and averages: `double`
|
||||
- Boolean flags: `bool`
|
||||
- Time values: `datetime`
|
||||
- Array buffers: `double[]`
|
||||
- String values: `string`
|
||||
|
||||
### Error Handling
|
||||
- Always check return values for:
|
||||
- CTrade.OrderOpen() - check return value
|
||||
- CTrade.PositionModify() - check return value
|
||||
- CTrade.PositionClose() - check return value
|
||||
- Indicator handle creation - check if handle != INVALID_HANDLE
|
||||
- ObjectCreate() - check return value
|
||||
- Use GetLastError() after failed operations
|
||||
- Log errors using Print() or Alert() for critical issues
|
||||
- Example:
|
||||
```mql5
|
||||
CTrade trade;
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
if(!trade.Buy(lotSize, Symbol(), price, sl, tp)) {
|
||||
int err = GetLastError();
|
||||
Print("OrderOpen failed. Error: ", err, " - ", ErrorDescription(err));
|
||||
return;
|
||||
}
|
||||
```
|
||||
|
||||
### Input Parameters Structure
|
||||
- Group related parameters together
|
||||
- Use clear, descriptive comments
|
||||
- Example format:
|
||||
```mql5
|
||||
// === EMA SETTINGS ===
|
||||
input int EMAPeriod = 30; // EMA period for all indicator lines
|
||||
|
||||
// === RISK MANAGEMENT ===
|
||||
input double TakeProfitUSD = 5.0; // Take profit target in USD
|
||||
input int BreakevenPoints = 100; // Points to trigger breakeven
|
||||
|
||||
// === FILTERS ===
|
||||
input bool UseMTFFilter = true; // Enable MTF filter
|
||||
input int MaxSpread = 30; // Maximum spread in points
|
||||
```
|
||||
|
||||
### Function Design
|
||||
- Keep functions focused and under 40 lines if possible
|
||||
- Use descriptive parameter names
|
||||
- Return meaningful values (bool for success/failure when applicable)
|
||||
- Document complex logic with inline comments
|
||||
- Separate calculation logic from trading logic
|
||||
|
||||
### Timezone Handling
|
||||
- All time-based logic uses Thailand timezone (UTC+7)
|
||||
- Use TimeGMT() + 25200 seconds for Thailand time
|
||||
- Convert server time to Thailand time for news filter checks
|
||||
- Document timezone conversions explicitly in code
|
||||
|
||||
### Testing Best Practices
|
||||
- Use MT5 Strategy Tester with "Every tick" model
|
||||
- Test on multiple currency pairs (EURUSD, GBPUSD, XAUUSD)
|
||||
- Test on different timeframes (M15, H1, H4)
|
||||
- Verify indicators by visual inspection in tester
|
||||
- Check both profitable and losing scenarios
|
||||
- Validate filter logic by comparing tester results with expected behavior
|
||||
- Paper trade on demo account before live trading
|
||||
|
||||
### Safety Constraints
|
||||
- Never change code to bypass risk management
|
||||
- Test all parameter changes in Strategy Tester first
|
||||
- Ensure only one position can be open at a time (MT5 uses positions, not orders)
|
||||
- Drawdown protection must be always active
|
||||
- Stop Loss must always be set when opening positions
|
||||
- Verify position count using PositionsTotal() and filter by MagicNumber
|
||||
|
||||
### Code Comments
|
||||
- Comment complex calculations (especially EMA and Border Line formulas)
|
||||
- Document edge cases and special conditions
|
||||
- Include formula explanations: `// Border Line = EMA High + (EMA Medium - EMA Low)`
|
||||
- No excessive comments for obvious code
|
||||
|
||||
### Trading Logic Organization
|
||||
- Typical entry points: OnTick() (per tick) or OnNewBar() (on new candle)
|
||||
- Structure: Indicators → Filters → Signals → Orders → Risk Management
|
||||
- Use state variables to track:
|
||||
- Pullback detection (buy and sell separately)
|
||||
- Current drawdown
|
||||
- Last bar time for new bar detection
|
||||
- Order tracking for management
|
||||
|
||||
### Git Practices
|
||||
- Commit after implementing each phase from the implementation plan
|
||||
- Commit message format: "Phase X: Title - Brief description"
|
||||
- Verify compilation before committing
|
||||
- Test major features before committing
|
||||
- Pull latest changes before starting new work
|
||||
698
MAEA.mq4
698
MAEA.mq4
@@ -1,698 +0,0 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MAEA.mq4 |
|
||||
//| Moving Average Expert Advisor |
|
||||
//| Advanced Trend-Following Strategy |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "MAEA"
|
||||
#property link "https://git.moreminimore.com/kunthawat/MAEA"
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 5
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Input Parameters |
|
||||
//+------------------------------------------------------------------+
|
||||
input string Section1 = "=== EMA Settings ===";
|
||||
input int EMAPeriod = 30; // EMA Period for all lines
|
||||
|
||||
input string Section2 = "=== Lot Settings ===";
|
||||
input double LotSizeNormal = 0.01; // Lot size without pullback
|
||||
input double LotSizePullback = 0.02; // Lot size with pullback
|
||||
|
||||
input string Section3 = "=== Risk Management ===";
|
||||
input double TakeProfitUSD = 5.0; // Take Profit target in USD
|
||||
input int BreakevenPoints = 100; // Points to trigger breakeven
|
||||
input int TrailingStopPoints = 100; // Trailing stop distance
|
||||
input double MaxDrawdownPercent = 10.0;// Max drawdown percentage
|
||||
|
||||
input string Section4 = "=== Filters ===";
|
||||
input int MaxSpread = 30; // Maximum allowed spread in points
|
||||
input int VolumePeriod = 20; // Period for volume average
|
||||
input bool UseMTFFilter = true; // Enable MTF filter
|
||||
input bool UseNewsFilter = true; // Enable news filter
|
||||
input string NewsAvoidHours = "14,15,20,21"; // Hours to avoid (Thailand time)
|
||||
input string NewsAvoidDays = "1,5"; // Days to avoid (Monday=1, Friday=5)
|
||||
|
||||
input string Section5 = "=== General ===";
|
||||
input int MagicNumber = 12345; // EA unique identifier
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Global Variables |
|
||||
//+------------------------------------------------------------------+
|
||||
// Indicator buffers
|
||||
double EMAHighBuffer[];
|
||||
double EMAMediumBuffer[];
|
||||
double EMALowBuffer[];
|
||||
double HighBorderBuffer[];
|
||||
double LowBorderBuffer[];
|
||||
|
||||
// State tracking
|
||||
bool PullbackBuy = false;
|
||||
bool PullbackSell = false;
|
||||
bool BreakevenTriggered = false;
|
||||
double OrderOpenPrice = 0;
|
||||
double OrderStopLoss = 0;
|
||||
double OrderTakeProfit = 0;
|
||||
int OrderTicket = 0;
|
||||
|
||||
// Drawdown tracking
|
||||
double AccountEquityPeak = 0;
|
||||
|
||||
// Previous bar values for signal detection
|
||||
double PrevClose = 0;
|
||||
double PrevEMAHigh = 0;
|
||||
double PrevEMAMedium = 0;
|
||||
double PrevEMALow = 0;
|
||||
|
||||
// News filter arrays
|
||||
int AvoidHoursArray[];
|
||||
int AvoidDaysArray[];
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
// Set indicator buffers
|
||||
SetIndexBuffer(0, EMAHighBuffer);
|
||||
SetIndexBuffer(1, EMAMediumBuffer);
|
||||
SetIndexBuffer(2, EMALowBuffer);
|
||||
SetIndexBuffer(3, HighBorderBuffer);
|
||||
SetIndexBuffer(4, LowBorderBuffer);
|
||||
|
||||
// Set indicator labels
|
||||
SetIndexLabel(0, "EMA High");
|
||||
SetIndexLabel(1, "EMA Medium");
|
||||
SetIndexLabel(2, "EMA Low");
|
||||
SetIndexLabel(3, "High Border");
|
||||
SetIndexLabel(4, "Low Border");
|
||||
|
||||
// Set indicator styles
|
||||
SetIndexStyle(0, DRAW_LINE, STYLE_SOLID, 2, clrLightBlue);
|
||||
SetIndexStyle(1, DRAW_LINE, STYLE_SOLID, 2, clrYellow);
|
||||
SetIndexStyle(2, DRAW_LINE, STYLE_SOLID, 2, clrOrange);
|
||||
SetIndexStyle(3, DRAW_LINE, STYLE_DASH, 1, clrPurple);
|
||||
SetIndexStyle(4, DRAW_LINE, STYLE_DASH, 1, clrPurple);
|
||||
|
||||
// Parse news filter arrays
|
||||
ParseNewsFilterArrays();
|
||||
|
||||
// Initialize account equity peak
|
||||
AccountEquityPeak = AccountEquity();
|
||||
|
||||
Print("MAEA initialized successfully");
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
Print("MAEA deinitialized");
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
// Check for minimum bars
|
||||
if(rates_total < EMAPeriod + 1) return(0);
|
||||
|
||||
// Set arrays as series
|
||||
ArraySetAsSeries(EMAHighBuffer, false);
|
||||
ArraySetAsSeries(EMAMediumBuffer, false);
|
||||
ArraySetAsSeries(EMALowBuffer, false);
|
||||
ArraySetAsSeries(HighBorderBuffer, false);
|
||||
ArraySetAsSeries(LowBorderBuffer, false);
|
||||
|
||||
// Calculate start position
|
||||
int start;
|
||||
if(prev_calculated == 0)
|
||||
{
|
||||
start = EMAPeriod;
|
||||
// Initialize buffers
|
||||
for(int i = 0; i < start; i++)
|
||||
{
|
||||
EMAHighBuffer[i] = 0;
|
||||
EMAMediumBuffer[i] = 0;
|
||||
EMALowBuffer[i] = 0;
|
||||
HighBorderBuffer[i] = 0;
|
||||
LowBorderBuffer[i] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
start = prev_calculated - 1;
|
||||
}
|
||||
|
||||
// Calculate EMA values and border lines
|
||||
for(int i = start; i < rates_total; i++)
|
||||
{
|
||||
// Get EMA values using iMA function (MQL4 style)
|
||||
double emaHigh = iMA(Symbol(), PERIOD_CURRENT, EMAPeriod, 0, MODE_EMA, PRICE_HIGH, i);
|
||||
double emaMedium = iMA(Symbol(), PERIOD_CURRENT, EMAPeriod, 0, MODE_EMA, PRICE_CLOSE, i);
|
||||
double emaLow = iMA(Symbol(), PERIOD_CURRENT, EMAPeriod, 0, MODE_EMA, PRICE_LOW, i);
|
||||
|
||||
// Calculate range
|
||||
double range = emaMedium - emaLow;
|
||||
|
||||
// Calculate border lines
|
||||
double highBorder = emaHigh + range;
|
||||
double lowBorder = emaLow - range;
|
||||
|
||||
// Store values in buffers
|
||||
EMAHighBuffer[i] = emaHigh;
|
||||
EMAMediumBuffer[i] = emaMedium;
|
||||
EMALowBuffer[i] = emaLow;
|
||||
HighBorderBuffer[i] = highBorder;
|
||||
LowBorderBuffer[i] = lowBorder;
|
||||
}
|
||||
|
||||
// Only process trading logic on new bar
|
||||
static datetime lastBarTime = 0;
|
||||
if(time[rates_total - 1] != lastBarTime)
|
||||
{
|
||||
lastBarTime = time[rates_total - 1];
|
||||
|
||||
// Update previous bar values
|
||||
int lastBar = rates_total - 1;
|
||||
int prevBar = rates_total - 2;
|
||||
|
||||
if(prevBar >= EMAPeriod)
|
||||
{
|
||||
PrevClose = close[prevBar];
|
||||
PrevEMAHigh = EMAHighBuffer[prevBar];
|
||||
PrevEMAMedium = EMAMediumBuffer[prevBar];
|
||||
PrevEMALow = EMALowBuffer[prevBar];
|
||||
|
||||
// Process trading logic
|
||||
ProcessTradingLogic(rates_total, time, open, high, low, close, tick_volume, spread);
|
||||
}
|
||||
}
|
||||
|
||||
// Manage open orders on every tick
|
||||
ManageOpenOrders();
|
||||
|
||||
return(rates_total);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get EMA value from handle |
|
||||
//+------------------------------------------------------------------+
|
||||
double GetEMAValue(int timeframe, int applied_price, int shift)
|
||||
{
|
||||
return iMA(Symbol(), timeframe, EMAPeriod, 0, MODE_EMA, applied_price, shift);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Parse news filter arrays |
|
||||
//+------------------------------------------------------------------+
|
||||
void ParseNewsFilterArrays()
|
||||
{
|
||||
// Parse hours
|
||||
string hoursStr = NewsAvoidHours;
|
||||
ArrayResize(AvoidHoursArray, 0);
|
||||
while(hoursStr != "")
|
||||
{
|
||||
int pos = StringFind(hoursStr, ",");
|
||||
string hourStr;
|
||||
if(pos >= 0)
|
||||
{
|
||||
hourStr = StringSubstr(hoursStr, 0, pos);
|
||||
hoursStr = StringSubstr(hoursStr, pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
hourStr = hoursStr;
|
||||
hoursStr = "";
|
||||
}
|
||||
StringTrimLeft(hourStr);
|
||||
StringTrimRight(hourStr);
|
||||
if(hourStr != "")
|
||||
{
|
||||
int hour = (int)StringToInteger(hourStr);
|
||||
int size = ArraySize(AvoidHoursArray);
|
||||
ArrayResize(AvoidHoursArray, size + 1);
|
||||
AvoidHoursArray[size] = hour;
|
||||
}
|
||||
}
|
||||
|
||||
// Parse days
|
||||
string daysStr = NewsAvoidDays;
|
||||
ArrayResize(AvoidDaysArray, 0);
|
||||
while(daysStr != "")
|
||||
{
|
||||
int pos = StringFind(daysStr, ",");
|
||||
string dayStr;
|
||||
if(pos >= 0)
|
||||
{
|
||||
dayStr = StringSubstr(daysStr, 0, pos);
|
||||
daysStr = StringSubstr(daysStr, pos + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
dayStr = daysStr;
|
||||
daysStr = "";
|
||||
}
|
||||
StringTrimLeft(dayStr);
|
||||
StringTrimRight(dayStr);
|
||||
if(dayStr != "")
|
||||
{
|
||||
int day = (int)StringToInteger(dayStr);
|
||||
int size = ArraySize(AvoidDaysArray);
|
||||
ArrayResize(AvoidDaysArray, size + 1);
|
||||
AvoidDaysArray[size] = day;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Process trading logic |
|
||||
//+------------------------------------------------------------------+
|
||||
void ProcessTradingLogic(const int rates_total,
|
||||
const datetime &time[],
|
||||
const double &open[],
|
||||
const double &high[],
|
||||
const double &low[],
|
||||
const double &close[],
|
||||
const long &tick_volume[],
|
||||
const int &spread[])
|
||||
{
|
||||
// Check if we have an open order
|
||||
if(HasOpenOrder()) return;
|
||||
|
||||
// Check drawdown
|
||||
if(!CheckDrawdown()) return;
|
||||
|
||||
// Check news filter
|
||||
if(UseNewsFilter && !CheckNewsFilter(time[rates_total - 1])) return;
|
||||
|
||||
// Check spread filter
|
||||
if(spread[rates_total - 1] > MaxSpread) return;
|
||||
|
||||
// Check volume filter
|
||||
if(!CheckVolumeFilter(tick_volume, rates_total)) return;
|
||||
|
||||
// Check MTF filter
|
||||
if(UseMTFFilter && !CheckMTFFilter()) return;
|
||||
|
||||
// Get current values
|
||||
int lastBar = rates_total - 1;
|
||||
double currentClose = close[lastBar];
|
||||
double currentEMAHigh = EMAHighBuffer[lastBar];
|
||||
double currentEMALow = EMALowBuffer[lastBar];
|
||||
|
||||
// Detect pullback signals
|
||||
DetectPullbackSignals(currentClose, currentEMAHigh, PrevEMAHigh, currentEMALow, PrevEMALow, PrevEMAMedium);
|
||||
|
||||
// Detect breakthrough signals
|
||||
if(DetectBreakthroughBuy(currentClose, currentEMAHigh, PrevClose, PrevEMAHigh))
|
||||
{
|
||||
OpenBuyOrder();
|
||||
}
|
||||
else if(DetectBreakthroughSell(currentClose, currentEMALow, PrevClose, PrevEMALow))
|
||||
{
|
||||
OpenSellOrder();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detect pullback signals |
|
||||
//+------------------------------------------------------------------+
|
||||
void DetectPullbackSignals(double currentClose, double currentEMAHigh, double prevEMAHigh,
|
||||
double currentEMALow, double prevEMALow, double prevEMAMedium)
|
||||
{
|
||||
// Buy pullback: price moved down to hit a line, then closed above it
|
||||
if(PrevClose < prevEMAMedium && currentClose > currentEMALow)
|
||||
{
|
||||
PullbackBuy = true;
|
||||
}
|
||||
else if(PrevClose < prevEMALow && currentClose > currentEMALow)
|
||||
{
|
||||
PullbackBuy = true;
|
||||
}
|
||||
else if(PrevClose < prevEMAHigh && currentClose > currentEMAHigh)
|
||||
{
|
||||
PullbackBuy = true;
|
||||
}
|
||||
|
||||
// Sell pullback: price moved up to hit a line, then closed below it
|
||||
if(PrevClose > prevEMAMedium && currentClose < currentEMAHigh)
|
||||
{
|
||||
PullbackSell = true;
|
||||
}
|
||||
else if(PrevClose > prevEMAHigh && currentClose < currentEMAHigh)
|
||||
{
|
||||
PullbackSell = true;
|
||||
}
|
||||
else if(PrevClose > prevEMALow && currentClose < currentEMALow)
|
||||
{
|
||||
PullbackSell = true;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detect breakthrough buy signal |
|
||||
//+------------------------------------------------------------------+
|
||||
bool DetectBreakthroughBuy(double currentClose, double currentEMAHigh, double prevClose, double prevEMAHigh)
|
||||
{
|
||||
return (prevClose <= prevEMAHigh && currentClose > currentEMAHigh);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Detect breakthrough sell signal |
|
||||
//+------------------------------------------------------------------+
|
||||
bool DetectBreakthroughSell(double currentClose, double currentEMALow, double prevClose, double prevEMALow)
|
||||
{
|
||||
return (prevClose >= prevEMALow && currentClose < currentEMALow);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check volume filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckVolumeFilter(const long &tick_volume[], int rates_total)
|
||||
{
|
||||
if(rates_total < VolumePeriod + 1) return false;
|
||||
|
||||
// Calculate average volume
|
||||
double avgVolume = 0;
|
||||
for(int i = rates_total - VolumePeriod - 1; i < rates_total - 1; i++)
|
||||
{
|
||||
avgVolume += tick_volume[i];
|
||||
}
|
||||
avgVolume /= VolumePeriod;
|
||||
|
||||
// Check if current volume is above average
|
||||
return (tick_volume[rates_total - 1] > avgVolume);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check MTF filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckMTFFilter()
|
||||
{
|
||||
double d1Close = iClose(Symbol(), PERIOD_D1, 0);
|
||||
double d1EMAHigh = GetEMAValue(PERIOD_D1, PRICE_HIGH, 0);
|
||||
double d1EMALow = GetEMAValue(PERIOD_D1, PRICE_LOW, 0);
|
||||
|
||||
if(d1Close > d1EMAHigh)
|
||||
{
|
||||
// Only buy orders allowed
|
||||
return true;
|
||||
}
|
||||
else if(d1Close < d1EMALow)
|
||||
{
|
||||
// Only sell orders allowed
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Price between lines - no orders allowed
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check news filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckNewsFilter(datetime currentTime)
|
||||
{
|
||||
// Convert to Thailand timezone (UTC+7)
|
||||
// MT4 server time is usually UTC, so add 7 hours
|
||||
datetime thailandTime = currentTime + 7 * 3600; // 7 hours in seconds
|
||||
int thailandHour = TimeHour(thailandTime);
|
||||
int thailandDay = TimeDayOfWeek(thailandTime);
|
||||
|
||||
// Check if current hour is in avoid list
|
||||
for(int i = 0; i < ArraySize(AvoidHoursArray); i++)
|
||||
{
|
||||
if(thailandHour == AvoidHoursArray[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if current day is in avoid list
|
||||
for(int i = 0; i < ArraySize(AvoidDaysArray); i++)
|
||||
{
|
||||
if(thailandDay == AvoidDaysArray[i])
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check drawdown |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckDrawdown()
|
||||
{
|
||||
double currentEquity = AccountEquity();
|
||||
|
||||
// Update peak equity
|
||||
if(currentEquity > AccountEquityPeak)
|
||||
{
|
||||
AccountEquityPeak = currentEquity;
|
||||
}
|
||||
|
||||
// Calculate drawdown percentage
|
||||
double drawdownPercent = ((AccountEquityPeak - currentEquity) / AccountEquityPeak) * 100;
|
||||
|
||||
// Check if drawdown exceeds limit
|
||||
if(drawdownPercent >= MaxDrawdownPercent)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy order |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyOrder()
|
||||
{
|
||||
double lotSize = PullbackBuy ? LotSizePullback : LotSizeNormal;
|
||||
double stopLoss = LowBorderBuffer[ArraySize(LowBorderBuffer) - 1];
|
||||
double takeProfit = CalculateTakeProfit(lotSize, OP_BUY);
|
||||
|
||||
OrderTicket = OrderSend(Symbol(), OP_BUY, lotSize, Ask, 3, stopLoss, takeProfit, "MAEA Buy", MagicNumber, 0, clrBlue);
|
||||
|
||||
if(OrderTicket > 0)
|
||||
{
|
||||
OrderOpenPrice = Ask;
|
||||
OrderStopLoss = stopLoss;
|
||||
OrderTakeProfit = takeProfit;
|
||||
BreakevenTriggered = false;
|
||||
|
||||
// Reset pullback flags
|
||||
PullbackBuy = false;
|
||||
PullbackSell = false;
|
||||
|
||||
Print("Buy order opened: Ticket=", OrderTicket, " Price=", Ask, " SL=", stopLoss, " TP=", takeProfit);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Error opening buy order: ", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell order |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellOrder()
|
||||
{
|
||||
double lotSize = PullbackSell ? LotSizePullback : LotSizeNormal;
|
||||
double stopLoss = HighBorderBuffer[ArraySize(HighBorderBuffer) - 1];
|
||||
double takeProfit = CalculateTakeProfit(lotSize, OP_SELL);
|
||||
|
||||
OrderTicket = OrderSend(Symbol(), OP_SELL, lotSize, Bid, 3, stopLoss, takeProfit, "MAEA Sell", MagicNumber, 0, clrRed);
|
||||
|
||||
if(OrderTicket > 0)
|
||||
{
|
||||
OrderOpenPrice = Bid;
|
||||
OrderStopLoss = stopLoss;
|
||||
OrderTakeProfit = takeProfit;
|
||||
BreakevenTriggered = false;
|
||||
|
||||
// Reset pullback flags
|
||||
PullbackBuy = false;
|
||||
PullbackSell = false;
|
||||
|
||||
Print("Sell order opened: Ticket=", OrderTicket, " Price=", Bid, " SL=", stopLoss, " TP=", takeProfit);
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Error opening sell order: ", GetLastError());
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate take profit in pips from USD target |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateTakeProfit(double lotSize, int orderType)
|
||||
{
|
||||
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
|
||||
double tickSize = MarketInfo(Symbol(), MODE_TICKSIZE);
|
||||
double pipValue = tickValue / tickSize * Point;
|
||||
|
||||
double profitInPips = TakeProfitUSD / (lotSize * pipValue);
|
||||
double profitInPrice = profitInPips * Point;
|
||||
|
||||
if(orderType == OP_BUY)
|
||||
{
|
||||
return Ask + profitInPrice;
|
||||
}
|
||||
else
|
||||
{
|
||||
return Bid - profitInPrice;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if we have an open order |
|
||||
//+------------------------------------------------------------------+
|
||||
bool HasOpenOrder()
|
||||
{
|
||||
if(OrderTicket == 0) return false;
|
||||
|
||||
if(OrderSelect(OrderTicket, SELECT_BY_TICKET))
|
||||
{
|
||||
if(OrderCloseTime() == 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
OrderTicket = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
OrderTicket = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Manage open orders |
|
||||
//+------------------------------------------------------------------+
|
||||
void ManageOpenOrders()
|
||||
{
|
||||
if(!HasOpenOrder()) return;
|
||||
|
||||
if(!OrderSelect(OrderTicket, SELECT_BY_TICKET)) return;
|
||||
|
||||
double currentPrice = OrderType() == OP_BUY ? Bid : Ask;
|
||||
double currentProfit = OrderProfit();
|
||||
double openPrice = OrderOpenPrice();
|
||||
|
||||
// Check take profit
|
||||
if(currentProfit >= TakeProfitUSD)
|
||||
{
|
||||
CloseOrder();
|
||||
return;
|
||||
}
|
||||
|
||||
// Check stop loss
|
||||
if(OrderType() == OP_BUY && currentPrice <= OrderStopLoss())
|
||||
{
|
||||
CloseOrder();
|
||||
return;
|
||||
}
|
||||
else if(OrderType() == OP_SELL && currentPrice >= OrderStopLoss())
|
||||
{
|
||||
CloseOrder();
|
||||
return;
|
||||
}
|
||||
|
||||
// Calculate profit in points
|
||||
double profitPoints = 0;
|
||||
if(OrderType() == OP_BUY)
|
||||
{
|
||||
profitPoints = (currentPrice - openPrice) / Point;
|
||||
}
|
||||
else
|
||||
{
|
||||
profitPoints = (openPrice - currentPrice) / Point;
|
||||
}
|
||||
|
||||
// Check breakeven
|
||||
if(!BreakevenTriggered && profitPoints >= BreakevenPoints)
|
||||
{
|
||||
double newSL = openPrice;
|
||||
if(OrderModify(OrderTicket, openPrice, newSL, OrderTakeProfit(), 0, clrNONE))
|
||||
{
|
||||
BreakevenTriggered = true;
|
||||
OrderStopLoss = newSL;
|
||||
Print("Breakeven triggered: SL moved to ", newSL);
|
||||
}
|
||||
}
|
||||
|
||||
// Check trailing stop
|
||||
if(BreakevenTriggered && profitPoints >= BreakevenPoints + TrailingStopPoints)
|
||||
{
|
||||
double newSL;
|
||||
if(OrderType() == OP_BUY)
|
||||
{
|
||||
newSL = currentPrice - TrailingStopPoints * Point;
|
||||
if(newSL > OrderStopLoss())
|
||||
{
|
||||
if(OrderModify(OrderTicket, openPrice, newSL, OrderTakeProfit(), 0, clrNONE))
|
||||
{
|
||||
OrderStopLoss = newSL;
|
||||
Print("Trailing stop: SL moved to ", newSL);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
newSL = currentPrice + TrailingStopPoints * Point;
|
||||
if(newSL < OrderStopLoss())
|
||||
{
|
||||
if(OrderModify(OrderTicket, openPrice, newSL, OrderTakeProfit(), 0, clrNONE))
|
||||
{
|
||||
OrderStopLoss = newSL;
|
||||
Print("Trailing stop: SL moved to ", newSL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Close order |
|
||||
//+------------------------------------------------------------------+
|
||||
void CloseOrder()
|
||||
{
|
||||
if(OrderSelect(OrderTicket, SELECT_BY_TICKET))
|
||||
{
|
||||
double closePrice = OrderType() == OP_BUY ? Bid : Ask;
|
||||
if(OrderClose(OrderTicket, OrderLots(), closePrice, 3, clrNONE))
|
||||
{
|
||||
Print("Order closed: Ticket=", OrderTicket, " Profit=", OrderProfit());
|
||||
OrderTicket = 0;
|
||||
BreakevenTriggered = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
Print("Error closing order: ", GetLastError());
|
||||
}
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
509
MAEA.mq5
Normal file
509
MAEA.mq5
Normal file
@@ -0,0 +1,509 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MAEA.mq5 |
|
||||
//| Moving Average EA |
|
||||
//| Trend-following EA with EMA zone breakout |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "MAEA"
|
||||
#property link ""
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
#include <Trade\Trade.mqh>
|
||||
#include <Indicators\Indicators.mqh>
|
||||
|
||||
// === EMA SETTINGS ===
|
||||
input int EMAPeriod = 30;
|
||||
input int EMAShift = 0;
|
||||
input int MinZoneWidthPoints = 100;
|
||||
|
||||
// === RISK MANAGEMENT ===
|
||||
input double LotSize = 0.01;
|
||||
input double TakeProfitUSD = 5.0;
|
||||
input int BreakevenPoints = 100;
|
||||
input int TrailingStopPoints = 100;
|
||||
|
||||
// === FILTERS ===
|
||||
input bool UseMTFFilter = true;
|
||||
input bool UseNewsFilter = true;
|
||||
input int MaxSpread = 30;
|
||||
input int VolumePeriod = 20;
|
||||
|
||||
// === NEWS FILTER ===
|
||||
input string NewsAvoidHours = "14,15,20,21";
|
||||
input string NewsAvoidDays = "1,5";
|
||||
|
||||
// === RISK PROTECTION ===
|
||||
input double MaxDrawdownPercent = 10.0;
|
||||
|
||||
// === EA SETTINGS ===
|
||||
input int MagicNumber = 12345;
|
||||
|
||||
// === GLOBAL VARIABLES ===
|
||||
CTrade trade;
|
||||
int handleEMAHigh = INVALID_HANDLE;
|
||||
int handleEMALow = INVALID_HANDLE;
|
||||
int handleD1EMAHigh = INVALID_HANDLE;
|
||||
int handleD1EMALow = INVALID_HANDLE;
|
||||
|
||||
double g_EMAHighBuffer[];
|
||||
double g_EMALowBuffer[];
|
||||
double g_D1EMAHighBuffer[];
|
||||
double g_D1EMALowBuffer[];
|
||||
|
||||
datetime g_LastBarTime = 0;
|
||||
double g_EntryPrice = 0;
|
||||
double g_BreakevenPrice = 0;
|
||||
bool g_BreakevenTriggered = false;
|
||||
bool g_TradingAllowed = true;
|
||||
double g_AccountHighBalance = 0;
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit() {
|
||||
Print("[MAEA] Initializing EA...");
|
||||
|
||||
trade.SetExpertMagicNumber(MagicNumber);
|
||||
|
||||
handleEMAHigh = iMA(_Symbol, PERIOD_CURRENT, EMAPeriod, EMAShift, MODE_EMA, PRICE_HIGH);
|
||||
handleEMALow = iMA(_Symbol, PERIOD_CURRENT, EMAPeriod, EMAShift, MODE_EMA, PRICE_LOW);
|
||||
handleD1EMAHigh = iMA(_Symbol, PERIOD_D1, EMAPeriod, EMAShift, MODE_EMA, PRICE_HIGH);
|
||||
handleD1EMALow = iMA(_Symbol, PERIOD_D1, EMAPeriod, EMAShift, MODE_EMA, PRICE_LOW);
|
||||
|
||||
if(handleEMAHigh == INVALID_HANDLE || handleEMALow == INVALID_HANDLE ||
|
||||
handleD1EMAHigh == INVALID_HANDLE || handleD1EMALow == INVALID_HANDLE) {
|
||||
Print("[MAEA] Failed to create EMA handles");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
Print("[MAEA] Handles - EMAHigh: ", handleEMAHigh, ", EMALow: ", handleEMALow);
|
||||
|
||||
ArraySetAsSeries(g_EMAHighBuffer, true);
|
||||
ArraySetAsSeries(g_EMALowBuffer, true);
|
||||
ArraySetAsSeries(g_D1EMAHighBuffer, true);
|
||||
ArraySetAsSeries(g_D1EMALowBuffer, true);
|
||||
|
||||
g_AccountHighBalance = AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
g_LastBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
|
||||
|
||||
Print("[MAEA] Initialization successful");
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason) {
|
||||
Print("[MAEA] Deinitializing. Reason: ", reason);
|
||||
|
||||
if(handleEMAHigh != INVALID_HANDLE) IndicatorRelease(handleEMAHigh);
|
||||
if(handleEMALow != INVALID_HANDLE) IndicatorRelease(handleEMALow);
|
||||
if(handleD1EMAHigh != INVALID_HANDLE) IndicatorRelease(handleD1EMAHigh);
|
||||
if(handleD1EMALow != INVALID_HANDLE) IndicatorRelease(handleD1EMALow);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert tick function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnTick() {
|
||||
datetime currentBarTime = iTime(_Symbol, PERIOD_CURRENT, 0);
|
||||
|
||||
if(currentBarTime != g_LastBarTime) {
|
||||
g_LastBarTime = currentBarTime;
|
||||
CheckDrawdown();
|
||||
OnNewBar();
|
||||
}
|
||||
|
||||
ManageOpenPosition();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| New bar processing |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnNewBar() {
|
||||
if(HasOpenPosition()) {
|
||||
CheckOppositeSignal();
|
||||
return;
|
||||
}
|
||||
|
||||
CheckBreakthroughSignal();
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check breakthrough signal and open position |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckBreakthroughSignal() {
|
||||
if(!CopyIndicatorData()) return;
|
||||
|
||||
double prevClose = iClose(_Symbol, PERIOD_CURRENT, 1);
|
||||
double currClose = iClose(_Symbol, PERIOD_CURRENT, 0);
|
||||
double emaHigh = g_EMAHighBuffer[0];
|
||||
double emaLow = g_EMALowBuffer[0];
|
||||
double zoneWidth = MathAbs(emaHigh - emaLow);
|
||||
|
||||
if(zoneWidth < MinZoneWidthPoints * _Point) return;
|
||||
|
||||
bool prevInsideZone = (prevClose <= emaHigh && prevClose >= emaLow);
|
||||
|
||||
if(!prevInsideZone) return;
|
||||
|
||||
bool buySignal = (currClose > emaHigh);
|
||||
bool sellSignal = (currClose < emaLow);
|
||||
|
||||
if(!buySignal && !sellSignal) return;
|
||||
|
||||
if(buySignal && !AllFiltersPass(true)) return;
|
||||
if(sellSignal && !AllFiltersPass(false)) return;
|
||||
|
||||
if(buySignal) {
|
||||
OpenBuyPosition();
|
||||
}
|
||||
else if(sellSignal) {
|
||||
OpenSellPosition();
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check opposite signal and close position |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckOppositeSignal() {
|
||||
if(!CopyIndicatorData()) return;
|
||||
|
||||
if(!HasOpenPosition()) return;
|
||||
|
||||
double currClose = iClose(_Symbol, PERIOD_CURRENT, 0);
|
||||
double prevClose = iClose(_Symbol, PERIOD_CURRENT, 1);
|
||||
double emaHigh = g_EMAHighBuffer[0];
|
||||
double emaLow = g_EMALowBuffer[0];
|
||||
|
||||
bool buySignal = (prevClose <= emaHigh && prevClose >= emaLow && currClose > emaHigh);
|
||||
bool sellSignal = (prevClose <= emaHigh && prevClose >= emaLow && currClose < emaLow);
|
||||
|
||||
if(!buySignal && !sellSignal) return;
|
||||
|
||||
ulong positionTicket = GetPositionTicket();
|
||||
if(positionTicket == 0) return;
|
||||
|
||||
ENUM_POSITION_TYPE posType = GetPositionType(positionTicket);
|
||||
|
||||
if(posType == POSITION_TYPE_BUY && sellSignal) {
|
||||
trade.PositionClose(positionTicket);
|
||||
ResetPositionVariables();
|
||||
Print("Buy position closed due to opposite sell signal");
|
||||
}
|
||||
else if(posType == POSITION_TYPE_SELL && buySignal) {
|
||||
trade.PositionClose(positionTicket);
|
||||
ResetPositionVariables();
|
||||
Print("Sell position closed due to opposite buy signal");
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Manage open position (TP, SL, breakeven, trailing stop) |
|
||||
//+------------------------------------------------------------------+
|
||||
void ManageOpenPosition() {
|
||||
if(!HasOpenPosition()) return;
|
||||
|
||||
ulong positionTicket = GetPositionTicket();
|
||||
if(positionTicket == 0) return;
|
||||
|
||||
if(!PositionSelectByTicket(positionTicket)) return;
|
||||
|
||||
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
|
||||
double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);
|
||||
double currentSL = PositionGetDouble(POSITION_SL);
|
||||
double currentTP = PositionGetDouble(POSITION_TP);
|
||||
double profit = PositionGetDouble(POSITION_PROFIT);
|
||||
ENUM_POSITION_TYPE posType = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
|
||||
if(currentTP > 0 && profit >= TakeProfitUSD) {
|
||||
trade.PositionClose(positionTicket);
|
||||
ResetPositionVariables();
|
||||
Print("Position closed by Take Profit");
|
||||
return;
|
||||
}
|
||||
|
||||
double pointsProfit = 0;
|
||||
double breakevenLevel = 0;
|
||||
|
||||
if(posType == POSITION_TYPE_BUY) {
|
||||
pointsProfit = (currentPrice - openPrice) / _Point;
|
||||
breakevenLevel = openPrice + BreakevenPoints * _Point;
|
||||
}
|
||||
else {
|
||||
pointsProfit = (openPrice - currentPrice) / _Point;
|
||||
breakevenLevel = openPrice - BreakevenPoints * _Point;
|
||||
}
|
||||
|
||||
if(!g_BreakevenTriggered && pointsProfit >= BreakevenPoints) {
|
||||
if(posType == POSITION_TYPE_BUY) {
|
||||
trade.PositionModify(positionTicket, openPrice, currentTP);
|
||||
}
|
||||
else {
|
||||
trade.PositionModify(positionTicket, openPrice, currentTP);
|
||||
}
|
||||
g_BreakevenTriggered = true;
|
||||
Print("Breakeven triggered for position ", positionTicket);
|
||||
}
|
||||
|
||||
if(g_BreakevenTriggered && TrailingStopPoints > 0) {
|
||||
double trailDistance = TrailingStopPoints * _Point;
|
||||
double newSL;
|
||||
|
||||
if(posType == POSITION_TYPE_BUY) {
|
||||
newSL = currentPrice - trailDistance;
|
||||
if(newSL > currentSL + _Point && newSL > openPrice) {
|
||||
trade.PositionModify(positionTicket, newSL, currentTP);
|
||||
}
|
||||
}
|
||||
else {
|
||||
newSL = currentPrice + trailDistance;
|
||||
if(newSL < currentSL - _Point && newSL < openPrice) {
|
||||
trade.PositionModify(positionTicket, newSL, currentTP);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open buy position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenBuyPosition() {
|
||||
if(!CopyIndicatorData()) return;
|
||||
|
||||
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
|
||||
double sl = g_EMALowBuffer[0];
|
||||
double tp = CalculateTakeProfit(ask, sl, true);
|
||||
|
||||
if(!trade.Buy(LotSize, _Symbol, ask, sl, tp, "MAEA Buy")) {
|
||||
int err = GetLastError();
|
||||
Print("Buy order failed. Error: ", err);
|
||||
}
|
||||
else {
|
||||
g_EntryPrice = ask;
|
||||
g_BreakevenTriggered = false;
|
||||
Print("Buy position opened at ", ask);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Open sell position |
|
||||
//+------------------------------------------------------------------+
|
||||
void OpenSellPosition() {
|
||||
if(!CopyIndicatorData()) return;
|
||||
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
double sl = g_EMAHighBuffer[0];
|
||||
double tp = CalculateTakeProfit(bid, sl, false);
|
||||
|
||||
if(!trade.Sell(LotSize, _Symbol, bid, sl, tp, "MAEA Sell")) {
|
||||
int err = GetLastError();
|
||||
Print("Sell order failed. Error: ", err);
|
||||
}
|
||||
else {
|
||||
g_EntryPrice = bid;
|
||||
g_BreakevenTriggered = false;
|
||||
Print("Sell position opened at ", bid);
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculate take profit in price |
|
||||
//+------------------------------------------------------------------+
|
||||
double CalculateTakeProfit(double entryPrice, double sl, bool isBuy) {
|
||||
double pointValue = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
|
||||
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
|
||||
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
|
||||
|
||||
double profitPoints = TakeProfitUSD / (tickValue * LotSize / tickSize);
|
||||
double profitPrice = profitPoints * pointValue;
|
||||
|
||||
if(isBuy) {
|
||||
return entryPrice + profitPrice;
|
||||
}
|
||||
else {
|
||||
return entryPrice - profitPrice;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Copy indicator data |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CopyIndicatorData() {
|
||||
if(CopyBuffer(handleEMAHigh, 0, 0, 10, g_EMAHighBuffer) <= 0) return false;
|
||||
if(CopyBuffer(handleEMALow, 0, 0, 10, g_EMALowBuffer) <= 0) return false;
|
||||
if(UseMTFFilter) {
|
||||
if(CopyBuffer(handleD1EMAHigh, 0, 0, 2, g_D1EMAHighBuffer) <= 0) return false;
|
||||
if(CopyBuffer(handleD1EMALow, 0, 0, 2, g_D1EMALowBuffer) <= 0) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check all filters |
|
||||
//+------------------------------------------------------------------+
|
||||
bool AllFiltersPass(bool isBuyDirection) {
|
||||
if(!CheckVolumeFilter()) return false;
|
||||
if(!CheckSpreadFilter()) return false;
|
||||
if(!CheckDrawdownAllowed()) return false;
|
||||
if(UseMTFFilter && !CheckMTFFilter(isBuyDirection)) return false;
|
||||
if(UseNewsFilter && !CheckNewsFilter()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Volume filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckVolumeFilter() {
|
||||
long currentVolume = iVolume(_Symbol, PERIOD_CURRENT, 0);
|
||||
long avgVolume = 0;
|
||||
|
||||
for(int i = 1; i <= VolumePeriod; i++) {
|
||||
avgVolume += iVolume(_Symbol, PERIOD_CURRENT, i);
|
||||
}
|
||||
avgVolume = avgVolume / VolumePeriod;
|
||||
|
||||
return (currentVolume > avgVolume);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Spread filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckSpreadFilter() {
|
||||
long spread;
|
||||
SymbolInfoInteger(_Symbol, SYMBOL_SPREAD, spread);
|
||||
return (spread <= MaxSpread);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| MTF filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckMTFFilter(bool isBuyDirection) {
|
||||
double d1Close = iClose(_Symbol, PERIOD_D1, 0);
|
||||
double d1EMAHigh = g_D1EMAHighBuffer[0];
|
||||
double d1EMALow = g_D1EMALowBuffer[0];
|
||||
|
||||
if(d1Close > d1EMAHigh) {
|
||||
return isBuyDirection;
|
||||
}
|
||||
else if(d1Close < d1EMALow) {
|
||||
return !isBuyDirection;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| News filter |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckNewsFilter() {
|
||||
datetime gmtTime = TimeGMT();
|
||||
datetime thaiTime = gmtTime + 25200;
|
||||
MqlDateTime timeStruct;
|
||||
TimeToStruct(thaiTime, timeStruct);
|
||||
|
||||
string hoursArr[];
|
||||
StringSplit(NewsAvoidHours, ',', hoursArr);
|
||||
for(int i = 0; i < ArraySize(hoursArr); i++) {
|
||||
string h = hoursArr[i];
|
||||
StringTrimRight(h);
|
||||
StringTrimLeft(h);
|
||||
if(h == IntegerToString(timeStruct.hour)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
string daysArr[];
|
||||
StringSplit(NewsAvoidDays, ',', daysArr);
|
||||
for(int i = 0; i < ArraySize(daysArr); i++) {
|
||||
string d = daysArr[i];
|
||||
StringTrimRight(d);
|
||||
StringTrimLeft(d);
|
||||
if(d == IntegerToString(timeStruct.day_of_week)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check drawdown |
|
||||
//+------------------------------------------------------------------+
|
||||
void CheckDrawdown() {
|
||||
double currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
|
||||
if(currentBalance > g_AccountHighBalance) {
|
||||
g_AccountHighBalance = currentBalance;
|
||||
}
|
||||
|
||||
if(currentBalance > 0 && g_AccountHighBalance > 0) {
|
||||
double drawdownPercent = ((g_AccountHighBalance - currentBalance) / g_AccountHighBalance) * 100;
|
||||
|
||||
if(drawdownPercent >= MaxDrawdownPercent) {
|
||||
g_TradingAllowed = false;
|
||||
Print("Drawdown limit reached. Trading stopped.");
|
||||
}
|
||||
else {
|
||||
g_TradingAllowed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if trading is allowed based on drawdown |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckDrawdownAllowed() {
|
||||
return g_TradingAllowed;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if has open position |
|
||||
//+------------------------------------------------------------------+
|
||||
bool HasOpenPosition() {
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
if(PositionGetSymbol(i) == _Symbol) {
|
||||
ulong magic = PositionGetInteger(POSITION_MAGIC);
|
||||
if(magic == MagicNumber) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get position ticket |
|
||||
//+------------------------------------------------------------------+
|
||||
ulong GetPositionTicket() {
|
||||
for(int i = PositionsTotal() - 1; i >= 0; i--) {
|
||||
if(PositionGetSymbol(i) == _Symbol) {
|
||||
ulong ticket = PositionGetInteger(POSITION_TICKET);
|
||||
ulong magic = PositionGetInteger(POSITION_MAGIC);
|
||||
if(magic == MagicNumber) {
|
||||
return ticket;
|
||||
}
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Get position type |
|
||||
//+------------------------------------------------------------------+
|
||||
ENUM_POSITION_TYPE GetPositionType(ulong ticket) {
|
||||
if(PositionSelectByTicket(ticket)) {
|
||||
return (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
|
||||
}
|
||||
return POSITION_TYPE_BUY;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Reset position variables |
|
||||
//+------------------------------------------------------------------+
|
||||
void ResetPositionVariables() {
|
||||
g_EntryPrice = 0;
|
||||
g_BreakevenTriggered = false;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
109
MAEA_Indicator.mq5
Normal file
109
MAEA_Indicator.mq5
Normal file
@@ -0,0 +1,109 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| MAEA_Indicator.mq5 |
|
||||
//| Moving Average EA |
|
||||
//| Visual indicator for EMA zone breakout |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "MAEA"
|
||||
#property link ""
|
||||
#property version "1.00"
|
||||
#property strict
|
||||
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 3
|
||||
#property indicator_plots 3
|
||||
|
||||
#property indicator_label1 "EMA High"
|
||||
#property indicator_type1 DRAW_LINE
|
||||
#property indicator_color1 clrLightBlue
|
||||
#property indicator_style1 STYLE_SOLID
|
||||
#property indicator_width1 2
|
||||
|
||||
#property indicator_label2 "EMA Low"
|
||||
#property indicator_type2 DRAW_LINE
|
||||
#property indicator_color2 clrOrange
|
||||
#property indicator_style2 STYLE_SOLID
|
||||
#property indicator_width2 2
|
||||
|
||||
#property indicator_label3 "EMA Zone"
|
||||
#property indicator_type3 DRAW_FILLING
|
||||
#property indicator_color3 clrYellow
|
||||
#property indicator_style3 STYLE_SOLID
|
||||
#property indicator_width3 1
|
||||
|
||||
input int EMAPeriod = 30;
|
||||
input int EMAShift = 0;
|
||||
|
||||
int handleEMAHigh;
|
||||
int handleEMALow;
|
||||
|
||||
double BufferEMAHigh[];
|
||||
double BufferEMALow[];
|
||||
double BufferZone[];
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit() {
|
||||
ArraySetAsSeries(BufferEMAHigh, true);
|
||||
ArraySetAsSeries(BufferEMALow, true);
|
||||
ArraySetAsSeries(BufferZone, true);
|
||||
|
||||
SetIndexBuffer(0, BufferEMAHigh, INDICATOR_DATA);
|
||||
SetIndexBuffer(1, BufferEMALow, INDICATOR_DATA);
|
||||
SetIndexBuffer(2, BufferZone, INDICATOR_CALCULATIONS);
|
||||
|
||||
ArraySetAsSeries(BufferEMAHigh, true);
|
||||
ArraySetAsSeries(BufferEMALow, true);
|
||||
ArraySetAsSeries(BufferZone, true);
|
||||
|
||||
PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
||||
PlotIndexSetDouble(1, PLOT_EMPTY_VALUE, EMPTY_VALUE);
|
||||
|
||||
PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, EMAPeriod + EMAShift);
|
||||
PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, EMAPeriod + EMAShift);
|
||||
PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, EMAPeriod + EMAShift);
|
||||
|
||||
handleEMAHigh = iMA(_Symbol, PERIOD_CURRENT, EMAPeriod, EMAShift, MODE_EMA, PRICE_HIGH);
|
||||
handleEMALow = iMA(_Symbol, PERIOD_CURRENT, EMAPeriod, EMAShift, MODE_EMA, PRICE_LOW);
|
||||
|
||||
if(handleEMAHigh == INVALID_HANDLE || handleEMALow == INVALID_HANDLE) {
|
||||
Print("Failed to create EMA handles");
|
||||
return INIT_FAILED;
|
||||
}
|
||||
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason) {
|
||||
IndicatorRelease(handleEMAHigh);
|
||||
IndicatorRelease(handleEMALow);
|
||||
}
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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 < EMAPeriod + EMAShift) return 0;
|
||||
|
||||
int copied = CopyBuffer(handleEMAHigh, 0, 0, rates_total, BufferEMAHigh);
|
||||
if(copied <= 0) return 0;
|
||||
|
||||
copied = CopyBuffer(handleEMALow, 0, 0, rates_total, BufferEMALow);
|
||||
if(copied <= 0) return 0;
|
||||
|
||||
return rates_total;
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
345
README.md
345
README.md
@@ -1,345 +0,0 @@
|
||||
# MAEA - Moving Average Expert Advisor
|
||||
|
||||
Advanced trend-following Expert Advisor for MetaTrader 4 with sophisticated filtering and risk management features.
|
||||
|
||||
## 📋 Table of Contents
|
||||
|
||||
- [Overview](#overview)
|
||||
- [Features](#features)
|
||||
- [Strategy Details](#strategy-details)
|
||||
- [Installation](#installation)
|
||||
- [Parameters](#parameters)
|
||||
- [Usage](#usage)
|
||||
- [Visual Indicators](#visual-indicators)
|
||||
- [Risk Management](#risk-management)
|
||||
- [Troubleshooting](#troubleshooting)
|
||||
- [Disclaimer](#disclaimer)
|
||||
|
||||
## 🎯 Overview
|
||||
|
||||
MAEA is a sophisticated trading robot that uses Exponential Moving Averages (EMAs) with dynamic border lines to identify trend-following opportunities. The EA includes multiple filters to ensure high-quality trade entries and comprehensive risk management to protect your account.
|
||||
|
||||
**Repository:** https://git.moreminimore.com/kunthawat/MAEA
|
||||
**Platform:** MetaTrader 4
|
||||
**Language:** MQL4
|
||||
**Timezone:** Thailand (UTC+7)
|
||||
|
||||
## ✨ Features
|
||||
|
||||
### Core Strategy
|
||||
- **5 Visual Indicator Lines:** 3 EMA lines + 2 dynamic Border Lines
|
||||
- **Breakthrough Signals:** Entry when price breaks through EMA High/Low
|
||||
- **Pullback Signals:** Enhanced lot sizing after pullback detection
|
||||
- **Dynamic Lot Sizing:** 0.01 or 0.02 lots based on market behavior
|
||||
- **Single Order Management:** Prevents over-trading
|
||||
|
||||
### Advanced Filters
|
||||
- **Volume Filter:** Trade only when volume exceeds 20-bar average
|
||||
- **Spread Filter:** Avoid high spread periods (max 30 points)
|
||||
- **Multiple Timeframe Filter:** D1 trend confirmation (optional)
|
||||
- **News Filter:** Avoid specific hours/days (Thailand timezone, optional)
|
||||
|
||||
### Risk Management
|
||||
- **Take Profit:** Target in USD (default $5)
|
||||
- **Stop Loss:** At dynamic Border Lines
|
||||
- **Breakeven:** Move SL to entry at 100 points profit
|
||||
- **Trailing Stop:** Trail by 100 points after breakeven
|
||||
- **Max Drawdown Protection:** Stop trading at 10% drawdown
|
||||
|
||||
## 📊 Strategy Details
|
||||
|
||||
### Indicator System
|
||||
|
||||
#### EMA Lines (3 Base Lines)
|
||||
All EMAs use period 30 with different price sources:
|
||||
|
||||
1. **EMA High** (Light Blue) - EMA of High prices
|
||||
2. **EMA Medium** (Yellow) - EMA of Close prices
|
||||
3. **EMA Low** (Orange) - EMA of Low prices
|
||||
|
||||
#### Border Lines (2 Dynamic Lines)
|
||||
Calculated based on the range between EMAs:
|
||||
|
||||
1. **High Border** (Purple) = EMA High + (EMA Medium - EMA Low)
|
||||
2. **Low Border** (Purple) = EMA Low - (EMA Medium - EMA Low)
|
||||
|
||||
**Example Calculation:**
|
||||
```
|
||||
EMA High = 3500
|
||||
EMA Medium = 3400
|
||||
EMA Low = 3300
|
||||
Range = EMA Medium - EMA Low = 3400 - 3300 = 100
|
||||
|
||||
High Border = 3500 + 100 = 3600
|
||||
Low Border = 3300 - 100 = 3200
|
||||
```
|
||||
|
||||
### Signal Types
|
||||
|
||||
#### 1. Breakthrough Signal
|
||||
- **Buy Signal:** Close price breaks above EMA High
|
||||
- **Sell Signal:** Close price breaks below EMA Low
|
||||
- **Purpose:** Triggers order opening
|
||||
|
||||
#### 2. Pullback Signal
|
||||
- **Buy Pullback:** Price moves down to hit any line, then closes above the line
|
||||
- **Sell Pullback:** Price moves up to hit any line, then closes below the line
|
||||
- **Purpose:** Increases lot size when breakthrough occurs in same direction
|
||||
- **Tracking:** Separate for buy and sell directions
|
||||
|
||||
### Order Management
|
||||
- **Single Order:** Only one order at a time
|
||||
- **Dynamic Lot Sizing:**
|
||||
- 0.01 lot (no pullback before breakthrough)
|
||||
- 0.02 lot (pullback occurred before breakthrough)
|
||||
- **Stop Loss:** At Border Lines (Low Border for buys, High Border for sells)
|
||||
- **Take Profit:** Target in USD (default $5)
|
||||
- **Breakeven:** Move SL to entry at X points profit (default 100)
|
||||
- **Trailing Stop:** Trail by X points after breakeven (default 100)
|
||||
|
||||
## 🚀 Installation
|
||||
|
||||
1. **Download the EA:**
|
||||
- Clone the repository: `git clone https://git.moreminimore.com/kunthawat/MAEA.git`
|
||||
- Or download [`MAEA.mq4`](MAEA.mq4) directly
|
||||
|
||||
2. **Copy to MT4:**
|
||||
- Navigate to your MT4 data folder
|
||||
- Go to `MQL4/Indicators` or `MQL4/Experts`
|
||||
- Copy [`MAEA.mq4`](MAEA.mq4) to that folder
|
||||
|
||||
3. **Compile in MetaEditor:**
|
||||
- Open MetaEditor (press F4 in MT4)
|
||||
- Open [`MAEA.mq4`](MAEA.mq4)
|
||||
- Press F7 to compile
|
||||
- Ensure no compilation errors
|
||||
|
||||
4. **Attach to Chart:**
|
||||
- Open MT4
|
||||
- Drag MAEA from Navigator to your chart
|
||||
- Recommended timeframe: H1
|
||||
- Configure parameters as needed
|
||||
|
||||
5. **Enable Auto Trading:**
|
||||
- Click "Auto Trading" button in MT4 toolbar
|
||||
- Ensure EA is allowed to trade in Tools → Options → Expert Advisors
|
||||
|
||||
## ⚙️ Parameters
|
||||
|
||||
### EMA Settings
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `EMAPeriod` | 30 | EMA period for all lines |
|
||||
|
||||
### Lot Settings
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `LotSizeNormal` | 0.01 | Lot size without pullback |
|
||||
| `LotSizePullback` | 0.02 | Lot size with pullback |
|
||||
|
||||
### Risk Management
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `TakeProfitUSD` | 5.0 | Take profit target in USD |
|
||||
| `BreakevenPoints` | 100 | Points to trigger breakeven |
|
||||
| `TrailingStopPoints` | 100 | Trailing stop distance |
|
||||
| `MaxDrawdownPercent` | 10.0 | Maximum drawdown percentage |
|
||||
|
||||
### Filters
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `MaxSpread` | 30 | Maximum allowed spread in points |
|
||||
| `VolumePeriod` | 20 | Period for volume average |
|
||||
| `UseMTFFilter` | true | Enable MTF filter |
|
||||
| `UseNewsFilter` | true | Enable news filter |
|
||||
| `NewsAvoidHours` | "14,15,20,21" | Hours to avoid (Thailand time) |
|
||||
| `NewsAvoidDays` | "1,5" | Days to avoid (Monday=1, Friday=5) |
|
||||
|
||||
### General
|
||||
| Parameter | Default | Description |
|
||||
|-----------|---------|-------------|
|
||||
| `MagicNumber` | 12345 | EA unique identifier |
|
||||
|
||||
## 📖 Usage
|
||||
|
||||
### Basic Setup
|
||||
1. Attach MAEA to an H1 chart
|
||||
2. Adjust parameters according to your risk tolerance
|
||||
3. Enable Auto Trading
|
||||
4. Monitor the EA's performance
|
||||
|
||||
### Recommended Timeframes
|
||||
- **Trading Timeframe:** H1 (recommended)
|
||||
- **Filter Timeframe:** D1 (for MTF filter)
|
||||
|
||||
### Currency Pairs
|
||||
- Works on all major currency pairs
|
||||
- Best performance on trending pairs (EURUSD, GBPUSD, USDJPY)
|
||||
|
||||
### Account Types
|
||||
- Compatible with any MT4 account type
|
||||
- Ensure sufficient margin for lot sizes
|
||||
|
||||
## 🎨 Visual Indicators
|
||||
|
||||
The EA displays 5 lines on your chart:
|
||||
|
||||
| Line | Color | Style | Description |
|
||||
|------|-------|-------|-------------|
|
||||
| EMA High | Light Blue | Solid | EMA of High prices |
|
||||
| EMA Medium | Yellow | Solid | EMA of Close prices |
|
||||
| EMA Low | Orange | Solid | EMA of Low prices |
|
||||
| High Border | Purple | Dashed | Upper dynamic border |
|
||||
| Low Border | Purple | Dashed | Lower dynamic border |
|
||||
|
||||
### Reading the Indicators
|
||||
- **Price above all lines:** Strong uptrend
|
||||
- **Price below all lines:** Strong downtrend
|
||||
- **Price between lines:** Consolidation/ranging
|
||||
- **Border Lines:** Dynamic support/resistance levels
|
||||
|
||||
## 🛡️ Risk Management
|
||||
|
||||
### Take Profit
|
||||
- Closes order when profit reaches target amount in USD
|
||||
- Automatically calculated based on lot size and symbol
|
||||
|
||||
### Stop Loss
|
||||
- **Buy Orders:** SL at Low Border Line
|
||||
- **Sell Orders:** SL at High Border Line
|
||||
- Moves dynamically as Border Lines update
|
||||
|
||||
### Breakeven
|
||||
- Triggered when profit reaches specified points (default 100)
|
||||
- Moves Stop Loss to breakeven (entry price)
|
||||
- Protects profits while allowing room for trend continuation
|
||||
|
||||
### Trailing Stop
|
||||
- Activates after breakeven is reached
|
||||
- Trails Stop Loss by specified points (default 100)
|
||||
- Locks in profits as trend continues
|
||||
|
||||
### Drawdown Protection
|
||||
- Calculates drawdown percentage from peak equity
|
||||
- Stops trading if drawdown exceeds limit (default 10%)
|
||||
- Resumes trading when drawdown is below limit
|
||||
|
||||
## 🔧 Troubleshooting
|
||||
|
||||
### EA Not Opening Orders
|
||||
|
||||
**Problem:** EA is attached but not opening any orders
|
||||
|
||||
**Solutions:**
|
||||
1. Check if Auto Trading is enabled (green button in MT4 toolbar)
|
||||
2. Verify EA is allowed in Tools → Options → Expert Advisors
|
||||
3. Check if filters are too restrictive:
|
||||
- Reduce `MaxSpread` if spread is too high
|
||||
- Disable `UseMTFFilter` temporarily
|
||||
- Disable `UseNewsFilter` temporarily
|
||||
4. Verify account has sufficient margin
|
||||
5. Check Experts tab for error messages
|
||||
|
||||
### Compilation Errors
|
||||
|
||||
**Problem:** EA fails to compile in MetaEditor
|
||||
|
||||
**Solutions:**
|
||||
1. Ensure you're using MT4 (not MT5)
|
||||
2. Check for missing brackets or semicolons
|
||||
3. Verify all function names are spelled correctly
|
||||
4. Update MetaEditor to latest version
|
||||
|
||||
### Incorrect Indicator Display
|
||||
|
||||
**Problem:** Lines not displaying correctly on chart
|
||||
|
||||
**Solutions:**
|
||||
1. Ensure sufficient historical data (at least 50 bars)
|
||||
2. Check if `EMAPeriod` is too high for available data
|
||||
3. Refresh chart (right-click → Refresh)
|
||||
4. Reattach EA to chart
|
||||
|
||||
### Orders Closing Prematurely
|
||||
|
||||
**Problem:** Orders closing too early or not reaching TP
|
||||
|
||||
**Solutions:**
|
||||
1. Check if `TakeProfitUSD` is too low
|
||||
2. Verify `MaxDrawdownPercent` is not too restrictive
|
||||
3. Check if spread is causing SL hits
|
||||
4. Review trade logs for closure reasons
|
||||
|
||||
### Drawdown Protection Triggering
|
||||
|
||||
**Problem:** EA stops trading due to drawdown
|
||||
|
||||
**Solutions:**
|
||||
1. Increase `MaxDrawdownPercent` if too conservative
|
||||
2. Wait for equity to recover above threshold
|
||||
3. Review trading strategy and risk settings
|
||||
4. Consider reducing lot sizes
|
||||
|
||||
### Timezone Issues
|
||||
|
||||
**Problem:** News filter not working at expected times
|
||||
|
||||
**Solutions:**
|
||||
1. Verify your MT4 server timezone
|
||||
2. Adjust `NewsAvoidHours` accordingly
|
||||
3. Thailand timezone is UTC+7
|
||||
4. Test with different hour values
|
||||
|
||||
### Performance Issues
|
||||
|
||||
**Problem:** EA slow or causing MT4 lag
|
||||
|
||||
**Solutions:**
|
||||
1. Reduce `EMAPeriod` for faster calculations
|
||||
2. Disable MTF filter if not needed
|
||||
3. Close unnecessary charts and indicators
|
||||
4. Check MT4 and computer performance
|
||||
|
||||
## 📝 Best Practices
|
||||
|
||||
1. **Start Small:** Begin with minimum lot sizes and conservative settings
|
||||
2. **Test Thoroughly:** Use demo account before live trading
|
||||
3. **Monitor Regularly:** Check EA performance and adjust as needed
|
||||
4. **Keep Records:** Track trades and analyze performance
|
||||
5. **Stay Informed:** Be aware of market conditions and news events
|
||||
6. **Use Stop Loss:** Never disable risk management features
|
||||
7. **Diversify:** Don't rely on a single EA or strategy
|
||||
|
||||
## ⚠️ Disclaimer
|
||||
|
||||
**IMPORTANT NOTICE:**
|
||||
|
||||
Trading Forex and CFDs involves significant risk of loss and may not be suitable for all investors. MAEA is provided as-is without any warranty or guarantee of performance.
|
||||
|
||||
- Past performance is not indicative of future results
|
||||
- Always trade with money you can afford to lose
|
||||
- Test thoroughly on demo accounts before live trading
|
||||
- The authors are not responsible for any financial losses
|
||||
- Use at your own risk
|
||||
|
||||
**By using MAEA, you acknowledge that:**
|
||||
- You understand the risks involved in trading
|
||||
- You are solely responsible for your trading decisions
|
||||
- You will not hold the authors liable for any losses
|
||||
- You have read and understood this disclaimer
|
||||
|
||||
## 📞 Support
|
||||
|
||||
For issues, questions, or contributions:
|
||||
- **Repository:** https://git.moreminimore.com/kunthawat/MAEA
|
||||
- **Issues:** Report bugs or request features via repository issues
|
||||
|
||||
## 📄 License
|
||||
|
||||
This project is provided for educational and research purposes. Use responsibly and in accordance with your broker's terms of service.
|
||||
|
||||
---
|
||||
|
||||
**Version:** 1.00
|
||||
**Last Updated:** 2026-01-02
|
||||
**Timezone:** Thailand (UTC+7)
|
||||
13
opencode.jsonc
Normal file
13
opencode.jsonc
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"$schema": "https://opencode.ai/config.json",
|
||||
"mcp": {
|
||||
"mql5_help": {
|
||||
"type": "local",
|
||||
"command": [
|
||||
"npx",
|
||||
"-y",
|
||||
"github:caoshuo594/mql5-help-mcp"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,58 +2,44 @@
|
||||
|
||||
## Project Overview
|
||||
- **Name**: MAEA
|
||||
- **Type**: MQL4 Expert Advisor for MetaTrader 4
|
||||
- **Type**: MQL5 Expert Advisor for MetaTrader 5
|
||||
- **Strategy**: Advanced trend-following with EMA-based signals, multiple filters, and risk management
|
||||
- **Repository**: https://git.moreminimore.com/kunthawat/MAEA
|
||||
- **Timezone**: Thailand (UTC+7)
|
||||
|
||||
## Strategy Details
|
||||
|
||||
### 1. EMA Lines (3 Base Lines)
|
||||
### 1. EMA Lines (2 Base Lines)
|
||||
All EMAs use period 30 with different price sources:
|
||||
- **EMA High**: EMA of High prices - Light Blue color
|
||||
- **EMA Medium**: EMA of Close prices - Yellow color
|
||||
- **EMA Low**: EMA of Low prices - Orange color
|
||||
|
||||
### 2. Border Lines (2 Dynamic Lines)
|
||||
Calculated based on the range between EMAs:
|
||||
- **High Border Line**: EMA High + (EMA Medium - EMA Low) - Purple color
|
||||
- **Low Border Line**: EMA Low - (EMA Medium - EMA Low) - Purple color
|
||||
### 2. EMA Zone (Visual Area)
|
||||
- **Zone Definition**: The area between EMA High and EMA Low
|
||||
- **Visual**: Light yellow transparent fill between EMA High and EMA Low
|
||||
|
||||
**Example Calculation:**
|
||||
```
|
||||
EMA High = 3500
|
||||
EMA Medium = 3400
|
||||
EMA Low = 3300
|
||||
Range = EMA Medium - EMA Low = 3400 - 3300 = 100
|
||||
|
||||
High Border = 3500 + 100 = 3600
|
||||
Low Border = 3300 - 100 = 3200
|
||||
```
|
||||
|
||||
### 3. Signal Types
|
||||
### 3. Signal Type
|
||||
|
||||
#### 3.1 Breakthrough Signal
|
||||
- **Buy Signal**: Close price breaks above EMA High
|
||||
- **Sell Signal**: Close price breaks below EMA Low
|
||||
- **Purpose**: Triggers order opening
|
||||
- **Buy Signal**: Close price breaks above EMA High (zone breakout upward)
|
||||
- **Sell Signal**: Close price breaks below EMA Low (zone breakout downward)
|
||||
- **Purpose**: Triggers position opening/closing
|
||||
- **Logic**:
|
||||
- Previous close must be inside zone (between EMA High and EMA Low)
|
||||
- Current close must be outside zone
|
||||
- For buy: previous_close <= EMA_High AND current_close > EMA_High
|
||||
- For sell: previous_close >= EMA_Low AND current_close < EMA_Low
|
||||
|
||||
#### 3.2 Pullback Signal
|
||||
- **Definition**: Price hits a line and closes on the opposite side
|
||||
- **Buy Pullback**: Price moves down to hit any line, then closes above the line
|
||||
- **Sell Pullback**: Price moves up to hit any line, then closes below the line
|
||||
- **Purpose**: Increases lot size when breakthrough occurs in the same direction
|
||||
- **Tracking**: Separate tracking for buy and sell directions, resets when order opens
|
||||
- **Lot Size Impact**:
|
||||
- No pullback before breakthrough = 0.01 lot
|
||||
- Pullback occurred before breakthrough = 0.02 lot
|
||||
#### 3.2 Opposite Signal Close
|
||||
- **Close Buy Position**: When sell signal occurs (price breaks below EMA Low)
|
||||
- **Close Sell Position**: When buy signal occurs (price breaks above EMA High)
|
||||
- **Priority**: Opposite signal closes existing position immediately before opening new one
|
||||
|
||||
### 4. Order Opening Logic
|
||||
- **Only one order at a time**
|
||||
- **Lot Size**:
|
||||
- 0.01 lot if no pullback occurred before breakthrough
|
||||
- 0.02 lot if at least one pullback occurred before breakthrough in the same direction
|
||||
- **Only one position at a time**
|
||||
- **Lot Size**: Fixed 0.01 lot for all trades
|
||||
- **Trigger**: Breakthrough signal only
|
||||
- **Minimum Zone Width**: Zone must be at least 100 points before trading
|
||||
- **Filters Applied**:
|
||||
- Volume filter must pass
|
||||
- Spread filter must pass
|
||||
@@ -67,8 +53,8 @@ Low Border = 3300 - 100 = 3200
|
||||
- Closes order when profit reaches target amount
|
||||
|
||||
#### 5.2 Stop Loss
|
||||
- **Buy Orders**: SL at Low Border Line
|
||||
- **Sell Orders**: SL at High Border Line
|
||||
- **Buy Orders**: SL at EMA Low
|
||||
- **Sell Orders**: SL at EMA High
|
||||
|
||||
#### 5.3 Breakeven
|
||||
- Triggered when profit reaches specified number of points (e.g., 100 points)
|
||||
@@ -90,10 +76,10 @@ Low Border = 3300 - 100 = 3200
|
||||
- **Timeframes**: H1 (trading) and D1 (filter)
|
||||
- **Status**: Optional feature (can be turned on/off)
|
||||
- **D1 Filter Logic**:
|
||||
- If D1 close > D1 EMA High: Only buy orders allowed
|
||||
- If D1 close < D1 EMA Low: Only sell orders allowed
|
||||
- If D1 close between D1 EMA High and D1 EMA Low: No orders allowed
|
||||
- **Behavior**: Order opens immediately when filter condition is met
|
||||
- If D1 close > D1 EMA High: Only buy positions allowed (bullish trend)
|
||||
- If D1 close < D1 EMA Low: Only sell positions allowed (bearish trend)
|
||||
- If D1 close between D1 EMA High and D1 EMA Low: No positions allowed (no clear trend)
|
||||
- **Behavior**: Position opens immediately when filter condition is met
|
||||
|
||||
### 8. Spread Filter
|
||||
- **Purpose**: Avoid trading during high spread periods
|
||||
@@ -115,80 +101,83 @@ Low Border = 3300 - 100 = 3200
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[Start New Bar] --> B[Calculate EMAs]
|
||||
B --> C[Calculate Border Lines]
|
||||
C --> D[Check for Open Orders]
|
||||
D -->|Has Open Order| E[Manage Open Order]
|
||||
D -->|No Open Order| F[Check Pullback Signals]
|
||||
A[Start New Bar] --> B[Calculate EMA High/Low]
|
||||
B --> C[Fill Zone Between EMAs]
|
||||
C --> D[Check for Open Positions]
|
||||
D -->|Has Open Position| E[Check Opposite Signal]
|
||||
D -->|No Open Position| F[Check Breakthrough Signals]
|
||||
|
||||
E --> E1[Check Take Profit]
|
||||
E1 -->|TP Reached| E2[Close Order]
|
||||
E1 -->|TP Not Reached| E3[Check Breakeven]
|
||||
E3 -->|Breakeven Reached| E4[Move SL to Entry]
|
||||
E3 -->|Breakeven Not Reached| E5[Check Stop Loss]
|
||||
E5 -->|SL Hit| E2
|
||||
E5 -->|SL Not Hit| A
|
||||
E --> E1{Opposite Signal?}
|
||||
E1 -->|Buy open, Sell signal| E2[Close Buy Position]
|
||||
E1 -->|Sell open, Buy signal| E3[Close Sell Position]
|
||||
E1 -->|No opposite signal| E4[Manage Position Risks]
|
||||
E2 --> A
|
||||
E3 --> A
|
||||
|
||||
F --> F1[Close Below EMA High]
|
||||
F1 -->|Yes| F2[Set Pullback Flag]
|
||||
F1 -->|No| F3[Close Below EMA Medium]
|
||||
F3 -->|Yes| F2
|
||||
F3 -->|No| F4[Close Below EMA Low]
|
||||
F4 -->|Yes| F2
|
||||
F4 -->|No| F5[Check Breakthrough Signals]
|
||||
E4 --> E5[Check Take Profit]
|
||||
E5 -->|TP Reached| E6[Close Position]
|
||||
E5 -->|TP Not Reached| E7[Check Breakeven]
|
||||
E7 -->|Breakeven Reached| E8[Move SL to Entry]
|
||||
E7 -->|Breakeven Not Reached| E9[Check SL Hit]
|
||||
E9 -->|SL Hit| E6
|
||||
E9 -->|SL Not Hit| A
|
||||
E6 --> A
|
||||
|
||||
F2 --> F5
|
||||
F5 --> F6[Close Above EMA High]
|
||||
F6 -->|Yes| F7[Open Buy Order]
|
||||
F6 -->|No| F8[Close Below EMA Low]
|
||||
F8 -->|Yes| F9[Open Sell Order]
|
||||
F8 -->|No| A
|
||||
F --> F1{Previous Close Inside Zone?}
|
||||
F1 -->|No| A
|
||||
F1 -->|Yes| F2{Zone Width >= 100 points?}
|
||||
F2 -->|No| A
|
||||
F2 -->|Yes| F3{Current Close Direction}
|
||||
F3 -->|Close > EMA High| F4[Check Filters]
|
||||
F3 -->|Close < EMA Low| F5[Check Filters]
|
||||
F3 -->|Still Inside| A
|
||||
|
||||
F7 --> F10[Set Lot Size]
|
||||
F10 -->|Pullback| F11[0.02 Lot]
|
||||
F10 -->|No Pullback| F12[0.01 Lot]
|
||||
F11 --> F13[Set SL at Low Border]
|
||||
F12 --> F13
|
||||
F13 --> F14[Set TP based on USD Target]
|
||||
F14 --> F15[Reset Pullback Flag]
|
||||
F15 --> A
|
||||
F4 --> F6{Volume OK? Spread OK? MTF OK? News OK?}
|
||||
F5 --> F6
|
||||
F6 -->|All Pass| F7[Open Buy Position]
|
||||
F6 -->|Any Fail| A
|
||||
|
||||
F9 --> F16[Set Lot Size]
|
||||
F16 -->|Pullback| F17[0.02 Lot]
|
||||
F16 -->|No Pullback| F18[0.01 Lot]
|
||||
F17 --> F19[Set SL at High Border]
|
||||
F18 --> F19
|
||||
F19 --> F20[Set TP based on USD Target]
|
||||
F20 --> F21[Reset Pullback Flag]
|
||||
F21 --> A
|
||||
F7 --> F8[Set SL at EMA Low]
|
||||
F8 --> F9[Set TP based on USD Target]
|
||||
F9 --> A
|
||||
|
||||
E2 --> F15
|
||||
F5 --> F10{Volume OK? Spread OK? MTF OK? News OK?}
|
||||
F10 -->|All Pass| F11[Open Sell Position]
|
||||
F10 -->|Any Fail| A
|
||||
|
||||
F11 --> F12[Set SL at EMA High]
|
||||
F12 --> F13[Set TP based on USD Target]
|
||||
F13 --> A
|
||||
```
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Project Setup & Git Configuration
|
||||
1. Create MQL4 project structure
|
||||
1. Create MQL5 project structure
|
||||
2. Initialize Git repository
|
||||
3. Configure remote to Gitea server (https://git.moreminimore.com/kunthawat/MAEA)
|
||||
|
||||
### Phase 2: Core EA Structure
|
||||
4. Create [`MAEA.mq4`](MAEA.mq4) with basic EA framework
|
||||
5. Define all input parameters (EMA period, lot sizes, TP, breakeven, trailing stop, filters, etc.)
|
||||
6. Set up indicator buffers for 5 visual lines
|
||||
4. Create [`MAEA.mq5`](MAEA.mq5) with basic EA framework
|
||||
5. Define all input parameters (EMA period, lot size, TP, breakeven, trailing stop, filters, etc.)
|
||||
6. Set up indicator buffers for 2 EMA lines + zone fill (3 buffers total)
|
||||
7. Initialize global variables for state tracking
|
||||
|
||||
### Phase 3: Indicator Calculations
|
||||
8. Implement EMA calculations for High, Medium, Low (period 30)
|
||||
9. Implement Border Line calculations (High Border = High + Range, Low Border = Low - Range)
|
||||
10. Add visual indicators with correct colors (Light Blue, Yellow, Orange, Purple)
|
||||
8. Implement EMA calculations for High and Low (period 30)
|
||||
9. Implement zone fill between EMA High and EMA Low (transparent light yellow)
|
||||
10. Add visual indicators with correct colors (Light Blue for EMA High, Orange for EMA Low)
|
||||
11. Implement Volume average calculation (20-bar average)
|
||||
|
||||
### Phase 4: Signal Detection
|
||||
12. Implement breakthrough signal detection (price breaks High/Low EMA)
|
||||
13. Implement pullback signal detection (price hits line and closes on opposite side)
|
||||
14. Implement separate pullback tracking for buy and sell directions
|
||||
15. Implement pullback flag reset logic after order opens
|
||||
12. Implement breakthrough signal detection
|
||||
- Check if previous close was inside zone
|
||||
- Check if current close broke above EMA High or below EMA Low
|
||||
13. Implement opposite signal detection and position closing
|
||||
- If buy position open and sell signal occurs: close buy
|
||||
- If sell position open and buy signal occurs: close sell
|
||||
14. Implement minimum zone width check (100 points)
|
||||
15. Implement single position check
|
||||
|
||||
### Phase 5: Multiple Timeframe Filter
|
||||
16. Implement D1 EMA calculations for MTF filter
|
||||
@@ -202,13 +191,15 @@ graph TD
|
||||
22. Add enable/disable toggles for news filter
|
||||
|
||||
### Phase 7: Order Management
|
||||
23. Implement order opening logic with all filter checks
|
||||
24. Implement dynamic lot sizing (0.01 no pullback, 0.02 with pullback)
|
||||
25. Implement Stop Loss placement at Border Lines
|
||||
23. Implement position opening logic with all filter checks
|
||||
24. Implement fixed lot sizing (0.01 lot)
|
||||
25. Implement Stop Loss placement at opposite EMA
|
||||
- Buy: SL at EMA Low
|
||||
- Sell: SL at EMA High
|
||||
26. Implement Take Profit calculation (convert USD target to pips)
|
||||
27. Implement Breakeven logic (move SL to entry at X points)
|
||||
28. Implement Trailing Stop logic (trail by X points after breakeven)
|
||||
29. Implement single order restriction
|
||||
29. Implement single position restriction (use PositionsTotal())
|
||||
|
||||
### Phase 8: Risk Management
|
||||
30. Implement max drawdown calculation
|
||||
@@ -216,20 +207,24 @@ graph TD
|
||||
32. Implement trading resume logic when drawdown is below limit
|
||||
|
||||
### Phase 9: Order Monitoring & Management
|
||||
33. Implement Take Profit checking on each tick
|
||||
34. Implement Breakeven checking and SL modification
|
||||
35. Implement Trailing Stop checking and SL modification
|
||||
36. Implement Stop Loss checking
|
||||
37. Implement order closure logic
|
||||
33. Implement opposite signal checking on each tick
|
||||
34. If opposite signal detected, close existing position immediately
|
||||
35. Implement Take Profit checking on each tick
|
||||
36. Implement Breakeven checking and SL modification
|
||||
37. Implement Trailing Stop checking and SL modification
|
||||
38. Implement Stop Loss checking
|
||||
39. Implement position closure logic
|
||||
|
||||
### Phase 10: Testing & Validation
|
||||
38. Test all EMA and Border Line calculations
|
||||
39. Test breakthrough and pullback signal detection
|
||||
40. Test all filters (volume, spread, MTF, news)
|
||||
41. Test order opening with correct lot sizes
|
||||
42. Test TP, SL, breakeven, and trailing stop
|
||||
43. Test drawdown protection
|
||||
44. Test visual indicators display
|
||||
38. Test EMA High and Low calculations
|
||||
39. Test zone fill visualization (transparent yellow)
|
||||
40. Test breakthrough signal detection
|
||||
- Verify breakout requires previous close inside zone
|
||||
41. Test all filters (volume, spread, MTF, news)
|
||||
42. Test position opening with fixed 0.01 lot
|
||||
43. Test TP, SL (at opposite EMA), breakeven, and trailing stop
|
||||
44. Test drawdown protection
|
||||
45. Test visual indicators display
|
||||
|
||||
### Phase 11: Documentation & Deployment
|
||||
45. Create comprehensive [`README.md`](README.md) with strategy documentation
|
||||
@@ -243,15 +238,15 @@ graph TD
|
||||
|
||||
| Parameter | Description | Default Value |
|
||||
|-----------|-------------|---------------|
|
||||
| `EMAPeriod` | EMA period for all lines | 30 |
|
||||
| `LotSizeNormal` | Lot size without pullback | 0.01 |
|
||||
| `LotSizePullback` | Lot size with pullback | 0.02 |
|
||||
| `EMAPeriod` | EMA period for both lines | 30 |
|
||||
| `LotSize` | Fixed lot size | 0.01 |
|
||||
| `TakeProfitUSD` | Take profit target in USD | 5.0 |
|
||||
| `BreakevenPoints` | Points to trigger breakeven | 100 |
|
||||
| `TrailingStopPoints` | Points for trailing stop distance | 100 |
|
||||
| `MagicNumber` | EA unique identifier | 12345 |
|
||||
| `MaxSpread` | Maximum allowed spread in points | 30 |
|
||||
| `VolumePeriod` | Period for volume average calculation | 20 |
|
||||
| `MinZoneWidthPoints` | Minimum zone width to trade (points) | 100 |
|
||||
| `MaxDrawdownPercent` | Maximum drawdown percentage | 10.0 |
|
||||
| `UseMTFFilter` | Enable/disable MTF filter | true |
|
||||
| `UseNewsFilter` | Enable/disable news filter | true |
|
||||
@@ -263,61 +258,73 @@ graph TD
|
||||
| Line | Color | Description |
|
||||
|------|-------|-------------|
|
||||
| EMA High | Light Blue (clrLightBlue) | EMA of High prices |
|
||||
| EMA Medium | Yellow (clrYellow) | EMA of Close prices |
|
||||
| EMA Low | Orange (clrOrange) | EMA of Low prices |
|
||||
| High Border | Purple (clrPurple) | Upper dynamic border |
|
||||
| Low Border | Purple (clrPurple) | Lower dynamic border |
|
||||
| Zone Fill | Light Yellow (transparent) | Area between EMA High and EMA Low |
|
||||
|
||||
## Key Considerations
|
||||
|
||||
1. **Pullback Detection**: Track price hitting lines and closing on opposite side separately for buy/sell
|
||||
2. **Pullback Reset**: Reset pullback flag immediately after opening an order
|
||||
3. **Single Order**: Only one order open at any time
|
||||
4. **Dynamic SL**: Stop Loss moves with Border Lines as they update
|
||||
5. **Breakeven**: Only moves SL to entry price, not to profit
|
||||
6. **TP Calculation**: Convert USD target to pips based on lot size and symbol
|
||||
7. **Volume Filter**: Only trade when current volume exceeds 20-bar average
|
||||
8. **MTF Filter**: D1 timeframe acts as trend filter, H1 for entry signals
|
||||
9. **Spread Filter**: Avoid high spread periods
|
||||
10. **Timezone**: All time-based filters use Thailand timezone (UTC+7)
|
||||
11. **Trailing Stop**: Activates after breakeven, trails by specified points
|
||||
12. **Drawdown Protection**: Stops trading if max drawdown exceeded
|
||||
1. **Breakthrough Detection**: Previous close must be inside zone, current close outside zone
|
||||
2. **Opposite Signal Close**: Close existing position when opposite breakthrough signal occurs
|
||||
3. **Minimum Zone Width**: Zone must be at least 100 points wide before trading
|
||||
4. **Single Position**: Only one position open at any time (MT5 uses positions, not orders)
|
||||
5. **SL at Opposite EMA**: Buy SL at EMA Low, Sell SL at EMA High
|
||||
6. **Fixed Lot Size**: Always 0.01 lot regardless of market conditions
|
||||
7. **Breakeven**: Only moves SL to entry price, not to profit
|
||||
8. **TP Calculation**: Convert USD target to pips based on lot size and symbol
|
||||
9. **Volume Filter**: Only trade when current volume exceeds 20-bar average
|
||||
10. **MTF Filter**: D1 price position relative to zone determines allowed direction
|
||||
11. **Spread Filter**: Avoid high spread periods
|
||||
12. **Timezone**: All time-based filters use Thailand timezone (UTC+7)
|
||||
13. **Trailing Stop**: Activates after breakeven, trails by specified points
|
||||
14. **Drawdown Protection**: Stops trading if max drawdown exceeded
|
||||
15. **Zone Visualization**: Light yellow transparent fill between EMA High and EMA Low
|
||||
|
||||
## Technical Specifications
|
||||
|
||||
- **Platform**: MetaTrader 4
|
||||
- **Language**: MQL4
|
||||
- **Platform**: MetaTrader 5
|
||||
- **Language**: MQL5
|
||||
- **Trading Timeframe**: H1 (recommended)
|
||||
- **Filter Timeframe**: D1 (for MTF filter)
|
||||
- **Currency Pairs**: All pairs (user-selectable)
|
||||
- **Account Types**: Any MT4 account type
|
||||
- **Account Types**: Any MT5 account type
|
||||
- **Server Timezone**: Thailand (UTC+7)
|
||||
|
||||
## Testing Checklist
|
||||
|
||||
### Core Strategy
|
||||
- [ ] EMA calculations verify correctly (High, Medium, Low)
|
||||
- [ ] Border Line calculations verify correctly
|
||||
- [ ] EMA calculations verify correctly (High and Low)
|
||||
- [ ] Zone fill displays correctly (light yellow, transparent)
|
||||
- [ ] Zone width calculation verify correctly (in points)
|
||||
- [ ] Minimum zone width filter works (100 points minimum)
|
||||
- [ ] Breakthrough signals trigger correctly
|
||||
- [ ] Pullback signals detect correctly (buy and sell separately)
|
||||
- [ ] Pullback flag resets after order opens
|
||||
- [ ] Lot sizes apply correctly (0.01 vs 0.02)
|
||||
- [ ] Previous close inside zone check
|
||||
- [ ] Buy signal: close > EMA High
|
||||
- [ ] Sell signal: close < EMA Low
|
||||
- [ ] Opposite signal detection works
|
||||
- [ ] Buy position closes when sell signal occurs
|
||||
- [ ] Sell position closes when buy signal occurs
|
||||
|
||||
### Filters
|
||||
- [ ] Volume filter works (20-bar average, current > average)
|
||||
- [ ] Spread filter prevents high spread trades
|
||||
- [ ] MTF filter works correctly (D1 > High = buy only, D1 < Low = sell only, between = no trade)
|
||||
- [ ] MTF filter works correctly
|
||||
- [ ] D1 close > EMA High: buy only
|
||||
- [ ] D1 close < EMA Low: sell only
|
||||
- [ ] D1 close between: no trade
|
||||
- [ ] MTF filter can be enabled/disabled
|
||||
- [ ] Min zone width filter works (100 points minimum)
|
||||
- [ ] News filter avoids specified times (Thailand timezone)
|
||||
- [ ] News filter can be enabled/disabled
|
||||
|
||||
### Order Management
|
||||
- [ ] Stop Loss places at correct Border Lines
|
||||
- [ ] Stop Loss places at opposite EMA (Buy: EMA Low, Sell: EMA High)
|
||||
- [ ] Take Profit closes at correct USD amount
|
||||
- [ ] Breakeven triggers at correct points
|
||||
- [ ] Trailing stop activates after breakeven
|
||||
- [ ] Trailing stop trails by correct distance
|
||||
- [ ] Only one order opens at a time
|
||||
- [ ] Opposite signal closes existing position immediately
|
||||
- [ ] Only one position opens at a time
|
||||
- [ ] Fixed lot size always 0.01
|
||||
|
||||
### Risk Management
|
||||
- [ ] Max drawdown protection works
|
||||
@@ -332,11 +339,15 @@ graph TD
|
||||
|
||||
## Notes
|
||||
|
||||
- The strategy uses 5 visual lines on the chart
|
||||
- Pullback tracking is separate for buy and sell directions
|
||||
- Border Lines expand the range beyond the EMAs for wider stops
|
||||
- The strategy uses 2 EMA lines with a filled zone between them
|
||||
- No pullback tracking or dynamic lot sizing - simplified approach
|
||||
- Fixed lot size: 0.01 for all trades
|
||||
- Positions close when opposite signal occurs (reversal protection)
|
||||
- Minimum zone width of 100 points ensures meaningful setups
|
||||
- The strategy is trend-following and works best in trending markets
|
||||
- Breakthrough signals require price to be inside zone before breaking out
|
||||
- Multiple filters ensure quality trade entries
|
||||
- All time-based calculations use Thailand timezone (UTC+7)
|
||||
- MTF filter provides higher timeframe trend confirmation
|
||||
- MTF filter matches price position relative to D1 zone
|
||||
- Risk management features protect account from excessive losses
|
||||
- Zone fill uses light yellow color with transparency for better visibility
|
||||
@@ -1,39 +1,37 @@
|
||||
# MAEA Project Summary
|
||||
|
||||
## Project Overview
|
||||
**MAEA (Moving Average Expert Advisor)** - An advanced trend-following trading robot for MetaTrader 4 with sophisticated filtering and risk management features.
|
||||
**MAEA (Moving Average Expert Advisor)** - An advanced trend-following trading robot for MetaTrader 5 with sophisticated filtering and risk management features.
|
||||
|
||||
**Repository:** https://git.moreminimore.com/kunthawat/MAEA
|
||||
**Timezone:** Thailand (UTC+7)
|
||||
|
||||
## Core Strategy
|
||||
|
||||
### Indicator System (5 Visual Lines)
|
||||
### Indicator System (2 EMA Lines + Zone)
|
||||
1. **EMA High** (Light Blue) - EMA of High prices, period 30
|
||||
2. **EMA Medium** (Yellow) - EMA of Close prices, period 30
|
||||
3. **EMA Low** (Orange) - EMA of Low prices, period 30
|
||||
4. **High Border** (Purple) - EMA High + (EMA Medium - EMA Low)
|
||||
5. **Low Border** (Purple) - EMA Low - (EMA Medium - EMA Low)
|
||||
2. **EMA Low** (Orange) - EMA of Low prices, period 30
|
||||
3. **Zone Fill** (Light Yellow, transparent) - Area between EMA High and EMA Low
|
||||
|
||||
### Signal Types
|
||||
|
||||
#### 1. Breakthrough Signal
|
||||
- **Buy:** Close price breaks above EMA High
|
||||
- **Sell:** Close price breaks below EMA Low
|
||||
- **Purpose:** Triggers order opening
|
||||
- **Buy:** Close price breaks above EMA High (must have previous close inside zone)
|
||||
- **Sell:** Close price breaks below EMA Low (must have previous close inside zone)
|
||||
- **Purpose:** Triggers position opening
|
||||
- **Verification:** Previous bar close must be inside zone between EMA High and EMA Low
|
||||
|
||||
#### 2. Pullback Signal
|
||||
- **Buy Pullback:** Price moves down to hit any line, then closes above the line
|
||||
- **Sell Pullback:** Price moves up to hit any line, then closes below the line
|
||||
- **Purpose:** Increases lot size when breakthrough occurs in same direction
|
||||
- **Tracking:** Separate for buy and sell directions
|
||||
#### 2. Opposite Signal Close
|
||||
- **Close Buy:** When sell signal occurs (price breaks below EMA Low)
|
||||
- **Close Sell:** When buy signal occurs (price breaks above EMA High)
|
||||
- **Immediate Action:** Position closes before checking for new trade
|
||||
|
||||
### Order Management
|
||||
- **Single Order:** Only one order at a time
|
||||
- **Dynamic Lot Sizing:**
|
||||
- 0.01 lot (no pullback before breakthrough)
|
||||
- 0.02 lot (pullback occurred before breakthrough)
|
||||
- **Stop Loss:** At Border Lines (Low Border for buys, High Border for sells)
|
||||
- **Single Position:** Only one position open at a time (MT5 uses positions, not orders)
|
||||
- **Fixed Lot Size:** 0.01 lot for all trades
|
||||
- **Stop Loss:** At opposite EMA (Buy: EMA Low, Sell: EMA High)
|
||||
- **Reverse Protection:** Close position when opposite signal occurs
|
||||
- **Min Zone Width:** Zone must be at least 100 points to trade
|
||||
- **Take Profit:** Target in USD (default $5)
|
||||
- **Breakeven:** Move SL to entry at X points profit (default 100)
|
||||
- **Trailing Stop:** Trail by X points after breakeven (default 100)
|
||||
@@ -42,8 +40,9 @@
|
||||
|
||||
### 1. Volume Filter
|
||||
- Calculate 20-bar volume average
|
||||
- Trade only when current volume > average
|
||||
- Ensures sufficient market activity
|
||||
- Trade only when current volume > average
|
||||
- Ensures sufficient market activity
|
||||
- Note: MT5 uses tick volume by default (similar to MT4)
|
||||
|
||||
### 2. Spread Filter
|
||||
- Maximum allowed spread: 30 points
|
||||
@@ -53,9 +52,9 @@
|
||||
- **Trading Timeframe:** H1
|
||||
- **Filter Timeframe:** D1
|
||||
- **Logic:**
|
||||
- D1 close > D1 EMA High: Only buy orders allowed
|
||||
- D1 close < D1 EMA Low: Only sell orders allowed
|
||||
- D1 close between: No orders allowed
|
||||
- D1 close > D1 EMA High: Only buy positions allowed (bullish)
|
||||
- D1 close < D1 EMA Low: Only sell positions allowed (bearish)
|
||||
- D1 close between: No positions allowed (no trend)
|
||||
- Can be enabled/disabled
|
||||
|
||||
### 4. News Filter (Optional)
|
||||
@@ -69,30 +68,38 @@
|
||||
- Stops trading if drawdown exceeds limit
|
||||
- Resumes trading when drawdown is below limit
|
||||
|
||||
### 6. Zone Width Filter
|
||||
- **Min Zone Width:** 100 points minimum before trading
|
||||
- Ensures meaningful trend setups
|
||||
- Prevents trading during tight consolidation
|
||||
|
||||
## Implementation Phases
|
||||
|
||||
### Phase 1: Project Setup & Git Configuration (3 tasks)
|
||||
- Create MQL4 project structure
|
||||
- Create MQL5 project structure
|
||||
- Initialize Git repository
|
||||
- Configure remote to Gitea server
|
||||
|
||||
### Phase 2: Core EA Structure (4 tasks)
|
||||
- Create MAEA.mq4 with basic framework
|
||||
- Create MAEA.mq5 with basic framework
|
||||
- Define all input parameters
|
||||
- Set up indicator buffers
|
||||
- Initialize global variables
|
||||
|
||||
### Phase 3: Indicator Calculations (4 tasks)
|
||||
- Implement EMA calculations (High, Medium, Low)
|
||||
- Implement Border Line calculations
|
||||
- Add visual indicators with colors
|
||||
- Implement EMA calculations (High and Low only)
|
||||
- Implement zone fill between EMA High and EMA Low
|
||||
- Add visual indicators with colors (Light Blue, Orange, Light Yellow fill)
|
||||
- Implement Volume average calculation
|
||||
|
||||
### Phase 4: Signal Detection (4 tasks)
|
||||
### Phase 4: Signal Detection (3 tasks)
|
||||
- Implement breakthrough signal detection
|
||||
- Implement pullback signal detection
|
||||
- Implement separate pullback tracking
|
||||
- Implement pullback flag reset logic
|
||||
- Check if previous close inside zone
|
||||
- Check if current close broke above EMA High or below EMA Low
|
||||
- Implement opposite signal detection and position closing
|
||||
- Close buy position when sell signal occurs
|
||||
- Close sell position when buy signal occurs
|
||||
- Implement minimum zone width check (100 points)
|
||||
|
||||
### Phase 5: Multiple Timeframe Filter (3 tasks)
|
||||
- Implement D1 EMA calculations
|
||||
@@ -106,31 +113,37 @@
|
||||
- Add enable/disable toggle for news filter
|
||||
|
||||
### Phase 7: Order Management (7 tasks)
|
||||
- Implement order opening with all filters
|
||||
- Implement dynamic lot sizing
|
||||
- Implement Stop Loss placement
|
||||
- Implement position opening with all filters
|
||||
- Implement fixed lot sizing (0.01 lot)
|
||||
- Implement Stop Loss placement at opposite EMA
|
||||
- Implement Take Profit calculation
|
||||
- Implement Breakeven logic
|
||||
- Implement Trailing Stop logic
|
||||
- Implement single order restriction
|
||||
- Implement single position restriction
|
||||
|
||||
### Phase 8: Risk Management (3 tasks)
|
||||
- Implement max drawdown calculation
|
||||
- Implement drawdown protection
|
||||
- Implement trading resume logic
|
||||
|
||||
### Phase 9: Order Monitoring & Management (5 tasks)
|
||||
### Phase 9: Order Monitoring & Management (6 tasks)
|
||||
- Implement opposite signal checking on each tick
|
||||
- Close position when opposite signal detected
|
||||
- Implement Take Profit checking
|
||||
- Implement Breakeven checking and SL modification
|
||||
- Implement Trailing Stop checking and SL modification
|
||||
- Implement Stop Loss checking
|
||||
- Implement order closure logic
|
||||
- Implement position closure logic
|
||||
|
||||
### Phase 10: Testing & Validation (7 tasks)
|
||||
- Test all EMA and Border Line calculations
|
||||
- Test breakthrough and pullback signals
|
||||
### Phase 10: Testing & Validation (8 tasks)
|
||||
- Test EMA High and Low calculations
|
||||
- Test zone fill visualization
|
||||
- Test zone width calculation
|
||||
- Test minimum zone width filter (100 points)
|
||||
- Test breakthrough signal detection (with zone check)
|
||||
- Test opposite signal detection and position closing
|
||||
- Test all filters
|
||||
- Test order opening with correct lot sizes
|
||||
- Test position opening with fixed 0.01 lot
|
||||
- Test TP, SL, breakeven, and trailing stop
|
||||
- Test drawdown protection
|
||||
- Test visual indicators display
|
||||
@@ -142,44 +155,46 @@
|
||||
- Commit initial code to Git
|
||||
- Push to Gitea repository and verify
|
||||
|
||||
## Total Tasks: 50
|
||||
## Total Tasks: 51
|
||||
|
||||
## Key Features Summary
|
||||
|
||||
✅ **Advanced Trend Following:** EMA-based with dynamic border lines
|
||||
✅ **Smart Signal Detection:** Breakthrough and pullback signals with separate tracking
|
||||
✅ **Dynamic Lot Sizing:** 0.01 or 0.02 based on market behavior
|
||||
✅ **Simple Trend Following:** EMA-based with visual zone fill
|
||||
✅ **Clear Breakthrough Signals:** Zone breakout with previous bar confirmation
|
||||
✅ **Reverse Protection:** Positions close when opposite signal occurs
|
||||
✅ **Minimum Zone Width:** 100 points requirement for meaningful setups
|
||||
✅ **Fixed Lot Size:** Consistent 0.01 lot position sizing
|
||||
✅ **Comprehensive Filters:** Volume, spread, MTF, news, and drawdown protection
|
||||
✅ **Risk Management:** TP in USD, SL at borders, breakeven, trailing stop
|
||||
✅ **Visual Indicators:** 5 colored lines for easy analysis
|
||||
✅ **Risk Management:** TP in USD, SL at opposite EMA, breakeven, trailing stop
|
||||
✅ **Visual Indicators:** 2 EMAs with light yellow zone fill
|
||||
✅ **Flexible Configuration:** All features can be enabled/disabled
|
||||
✅ **Single Order Management:** Prevents over-trading
|
||||
✅ **Single Position Management:** Prevents over-trading
|
||||
✅ **Timezone Aware:** Thailand timezone (UTC+7) for all time-based features
|
||||
|
||||
## Default Parameters
|
||||
|
||||
| Parameter | Value | Description |
|
||||
|-----------|-------|-------------|
|
||||
| EMA Period | 30 | Period for all EMAs |
|
||||
| Lot Size (Normal) | 0.01 | Lot without pullback |
|
||||
| Lot Size (Pullback) | 0.02 | Lot with pullback |
|
||||
| EMA Period | 30 | Period for EMA High and EMA Low |
|
||||
| Lot Size | 0.01 | Fixed lot size for all trades |
|
||||
| Take Profit | $5 | Target profit in USD |
|
||||
| Breakeven Points | 100 | Points to trigger breakeven |
|
||||
| Trailing Stop Points | 100 | Trail distance after breakeven |
|
||||
| Max Spread | 30 points | Maximum allowed spread |
|
||||
| Volume Period | 20 | Bars for volume average |
|
||||
| Min Zone Width | 100 points | Minimum zone width to trade |
|
||||
| Max Drawdown | 10% | Maximum drawdown percentage |
|
||||
| MTF Filter | true | Enable/disable MTF filter |
|
||||
| News Filter | true | Enable/disable news filter |
|
||||
|
||||
## Technical Specifications
|
||||
|
||||
- **Platform:** MetaTrader 4
|
||||
- **Language:** MQL4
|
||||
- **Platform:** MetaTrader 5
|
||||
- **Language:** MQL5
|
||||
- **Trading Timeframe:** H1 (recommended)
|
||||
- **Filter Timeframe:** D1 (for MTF)
|
||||
- **Currency Pairs:** All pairs (user-selectable)
|
||||
- **Account Types:** Any MT4 account
|
||||
- **Account Types:** Any MT5 account
|
||||
- **Server Timezone:** Thailand (UTC+7)
|
||||
|
||||
## Next Steps
|
||||
|
||||
Reference in New Issue
Block a user