//+------------------------------------------------------------------+
//| EA_SMA_RSI_Strategy.mq4 |
//| Copyright 2024, MetaQuotes Software Corp. |
//| MQL4: automated forex trading, strategy tester and custom indicators with MetaTrader |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Software Corp."
#property link "MQL4: automated forex trading, strategy tester and custom indicators with MetaTrader"
#property version "1.10"
#property strict
//--- Входные параметры
input int SMAPeriod = 14; // Период Simple Moving Average
input int RSIPeriod = 14; // Период RSI
input double RSIBuyLevel = 30.0; // Уровень RSI для входа в покупку
input double RSISellLevel = 70.0; // Уровень RSI для входа в продажу
input double RSIExitBuyLevel = 70.0; // Уровень RSI для выхода из покупки
input double RSIExitSellLevel = 30.0; // Уровень RSI для выхода из продажи
input double LotSize = 0.1; // Размер лота
input int MagicNumber = 12345; // Магический номер
input int Slippage = 3; // Проскальзывание в пунктах
//--- Дополнительные параметры
input bool UseMarginCheck = true; // Проверять уровень свободной маржи
input double MinMarginPercent = 50.0; // Минимальный процент свободной маржи
input bool UseTimeFilter = false; // Использовать фильтр по времени
input int StartHour = 8; // Час начала торговли (0-23)
input int EndHour = 18; // Час окончания торговли (0-23)
input bool SendAlerts = false; // Отправлять алерты
//--- Глобальные переменные
datetime lastBarTime = 0; // Время последнего обработанного бара
bool positionOpen = false; // Флаг открытой позиции
int positionType = -1; // Тип позиции: 0 - BUY, 1 - SELL, -1 - нет позиции
string globalVarName = ""; // Имя глобальной переменной для сохранения времени бара
//+------------------------------------------------------------------+
//| Функция инициализации эксперта |
//+------------------------------------------------------------------+
int OnInit()
{
Print("=== EA SMA RSI Strategy v1.10 инициализирован ===");
Print("Параметры торговли:");
Print("- SMA период: ", SMAPeriod);
Print("- RSI период: ", RSIPeriod);
Print("- RSI уровни: Buy<", RSIBuyLevel, ", Sell>", RSISellLevel);
Print("- RSI выход: Buy>", RSIExitBuyLevel, ", Sell<", RSIExitSellLevel);
Print("- Размер лота: ", LotSize);
Print("- Магический номер: ", MagicNumber);
// Проверка входных параметров
if(!ValidateInputs())
return(INIT_PARAMETERS_INCORRECT);
// Создание имени глобальной переменной
globalVarName = "EA_" + IntegerToString(MagicNumber) + "_" + Symbol() + "_LastBar";
// Восстановление времени последнего обработанного бара
if(GlobalVariableCheck(globalVarName))
{
lastBarTime = (datetime)GlobalVariableGet(globalVarName);
Print("Восстановлено время последнего бара: ", TimeToStr(lastBarTime));
}
// Проверка наличия открытых позиций при запуске
CheckExistingPositions();
// Информация о дополнительных настройках
if(UseMarginCheck)
Print("Проверка маржи включена: минимум ", MinMarginPercent, "%");
if(UseTimeFilter)
Print("Фильтр времени включен: ", StartHour, ":00 - ", EndHour, ":00");
if(SendAlerts)
Print("Алерты включены");
Print("=== Инициализация завершена ===");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Функция деинициализации эксперта |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Сохранение времени последнего обработанного бара
if(lastBarTime > 0)
{
GlobalVariableSet(globalVarName, (double)lastBarTime);
Print("Время последнего бара сохранено: ", TimeToStr(lastBarTime));
}
Print("EA SMA RSI Strategy деинициализирован. Причина: ", GetDeinitReasonText(reason));
}
//+------------------------------------------------------------------+
//| Основная функция эксперта |
//+------------------------------------------------------------------+
void OnTick()
{
// Проверяем, что сформировался новый бар
if(Time[0] == lastBarTime)
return;
// Проверка фильтра по времени
if(UseTimeFilter && !IsTradeTimeAllowed())
{
return;
}
// Проверяем наличие достаточного количества баров для расчета индикаторов
if(Bars < MathMax(SMAPeriod, RSIPeriod) + 2)
{
LogMessage("Недостаточно баров для расчета индикаторов", true);
return;
}
// Обновляем время последнего обработанного бара
lastBarTime = Time[0];
GlobalVariableSet(globalVarName, (double)lastBarTime);
// Обновляем статус позиции
UpdatePositionStatus();
// Получаем значения индикаторов
double sma_current = iMA(NULL, 0, SMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
double sma_previous = iMA(NULL, 0, SMAPeriod, 0, MODE_SMA, PRICE_CLOSE, 2);
double rsi_current = iRSI(NULL, 0, RSIPeriod, PRICE_CLOSE, 1);
// Проверяем корректность значений индикаторов
if(sma_current <= 0 || sma_previous <= 0 || rsi_current <= 0)
{
LogMessage("Ошибка получения значений индикаторов", true);
return;
}
// Цены закрытия
double close_current = Close[1]; // Закрытие текущего завершенного бара
double close_previous = Close[2]; // Закрытие предыдущего бара
// Логика торговли
if(!positionOpen)
{
// Проверка условий для входа в покупку
if(CheckBuyCondition(close_previous, close_current, sma_previous, sma_current, rsi_current))
{
if(CheckMarginRequirement(OP_BUY))
{
OpenBuyPosition();
}
else
{
LogMessage("Недостаточно свободной маржи для открытия позиции BUY", true);
}
}
// Проверка условий для входа в продажу
else if(CheckSellCondition(close_previous, close_current, sma_previous, sma_current, rsi_current))
{
if(CheckMarginRequirement(OP_SELL))
{
OpenSellPosition();
}
else
{
LogMessage("Недостаточно свободной маржи для открытия позиции SELL", true);
}
}
}
else
{
// Проверка условий для выхода из позиции
if(positionType == OP_BUY && rsi_current > RSIExitBuyLevel)
{
LogMessage("Сигнал выхода из BUY: RSI=" + DoubleToStr(rsi_current, 2) + " > " + DoubleToStr(RSIExitBuyLevel, 2), false);
ClosePosition();
}
else if(positionType == OP_SELL && rsi_current < RSIExitSellLevel)
{
LogMessage("Сигнал выхода из SELL: RSI=" + DoubleToStr(rsi_current, 2) + " < " + DoubleToStr(RSIExitSellLevel, 2), false);
ClosePosition();
}
}
}
//+------------------------------------------------------------------+
//| Валидация входных параметров |
//+------------------------------------------------------------------+
bool ValidateInputs()
{
bool isValid = true;
if(SMAPeriod <= 0)
{
Print("ОШИБКА: Период SMA должен быть больше 0");
isValid = false;
}
if(RSIPeriod <= 0)
{
Print("ОШИБКА: Период RSI должен быть больше 0");
isValid = false;
}
if(LotSize <= 0)
{
Print("ОШИБКА: Размер лота должен быть больше 0");
isValid = false;
}
if(RSIBuyLevel >= RSISellLevel)
{
Print("ОШИБКА: Уровень RSI для покупки должен быть меньше уровня для продажи");
isValid = false;
}
if(UseTimeFilter && StartHour < 0 || StartHour > 23 || EndHour < 0 || EndHour > 23)
{
Print("ОШИБКА: Торговые часы должны быть в диапазоне 0-23");
isValid = false;
}
if(UseMarginCheck && MinMarginPercent < 0)
{
Print("ОШИБКА: Минимальный процент маржи не может быть отрицательным");
isValid = false;
}
return isValid;
}
//+------------------------------------------------------------------+
//| Проверка торгового времени |
//+------------------------------------------------------------------+
bool IsTradeTimeAllowed()
{
if(!UseTimeFilter)
return true;
int currentHour = Hour();
if(StartHour <= EndHour)
{
// Обычный диапазон (например, 8-18)
return (currentHour >= StartHour && currentHour < EndHour);
}
else
{
// Ночной диапазон (например, 22-6)
return (currentHour >= StartHour || currentHour < EndHour);
}
}
//+------------------------------------------------------------------+
//| Проверка уровня маржи |
//+------------------------------------------------------------------+
bool CheckMarginRequirement(int orderType)
{
if(!UseMarginCheck)
return true;
double freeMargin = AccountFreeMargin();
double equity = AccountEquity();
if(equity <= 0)
return false;
double freeMarginPercent = (freeMargin / equity) * 100.0;