В качестве первого опыта решил реализовать следующий алгоритм: можно ожидать, что после сближения линий Боллинджера в узкий коридор через какое-то время будет резкое движение рынка вверх или вниз. В советнике анализирую состояние линий Боллинджера и при их близком сближении (Delta пунктов) ставим отложенный ордер на продажу в нижнем направлении (на StepOpen пунктов ниже нижней линии) в надежде что рынок резко пойдет именно в эту сторону. Если рынок пошел в другую сторону, то просто удаляем этот ордер.
externdouble Delta=800.0; // Ширина канала, которую мы считаем достаточно узкой чтобы ожидать скоро серьезного движения в одну из сторонexterndouble StepOpen=150.0; // Отступ от линии Боллинджера для открытия отложенного ордераexterndouble TP=350.0; // Take Profitexterndouble SL=400.0; // Stop Lossint start()
{
double T1=iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0); // верхняя линия Боллинджераdouble T2=iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0); // нижняя линия Боллинджераif ((Ask>T1+StepOpen*Point)&&OrderSelect(0,SELECT_BY_POS,MODE_TRADES)==true) OrderDelete(0); // если рынок пошел вверх – то удаляем отложенный ордерif (OrderSelect(0,SELECT_BY_POS,MODE_TRADES)==true) return(0); // если есть ранее открытый ордер – прекращаем выполнение текущей итерации советникаif (T1-T2<Delta*Point) { // если линии Боллинджера сблизились ближе чем на Delta пунктов начинаем операцию открытия ордераdouble PriceOpen=NormalizeDouble(T2-StepOpen*Point,5); // вычисляем цену открытияdouble StopLoss=NormalizeDouble(T2-StepOpen*Point+SL*Point,5); // вычисляем StopLossdouble TakeProfit=NormalizeDouble(T2-StepOpen*Point-TP*Point,5); // вычисляем TakeProfitOrderSend(Symbol(),OP_SELL,0.1,PriceOpen,5,StopLoss,TakeProfit,0,0,0,Green); // открываем ордер на продажу
}
return(0);
}
Алгоритм работает нестабильно, иногда открывает по два ордера через короткий промежуток времени, постоянно выдает ошибки OrderSend Error 130 и OrderSend Error 138, а удаление открытых ордеров в случае движения рынка в другую сторону вообще не срабатывает.
static datetime PrevTime=0; // Время открытия предпоследнего бара
//Дополнительные проверки
if (PrevTime==0) PrevTime=Time[0]; // При первом запуске текущий бар пропускаем
if (Time[0]<=PrevTime) return(0); // Контроль времени открытия нового бара
//--Ваш основной код
PrevTime=Time[0]; // Запоминаем время открытия нулевого бара
return(0);
}
Если у Вас сетап по открытию бара, вот шаблон, он работает.
Большая просьба Вы не могли бы вписать сами эту функцию в советник? На картинке видно открыл 3 ордера на одном баре. А надо только один У меня не получается исправить код.СПАСИБО.
//+------------------------------------------------------------------+int start()
//+------------------------------------------------------------------+
{
//--- Разрешение на открытие позиций - каждую свечуif(candle_time != Time[0])
{
candle_time = Time[0];
new_bar_buy = true;
new_bar_sell = true;
}
if (Bars < bars_count){Print("Мало данных для работы"); return(0);}
//--- Получение значений индикатора iMA
ma10 = iMA ( Symbol(), Period(), MA1_period, MA1_shift, MA1_method, MA1_price, bars_shift);
ma20 = iMA ( Symbol(), Period(), MA2_period, MA2_shift, MA2_method, MA2_price, bars_shift);
ma11 = iMA ( Symbol(), Period(), MA1_period, MA1_shift, MA1_method, MA1_price, bars_shift+1);
ma21 = iMA ( Symbol(), Period(), MA2_period, MA2_shift, MA2_method, MA2_price, bars_shift+1);
if (Revers)
{
if(rsi>50 && rsi<70)//--- включена инверсия
{
//--- Условие для продажиif(ma11 < ma21 && ma10 > ma20 && ma30 > ma10 && new_bar_sell)
{
sell_open=true;
new_bar_sell = false;
}
}
if(rsi>30 && rsi<50)//--- включена инверсия
{
//--- Условие для продажиif(ma11 > ma21 && ma10 < ma20 && ma30 < ma10 && new_bar_buy)
{
buy_open=true;
new_bar_buy = false;
}
}
}
//--- выставление рыночных ордеровif(IsTradeAllowed())
{
Trade_BUY();
Trade_SELL();
}
return(0);
//+------------------------------------------------------------------+void Trade_BUY()
//+------------------------------------------------------------------+
{
for ( int i = 0; i < OrdersTotal(); i++ )
{
if ( OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) )
{
if ((OrderSymbol() != Symbol()) || (OrderMagicNumber() != Magic)) continue; //не наш ордерif ( OrderType() == OP_BUY) // если ордер OP_BUY
{
min_level = MarketInfo( Symbol(), MODE_STOPLEVEL );
//--- проверка на работу трейлинг стопаif (trailing_stop !=0.0 && Ask > NormalizeDouble(OrderStopLoss() + (stop_loss_buy + MathMax(min_level, trailing_stop)) * Point, Digits) && OrderProfit() > 0)
{
if ( OrderModify ( OrderTicket(), OrderOpenPrice(),
NormalizeDouble (OrderStopLoss() + MathMax(min_level, trailing_stop) * Point, Digits),
OrderTakeProfit(), 0, CLR_NONE))
{
Print("Сработал трейлинг стоп для Buy");
}
else
{
Print ("Ошибка модификации ордера #", GetLastError());
}
RefreshRates();
Sleep(3000);
} //end modify
}// end BUY
}//end OrderSelectelse
{
Print( "OrderSelect ошибка #", GetLastError() );
Sleep(3000);
RefreshRates();
return;
}
}// end for//--- Открываем ордер если есть сигналwhile (buy_open)
{
//--- нормализация лота
lot = Normalize_Lot(Lots);
//--- проверка на наличие свободной маржиif( AccountFreeMarginCheck(Symbol(),OP_BUY, lot) <= 0 || GetLastError() == 134 )
{
Print("Недостаточно свободной маржи для открытия ордера");
buy_open = false;
break;
}
min_level = MarketInfo( Symbol(), MODE_STOPLEVEL );
if ( OrderSend( Symbol(), OP_BUY, lot, NormalizeDouble(Ask, Digits), slippage,
NormalizeDouble(Bid - MathMax(stop_loss_buy, min_level) * Point, Digits),
NormalizeDouble(Bid + MathMax(take_profit_buy,min_level) * Point, Digits),
DoubleToStr(Magic, 0), Magic, 0, Blue) > 0 )
{
PlaySound("Wait.wav");
buy_open = false; // ордер открытbreak;
}
else
{
int Error = GetLastError(); // Не получилось :(switch(Error) // Преодолимые ошибки
{
case138:Alert("Ошибка: ",Error," Новые цены.");
RefreshRates();
continue;
case135:Alert("Ошибка: ",Error," Цена изменилась.");
RefreshRates();
continue;
case136:Alert("Нет цен.");
while(RefreshRates() == false)
Sleep(500);
continue;
case146:Alert("Подсистема торговли занята.");
Sleep(500);
RefreshRates();
continue;
default: Alert("Возникла ошибка ", Error," Выход из подпрограммы."); // Другие варианты ошибок
}// end switch
}// end elsebreak;
}// end while
}// end Trade_BUY//+------------------------------------------------------------------+void Trade_SELL()
//+------------------------------------------------------------------+
{
for ( int i = 0; i < OrdersTotal(); i++ )
{
if ( OrderSelect( i, SELECT_BY_POS, MODE_TRADES ) )
{
if ((OrderSymbol() != Symbol()) || (OrderMagicNumber() != Magic)) continue; //не наш ордерif ( OrderType() == OP_SELL) //если ордер OP_SELL
{
min_level = MarketInfo( Symbol(), MODE_STOPLEVEL );
//--- проверка на работу трейлинг стопаif (trailing_stop !=0.0 && Bid < NormalizeDouble(OrderStopLoss() - (stop_loss_sell + MathMax(min_level, trailing_stop)) * Point, Digits)&&OrderProfit() > 0)
{
if ( OrderModify ( OrderTicket(), OrderOpenPrice(),
NormalizeDouble (OrderStopLoss() - MathMax(min_level, trailing_stop) * Point, Digits),
OrderTakeProfit(), 0, CLR_NONE))
{
Print("Сработал трейлинг стоп для Sell");
}
else
{
Print ( "Ошибка модификации ордера #", GetLastError());
}
RefreshRates();
Sleep(3000);
}
}// end BUY
}//end OrderSelectelse
{
Print( "OrderSelect ошибка #", GetLastError() );
Sleep(3000);
RefreshRates();
return;
}
}// end for//--- Открываем ордер если есть сигналwhile (sell_open)
{
//--- нормализация лота
lot = Normalize_Lot(Lots);
//--- проверка на наличие свободной маржиif( AccountFreeMarginCheck(Symbol(),OP_SELL, lot) <= 0 || GetLastError() == 134 )
{
Print("Недостаточно свободной маржи для открытия ордера");
sell_open = false;
break;
}
min_level = MarketInfo( Symbol(), MODE_STOPLEVEL );
if ( OrderSend( Symbol(), OP_SELL, lot, NormalizeDouble(Bid, Digits), slippage,
NormalizeDouble(Ask + MathMax(stop_loss_sell, min_level) * Point, Digits),
NormalizeDouble(Ask - MathMax(take_profit_sell, min_level) * Point, Digits),
DoubleToStr(Magic, 0), Magic, 0, Blue) > 0 )
{
PlaySound("Wait.wav");
sell_open = false; // ордер открытbreak;
}
else
{
int Error = GetLastError(); // Не получилось :(switch(Error) // Преодолимые ошибки
{
case138:Alert("Ошибка: ",Error," Новые цены.");
RefreshRates();
continue;
case135:Alert("Ошибка: ",Error," Цена изменилась.");
RefreshRates();
continue;
case136:Alert("Нет цен.");
while(RefreshRates() == false)
Sleep(500);
continue;
case146:Alert("Подсистема торговли занята.");
Sleep(500);
RefreshRates();
continue;
default: Alert("Возникла ошибка ", Error," Выход из подпрограммы."); // Другие варианты ошибок
}// end switch
}// end elsebreak;
}// end while
}// end Trade_SELL//+------------------------------------------------------------------+double Normalize_Lot(double lot)// Проверка на допустимое значение лота//+------------------------------------------------------------------+
{
double lot_min = MarketInfo(Symbol(), MODE_MINLOT);
double lot_max = MarketInfo(Symbol(), MODE_MAXLOT);
double lot_step = MarketInfo(Symbol(), MODE_LOTSTEP);
if ( lot <= lot_min ) lot = lot_min; // минимальныйelseif ( lot >= lot_max ) lot = lot_max; // максимальныйelse lot = MathFloor( lot / lot_step ) * lot_step ; // округление до ближайшего меньшегоreturn(lot);
}
//+------------------------------------------------------------------+int MathMax4(int i1,int i2,int i3,int i4)// Возврат максимального значения//+------------------------------------------------------------------+
{
int imax=i1;
if(i2>imax)imax=i2;
if(i3>imax)imax=i3;
if(i4>imax)imax=i4;
return(imax);
}
Добрый день,уважаемые форумчане. Нужна помощь в изменении советника,т.е. оставить всё как есть,только изменить действие(покупка/продажа) на (продажа/покупка),мои тесты показали что на восходящем тренде происходит sell,а при нисходящем buy.Простое изменение в коде BUY на SELL мне ничего не дало,либо что-то пропустил,либо.... вобщем,ай нид хелп Заранее благодарю.
Как вычисляется iMA?
Где-нибудь можно найти как вычисляется функция iMA (или она засекреченная)
Особеннно меня интересует MODE_LWMA.
Хочу посмотреть и подправить на свой вкус, но что-то нагуглить исходники не получилось
https://docs.mql4.com/ru/indicators/iMA
Вам нужна формула, так Гугл её тоже легко находит.
https://docs.mql4.com/ru/indicators/iMA
Вам нужна формула, так Гугл её тоже легко находит.
Или Вам непонятен термин "линейно-взвешенная"?
Где-нибудь можно найти как вычисляется функция iMA (или она засекреченная)
Особеннно меня интересует MODE_LWMA.
Хочу посмотреть и подправить на свой вкус, но что-то нагуглить исходники не получилось
Добрый день!
В качестве первого опыта решил реализовать следующий алгоритм: можно ожидать, что после сближения линий Боллинджера в узкий коридор через какое-то время будет резкое движение рынка вверх или вниз. В советнике анализирую состояние линий Боллинджера и при их близком сближении (Delta пунктов) ставим отложенный ордер на продажу в нижнем направлении (на StepOpen пунктов ниже нижней линии) в надежде что рынок резко пойдет именно в эту сторону. Если рынок пошел в другую сторону, то просто удаляем этот ордер.
Алгоритм работает нестабильно, иногда открывает по два ордера через короткий промежуток времени, постоянно выдает ошибки OrderSend Error 130 и OrderSend Error 138, а удаление открытых ордеров в случае движения рынка в другую сторону вообще не срабатывает.Большая просьба помочь советом! Спасибо!
Виктор Иванович!
Так много листать, че Вы не дали ссылку? Вложили код... Зачем?
//--Ваш основной код
PrevTime=Time[0]; // Запоминаем время открытия нулевого бара
Если у Вас сетап по открытию бара, вот шаблон, он работает.
Большая просьба Вы не могли бы вписать сами эту функцию в советник? На картинке видно открыл 3 ордера на одном баре. А надо только один У меня не получается исправить код.СПАСИБО.
Привет всем )))
Помогите в советнике ограничить открытие ордеров до 1-го в сутки, неважно сколько он раз точку входа проходить будет...
Пытаюсь написать типа чтоб перед открытием проверял историю последнего закрытого ордера и если совпадает тогда не открывать...
for(int i=0;i<OrdersTotal();i++)
{
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==true)
{
if(OrderCloseTime()==Day()
break;
}
что то фигово получается, помогите плз ламочинке ))))
ордер на одном баре site:mql4.com
https://www.mql5.com/ru/forum/102366/page3
Нужна помощь в изменении советника,т.е. оставить всё как есть,только изменить действие(покупка/продажа) на (продажа/покупка),мои тесты показали что на восходящем тренде происходит sell,а при нисходящем buy.Простое изменение в коде BUY на SELL мне ничего не дало,либо что-то пропустил,либо.... вобщем,ай нид хелп
Заранее благодарю.