← К каталогу
Исходный код · ID 3867

OrderReliable

ordersendreliable.mqh
Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

OrderReliable — это библиотека исходного кода для MetaTrader 4, предоставляющая функции надёжной обработки торговых операций для экспертных советников. Она выступает заменой стандартным функциям OrderSend(), OrderModify() и OrderClose(), добавляя обработку ошибок и повторные попытки выполнения.

Состав библиотеки

Классов: 0 · методов: 0 · конструкторов: 0 · деструкторов: 0 · отдельных функций: 10

Функции
Функция bool OrderModifyReliable(int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color)

Модифицирует существующий ордер с обработкой ошибок и повторными попытками.

Функция bool OrderModifyReliableSymbol(string symbol, int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color)

Модифицирует ордер с явным указанием символа, обеспечивая нормализацию и проверку стоп-лосса.

Функция int OrderReliableLastErr()

Возвращает код последней ошибки, зафиксированной при вызове функций Order*Reliable.

Функция string OrderReliableErrTxt(int err)

Возвращает текстовое описание ошибки по её коду.

Функция void OrderReliablePrint(string s)

Выводит сообщение в лог с именем функции и версией библиотеки.

Функция void OrderReliable_EnsureValidStop(string symbol, double price, double& sl)

Корректирует стоп-лосс, если он слишком близок к цене, в соответствии с минимальным расстоянием сервера.

Функция string OrderReliable_CommandString(int cmd)

Возвращает строковое представление типа торговой команды.

Функция void OrderReliable_SleepRandomTime(double mean_time, double max_time)

Приостанавливает выполнение на случайное время с экспоненциальным распределением (back-off).

Функция bool O_R_CheckForHistory(int ticket)

Проверяет, появился ли ордер с заданным тикетом в истории открытых или закрытых ордеров.

Функция void O_R_Sleep(double mean_time, double max_time)

Приостанавливает выполнение на случайное время с экспоненциальным распределением.

Получить полный код

Поиск по коду файла

/*         This is intended to be a drop-in replacement for OrderSend() which, one hopes
           is more resistant to various forms of errors prevalent with MetaTrader.

syntax:

    int OrderSendReliable(string symbol, int cmd, double volume, double price,
		   int slippage, double stoploss, double takeprofit,
		   string comment, int magic, datetime expiration =
		   0, color arrow_color = CLR_NONE) //    

returns: ticket number or -1 under some error conditions. 

    Features:
       * re-trying under some error conditions, sleeping
         a random time defined by an exponential probability distribution.
       * automatic normalization of Digits
       * automatically makes sure that stop levels are more than
         the minimum stop distance, as given by the server.
       * automatically converts limit orders to market orders 
         when the limit orders are rejected by the server for being
         to close to market.
       * displays various error messages on the log for debugging.

  Matt Kennel, m******l*@gmail.com  2006-05-28
 */

#include <stdlib.mqh>
#include <stderror.mqh> 

string OrderReliableVersion = "V0_2_3"; 

int retry_attempts = 10; 
double sleep_time = 4.0, sleep_maximum = 25.0;  // in seconds

string OrderReliable_Fname = "OrderReliable fname unset";

static int _OR_err = 0; // 

int 	         O_R_Setting_max_retries 	= 10;
double 	      O_R_Setting_sleep_time 		= 4.0; /* seconds */
double 	      O_R_Setting_sleep_max 		= 15.0; /* seconds */

int OrderSendReliable(string symbol, int cmd, double volume, double price,
		   int slippage, double stoploss, double takeprofit,
		   string comment, int magic, datetime expiration =
		   0, color arrow_color = CLR_NONE) {

   OrderReliable_Fname = "OrderSendReliable";
   OrderReliablePrint(" attempted "+OrderReliable_CommandString(cmd)+" "+volume+" lots @"+price+" sl:"+stoploss+" tp:"+takeprofit); 
   if (!IsConnected()) {
      OrderReliablePrint("error: IsConnected() == false");
      _OR_err = ERR_NO_CONNECTION; 
      return(-1);
   }
   if (IsStopped()) {
      OrderReliablePrint("error: IsStopped() == true");
      _OR_err = ERR_COMMON_ERROR; 
      return(-1);
   }
   int cnt = 0;
   while(!IsTradeAllowed() && cnt < retry_attempts) {
      OrderReliable_SleepRandomTime(sleep_time,sleep_maximum); 
      cnt++;
   }
   if (!IsTradeAllowed()) {
      OrderReliablePrint("error: no operation possible because IsTradeAllowed()==false, even after retries.");
      _OR_err = ERR_TRADE_CONTEXT_BUSY; 

      return(-1);  
   }

   int digits = MarketInfo(symbol,MODE_DIGITS);
   if (digits > 0) {
      price = NormalizeDouble(price,digits);
      stoploss = NormalizeDouble(stoploss,digits);
      takeprofit = NormalizeDouble(takeprofit,digits); 
   }
   if (stoploss != 0) OrderReliable_EnsureValidStop(symbol,price,stoploss); 

   int err = GetLastError(); // so we clear the global variable.  
   err = 0; 
   _OR_err = 0; 
   bool exit_loop = false;
   bool limit_to_market = false; 

   int ticket=-1;

   if ((cmd == OP_BUYSTOP) || (cmd == OP_SELLSTOP) || (cmd == OP_BUYLIMIT) || (cmd == OP_SELLLIMIT)) {
       cnt = 0;
       while (!exit_loop) {
          if (IsTradeAllowed()) {
             ticket = OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color);
             err = GetLastError();
             _OR_err = err; 
          } else {
            cnt++;
          } 
          switch (err) {
            case ERR_NO_ERROR:
               exit_loop = true;
               break;
            case ERR_SERVER_BUSY:
            case ERR_NO_CONNECTION:
            case ERR_INVALID_PRICE:
            case ERR_OFF_QUOTES:
            case ERR_BROKER_BUSY:
            case ERR_TRADE_CONTEXT_BUSY: 
               cnt++; // a retryable error
               break;
            case ERR_PRICE_CHANGED:
            case ERR_REQUOTE:
               RefreshRates();
               continue; // we can apparently retry immediately according to MT docs.
            case ERR_INVALID_STOPS:
               double servers_min_stop = MarketInfo(symbol,MODE_STOPLEVEL)*MarketInfo(symbol,MODE_POINT); 
               if (cmd == OP_BUYSTOP) {
                 if (MathAbs(Ask - price) <= servers_min_stop)

                    limit_to_market = true; 
               } else if (cmd == OP_SELLSTOP) {
                 if (MathAbs(Bid - price) <= servers_min_stop)
                    limit_to_market = true; 
               }
               exit_loop = true; 
               break; 
            default:

               exit_loop = true;
               break; 
          }  // end switch 

          if (cnt > retry_attempts) exit_loop = true; 
          if (exit_loop) {
            if (err != ERR_NO_ERROR) {
               OrderReliablePrint("non-retryable error: " +OrderReliableErrTxt(err)); 
            }
            if (cnt > retry_attempts) {
               OrderReliablePrint("retry attempts maxed at "+retry_attempts); 
            }
          }
          if (!exit_loop) {
              OrderReliablePrint("retryable error ("+cnt+"/"+retry_attempts+"): " + OrderReliableErrTxt(err)); 
              OrderReliable_SleepRandomTime(sleep_time,sleep_maximum); 
              RefreshRates(); 
          }
       }

      if (err == ERR_NO_ERROR) {
         OrderReliablePrint("apparently successful OP_BUYSTOP or OP_SELLSTOP order placed, details follow.");
         OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES); 
         OrderPrint(); 
         return(ticket); // SUCCESS! 
      } 
      if (!limit_to_market) {
         OrderReliablePrint("failed to execute stop or limit order after "+cnt+" retries");
         OrderReliablePrint("failed trade: " + OrderReliable_CommandString(cmd)+" "+symbol+"@"+price+" tp@"+takeprofit+" sl@"+stoploss); 
         OrderReliablePrint("last error: "+OrderReliableErrTxt(err)); 
         return(-1); 
      }
   }  // end     

   if (limit_to_market) {
      OrderReliablePrint("going from limit order to market order because market is too close.");
      if ((cmd == OP_BUYSTOP) || (cmd == OP_BUYLIMIT)) {
         cmd = OP_BUY;
         price = Ask;
      } else if ((cmd == OP_SELLSTOP) || (cmd == OP_SELLLIMIT)) {
         cmd = OP_SELL;
         price = Bid;
      }   
   }

   err = GetLastError(); // so we clear the global variable.  
   err = 0; 
   _OR_err = 0; 
   ticket=-1;

   if ((cmd == OP_BUY) || (cmd == OP_SELL)) {
       cnt = 0;
       while (!exit_loop) {
          if (IsTradeAllowed()) {
             ticket = OrderSend(symbol, cmd, volume, price, slippage, stoploss, takeprofit, comment, magic, expiration, arrow_color);
             err = GetLastError();
             _OR_err = err; 
          } else {
            cnt++;
          } 
          switch (err) {
            case ERR_NO_ERROR:
               exit_loop = true;
               break;
            case ERR_SERVER_BUSY:
            case ERR_NO_CONNECTION:
            case ERR_INVALID_PRICE:
            case ERR_OFF_QUOTES:
            case ERR_BROKER_BUSY:
            case ERR_TRADE_CONTEXT_BUSY: 
               cnt++; // a retryable error
               break;
            case ERR_PRICE_CHANGED:
            case ERR_REQUOTE:
               RefreshRates();
               continue; // we can apparently retry immediately according to MT docs.
            default:

               exit_loop = true;
               break; 
          }  // end switch 

          if (cnt > retry_attempts) exit_loop = true; 
          if (!exit_loop) {
              OrderReliablePrint("retryable error ("+cnt+"/"+retry_attempts+"): " + OrderReliableErrTxt(err)); 
              OrderReliable_SleepRandomTime(sleep_time,sleep_maximum); 
              RefreshRates(); 
          }
          if (exit_loop) {
            if (err != ERR_NO_ERROR) {
               OrderReliablePrint("non-retryable error: " +OrderReliableErrTxt(err)); 
            }
            if (cnt > retry_attempts) {
               OrderReliablePrint("retry attempts maxed at "+retry_attempts); 
            }
          }
       }

      if (err == ERR_NO_ERROR) {
         OrderReliablePrint("apparently successful OP_BUY or OP_SELL order placed, details follow.");
          O_R_CheckForHistory(ticket);
         OrderSelect(ticket, SELECT_BY_TICKET, MODE_TRADES); 
         OrderPrint(); 
         return(ticket); // SUCCESS! 
      } 
      OrderReliablePrint("failed to execute OP_BUY/OP_SELL, after "+cnt+" retries");
      OrderReliablePrint("failed trade: " + OrderReliable_CommandString(cmd)+" "+symbol+"@"+price+" tp@"+takeprofit+" sl@"+stoploss); 
      OrderReliablePrint("last error: "+OrderReliableErrTxt(err)); 
      return(-1); 
   }
}  // end     

bool OrderModifyReliable(int ticket, double price, double stoploss, double takeprofit, datetime expiration, color arrow_color=CLR_NONE) {

    OrderReliable_Fname = "OrderModifyReliable";

   OrderReliablePrint(" attempted modify of #"+ticket+" price:"+price+" sl:"+stoploss+" tp:"+takeprofit); 

    if (!IsConnected()) {
      OrderReliablePrint("error: IsConnected() == false");
      _OR_err = ERR_NO_CONNECTION; 
      return(false);
   }
   if (IsStopped()) {
      OrderReliablePrint("error: IsStopped() == true");
      return(false);
   }
   int cnt = 0;
   while(!IsTradeAllowed() && cnt < retry_attempts) {
      OrderReliable_SleepRandomTime(sleep_time,sleep_maximum); 
      cnt++;
   }
   if (!IsTradeAllowed()) {
      OrderReliablePrint("error: no operation possible because IsTradeAllowed()==false, even after retries.");
      _OR_err = ERR_TRADE_CONTEXT_BUSY; 
      return(false);  
   }

   if (false) {

       OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES);
       string symbol = OrderSymbol();
       int digits = MarketInfo(symbol,MODE_DIGITS);
       if (digits > 0) {
          price = NormalizeDouble(price,digits);
          stoploss = NormalizeDouble(stoploss,digits);
          takeprofit = NormalizeDou

Показано первые 50% кода (символов: 14271)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
1 427,10₽ ≈ $17.44