Исходный код · ID 3867
OrderReliable ordersendreliable.mqh
Вы автор или правообладатель? Сообщите нам, если считаете, что материал размещён без разрешения.
Пожаловаться или запросить удаление
×
Сообщить о материале
Обращение по товару «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)
Открыть по тарифу Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.