Загрузка данных
//+------------------------------------------------------------------+
//| EA_Fibonacci.mq4|
//| AI Advisor |
//| https://metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "AI Advisor"
#property link "https://metaquotes.net"
#property version "1.08"
#property strict
//--- Входные параметры
input string Group_Fibo = "--- Настройки Фибоначчи ---";
input int InpBarsCount = 150; // Количество баров для поиска экстремумов
input string Group_Trading = "--- Настройки торговли ---";
input bool InpUseMM = true; // Включить расчет лота в % от депозита?
input double InpLotPercent = 1.0; // Процент от депозита для первого ордера (61.8%)
input double InpLotMain = 0.01; // Фиксированный лот (если InpUseMM = false)
input double InpGridMultiplier = 1.0; // Множитель лота для второго ордера (76.4%)
input int InpMagic = 123456; // Магический номер
input double InpProfitBuffer = 1.0; // Подушка профита в валюте на каждые 0.01 лота
input string Group_Visual = "--- Настройки графики ---";
input color InpLineColor = clrDodgerBlue;// Цвет линий уровней
input int InpLineStyle = 3; // Стиль линий (STYLE_DASHDOT)
input int InpLineWidth = 1; // Толщина линий
//--- Глобальные переменные для отслеживания состояния
double lastPriceMax = 0;
double lastPriceMin = 0;
bool isCycleFinished = false;
#define OBJ_PREFIX "EA_Fibo_"
//+------------------------------------------------------------------+
//| Функции инициализации и деинициализации |
//+------------------------------------------------------------------+
int OnInit() { return(INIT_SUCCEEDED); }
void OnDeinit(const int reason) { ObjectsDeleteAll(0, OBJ_PREFIX); Comment(""); }
//+------------------------------------------------------------------+
//| Вспомогательные функции (Лот и Отрисовка) |
//+------------------------------------------------------------------+
double CalculateLot(double percent)
{
double freeMargin = AccountFreeMargin();
double marginRequired = MarketInfo(Symbol(), MODE_MARGINREQUIRED);
if(marginRequired <= 0) return(InpLotMain);
double calculatedLot = (freeMargin * (percent / 100.0)) / marginRequired;
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
if(lotStep > 0) calculatedLot = MathFloor(calculatedLot / lotStep) * lotStep;
return(calculatedLot);
}
double CheckLotBounds(double lot)
{
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
if(lot < minLot) lot = minLot;
if(lot > maxLot) lot = maxLot;
return(NormalizeDouble(lot, 2));
}
void DrawHLine(string name, double price)
{
string objName = OBJ_PREFIX + name;
if(ObjectFind(0, objName) >= 0) { ObjectMove(0, objName, 0, 0, price); return; }
ObjectCreate(0, objName, OBJ_HLINE, 0, 0, price);
ObjectSetInteger(0, objName, OBJPROP_COLOR, InpLineColor);
ObjectSetInteger(0, objName, OBJPROP_WIDTH, InpLineWidth);
ObjectSetInteger(0, objName, OBJPROP_STYLE, InpLineStyle);
ObjectSetString(0, objName, OBJPROP_TEXT, name);
}
//+------------------------------------------------------------------+
//| Основной рабочий модуль советника |
//+------------------------------------------------------------------+
void OnTick()
{
RefreshRates();
int bars = Bars(Symbol(), Period());
int searchBars = (bars < InpBarsCount) ? bars : InpBarsCount;
if(searchBars <= 0) return;
int maxBarIdx = iHighest(Symbol(), Period(), MODE_HIGH, searchBars, 1);
int minBarIdx = iLowest(Symbol(), Period(), MODE_LOW, searchBars, 1);
if(maxBarIdx < 0 || minBarIdx < 0) return;
double priceMax = NormalizeDouble(iHigh(Symbol(), Period(), maxBarIdx), Digits);
double priceMin = NormalizeDouble(iLow(Symbol(), Period(), minBarIdx), Digits);
datetime timeMax = iTime(Symbol(), Period(), maxBarIdx);
datetime timeMin = iTime(Symbol(), Period(), minBarIdx);
bool isBullish = (timeMax > timeMin);
if(priceMax != lastPriceMax || priceMin != lastPriceMin)
{
lastPriceMax = priceMax;
lastPriceMin = priceMin;
isCycleFinished = false;
}
double height = priceMax - priceMin;
double f50_Price = NormalizeDouble(isBullish ? (priceMax - height * 0.500) : (priceMin + height * 0.500), Digits);
double f618_Price = NormalizeDouble(isBullish ? (priceMax - height * 0.618) : (priceMin + height * 0.618), Digits);
double f764_Price = NormalizeDouble(isBullish ? (priceMax - height * 0.764) : (priceMin + height * 0.764), Digits);
double f100_Price = isBullish ? priceMin : priceMax;
DrawHLine("50.0", f50_Price);
DrawHLine("61.8 (Вход)", f618_Price);
DrawHLine("76.4 (Доливка)", f764_Price);
DrawHLine("100.0 (Стоп)", f100_Price);
int totalOrders = 0;
int mainOrderTicket = -1;
int mainType = -1;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != InpMagic) continue;
totalOrders++;
if(mainOrderTicket == -1)
{
mainOrderTicket = OrderTicket();
mainType = OrderType();
}
}
double tradeLotMain = InpUseMM ? CalculateLot(InpLotPercent) : InpLotMain;
double tradeLotGrid = NormalizeDouble(tradeLotMain * InpGridMultiplier, 2);
tradeLotMain = CheckLotBounds(tradeLotMain);
tradeLotGrid = CheckLotBounds(tradeLotGrid);
string textStatus = isCycleFinished ? "Ожидание новой сетки" : "Поиск входа";
if(totalOrders == 1) textStatus = "Один ордер в рынке";
if(totalOrders == 2) textStatus = "Два ордера в рынке. Поиск БУ.";
Comment("=== СТАТУС EA FIBONACCI ===\n",
"Направление: ", (isBullish ? "ВВЕРХ (BUY)" : "ВНИЗ (SELL)"), "\n",
"Статус: ", textStatus, "\n",
"Лот: ", DoubleToString(tradeLotMain, 2), "\n",
"-------------------------------------\n",
"50.0% (TP): ", DoubleToString(f50_Price, Digits), "\n",
"61.8% (Вход): ", DoubleToString(f618_Price, Digits), "\n",
"76.4% (Grid): ", DoubleToString(f764_Price, Digits), "\n",
"100.0% (SL): ", DoubleToString(f100_Price, Digits));
if(isCycleFinished) return;
double AskPrice = MarketInfo(Symbol(), MODE_ASK);
double BidPrice = MarketInfo(Symbol(), MODE_BID);
bool actionResult = false;
// --- СЛУЧАЙ А: Нет открытых ордеров ---
if(totalOrders == 0)
{
if(isBullish && BidPrice <= f618_Price && BidPrice > f764_Price)
if(OrderSend(Symbol(), OP_BUY, tradeLotMain, AskPrice, 3, 0, 0, "Fibo BUY Main", InpMagic, 0, clrGreen) < 0) Print("Ошибка BUY: ", GetLastError());
if(!isBullish && AskPrice >= f618_Price && AskPrice < f764_Price)
if(OrderSend(Symbol(), OP_SELL, tradeLotMain, BidPrice, 3, 0, 0, "Fibo SELL Main", InpMagic, 0, clrRed) < 0) Print("Ошибка SELL: ", GetLastError());
}
// --- СЛУЧАЙ Б: Открыт ОДИН ордер ---
if(totalOrders == 1 && OrderSelect(mainOrderTicket, SELECT_BY_TICKET))
{
if(mainType == OP_BUY)
{
if(BidPrice >= f50_Price) { actionResult = OrderClose(OrderTicket(), OrderLots(), BidPrice, 3, CLR_NONE); if(actionResult) isCycleFinished = true; return; }
if(BidPrice <= f100_Price) { actionResult = OrderClose(OrderTicket(), OrderLots(), BidPrice, 3, CLR_NONE); if(actionResult) isCycleFinished = true; return; }
if(BidPrice <= f764_Price) if(OrderSend(Symbol(), OP_BUY, tradeLotGrid, AskPrice, 3, 0, 0, "Fibo BUY Grid", InpMagic, 0, clrGreen) < 0) Print("Ошибка Grid BUY: ", GetLastError());
}
if(mainType == OP_SELL)
{
if(AskPrice <= f50_Price) { actionResult = OrderClose(OrderTicket(), OrderLots(), AskPrice, 3, CLR_NONE); if(actionResult) isCycleFinished = true; return; }
if(AskPrice >= f100_Price) { actionResult = OrderClose(OrderTicket(), OrderLots(), AskPrice, 3, CLR_NONE); if(actionResult) isCycleFinished = true; return; }
if(AskPrice >= f764_Price) if(OrderSend(Symbol(), OP_SELL, tradeLotGrid, BidPrice, 3, 0, 0, "Fibo SELL Grid", InpMagic, 0, clrRed) < 0) Print("Ошибка Grid SELL: ", GetLastError());
}
}
// --- СЛУЧАЙ В: Открыты ОБА ордера (Безубыток с денежной подушкой) ---
if(totalOrders == 2)
{
double totalProfit = 0;
double totalGridLots = 0;
for(int i = OrdersTotal() - 1; i >= 0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != InpMagic) continue;
totalProfit += OrderProfit() + OrderSwap() + OrderCommission();
totalGridLots += OrderLots();
}
double requiredProfit = (totalGridLots / 0.01) * InpProfitBuffer;
if(totalProfit >= requiredProfit)
{
for(int k = OrdersTotal() - 1; k >= 0; k--)
{
if(!OrderSelect(k, SELECT_BY_POS, MODE_TRADES)) continue;
if(OrderSymbol() != Symbol() || OrderMagicNumber() != InpMagic) continue;
double closePrice = (OrderType() == OP_BUY) ? BidPrice : AskPrice;
actionResult = OrderClose(OrderTicket(), OrderLots(), closePrice, 3, CLR_NONE);
if(!actionResult) Print("Ошибка закрытия БУ для билета ", OrderTicket(), ": ", GetLastError());
}
isCycleFinished = true;
}
}
}