Breakout_and_Risk_manager_EA.mq5 Trade.mqh Object.mqh StdLibErr.mqh OrderInfo.mqh HistoryOrderInfo.mqh PositionInfo.mqh DealInfo.mqh idenfitier 'SymbolName' already used Breakout_and_Risk_manager_EA.mq5 41 8 built-in 'SymbolName' 0 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 83 18 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 85 18 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 86 45 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 88 31 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 88 21 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 89 51 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 106 37 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 106 27 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 107 41 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 107 31 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 108 39 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 108 29 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 116 29 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 116 19 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 117 29 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 117 19 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 206 96 implicit conversion from 'unknown' to 'string' Breakout_and_Risk_manager_EA.mq5 206 85 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 241 164 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 241 154 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 241 216 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 241 206 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 253 51 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 253 41 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 255 177 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 255 167 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 262 67 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 262 57 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 262 99 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 262 131 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 262 121 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 262 89 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 263 53 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 263 84 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 263 74 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 263 43 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 263 149 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 263 139 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 270 52 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 270 42 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 275 39 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 277 51 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 284 52 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 284 42 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 289 40 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 291 51 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 143 93 implicit conversion from 'unknown' to 'string' Breakout_and_Risk_manager_EA.mq5 143 83 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 147 75 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 306 94 implicit conversion from 'unknown' to 'string' Breakout_and_Risk_manager_EA.mq5 306 83 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 313 103 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 313 93 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 313 146 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 313 136 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 323 35 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 329 35 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 336 47 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 336 37 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 356 35 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 434 35 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 434 25 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 465 34 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 465 59 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 465 49 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 465 24 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 466 46 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 466 36 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 472 32 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 472 56 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 472 46 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 472 22 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 473 46 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 473 36 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 479 47 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 479 37 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 482 47 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 482 37 open parenthesis expected Breakout_and_Risk_manager_EA.mq5 483 47 implicit conversion from 'number' to 'string' Breakout_and_Risk_manager_EA.mq5 483 37 47 errors, 34 warnings 47 34
Я скачал исходный код MQL5 — это немало работы, спасибо вам за это, но выше приведены все предупреждения и ошибки, которые выдает MetaEditor при компиляции кода.
Как, пожалуйста, это можно исправить?
MetaQuotes:
Ознакомьтесь с новой статьей: «Автоматизированное управление рисками для преодоления вызовов, стоящих перед проп-фирмами».
Автор: Юджин Ммене
Замените строку TradeSymbol = _Symbol;
Затем замените все вхождения SymbolName на TradeSymbol
Austin Reade исходный код MQL5 — это немало работы, спасибо вам за это, но выше приведены все предупреждения и ошибки, которые выдает MetaEditor при компиляции кода.
Ааа, извините за это. Думаю, я знаю, откуда берутся эти ошибки. Я отлажу код и загружу его заново.
Как, пожалуйста, можно это исправить?
#property copyright "Copyright 2025, Crystal Forex" #property link "" #property version "1.50" #property description «🚀 ПРЕВЗОЙДИТЕ ПРОФЕССИОНАЛЬНЫЕ ТОРГОВЫЕ КОМПАНИИ: Разработано специально для пары XAUUSD, чтобы с легкостью преодолевать любые трудности». #property description «🛡️ ИНСТИТУЦИОНАЛЬНАЯ ЗАЩИТА: встроенные механизмы контроля за просадкой и уровнем собственного капитала гарантируют, что вы никогда не нарушите правила». #property description «📈 АДАПТИВНЫЕ ПРОРЫВЫ: интеллектуальные фильтры новостей и логика, учитывающая несколько временных интервалов, позволяют уловить значительные колебания цены на золото». #property description «💰 FUNDED READY: Полностью автоматизированная система, которая превратит вашу торговлю в профессиональную карьеру». #include <Trade\Trade.mqh> //+------------------------------------------------------------------+ //| Входные параметры | //+------------------------------------------------------------------+ input group "Risk Management" input double RiskPct = 2.0; // Базовый риск на одну сделку, % input double MaxLossUSD = 110.0; // Максимальный убыток на одну сделку в долларах США (жесткий лимит) input double DailyDDLimit = 2.5; // Ежедневный лимит просадки (%) input double OverallDDLimit = 5.5; // Общий лимит просадки (%) input double TargetBalanceOrEquity = 108000.0; // Цель — пройти испытание input group "Strategy Settings" input int ATR_Prd = 14; // Период ATR input int Brk_Prd = 10; // Период обратного анализа для стратегии «Breakout» (бары) input double MinBrkStr = 0.1; // Минимальная пробиваемость (множитель ATR) input int EMA_Prd = 20; // Период EMA для фильтра тренда input bool useHTF = true; // Использовать фильтр направления HTF (D1/H4) input group "News Filter" input bool NewsFilt = true; // Включить фильтр новостей input int NewsPause = 15; // Количество минут паузы до/после новостей //+------------------------------------------------------------------+ //| Глобальные переменные | //+------------------------------------------------------------------+ double CurRisk = RiskPct; double LastEqHigh = 0; double StartingBalance = 0; double DailyBalance = 0; datetime LastDay = 0; bool ProfitTargetReached = false; bool DailyDDReached = false; double dynBrkStr = MinBrkStr; CTrade trade; int h_ema_d1 = INVALID_HANDLE; int h_ema_h4 = INVALID_HANDLE; string WorkSymbol; // Переименовано, чтобы избежать конфликта со встроенной функцией SymbolName() // Структура для данных, относящихся к конкретному временному интервалу struct TimeframeData { ENUM_TIMEFRAMES tf; int h_atr; datetime lastSig; datetime lastBar; }; TimeframeData tfs[]; // Структура новостных событий struct NewsEvt { datetime time; int impact; // 0 = низкий, 1 = средний, 2 = высокий }; NewsEvt newsCal[]; int newsCnt = 0; //+------------------------------------------------------------------+ //| Функция инициализации эксперта | //+------------------------------------------------------------------+ int OnInit() { datetime ExpiryDate = D'2025.12.30'; // Укажите здесь дату истечения срока действия (ГГГГ.ММ.ДД) if(TimeCurrent() > ExpiryDate) { Alert("Trial Expired! Please contact the developer: https://www.mql5.com/ru/users/jawadtrader22/seller"); Print("Trial Expired! Please contact the developer."); return(INIT_FAILED); // Это предотвращает инициализацию советника } if(AccountInfoDouble(ACCOUNT_BALANCE) < 100.0) { Print("Error: Balance too low for Prop Firm logic."); return(INIT_FAILED); } WorkSymbol = _Symbol; if(!SymbolSelect(WorkSymbol, true)) { Print("Failed to select symbol."); return(INIT_FAILED); } StartingBalance = AccountInfoDouble(ACCOUNT_BALANCE); LastEqHigh = AccountInfoDouble(ACCOUNT_EQUITY); DailyBalance = StartingBalance; LastDay = (datetime)(TimeCurrent() / 86400 * 86400); ArrayResize(tfs, 2); tfs[0].tf = PERIOD_M15; tfs[1].tf = PERIOD_H1; for(int i = 0; i < 2; i++) { tfs[i].h_atr = iATR(WorkSymbol, tfs[i].tf, ATR_Prd); tfs[i].lastBar = 0; if(tfs[i].h_atr == INVALID_HANDLE) { Print("Failed to create ATR handle."); return(INIT_FAILED); } } h_ema_d1 = iMA(WorkSymbol, PERIOD_D1, EMA_Prd, 0, MODE_EMA, PRICE_CLOSE); h_ema_h4 = iMA(WorkSymbol, PERIOD_H4, EMA_Prd, 0, MODE_EMA, PRICE_CLOSE); if(h_ema_d1 == INVALID_HANDLE || h_ema_h4 == INVALID_HANDLE) { Print("Failed to create HTF EMA handles."); return(INIT_FAILED); } if(NewsFilt) FetchNewsCalendar(); Print("EA Initialized. Target: ", DoubleToString(TargetBalanceOrEquity, 2)); return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Функция деинициализации эксперта | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { IndicatorRelease(h_ema_d1); IndicatorRelease(h_ema_h4); for(int i = 0; i < ArraySize(tfs); i++) { IndicatorRelease(tfs[i].h_atr); } Print("EA Deinitialized."); } //+------------------------------------------------------------------+ //| Функция «экспертного тика» | //+------------------------------------------------------------------+ void OnTick() { // --- Алгоритм ежедневного сброса --- datetime currentDay = (datetime)(TimeCurrent() / 86400 * 86400); if(currentDay > LastDay) { DailyBalance = AccountInfoDouble(ACCOUNT_BALANCE); LastDay = currentDay; DailyDDReached = false; Print("New Day. Daily Balance Reset to: ", DoubleToString(DailyBalance, 2)); } // --- Проверка брокерских фирм --- if(DailyDDReached || ProfitTargetReached) return; double equity = AccountInfoDouble(ACCOUNT_EQUITY); double balance = AccountInfoDouble(ACCOUNT_BALANCE); if(balance >= TargetBalanceOrEquity || equity >= TargetBalanceOrEquity) { CloseAllPositions(); ProfitTargetReached = true; Print("PROFIT TARGET REACHED! Trading Stopped."); return; } double dailyDD = (DailyBalance - equity) / DailyBalance * 100.0; double overallDD = (StartingBalance - equity) / StartingBalance * 100.0; if(dailyDD >= DailyDDLimit || overallDD >= OverallDDLimit) { CloseAllPositions(); DailyDDReached = true; Print("DRAWDOWN LIMIT BREACHED! Daily: ", DoubleToString(dailyDD, 2), "%, Overall: ", DoubleToString(overallDD, 2), "%"); return; } // --- Последние новости --- static datetime lastNewsFetch = 0; if(NewsFilt && TimeCurrent() >= lastNewsFetch + 4*3600) { FetchNewsCalendar(); lastNewsFetch = TimeCurrent(); } if(NewsFilt && IsNews()) return; // --- Цикл стратегии --- for(int i = 0; i < ArraySize(tfs); i++) { ManageTrades(tfs[i].tf); if(!NewBar(tfs[i].tf, tfs[i].lastBar)) continue; if(PositionsTotal() < 5) { double atrVal = GetIndicatorVal(tfs[i].h_atr, 0); bool buySignal = BuyBrk(tfs[i].tf) && (!useHTF || BullTrend()); bool sellSignal = SellBrk(tfs[i].tf) && (!useHTF || BearTrend()); if(buySignal) { double sl = SymbolInfoDouble(WorkSymbol, SYMBOL_ASK) - (atrVal * 1.5); double tp = SymbolInfoDouble(WorkSymbol, SYMBOL_ASK) + (atrVal * 3.0); double lots = CalcLots(MathAbs(SymbolInfoDouble(WorkSymbol, SYMBOL_ASK) - sl)); if(lots > 0) { trade.SetExpertMagicNumber(MagicNumber(tfs[i].tf)); trade.Buy(lots, WorkSymbol, 0, sl, tp, "Gold Breakout Buy"); } } else if(sellSignal) { double sl = SymbolInfoDouble(WorkSymbol, SYMBOL_BID) + (atrVal * 1.5); double tp = SymbolInfoDouble(WorkSymbol, SYMBOL_BID) - (atrVal * 3.0); double lots = CalcLots(MathAbs(sl - SymbolInfoDouble(WorkSymbol, SYMBOL_BID))); if(lots > 0) { trade.SetExpertMagicNumber(MagicNumber(tfs[i].tf)); trade.Sell(lots, WorkSymbol, 0, sl, tp, "Gold Breakout Sell"); } } } } } //+------------------------------------------------------------------+ //| Вспомогательные функции | //+------------------------------------------------------------------+ double CalcLots(double slPointsDistance) { if(slPointsDistance <= 0) return 0.0; double accountBalance = AccountInfoDouble(ACCOUNT_BALANCE); double riskMoney = accountBalance * (CurRisk / 100.0); if(riskMoney > MaxLossUSD) riskMoney = MaxLossUSD; // Верхний предел double tickValue = SymbolInfoDouble(WorkSymbol, SYMBOL_TRADE_TICK_VALUE); double tickSize = SymbolInfoDouble(WorkSymbol, SYMBOL_TRADE_TICK_SIZE); if(tickValue == 0 || tickSize == 0) return 0.0; double lots = riskMoney / ( (slPointsDistance / tickSize) * tickValue ); double minLot = SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_MIN); double maxLot = SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_MAX); double stepLot = SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_STEP); lots = MathFloor(lots / stepLot) * stepLot; if(lots < minLot) return 0.0; if(lots > maxLot) lots = maxLot; return lots; } void ManageTrades(ENUM_TIMEFRAMES tf) { for(int i = PositionsTotal()-1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(!PositionSelectByTicket(ticket)) continue; if(PositionGetString(POSITION_SYMBOL) != WorkSymbol) continue; if(PositionGetInteger(POSITION_MAGIC) != MagicNumber(tf)) continue; double openPrice = PositionGetDouble(POSITION_PRICE_OPEN); double sl = PositionGetDouble(POSITION_SL); double tp = PositionGetDouble(POSITION_TP); double lots = PositionGetDouble(POSITION_VOLUME); double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT); long type = PositionGetInteger(POSITION_TYPE); int tfIdx = (tf == PERIOD_M15) ? 0 : 1; double atr = GetIndicatorVal(tfs[tfIdx].h_atr, 0); // Аварийный выход if(type == POSITION_TYPE_BUY && SellBrk(tf)) { trade.PositionClose(ticket); continue; } if(type == POSITION_TYPE_SELL && BuyBrk(tf)) { trade.PositionClose(ticket); continue; } // Частичное закрытие и BE double dist = (type == POSITION_TYPE_BUY) ? (currentPrice - openPrice) : (openPrice - currentPrice); if(dist > (atr * 2.5)) { bool isBE = (type == POSITION_TYPE_BUY && sl >= openPrice) || (type == POSITION_TYPE_SELL && sl <= openPrice); if(!isBE && lots >= SymbolInfoDouble(WorkSymbol, SYMBOL_VOLUME_MIN) * 2) { trade.PositionClosePartial(ticket, lots / 2.0); trade.PositionModify(ticket, openPrice, tp); } } // Трейлинг-стоп double trailDist = atr * 1.6; if(type == POSITION_TYPE_BUY) { double newSL = currentPrice - trailDist; if(newSL > sl && newSL < currentPrice) trade.PositionModify(ticket, newSL, tp); } else if(type == POSITION_TYPE_SELL) { double newSL = currentPrice + trailDist; if(newSL < sl || sl == 0) trade.PositionModify(ticket, newSL, tp); } } } bool BuyBrk(ENUM_TIMEFRAMES tf) { double close1 = iClose(WorkSymbol, tf, 1); int highIdx = iHighest(WorkSymbol, tf, MODE_HIGH, Brk_Prd, 2); if(highIdx < 0) return false; double highVal = iHigh(WorkSymbol, tf, highIdx); int tfIdx = (tf == PERIOD_M15) ? 0 : 1; double atr = GetIndicatorVal(tfs[tfIdx].h_atr, 1); return (close1 > (highVal + (atr * dynBrkStr))); } bool SellBrk(ENUM_TIMEFRAMES tf) { double close1 = iClose(WorkSymbol, tf, 1); int lowIdx = iLowest(WorkSymbol, tf, MODE_LOW, Brk_Prd, 2); if(lowIdx < 0) return false; double lowVal = iLow(WorkSymbol, tf, lowIdx); int tfIdx = (tf == PERIOD_M15) ? 0 : 1; double atr = GetIndicatorVal(tfs[tfIdx].h_atr, 1); return (close1 < (lowVal - (atr * dynBrkStr))); } bool BullTrend() { double d1_ema = GetIndicatorVal(h_ema_d1, 1); double d1_close = iClose(WorkSymbol, PERIOD_D1, 1); return (d1_close > d1_ema); } bool BearTrend() { double d1_ema = GetIndicatorVal(h_ema_d1, 1); double d1_close = iClose(WorkSymbol, PERIOD_D1, 1); return (d1_close < d1_ema); } bool IsNews() { datetime now = TimeCurrent(); for(int i=0; i<newsCnt; i++) { if(newsCal[i].impact < 2) continue; if(now >= newsCal[i].time - (NewsPause * 60) && now <= newsCal[i].time + (NewsPause * 60)) return true; } return false; } void FetchNewsCalendar() { // Заполнитель: сброс счетчика новостей в целях безопасности newsCnt = 0; } void CloseAllPositions() { for(int i = PositionsTotal() - 1; i >= 0; i--) { ulong ticket = PositionGetTicket(i); if(PositionSelectByTicket(ticket) && PositionGetString(POSITION_SYMBOL) == WorkSymbol) { trade.PositionClose(ticket); } } } double GetIndicatorVal(int handle, int index) { double buf[1]; if(CopyBuffer(handle, 0, index, 1, buf) < 0) return 0.0; return buf[0]; } bool NewBar(ENUM_TIMEFRAMES tf, datetime &last_bar_time) { datetime curr_bar_time = iTime(WorkSymbol, tf, 0); if(curr_bar_time != last_bar_time) { last_bar_time = curr_bar_time; return true; } return false; } long MagicNumber(ENUM_TIMEFRAMES tf) { if(tf == PERIOD_M15) return 1015; if(tf == PERIOD_H1) return 1060; return 1000; }Полный код для копирования и вставки
Файлы:
propfirm.mq5
27 kb
Austin Reade исходный код Mql5 — это немало работы, спасибо за это, но выше приведены все предупреждения и ошибки, которые выдает MetaEditor при компиляции кода.
Вот исправленный код
Как, пожалуйста, это исправить?
Файлы:
Вы упускаете торговые возможности:
- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Регистрация
Вход
Вы принимаете политику сайта и условия использования
Если у вас нет учетной записи, зарегистрируйтесь
Опубликована статья Автоматизированный риск-менеджмент для прохождения челленджей проп-фирм:
Эта статья написана мной с единственной целью — рассмотреть недавно возникшее явление, известное как торговля в проп-фирмах. Дело в том, что торговля в проп-фирмах в целом — это привлекательное, прибыльное и приносящее удовлетворение занятие, но, как только человек решает пойти по этому пути, ему приходится сталкиваться с серьезными трудностями и препятствиями. Самое распространённое препятствие, с которым сталкивается большинство трейдеров, пытающихся пройти челленджи проп-фирм, — это не отсутствие стратегии, методики или навыков, а строгие ограничения и торговые правила, установленные проп-фирмой; их необходимо соблюдать, чтобы трейдер мог доказать, что ему можно предоставить доступ к реальному торговому счёту.
Дело в том, что трейдер может хорошо анализировать рынок, придерживаться своего торгового плана, открывать сделки и распознавать тренды — этого вполне может хватить для торговли собственными реальными средствами, но не для торговли в проп-фирме, где от трейдера требуется строго соблюдать ее правила и заданные лимиты.
К числу наиболее распространенных правил, целевых показателей и ограничений относятся:
Автор: Eugene Mmene