//+------------------------------------------------------------------+ //| TMS_EA.mq4 | //| Generated by MetaEditor | //| | //+------------------------------------------------------------------+ #property strict // Входни параметри input double LotSize = 0.1; // Размер на лота input int TakeProfitPips = 50; // Тейкпрофит в пипсове input int StopLoss = 30; // Стоплос в пипсове input int MagicNumber = 123456; // Магическо число за идентификация на поръчките // Глобални променливи int LastSignal = 0; // Последен сигнал (0 - няма, 1 - покупка, 2 - продажба) double AccumulatedLoss = 0; // Натрупана загуба double TotalProfit = 0; // Обща натрупана печалба int TradeCount = 1; // Брояч на поръчките в серията bool LastTradePositive = true; // Флаг за последната успешна търговия bool IsDynamicLotGroup = false; // Флаг за група операции с динамичен лот //+------------------------------------------------------------------+ //| Функция за изчисляване на стойността на 1 пип в текущата валута | //+------------------------------------------------------------------+ double PipValue() { return MarketInfo(Symbol(), MODE_TICKVALUE); } //+------------------------------------------------------------------+ //| Функция за преобразуване на цена в пипсове | //+------------------------------------------------------------------+ double PriceToPips(double price) { if (Digits == 2 || Digits == 3) // За валутни двойки (например EURUSD) return price * 10; // 1 пипс = 0.0001, но в MT4 се представя като 0.00010 else if (Digits == 5 || Digits == 4) // За валутни двойки с 5 знака (например EURUSD.pro) return price * 10; // 1 пипс = 0.00010 else if (Digits == 2 && StringFind(Symbol(), "XAU") != -1) // За злато (XAUUSD) return price * 10; // 1 пипс = 0.1 return price; // За други инструменти } //+------------------------------------------------------------------+ //| Функция за запис на състоянието във файл | //+------------------------------------------------------------------+ void SaveState() { int retries = 3; while (retries > 0) { int handle = FileOpen("TMS_EA_state.txt", FILE_WRITE|FILE_TXT); if(handle != INVALID_HANDLE) { string data = StringFormat("%d,%.2f,%.2f,%d,%d,%d", LastSignal, AccumulatedLoss, TotalProfit, TradeCount, LastTradePositive, IsDynamicLotGroup); FileWrite(handle, data); FileClose(handle); break; } else { Print("Грешка при запис на състоянието: ", GetLastError()); retries--; Sleep(1000); // Изчакване преди повторен опит } } } //+------------------------------------------------------------------+ //| Функция за четене на състоянието от файл | //+------------------------------------------------------------------+ void LoadState() { if (FileIsExist("TMS_EA_state.txt")) { int retries = 3; while (retries > 0) { int handle = FileOpen("TMS_EA_state.txt", FILE_READ|FILE_TXT); if(handle != INVALID_HANDLE) { string data = FileReadString(handle); string values[]; int count = StringSplit(data, ',', values); if(count == 6) { LastSignal = (int)StringToInteger(values[0]); AccumulatedLoss = StringToDouble(values[1]); TotalProfit = StringToDouble(values[2]); TradeCount = (int)StringToInteger(values[3]); LastTradePositive = (bool)StringToInteger(values[4]); IsDynamicLotGroup = (bool)StringToInteger(values[5]); } else { Print("Грешка при четене на състоянието: Неправилен брой стойности."); } FileClose(handle); break; } else { Print("Грешка при четене на състоянието: ", GetLastError()); retries--; Sleep(1000); // Изчакване преди повторен опит } } } else { Print("Файлът със състоянието не съществува. Създаване на нов."); } } //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { LoadState(); // Зареждане на състоянието при стартиране Print("EA initialized successfully."); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { SaveState(); // Запис на състоянието при затваряне на EA Print("EA deinitialized successfully."); } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { static datetime LastBarTime = 0; if (LastBarTime == iTime(NULL, 0, 0)) return; LastBarTime = iTime(NULL, 0, 0); double TrendUp1 = iCustom(NULL, 0, "TMS-Osc Histo", 4, 1); double TrendUp0 = iCustom(NULL, 0, "TMS-Osc Histo", 4, 0); double TrendDn1 = iCustom(NULL, 0, "TMS-Osc Histo", 5, 1); double TrendDn0 = iCustom(NULL, 0, "TMS-Osc Histo", 5, 0); // Проверка дали да спре EA само за група операции с динамичен лот if (IsDynamicLotGroup && TotalProfit >= TakeProfitPips * PipValue() * LotSize * TradeCount) return; if (TrendUp1 == 1 && TrendUp0 == 1 && LastSignal != 1) { HandleTrade(OP_BUY); SaveState(); // Запис на състоянието след всяка търговия } if (TrendDn1 == 1 && TrendDn0 == 1 && LastSignal != 2) { HandleTrade(OP_SELL); SaveState(); // Запис на състоянието след всяка търговия } } //+------------------------------------------------------------------+ //| HandleTrade function | //+------------------------------------------------------------------+ void HandleTrade(int cmd) { CloseAllOrders(); if (LastTradePositive) { TradeCount = 1; // Нулиране на брояча при положителна сделка AccumulatedLoss = 0; // Нулиране на натрупаната загуба IsDynamicLotGroup = false; // Нулиране на флага за група операции } else { IsDynamicLotGroup = true; // Активиране на флага за група операции } double lot = LotSize * TradeCount; // Лотът се увеличава // Изчисляване на тейкпрофита за текущата операция double targetProfitPips = (AccumulatedLoss + TakeProfitPips) * TradeCount; // Умножаваме по броя на операциите // Логиране на стойностите Print("AccumulatedLoss: ", AccumulatedLoss); Print("TradeCount: ", TradeCount); Print("TotalProfit: ", TotalProfit); Print("IsDynamicLotGroup: ", IsDynamicLotGroup); Print("targetProfitPips: ", targetProfitPips); Print("Lot: ", lot); if (OpenOrder(cmd, lot, targetProfitPips)) { LastSignal = (cmd == OP_BUY) ? 1 : 2; } } //+------------------------------------------------------------------+ //| Функция за отваряне на поръчка | //+------------------------------------------------------------------+ bool OpenOrder(int cmd, double lot, double tpPips) { double price = (cmd == OP_BUY) ? Ask : Bid; double sl = (cmd == OP_BUY) ? price - StopLoss * Point : price + StopLoss * Point; double tp = (cmd == OP_BUY) ? price + tpPips * Point : price - tpPips * Point; int ticket = OrderSend(Symbol(), cmd, lot, price, 3, sl, tp, "", MagicNumber, 0, clrNONE); if (ticket < 0) { Print("Грешка при отваряне на поръчка: ", GetLastError()); return false; } return true; } //+------------------------------------------------------------------+ //| Функция за затваряне на всички поръчки | //+------------------------------------------------------------------+ void CloseAllOrders() { double totalProfit = 0; double totalWeightedLossPips = 0; // Обща претеглена загуба в пипсове for (int i = OrdersTotal() - 1; i >= 0; i--) { if (OrderSelect(i, SELECT_BY_POS) && OrderMagicNumber() == MagicNumber && OrderSymbol() == Symbol()) { if (OrderType() == OP_BUY || OrderType() == OP_SELL) { // Изчисляване на печалбата за текущата поръчка double profit = OrderProfit() + OrderSwap() + OrderCommission(); totalProfit += profit; // Затваряне на поръчката if (!OrderClose(OrderTicket(), OrderLots(), OrderClosePrice(), 3, clrNONE)) { Print("Грешка при затваряне на поръчка: ", GetLastError()); } // Натрупване на загубите в пипсове, претеглени според лота if (profit < 0) { double lossPips = MathAbs(profit) / (OrderLots() * PipValue()); lossPips = PriceToPips(lossPips); // Преобразуване на загубата в пипсове totalWeightedLossPips += lossPips * OrderLots(); // Претеглена загуба // Логиране на загубата Print("Загуба в пипсове: ", lossPips, " (Лот: ", OrderLots(), ")"); } } } } // Обновяване на общата печалба TotalProfit += totalProfit; // Проверка дали последната търговия е с положителен изход if (totalProfit >= 0) { LastTradePositive = true; // Нулиране на флага само ако общата печалба е по-голяма или равна на целевата печалба if (TotalProfit >= TakeProfitPips * PipValue() * LotSize * TradeCount) { IsDynamicLotGroup = false; // Нулиране на флага за група операции TradeCount = 1; // Нулиране на брояча на търговиите AccumulatedLoss = 0; // Нулиране на натрупаната загуба TotalProfit = 0; // Нулиране на общата печалба } } else { LastTradePositive = false; IsDynamicLotGroup = true; // Активиране на флага за група операции } if (!LastTradePositive) TradeCount++; // Увеличаваме само при загуба // Логиране на стойностите Print("AccumulatedLoss: ", AccumulatedLoss); Print("TradeCount: ", TradeCount); Print("TotalProfit: ", TotalProfit); Print("IsDynamicLotGroup: ", IsDynamicLotGroup); Print("TotalWeightedLossPips: ", totalWeightedLossPips); SaveState(); // Запис на състоянието след затваряне на поръчки }