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
|
## Project Overview
|
||||||
- **Name**: MAEA
|
- **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
|
- **Strategy**: Advanced trend-following with EMA-based signals, multiple filters, and risk management
|
||||||
- **Repository**: https://git.moreminimore.com/kunthawat/MAEA
|
- **Repository**: https://git.moreminimore.com/kunthawat/MAEA
|
||||||
- **Timezone**: Thailand (UTC+7)
|
- **Timezone**: Thailand (UTC+7)
|
||||||
|
|
||||||
## Strategy Details
|
## Strategy Details
|
||||||
|
|
||||||
### 1. EMA Lines (3 Base Lines)
|
### 1. EMA Lines (2 Base Lines)
|
||||||
All EMAs use period 30 with different price sources:
|
All EMAs use period 30 with different price sources:
|
||||||
- **EMA High**: EMA of High prices - Light Blue color
|
- **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
|
- **EMA Low**: EMA of Low prices - Orange color
|
||||||
|
|
||||||
### 2. Border Lines (2 Dynamic Lines)
|
### 2. EMA Zone (Visual Area)
|
||||||
Calculated based on the range between EMAs:
|
- **Zone Definition**: The area between EMA High and EMA Low
|
||||||
- **High Border Line**: EMA High + (EMA Medium - EMA Low) - Purple color
|
- **Visual**: Light yellow transparent fill between EMA High and EMA Low
|
||||||
- **Low Border Line**: EMA Low - (EMA Medium - EMA Low) - Purple color
|
|
||||||
|
|
||||||
**Example Calculation:**
|
### 3. Signal Type
|
||||||
```
|
|
||||||
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.1 Breakthrough Signal
|
#### 3.1 Breakthrough Signal
|
||||||
- **Buy Signal**: Close price breaks above EMA High
|
- **Buy Signal**: Close price breaks above EMA High (zone breakout upward)
|
||||||
- **Sell Signal**: Close price breaks below EMA Low
|
- **Sell Signal**: Close price breaks below EMA Low (zone breakout downward)
|
||||||
- **Purpose**: Triggers order opening
|
- **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
|
#### 3.2 Opposite Signal Close
|
||||||
- **Definition**: Price hits a line and closes on the opposite side
|
- **Close Buy Position**: When sell signal occurs (price breaks below EMA Low)
|
||||||
- **Buy Pullback**: Price moves down to hit any line, then closes above the line
|
- **Close Sell Position**: When buy signal occurs (price breaks above EMA High)
|
||||||
- **Sell Pullback**: Price moves up to hit any line, then closes below the line
|
- **Priority**: Opposite signal closes existing position immediately before opening new one
|
||||||
- **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
|
|
||||||
|
|
||||||
### 4. Order Opening Logic
|
### 4. Order Opening Logic
|
||||||
- **Only one order at a time**
|
- **Only one position at a time**
|
||||||
- **Lot Size**:
|
- **Lot Size**: Fixed 0.01 lot for all trades
|
||||||
- 0.01 lot if no pullback occurred before breakthrough
|
|
||||||
- 0.02 lot if at least one pullback occurred before breakthrough in the same direction
|
|
||||||
- **Trigger**: Breakthrough signal only
|
- **Trigger**: Breakthrough signal only
|
||||||
|
- **Minimum Zone Width**: Zone must be at least 100 points before trading
|
||||||
- **Filters Applied**:
|
- **Filters Applied**:
|
||||||
- Volume filter must pass
|
- Volume filter must pass
|
||||||
- Spread filter must pass
|
- Spread filter must pass
|
||||||
@@ -67,8 +53,8 @@ Low Border = 3300 - 100 = 3200
|
|||||||
- Closes order when profit reaches target amount
|
- Closes order when profit reaches target amount
|
||||||
|
|
||||||
#### 5.2 Stop Loss
|
#### 5.2 Stop Loss
|
||||||
- **Buy Orders**: SL at Low Border Line
|
- **Buy Orders**: SL at EMA Low
|
||||||
- **Sell Orders**: SL at High Border Line
|
- **Sell Orders**: SL at EMA High
|
||||||
|
|
||||||
#### 5.3 Breakeven
|
#### 5.3 Breakeven
|
||||||
- Triggered when profit reaches specified number of points (e.g., 100 points)
|
- 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)
|
- **Timeframes**: H1 (trading) and D1 (filter)
|
||||||
- **Status**: Optional feature (can be turned on/off)
|
- **Status**: Optional feature (can be turned on/off)
|
||||||
- **D1 Filter Logic**:
|
- **D1 Filter Logic**:
|
||||||
- If D1 close > D1 EMA High: Only buy orders allowed
|
- If D1 close > D1 EMA High: Only buy positions allowed (bullish trend)
|
||||||
- If D1 close < D1 EMA Low: Only sell orders allowed
|
- If D1 close < D1 EMA Low: Only sell positions allowed (bearish trend)
|
||||||
- If D1 close between D1 EMA High and D1 EMA Low: No orders allowed
|
- If D1 close between D1 EMA High and D1 EMA Low: No positions allowed (no clear trend)
|
||||||
- **Behavior**: Order opens immediately when filter condition is met
|
- **Behavior**: Position opens immediately when filter condition is met
|
||||||
|
|
||||||
### 8. Spread Filter
|
### 8. Spread Filter
|
||||||
- **Purpose**: Avoid trading during high spread periods
|
- **Purpose**: Avoid trading during high spread periods
|
||||||
@@ -115,80 +101,83 @@ Low Border = 3300 - 100 = 3200
|
|||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
graph TD
|
graph TD
|
||||||
A[Start New Bar] --> B[Calculate EMAs]
|
A[Start New Bar] --> B[Calculate EMA High/Low]
|
||||||
B --> C[Calculate Border Lines]
|
B --> C[Fill Zone Between EMAs]
|
||||||
C --> D[Check for Open Orders]
|
C --> D[Check for Open Positions]
|
||||||
D -->|Has Open Order| E[Manage Open Order]
|
D -->|Has Open Position| E[Check Opposite Signal]
|
||||||
D -->|No Open Order| F[Check Pullback Signals]
|
D -->|No Open Position| F[Check Breakthrough Signals]
|
||||||
|
|
||||||
E --> E1[Check Take Profit]
|
E --> E1{Opposite Signal?}
|
||||||
E1 -->|TP Reached| E2[Close Order]
|
E1 -->|Buy open, Sell signal| E2[Close Buy Position]
|
||||||
E1 -->|TP Not Reached| E3[Check Breakeven]
|
E1 -->|Sell open, Buy signal| E3[Close Sell Position]
|
||||||
E3 -->|Breakeven Reached| E4[Move SL to Entry]
|
E1 -->|No opposite signal| E4[Manage Position Risks]
|
||||||
E3 -->|Breakeven Not Reached| E5[Check Stop Loss]
|
E2 --> A
|
||||||
E5 -->|SL Hit| E2
|
E3 --> A
|
||||||
E5 -->|SL Not Hit| A
|
|
||||||
|
|
||||||
F --> F1[Close Below EMA High]
|
E4 --> E5[Check Take Profit]
|
||||||
F1 -->|Yes| F2[Set Pullback Flag]
|
E5 -->|TP Reached| E6[Close Position]
|
||||||
F1 -->|No| F3[Close Below EMA Medium]
|
E5 -->|TP Not Reached| E7[Check Breakeven]
|
||||||
F3 -->|Yes| F2
|
E7 -->|Breakeven Reached| E8[Move SL to Entry]
|
||||||
F3 -->|No| F4[Close Below EMA Low]
|
E7 -->|Breakeven Not Reached| E9[Check SL Hit]
|
||||||
F4 -->|Yes| F2
|
E9 -->|SL Hit| E6
|
||||||
F4 -->|No| F5[Check Breakthrough Signals]
|
E9 -->|SL Not Hit| A
|
||||||
|
E6 --> A
|
||||||
|
|
||||||
F2 --> F5
|
F --> F1{Previous Close Inside Zone?}
|
||||||
F5 --> F6[Close Above EMA High]
|
F1 -->|No| A
|
||||||
F6 -->|Yes| F7[Open Buy Order]
|
F1 -->|Yes| F2{Zone Width >= 100 points?}
|
||||||
F6 -->|No| F8[Close Below EMA Low]
|
F2 -->|No| A
|
||||||
F8 -->|Yes| F9[Open Sell Order]
|
F2 -->|Yes| F3{Current Close Direction}
|
||||||
F8 -->|No| A
|
F3 -->|Close > EMA High| F4[Check Filters]
|
||||||
|
F3 -->|Close < EMA Low| F5[Check Filters]
|
||||||
|
F3 -->|Still Inside| A
|
||||||
|
|
||||||
F7 --> F10[Set Lot Size]
|
F4 --> F6{Volume OK? Spread OK? MTF OK? News OK?}
|
||||||
F10 -->|Pullback| F11[0.02 Lot]
|
F5 --> F6
|
||||||
F10 -->|No Pullback| F12[0.01 Lot]
|
F6 -->|All Pass| F7[Open Buy Position]
|
||||||
F11 --> F13[Set SL at Low Border]
|
F6 -->|Any Fail| A
|
||||||
F12 --> F13
|
|
||||||
F13 --> F14[Set TP based on USD Target]
|
|
||||||
F14 --> F15[Reset Pullback Flag]
|
|
||||||
F15 --> A
|
|
||||||
|
|
||||||
F9 --> F16[Set Lot Size]
|
F7 --> F8[Set SL at EMA Low]
|
||||||
F16 -->|Pullback| F17[0.02 Lot]
|
F8 --> F9[Set TP based on USD Target]
|
||||||
F16 -->|No Pullback| F18[0.01 Lot]
|
F9 --> A
|
||||||
F17 --> F19[Set SL at High Border]
|
|
||||||
F18 --> F19
|
|
||||||
F19 --> F20[Set TP based on USD Target]
|
|
||||||
F20 --> F21[Reset Pullback Flag]
|
|
||||||
F21 --> 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
|
## Implementation Steps
|
||||||
|
|
||||||
### Phase 1: Project Setup & Git Configuration
|
### Phase 1: Project Setup & Git Configuration
|
||||||
1. Create MQL4 project structure
|
1. Create MQL5 project structure
|
||||||
2. Initialize Git repository
|
2. Initialize Git repository
|
||||||
3. Configure remote to Gitea server (https://git.moreminimore.com/kunthawat/MAEA)
|
3. Configure remote to Gitea server (https://git.moreminimore.com/kunthawat/MAEA)
|
||||||
|
|
||||||
### Phase 2: Core EA Structure
|
### Phase 2: Core EA Structure
|
||||||
4. Create [`MAEA.mq4`](MAEA.mq4) with basic EA framework
|
4. Create [`MAEA.mq5`](MAEA.mq5) with basic EA framework
|
||||||
5. Define all input parameters (EMA period, lot sizes, TP, breakeven, trailing stop, filters, etc.)
|
5. Define all input parameters (EMA period, lot size, TP, breakeven, trailing stop, filters, etc.)
|
||||||
6. Set up indicator buffers for 5 visual lines
|
6. Set up indicator buffers for 2 EMA lines + zone fill (3 buffers total)
|
||||||
7. Initialize global variables for state tracking
|
7. Initialize global variables for state tracking
|
||||||
|
|
||||||
### Phase 3: Indicator Calculations
|
### Phase 3: Indicator Calculations
|
||||||
8. Implement EMA calculations for High, Medium, Low (period 30)
|
8. Implement EMA calculations for High and Low (period 30)
|
||||||
9. Implement Border Line calculations (High Border = High + Range, Low Border = Low - Range)
|
9. Implement zone fill between EMA High and EMA Low (transparent light yellow)
|
||||||
10. Add visual indicators with correct colors (Light Blue, Yellow, Orange, Purple)
|
10. Add visual indicators with correct colors (Light Blue for EMA High, Orange for EMA Low)
|
||||||
11. Implement Volume average calculation (20-bar average)
|
11. Implement Volume average calculation (20-bar average)
|
||||||
|
|
||||||
### Phase 4: Signal Detection
|
### Phase 4: Signal Detection
|
||||||
12. Implement breakthrough signal detection (price breaks High/Low EMA)
|
12. Implement breakthrough signal detection
|
||||||
13. Implement pullback signal detection (price hits line and closes on opposite side)
|
- Check if previous close was inside zone
|
||||||
14. Implement separate pullback tracking for buy and sell directions
|
- Check if current close broke above EMA High or below EMA Low
|
||||||
15. Implement pullback flag reset logic after order opens
|
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
|
### Phase 5: Multiple Timeframe Filter
|
||||||
16. Implement D1 EMA calculations for MTF filter
|
16. Implement D1 EMA calculations for MTF filter
|
||||||
@@ -202,13 +191,15 @@ graph TD
|
|||||||
22. Add enable/disable toggles for news filter
|
22. Add enable/disable toggles for news filter
|
||||||
|
|
||||||
### Phase 7: Order Management
|
### Phase 7: Order Management
|
||||||
23. Implement order opening logic with all filter checks
|
23. Implement position opening logic with all filter checks
|
||||||
24. Implement dynamic lot sizing (0.01 no pullback, 0.02 with pullback)
|
24. Implement fixed lot sizing (0.01 lot)
|
||||||
25. Implement Stop Loss placement at Border Lines
|
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)
|
26. Implement Take Profit calculation (convert USD target to pips)
|
||||||
27. Implement Breakeven logic (move SL to entry at X points)
|
27. Implement Breakeven logic (move SL to entry at X points)
|
||||||
28. Implement Trailing Stop logic (trail by X points after breakeven)
|
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
|
### Phase 8: Risk Management
|
||||||
30. Implement max drawdown calculation
|
30. Implement max drawdown calculation
|
||||||
@@ -216,20 +207,24 @@ graph TD
|
|||||||
32. Implement trading resume logic when drawdown is below limit
|
32. Implement trading resume logic when drawdown is below limit
|
||||||
|
|
||||||
### Phase 9: Order Monitoring & Management
|
### Phase 9: Order Monitoring & Management
|
||||||
33. Implement Take Profit checking on each tick
|
33. Implement opposite signal checking on each tick
|
||||||
34. Implement Breakeven checking and SL modification
|
34. If opposite signal detected, close existing position immediately
|
||||||
35. Implement Trailing Stop checking and SL modification
|
35. Implement Take Profit checking on each tick
|
||||||
36. Implement Stop Loss checking
|
36. Implement Breakeven checking and SL modification
|
||||||
37. Implement order closure logic
|
37. Implement Trailing Stop checking and SL modification
|
||||||
|
38. Implement Stop Loss checking
|
||||||
|
39. Implement position closure logic
|
||||||
|
|
||||||
### Phase 10: Testing & Validation
|
### Phase 10: Testing & Validation
|
||||||
38. Test all EMA and Border Line calculations
|
38. Test EMA High and Low calculations
|
||||||
39. Test breakthrough and pullback signal detection
|
39. Test zone fill visualization (transparent yellow)
|
||||||
40. Test all filters (volume, spread, MTF, news)
|
40. Test breakthrough signal detection
|
||||||
41. Test order opening with correct lot sizes
|
- Verify breakout requires previous close inside zone
|
||||||
42. Test TP, SL, breakeven, and trailing stop
|
41. Test all filters (volume, spread, MTF, news)
|
||||||
43. Test drawdown protection
|
42. Test position opening with fixed 0.01 lot
|
||||||
44. Test visual indicators display
|
43. Test TP, SL (at opposite EMA), breakeven, and trailing stop
|
||||||
|
44. Test drawdown protection
|
||||||
|
45. Test visual indicators display
|
||||||
|
|
||||||
### Phase 11: Documentation & Deployment
|
### Phase 11: Documentation & Deployment
|
||||||
45. Create comprehensive [`README.md`](README.md) with strategy documentation
|
45. Create comprehensive [`README.md`](README.md) with strategy documentation
|
||||||
@@ -243,15 +238,15 @@ graph TD
|
|||||||
|
|
||||||
| Parameter | Description | Default Value |
|
| Parameter | Description | Default Value |
|
||||||
|-----------|-------------|---------------|
|
|-----------|-------------|---------------|
|
||||||
| `EMAPeriod` | EMA period for all lines | 30 |
|
| `EMAPeriod` | EMA period for both lines | 30 |
|
||||||
| `LotSizeNormal` | Lot size without pullback | 0.01 |
|
| `LotSize` | Fixed lot size | 0.01 |
|
||||||
| `LotSizePullback` | Lot size with pullback | 0.02 |
|
|
||||||
| `TakeProfitUSD` | Take profit target in USD | 5.0 |
|
| `TakeProfitUSD` | Take profit target in USD | 5.0 |
|
||||||
| `BreakevenPoints` | Points to trigger breakeven | 100 |
|
| `BreakevenPoints` | Points to trigger breakeven | 100 |
|
||||||
| `TrailingStopPoints` | Points for trailing stop distance | 100 |
|
| `TrailingStopPoints` | Points for trailing stop distance | 100 |
|
||||||
| `MagicNumber` | EA unique identifier | 12345 |
|
| `MagicNumber` | EA unique identifier | 12345 |
|
||||||
| `MaxSpread` | Maximum allowed spread in points | 30 |
|
| `MaxSpread` | Maximum allowed spread in points | 30 |
|
||||||
| `VolumePeriod` | Period for volume average calculation | 20 |
|
| `VolumePeriod` | Period for volume average calculation | 20 |
|
||||||
|
| `MinZoneWidthPoints` | Minimum zone width to trade (points) | 100 |
|
||||||
| `MaxDrawdownPercent` | Maximum drawdown percentage | 10.0 |
|
| `MaxDrawdownPercent` | Maximum drawdown percentage | 10.0 |
|
||||||
| `UseMTFFilter` | Enable/disable MTF filter | true |
|
| `UseMTFFilter` | Enable/disable MTF filter | true |
|
||||||
| `UseNewsFilter` | Enable/disable news filter | true |
|
| `UseNewsFilter` | Enable/disable news filter | true |
|
||||||
@@ -263,61 +258,73 @@ graph TD
|
|||||||
| Line | Color | Description |
|
| Line | Color | Description |
|
||||||
|------|-------|-------------|
|
|------|-------|-------------|
|
||||||
| EMA High | Light Blue (clrLightBlue) | EMA of High prices |
|
| 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 |
|
| EMA Low | Orange (clrOrange) | EMA of Low prices |
|
||||||
| High Border | Purple (clrPurple) | Upper dynamic border |
|
| Zone Fill | Light Yellow (transparent) | Area between EMA High and EMA Low |
|
||||||
| Low Border | Purple (clrPurple) | Lower dynamic border |
|
|
||||||
|
|
||||||
## Key Considerations
|
## Key Considerations
|
||||||
|
|
||||||
1. **Pullback Detection**: Track price hitting lines and closing on opposite side separately for buy/sell
|
1. **Breakthrough Detection**: Previous close must be inside zone, current close outside zone
|
||||||
2. **Pullback Reset**: Reset pullback flag immediately after opening an order
|
2. **Opposite Signal Close**: Close existing position when opposite breakthrough signal occurs
|
||||||
3. **Single Order**: Only one order open at any time
|
3. **Minimum Zone Width**: Zone must be at least 100 points wide before trading
|
||||||
4. **Dynamic SL**: Stop Loss moves with Border Lines as they update
|
4. **Single Position**: Only one position open at any time (MT5 uses positions, not orders)
|
||||||
5. **Breakeven**: Only moves SL to entry price, not to profit
|
5. **SL at Opposite EMA**: Buy SL at EMA Low, Sell SL at EMA High
|
||||||
6. **TP Calculation**: Convert USD target to pips based on lot size and symbol
|
6. **Fixed Lot Size**: Always 0.01 lot regardless of market conditions
|
||||||
7. **Volume Filter**: Only trade when current volume exceeds 20-bar average
|
7. **Breakeven**: Only moves SL to entry price, not to profit
|
||||||
8. **MTF Filter**: D1 timeframe acts as trend filter, H1 for entry signals
|
8. **TP Calculation**: Convert USD target to pips based on lot size and symbol
|
||||||
9. **Spread Filter**: Avoid high spread periods
|
9. **Volume Filter**: Only trade when current volume exceeds 20-bar average
|
||||||
10. **Timezone**: All time-based filters use Thailand timezone (UTC+7)
|
10. **MTF Filter**: D1 price position relative to zone determines allowed direction
|
||||||
11. **Trailing Stop**: Activates after breakeven, trails by specified points
|
11. **Spread Filter**: Avoid high spread periods
|
||||||
12. **Drawdown Protection**: Stops trading if max drawdown exceeded
|
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
|
## Technical Specifications
|
||||||
|
|
||||||
- **Platform**: MetaTrader 4
|
- **Platform**: MetaTrader 5
|
||||||
- **Language**: MQL4
|
- **Language**: MQL5
|
||||||
- **Trading Timeframe**: H1 (recommended)
|
- **Trading Timeframe**: H1 (recommended)
|
||||||
- **Filter Timeframe**: D1 (for MTF filter)
|
- **Filter Timeframe**: D1 (for MTF filter)
|
||||||
- **Currency Pairs**: All pairs (user-selectable)
|
- **Currency Pairs**: All pairs (user-selectable)
|
||||||
- **Account Types**: Any MT4 account type
|
- **Account Types**: Any MT5 account type
|
||||||
- **Server Timezone**: Thailand (UTC+7)
|
- **Server Timezone**: Thailand (UTC+7)
|
||||||
|
|
||||||
## Testing Checklist
|
## Testing Checklist
|
||||||
|
|
||||||
### Core Strategy
|
### Core Strategy
|
||||||
- [ ] EMA calculations verify correctly (High, Medium, Low)
|
- [ ] EMA calculations verify correctly (High and Low)
|
||||||
- [ ] Border Line calculations verify correctly
|
- [ ] 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
|
- [ ] Breakthrough signals trigger correctly
|
||||||
- [ ] Pullback signals detect correctly (buy and sell separately)
|
- [ ] Previous close inside zone check
|
||||||
- [ ] Pullback flag resets after order opens
|
- [ ] Buy signal: close > EMA High
|
||||||
- [ ] Lot sizes apply correctly (0.01 vs 0.02)
|
- [ ] Sell signal: close < EMA Low
|
||||||
|
- [ ] Opposite signal detection works
|
||||||
|
- [ ] Buy position closes when sell signal occurs
|
||||||
|
- [ ] Sell position closes when buy signal occurs
|
||||||
|
|
||||||
### Filters
|
### Filters
|
||||||
- [ ] Volume filter works (20-bar average, current > average)
|
- [ ] Volume filter works (20-bar average, current > average)
|
||||||
- [ ] Spread filter prevents high spread trades
|
- [ ] 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
|
- [ ] MTF filter can be enabled/disabled
|
||||||
|
- [ ] Min zone width filter works (100 points minimum)
|
||||||
- [ ] News filter avoids specified times (Thailand timezone)
|
- [ ] News filter avoids specified times (Thailand timezone)
|
||||||
- [ ] News filter can be enabled/disabled
|
- [ ] News filter can be enabled/disabled
|
||||||
|
|
||||||
### Order Management
|
### 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
|
- [ ] Take Profit closes at correct USD amount
|
||||||
- [ ] Breakeven triggers at correct points
|
- [ ] Breakeven triggers at correct points
|
||||||
- [ ] Trailing stop activates after breakeven
|
- [ ] Trailing stop activates after breakeven
|
||||||
- [ ] Trailing stop trails by correct distance
|
- [ ] 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
|
### Risk Management
|
||||||
- [ ] Max drawdown protection works
|
- [ ] Max drawdown protection works
|
||||||
@@ -332,11 +339,15 @@ graph TD
|
|||||||
|
|
||||||
## Notes
|
## Notes
|
||||||
|
|
||||||
- The strategy uses 5 visual lines on the chart
|
- The strategy uses 2 EMA lines with a filled zone between them
|
||||||
- Pullback tracking is separate for buy and sell directions
|
- No pullback tracking or dynamic lot sizing - simplified approach
|
||||||
- Border Lines expand the range beyond the EMAs for wider stops
|
- 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
|
- 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
|
- Multiple filters ensure quality trade entries
|
||||||
- All time-based calculations use Thailand timezone (UTC+7)
|
- 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
|
- 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
|
# MAEA Project Summary
|
||||||
|
|
||||||
## Project Overview
|
## 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
|
**Repository:** https://git.moreminimore.com/kunthawat/MAEA
|
||||||
**Timezone:** Thailand (UTC+7)
|
**Timezone:** Thailand (UTC+7)
|
||||||
|
|
||||||
## Core Strategy
|
## Core Strategy
|
||||||
|
|
||||||
### Indicator System (5 Visual Lines)
|
### Indicator System (2 EMA Lines + Zone)
|
||||||
1. **EMA High** (Light Blue) - EMA of High prices, period 30
|
1. **EMA High** (Light Blue) - EMA of High prices, period 30
|
||||||
2. **EMA Medium** (Yellow) - EMA of Close prices, period 30
|
2. **EMA Low** (Orange) - EMA of Low prices, period 30
|
||||||
3. **EMA Low** (Orange) - EMA of Low prices, period 30
|
3. **Zone Fill** (Light Yellow, transparent) - Area between EMA High and EMA Low
|
||||||
4. **High Border** (Purple) - EMA High + (EMA Medium - EMA Low)
|
|
||||||
5. **Low Border** (Purple) - EMA Low - (EMA Medium - EMA Low)
|
|
||||||
|
|
||||||
### Signal Types
|
### Signal Types
|
||||||
|
|
||||||
#### 1. Breakthrough Signal
|
#### 1. Breakthrough Signal
|
||||||
- **Buy:** Close price breaks above EMA High
|
- **Buy:** Close price breaks above EMA High (must have previous close inside zone)
|
||||||
- **Sell:** Close price breaks below EMA Low
|
- **Sell:** Close price breaks below EMA Low (must have previous close inside zone)
|
||||||
- **Purpose:** Triggers order opening
|
- **Purpose:** Triggers position opening
|
||||||
|
- **Verification:** Previous bar close must be inside zone between EMA High and EMA Low
|
||||||
|
|
||||||
#### 2. Pullback Signal
|
#### 2. Opposite Signal Close
|
||||||
- **Buy Pullback:** Price moves down to hit any line, then closes above the line
|
- **Close Buy:** When sell signal occurs (price breaks below EMA Low)
|
||||||
- **Sell Pullback:** Price moves up to hit any line, then closes below the line
|
- **Close Sell:** When buy signal occurs (price breaks above EMA High)
|
||||||
- **Purpose:** Increases lot size when breakthrough occurs in same direction
|
- **Immediate Action:** Position closes before checking for new trade
|
||||||
- **Tracking:** Separate for buy and sell directions
|
|
||||||
|
|
||||||
### Order Management
|
### Order Management
|
||||||
- **Single Order:** Only one order at a time
|
- **Single Position:** Only one position open at a time (MT5 uses positions, not orders)
|
||||||
- **Dynamic Lot Sizing:**
|
- **Fixed Lot Size:** 0.01 lot for all trades
|
||||||
- 0.01 lot (no pullback before breakthrough)
|
- **Stop Loss:** At opposite EMA (Buy: EMA Low, Sell: EMA High)
|
||||||
- 0.02 lot (pullback occurred before breakthrough)
|
- **Reverse Protection:** Close position when opposite signal occurs
|
||||||
- **Stop Loss:** At Border Lines (Low Border for buys, High Border for sells)
|
- **Min Zone Width:** Zone must be at least 100 points to trade
|
||||||
- **Take Profit:** Target in USD (default $5)
|
- **Take Profit:** Target in USD (default $5)
|
||||||
- **Breakeven:** Move SL to entry at X points profit (default 100)
|
- **Breakeven:** Move SL to entry at X points profit (default 100)
|
||||||
- **Trailing Stop:** Trail by X points after breakeven (default 100)
|
- **Trailing Stop:** Trail by X points after breakeven (default 100)
|
||||||
@@ -44,6 +42,7 @@
|
|||||||
- Calculate 20-bar volume average
|
- Calculate 20-bar volume average
|
||||||
- Trade only when current volume > average
|
- Trade only when current volume > average
|
||||||
- Ensures sufficient market activity
|
- Ensures sufficient market activity
|
||||||
|
- Note: MT5 uses tick volume by default (similar to MT4)
|
||||||
|
|
||||||
### 2. Spread Filter
|
### 2. Spread Filter
|
||||||
- Maximum allowed spread: 30 points
|
- Maximum allowed spread: 30 points
|
||||||
@@ -53,9 +52,9 @@
|
|||||||
- **Trading Timeframe:** H1
|
- **Trading Timeframe:** H1
|
||||||
- **Filter Timeframe:** D1
|
- **Filter Timeframe:** D1
|
||||||
- **Logic:**
|
- **Logic:**
|
||||||
- D1 close > D1 EMA High: Only buy orders allowed
|
- D1 close > D1 EMA High: Only buy positions allowed (bullish)
|
||||||
- D1 close < D1 EMA Low: Only sell orders allowed
|
- D1 close < D1 EMA Low: Only sell positions allowed (bearish)
|
||||||
- D1 close between: No orders allowed
|
- D1 close between: No positions allowed (no trend)
|
||||||
- Can be enabled/disabled
|
- Can be enabled/disabled
|
||||||
|
|
||||||
### 4. News Filter (Optional)
|
### 4. News Filter (Optional)
|
||||||
@@ -69,30 +68,38 @@
|
|||||||
- Stops trading if drawdown exceeds limit
|
- Stops trading if drawdown exceeds limit
|
||||||
- Resumes trading when drawdown is below 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
|
## Implementation Phases
|
||||||
|
|
||||||
### Phase 1: Project Setup & Git Configuration (3 tasks)
|
### Phase 1: Project Setup & Git Configuration (3 tasks)
|
||||||
- Create MQL4 project structure
|
- Create MQL5 project structure
|
||||||
- Initialize Git repository
|
- Initialize Git repository
|
||||||
- Configure remote to Gitea server
|
- Configure remote to Gitea server
|
||||||
|
|
||||||
### Phase 2: Core EA Structure (4 tasks)
|
### Phase 2: Core EA Structure (4 tasks)
|
||||||
- Create MAEA.mq4 with basic framework
|
- Create MAEA.mq5 with basic framework
|
||||||
- Define all input parameters
|
- Define all input parameters
|
||||||
- Set up indicator buffers
|
- Set up indicator buffers
|
||||||
- Initialize global variables
|
- Initialize global variables
|
||||||
|
|
||||||
### Phase 3: Indicator Calculations (4 tasks)
|
### Phase 3: Indicator Calculations (4 tasks)
|
||||||
- Implement EMA calculations (High, Medium, Low)
|
- Implement EMA calculations (High and Low only)
|
||||||
- Implement Border Line calculations
|
- Implement zone fill between EMA High and EMA Low
|
||||||
- Add visual indicators with colors
|
- Add visual indicators with colors (Light Blue, Orange, Light Yellow fill)
|
||||||
- Implement Volume average calculation
|
- Implement Volume average calculation
|
||||||
|
|
||||||
### Phase 4: Signal Detection (4 tasks)
|
### Phase 4: Signal Detection (3 tasks)
|
||||||
- Implement breakthrough signal detection
|
- Implement breakthrough signal detection
|
||||||
- Implement pullback signal detection
|
- Check if previous close inside zone
|
||||||
- Implement separate pullback tracking
|
- Check if current close broke above EMA High or below EMA Low
|
||||||
- Implement pullback flag reset logic
|
- 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)
|
### Phase 5: Multiple Timeframe Filter (3 tasks)
|
||||||
- Implement D1 EMA calculations
|
- Implement D1 EMA calculations
|
||||||
@@ -106,31 +113,37 @@
|
|||||||
- Add enable/disable toggle for news filter
|
- Add enable/disable toggle for news filter
|
||||||
|
|
||||||
### Phase 7: Order Management (7 tasks)
|
### Phase 7: Order Management (7 tasks)
|
||||||
- Implement order opening with all filters
|
- Implement position opening with all filters
|
||||||
- Implement dynamic lot sizing
|
- Implement fixed lot sizing (0.01 lot)
|
||||||
- Implement Stop Loss placement
|
- Implement Stop Loss placement at opposite EMA
|
||||||
- Implement Take Profit calculation
|
- Implement Take Profit calculation
|
||||||
- Implement Breakeven logic
|
- Implement Breakeven logic
|
||||||
- Implement Trailing Stop logic
|
- Implement Trailing Stop logic
|
||||||
- Implement single order restriction
|
- Implement single position restriction
|
||||||
|
|
||||||
### Phase 8: Risk Management (3 tasks)
|
### Phase 8: Risk Management (3 tasks)
|
||||||
- Implement max drawdown calculation
|
- Implement max drawdown calculation
|
||||||
- Implement drawdown protection
|
- Implement drawdown protection
|
||||||
- Implement trading resume logic
|
- 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 Take Profit checking
|
||||||
- Implement Breakeven checking and SL modification
|
- Implement Breakeven checking and SL modification
|
||||||
- Implement Trailing Stop checking and SL modification
|
- Implement Trailing Stop checking and SL modification
|
||||||
- Implement Stop Loss checking
|
- Implement Stop Loss checking
|
||||||
- Implement order closure logic
|
- Implement position closure logic
|
||||||
|
|
||||||
### Phase 10: Testing & Validation (7 tasks)
|
### Phase 10: Testing & Validation (8 tasks)
|
||||||
- Test all EMA and Border Line calculations
|
- Test EMA High and Low calculations
|
||||||
- Test breakthrough and pullback signals
|
- 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 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 TP, SL, breakeven, and trailing stop
|
||||||
- Test drawdown protection
|
- Test drawdown protection
|
||||||
- Test visual indicators display
|
- Test visual indicators display
|
||||||
@@ -142,44 +155,46 @@
|
|||||||
- Commit initial code to Git
|
- Commit initial code to Git
|
||||||
- Push to Gitea repository and verify
|
- Push to Gitea repository and verify
|
||||||
|
|
||||||
## Total Tasks: 50
|
## Total Tasks: 51
|
||||||
|
|
||||||
## Key Features Summary
|
## Key Features Summary
|
||||||
|
|
||||||
✅ **Advanced Trend Following:** EMA-based with dynamic border lines
|
✅ **Simple Trend Following:** EMA-based with visual zone fill
|
||||||
✅ **Smart Signal Detection:** Breakthrough and pullback signals with separate tracking
|
✅ **Clear Breakthrough Signals:** Zone breakout with previous bar confirmation
|
||||||
✅ **Dynamic Lot Sizing:** 0.01 or 0.02 based on market behavior
|
✅ **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
|
✅ **Comprehensive Filters:** Volume, spread, MTF, news, and drawdown protection
|
||||||
✅ **Risk Management:** TP in USD, SL at borders, breakeven, trailing stop
|
✅ **Risk Management:** TP in USD, SL at opposite EMA, breakeven, trailing stop
|
||||||
✅ **Visual Indicators:** 5 colored lines for easy analysis
|
✅ **Visual Indicators:** 2 EMAs with light yellow zone fill
|
||||||
✅ **Flexible Configuration:** All features can be enabled/disabled
|
✅ **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
|
✅ **Timezone Aware:** Thailand timezone (UTC+7) for all time-based features
|
||||||
|
|
||||||
## Default Parameters
|
## Default Parameters
|
||||||
|
|
||||||
| Parameter | Value | Description |
|
| Parameter | Value | Description |
|
||||||
|-----------|-------|-------------|
|
|-----------|-------|-------------|
|
||||||
| EMA Period | 30 | Period for all EMAs |
|
| EMA Period | 30 | Period for EMA High and EMA Low |
|
||||||
| Lot Size (Normal) | 0.01 | Lot without pullback |
|
| Lot Size | 0.01 | Fixed lot size for all trades |
|
||||||
| Lot Size (Pullback) | 0.02 | Lot with pullback |
|
|
||||||
| Take Profit | $5 | Target profit in USD |
|
| Take Profit | $5 | Target profit in USD |
|
||||||
| Breakeven Points | 100 | Points to trigger breakeven |
|
| Breakeven Points | 100 | Points to trigger breakeven |
|
||||||
| Trailing Stop Points | 100 | Trail distance after breakeven |
|
| Trailing Stop Points | 100 | Trail distance after breakeven |
|
||||||
| Max Spread | 30 points | Maximum allowed spread |
|
| Max Spread | 30 points | Maximum allowed spread |
|
||||||
| Volume Period | 20 | Bars for volume average |
|
| Volume Period | 20 | Bars for volume average |
|
||||||
|
| Min Zone Width | 100 points | Minimum zone width to trade |
|
||||||
| Max Drawdown | 10% | Maximum drawdown percentage |
|
| Max Drawdown | 10% | Maximum drawdown percentage |
|
||||||
| MTF Filter | true | Enable/disable MTF filter |
|
| MTF Filter | true | Enable/disable MTF filter |
|
||||||
| News Filter | true | Enable/disable news filter |
|
| News Filter | true | Enable/disable news filter |
|
||||||
|
|
||||||
## Technical Specifications
|
## Technical Specifications
|
||||||
|
|
||||||
- **Platform:** MetaTrader 4
|
- **Platform:** MetaTrader 5
|
||||||
- **Language:** MQL4
|
- **Language:** MQL5
|
||||||
- **Trading Timeframe:** H1 (recommended)
|
- **Trading Timeframe:** H1 (recommended)
|
||||||
- **Filter Timeframe:** D1 (for MTF)
|
- **Filter Timeframe:** D1 (for MTF)
|
||||||
- **Currency Pairs:** All pairs (user-selectable)
|
- **Currency Pairs:** All pairs (user-selectable)
|
||||||
- **Account Types:** Any MT4 account
|
- **Account Types:** Any MT5 account
|
||||||
- **Server Timezone:** Thailand (UTC+7)
|
- **Server Timezone:** Thailand (UTC+7)
|
||||||
|
|
||||||
## Next Steps
|
## Next Steps
|
||||||
|
|||||||
Reference in New Issue
Block a user