return; после удаления ордера, вызовет выход из функции в котором этот оператор используется, в данном случае из OnStart(). Получается что если наткнётся на отложенный ордер, скрипт его удалит и прекратит работу. А там могут быть ещё не закрытые и не удалённые ордера.Спасибо. Поправил. Если не сложно - проверьте.
C++:#property strict int slipp; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() // Следующая задача. // Напишите скрипт, который закрывает все открытые ордера на счете. // (перед запуском скрипта, желательно открыть несколько ордеров Бай и Селл) { bool resalt; int OT, Ticket, i; for(i = OrdersTotal()-1; i >= 0; i--) // Переменной i присваиваем значение OrdersTotal()-1. После этого проверено условие что i>=0, { // если это так, то выполняется один раз все, что написано внутри тела цикла if(OrderSelect(i, SELECT_BY_POS)) { OT = OrderType(); //Переменной OT присваиваем значение OrderType() Ticket = OrderTicket(); //Переменной Ticket присваиваем значение OrderTicket() if(OT == OP_BUY) // Если тип операций для функции OrderType() выбран OP_BUY (покупка), то { RefreshRates(); // обновляем цену resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается } if(OT == OP_SELL) // Если тип операций для функции OrderType() выбран OP_SELL (продажа), то { RefreshRates(); // обновляем цену resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE); // выбранный тип закрывается } if(OT == OP_BUYLIMIT) // Если тип операций для функции OrderType() выбран OP_BUYLIMIT, то { // выбранный тип закрывается resalt = OrderDelete(Ticket,CLR_NONE); return; } if(OT == OP_SELLLIMIT) // Если тип операций для функции OrderType() выбран OP_SELLLIMIT, то { // выбранный тип удаляется resalt = OrderDelete(Ticket,CLR_NONE); return; } if(OT == OP_BUYSTOP) // Если тип операций для функции OrderType() выбран OP_BUYSTOP, то { // выбранный тип удаляется resalt = OrderDelete(Ticket,CLR_NONE); return; } } } }
if(OT > OP_SELL) // Если ордер отложенный, то
{
resalt = OrderDelete(Ticket,CLR_NONE);//Удалить
}
При инициализации должны инициализироваться переменные объявленные на глобальном уровне.Правильно ли то что при смене настроек в индикаторе сбиваются глобальные переменные?
Нет. Такого не должно быть. Разве что косяк языка. Но я много писал таких и никогда не сбивались маджики.Бывали ли у кого то случаи в мультивалютном советнике что Magic слетал?
(ордер открывался с 0 magic)
В советниках не иницилиаризуются.При инициализации должны инициализироваться переменные объявленные на глобальном уровне.
Но я, на всякий случай, дополнительно инициализирую их, например в OnInit(). Так надёжнее.
У меня уже 2 раза было. На разных советниках MSY. Меджик прямо из настроек в OrderSend передаётся.Нет. Такого не должно быть. Разве что косяк языка. Но я много писал таких и никогда не сбивались маджики.
А недавно видел в каком то советникеУ меня уже 2 раза было. На разных советниках MSY. Меджик прямо из настроек в OrderSend передаётся.
Смотрю что то советник не трейлит 3 из 7 ордеров. Навожу на ордер. Пишет "Placed by expert id0"
extern const int magic = 567;
Поправилreturn; после удаления ордера, вызовет выход из функции в котором этот оператор используется, в данном случае из OnStart(). Получается что если наткнётся на отложенный ордер, скрипт его удалит и прекратит работу. А там могут быть ещё не закрытые и не удалённые ордера.
В данном случае аргументы всех OrderDelete() одинаковые. Можно написать один раз для всех отложенных ордеров.
Ну и наконец, нет никакой обработки ошибок, даже в журнал не пишет.Код:if(OT > OP_SELL) // Если ордер отложенный, то { resalt = OrderDelete(Ticket,CLR_NONE);//Удалить }
#property strict
int slipp;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
// Следующая задача.
// Напишите скрипт, который закрывает все открытые ордера на счете.
// (перед запуском скрипта, желательно открыть несколько ордеров Бай и Селл)
{
bool resalt;
int OT, Ticket, i;
for(i = OrdersTotal()-1; i >= 0; i--) // Переменной i присваиваем значение OrdersTotal()-1. После этого проверено условие что i>=0,
{ // если это так, то выполняется один раз все, что написано внутри тела цикла
if(OrderSelect(i, SELECT_BY_POS))
{
OT = OrderType(); //Переменной OT присваиваем значение OrderType()
Ticket = OrderTicket(); //Переменной Ticket присваиваем значение OrderTicket()
if(OT == OP_BUY) // Если тип операций для функции OrderType() выбран OP_BUY (покупка), то
{
RefreshRates(); // обновляем цену
resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается
if(!resalt) i--; // Если по к.л. ошибке ордер не закрылся, просто повторяем операция закрытия еще раз
else Alert("Closed BUY, OrderTicket ",OrderTicket(),", Lots ",OrderLots(),", Close price ",MarketInfo(OrderSymbol(),MODE_BID));
}
if(OT == OP_SELL) // Если тип операций для функции OrderType() выбран OP_SELL (продажа), то
{
RefreshRates(); // обновляем цену
resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается
if(!resalt) i--; // Если по к.л. ошибке ордер не закрылся, просто повторяем операция закрытия еще раз
else Alert("Closed Sell, OrderTicket ",OrderTicket(),", Lots ",OrderLots(),", Close price ",MarketInfo(OrderSymbol(),MODE_ASK));
}
// return; после удаления ордера, вызовет выход из функции в котором этот оператор используется,
// в данном случае из OnStart(). Получается что если наткнётся на отложенный ордер, скрипт его удалит и прекратит работу.
// А там могут быть ещё не закрытые и не удалённые ордера.
// В данном случае аргументы всех OrderDelete() одинаковые. Можно написать один раз для всех отложенных ордеров.
/* if(OT == OP_BUYLIMIT) // Если тип операций для функции OrderType() выбран OP_BUYLIMIT, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return;
}
if(OT == OP_SELLLIMIT) // Если тип операций для функции OrderType() выбран OP_SELLLIMIT, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return; }
if(OT == OP_BUYSTOP) // Если тип операций для функции OrderType() выбран OP_BUYSTOP, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return;
}
if(OT == OP_SELLSTOP) // Если тип операций для функции OrderType() выбран OP_SELLSTOP, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return;
}*/
if(OT > OP_SELL) // Если ордер отложенный, то
{
resalt = OrderDelete(Ticket,CLR_NONE);//Удалить
if(!resalt) i--; // Если по какой либо ошибке ордер не закрылся, просто повторяем операция закрытия еще раз
else Alert("Closed Buy/Sell: Limit or Stop orders, OrderTicket ",OrderTicket(),", Lots ",OrderLots());
}
if(Ticket>0)
{
Print("OrderClose завершилась с ошибкой #",GetLastError());
}
else
Print("Функция OrderClose успешно выполнена");
}
}
}
Цикл выполняется от последнего ордера к первому for(i = OrdersTotal()-1; i >= 0; i--). По этому if(!resalt) i--; приведёт не к повторению, а к пропуску следующего ордера.Поправил
C++:#property strict int slipp; //+------------------------------------------------------------------+ //| Script program start function | //+------------------------------------------------------------------+ void OnStart() // Следующая задача. // Напишите скрипт, который закрывает все открытые ордера на счете. // (перед запуском скрипта, желательно открыть несколько ордеров Бай и Селл) { bool resalt; int OT, Ticket, i; for(i = OrdersTotal()-1; i >= 0; i--) // Переменной i присваиваем значение OrdersTotal()-1. После этого проверено условие что i>=0, { // если это так, то выполняется один раз все, что написано внутри тела цикла if(OrderSelect(i, SELECT_BY_POS)) { OT = OrderType(); //Переменной OT присваиваем значение OrderType() Ticket = OrderTicket(); //Переменной Ticket присваиваем значение OrderTicket() if(OT == OP_BUY) // Если тип операций для функции OrderType() выбран OP_BUY (покупка), то { RefreshRates(); // обновляем цену resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается if(!resalt) i--; // Если по к.л. ошибке ордер не закрылся, просто повторяем операция закрытия еще раз else Alert("Closed BUY, OrderTicket ",OrderTicket(),", Lots ",OrderLots(),", Close price ",MarketInfo(OrderSymbol(),MODE_BID)); } if(OT == OP_SELL) // Если тип операций для функции OrderType() выбран OP_SELL (продажа), то { RefreshRates(); // обновляем цену resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается if(!resalt) i--; // Если по к.л. ошибке ордер не закрылся, просто повторяем операция закрытия еще раз else Alert("Closed Sell, OrderTicket ",OrderTicket(),", Lots ",OrderLots(),", Close price ",MarketInfo(OrderSymbol(),MODE_ASK)); } // return; после удаления ордера, вызовет выход из функции в котором этот оператор используется, // в данном случае из OnStart(). Получается что если наткнётся на отложенный ордер, скрипт его удалит и прекратит работу. // А там могут быть ещё не закрытые и не удалённые ордера. // В данном случае аргументы всех OrderDelete() одинаковые. Можно написать один раз для всех отложенных ордеров. /* if(OT == OP_BUYLIMIT) // Если тип операций для функции OrderType() выбран OP_BUYLIMIT, то { // выбранный тип удаляется resalt = OrderDelete(Ticket,CLR_NONE); return; } if(OT == OP_SELLLIMIT) // Если тип операций для функции OrderType() выбран OP_SELLLIMIT, то { // выбранный тип удаляется resalt = OrderDelete(Ticket,CLR_NONE); return; } if(OT == OP_BUYSTOP) // Если тип операций для функции OrderType() выбран OP_BUYSTOP, то { // выбранный тип удаляется resalt = OrderDelete(Ticket,CLR_NONE); return; } if(OT == OP_SELLSTOP) // Если тип операций для функции OrderType() выбран OP_SELLSTOP, то { // выбранный тип удаляется resalt = OrderDelete(Ticket,CLR_NONE); return; }*/ if(OT > OP_SELL) // Если ордер отложенный, то { resalt = OrderDelete(Ticket,CLR_NONE);//Удалить if(!resalt) i--; // Если по какой либо ошибке ордер не закрылся, просто повторяем операция закрытия еще раз else Alert("Closed Buy/Sell: Limit or Stop orders, OrderTicket ",OrderTicket(),", Lots ",OrderLots()); } if(Ticket>0) { Print("OrderClose завершилась с ошибкой #",GetLastError()); } else Print("Функция OrderClose успешно выполнена"); } } }
if(true)
{
int a=0;
a++;
Print(a);
}
if(true)
{
int a=0;
a+=3;
Print(a);
}
int a=0;
if(true)
{
a++;
Print(a);
}
if(true)
{
a+=3;
Print(a);
}
int a=0;
if(true)
{
a++;
Print(a);
}
if(true)
{
int a=0;
a+=3;
Print(a);
}
int a;
int OnInit()
{
//---
a=0;
//---
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason)
{
//---
a=0;
}
void OnTick()
{
//---
a++;
Comment(a);
}
Вот по этому я всегда инициализирую глобальные переменные.В советниках не иницилиаризуются.
И это правильно.
В старом языке внешние переменные обозначались extern. В ходе выполнения программы можно было менять значение этой переменной. Если где то в коде есть magic=0; то да, значение могло смениться на 0. Тогда это косяк программиста.А недавно видел в каком то советнике
думаю поможет ли.Код:extern const int magic = 567;
Возвращает true или false в зависимости от успешности выполнения функции. В случае успеха значение свойства помещается в приемную переменную, передаваемую по ссылке последним параметром.
bool SymbolInfoInteger(
string name, // символ
ENUM_SYMBOL_INFO_INTEGER prop_id, // идентификатор свойства
long& long_var // сюда примем значение свойства
);
long Spread;
if(SymbolInfoInteger(Symbol(),SYMBOL_SPREAD,Spread))Print("Текущий спред ",Spread);
else Print("Ошибка получения спреда ",_LastError);
Очень хорошо.Я попробовал. Проверьте пожалуйста. Но Comment не выдает...
О, Вы уже используете пользовательские функцию OrdersCount(). Здесь ещё не рассматривали пользовательские функции. Самостоятельно написали или содрали у кого? Для начинающего она написана правильно, а вот использована нет. Что бы правильно использовать функцию, не обязательно знать как она устроена. Важно знать что она делает, что возвращает, какие аргументы. Первый аргумент у неё тип ордера. Вы указали 0, а это OP_BUY. Соответственно, она только Buy и считает.Я попробовал. Проверьте пожалуйста. Но Comment не выдает...
C++:#property strict // Следующая задача. // Нужно написать советник, который подсчитывает и выводит (через Comment) // количество открытых ордеров соответствующих инструменту своего графика. // Пример: советник запущен на графике EURUSD, подсчитываем только ордера EURUSD, // а другие игнорируем. Если открытых ордеров нет, то советник открывает один ордер. // Направление открытия (buy/sell) советник определяет следующим образом: // если Close[1] > Close[3]+N*Point, то открывается ордер Buy, а если Close[1] < Close[3]-N*Point, // то открывается ордер Sell. Значение переменной N (в пунктах), а также MagicNumber, StopLoss и TakeProfit // нужно вывести во входные параметры (input). // Советник нужно протестировать в тестере стратегий. //+------------------------------------------------------------------+ input double Lots = 0.01; // Lots: input int Delta_N = 25; // Delta: input int TakeProfit = 300; // Take Profit: input int StopLoss = 100; // Stop Loss: input int Magic = 12345; // Magic Number: input int Slippage = 3; // Slippage: //+------------------------------------------------------------------+ int slipp, del; double point, lot; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //----Определение пяти значного брокера point = _Point; if(_Digits == 3 || _Digits == 5) { point = 10.0 * point; slipp = Slippage * 10; } //--- lot = Lots; del = Delta_N; //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //--- получим минимальное значение Stop level double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL); Print("Minimum Stop Level=",minstoplevel," points"); //--- вычисленные значения цен SL и TP должны быть нормализованы double stoploss=NormalizeDouble(Bid-minstoplevel*Point,Digits); double takeprofit=NormalizeDouble(Bid+minstoplevel*Point,Digits); double minlot = MarketInfo(Symbol(),MODE_MINLOT); // узнаем каков минимальный размер лота double maxlot = MarketInfo(Symbol(),MODE_MAXLOT); // узнаем каков максимальный размер лота //--- if (OrdersCount(0,Magic)>=0) Comment (OrdersCount(0,Magic)); else if (OrdersCount(0,Magic)<1) { if (lot >= minlot && lot <= maxlot ) { //--- размещаем рыночный ордер на покупку 1 лота if (OrdersTotal()<1 && Close[1] > Close[3]+Delta_N*Point) { int ticket=OrderSend(Symbol(),OP_BUY,lot,Ask,Slippage,StopLoss,TakeProfit,"My order BUY",Magic,0,clrGreen); if(ticket<0) { Print("OrderSend завершилась с ошибкой #",GetLastError()); } else Print("Функция OrderSend успешно выполнена"); } //--- размещаем рыночный ордер на продажу 1 лота if (OrdersTotal()<1 && Close[1] < Close[3]-Delta_N*Point) { int ticket=OrderSend(Symbol(),OP_SELL,lot,Bid,Slippage,StopLoss,TakeProfit,"My order BUY",Magic,0,clrGreen); if(ticket<0) { Print("OrderSend завершилась с ошибкой #",GetLastError()); } else Print("Функция OrderSend успешно выполнена"); } else {return;} } } } //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| Подсчет ордеров по символу | //+------------------------------------------------------------------+ int OrdersCount(int type, int MagicNum) { int orders = 0; for(int i = OrdersTotal()-1; i >= 0; i--) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == _Symbol && OrderMagicNumber() == MagicNum) { if(OrderType() == type)orders++; } } } return orders; }
Спасибо. Функция действительно не моя. Написана нашим форумчанином strannik-ps. Мной не содрана. Пользуюсь функциями написанными Пашей с его же ведома и разрешения.О, Вы уже используете пользовательские функцию OrdersCount(). Здесь ещё не рассматривали пользовательские функции. Самостоятельно написали или содрали у кого? Для начинающего она написана правильно, а вот использована нет. Что бы правильно использовать функцию, не обязательно знать как она устроена. Важно знать что она делает, что возвращает, какие аргументы. Первый аргумент у неё тип ордера. Вы указали 0, а это OP_BUY. Соответственно, она только Buy и считает.
Нужно понимать что функция это программа, которая выполняется компьютером. На это уходят ресурсы компьютера. А переменная это кусочек памяти, для обращения к ней ресурсов практически не надо.
if (OrdersCount(0,Magic)>=0) Comment (OrdersCount(0,Magic));
else
if (OrdersCount(0,Magic)<1)
Вы тут трижды вызвали функцию. А можно было один раз вызвать, результат загнать в переменную, потом обращаться к ней сколько угодно раз. К экономии ресурсов надо привыкать с самого начала.
int OrdersBuy=OrdersCount(OP_BUY,Magic);//Посчитали Buy ордера
int OrdersSell=OrdersCount(OP_SELL,Magic);//Посчитали Sell ордера
Comment("Buy Orders ",OrdersBuy,"\nBuy Orders ",OrdersSell);
В условиях открытия ордеров использовано OrdersTotal()<1. А OrdersTotal() возвращает количество ордеров независимо от типа, символа и маджика. А между тем уже есть посчитанные ордера с учётом символа и маджика функцией OrdersCount(). Стоит использовать эти данные, а не OrdersTotal().
Если кто то выкладывает в общедоступном месте код в открытом виде, значит он не против что этот код будут изучать, брать от туда функции... Иначе он об этом напишет (это мало помогает) или выложит только компилированную программу.Спасибо. Функция действительно не моя. Написана нашим форумчанином strannik-ps. Мной не содрана. Пользуюсь функциями написанными Пашей с его же ведома и разрешения.
Особое спасибо за понятные разъяснения!
Следующая задача.
Напишите скрипт, который закрывает все открытые ордера на счете.
(перед запуском скрипта, желательно открыть несколько ордеров Бай и Селл)
#property strict
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
//Следующая задача.
//Напишите скрипт, который закрывает все открытые ордера на счете.
//(перед запуском скрипта, желательно открыть несколько ордеров Бай и Селл)
{
int i,type;
bool result;
for(i=OrdersTotal()-1; i>=0; i--) //
{
if(OrderSelect (i,SELECT_BY_POS,MODE_TRADES)) //выбираем ордер для работы
{
type = OrderType(); // записываем тип ордера
result = false; //
RefreshRates(); // обновляем цену
switch(type) // выполняем тот case, который соответствует типу ордера(type)
{
//закрываем ордера на покупку
case OP_BUY : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_BID), MODE_DIGITS, Red );
break;
//закрываем ордера на подажу
case OP_SELL : result = OrderClose( OrderTicket(), OrderLots(), MarketInfo(OrderSymbol(), MODE_ASK), MODE_DIGITS, Red );
break;
//удаляем отложенные ордера
case OP_BUYLIMIT :
case OP_BUYSTOP :
case OP_SELLLIMIT :
case OP_SELLSTOP : result = OrderDelete( OrderTicket() );
}
// если в OrderClose или OrderDlete произошла ошибка и закрытие или удаление ордера не произошло...
if(result == false)
{
// ... то выдаем алерт...
Alert("Ордер " , OrderTicket() , " не закрыт. Ошибка: " , GetLastError() );
// ... и делаем задержку на 3000мс = 3 сек.
Sleep(3000);
}
}
}
return;
}
//+------------------------------------------------------------------+
result = false; |
Sleep(3000); |
#property strict
int slipp;
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
// Следующая задача.
// Напишите скрипт, который закрывает все открытые ордера на счете.
// (перед запуском скрипта, желательно открыть несколько ордеров Бай и Селл)
{
bool resalt;
int OT, Ticket, i;
for(i = OrdersTotal()-1; i >= 0; i--) // Переменной i присваиваем значение OrdersTotal()-1. После этого проверено условие что i>=0,
{ // если это так, то выполняется один раз все, что написано внутри тела цикла
if(OrderSelect(i, SELECT_BY_POS))
{
OT = OrderType(); //Переменной OT присваиваем значение OrderType()
Ticket = OrderTicket(); //Переменной Ticket присваиваем значение OrderTicket()
if(OT == OP_BUY) // Если тип операций для функции OrderType() выбран OP_BUY (покупка), то
{
RefreshRates(); // обновляем цену
resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_BID),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается
if(!resalt) i--; // Если по к.л. ошибке ордер не закрылся, просто повторяем операция закрытия еще раз
else Alert("Closed BUY, OrderTicket ",OrderTicket(),", Lots ",OrderLots(),", Close price ",MarketInfo(OrderSymbol(),MODE_BID));
}
if(OT == OP_SELL) // Если тип операций для функции OrderType() выбран OP_SELL (продажа), то
{
RefreshRates(); // обновляем цену
resalt = OrderClose(Ticket,OrderLots(),NormalizeDouble(MarketInfo(OrderSymbol(),MODE_ASK),(int)MarketInfo(OrderSymbol(),MODE_DIGITS)),slipp,clrNONE);// выбранный тип закрывается
if(!resalt) i--; // Если по к.л. ошибке ордер не закрылся, просто повторяем операция закрытия еще раз
else Alert("Closed Sell, OrderTicket ",OrderTicket(),", Lots ",OrderLots(),", Close price ",MarketInfo(OrderSymbol(),MODE_ASK));
}
// return; после удаления ордера, вызовет выход из функции в котором этот оператор используется,
// в данном случае из OnStart(). Получается что если наткнётся на отложенный ордер, скрипт его удалит и прекратит работу.
// А там могут быть ещё не закрытые и не удалённые ордера.
// В данном случае аргументы всех OrderDelete() одинаковые. Можно написать один раз для всех отложенных ордеров.
/* if(OT == OP_BUYLIMIT) // Если тип операций для функции OrderType() выбран OP_BUYLIMIT, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return;
}
if(OT == OP_SELLLIMIT) // Если тип операций для функции OrderType() выбран OP_SELLLIMIT, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return; }
if(OT == OP_BUYSTOP) // Если тип операций для функции OrderType() выбран OP_BUYSTOP, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return;
}
if(OT == OP_SELLSTOP) // Если тип операций для функции OrderType() выбран OP_SELLSTOP, то
{ // выбранный тип удаляется
resalt = OrderDelete(Ticket,CLR_NONE); return;
}*/
if(OT > OP_SELL) // Если ордер отложенный, то
{
resalt = OrderDelete(Ticket,CLR_NONE);//Удалить
if(!resalt) i--; // Если по какой либо ошибке ордер не закрылся, просто повторяем операция закрытия еще раз
else Alert("Closed Buy/Sell: Limit or Stop orders, OrderTicket ",OrderTicket(),", Lots ",OrderLots());
}
if(Ticket>0)
{
Print("OrderClose завершилась с ошибкой #",GetLastError());
}
else
Print("Функция OrderClose успешно выполнена");
}
}
}
Ticket = OrderTicket(); |
(itn)MarketInfo(OrderSymbol(),MODE_DIGITS)) |
if(!resalt) i++; |
Скажите, почему не открывает ордера в тестере сделки? Натолкните в направлении поиска ошибки пожалуйста. А то мозг зациклился..Следующая задача.
Нужно написать советник, который подсчитывает и выводит (через Comment) количество открытых ордеров соответствующих инструменту своего графика. Пример: советник запущен на графике EURUSD, подсчитываем только ордера EURUSD, а другие игнорируем. Если открытых ордеров нет, то советник открывает один ордер. Направление открытия (buy/sell) советник определяет следующим образом: если Close[1] > Close[3]+N*Point, то открывается ордер Buy, а если Close[1] < Close[3]-N*Point, то открывается ордер Sell. Значение переменной N (в пунктах), а также MagicNumber, StopLoss и TakeProfit нужно вывести во входные параметры (input).
Советник нужно протестировать в тестере стратегий.
Для создания советника можно использовать следующий шаблон.
C++:#property strict //input int MagicNumber = 555; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { //Comment(MagicNumber); } //+------------------------------------------------------------------+
#property strict
// Следующая задача.
// Нужно написать советник, который подсчитывает и выводит (через Comment)
// количество открытых ордеров соответствующих инструменту своего графика.
// Пример: советник запущен на графике EURUSD, подсчитываем только ордера EURUSD,
// а другие игнорируем. Если открытых ордеров нет, то советник открывает один ордер.
// Направление открытия (buy/sell) советник определяет следующим образом:
// если Close[1] > Close[3]+N*Point, то открывается ордер Buy, а если Close[1] < Close[3]-N*Point,
// то открывается ордер Sell. Значение переменной N (в пунктах), а также MagicNumber, StopLoss и TakeProfit
// нужно вывести во входные параметры (input).
// Советник нужно протестировать в тестере стратегий.
//+------------------------------------------------------------------+
input double Lots = 0.01; // Lots:
input int Delta_N = 25; // Delta:
input double TakeProfit = 300; // Take Profit:
input double StopLoss = 100; // Stop Loss:
input int Magic = 12345; // Magic Number:
input int Slippage = 3; // Slippage:
//+------------------------------------------------------------------+
int slipp, del, ticket;
double point, lot, SL, TP;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//---
//----Определение пяти значного брокера
point = _Point;
if(_Digits == 3 || _Digits == 5)
{
point = 10.0 * point;
slipp = Slippage * 10;
}
//---
lot = Lots;
del = Delta_N;
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
int OT=0;
//--- получим минимальное значение Stop level
double minstoplevel=MarketInfo(Symbol(),MODE_STOPLEVEL);
Print("Minimum Stop Level=",minstoplevel," points");
//--- вычисленные значения цен SL и TP должны быть нормализованы
// double stoploss=NormalizeDouble(Bid-minstoplevel*Point,Digits);
// if (StopLoss<stoploss) StopLoss=stoploss;
// double takeprofit=NormalizeDouble(Bid+minstoplevel*Point,Digits);
// if (TakeProfit<takeprofit) TakeProfit=takeprofit;
double minlot = MarketInfo(Symbol(),MODE_MINLOT); // узнаем каков минимальный размер лота
Print("Minimal lot=",minlot," lots");
double maxlot = MarketInfo(Symbol(),MODE_MAXLOT); // узнаем каков максимальный размер лота
Print("Maximal lot=",maxlot," lots");
//---
// функциz OrdersCount()написана правильно, а вот использована нет.
// Что бы правильно использовать функцию, не обязательно знать как она устроена. Важно знать что она делает, что возвращает, какие аргументы.
// Первый аргумент у неё тип ордера. Вы указали 0, а это OP_BUY. Соответственно, она только Buy и считает.
// Нужно понимать что функция это программа, которая выполняется компьютером. На это уходят ресурсы компьютера.
// А переменная это кусочек памяти, для обращения к ней ресурсов практически не надо.
/*if (OrdersCount(0,Magic)>=0) Comment (OrdersCount(0,Magic));
else
if (OrdersCount(0,Magic)<1)*/
// Вы тут трижды вызвали функцию. А можно было один раз вызвать, результат загнать в переменную,
// потом обращаться к ней сколько угодно раз. К экономии ресурсов надо привыкать с самого начала.
int OrdersBuy=OrdersCount(OP_BUY,Magic); //Посчитали Buy ордера
int OrdersSell=OrdersCount(OP_SELL,Magic);//Посчитали Sell ордера
OT = OrdersBuy+OrdersSell; // Сумировали ордера BUY и SELL
Comment("Buy Orders ",OrdersBuy,"\nSell Orders ",OrdersSell);
// В условиях открытия ордеров использовано OrdersTotal()<1. А OrdersTotal() возвращает количество ордеров
// независимо от типа, символа и маджика. А между тем уже есть посчитанные ордера с учётом символа и маджика функцией OrdersCount().
// Стоит использовать эти данные, а не OrdersTotal().
for(int i=0;i<OT;i++)
{
{
if (lot >= minlot && lot <= maxlot )
{
//--- размещаем рыночный ордер на покупку 1 лота
// if (OrdersTotal()<1 && Close[1] > Close[3]+Delta_N*Point)
if (OT==0 && Close[i+1] > Close[i+3]+Delta_N*Point)
{
ticket=OrderSend(Symbol(),OP_BUY,lot,Ask,Slippage,0,0,"My order BUY",Magic,0,clrGreen);
if(ticket<0)
{
SL = NormalizeDouble(Ask - StopLoss*Point,Digits);
TP = NormalizeDouble(Ask + TakeProfit*Point,Digits);
if (OrderSelect(ticket,SELECT_BY_TICKET))
if (OrderModify(ticket,OrderOpenPrice(),SL,TP,0,clrRed) == true)
Print ("Ошибка модификации ордера на продажу");
} else Print("Ошибка открытия ордера на продажу");
}
//--- размещаем рыночный ордер на продажу 1 лота
if (OT==0 && Close[i+1] < Close[i+3]-Delta_N*Point)
{
ticket=OrderSend(Symbol(),OP_SELL,lot,Bid,Slippage,0,0,"My order BUY",Magic,0,clrGreen);
if(ticket<0)
{
SL = NormalizeDouble(Bid + StopLoss*Point,Digits);
TP = NormalizeDouble(Bid - TakeProfit*Point,Digits);
if (OrderSelect(ticket,SELECT_BY_TICKET))
if (OrderModify(ticket,OrderOpenPrice(),SL,TP,0,clrRed) == true)
Print ("Ошибка модификации ордера на продажу");
} else Print("Ошибка открытия ордера на продажу");
}
//else {return;}
}
}
}
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Подсчет ордеров по символу |
//+------------------------------------------------------------------+
int OrdersCount(int type, int MagicNum)
{
int orders = 0;
for(int i = OrdersTotal()-1; i >= 0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == _Symbol && OrderMagicNumber() == MagicNum)
{
if(OrderType() == type)orders++;
}
}
}
return orders;
}