Пару своих лепт:
1)
class CTrade : public CObject { //--- bla-bla-bla }
2) Потом, имхо, стоит придумать свою версию класса СSymbolInfo, чтобы избежать:
SymbolInfoDouble () SymbolInfoInteger()
По аналогии с MQL5 придётся создавать свои классы СOrderInfo, CHistoryOrderInfo.
Видать, что у MQ не дошли руки до торговых классов Стандартной библиотеки...
3) Члены-данные называл бы с префикcа m_
Описание членов-переменных хде?
Пару своих лепт:
1)
2) Потом, имхо, стоит придумать свою версию класса СSymbolInfo, чтобы избежать:
По аналогии с MQL5 придётся создавать свои классы СOrderInfo, CHistoryOrderInfo.
Видать у MQ не дошли руки до торговых классов Стандартной библиотеки...
3) Члены-данные называл бы с префикcа m_
Описание членов-переменных хде?
1 не понятно зачем тулить CObject
2 что значит описание , можно больше инфы ?
1 не понятно зачем тулить CObject
ООП. Чтим, ну или не чтим традиции языка :-)
Что означает член-данные. Хотя многое понятно, но всё же...
class Trade { private: MqlTick tick; //ЗАЧЕМ ЭТОТ ТИК ЕСЛИ ЕГО ДОСТАТОЧНО ОБЪЯВИТЬ В МЕТОДЕ? public: //УБРАТЬ ПОЛЯ В ЗОНУ PRIVATE //ЗАЧЕМ ВСЕ ЭТИ ПОЛЯ, ЕСЛИ ОНИ НЕ ИСПОЛЬЗУЮТСЯ В МЕТОДАХ? string symbol; int type; int error; double lots; double price; int slippage; double stoploss; double takeprofit; string comment; int magic; datetime expiration; color arcolor; int ticket; bool rezult; int digits; double point; double breakeven; double breakstep; double trailing; double trailstep; bool F_Send(Trade &str);//ПЕРЕИМЕНОВАТЬ. НАПРИМЕР НА ORDERSEND Trade(); //ЗАЧЕМ ПИСАТЬ ПУСТЫЕ КОНСТРУКТОР И ДИСТРУКТОР? ~Trade(); //УДАЛИТЬ. }; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ Trade :: Trade(){ } Trade :: ~Trade(){ } //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ bool Trade :: F_Send(Trade &str) { ResetLastError(); if(str.symbol==NULL || str.symbol=="")str.symbol=_Symbol; if(str.magic==NULL)str.magic=0; if(str.comment==NULL || str.comment=="")str.comment=StringConcatenate(WindowExpertName()," ",str.magic); int p=0; str.digits=(int)SymbolInfoInteger(str.symbol,SYMBOL_DIGITS); str.point =SymbolInfoDouble (str.symbol,SYMBOL_POINT); if(str.lots<SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MIN))str.lots =SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MIN); if(str.lots>SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MAX))str.lots =SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MAX); while(!IsTradeContextBusy() && p++<5)//НАСКОЛЬКО ПОМНЮ, ContextBusy НЕ АКТУАЛЕН В ПОСЛЕДНИХ ВЕРСИЯХ MQL4 { if(!SymbolInfoTick(str.symbol,tick)) Print("SymbolInfoTick() failed, error = ",GetLastError()); if(str.type==OP_BUY ) str.price=NormalizeDouble(tick.ask,str.digits); //НОРМАЛИЗАЦИЯ НУЖНА В НЕЗАВИСИМОСТИ ОТ ТИПА ОРДЕРА. if(str.type==OP_SELL) str.price=NormalizeDouble(tick.bid,str.digits); RefreshRates();//ВЫЗВАТЬ ДО ПОЛУЧЕНИЯ if(!SymbolInfoTick(str.symbol,tick)) str.ticket=OrderSend( str.symbol, str.type, str.lots, str.price, str.slippage, str.stoploss, str.takeprofit, str.comment, str.magic, str.expiration, str.arcolor ); if(str.ticket<0) Sleep(500); else break; } if(str.ticket>=0) { str.rezult=true; str.error=GetLastError(); return true; } else { str.rezult=false; str.error=GetLastError(); return false; } return false; } //+------------------------------------------------------------------+
После этого
if(!SymbolInfoTick(str.symbol,tick)) Print("SymbolInfoTick() failed, error = ",GetLastError());
Нужно наверное или return или continue. Иначе зачем эта проверка?
В возвращаемой структуре будет запрашиваемая цена, а не цена фактического открытия, которая может отличаться из-за проскальзывания.
+
цены SL и TP тоже было бы неплохо нормализовать.
+ Добавить проверку на разрешение советнику торговать и автоторговлю в терминале. Если эти проверки не сделаны раньше.
+ Проверку на TerminalConnected на случай если вызов идет не из OnTick() а например из OnTimer().
+ Проверка уровней SL & TP на соответствие ограничениям брокера и положению относительно текущей цены.
+ Проверить/Нормализовать запрашиваемый объем позиции (в соотв с VOLUME_STEP)
+ Проверить достаточность маржи
Вот накатал
bool Trade :: SendOrder(Trade &str) { ResetLastError(); //--------------- Проверка на разрешение советнику торговать --------------// int p=0,c=0;string txt=NULL; bool Lan=(TerminalInfoString(TERMINAL_LANGUAGE)=="Russian"); // Разрешение на торговлю кнопка в терминале if(!TerminalInfoInteger(TERMINAL_TRADE_ALLOWED)) { c++; if(Lan)txt=(string)c+"-Отключена кнопка Авто-Торговля "; else txt=(string)c+"-Disable button Auto-Trading "; } // Свойства терминала if(!MQLInfoInteger(MQL_TRADE_ALLOWED)) { c++; if(Lan)txt=txt+(string)c+"-В настройках терминала включите \"Разрешить автоматическую торговлю\", запустите советник в термнале"; else txt=txt+(string)c+"-In the terminal settings include \"Allow automated trading \", run counselor in termnale"; } // Наличие связи с стервером брокера if(!IsConnected()) { c++; if(Lan)txt=txt+(string)c+"-Отсутсвует связь с интернетом / сервером брокера"; else txt=txt+(string)c+"-Not available Internet connection / server broker"; } // алерт с инструкциями if(txt!=NULL) { Alert(txt); return false; } //-------------------------------------------------------------------------// //----------------------------- Неучтенка ---------------------------------// if(str.symbol==NULL || str.symbol=="")str.symbol=_Symbol; if(str.magic==NULL)str.magic=0; if(str.comment==NULL || str.comment=="")str.comment=StringConcatenate(WindowExpertName()," ",str.magic); str.digits=(int)SymbolInfoInteger(str.symbol,SYMBOL_DIGITS); str.point =SymbolInfoDouble (str.symbol,SYMBOL_POINT); m_fl=NormalizeDouble(SymbolInfoInteger(str.symbol,SYMBOL_TRADE_FREEZE_LEVEL)*str.point,str.digits); //-------------------------------------------------------------------------// //------------------ Проверка и нормализация лота--------------------------// if(str.lots<SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MIN))str.lots =SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MIN); if(str.lots>SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MAX))str.lots =SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_MAX); if(MarketInfo(str.symbol,MODE_MARGINREQUIRED)*str.lots>AccountEquity()) // ПО НОВОМУ НЕ НАШОЛ { str.comment="Not enough money to open a position"; str.error=GetLastError(); return false; } if(SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_STEP)==0.001) str.lots=NormalizeDouble(str.lots,3); if(SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_STEP)==0.01) str.lots=NormalizeDouble(str.lots,2); if(SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_STEP)==0.1) str.lots=NormalizeDouble(str.lots,1); if(SymbolInfoDouble (str.symbol,SYMBOL_VOLUME_STEP)==1) str.lots=NormalizeDouble(str.lots,0); //-------------------------------------------------------------------------// //------------------ запускаем цикл на 5 попыток --------------------------// while(!IsTradeContextBusy() && p++<5) { RefreshRates(); // Обновим данные на каждой интерации if(!SymbolInfoTick(str.symbol,tick)) { Print("SymbolInfoTick() failed, error = ",GetLastError()); str.error=GetLastError(); return false; } if(str.type==OP_BUY) { if(str.takeprofit>0) { str.takeprofit=NormalizeDouble(tick.ask+str.takeprofit*str.point,str.digits); if((str.takeprofit-m_fl)<=tick.ask) { str.comment="Error open buy TP freeze level"; str.error=GetLastError(); return false; } } if(str.stoploss>0) { str.stoploss=NormalizeDouble(tick.ask-str.stoploss *str.point,str.digits); if((str.stoploss+m_fl)>=tick.ask) { str.comment="Error open buy SL freeze level"; str.error=GetLastError(); return false; } } str.price=NormalizeDouble(tick.ask,str.digits); } if(str.type==OP_SELL) { if(str.takeprofit>0) { str.takeprofit=NormalizeDouble(tick.bid-str.takeprofit*str.point,str.digits); if((str.takeprofit+m_fl)<=tick.bid) { str.comment="Error open sell TP freeze level"; str.error=GetLastError(); return false; } } if(str.stoploss>0) { str.stoploss=NormalizeDouble(tick.bid+str.stoploss *str.point,str.digits); if((str.stoploss-m_fl)<=tick.bid) { str.comment="Error open sell SL freeze level"; str.error=GetLastError(); return false; } } str.price=NormalizeDouble(tick.bid,str.digits); } str.ticket=OrderSend( str.symbol, str.type, str.lots, str.price, str.slippage, str.stoploss, str.takeprofit, str.comment, str.magic, str.expiration, str.arcolor ); if(str.ticket<0) Sleep(500); else break; } if(str.ticket>=0) { str.rezult=true; str.Get_price=str.price; str.error=GetLastError(); return true; } else { str.rezult=false; str.error=GetLastError(); return false; } return false; }
str.digits str.point
Думаю можно перенести в private
Нафига в параметры засовывать чужой объект (ну или свой)?
bool Trade :: SendOrder(Trade &str)
Имхо, лучше создать для всех торговых параметров структуру что-то типа:
//+------------------------------------------------------------------+ //| Структура базовых торговых элементов | //+------------------------------------------------------------------+ struct STradeElements { double lot; // лот uint stop_loss; // стоплосс,пп uint take_profit; // профит,пп uint trailing_stop; // трал,пп uint slippage; // проскальзывание,пп uint pause; // торговая пауза,мс uint attempts; // торговых попыток string symbol; // инструмент }
и её потом принимать:
bool Trade :: SendOrder(const STradeElements &_tradeStr)
А лучше сделать перегрузку методов.
Для своих торговых параметров так:
bool Trade :: SendOrder(void)
Тогда до этого нужно будет параметры проинициализировать...

- Бесплатные приложения для трейдинга
- 8 000+ сигналов для копирования
- Экономические новости для анализа финансовых рынков
Вы принимаете политику сайта и условия использования
Всем привет!
Недавно в теме вели горячую дискуссию о правильности того или иного кода, по скольку я продолжаю учиться и есть желание не только поделиться своими кодами и опытом но и (получить подзатыльник) получить опыт и примеры других.
Предлагаю кидать не только кирпичи типа: код фуфло и так нельзя но и предлагать свои варианты а так же вести конструктивную тему..
Код не претендует на идеал по этому давайте сообща сделаем его луще!
Вызов в советнике
Пинайте ......