At least tell me what you think of the idea...
Forgot to say: Take profit line can be deleted if it is not needed.
The type of order is chosen depending on the location of the opener and stoploss...
As for those criticizing the implementation, I don't know why they say it is "crude".
I'm sure many people will find your script very convenient to use for placing pending orders.
For those who like to trade from the market, I offered the version of the script that buys at the current market price with automatic calculation of lot size on the basis of a stop loss placed in Forex Magazine (see the article "Libraries of functions and their usage in programs", issue 52, January 24, 2005). At that time, it was impossible to get the price at which the script was "lowered" to the chart in MQL4, so the price in the script is always the same as in the market.
The same program can be easily modified to open, say, one minilot with a permanent stop. And this MessageBox trick will definitely allow me to add functionality to my script as well.
//+------------------------------------------------------------------+ //| order_buy.mq4 | //| Copyright c 2004, Alexander Ivanov. | //| mailto:alexander@indus.ru | //+------------------------------------------------------------------+ #property copyright "Copyright c 2004, Alexander Ivanov." #property link "mailto:alexander@indus.ru" #include <WinUser32.mqh> #include <stderror.mqh> // Далее константа DAYS_TO_CONSIDER будет нам заменять количество // дней, на которых мы будем искать минимум для выставления Stop loss'а #define DAYS_TO_CONSIDER 3 ////////////////////////////////////////////////////////////////// // // Необходимо разрешить импорт функций из библиотек. Для этого // нужно поставив галочку 'Разрешить импортирование внешних экспертов' // на закладке 'Советники' окна 'Настройки' вызываемого выбором пункта // меню 'Сервис'->'Настройки' // ////////////////////////////////////////////////////////////////// #include <stdlib.mqh> // содержит нужную нам функцию ErrorDescription(...) int init() { return(0); } int start() { double DaysLowArray[]; int nBarWithMinimum = 0; double dMyStopLoss = 0; double dMyPrice = 0; double dMyTakeProfit = 0; double dMyLots = 0; if(ArrayCopySeries(DaysLowArray, MODE_LOW, Symbol(),PERIOD_D1) < DAYS_TO_CONSIDER) { return(PrintErrorDescription()); } dMyPrice = Ask; dMyStopLoss = DaysLowArray[Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER)]; dMyTakeProfit = dMyPrice + 2*MathMax((MathAbs(Ask-Bid)/2),MathAbs(dMyPrice-dMyStopLoss)); dMyStopLoss -= 10*Point; dMyLots = 0.1; Print("Цена = ", dMyPrice, " Стоп = ", dMyStopLoss, " Тейк профит = ", dMyTakeProfit, " Лот = ", dMyLots); ObjectCreate( "order_buy_Stop_Loss_Line", OBJ_HLINE, 0, 0, dMyStopLoss, 0, 0, 0, 0 ); ObjectSet( "order_buy_Stop_Loss_Line", OBJPROP_COLOR, Red ); ObjectSetText( "order_buy_Stop_Loss_Line", "Stop_Loss_Line", 6, "Arial", Red ); ObjectCreate( "order_buy_Take_Profit_Line", OBJ_HLINE, 0, 0, dMyTakeProfit, 0, 0, 0, 0 ); ObjectSet( "order_buy_Take_Profit_Line", OBJPROP_COLOR, Lime ); ObjectSetText( "order_buy_Take_Profit_Line", "Take_Profit_Line", 6, "Arial", Lime ); int MyError = 0; int Answer = MessageBoxA( 0, "\"order_buy\"\nПереместите линии на необходимые уровни, и нажмите ОК", "Установка ордера", MB_OKCANCEL | MB_ICONASTERISK | MB_TOPMOST); if ( Answer == IDOK ) { dMyStopLoss = ObjectGet( "order_buy_Stop_Loss_Line", OBJPROP_PRICE1); dMyTakeProfit = ObjectGet( "order_buy_Take_Profit_Line", OBJPROP_PRICE1); while(true) { if(OrderSend(Symbol(),OP_BUY,dMyLots,dMyPrice,3,dMyStopLoss,dMyTakeProfit, "Ordered by \"order_buy\" script" ,255,0,HotPink) <= 0) { MyError = PrintErrorDescription(); if((MyError == ERR_NOT_ENOUGH_MONEY) || (MyError == ERR_TRADE_DISABLED) || (MyError == ERR_INVALID_TRADE_PARAMETERS)) { MessageBoxA(0,ErrorDescription(MyError), "Ошибка", MB_OK | MB_ICONERROR); break; } else if(MyError == ERR_INVALID_STOPS) { dMyStopLoss = ObjectGet( "order_buy_Stop_Loss_Line", OBJPROP_PRICE1); dMyTakeProfit = ObjectGet( "order_buy_Take_Profit_Line", OBJPROP_PRICE1); Print("Цена = ", dMyPrice, " Стоп = ", dMyStopLoss, " Тейк профит = ", dMyTakeProfit, " Лот = ", dMyLots); } else if(MyError == ERR_PRICE_CHANGED) { MessageBoxA(0,"Цена успела измениться", "Ошибка", MB_OK | MB_ICONERROR); RefreshRates(); } else { // 10 seconds wait Sleep(10000); } } else { Answer = MessageBoxA( 0, "Ордер успешно исполнен\nРаспечатать ордер?", "Установка ордера", MB_OKCANCEL | MB_ICONASTERISK | MB_TOPMOST); if(Answer == IDOK ) { OrderPrint(); } break; } } } return(MyError); } int PrintErrorDescription() { int error=GetLastError(); Print("Error = ",ErrorDescription(error)); return(error); } int deinit() { ObjectDelete( "order_buy_Stop_Loss_Line"); ObjectDelete( "order_buy_Take_Profit_Line"); return(0); }
I have somehow inadequate behavior of Lowest and ArrayMinimum function on EURUSD_H1 chart
The point is that it seems that minimum should coincide with last Friday's value, but it does not happen and I return two-day minimum as a minimum.
The code above, before the chart changes please check (i.e. before Sunday night).
Maybe I'm doing something wrong?
the implementation is really crude :) i've been writing this script for an hour and a half.....
I suggested it as an idea, if you like it, you'll need to refine it...
horn 06.02.05 06:45
thanks for the respect ;) and the opportunity is really sea - you have to look for it!
rty: if anyone knows how to make a message "on top of all windows", tell me, plz.... it's so undubly.....
to automate routine operations.
Here is a seriously corrected and working version of the script for visual order placement:
//+------------------------------------------------------------------+ //| order_buy.mq4 | //| Copyright c 2004, Alexander Ivanov. | //| mailto:alexander@indus.ru | //+------------------------------------------------------------------+ //| Разрешите импорт функций из библиотек через: | //| "Сервис -> Настройки -> Советники -> Разрешить импорт DLL" | //+------------------------------------------------------------------+ #property copyright "Copyright c 2004, Alexander Ivanov." #property link "mailto:alexander@indus.ru" #include <WinUser32.mqh> #include <stdlib.mqh> #include <stderror.mqh> //+------------------------------------------------------------------+ //| Указываем количество последних дней, на которых ищем минимум | //| для установки стоплосса | //+------------------------------------------------------------------+ #define DAYS_TO_CONSIDER 3 //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ int init() { return(0); } int deinit() { //---- просто удалим свои линии стопов ObjectDelete( "order_buy_Stop_Loss_Line"); ObjectDelete( "order_buy_Take_Profit_Line"); //---- return(0); } //+------------------------------------------------------------------+ //| Основная функция скрипта | //+------------------------------------------------------------------+ int start() { double DaysLowArray[]; double dMyStopLoss = 0; double dMyPrice = 0; double dMyTakeProfit = 0; double dMyLots = 0; //---- скопируем массив дневных данных if(ArrayCopySeries(DaysLowArray, MODE_LOW, Symbol(),PERIOD_D1) < DAYS_TO_CONSIDER) { return(-1); } //---- расчет цен dMyPrice = Ask; dMyStopLoss = DaysLowArray[Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0)]; dMyTakeProfit = dMyPrice + 2*MathMax((MathAbs(Ask-Bid)/2),MathAbs(dMyPrice-dMyStopLoss)); dMyStopLoss -= 10*Point; dMyLots = 0.1; //---- выставим линии для визуального управления стопами ObjectCreate( "order_buy_Stop_Loss_Line", OBJ_HLINE, 0, 0, dMyStopLoss, 0, 0, 0, 0 ); ObjectSet( "order_buy_Stop_Loss_Line", OBJPROP_COLOR, Red ); ObjectSetText( "order_buy_Stop_Loss_Line", "Stop_Loss_Line", 6, "Arial", Red ); ObjectCreate( "order_buy_Take_Profit_Line", OBJ_HLINE, 0, 0, dMyTakeProfit, 0, 0, 0, 0 ); ObjectSet( "order_buy_Take_Profit_Line", OBJPROP_COLOR, Lime ); ObjectSetText( "order_buy_Take_Profit_Line", "Take_Profit_Line", 6, "Arial", Lime ); //---- запросим подтверждение на отработку string quest="Вы хотите купить "+DoubleToStr(dMyLots,2)+" "+Symbol()+" по цене Ask "+ DoubleToStr(dMyPrice,Digits)+" \n\n"+ "Переместите выставленные линии на необходимые уровни и нажмите ОК \n"+ "(красная линия - Stop Loss, зеленая - Take Profit)\n\n"+ "Нажмите Отмена чтобы отказаться от сделки"; if(MessageBoxA(0,quest,"Визуальная установка ордера на покупку", MB_OKCANCEL | MB_ICONASTERISK | MB_TOPMOST)!=IDOK) return(-2); //---- трейдер согласился, возьмем новые уровни стопов и обязательно проверим их! dMyStopLoss =NormalizeDouble(ObjectGet( "order_buy_Stop_Loss_Line", OBJPROP_PRICE1),Digits); dMyTakeProfit=NormalizeDouble(ObjectGet( "order_buy_Take_Profit_Line",OBJPROP_PRICE1),Digits); if((dMyStopLoss>0 && dMyStopLoss>Ask) || (dMyTakeProfit>0 && dMyTakeProfit<Ask)) { Print("Неправильно выставлены уровни Stop Loss и Take Profit!"); MessageBoxA(0,"Неправильно выставлены уровни Stop Loss и Take Profit! \n"+ "Операция отменена\n\n", "Визуальная установка ордера на покупку",MB_OK | MB_ICONSTOP | MB_TOPMOST); return(-3); } //---- выведем в лог сообщение об заявке Print("buy ",DoubleToStr(dMyLots,2)," ",Symbol()," at ",DoubleToStr(dMyPrice,Digits), "sl ",DoubleToStr(dMyStopLoss,Digits)," tp ",DoubleToStr(dMyTakeProfit,Digits)); //---- пробуем послать команду int ticket=OrderSend(Symbol(),OP_BUY,dMyLots,dMyPrice,3,dMyStopLoss,dMyTakeProfit, "Ordered by \"order_buy\" script" ,255,0,HotPink); if(ticket>0) // все отлично - заявка прошла { //---- сразу же выведем в лог подтверждение Print("#",ticket," buy ",DoubleToStr(dMyLots,2)," ",Symbol()," at ", DoubleToStr(dMyPrice,Digits)," is done"); //---- покажем окно if(MessageBoxA(0,"Ордер успешно исполнен \nРаспечатать его?", "Визуальная установка ордера на покупку", MB_YESNO | MB_ICONASTERISK | MB_TOPMOST)==IDYES) { OrderPrint(); } //---- все ок, выходим return(0); } //---- тут все плохо - выведем в лог сообщение int err=GetLastError(); Print("buy ",DoubleToStr(dMyLots,2)," ",Symbol()," at ", DoubleToStr(dMyPrice,Digits)," failed [",ErrorDescription(err),"]"); //----покажем окно MessageBoxA(0,ErrorDescription(err), "Ошибка визуальной установки ордера", MB_OK | MB_ICONERROR | MB_TOPMOST); return(-4); } //+------------------------------------------------------------------+
What's fixed:
1) all parameters in Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0) are specified,
it looks like Horn's error was that the default value was not set. we will check how Lowest function is called and works
2) NormalizeDouble - this is very important!
3) Pre-checking of stop levels for correctness before sending to orders
4) the trader is given more information in the windows (in the first version of the script without reading the code it was very difficult to understand what the script does)
5) detailed and timely output of logs
6) comments added
7) cyclic attempt to send a request has been removed - it is very important.
Unfortunately, using looped algorithms like :
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
is absolutely contraindicated, even forbidden.
Let me try to roughly explain the reason:
If you catch an error, you won't be able to handle all error types by yourself anyway. It is too probable that you will catch five or so popular errors and do something about them but still _repeat operations_ for all the rest. And Sleep(10000) will not serve as an excuse for the script to send incorrect requests. The brokers will simply block the account.
How should an Expert Advisor writer proceed:
1) Prepare an order
a) check input parameters of the Expert Advisor for correctness
b) independently normalize all prices and volumes (yes, those too!) of the request
c) independently check all fields of the request for silly mistakes, at least - so that all prices are more or less correct
d) before sending the request, display details of the request in the log
2) organize the cycle of request sending
a) the cycle must be finite, for example no more than 3 times for(i=0;i<3;i++) and in no case while(true)
b) if the request passes, then everything is easy output to the log, notify the trader and exit
c) caught an error, then point 3
3) handling order sending errors
a) check those situations where we can recover, and for any other error - exit with notifications as soon as possible
b) cases of recovery choose as few as possible, only the most important and potentially recoverable
c) no attempts to "push through" your repeated order thinking "maybe they will still accept?"
d) mandatory slippage accounting, at least 1 point (be honest with yourself, slippage is inevitable in real trading)
One of the main points in using order execution from MQL4 - minimize the number of orders.
This directly affects the quality of your service.
Also, for experts writing for the public, you need to write the most foolproof code.
And for internal use as well.
I used MB_TOPMOST, try it, it seems to work for me.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Yesterday I remembered and thought - why not implement it?
19.03.2005
Read the instructions before using it =)
If anyone has any ideas, let us know and we'll think about it.
Maybe we can make a GUO ourselves.........;)