Обучение языку MQL4 под MetaTrader 4📌

От xbms, 13 апреля, 2013 в Уголок Программиста

#601


ну и разумеется эту функцию нужно вызвать из нужного места так: CLOSEORDER();
хотя в данном случае её логичней было бы обозвать уже CloseAllopenOrders; :)

Не закрывает :d Вот это хозяйство мне надо все прикрыть по сигналу индикатора
if(iMA(NULL,0,period,0,MODE_EMA,PRICE_CLOSE,2) {if (CloseRevers) CLOSEORDER();
.......

Безымянный12.jpg

Автор#602




ну и разумеется эту функцию нужно вызвать из нужного места так: CLOSEORDER();
хотя в данном случае её логичней было бы обозвать уже CloseAllopenOrders; :)


Цитата


Не закрывает :d Вот это хозяйство мне надо все прикрыть по сигналу индикатора
if(iMA(NULL,0,period,0,MODE_EMA,PRICE_CLOSE,2) {if (CloseRevers) CLOSEORDER();
.......



ну так скорее всего дело не в функции, а в условии... именно оно не выполняется...
тут легко проверить... оформи эту функцию в виде скрипта и выполни её на демо, сразу будет видно отработала функция или нет.

#603


mzk_3om6u.Приветствую подскажи пожалуйста что это за переменная- NumberOfTry?


Кол-во попыток на закрытие
#604

Дарова всем.

Хотел спросить как написать в коде в условии открытия ордера следующее

"если время открытия последнего ордера любой пары больше чем текущее время на ХХ секунд"

Мне нужно чтобы мультивалютный сов открывал ордера по рынку не чаще чем через заданное время, но сравнивать он должен возможность открытия по текущей паре в зависимости от времени последнего открытия по любой из них.

Заранее благодарствую за ответ v:)

Автор#605

ну соб-сно, не сложно...
Получить время открытия последнего ордера(OrderOpenTime), мы это разбирали на одном из уроков...
Сравнить текущее время (TimeCurrent) с полученным значением, и если оно >=, то открываем новый ордер...

#606

при выполнении этого действия, иногда открывается целая пачка одинаковых sellstop, подскажите пожалуйста, где тут ошибка:

double ff= NormalizeDouble ( OrderOpenPrice(), Digits);
double ss= NormalizeDouble ( FindLastSellStopPrice(), Digits);
if (ff != ss)
{
ticket = OrderSend(Symbol(), OP_SELLSTOP, Lots, ff, Slippage, 0, 0, "", Magic, 0, Red);
}

#607
Ricedeni
По этому куску кода не совсем понятно.
Чтобы получить OrderOpenPrice(), надо, чтобы нужный ордер был выбран командой OrderSelect(). Есть это перед расчётом ff?

Добавлено: 14-12-2013 16:03:17

При отладке, полезно пользоваться журналом.
После:
double ff= NormalizeDouble ( OrderOpenPrice(), Digits);
double ss= NormalizeDouble ( FindLastSellStopPrice(), Digits);
пишем:
Print("ff = ", DoubleToStr(ff, Digits), "; ss = ", DoubleToStr(ss, Digits));

тогда, в журнале, можно посмотреть, что мы сравнивали в if (ff != ss) ;)

Изменено 14 декабря, 2013 пользователем Vorchunozavr

#608

Ну как сказать...

Во-первых, предшествующие ордера могут быть уже и закрыты.
Так что ковыряться надо будет и в истории, нет?

Во-вторых, ботов будет дохрена - сколько торгуемых пар?!
А топикстартеру нужно сравнивать с временем открытия последнего ордера на всех торгуемых парах - о чем копии бота на одной паре вроде ничего не известно.
По крайней мере на каких парах надо учитывать ордера для торгов данным ботом в данной копии бота вряд ли что-то будет известно - или надо налаживать связь между копиями бота.

В-третьих, само логическое условие с ошибкой, нет?

Может оно не так все и сложно, но это явно не одно запрошенное логическое условие, а скорее блок программы.

#609
Старик, один магик у всех копий - решит проблему.
#610

Общий магик решит одну проблему, но колхоз в данных еще ни одного бота до добра не довел.

#611


xbms,Здравствуйте! Подскажите пожалуйста как закрыть большую пачку ордеров?
Набрал вот такой код,но что то он не работает:
void CLOSEORDER(int ord)
{
for (int i=0; i {
if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
{
if (OrderSymbol()==Symbol() && OrderMagicNumber()==Magic)
{
if (OrderType()==OP_BUY && ord==OP_BUY)
OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Bid,Digits),3,CLR_NONE);
if (OrderType()==OP_SELL && ord==OP_SELL)
OrderClose(OrderTicket(),OrderLots(),NormalizeDouble(Ask,Digits),3,CLR_NONE);
}
}
}
}



замени for (int i=0; i0; i--)
часто встречающаяся ошибка.
Если открыто несколько ордеров и ты закрыл нулевой (на первом проходе цикла), то на следующем шаге цикла первый ордер станет нулевым, а твой цикл будет работать со следующим ордером в списке.
Выглядит как закрытие через один.
#612

Спасибо за советы,все варианты оказались рабочими.Косяк был в том ,что по 1 му сигналу поставил открыть встречный ордер и закрыть предыдущие,продублировал этот момент отдельно для CLOSEORDER() и все заработало.
Возник новый вопрос: нужно пересчитать StopLoss для корзины ордеров,ну соответственно тащить с каждым новым уровнем.
void ModifyOrders(int otype)
{
double avgprice = 0,
order_lots = 0;

price = 0;
for(int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype)
{
price += OrderOpenPrice() * OrderLots();
order_lots += OrderLots();
}
}
}


avgprice = NormalizeDouble(price / order_lots, Digits);

if(otype == OP_BUY)
TP = NormalizeDouble(avgprice + TakeProfit * Point, Digits);
SL = NormalizeDouble(avgprice - StopLoss * Point, Digits);
if(otype == OP_SELL)
TP = NormalizeDouble(avgprice - TakeProfit * Point, Digits);
SL = NormalizeDouble(avgprice + StopLoss * Point, Digits);
for(i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
{
if(OrderSymbol() == Symbol() && OrderMagicNumber() == Magic && OrderType() == otype)
{ if (NormalizeDouble(OrderTakeProfit(), Digits) != TP&&NormalizeDouble(OrderStopLoss(),Digits)!=SL)
OrderModify(OrderTicket(), OrderOpenPrice(), 0, SL, 0, 0);
}
}
}

}

#613


тогда, в журнале, можно посмотреть, что мы сравнивали в if (ff != ss) ;)



посмотрел. и захотелось биться головой об стену. теперь я точно не понимаю в чем беда.
Значение переменных - 100% одинаковое. Почему может не срабатывать условие:

if (ff != ss)
{
ticket = OrderSend(Symbol(), OP_SELLSTOP, Lots, ff, Slippage, 0, 0, "", Magic, 0, Red);
}
:(( :(( :((

GBPUSDM5.jpg

Изменено 15 декабря, 2013 пользователем Ricedeni

#614


if(otype == OP_BUY)
TP = NormalizeDouble(avgprice + TakeProfit * Point, Digits);
SL = NormalizeDouble(avgprice - StopLoss * Point, Digits);
if(otype == OP_SELL)
TP = NormalizeDouble(avgprice - TakeProfit * Point, Digits);
SL = NormalizeDouble(avgprice + StopLoss * Point, Digits);



Каждый TP и SL нужно брать в фигурные скобки. У тебя всегда используется SL от sell
#615

Написал функцию проверки.

Пример: Открывать ордер если прошло больше 300 секунд c момента открытия последнего ордера

if(proverka(300)) OrderSend(...);

PS: Ну это конечно на скорую руку, без обработки ошибок,но работать будет



bool proverka(int second)
{
datetime l=0;

// Узнаём время открытия последнего ордера в открытых ордерах
if(OrdersTotal()>0)
{
OrderSelect(OrdersTotal()-1,SELECT_BY_POS,MODE_TRADES);
l=OrderOpenTime();
}

/// Узнаём время открытия последнего ордера в закрытых ордерах
if(OrdersHistoryTotal()>0)
{
OrderSelect(OrdersHistoryTotal()-1,SELECT_BY_POS,MODE_HISTORY);
if(OrderOpenTime()>l) l=OrderOpenTime(); // Сравниваем два времени
}

if(l==0) return(True); // Если у нас вдруг ещё не было ни одной сделки на счёте.

if(TimeCurrent()-l>second) return(True); // Сравниваем прошло ли заданное время
else return(False);

}

Изменено 15 декабря, 2013 пользователем DmitrySL

#616


посмотрел. и захотелось биться головой об стену. теперь я точно не понимаю в чем беда.
Значение переменных - 100% одинаковое. Почему может не срабатывать условие:

if (ff != ss)
{
ticket = OrderSend(Symbol(), OP_SELLSTOP, Lots, ff, Slippage, 0, 0, "", Magic, 0, Red);
}
:(( :(( :((


Странно. Можно попробовать сделать выход по условию - if (ff = ss) return();
Но тогда, нужно согласовывать дальнейший код.

Для отложенных ордеров slippage должен быть равен 0:
ticket = OrderSend(Symbol(), OP_SELLSTOP, Lots, ff, 0, 0, 0, "", Magic, 0, Red);
#617



Значение переменных - 100% одинаковое. Почему может не срабатывать условие:



if (NormalizeDouble(ff, Points) != NormalizeDouble(ss, Points))
#618

Vorchunozavr и mzk_3om6u, спасибо за ваши идеи, буду пробовать :)

#619

Здравствуйте. Напишите, пожалуйста, кому не сложно, как выбрать последний ордер в истории? Нужно чтобы он выбрался не по тикету, а по времени закрытия ордера.
Как выбрать последний ордер по тикету, я знаю:

Цитата

double FindLastOrderLots()
{
double last_lots;
int oldticket;

ticket=0;
for (int i=OrdersTotal()-1; i>=0; i--)
{
if(OrderSelect(i, SELECT_BY_POS,MODE_HISTORY))
{
if(OrderSymbol()==Symbol())
{
oldticket=OrderTicket();
if(oldticket>ticket)
{
last_lots = OrderLots();
ticket = oldticket;
}
}
}
}
return(last_lots);
}


Но меня это не устраивает, т.к. у моего ДЦ история счета ведется не так как у остальных, и я не могу выбрать последний ордер по тикету.

Изменено 16 декабря, 2013 пользователем Hurricane in the head

#620

Такое должно работать. Но, честно, не тестировал.


double FindLastOrderLots()
{
double last_lots = 0.0;
datetime last_order_time = 0;

for (int i=OrdersTotal()-1; i>=0; i--)
{
if(!OrderSelect(i, SELECT_BY_POS,MODE_HISTORY))
continue;
if(OrderSymbol() == Symbol())
continue;
if(OrderCloseTime() continue;

last_lots = OrderLots();
last_order_time = OrderCloseTime();

}

return (last_lots);
}
#621

Почему Советник отказывается открывать ордера на покупку при значении сдвига ЕМА 8 равному - (-2), и в журнале пишет ошибку 138 ? Если поставить значение 0 и больше, то всё норм, а с отрицательным шифтом открывает только продажи



int start()
{
double ma = iMA(Symbol(),0,200,0,MODE_EMA,PRICE_CLOSE,0);
double ma2 = iMA(Symbol(),0,8,-2,MODE_EMA,PRICE_CLOSE,0);

if(OrdersTotal() == 0)
{
if (ma2>ma)
OrderSend(Symbol(),OP_BUY,0.5,Ask,0,0,0,0,0,0,0);
}
return(0);
}

#622

Потому, что прочитайте документацию по MQL4, и отсчёт баров идёт от текущего, который равен 0, к предыдущим 0-1-2-3-4...

#623


Почему Советник отказывается открывать ордера на покупку при значении сдвига ЕМА 8 равному - (-2), и в журнале пишет ошибку 138 ? Если поставить значение 0 и больше, то всё норм, а с отрицательным шифтом открывает только продажи



int start()
{
double ma = iMA(Symbol(),0,200,0,MODE_EMA,PRICE_CLOSE,0);
double ma2 = iMA(Symbol(),0,8,-2,MODE_EMA,PRICE_CLOSE,0);

if(OrdersTotal() == 0)
{
if (ma2>ma)
OrderSend(Symbol(),OP_BUY,0.5,Ask,0,0,0,0,0,0,0);
}
return(0);
}




Если запрашиваемая цена открытия сильно устарела, то независимо от значения параметра slippage будет сгенерирована ошибка 138 (ERR_REQUOTE).
А устарела она почему? Потому что, при смещении -2 скользящей средней, последняя цена будет на 2 баре, а не на нулевом. Если у вас нету котировок из будующего, то смысла такой ма нету. Очередная попытка обмануть время)
#624
Хорошо, Спасибо. Понял, но не совсем

Вот ещё что не могу понять, так это циклы. Вот смотрите:

Вот вариант подсчёта количества ордеров который пишет Сергей в своих уроках:

int CountTrades()
{
int count = 0;
for (int i=OrdersTotal()-1;i>=0;i--)
{
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
count++;
Alert(count);
}
return(count);
}

Здесь я ещё добавил Алерт что бы посмотреть как он считает. И вот этот вариант записи:

int CountTrades2()
{
int count;
for (int i=0; i{
OrderSelect(i,SELECT_BY_POS,MODE_TRADES);
if (OrderSymbol() == Symbol() && OrderMagicNumber() == Magic)
count++;
Alert(count);
}
return(count);
}

В журнале Алерт выдаёт всё то же самое что и в первом варианте в такой же последовательности.
Так в каком случае использовать первый вариант и в каком второй?
#625


Так в каком случае использовать первый вариант и в каком второй?



Логичнее было выводить count, i, ticket - тогда бы была видна разница.
Второй цикл считает от начала списка ордеров, первый - с конца.
Используют, кому как нравится. Но, если нужны последние ордера, лучше начать с конца.

Для публикации сообщений создайте учётную запись или авторизуйтесь

Перейти к списку тем
Форум · 2.0.20260627.0025