En cuanto a los que critican la aplicación, no sé por qué dicen que es "burda".
Estoy seguro de que a mucha gente le resultará muy cómodo utilizar su script para hacer pedidos pendientes.
Para aquellos que les gusta operar desde el mercado, ofrecí la versión del script que compra al precio actual del mercado con el cálculo automático del tamaño del lote sobre la base de un stop loss colocado en Forex Magazine (ver el artículo "Bibliotecas de funciones y su uso en programas", número 52, 24 de enero de 2005). En ese momento, era imposible llevar el precio al que se "bajaba" el script al gráfico en MQL4, por lo que el precio en el script es siempre el mismo que en el mercado.
El mismo programa puede modificarse fácilmente para abrir, por ejemplo, un minilote con una parada permanente. Este truco de MessageBox definitivamente me permitirá añadir funcionalidad a mi script también.
//+------------------------------------------------------------------+ //| 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); }
tengo de alguna manera un comportamiento inadecuado de la función Lowest y ArrayMinimum en el gráfico de EURUSD_H1
La cuestión es que aparentemente el mínimo debería coincidir con el valor del último viernes, pero no ocurre y obtengo un mínimo de dos días como mínimo.
El código de arriba, antes de que el gráfico cambie, por favor, compruébalo (es decir, antes del domingo por la noche).
¿Quizás estoy haciendo algo mal?
la implementación es realmente cruda :) he estado escribiendo este script durante una hora y media.....
Lo sugerí como una idea, si te gusta, tendrás que refinarlo...
cuerno 06.02.05 06:45
¡gracias por el respeto ;) y la oportunidad es realmente el mar - hay que buscarla!
rty: si alguien sabe cómo hacer un mensaje "encima de todas las ventanas", que me lo diga, plz.... es tan indubitable.....
para automatizar las operaciones rutinarias.
Aquí hay una versión seriamente corregida y en funcionamiento del script para la colocación de órdenes visuales:
//+------------------------------------------------------------------+ //| 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); } //+------------------------------------------------------------------+
Lo que está arreglado:
1) se especifican todos los parámetros en Lowest(Symbol(),PERIOD_D1,MODE_LOW,DAYS_TO_CONSIDER,0),
parece que el error de Horn fue que no se estableció el valor por defecto. vamos a comprobar cómo se llama y funciona la función Lowest
2) NormalizeDouble - ¡esto es muy importante!
3) Comprobación previa de la corrección de los niveles de parada antes de enviar las órdenes
4) el comerciante recibe más información en las ventanas (en la primera versión del script sin leer el código era muy difícil entender lo que hace el script)
5) salida detallada y puntual de los registros
6) comentarios añadidos
7) Se ha eliminado el intento cíclico de enviar una solicitud - es muy importante.
Por desgracia, el uso de algoritmos en bucle como :
while(true) { if(OrderSend(....)<=0) { // проверимся Sleep(10000); } }
está absolutamente contraindicado, incluso prohibido.
Intentaré explicar a grandes rasgos la razón:
Si capturas un error, no podrás manejar todos los tipos de errores por ti mismo de todos modos. Es demasiado probable que se detecten unos cinco errores populares y se haga algo al respecto, pero que se sigan repitiendo las operaciones para el resto. Y Sleep(10000) no servirá de excusa para que el script envíe peticiones incorrectas. Los corredores simplemente bloquearán la cuenta.
Cómo debe proceder el redactor de un Asesor Experto:
1) Preparar una orden
a) comprobar que los parámetros de entrada del Asesor Experto son correctos
b) normalizar independientemente todos los precios y volúmenes (¡sí, esos también!) de la solicitud
c) comprobar de forma independiente todos los campos de la solicitud en busca de errores tontos, al menos - para que todos los precios sean más o menos correctos
d) antes de enviar la solicitud, mostrar los detalles de la solicitud en el registro
2) organizar el ciclo de envío de la solicitud
a) el ciclo debe ser finito, por ejemplo no más de 3 veces for(i=0;i<3;i++) y en ningún caso while(true)
b) si la solicitud pasa, entonces todo es fácil salida al registro, notificar al comerciante y salir
c) atrapado un error, entonces el punto 3
3) manejo de los errores de envío de órdenes
a) comprobar las situaciones en las que podemos recuperar, y para cualquier otro error - salir con notificaciones tan pronto como sea posible
b) los casos de recuperación elegir tan pocos como sea posible, sólo los más importantes y potencialmente recuperables
c) no intentar "empujar" su orden repetida pensando "tal vez todavía aceptan?"
d) contabilidad obligatoria del deslizamiento, al menos 1 punto (sea honesto consigo mismo, el deslizamiento es inevitable en el comercio real)
Uno de los puntos principales en el uso de la ejecución de órdenes de MQL4 - minimizar el número de órdenes.
Esto afecta directamente a la calidad de su servicio.
Además, para los expertos que escriben para el público, hay que escribir el código más infalible.
Y también para uso interno.
He utilizado MB_TOPMOST, pruébalo, parece que me funciona.
- Aplicaciones de trading gratuitas
- 8 000+ señales para copiar
- Noticias económicas para analizar los mercados financieros
Usted acepta la política del sitio web y las condiciones de uso
Ayer me acordé y pensé: ¿por qué no ponerlo en práctica?
19.03.2005
Lea las instrucciones antes de utilizarlo =)
Si alguien tiene alguna idea, que nos lo haga saber y lo pensaremos.
Tal vez podamos hacer un GUO nosotros mismos.........;)