147 lines
4.3 KiB
Text
147 lines
4.3 KiB
Text
|
|
//+------------------------------------------------------------------+
|
||
|
|
//| Trend + Pullback EA (Default Version) |
|
||
|
|
//| Works on NASDAQ100 & GOLD |
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
#property strict
|
||
|
|
|
||
|
|
input int EMA_Fast = 20;
|
||
|
|
input int EMA_Trend = 200;
|
||
|
|
input double RiskPercent = 1.0;
|
||
|
|
input double RR = 2.0;
|
||
|
|
|
||
|
|
//--- Handles
|
||
|
|
int fastEMA, trendEMA;
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
int OnInit()
|
||
|
|
{
|
||
|
|
fastEMA = iMA(_Symbol, _Period, EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
|
||
|
|
trendEMA = iMA(_Symbol, _Period, EMA_Trend, 0, MODE_EMA, PRICE_CLOSE);
|
||
|
|
|
||
|
|
if (fastEMA == INVALID_HANDLE || trendEMA == INVALID_HANDLE)
|
||
|
|
{
|
||
|
|
Print("Error creating indicators.");
|
||
|
|
return INIT_FAILED;
|
||
|
|
}
|
||
|
|
|
||
|
|
return INIT_SUCCEEDED;
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
|
||
|
|
void OnTick()
|
||
|
|
{
|
||
|
|
if(!IsNewCandle()) return;
|
||
|
|
|
||
|
|
double fastEMA_val = CopyBufferVal(fastEMA, 0);
|
||
|
|
double trendEMA_val = CopyBufferVal(trendEMA, 0);
|
||
|
|
|
||
|
|
double prevHigh = iHigh(_Symbol, _Period, 1);
|
||
|
|
double prevLow = iLow(_Symbol, _Period, 1);
|
||
|
|
|
||
|
|
double close1 = iClose(_Symbol, _Period, 1); // previous candle close
|
||
|
|
double open1 = iOpen (_Symbol, _Period, 1); // previous candle open
|
||
|
|
double low1 = iLow (_Symbol, _Period, 1);
|
||
|
|
double high1 = iHigh (_Symbol, _Period, 1);
|
||
|
|
|
||
|
|
// Trend Filters
|
||
|
|
bool upTrend = (close1 > trendEMA_val);
|
||
|
|
bool downTrend = (close1 < trendEMA_val);
|
||
|
|
|
||
|
|
// Pullback Check = price touches EMA20
|
||
|
|
bool touchedFastEMA = (low1 <= fastEMA_val && high1 >= fastEMA_val);
|
||
|
|
|
||
|
|
// Engulfing Conditions
|
||
|
|
bool bullishEngulf =
|
||
|
|
(close1 > open1) &&
|
||
|
|
(close1 > iOpen(_Symbol, _Period, 2)) &&
|
||
|
|
(open1 < iClose(_Symbol, _Period, 2));
|
||
|
|
|
||
|
|
bool bearishEngulf =
|
||
|
|
(close1 < open1) &&
|
||
|
|
(close1 < iOpen(_Symbol, _Period, 2)) &&
|
||
|
|
(open1 > iClose(_Symbol, _Period, 2));
|
||
|
|
|
||
|
|
// BUY CONDITIONS
|
||
|
|
if (upTrend && touchedFastEMA && bullishEngulf)
|
||
|
|
{
|
||
|
|
double sl = prevLow; // swing low
|
||
|
|
double entry = close1;
|
||
|
|
double tp = entry + (entry - sl) * RR; // RR = 2
|
||
|
|
|
||
|
|
OpenTrade(ORDER_TYPE_BUY, entry, sl, tp);
|
||
|
|
}
|
||
|
|
|
||
|
|
// SELL CONDITIONS
|
||
|
|
if (downTrend && touchedFastEMA && bearishEngulf)
|
||
|
|
{
|
||
|
|
double sl = prevHigh; // swing high
|
||
|
|
double entry = close1;
|
||
|
|
double tp = entry - (sl - entry) * RR;
|
||
|
|
|
||
|
|
OpenTrade(ORDER_TYPE_SELL, entry, sl, tp);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
// Risk-based Lot Calculation
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double LotByRisk(double slPrice, ENUM_ORDER_TYPE type)
|
||
|
|
{
|
||
|
|
double riskMoney = AccountBalance() * (RiskPercent / 100.0);
|
||
|
|
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
|
||
|
|
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
|
||
|
|
|
||
|
|
double slDistance = MathAbs(slPrice - SymbolInfoDouble(_Symbol, SYMBOL_BID));
|
||
|
|
double costPerLot = slDistance / tickSize * tickValue;
|
||
|
|
|
||
|
|
if (costPerLot <= 0) return 0.1;
|
||
|
|
return NormalizeDouble(riskMoney / costPerLot, 2);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
void OpenTrade(ENUM_ORDER_TYPE type, double price, double sl, double tp)
|
||
|
|
{
|
||
|
|
if (PositionsTotal() > 0) return; // one trade at a time
|
||
|
|
|
||
|
|
double lots = LotByRisk(sl, type);
|
||
|
|
|
||
|
|
MqlTradeRequest req;
|
||
|
|
MqlTradeResult res;
|
||
|
|
ZeroMemory(req);
|
||
|
|
|
||
|
|
req.action = TRADE_ACTION_DEAL;
|
||
|
|
req.symbol = _Symbol;
|
||
|
|
req.volume = lots;
|
||
|
|
req.type = type;
|
||
|
|
req.price = (type == ORDER_TYPE_BUY ? SymbolInfoDouble(_Symbol, SYMBOL_ASK)
|
||
|
|
: SymbolInfoDouble(_Symbol, SYMBOL_BID));
|
||
|
|
req.sl = sl;
|
||
|
|
req.tp = tp;
|
||
|
|
req.magic = 12345;
|
||
|
|
|
||
|
|
OrderSend(req, res);
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
bool IsNewCandle()
|
||
|
|
{
|
||
|
|
static datetime lastTime = 0;
|
||
|
|
datetime current = iTime(_Symbol, _Period, 0);
|
||
|
|
|
||
|
|
if (current != lastTime)
|
||
|
|
{
|
||
|
|
lastTime = current;
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
//+------------------------------------------------------------------+
|
||
|
|
double CopyBufferVal(int handle, int index)
|
||
|
|
{
|
||
|
|
double val[];
|
||
|
|
if(CopyBuffer(handle, 0, index, 1, val) < 1)
|
||
|
|
return EMPTY_VALUE;
|
||
|
|
return val[0];
|
||
|
|
}
|
||
|
|
//+------------------------------------------------------------------+
|